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>
46 #include <sys/interrupt.h>
47 #include <sys/module.h>
49 #include <machine/cpu.h>
50 #include <machine/bus.h>
51 #include <machine/param.h>
52 #include <machine/intr_machdep.h>
53 #include <machine/clock.h> /* for DELAY */
54 #include <machine/resource.h>
56 #include <mips/rmi/board.h>
57 #include <mips/rmi/pic.h>
58 #include <mips/rmi/interrupt.h>
59 #include <mips/rmi/msgring.h>
60 #include <mips/rmi/iomap.h>
61 #include <mips/rmi/rmi_mips_exts.h>
63 #include <mips/rmi/dev/xlr/atx_cpld.h>
64 #include <mips/rmi/dev/xlr/xgmac_mdio.h>
66 extern bus_space_tag_t uart_bus_space_mem;
68 static struct resource *
69 iodi_alloc_resource(device_t, device_t, int, int *,
70 u_long, u_long, u_long, u_int);
73 iodi_activate_resource(device_t, device_t, int, int,
76 iodi_setup_intr(device_t, device_t, struct resource *, int,
77 driver_filter_t *, driver_intr_t *, void *, void **);
79 struct iodi_softc *iodi_softc; /* There can be only one. */
82 * We will manage the Flash/PCMCIA devices in IODI for now.
83 * The NOR flash, Compact flash etc. which can be connected on
84 * various chip selects on the peripheral IO, should have a
88 bridge_pcmcia_ack(int irq)
90 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_FLASH_OFFSET);
92 xlr_write_reg(mmio, 0x60, 0xffffffff);
96 iodi_setup_intr(device_t dev, device_t child,
97 struct resource *ires, int flags, driver_filter_t *filt,
98 driver_intr_t *intr, void *arg, void **cookiep)
100 const char *name = device_get_name(child);
102 if (strcmp(name, "uart") == 0) {
104 cpu_establish_hardintr("uart", filt, intr, arg,
105 PIC_UART_0_IRQ, flags, cookiep);
106 pic_setup_intr(PIC_IRT_UART_0_INDEX, PIC_UART_0_IRQ, 0x1, 1);
107 } else if (strcmp(name, "rge") == 0 || strcmp(name, "nlge") == 0) {
110 /* This is a hack to pass in the irq */
111 irq = (intptr_t)ires->__r_i;
112 cpu_establish_hardintr("rge", filt, intr, arg, irq, flags,
114 pic_setup_intr(irq - PIC_IRQ_BASE, irq, 0x1, 1);
115 } else if (strcmp(name, "ehci") == 0) {
116 cpu_establish_hardintr("ehci", filt, intr, arg, PIC_USB_IRQ, flags,
118 pic_setup_intr(PIC_USB_IRQ - PIC_IRQ_BASE, PIC_USB_IRQ, 0x1, 1);
119 } else if (strcmp(name, "ata") == 0) {
120 xlr_establish_intr("ata", filt, intr, arg, PIC_PCMCIA_IRQ, flags,
121 cookiep, bridge_pcmcia_ack);
122 pic_setup_intr(PIC_PCMCIA_IRQ - PIC_IRQ_BASE, PIC_PCMCIA_IRQ, 0x1, 1);
127 static struct resource *
128 iodi_alloc_resource(device_t bus, device_t child, int type, int *rid,
129 u_long start, u_long end, u_long count, u_int flags)
131 struct resource *res = malloc(sizeof(*res), M_DEVBUF, M_WAITOK);
132 const char *name = device_get_name(child);
138 device_printf(bus, "IRQ resource - for %s %lx-%lx\n",
139 device_get_nameunit(child), start, end);
143 device_printf(bus, "IOPORT resource - for %s %lx-%lx\n",
144 device_get_nameunit(child), start, end);
148 device_printf(bus, "MEMORY resource - for %s %lx-%lx\n",
149 device_get_nameunit(child), start, end);
154 if (strcmp(name, "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);
160 printf("%s: Unknown uart unit\n", __FUNCTION__);
162 res->r_bustag = uart_bus_space_mem;
163 } else if (strcmp(name, "ehci") == 0) {
164 res->r_bushandle = MIPS_PHYS_TO_KSEG1(0x1ef24000);
165 res->r_bustag = rmi_pci_bus_space;
166 } else if (strcmp(name, "cfi") == 0) {
167 res->r_bushandle = MIPS_PHYS_TO_KSEG1(0x1c000000);
169 } else if (strcmp(name, "ata") == 0) {
170 res->r_bushandle = MIPS_PHYS_TO_KSEG1(0x1d000000);
171 res->r_bustag = rmi_pci_bus_space; /* byte swapping (not really PCI) */
173 /* res->r_start = *rid; */
178 iodi_activate_resource(device_t bus, device_t child, int type, int rid,
185 static int iodi_probe(device_t);
186 static int iodi_attach(device_t);
187 static int iodi_detach(device_t);
188 static void iodi_identify(driver_t *, device_t);
191 iodi_probe(device_t dev)
197 iodi_identify(driver_t * driver, device_t parent)
200 BUS_ADD_CHILD(parent, 0, "iodi", 0);
204 iodi_attach(device_t dev)
210 * Attach each devices
212 device_add_child(dev, "uart", 0);
213 device_add_child(dev, "xlr_i2c", 0);
214 device_add_child(dev, "xlr_i2c", 1);
215 device_add_child(dev, "pcib", 0);
216 device_add_child(dev, "rmisec", -1);
218 if (xlr_board_info.usb)
219 device_add_child(dev, "ehci", 0);
221 if (xlr_board_info.cfi)
222 device_add_child(dev, "cfi", 0);
224 if (xlr_board_info.ata)
225 device_add_child(dev, "ata", 0);
227 if (xlr_board_info.gmac_block[0].enabled) {
228 tmpd = device_add_child(dev, "rge", 0);
229 device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
231 tmpd = device_add_child(dev, "rge", 1);
232 device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
234 tmpd = device_add_child(dev, "rge", 2);
235 device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
237 tmpd = device_add_child(dev, "rge", 3);
238 device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
240 if (xlr_board_info.gmac_block[1].enabled) {
241 if (xlr_board_info.gmac_block[1].type == XLR_GMAC) {
242 tmpd = device_add_child(dev, "rge", 4);
243 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
245 tmpd = device_add_child(dev, "rge", 5);
246 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
248 if (xlr_board_info.gmac_block[1].enabled & 0x4) {
249 tmpd = device_add_child(dev, "rge", 6);
250 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
253 if (xlr_board_info.gmac_block[1].enabled & 0x8) {
254 tmpd = device_add_child(dev, "rge", 7);
255 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
257 } else if (xlr_board_info.gmac_block[1].type == XLR_XGMAC) {
258 #if 0 /* XGMAC not yet */
259 tmpd = device_add_child(dev, "rge", 4);
260 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
262 tmpd = device_add_child(dev, "rge", 5);
263 device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
266 device_printf(dev, "Unknown type of gmac 1\n");
269 /* This is to add the new GMAC driver. The above adds the old driver,
270 which has been retained for now as the new driver is stabilized.
271 The new driver is enabled with "option nlge". Make sure that only
272 one of rge or nlge is enabled in the conf file. */
273 for (i = 0; i < 3; i++) {
274 if (xlr_board_info.gmac_block[i].enabled == 0)
276 tmpd = device_add_child(dev, "nlna", i);
277 device_set_ivars(tmpd, &xlr_board_info.gmac_block[i]);
279 bus_generic_probe(dev);
280 bus_generic_attach(dev);
285 iodi_detach(device_t dev)
292 for (i = 0; i < 3; i++) {
293 nlna_dev = device_find_child(dev, "nlna", i);
294 if (nlna_dev != NULL)
295 error = bus_generic_detach(nlna_dev);
302 static device_method_t iodi_methods[] = {
303 DEVMETHOD(device_probe, iodi_probe),
304 DEVMETHOD(device_attach, iodi_attach),
305 DEVMETHOD(device_detach, iodi_detach),
306 DEVMETHOD(device_identify, iodi_identify),
307 DEVMETHOD(bus_alloc_resource, iodi_alloc_resource),
308 DEVMETHOD(bus_activate_resource, iodi_activate_resource),
309 DEVMETHOD(bus_add_child, bus_generic_add_child),
310 DEVMETHOD(bus_setup_intr, iodi_setup_intr),
314 static driver_t iodi_driver = {
319 static devclass_t iodi_devclass;
321 DRIVER_MODULE(iodi, nexus, iodi_driver, iodi_devclass, 0, 0);