iodi.c revision 211994
1/*- 2 * Copyright (c) 2003-2009 RMI Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of RMI Corporation, nor the names of its contributors, 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * RMI_BSD 30 */ 31 32#include <sys/cdefs.h> 33__FBSDID("$FreeBSD: head/sys/mips/rmi/iodi.c 211994 2010-08-30 13:05:21Z jchandra $"); 34 35#define __RMAN_RESOURCE_VISIBLE 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/bus.h> 39#include <sys/kernel.h> 40#include <sys/lock.h> 41#include <sys/mutex.h> 42#include <sys/reboot.h> 43#include <sys/rman.h> 44#include <sys/types.h> 45#include <sys/malloc.h> 46#include <sys/bus.h> 47#include <sys/interrupt.h> 48#include <sys/module.h> 49 50#include <machine/cpu.h> 51#include <machine/bus.h> 52#include <machine/param.h> 53#include <machine/intr_machdep.h> 54#include <machine/clock.h> /* for DELAY */ 55#include <machine/resource.h> 56 57#include <mips/rmi/board.h> 58#include <mips/rmi/pic.h> 59#include <mips/rmi/interrupt.h> 60#include <mips/rmi/msgring.h> 61#include <mips/rmi/iomap.h> 62#include <mips/rmi/rmi_mips_exts.h> 63 64#include <mips/rmi/dev/xlr/atx_cpld.h> 65#include <mips/rmi/dev/xlr/xgmac_mdio.h> 66 67extern bus_space_tag_t uart_bus_space_mem; 68 69static struct resource * 70iodi_alloc_resource(device_t, device_t, int, int *, 71 u_long, u_long, u_long, u_int); 72 73static int 74iodi_activate_resource(device_t, device_t, int, int, 75 struct resource *); 76static int 77iodi_setup_intr(device_t, device_t, struct resource *, int, 78 driver_filter_t *, driver_intr_t *, void *, void **); 79 80struct iodi_softc *iodi_softc; /* There can be only one. */ 81 82/* 83 * We will manage the Flash/PCMCIA devices in IODI for now. 84 * The NOR flash, Compact flash etc. which can be connected on 85 * various chip selects on the peripheral IO, should have a 86 * separate bus later. 87 */ 88static void 89bridge_pcmcia_ack(int irq) 90{ 91 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_FLASH_OFFSET); 92 93 xlr_write_reg(mmio, 0x60, 0xffffffff); 94} 95 96static int 97iodi_setup_intr(device_t dev, device_t child, 98 struct resource *ires, int flags, driver_filter_t * filt, 99 driver_intr_t *intr, void *arg, void **cookiep) 100{ 101 const char *name = device_get_name(child); 102 103 if (strcmp(name, "uart") == 0) { 104 /* FIXME uart 1? */ 105 cpu_establish_hardintr("uart", filt, intr, arg, 106 PIC_UART_0_IRQ, flags, cookiep); 107 pic_setup_intr(PIC_IRT_UART_0_INDEX, PIC_UART_0_IRQ, 0x1, 0); 108 } else if (strcmp(name, "rge") == 0 || strcmp(name, "nlge") == 0) { 109 int irq; 110 111 /* This is a hack to pass in the irq */ 112 irq = (intptr_t)ires->__r_i; 113 cpu_establish_hardintr("rge", filt, intr, arg, irq, flags, 114 cookiep); 115 pic_setup_intr(irq - PIC_IRQ_BASE, irq, 0x1, 0); 116 } else if (strcmp(name, "ehci") == 0) { 117 cpu_establish_hardintr("ehci", filt, intr, arg, PIC_USB_IRQ, flags, 118 cookiep); 119 pic_setup_intr(PIC_USB_IRQ - PIC_IRQ_BASE, PIC_USB_IRQ, 0x1, 0); 120 } else if (strcmp(name, "ata") == 0) { 121 xlr_establish_intr("ata", filt, intr, arg, PIC_PCMCIA_IRQ, flags, 122 cookiep, bridge_pcmcia_ack); 123 pic_setup_intr(PIC_PCMCIA_IRQ - PIC_IRQ_BASE, PIC_PCMCIA_IRQ, 0x1, 0); 124 } 125 return (0); 126} 127 128static struct resource * 129iodi_alloc_resource(device_t bus, device_t child, int type, int *rid, 130 u_long start, u_long end, u_long count, u_int flags) 131{ 132 struct resource *res = malloc(sizeof(*res), M_DEVBUF, M_WAITOK); 133 int unit; 134 135#ifdef DEBUG 136 switch (type) { 137 case SYS_RES_IRQ: 138 device_printf(bus, "IRQ resource - for %s %lx-%lx\n", 139 device_get_nameunit(child), start, end); 140 break; 141 142 case SYS_RES_IOPORT: 143 device_printf(bus, "IOPORT resource - for %s %lx-%lx\n", 144 device_get_nameunit(child), start, end); 145 break; 146 147 case SYS_RES_MEMORY: 148 device_printf(bus, "MEMORY resource - for %s %lx-%lx\n", 149 device_get_nameunit(child), start, end); 150 break; 151 } 152#endif 153 154 if (strcmp(device_get_name(child), "uart") == 0) { 155 if ((unit = device_get_unit(child)) == 0) { /* uart 0 */ 156 res->r_bushandle = (xlr_io_base + XLR_IO_UART_0_OFFSET); 157 } else if (unit == 1) { 158 res->r_bushandle = (xlr_io_base + XLR_IO_UART_1_OFFSET); 159 } else 160 printf("%s: Unknown uart unit\n", __FUNCTION__); 161 162 res->r_bustag = uart_bus_space_mem; 163 } else if (strcmp(device_get_name(child), "ehci") == 0) { 164 res->r_bushandle = MIPS_PHYS_TO_KSEG1(0x1ef24000); 165 res->r_bustag = rmi_pci_bus_space; 166 } else if (strcmp(device_get_name(child), "cfi") == 0) { 167 res->r_bushandle = MIPS_PHYS_TO_KSEG1(0x1c000000); 168 res->r_bustag = 0; 169 } else if (strcmp(device_get_name(child), "ata") == 0) { 170 res->r_bushandle = MIPS_PHYS_TO_KSEG1(0x1d000000); 171 res->r_bustag = rmi_pci_bus_space; /* byte swapping (not really PCI) */ 172 } 173 /* res->r_start = *rid; */ 174 return (res); 175} 176 177static int 178iodi_activate_resource(device_t bus, device_t child, int type, int rid, 179 struct resource *r) 180{ 181 return (0); 182} 183 184/* prototypes */ 185static int iodi_probe(device_t); 186static int iodi_attach(device_t); 187static int iodi_detach(device_t); 188static void iodi_identify(driver_t *, device_t); 189 190int 191iodi_probe(device_t dev) 192{ 193 return 0; 194} 195 196void 197iodi_identify(driver_t * driver, device_t parent) 198{ 199 200 BUS_ADD_CHILD(parent, 0, "iodi", 0); 201} 202 203int 204iodi_attach(device_t dev) 205{ 206 device_t tmpd; 207 int i; 208 209 /* 210 * Attach each devices 211 */ 212 device_add_child(dev, "uart", 0); 213 device_add_child(dev, "xlr_i2c", 0); 214 device_add_child(dev, "pcib", 0); 215 216 if (xlr_board_info.usb) 217 device_add_child(dev, "ehci", 0); 218 219 if (xlr_board_info.cfi) 220 device_add_child(dev, "cfi", 0); 221 222 if (xlr_board_info.ata) 223 device_add_child(dev, "ata", 0); 224 225 if (xlr_board_info.gmac_block[0].enabled) { 226 tmpd = device_add_child(dev, "rge", 0); 227 device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]); 228 229 tmpd = device_add_child(dev, "rge", 1); 230 device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]); 231 232 tmpd = device_add_child(dev, "rge", 2); 233 device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]); 234 235 tmpd = device_add_child(dev, "rge", 3); 236 device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]); 237 } 238 if (xlr_board_info.gmac_block[1].enabled) { 239 if (xlr_board_info.gmac_block[1].type == XLR_GMAC) { 240 tmpd = device_add_child(dev, "rge", 4); 241 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]); 242 243 tmpd = device_add_child(dev, "rge", 5); 244 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]); 245 246 if (xlr_board_info.gmac_block[1].enabled & 0x4) { 247 tmpd = device_add_child(dev, "rge", 6); 248 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]); 249 } 250 251 if (xlr_board_info.gmac_block[1].enabled & 0x8) { 252 tmpd = device_add_child(dev, "rge", 7); 253 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]); 254 } 255 } else if (xlr_board_info.gmac_block[1].type == XLR_XGMAC) { 256#if 0 /* XGMAC not yet */ 257 tmpd = device_add_child(dev, "rge", 4); 258 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]); 259 260 tmpd = device_add_child(dev, "rge", 5); 261 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]); 262#endif 263 } else 264 device_printf(dev, "Unknown type of gmac 1\n"); 265 } 266 267 /* This is to add the new GMAC driver. The above adds the old driver, 268 which has been retained for now as the new driver is stabilized. 269 The new driver is enabled with "option nlge". Make sure that only 270 one of rge or nlge is enabled in the conf file. */ 271 for (i = 0; i < 3; i++) { 272 if (xlr_board_info.gmac_block[i].enabled == 0) 273 continue; 274 tmpd = device_add_child(dev, "nlna", i); 275 device_set_ivars(tmpd, &xlr_board_info.gmac_block[i]); 276 } 277 bus_generic_probe(dev); 278 bus_generic_attach(dev); 279 return 0; 280} 281 282int 283iodi_detach(device_t dev) 284{ 285 device_t nlna_dev; 286 int error, i, ret; 287 288 error = 0; 289 ret = 0; 290 for (i = 0; i < 3; i++) { 291 nlna_dev = device_find_child(dev, "nlna", i); 292 if (nlna_dev != NULL) 293 error = bus_generic_detach(nlna_dev); 294 if (error) 295 ret = error; 296 } 297 return ret; 298} 299 300static device_method_t iodi_methods[] = { 301 DEVMETHOD(device_probe, iodi_probe), 302 DEVMETHOD(device_attach, iodi_attach), 303 DEVMETHOD(device_detach, iodi_detach), 304 DEVMETHOD(device_identify, iodi_identify), 305 DEVMETHOD(bus_alloc_resource, iodi_alloc_resource), 306 DEVMETHOD(bus_activate_resource, iodi_activate_resource), 307 DEVMETHOD(bus_setup_intr, iodi_setup_intr), 308 {0, 0}, 309}; 310 311static driver_t iodi_driver = { 312 "iodi", 313 iodi_methods, 314 1 /* no softc */ 315}; 316static devclass_t iodi_devclass; 317 318DRIVER_MODULE(iodi, nexus, iodi_driver, iodi_devclass, 0, 0); 319