diff options
| author | Justin Hibbits <jhibbits@FreeBSD.org> | 2016-10-21 02:16:11 +0000 |
|---|---|---|
| committer | Justin Hibbits <jhibbits@FreeBSD.org> | 2016-10-21 02:16:11 +0000 |
| commit | 47cabd046d160d7c790185955ceab3e1ef432afa (patch) | |
| tree | 3334a78d1923e3817ec9817ccf8811d2856f487a /sys/dev | |
| parent | 525b23c541a7dcbe95fdab6e196011cfd93ea1ec (diff) | |
Notes
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/dpaa/fman.c | 33 | ||||
| -rw-r--r-- | sys/dev/dpaa/fman.h | 5 | ||||
| -rw-r--r-- | sys/dev/dpaa/fman_fdt.c | 11 | ||||
| -rw-r--r-- | sys/dev/dpaa/fman_mdio.c | 211 | ||||
| -rw-r--r-- | sys/dev/dpaa/if_dtsec.c | 56 | ||||
| -rw-r--r-- | sys/dev/dpaa/if_dtsec.h | 1 | ||||
| -rw-r--r-- | sys/dev/dpaa/if_dtsec_fdt.c | 36 |
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(¶ms); - 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) |
