aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJustin Hibbits <jhibbits@FreeBSD.org>2016-10-21 02:16:11 +0000
committerJustin Hibbits <jhibbits@FreeBSD.org>2016-10-21 02:16:11 +0000
commit47cabd046d160d7c790185955ceab3e1ef432afa (patch)
tree3334a78d1923e3817ec9817ccf8811d2856f487a /sys/dev
parent525b23c541a7dcbe95fdab6e196011cfd93ea1ec (diff)
Notes
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/dpaa/fman.c33
-rw-r--r--sys/dev/dpaa/fman.h5
-rw-r--r--sys/dev/dpaa/fman_fdt.c11
-rw-r--r--sys/dev/dpaa/fman_mdio.c211
-rw-r--r--sys/dev/dpaa/if_dtsec.c56
-rw-r--r--sys/dev/dpaa/if_dtsec.h1
-rw-r--r--sys/dev/dpaa/if_dtsec_fdt.c36
7 files changed, 282 insertions, 71 deletions
diff --git a/sys/dev/dpaa/fman.c b/sys/dev/dpaa/fman.c
index 38a91aeee6c2..ee1f0cd8bf2e 100644
--- a/sys/dev/dpaa/fman.c
+++ b/sys/dev/dpaa/fman.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <dev/fdt/fdt_common.h>
+#include <dev/fdt/simplebus.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -88,6 +89,8 @@ static struct fman_softc *fm_sc = NULL;
static t_Handle
fman_init(struct fman_softc *sc, struct fman_config *cfg)
{
+ struct ofw_bus_devinfo obd;
+ phandle_t node;
t_FmParams fm_params;
t_Handle muram_handle, fm_handle;
t_Error error;
@@ -158,6 +161,16 @@ fman_init(struct fman_softc *sc, struct fman_config *cfg)
device_printf(cfg->fman_device, "Hardware version: %d.%d.\n",
revision_info.majorRev, revision_info.minorRev);
+ /* Initialize the simplebus part of things */
+ simplebus_init(sc->sc_base.dev, 0);
+
+ node = ofw_bus_get_node(sc->sc_base.dev);
+ for (node = OF_child(node); node > 0; node = OF_peer(node)) {
+ if (ofw_bus_gen_setup_devinfo(&obd, node) != 0)
+ continue;
+ simplebus_add_device(sc->sc_base.dev, node, 0, NULL, -1, NULL);
+ }
+
return (fm_handle);
err2:
@@ -173,7 +186,7 @@ fman_exception_callback(t_Handle app_handle, e_FmExceptions exception)
struct fman_softc *sc;
sc = app_handle;
- device_printf(sc->dev, "FMan exception occurred.\n");
+ device_printf(sc->sc_base.dev, "FMan exception occurred.\n");
}
static void
@@ -183,7 +196,7 @@ fman_error_callback(t_Handle app_handle, e_FmPortType port_type,
struct fman_softc *sc;
sc = app_handle;
- device_printf(sc->dev, "FMan error occurred.\n");
+ device_printf(sc->sc_base.dev, "FMan error occurred.\n");
}
/** @} */
@@ -230,13 +243,25 @@ fman_get_bushandle(vm_offset_t *fm_base)
}
int
+fman_get_dev(device_t *fm_dev)
+{
+
+ if (fm_sc == NULL)
+ return (ENOMEM);
+
+ *fm_dev = fm_sc->sc_base.dev;
+
+ return (0);
+}
+
+int
fman_attach(device_t dev)
{
struct fman_softc *sc;
struct fman_config cfg;
sc = device_get_softc(dev);
- sc->dev = dev;
+ sc->sc_base.dev = dev;
fm_sc = sc;
/* Check if MallocSmart allocator is ready */
@@ -249,7 +274,7 @@ fman_attach(device_t dev)
sc->mem_rid = 0;
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
- RF_ACTIVE);
+ RF_ACTIVE | RF_SHAREABLE);
if (!sc->mem_res) {
device_printf(dev, "could not allocate memory.\n");
return (ENXIO);
diff --git a/sys/dev/dpaa/fman.h b/sys/dev/dpaa/fman.h
index 5a421e056423..52bc61762c2b 100644
--- a/sys/dev/dpaa/fman.h
+++ b/sys/dev/dpaa/fman.h
@@ -29,11 +29,13 @@
#ifndef FMAN_H_
#define FMAN_H_
+#include <dev/fdt/simplebus.h>
+
/**
* FMan driver instance data.
*/
struct fman_softc {
- device_t dev;
+ struct simplebus_softc sc_base;
struct resource *mem_res;
struct resource *irq_res;
struct resource *err_irq_res;
@@ -63,5 +65,6 @@ uint32_t fman_get_clock(struct fman_softc *sc);
int fman_get_handle(t_Handle *fmh);
int fman_get_muram_handle(t_Handle *muramh);
int fman_get_bushandle(vm_offset_t *fm_base);
+int fman_get_dev(device_t *fmd);
#endif /* FMAN_H_ */
diff --git a/sys/dev/dpaa/fman_fdt.c b/sys/dev/dpaa/fman_fdt.c
index 89c9eca1cb5b..b4693b5de956 100644
--- a/sys/dev/dpaa/fman_fdt.c
+++ b/sys/dev/dpaa/fman_fdt.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/module.h>
+#include <dev/fdt/simplebus.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -58,12 +59,8 @@ static device_method_t fman_methods[] = {
{ 0, 0 }
};
-static driver_t fman_driver = {
- "fman",
- fman_methods,
- sizeof(struct fman_softc),
-};
-
+DEFINE_CLASS_1(fman, fman_driver, fman_methods,
+ sizeof(struct fman_softc), simplebus_driver);
static devclass_t fman_devclass;
EARLY_DRIVER_MODULE(fman, simplebus, fman_driver, fman_devclass, 0, 0,
BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
@@ -88,7 +85,7 @@ fman_get_clock(struct fman_softc *sc)
phandle_t node;
pcell_t fman_clock;
- dev = sc->dev;
+ dev = sc->sc_base.dev;
node = ofw_bus_get_node(dev);
if ((OF_getprop(node, "clock-frequency", &fman_clock,
diff --git a/sys/dev/dpaa/fman_mdio.c b/sys/dev/dpaa/fman_mdio.c
new file mode 100644
index 000000000000..fad7fea5e8ec
--- /dev/null
+++ b/sys/dev/dpaa/fman_mdio.c
@@ -0,0 +1,211 @@
+/*-
+ * Copyright (c) 2016 Justin Hibbits
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+
+#include <machine/bus.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_var.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <contrib/ncsw/inc/Peripherals/fm_ext.h>
+
+#include "fman.h"
+#include "miibus_if.h"
+
+#define MDIO_LOCK() mtx_lock(&sc->sc_lock)
+#define MDIO_UNLOCK() mtx_unlock(&sc->sc_lock)
+#define MDIO_WRITE4(sc,r,v) \
+ bus_space_write_4(&bs_be_tag, sc->sc_handle, sc->sc_offset + r, v)
+#define MDIO_READ4(sc, r) \
+ bus_space_read_4(&bs_be_tag, sc->sc_handle, sc->sc_offset + r)
+
+#define MDIO_MIIMCFG 0x0
+#define MDIO_MIIMCOM 0x4
+#define MIIMCOM_SCAN_CYCLE 0x00000002
+#define MIIMCOM_READ_CYCLE 0x00000001
+#define MDIO_MIIMADD 0x8
+#define MDIO_MIIMCON 0xc
+#define MDIO_MIIMSTAT 0x10
+#define MDIO_MIIMIND 0x14
+#define MIIMIND_BUSY 0x1
+
+static int pqmdio_fdt_probe(device_t dev);
+static int pqmdio_fdt_attach(device_t dev);
+static int pqmdio_detach(device_t dev);
+static int pqmdio_miibus_readreg(device_t dev, int phy, int reg);
+static int pqmdio_miibus_writereg(device_t dev, int phy, int reg, int value);
+
+struct pqmdio_softc {
+ struct mtx sc_lock;
+ bus_space_handle_t sc_handle;
+ int sc_offset;
+};
+
+static device_method_t pqmdio_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, pqmdio_fdt_probe),
+ DEVMETHOD(device_attach, pqmdio_fdt_attach),
+ DEVMETHOD(device_detach, pqmdio_detach),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, pqmdio_miibus_readreg),
+ DEVMETHOD(miibus_writereg, pqmdio_miibus_writereg),
+
+ { 0, 0 }
+};
+
+static struct ofw_compat_data mdio_compat_data[] = {
+ {"fsl,fman-mdio", 0},
+ {NULL, 0}
+};
+
+static driver_t pqmdio_driver = {
+ "pq_mdio",
+ pqmdio_methods,
+ sizeof(struct pqmdio_softc),
+};
+
+static int
+pqmdio_fdt_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, mdio_compat_data)->ocd_str)
+ return (ENXIO);
+
+ device_set_desc(dev, "Freescale QorIQ MDIO");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+pqmdio_fdt_attach(device_t dev)
+{
+ struct pqmdio_softc *sc;
+ rman_res_t start, count;
+
+ sc = device_get_softc(dev);
+
+ fman_get_bushandle(&sc->sc_handle);
+ bus_get_resource(dev, SYS_RES_MEMORY, 0, &start, &count);
+ sc->sc_offset = start;
+
+ mtx_init(&sc->sc_lock, device_get_nameunit(dev), "QorIQ MDIO lock",
+ MTX_DEF);
+
+ return (0);
+}
+
+static int
+pqmdio_detach(device_t dev)
+{
+ struct pqmdio_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ mtx_destroy(&sc->sc_lock);
+
+ return (0);
+}
+
+int
+pqmdio_miibus_readreg(device_t dev, int phy, int reg)
+{
+ struct pqmdio_softc *sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+
+ MDIO_LOCK();
+
+ MDIO_WRITE4(sc, MDIO_MIIMADD, (phy << 8) | reg);
+ MDIO_WRITE4(sc, MDIO_MIIMCOM, MIIMCOM_READ_CYCLE);
+
+ MDIO_READ4(sc, MDIO_MIIMCOM);
+
+ while ((MDIO_READ4(sc, MDIO_MIIMIND)) & MIIMIND_BUSY)
+ ;
+
+ rv = MDIO_READ4(sc, MDIO_MIIMSTAT);
+
+ MDIO_WRITE4(sc, MDIO_MIIMCOM, 0);
+ MDIO_READ4(sc, MDIO_MIIMCOM);
+ MDIO_UNLOCK();
+
+ return (rv);
+}
+
+int
+pqmdio_miibus_writereg(device_t dev, int phy, int reg, int value)
+{
+ struct pqmdio_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ MDIO_LOCK();
+ /* Stop the MII management read cycle */
+ MDIO_WRITE4(sc, MDIO_MIIMCOM, 0);
+ MDIO_READ4(sc, MDIO_MIIMCOM);
+
+ MDIO_WRITE4(sc, MDIO_MIIMADD, (phy << 8) | reg);
+
+ MDIO_WRITE4(sc, MDIO_MIIMCON, value);
+ MDIO_READ4(sc, MDIO_MIIMCON);
+
+ /* Wait till MII management write is complete */
+ while ((MDIO_READ4(sc, MDIO_MIIMIND)) & MIIMIND_BUSY)
+ ;
+ MDIO_UNLOCK();
+
+ return (0);
+}
+
+static devclass_t pqmdio_devclass;
+DRIVER_MODULE(pqmdio, fman, pqmdio_driver, pqmdio_devclass, 0, 0);
+DRIVER_MODULE(miibus, pqmdio, miibus_driver, miibus_devclass, 0, 0);
+MODULE_DEPEND(pqmdio, miibus, 1, 1, 1);
+
diff --git a/sys/dev/dpaa/if_dtsec.c b/sys/dev/dpaa/if_dtsec.c
index 249d605bb42e..d5f771251e3e 100644
--- a/sys/dev/dpaa/if_dtsec.c
+++ b/sys/dev/dpaa/if_dtsec.c
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <net/if_arp.h>
#include <dev/fdt/fdt_common.h>
+#include <dev/fdt/simplebus.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include <dev/ofw/ofw_bus.h>
@@ -79,13 +80,6 @@ struct dtsec_fm_mac_ex_str {
const int num;
const char *str;
};
-
-/* XXX: Handle to FM_MAC instance of dTSEC0 */
-/* From QorIQ Data Path Acceleration Architecture Reference Manual, Rev 2, page
- * 3-37, "The MII management hardware is shared by all dTSECs... only through
- * the MIIM registers of dTSEC1 can external PHY's be accessed and configured."
- */
-static t_Handle dtsec_mdio_mac_handle;
/** @} */
@@ -205,8 +199,6 @@ dtsec_fm_mac_init(struct dtsec_softc *sc, uint8_t *mac)
params.h_Fm = sc->sc_fmh;
sc->sc_mach = FM_MAC_Config(&params);
- if (sc->sc_hidden)
- return (0);
if (sc->sc_mach == NULL) {
device_printf(sc->sc_dev, "couldn't configure FM_MAC module.\n"
);
@@ -647,20 +639,6 @@ dtsec_attach(device_t dev)
return (ENXIO);
}
- /*
- * XXX: All phys are connected to MDIO interface of the first dTSEC
- * device (dTSEC0). We have to save handle to the FM_MAC instance of
- * dTSEC0, which is used later during phy's registers accesses. Another
- * option would be adding new property to DTS pointing to correct dTSEC
- * instance, of which FM_MAC handle has to be used for phy's registers
- * accesses. We did not want to add new properties to DTS, thus this
- * quite ugly hack.
- */
- if (sc->sc_eth_id == 0)
- dtsec_mdio_mac_handle = sc->sc_mach;
- if (sc->sc_hidden)
- return (0);
-
/* Init FMan TX port */
error = sc->sc_port_tx_init(sc, device_get_unit(sc->sc_dev));
if (error != 0) {
@@ -797,47 +775,21 @@ int
dtsec_miibus_readreg(device_t dev, int phy, int reg)
{
struct dtsec_softc *sc;
- uint16_t data;
- t_Error error;
sc = device_get_softc(dev);
- if (phy != sc->sc_phy_addr)
- return (0xFFFF);
-
- DTSEC_MII_LOCK(sc);
- error = FM_MAC_MII_ReadPhyReg(dtsec_mdio_mac_handle, phy, reg, &data);
- DTSEC_MII_UNLOCK(sc);
- if (error != E_OK) {
- device_printf(dev, "Error while reading from PHY (NetCommSw "
- "error: %d)\n", error);
- return (0xFFFF);
- }
-
- return ((int)data);
+ return (MIIBUS_READREG(sc->sc_mdio, phy, reg));
}
int
dtsec_miibus_writereg(device_t dev, int phy, int reg, int value)
{
+
struct dtsec_softc *sc;
- t_Error error;
sc = device_get_softc(dev);
- if (phy != sc->sc_phy_addr)
- return (EINVAL);
-
- DTSEC_MII_LOCK(sc);
- error = FM_MAC_MII_WritePhyReg(dtsec_mdio_mac_handle, phy, reg, value);
- DTSEC_MII_UNLOCK(sc);
- if (error != E_OK) {
- device_printf(dev, "Error while writing to PHY (NetCommSw "
- "error: %d).\n", error);
- return (EIO);
- }
-
- return (0);
+ return (MIIBUS_WRITEREG(sc->sc_mdio, phy, reg, value));
}
void
diff --git a/sys/dev/dpaa/if_dtsec.h b/sys/dev/dpaa/if_dtsec.h
index 2e2e28fe24f9..0f9aa341d97e 100644
--- a/sys/dev/dpaa/if_dtsec.h
+++ b/sys/dev/dpaa/if_dtsec.h
@@ -75,6 +75,7 @@ struct dtsec_softc {
uint32_t sc_port_tx_qman_chan;
int sc_phy_addr;
bool sc_hidden;
+ device_t sc_mdio;
/* Params from fman_bus driver */
vm_offset_t sc_fm_base;
diff --git a/sys/dev/dpaa/if_dtsec_fdt.c b/sys/dev/dpaa/if_dtsec_fdt.c
index 25b2cfc2a712..49666f155a1d 100644
--- a/sys/dev/dpaa/if_dtsec_fdt.c
+++ b/sys/dev/dpaa/if_dtsec_fdt.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <contrib/ncsw/inc/xx_ext.h>
#include "if_dtsec.h"
+#include "fman.h"
static int dtsec_fdt_probe(device_t dev);
@@ -106,6 +107,28 @@ dtsec_fdt_probe(device_t dev)
}
static int
+find_mdio(phandle_t phy_node, device_t mac, device_t *mdio_dev)
+{
+ device_t bus;
+
+ while (phy_node > 0) {
+ if (ofw_bus_node_is_compatible(phy_node, "fsl,fman-mdio"))
+ break;
+ phy_node = OF_parent(phy_node);
+ }
+
+ if (phy_node <= 0)
+ return (ENOENT);
+
+ if (fman_get_dev(&bus) < 0)
+ return (ENOENT);
+
+ *mdio_dev = ofw_bus_find_child_device_by_phandle(bus, phy_node);
+
+ return (0);
+}
+
+static int
dtsec_fdt_attach(device_t dev)
{
struct dtsec_softc *sc;
@@ -127,13 +150,9 @@ dtsec_fdt_attach(device_t dev)
if (OF_getprop(enet_node, "local-mac-address",
(void *)sc->sc_mac_addr, 6) == -1) {
- if (device_get_unit(dev) != 0) {
- device_printf(dev,
- "Could not load local-mac-addr property "
- "from DTS\n");
- return (ENXIO);
- }
- sc->sc_hidden = true;
+ device_printf(dev,
+ "Could not load local-mac-addr property from DTS\n");
+ return (ENXIO);
}
/* Get link speed */
@@ -160,6 +179,9 @@ dtsec_fdt_attach(device_t dev)
sizeof(sc->sc_phy_addr)) <= 0)
return (ENXIO);
+ if (find_mdio(phy_node, dev, &sc->sc_mdio) != 0)
+ return (ENXIO);
+
/* Get PHY connection type */
if (OF_getprop(enet_node, "phy-connection-type", (void *)phy_type,
sizeof(phy_type)) <= 0)