1198160Srrs/*- 2198160Srrs * Copyright (c) 2003-2009 RMI Corporation 3198160Srrs * All rights reserved. 4198160Srrs * 5198160Srrs * Redistribution and use in source and binary forms, with or without 6198160Srrs * modification, are permitted provided that the following conditions 7198160Srrs * are met: 8198160Srrs * 1. Redistributions of source code must retain the above copyright 9198160Srrs * notice, this list of conditions and the following disclaimer. 10198160Srrs * 2. Redistributions in binary form must reproduce the above copyright 11198160Srrs * notice, this list of conditions and the following disclaimer in the 12198160Srrs * documentation and/or other materials provided with the distribution. 13198160Srrs * 3. Neither the name of RMI Corporation, nor the names of its contributors, 14198160Srrs * may be used to endorse or promote products derived from this software 15198160Srrs * without specific prior written permission. 16198160Srrs * 17198160Srrs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18198160Srrs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19198160Srrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20198160Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21198160Srrs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22198160Srrs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23198160Srrs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24198160Srrs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25198160Srrs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26198160Srrs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27198160Srrs * SUCH DAMAGE. 28198160Srrs * 29202066Simp * RMI_BSD 30202066Simp */ 31198160Srrs 32202066Simp#include <sys/cdefs.h> 33202066Simp__FBSDID("$FreeBSD$"); 34202066Simp 35198160Srrs#define __RMAN_RESOURCE_VISIBLE 36198160Srrs#include <sys/param.h> 37198160Srrs#include <sys/systm.h> 38198160Srrs#include <sys/bus.h> 39198160Srrs#include <sys/kernel.h> 40198160Srrs#include <sys/lock.h> 41198160Srrs#include <sys/mutex.h> 42198160Srrs#include <sys/reboot.h> 43211994Sjchandra#include <sys/rman.h> 44198160Srrs#include <sys/types.h> 45198160Srrs#include <sys/malloc.h> 46198160Srrs#include <sys/interrupt.h> 47198160Srrs#include <sys/module.h> 48198160Srrs 49198160Srrs#include <machine/cpu.h> 50198160Srrs#include <machine/bus.h> 51198607Srrs#include <machine/param.h> 52198607Srrs#include <machine/intr_machdep.h> 53198607Srrs#include <machine/clock.h> /* for DELAY */ 54198607Srrs#include <machine/resource.h> 55211994Sjchandra 56211994Sjchandra#include <mips/rmi/board.h> 57211994Sjchandra#include <mips/rmi/pic.h> 58198607Srrs#include <mips/rmi/interrupt.h> 59198607Srrs#include <mips/rmi/msgring.h> 60198607Srrs#include <mips/rmi/iomap.h> 61211994Sjchandra#include <mips/rmi/rmi_mips_exts.h> 62198607Srrs 63202066Simp#include <mips/rmi/dev/xlr/atx_cpld.h> 64202066Simp#include <mips/rmi/dev/xlr/xgmac_mdio.h> 65198607Srrs 66198160Srrsextern bus_space_tag_t uart_bus_space_mem; 67198160Srrs 68198625Srrsstatic struct resource * 69198625Srrsiodi_alloc_resource(device_t, device_t, int, int *, 70198625Srrs u_long, u_long, u_long, u_int); 71198160Srrs 72199090Srrsstatic int 73198625Srrsiodi_activate_resource(device_t, device_t, int, int, 74198625Srrs struct resource *); 75199090Srrsstatic int 76198625Srrsiodi_setup_intr(device_t, device_t, struct resource *, int, 77198625Srrs driver_filter_t *, driver_intr_t *, void *, void **); 78198160Srrs 79198625Srrsstruct iodi_softc *iodi_softc; /* There can be only one. */ 80198160Srrs 81211923Sjchandra/* 82211923Sjchandra * We will manage the Flash/PCMCIA devices in IODI for now. 83211923Sjchandra * The NOR flash, Compact flash etc. which can be connected on 84211923Sjchandra * various chip selects on the peripheral IO, should have a 85211923Sjchandra * separate bus later. 86211923Sjchandra */ 87211923Sjchandrastatic void 88211923Sjchandrabridge_pcmcia_ack(int irq) 89211923Sjchandra{ 90211923Sjchandra xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_FLASH_OFFSET); 91211923Sjchandra 92211923Sjchandra xlr_write_reg(mmio, 0x60, 0xffffffff); 93211923Sjchandra} 94211923Sjchandra 95198160Srrsstatic int 96198160Srrsiodi_setup_intr(device_t dev, device_t child, 97212102Sjchandra struct resource *ires, int flags, driver_filter_t *filt, 98211811Sjchandra driver_intr_t *intr, void *arg, void **cookiep) 99198160Srrs{ 100211946Sjchandra const char *name = device_get_name(child); 101198160Srrs 102211946Sjchandra if (strcmp(name, "uart") == 0) { 103198625Srrs /* FIXME uart 1? */ 104211811Sjchandra cpu_establish_hardintr("uart", filt, intr, arg, 105211811Sjchandra PIC_UART_0_IRQ, flags, cookiep); 106212248Sjchandra pic_setup_intr(PIC_IRT_UART_0_INDEX, PIC_UART_0_IRQ, 0x1, 1); 107211946Sjchandra } else if (strcmp(name, "rge") == 0 || strcmp(name, "nlge") == 0) { 108198625Srrs int irq; 109199090Srrs 110199089Srrs /* This is a hack to pass in the irq */ 111209808Sjchandra irq = (intptr_t)ires->__r_i; 112211811Sjchandra cpu_establish_hardintr("rge", filt, intr, arg, irq, flags, 113211811Sjchandra cookiep); 114212248Sjchandra pic_setup_intr(irq - PIC_IRQ_BASE, irq, 0x1, 1); 115211946Sjchandra } else if (strcmp(name, "ehci") == 0) { 116211811Sjchandra cpu_establish_hardintr("ehci", filt, intr, arg, PIC_USB_IRQ, flags, 117211811Sjchandra cookiep); 118212248Sjchandra pic_setup_intr(PIC_USB_IRQ - PIC_IRQ_BASE, PIC_USB_IRQ, 0x1, 1); 119211946Sjchandra } else if (strcmp(name, "ata") == 0) { 120211923Sjchandra xlr_establish_intr("ata", filt, intr, arg, PIC_PCMCIA_IRQ, flags, 121211923Sjchandra cookiep, bridge_pcmcia_ack); 122212248Sjchandra pic_setup_intr(PIC_PCMCIA_IRQ - PIC_IRQ_BASE, PIC_PCMCIA_IRQ, 0x1, 1); 123198625Srrs } 124198625Srrs return (0); 125198160Srrs} 126198160Srrs 127198160Srrsstatic struct resource * 128198160Srrsiodi_alloc_resource(device_t bus, device_t child, int type, int *rid, 129198625Srrs u_long start, u_long end, u_long count, u_int flags) 130198160Srrs{ 131198160Srrs struct resource *res = malloc(sizeof(*res), M_DEVBUF, M_WAITOK); 132212102Sjchandra const char *name = device_get_name(child); 133198160Srrs int unit; 134198160Srrs 135198160Srrs#ifdef DEBUG 136198160Srrs switch (type) { 137198160Srrs case SYS_RES_IRQ: 138198160Srrs device_printf(bus, "IRQ resource - for %s %lx-%lx\n", 139198625Srrs device_get_nameunit(child), start, end); 140198625Srrs break; 141198160Srrs 142198625Srrs case SYS_RES_IOPORT: 143198160Srrs device_printf(bus, "IOPORT resource - for %s %lx-%lx\n", 144198625Srrs device_get_nameunit(child), start, end); 145198625Srrs break; 146198160Srrs 147198625Srrs case SYS_RES_MEMORY: 148198160Srrs device_printf(bus, "MEMORY resource - for %s %lx-%lx\n", 149198625Srrs device_get_nameunit(child), start, end); 150198625Srrs break; 151198625Srrs } 152198160Srrs#endif 153198160Srrs 154212102Sjchandra if (strcmp(name, "uart") == 0) { 155198625Srrs if ((unit = device_get_unit(child)) == 0) { /* uart 0 */ 156198160Srrs res->r_bushandle = (xlr_io_base + XLR_IO_UART_0_OFFSET); 157198625Srrs } else if (unit == 1) { 158198160Srrs res->r_bushandle = (xlr_io_base + XLR_IO_UART_1_OFFSET); 159198625Srrs } else 160198160Srrs printf("%s: Unknown uart unit\n", __FUNCTION__); 161198160Srrs 162198160Srrs res->r_bustag = uart_bus_space_mem; 163212102Sjchandra } else if (strcmp(name, "ehci") == 0) { 164209808Sjchandra res->r_bushandle = MIPS_PHYS_TO_KSEG1(0x1ef24000); 165204577Srrs res->r_bustag = rmi_pci_bus_space; 166212102Sjchandra } else if (strcmp(name, "cfi") == 0) { 167209808Sjchandra res->r_bushandle = MIPS_PHYS_TO_KSEG1(0x1c000000); 168198160Srrs res->r_bustag = 0; 169212102Sjchandra } else if (strcmp(name, "ata") == 0) { 170211923Sjchandra res->r_bushandle = MIPS_PHYS_TO_KSEG1(0x1d000000); 171211923Sjchandra res->r_bustag = rmi_pci_bus_space; /* byte swapping (not really PCI) */ 172198160Srrs } 173198625Srrs /* res->r_start = *rid; */ 174198160Srrs return (res); 175198160Srrs} 176198160Srrs 177198160Srrsstatic int 178198160Srrsiodi_activate_resource(device_t bus, device_t child, int type, int rid, 179198625Srrs struct resource *r) 180198160Srrs{ 181198160Srrs return (0); 182198160Srrs} 183198625Srrs 184198160Srrs/* prototypes */ 185198625Srrsstatic int iodi_probe(device_t); 186198625Srrsstatic int iodi_attach(device_t); 187211946Sjchandrastatic int iodi_detach(device_t); 188198625Srrsstatic void iodi_identify(driver_t *, device_t); 189198160Srrs 190198160Srrsint 191198160Srrsiodi_probe(device_t dev) 192198160Srrs{ 193198160Srrs return 0; 194198160Srrs} 195198160Srrs 196198160Srrsvoid 197198625Srrsiodi_identify(driver_t * driver, device_t parent) 198198160Srrs{ 199198625Srrs 200198160Srrs BUS_ADD_CHILD(parent, 0, "iodi", 0); 201198160Srrs} 202198160Srrs 203198160Srrsint 204198160Srrsiodi_attach(device_t dev) 205198160Srrs{ 206198160Srrs device_t tmpd; 207211946Sjchandra int i; 208198625Srrs 209198160Srrs /* 210198625Srrs * Attach each devices 211198160Srrs */ 212198160Srrs device_add_child(dev, "uart", 0); 213198160Srrs device_add_child(dev, "xlr_i2c", 0); 214216390Sjchandra device_add_child(dev, "xlr_i2c", 1); 215208165Srrs device_add_child(dev, "pcib", 0); 216212763Sjchandra device_add_child(dev, "rmisec", -1); 217198625Srrs 218198160Srrs if (xlr_board_info.usb) 219198160Srrs device_add_child(dev, "ehci", 0); 220198625Srrs 221198160Srrs if (xlr_board_info.cfi) 222198160Srrs device_add_child(dev, "cfi", 0); 223198160Srrs 224211923Sjchandra if (xlr_board_info.ata) 225211923Sjchandra device_add_child(dev, "ata", 0); 226211923Sjchandra 227198160Srrs if (xlr_board_info.gmac_block[0].enabled) { 228198160Srrs tmpd = device_add_child(dev, "rge", 0); 229198160Srrs device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]); 230198160Srrs 231198160Srrs tmpd = device_add_child(dev, "rge", 1); 232198160Srrs device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]); 233198160Srrs 234198160Srrs tmpd = device_add_child(dev, "rge", 2); 235198160Srrs device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]); 236198160Srrs 237198160Srrs tmpd = device_add_child(dev, "rge", 3); 238198160Srrs device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]); 239198160Srrs } 240198160Srrs if (xlr_board_info.gmac_block[1].enabled) { 241198160Srrs if (xlr_board_info.gmac_block[1].type == XLR_GMAC) { 242198160Srrs tmpd = device_add_child(dev, "rge", 4); 243198160Srrs device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]); 244198160Srrs 245198160Srrs tmpd = device_add_child(dev, "rge", 5); 246198160Srrs device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]); 247198160Srrs 248204137Srrs if (xlr_board_info.gmac_block[1].enabled & 0x4) { 249204137Srrs tmpd = device_add_child(dev, "rge", 6); 250204137Srrs device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]); 251204137Srrs } 252198160Srrs 253204137Srrs if (xlr_board_info.gmac_block[1].enabled & 0x8) { 254204137Srrs tmpd = device_add_child(dev, "rge", 7); 255204137Srrs device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]); 256204137Srrs } 257198160Srrs } else if (xlr_board_info.gmac_block[1].type == XLR_XGMAC) { 258198625Srrs#if 0 /* XGMAC not yet */ 259198160Srrs tmpd = device_add_child(dev, "rge", 4); 260198160Srrs device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]); 261198160Srrs 262198160Srrs tmpd = device_add_child(dev, "rge", 5); 263198160Srrs device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]); 264198160Srrs#endif 265211946Sjchandra } else 266211946Sjchandra device_printf(dev, "Unknown type of gmac 1\n"); 267198160Srrs } 268211946Sjchandra 269211946Sjchandra /* This is to add the new GMAC driver. The above adds the old driver, 270211946Sjchandra which has been retained for now as the new driver is stabilized. 271211946Sjchandra The new driver is enabled with "option nlge". Make sure that only 272211946Sjchandra one of rge or nlge is enabled in the conf file. */ 273211946Sjchandra for (i = 0; i < 3; i++) { 274211946Sjchandra if (xlr_board_info.gmac_block[i].enabled == 0) 275211946Sjchandra continue; 276211946Sjchandra tmpd = device_add_child(dev, "nlna", i); 277211946Sjchandra device_set_ivars(tmpd, &xlr_board_info.gmac_block[i]); 278211946Sjchandra } 279198160Srrs bus_generic_probe(dev); 280198160Srrs bus_generic_attach(dev); 281198160Srrs return 0; 282198160Srrs} 283198160Srrs 284211946Sjchandraint 285211946Sjchandraiodi_detach(device_t dev) 286211946Sjchandra{ 287211946Sjchandra device_t nlna_dev; 288211946Sjchandra int error, i, ret; 289211946Sjchandra 290211946Sjchandra error = 0; 291211946Sjchandra ret = 0; 292211946Sjchandra for (i = 0; i < 3; i++) { 293211946Sjchandra nlna_dev = device_find_child(dev, "nlna", i); 294211946Sjchandra if (nlna_dev != NULL) 295211946Sjchandra error = bus_generic_detach(nlna_dev); 296211946Sjchandra if (error) 297211946Sjchandra ret = error; 298211946Sjchandra } 299211946Sjchandra return ret; 300211946Sjchandra} 301211946Sjchandra 302198160Srrsstatic device_method_t iodi_methods[] = { 303198160Srrs DEVMETHOD(device_probe, iodi_probe), 304198160Srrs DEVMETHOD(device_attach, iodi_attach), 305211946Sjchandra DEVMETHOD(device_detach, iodi_detach), 306198160Srrs DEVMETHOD(device_identify, iodi_identify), 307198160Srrs DEVMETHOD(bus_alloc_resource, iodi_alloc_resource), 308198160Srrs DEVMETHOD(bus_activate_resource, iodi_activate_resource), 309212550Sjchandra DEVMETHOD(bus_add_child, bus_generic_add_child), 310198160Srrs DEVMETHOD(bus_setup_intr, iodi_setup_intr), 311198160Srrs {0, 0}, 312198160Srrs}; 313198160Srrs 314198160Srrsstatic driver_t iodi_driver = { 315198160Srrs "iodi", 316198160Srrs iodi_methods, 317198625Srrs 1 /* no softc */ 318198160Srrs}; 319198160Srrsstatic devclass_t iodi_devclass; 320198160Srrs 321198160SrrsDRIVER_MODULE(iodi, nexus, iodi_driver, iodi_devclass, 0, 0); 322