2 * Copyright (c) 2003-2009 RMI Corporation
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 #define __RMAN_RESOURCE_VISIBLE
36 #include <sys/param.h>
37 #include <sys/systm.h>
39 #include <sys/kernel.h>
41 #include <sys/mutex.h>
42 #include <sys/reboot.h>
44 #include <sys/types.h>
45 #include <sys/malloc.h>
47 #include <sys/interrupt.h>
48 #include <sys/module.h>
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>
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>
64 #include <mips/rmi/dev/xlr/atx_cpld.h>
65 #include <mips/rmi/dev/xlr/xgmac_mdio.h>
67 extern bus_space_tag_t uart_bus_space_mem;
69 static struct resource *
70 iodi_alloc_resource(device_t, device_t, int, int *,
71 u_long, u_long, u_long, u_int);
74 iodi_activate_resource(device_t, device_t, int, int,
77 iodi_setup_intr(device_t, device_t, struct resource *, int,
78 driver_filter_t *, driver_intr_t *, void *, void **);
80 struct iodi_softc *iodi_softc; /* There can be only one. */
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
89 bridge_pcmcia_ack(int irq)
91 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_FLASH_OFFSET);
93 xlr_write_reg(mmio, 0x60, 0xffffffff);
97 iodi_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)
101 const char *name = device_get_name(child);
103 if (strcmp(name, "uart") == 0) {
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, 1);
108 } else if (strcmp(name, "rge") == 0 || strcmp(name, "nlge") == 0) {
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,
115 pic_setup_intr(irq - PIC_IRQ_BASE, irq, 0x1, 1);
116 } else if (strcmp(name, "ehci") == 0) {
117 cpu_establish_hardintr("ehci", filt, intr, arg, PIC_USB_IRQ, flags,
119 pic_setup_intr(PIC_USB_IRQ - PIC_IRQ_BASE, PIC_USB_IRQ, 0x1, 1);
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, 1);
128 static struct resource *
129 iodi_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)
132 struct resource *res = malloc(sizeof(*res), M_DEVBUF, M_WAITOK);
133 const char *name = device_get_name(child);
139 device_printf(bus, "IRQ resource - for %s %lx-%lx\n",
140 device_get_nameunit(child), start, end);
144 device_printf(bus, "IOPORT resource - for %s %lx-%lx\n",
145 device_get_nameunit(child), start, end);
149 device_printf(bus, "MEMORY resource - for %s %lx-%lx\n",
150 device_get_nameunit(child), start, end);
155 if (strcmp(name, "uart") == 0) {
156 if ((unit = device_get_unit(child)) == 0) { /* uart 0 */
157 res->r_bushandle = (xlr_io_base + XLR_IO_UART_0_OFFSET);
158 } else if (unit == 1) {
159 res->r_bushandle = (xlr_io_base + XLR_IO_UART_1_OFFSET);
161 printf("%s: Unknown uart unit\n", __FUNCTION__);
163 res->r_bustag = uart_bus_space_mem;
164 } else if (strcmp(name, "ehci") == 0) {
165 res->r_bushandle = MIPS_PHYS_TO_KSEG1(0x1ef24000);
166 res->r_bustag = rmi_pci_bus_space;
167 } else if (strcmp(name, "cfi") == 0) {
168 res->r_bushandle = MIPS_PHYS_TO_KSEG1(0x1c000000);
170 } else if (strcmp(name, "ata") == 0) {
171 res->r_bushandle = MIPS_PHYS_TO_KSEG1(0x1d000000);
172 res->r_bustag = rmi_pci_bus_space; /* byte swapping (not really PCI) */
174 /* res->r_start = *rid; */
179 iodi_activate_resource(device_t bus, device_t child, int type, int rid,
186 static int iodi_probe(device_t);
187 static int iodi_attach(device_t);
188 static int iodi_detach(device_t);
189 static void iodi_identify(driver_t *, device_t);
192 iodi_probe(device_t dev)
198 iodi_identify(driver_t * driver, device_t parent)
201 BUS_ADD_CHILD(parent, 0, "iodi", 0);
205 iodi_attach(device_t dev)
211 * Attach each devices
213 device_add_child(dev, "uart", 0);
214 device_add_child(dev, "xlr_i2c", 0);
215 device_add_child(dev, "xlr_i2c", 1);
216 device_add_child(dev, "pcib", 0);
217 device_add_child(dev, "rmisec", -1);
219 if (xlr_board_info.usb)
220 device_add_child(dev, "ehci", 0);
222 if (xlr_board_info.cfi)
223 device_add_child(dev, "cfi", 0);
225 if (xlr_board_info.ata)
226 device_add_child(dev, "ata", 0);
228 if (xlr_board_info.gmac_block[0].enabled) {
229 tmpd = device_add_child(dev, "rge", 0);
230 device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
232 tmpd = device_add_child(dev, "rge", 1);
233 device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
235 tmpd = device_add_child(dev, "rge", 2);
236 device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
238 tmpd = device_add_child(dev, "rge", 3);
239 device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
241 if (xlr_board_info.gmac_block[1].enabled) {
242 if (xlr_board_info.gmac_block[1].type == XLR_GMAC) {
243 tmpd = device_add_child(dev, "rge", 4);
244 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
246 tmpd = device_add_child(dev, "rge", 5);
247 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
249 if (xlr_board_info.gmac_block[1].enabled & 0x4) {
250 tmpd = device_add_child(dev, "rge", 6);
251 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
254 if (xlr_board_info.gmac_block[1].enabled & 0x8) {
255 tmpd = device_add_child(dev, "rge", 7);
256 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
258 } else if (xlr_board_info.gmac_block[1].type == XLR_XGMAC) {
259 #if 0 /* XGMAC not yet */
260 tmpd = device_add_child(dev, "rge", 4);
261 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
263 tmpd = device_add_child(dev, "rge", 5);
264 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
267 device_printf(dev, "Unknown type of gmac 1\n");
270 /* This is to add the new GMAC driver. The above adds the old driver,
271 which has been retained for now as the new driver is stabilized.
272 The new driver is enabled with "option nlge". Make sure that only
273 one of rge or nlge is enabled in the conf file. */
274 for (i = 0; i < 3; i++) {
275 if (xlr_board_info.gmac_block[i].enabled == 0)
277 tmpd = device_add_child(dev, "nlna", i);
278 device_set_ivars(tmpd, &xlr_board_info.gmac_block[i]);
280 bus_generic_probe(dev);
281 bus_generic_attach(dev);
286 iodi_detach(device_t dev)
293 for (i = 0; i < 3; i++) {
294 nlna_dev = device_find_child(dev, "nlna", i);
295 if (nlna_dev != NULL)
296 error = bus_generic_detach(nlna_dev);
303 static device_method_t iodi_methods[] = {
304 DEVMETHOD(device_probe, iodi_probe),
305 DEVMETHOD(device_attach, iodi_attach),
306 DEVMETHOD(device_detach, iodi_detach),
307 DEVMETHOD(device_identify, iodi_identify),
308 DEVMETHOD(bus_alloc_resource, iodi_alloc_resource),
309 DEVMETHOD(bus_activate_resource, iodi_activate_resource),
310 DEVMETHOD(bus_add_child, bus_generic_add_child),
311 DEVMETHOD(bus_setup_intr, iodi_setup_intr),
315 static driver_t iodi_driver = {
320 static devclass_t iodi_devclass;
322 DRIVER_MODULE(iodi, nexus, iodi_driver, iodi_devclass, 0, 0);