1256752Sbrooks/*- 2256752Sbrooks * Copyright (c) 2012,2013 Bjoern A. Zeeb 3256752Sbrooks * All rights reserved. 4256752Sbrooks * 5256752Sbrooks * This software was developed by SRI International and the University of 6256752Sbrooks * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-11-C-0249) 7256752Sbrooks * ("MRC2"), as part of the DARPA MRC research programme. 8256752Sbrooks * 9256752Sbrooks * Redistribution and use in source and binary forms, with or without 10256752Sbrooks * modification, are permitted provided that the following conditions 11256752Sbrooks * are met: 12256752Sbrooks * 1. Redistributions of source code must retain the above copyright 13256752Sbrooks * notice, this list of conditions and the following disclaimer. 14256752Sbrooks * 2. Redistributions in binary form must reproduce the above copyright 15256752Sbrooks * notice, this list of conditions and the following disclaimer in the 16256752Sbrooks * documentation and/or other materials provided with the distribution. 17256752Sbrooks * 18256752Sbrooks * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19256752Sbrooks * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20256752Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21256752Sbrooks * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22256752Sbrooks * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23256752Sbrooks * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24256752Sbrooks * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25256752Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26256752Sbrooks * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27256752Sbrooks * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28256752Sbrooks * SUCH DAMAGE. 29256752Sbrooks */ 30256752Sbrooks 31256752Sbrooks#include <sys/cdefs.h> 32256752Sbrooks__FBSDID("$FreeBSD$"); 33256752Sbrooks 34256752Sbrooks#include "opt_device_polling.h" 35256752Sbrooks 36256752Sbrooks#include <sys/param.h> 37256752Sbrooks#include <sys/kernel.h> 38256752Sbrooks#include <sys/bus.h> 39256752Sbrooks#include <sys/module.h> 40256752Sbrooks#include <sys/rman.h> 41256752Sbrooks#include <sys/socket.h> 42256752Sbrooks#include <sys/types.h> 43256752Sbrooks 44256752Sbrooks#include <machine/bus.h> 45256752Sbrooks#include <machine/resource.h> 46256752Sbrooks 47256752Sbrooks#include <net/ethernet.h> 48256752Sbrooks#include <net/if.h> 49256752Sbrooks#include <net/if_media.h> 50257269Sbrooks#include <net/if_var.h> 51256752Sbrooks 52256752Sbrooks#include <dev/mii/mii.h> 53256752Sbrooks#include <dev/mii/miivar.h> 54256752Sbrooks 55256752Sbrooks#include <dev/altera/atse/if_atsereg.h> 56256752Sbrooks 57256752Sbrooks/* "device miibus" required. See GENERIC if you get errors here. */ 58256752Sbrooks#include "miibus_if.h" 59256752Sbrooks 60256752SbrooksMODULE_DEPEND(atse, ether, 1, 1, 1); 61256752SbrooksMODULE_DEPEND(atse, miibus, 1, 1, 1); 62256752Sbrooks 63256752Sbrooks/* 64256752Sbrooks * Device routines for interacting with nexus (probe, attach, detach) & helpers. 65256752Sbrooks * XXX We should add suspend/resume later. 66256752Sbrooks */ 67256752Sbrooksstatic int 68256752Sbrooksatse_resource_int(device_t dev, const char *resname, int *v) 69256752Sbrooks{ 70256752Sbrooks int error; 71256752Sbrooks 72256752Sbrooks error = resource_int_value(device_get_name(dev), device_get_unit(dev), 73256752Sbrooks resname, v); 74256752Sbrooks if (error != 0) { 75256752Sbrooks /* If it does not exist, we fail, so not ingoring ENOENT. */ 76256752Sbrooks device_printf(dev, "could not fetch '%s' hint\n", resname); 77256752Sbrooks return (error); 78256752Sbrooks } 79256752Sbrooks 80256752Sbrooks return (0); 81256752Sbrooks} 82256752Sbrooks 83256752Sbrooksstatic int 84256752Sbrooksatse_resource_long(device_t dev, const char *resname, long *v) 85256752Sbrooks{ 86256752Sbrooks int error; 87256752Sbrooks 88256752Sbrooks error = resource_long_value(device_get_name(dev), device_get_unit(dev), 89256752Sbrooks resname, v); 90256752Sbrooks if (error != 0) { 91256752Sbrooks /* If it does not exist, we fail, so not ingoring ENOENT. */ 92256752Sbrooks device_printf(dev, "could not fetch '%s' hint\n", resname); 93256752Sbrooks return (error); 94256752Sbrooks } 95256752Sbrooks 96256752Sbrooks return (0); 97256752Sbrooks} 98256752Sbrooks 99256752Sbrooksstatic int 100256752Sbrooksatse_probe_nexus(device_t dev) 101256752Sbrooks{ 102256752Sbrooks struct resource *res; 103256752Sbrooks long l; 104256752Sbrooks int error, rid; 105256752Sbrooks 106256752Sbrooks /* 107256752Sbrooks * It is almost impossible to properly probe this device. We must 108256752Sbrooks * rely on hints being set correctly. So try to get hints and 109256752Sbrooks * one memory mapping. Must cleanup and do again in attach but 110256752Sbrooks * should not probe successfully if not able to attach later. 111256752Sbrooks */ 112256752Sbrooks error = atse_resource_int(dev, "rx_irq", &rid); 113256752Sbrooks error += atse_resource_long(dev, "rx_maddr", &l); 114256752Sbrooks error += atse_resource_long(dev, "rx_msize", &l); 115256752Sbrooks error += atse_resource_long(dev, "rxc_maddr", &l); 116256752Sbrooks error += atse_resource_long(dev, "rxc_msize", &l); 117256752Sbrooks error += atse_resource_int(dev, "tx_irq", &rid); 118256752Sbrooks error += atse_resource_long(dev, "tx_maddr", &l); 119256752Sbrooks error += atse_resource_long(dev, "tx_msize", &l); 120256752Sbrooks error += atse_resource_long(dev, "txc_maddr", &l); 121256752Sbrooks error += atse_resource_long(dev, "txc_msize", &l); 122256752Sbrooks if (error != 0) 123256752Sbrooks return (ENXIO); 124256752Sbrooks 125256752Sbrooks rid = 0; 126256752Sbrooks res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 127256752Sbrooks if (res == NULL) 128256752Sbrooks return (ENXIO); 129256752Sbrooks bus_release_resource(dev, SYS_RES_MEMORY, rid, res); 130256752Sbrooks 131256752Sbrooks /* Success. */ 132256752Sbrooks device_set_desc(dev, "Altera Triple-Speed Ethernet MegaCore"); 133257336Snwhitehorn return (BUS_PROBE_NOWILDCARD); 134256752Sbrooks} 135256752Sbrooks 136256752Sbrooksstatic int 137256752Sbrooksatse_attach_nexus(device_t dev) 138256752Sbrooks{ 139256752Sbrooks struct atse_softc *sc; 140256752Sbrooks int error; 141256752Sbrooks 142256752Sbrooks sc = device_get_softc(dev); 143256752Sbrooks sc->atse_dev = dev; 144256752Sbrooks sc->atse_unit = device_get_unit(dev); 145256752Sbrooks 146256752Sbrooks /* Get RX and TX IRQ and FIFO information from hints. */ 147256752Sbrooks error = atse_resource_int(dev, "rx_irq", &sc->atse_rx_irq); 148256752Sbrooks error += atse_resource_long(dev, "rx_maddr", &sc->atse_rx_maddr); 149256752Sbrooks error += atse_resource_long(dev, "rx_msize", &sc->atse_rx_msize); 150256752Sbrooks error += atse_resource_long(dev, "rxc_maddr", &sc->atse_rxc_maddr); 151256752Sbrooks error += atse_resource_long(dev, "rxc_msize", &sc->atse_rxc_msize); 152256752Sbrooks error += atse_resource_int(dev, "tx_irq", &sc->atse_tx_irq); 153256752Sbrooks error += atse_resource_long(dev, "tx_maddr", &sc->atse_tx_maddr); 154256752Sbrooks error += atse_resource_long(dev, "tx_msize", &sc->atse_tx_msize); 155256752Sbrooks error += atse_resource_long(dev, "txc_maddr", &sc->atse_txc_maddr); 156256752Sbrooks error += atse_resource_long(dev, "txc_msize", &sc->atse_txc_msize); 157256752Sbrooks if (error != 0) 158256752Sbrooks return (error); 159256752Sbrooks 160256752Sbrooks /* Avalon-MM, atse management register region. */ 161256752Sbrooks sc->atse_mem_rid = 0; 162256752Sbrooks sc->atse_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 163256752Sbrooks &sc->atse_mem_rid, RF_ACTIVE); 164256752Sbrooks if (sc->atse_mem_res == NULL) { 165256752Sbrooks device_printf(dev, "failed to map memory for ctrl region\n"); 166256752Sbrooks return (ENXIO); 167256752Sbrooks } 168256752Sbrooks 169256752Sbrooks /* 170256752Sbrooks * (Optional) RX IRQ and memory mapped regions. 171256752Sbrooks * 0x00: 2 * 32bit FIFO data, 172256752Sbrooks * 0x20: 8 * 32bit FIFO ctrl, Avalon-ST Sink to Avalon-MM R-Slave. 173256752Sbrooks */ 174256752Sbrooks sc->atse_rx_irq_rid = 0; 175256752Sbrooks sc->atse_rx_irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, 176256752Sbrooks &sc->atse_rx_irq_rid, sc->atse_rx_irq, sc->atse_rx_irq, 1, 177256752Sbrooks RF_ACTIVE | RF_SHAREABLE); 178256752Sbrooks 179256752Sbrooks sc->atse_rx_mem_rid = 0; 180256752Sbrooks sc->atse_rx_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, 181256752Sbrooks &sc->atse_rx_mem_rid, sc->atse_rx_maddr, sc->atse_rx_maddr + 182256752Sbrooks sc->atse_rx_msize, sc->atse_rx_msize, RF_ACTIVE); 183256752Sbrooks if (sc->atse_rx_mem_res == NULL) { 184256752Sbrooks device_printf(dev, "failed to map memory for RX\n"); 185256752Sbrooks goto err; 186256752Sbrooks } 187256752Sbrooks sc->atse_rxc_mem_rid = 0; 188256752Sbrooks sc->atse_rxc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, 189256752Sbrooks &sc->atse_rxc_mem_rid, sc->atse_rxc_maddr, sc->atse_rxc_maddr + 190256752Sbrooks sc->atse_rxc_msize, sc->atse_rxc_msize, RF_ACTIVE); 191256752Sbrooks if (sc->atse_rxc_mem_res == NULL) { 192256752Sbrooks device_printf(dev, "failed to map memory for RX control\n"); 193256752Sbrooks goto err; 194256752Sbrooks } 195256752Sbrooks 196256752Sbrooks /* 197256752Sbrooks * (Optional) TX IRQ and memory mapped regions. 198256752Sbrooks * 0x00: 2 * 32bit FIFO data, 199256752Sbrooks * 0x20: 8 * 32bit FIFO ctrl, Avalon-MM W-Slave to Avalon-ST Source. 200256752Sbrooks */ 201256752Sbrooks sc->atse_tx_irq_rid = 0; 202256752Sbrooks sc->atse_tx_irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, 203256752Sbrooks &sc->atse_tx_irq_rid, sc->atse_tx_irq, sc->atse_tx_irq, 1, 204256752Sbrooks RF_ACTIVE | RF_SHAREABLE); 205256752Sbrooks 206256752Sbrooks sc->atse_tx_mem_rid = 0; 207256752Sbrooks sc->atse_tx_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, 208256752Sbrooks &sc->atse_tx_mem_rid, sc->atse_tx_maddr, sc->atse_tx_maddr + 209256752Sbrooks sc->atse_tx_msize, sc->atse_tx_msize, RF_ACTIVE); 210256752Sbrooks if (sc->atse_tx_mem_res == NULL) { 211256752Sbrooks device_printf(dev, "failed to map memory for TX\n"); 212256752Sbrooks goto err; 213256752Sbrooks } 214256752Sbrooks sc->atse_txc_mem_rid = 0; 215256752Sbrooks sc->atse_txc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, 216256752Sbrooks &sc->atse_txc_mem_rid, sc->atse_txc_maddr, sc->atse_txc_maddr + 217256752Sbrooks sc->atse_txc_msize, sc->atse_txc_msize, RF_ACTIVE); 218256752Sbrooks if (sc->atse_txc_mem_res == NULL) { 219256752Sbrooks device_printf(dev, "failed to map memory for TX control\n"); 220256752Sbrooks goto err; 221256752Sbrooks } 222256752Sbrooks 223256752Sbrooks error = atse_attach(dev); 224256752Sbrooks if (error) 225256752Sbrooks goto err; 226256752Sbrooks 227256752Sbrooks return (0); 228256752Sbrooks 229256752Sbrookserr: 230256752Sbrooks /* Cleanup. */ 231256752Sbrooks atse_detach_resources(dev); 232256752Sbrooks 233256752Sbrooks return (error); 234256752Sbrooks} 235256752Sbrooks 236256752Sbrooksstatic device_method_t atse_methods_nexus[] = { 237256752Sbrooks /* Device interface */ 238256752Sbrooks DEVMETHOD(device_probe, atse_probe_nexus), 239256752Sbrooks DEVMETHOD(device_attach, atse_attach_nexus), 240256752Sbrooks DEVMETHOD(device_detach, atse_detach_dev), 241256752Sbrooks 242256752Sbrooks /* MII interface */ 243256752Sbrooks DEVMETHOD(miibus_readreg, atse_miibus_readreg), 244256752Sbrooks DEVMETHOD(miibus_writereg, atse_miibus_writereg), 245256752Sbrooks DEVMETHOD(miibus_statchg, atse_miibus_statchg), 246256752Sbrooks 247256752Sbrooks DEVMETHOD_END 248256752Sbrooks}; 249256752Sbrooks 250256752Sbrooksstatic driver_t atse_driver_nexus = { 251256752Sbrooks "atse", 252256752Sbrooks atse_methods_nexus, 253256752Sbrooks sizeof(struct atse_softc) 254256752Sbrooks}; 255256752Sbrooks 256256752SbrooksDRIVER_MODULE(atse, nexus, atse_driver_nexus, atse_devclass, 0, 0); 257256752SbrooksDRIVER_MODULE(miibus, atse, miibus_driver, miibus_devclass, 0, 0); 258256752Sbrooks 259256752Sbrooks/* end */ 260