From 8fe59fe28747ba709c59a05f911a60399b307105 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 18 Nov 2013 12:46:27 +0100 Subject: if_tsec: Add Nexus support --- Makefile | 1 + freebsd-to-rtems.py | 1 + freebsd/sys/dev/tsec/if_tsec.h | 2 + rtemsbsd/include/bsp/nexus-devices.h | 29 +++- rtemsbsd/sys/dev/tsec/if_tsec_nexus.c | 310 ++++++++++++++++++++++++++++++++++ 5 files changed, 342 insertions(+), 1 deletion(-) create mode 100644 rtemsbsd/sys/dev/tsec/if_tsec_nexus.c diff --git a/Makefile b/Makefile index 523e974b..6d26776c 100644 --- a/Makefile +++ b/Makefile @@ -135,6 +135,7 @@ LIB_C_FILES += rtemsbsd/telnetd/check_passwd.c LIB_C_FILES += rtemsbsd/telnetd/des.c LIB_C_FILES += rtemsbsd/telnetd/pty.c LIB_C_FILES += rtemsbsd/telnetd/telnetd.c +LIB_C_FILES += rtemsbsd/sys/dev/tsec/if_tsec_nexus.c LIB_GEN_FILES += rtemsbsd/rtems/rtems-kvm-symbols.c LIB_C_FILES += rtemsbsd/rtems/rtems-kvm-symbols.c rtemsbsd/rtems/rtems-kvm-symbols.c: rtemsbsd/rtems/generate_kvm_symbols diff --git a/freebsd-to-rtems.py b/freebsd-to-rtems.py index 2f4574a7..6fb8bb71 100755 --- a/freebsd-to-rtems.py +++ b/freebsd-to-rtems.py @@ -733,6 +733,7 @@ rtems.addRTEMSSourceFiles( 'telnetd/des.c', 'telnetd/pty.c', 'telnetd/telnetd.c', + 'sys/dev/tsec/if_tsec_nexus.c', ] ) diff --git a/freebsd/sys/dev/tsec/if_tsec.h b/freebsd/sys/dev/tsec/if_tsec.h index cfba3f6b..e4bbc9ae 100644 --- a/freebsd/sys/dev/tsec/if_tsec.h +++ b/freebsd/sys/dev/tsec/if_tsec.h @@ -51,7 +51,9 @@ struct tsec_softc { struct mtx transmit_lock; /* transmitter lock */ struct mtx receive_lock; /* receiver lock */ +#ifndef __rtems__ phandle_t node; +#endif /* __rtems__ */ device_t dev; device_t tsec_miibus; struct mii_data *tsec_mii; /* MII media control */ diff --git a/rtemsbsd/include/bsp/nexus-devices.h b/rtemsbsd/include/bsp/nexus-devices.h index d12d9bd9..9cd1da7e 100644 --- a/rtemsbsd/include/bsp/nexus-devices.h +++ b/rtemsbsd/include/bsp/nexus-devices.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved. + * Copyright (c) 2013-2015 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -88,4 +88,31 @@ RTEMS_BSD_DEFINE_NEXUS_DEVICE(cgem, 0, RTEMS_ARRAY_SIZE(cgem0_res), SYSINIT_DRIVER_REFERENCE(e1000phy, miibus); +#elif defined(LIBBSP_POWERPC_QORIQ_BSP_H) + +#include + +static const rtems_bsd_device_resource tsec0_res[] = { + { + .type = RTEMS_BSD_RES_MEMORY, + .start_request = 0, + .start_actual = 0xffeb0000 + }, { + .type = RTEMS_BSD_RES_IRQ, + .start_request = 0, + .start_actual = QORIQ_IRQ_ETSEC_TX_1 + }, { + .type = RTEMS_BSD_RES_IRQ, + .start_request = 1, + .start_actual = QORIQ_IRQ_ETSEC_RX_1 + }, { + .type = RTEMS_BSD_RES_IRQ, + .start_request = 2, + .start_actual = QORIQ_IRQ_ETSEC_ER_1 + } +}; + +RTEMS_BSD_DEFINE_NEXUS_DEVICE(tsec, 0, RTEMS_ARRAY_SIZE(tsec0_res), + &tsec0_res[0]); + #endif diff --git a/rtemsbsd/sys/dev/tsec/if_tsec_nexus.c b/rtemsbsd/sys/dev/tsec/if_tsec_nexus.c new file mode 100644 index 00000000..72dfafa1 --- /dev/null +++ b/rtemsbsd/sys/dev/tsec/if_tsec_nexus.c @@ -0,0 +1,310 @@ +#include + +/*- + * Copyright (C) 2007-2008 Semihalf, Rafal Jaworowski + * Copyright (C) 2006-2007 Semihalf, Piotr Kruszynski + * 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 ``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 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. + * + * From: FreeBSD: head/sys/dev/tsec/if_tsec_ocp.c 188712 2009-02-17 14:59:47Z raj + */ + +/* + * FDT 'simple-bus' attachment for Freescale TSEC controller. + */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#ifdef __rtems__ +#include +#endif /* __rtems__ */ + +#define TSEC_RID_TXIRQ 0 +#define TSEC_RID_RXIRQ 1 +#define TSEC_RID_ERRIRQ 2 + +static int tsec_fdt_probe(device_t dev); +static int tsec_fdt_attach(device_t dev); +static int tsec_fdt_detach(device_t dev); +static int tsec_setup_intr(struct tsec_softc *sc, struct resource **ires, + void **ihand, int *irid, driver_intr_t handler, const char *iname); +static void tsec_release_intr(struct tsec_softc *sc, struct resource *ires, + void *ihand, int irid, const char *iname); + +static device_method_t tsec_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, tsec_fdt_probe), + DEVMETHOD(device_attach, tsec_fdt_attach), + DEVMETHOD(device_detach, tsec_fdt_detach), + + DEVMETHOD(device_shutdown, tsec_shutdown), + DEVMETHOD(device_suspend, tsec_suspend), + DEVMETHOD(device_resume, tsec_resume), + + /* MII interface */ + DEVMETHOD(miibus_readreg, tsec_miibus_readreg), + DEVMETHOD(miibus_writereg, tsec_miibus_writereg), + DEVMETHOD(miibus_statchg, tsec_miibus_statchg), + + DEVMETHOD_END +}; + +static driver_t tsec_nexus_driver = { + "tsec", + tsec_methods, + sizeof(struct tsec_softc), +}; + +DRIVER_MODULE(tsec, nexus, tsec_nexus_driver, tsec_devclass, 0, 0); +MODULE_DEPEND(tsec, nexus, 1, 1, 1); +MODULE_DEPEND(tsec, ether, 1, 1, 1); + +static int +tsec_fdt_probe(device_t dev) +{ + struct tsec_softc *sc; + uint32_t id; + + sc = device_get_softc(dev); + + sc->sc_rrid = 0; + sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid, + RF_ACTIVE); + if (sc->sc_rres == NULL) + return (ENXIO); + + sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); + sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); + + /* Check if we are eTSEC (enhanced TSEC) */ + id = TSEC_READ(sc, TSEC_REG_ID); + sc->is_etsec = ((id >> 16) == TSEC_ETSEC_ID) ? 1 : 0; + id |= TSEC_READ(sc, TSEC_REG_ID2); + + bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, sc->sc_rres); + + if (id == 0) { + device_printf(dev, "could not identify TSEC type\n"); + return (ENXIO); + } + + if (sc->is_etsec) + device_set_desc(dev, "Enhanced Three-Speed Ethernet Controller"); + else + device_set_desc(dev, "Three-Speed Ethernet Controller"); + + return (BUS_PROBE_DEFAULT); +} + +static int +tsec_fdt_attach(device_t dev) +{ + struct tsec_softc *sc; + int error = 0; + + sc = device_get_softc(dev); + sc->dev = dev; + + /* FIXME */ + sc->phy_sc = sc; + sc->phyaddr = -1; + + /* Init timer */ + callout_init(&sc->tsec_callout, 1); + + /* Init locks */ + mtx_init(&sc->transmit_lock, device_get_nameunit(dev), "TSEC TX lock", + MTX_DEF); + mtx_init(&sc->receive_lock, device_get_nameunit(dev), "TSEC RX lock", + MTX_DEF); + mtx_init(&sc->ic_lock, device_get_nameunit(dev), "TSEC IC lock", + MTX_DEF); + + /* Allocate IO memory for TSEC registers */ + sc->sc_rrid = 0; + sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid, + RF_ACTIVE); + if (sc->sc_rres == NULL) { + device_printf(dev, "could not allocate IO memory range!\n"); + goto fail1; + } + sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); + sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); + + /* TSEC attach */ + if (tsec_attach(sc) != 0) { + device_printf(dev, "could not be configured\n"); + goto fail2; + } + + /* Set up interrupts (TX/RX/ERR) */ + sc->sc_transmit_irid = TSEC_RID_TXIRQ; + error = tsec_setup_intr(sc, &sc->sc_transmit_ires, + &sc->sc_transmit_ihand, &sc->sc_transmit_irid, + tsec_transmit_intr, "TX"); + if (error) + goto fail2; + + sc->sc_receive_irid = TSEC_RID_RXIRQ; + error = tsec_setup_intr(sc, &sc->sc_receive_ires, + &sc->sc_receive_ihand, &sc->sc_receive_irid, + tsec_receive_intr, "RX"); + if (error) + goto fail3; + + sc->sc_error_irid = TSEC_RID_ERRIRQ; + error = tsec_setup_intr(sc, &sc->sc_error_ires, + &sc->sc_error_ihand, &sc->sc_error_irid, + tsec_error_intr, "ERR"); + if (error) + goto fail4; + + return (0); + +fail4: + tsec_release_intr(sc, sc->sc_receive_ires, sc->sc_receive_ihand, + sc->sc_receive_irid, "RX"); +fail3: + tsec_release_intr(sc, sc->sc_transmit_ires, sc->sc_transmit_ihand, + sc->sc_transmit_irid, "TX"); +fail2: + bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, sc->sc_rres); +fail1: + mtx_destroy(&sc->receive_lock); + mtx_destroy(&sc->transmit_lock); + return (ENXIO); +} + +static int +tsec_setup_intr(struct tsec_softc *sc, struct resource **ires, void **ihand, + int *irid, driver_intr_t handler, const char *iname) +{ + int error; + + *ires = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, irid, RF_ACTIVE); + if (*ires == NULL) { + device_printf(sc->dev, "could not allocate %s IRQ\n", iname); + return (ENXIO); + } + error = bus_setup_intr(sc->dev, *ires, INTR_TYPE_NET | INTR_MPSAFE, + NULL, handler, sc, ihand); + if (error) { + device_printf(sc->dev, "failed to set up %s IRQ\n", iname); + if (bus_release_resource(sc->dev, SYS_RES_IRQ, *irid, *ires)) + device_printf(sc->dev, "could not release %s IRQ\n", iname); + *ires = NULL; + return (error); + } + return (0); +} + +static void +tsec_release_intr(struct tsec_softc *sc, struct resource *ires, void *ihand, + int irid, const char *iname) +{ + int error; + + if (ires == NULL) + return; + + error = bus_teardown_intr(sc->dev, ires, ihand); + if (error) + device_printf(sc->dev, "bus_teardown_intr() failed for %s intr" + ", error %d\n", iname, error); + + error = bus_release_resource(sc->dev, SYS_RES_IRQ, irid, ires); + if (error) + device_printf(sc->dev, "bus_release_resource() failed for %s " + "intr, error %d\n", iname, error); +} + +static int +tsec_fdt_detach(device_t dev) +{ + struct tsec_softc *sc; + int error; + + sc = device_get_softc(dev); + + /* Wait for stopping watchdog */ + callout_drain(&sc->tsec_callout); + + /* Stop and release all interrupts */ + tsec_release_intr(sc, sc->sc_transmit_ires, sc->sc_transmit_ihand, + sc->sc_transmit_irid, "TX"); + tsec_release_intr(sc, sc->sc_receive_ires, sc->sc_receive_ihand, + sc->sc_receive_irid, "RX"); + tsec_release_intr(sc, sc->sc_error_ires, sc->sc_error_ihand, + sc->sc_error_irid, "ERR"); + + /* TSEC detach */ + tsec_detach(sc); + + /* Free IO memory handler */ + if (sc->sc_rres) { + error = bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, + sc->sc_rres); + if (error) + device_printf(dev, "bus_release_resource() failed for" + " IO memory, error %d\n", error); + } + + /* Destroy locks */ + mtx_destroy(&sc->receive_lock); + mtx_destroy(&sc->transmit_lock); + mtx_destroy(&sc->ic_lock); + return (0); +} + +void +tsec_get_hwaddr(struct tsec_softc *sc, uint8_t *addr) +{ + rtems_bsd_get_mac_address(device_get_name(sc->dev), + device_get_unit(sc->dev), addr); +} -- cgit v1.2.3