Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/allwinner Add mii support and some initialization.
details: https://anonhg.NetBSD.org/src/rev/f385577b9455
branches: trunk
changeset: 789793:f385577b9455
user: matt <matt%NetBSD.org@localhost>
date: Sun Sep 08 00:05:27 2013 +0000
description:
Add mii support and some initialization.
diffstat:
sys/arch/arm/allwinner/awin_eth.c | 128 ++++++++++++++++++++++++++++++++++++-
1 files changed, 124 insertions(+), 4 deletions(-)
diffs (185 lines):
diff -r de2bd5f48ef9 -r f385577b9455 sys/arch/arm/allwinner/awin_eth.c
--- a/sys/arch/arm/allwinner/awin_eth.c Sun Sep 08 00:04:33 2013 +0000
+++ b/sys/arch/arm/allwinner/awin_eth.c Sun Sep 08 00:05:27 2013 +0000
@@ -31,52 +31,96 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: awin_eth.c,v 1.1 2013/09/04 02:39:01 matt Exp $");
+__KERNEL_RCSID(1, "$NetBSD: awin_eth.c,v 1.2 2013/09/08 00:05:27 matt Exp $");
#include <sys/bus.h>
#include <sys/device.h>
#include <sys/intr.h>
+#include <sys/mutex.h>
#include <sys/systm.h>
+#include <net/if.h>
+#include <net/if_ether.h>
+#include <net/if_media.h>
+
+#include <dev/mii/miivar.h>
+
#include <arm/allwinner/awin_reg.h>
#include <arm/allwinner/awin_var.h>
static int awin_eth_match(device_t, cfdata_t, void *);
static void awin_eth_attach(device_t, device_t, void *);
+static int awin_eth_miibus_read_reg(device_t, int, int);
+static void awin_eth_miibus_write_reg(device_t, int, int, int);
+static void awin_eth_miibus_statchg(struct ifnet *);
+
struct awin_eth_softc {
device_t sc_dev;
bus_space_tag_t sc_bst;
bus_space_handle_t sc_bsh;
bus_dma_tag_t sc_dmat;
+ struct ethercom sc_ec;
+ struct mii_data sc_mii;
+ kmutex_t sc_mdio_lock;
};
CFATTACH_DECL_NEW(awin_eth, sizeof(struct awin_eth_softc),
awin_eth_match, awin_eth_attach, NULL, NULL);
+static const struct awin_gpio_pinset awin_eth_pinsets[2] = {
+ [0] = { 'A', AWIN_PIO_PA_EMAC_FUNC, AWIN_PIO_PA_EMAC_PINS },
+ [1] = { 'H', AWIN_PIO_PH_EMAC_FUNC, AWIN_PIO_PH_EMAC_PINS },
+};
+
+static inline uint32_t
+awin_eth_read_4(struct awin_eth_softc *sc, bus_size_t o)
+{
+ return bus_space_read_4(sc->sc_bst, sc->sc_bsh, o);
+}
+
+static inline void
+awin_eth_write_4(struct awin_eth_softc *sc, bus_size_t o, uint32_t v)
+{
+ return bus_space_write_4(sc->sc_bst, sc->sc_bsh, o, v);
+}
+
static int
awin_eth_match(device_t parent, cfdata_t cf, void *aux)
{
struct awinio_attach_args * const aio = aux;
const struct awin_locators * const loc = &aio->aio_loc;
+ const struct awin_gpio_pinset * const pinset =
+ &awin_eth_pinsets[cf->cf_flags & 1];
- if (strcmp(cf->cf_name, loc->loc_name))
+ KASSERT(!strcmp(cf->cf_name, loc->loc_name));
+ KASSERT(cf->cf_loc[AWINIOCF_PORT] == AWINIOCF_PORT_DEFAULT
+ || cf->cf_loc[AWINIOCF_PORT] == loc->loc_port);
+
+ if (!awin_gpio_pinset_available(pinset))
return 0;
- KASSERT(cf->cf_loc[AWINIOCF_PORT] == AWINIOCF_PORT_DEFAULT);
-
return 1;
}
static void
awin_eth_attach(device_t parent, device_t self, void *aux)
{
+ cfdata_t cf = device_cfdata(self);
struct awin_eth_softc * const sc = device_private(self);
struct awinio_attach_args * const aio = aux;
const struct awin_locators * const loc = &aio->aio_loc;
+ const struct awin_gpio_pinset * const pinset =
+ &awin_eth_pinsets[cf->cf_flags & 1];
+ struct ifnet * const ifp = &sc->sc_ec.ec_if;
+ struct mii_data * const mii = &sc->sc_mii;
sc->sc_dev = self;
+ awin_gpio_pinset_acquire(pinset);
+
+ mutex_init(&sc->sc_mdio_lock, MUTEX_DEFAULT, IPL_NET);
+
sc->sc_bst = aio->aio_core_bst;
sc->sc_dmat = aio->aio_dmat;
bus_space_subregion(sc->sc_bst, aio->aio_core_bsh,
@@ -84,4 +128,80 @@
aprint_naive("\n");
aprint_normal("\n");
+
+ ifp->if_softc = sc;
+
+ ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus);
+
+ mii->mii_ifp = ifp;
+ mii->mii_readreg = awin_eth_miibus_read_reg;
+ mii->mii_writereg = awin_eth_miibus_write_reg;
+ mii->mii_statchg = awin_eth_miibus_statchg;
+
+ int mii_flags = 0;
+
+ mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, mii_flags);
+
+ if (LIST_EMPTY(&mii->mii_phys)) {
+ aprint_error_dev(self, "no PHY found!\n");
+ ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
+ ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_MANUAL);
+ } else {
+ ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO);
+ }
}
+
+int
+awin_eth_miibus_read_reg(device_t self, int phy, int reg)
+{
+ struct awin_eth_softc * const sc = device_private(self);
+
+ mutex_enter(&sc->sc_mdio_lock);
+
+ awin_eth_write_4(sc, AWIN_EMAC_MAC_MADR_REG, (phy << 8) | reg);
+ awin_eth_write_4(sc, AWIN_EMAC_MAC_MCMD_REG, 1);
+
+ delay(100);
+
+ awin_eth_write_4(sc, AWIN_EMAC_MAC_MCMD_REG, 0);
+ const uint32_t rv = awin_eth_read_4(sc, AWIN_EMAC_MAC_MRDD_REG);
+
+ mutex_exit(&sc->sc_mdio_lock);
+
+ return rv;
+}
+
+void
+awin_eth_miibus_write_reg(device_t self, int phy, int reg, int val)
+{
+ struct awin_eth_softc * const sc = device_private(self);
+
+ mutex_enter(&sc->sc_mdio_lock);
+
+ awin_eth_write_4(sc, AWIN_EMAC_MAC_MADR_REG, (phy << 8) | reg);
+ awin_eth_write_4(sc, AWIN_EMAC_MAC_MCMD_REG, 1);
+
+ delay(100);
+
+ awin_eth_write_4(sc, AWIN_EMAC_MAC_MCMD_REG, 0);
+ awin_eth_write_4(sc, AWIN_EMAC_MAC_MWTD_REG, val);
+
+ mutex_exit(&sc->sc_mdio_lock);
+}
+
+void
+awin_eth_miibus_statchg(struct ifnet *ifp)
+{
+ struct awin_eth_softc * const sc = ifp->if_softc;
+ struct mii_data * const mii = &sc->sc_mii;
+
+ /*
+ * Set MII or GMII interface based on the speed
+ * negotiated by the PHY.
+ */
+ switch (IFM_SUBTYPE(mii->mii_media_active)) {
+ case IFM_10_T:
+ case IFM_100_TX:
+ ;
+ }
+}
Home |
Main Index |
Thread Index |
Old Index