FreeBSD/Linux Kernel Cross Reference
sys/mips/rmi/iodi.c
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$");
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/interrupt.h>
47 #include <sys/module.h>
48
49 #include <machine/cpu.h>
50 #include <machine/bus.h>
51 #include <machine/intr_machdep.h>
52 #include <machine/clock.h> /* for DELAY */
53 #include <machine/resource.h>
54
55 #include <mips/rmi/board.h>
56 #include <mips/rmi/pic.h>
57 #include <mips/rmi/interrupt.h>
58 #include <mips/rmi/msgring.h>
59 #include <mips/rmi/iomap.h>
60 #include <mips/rmi/rmi_mips_exts.h>
61
62 #include <mips/rmi/dev/xlr/atx_cpld.h>
63 #include <mips/rmi/dev/xlr/xgmac_mdio.h>
64
65 extern bus_space_tag_t uart_bus_space_mem;
66
67 static struct resource *
68 iodi_alloc_resource(device_t, device_t, int, int *,
69 rman_res_t, rman_res_t, rman_res_t, u_int);
70
71 static int
72 iodi_activate_resource(device_t, device_t, int, int,
73 struct resource *);
74 static int
75 iodi_setup_intr(device_t, device_t, struct resource *, int,
76 driver_filter_t *, driver_intr_t *, void *, void **);
77
78 struct iodi_softc *iodi_softc; /* There can be only one. */
79
80 /*
81 * We will manage the Flash/PCMCIA devices in IODI for now.
82 * The NOR flash, Compact flash etc. which can be connected on
83 * various chip selects on the peripheral IO, should have a
84 * separate bus later.
85 */
86 static void
87 bridge_pcmcia_ack(int irq)
88 {
89 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_FLASH_OFFSET);
90
91 xlr_write_reg(mmio, 0x60, 0xffffffff);
92 }
93
94 static int
95 iodi_setup_intr(device_t dev, device_t child,
96 struct resource *ires, int flags, driver_filter_t *filt,
97 driver_intr_t *intr, void *arg, void **cookiep)
98 {
99 const char *name = device_get_name(child);
100
101 if (strcmp(name, "uart") == 0) {
102 /* FIXME uart 1? */
103 cpu_establish_hardintr("uart", filt, intr, arg,
104 PIC_UART_0_IRQ, flags, cookiep);
105 pic_setup_intr(PIC_IRT_UART_0_INDEX, PIC_UART_0_IRQ, 0x1, 1);
106 } else if (strcmp(name, "nlge") == 0) {
107 int irq;
108
109 /* This is a hack to pass in the irq */
110 irq = (intptr_t)ires->__r_i;
111 cpu_establish_hardintr("nlge", filt, intr, arg, irq, flags,
112 cookiep);
113 pic_setup_intr(irq - PIC_IRQ_BASE, irq, 0x1, 1);
114 } else if (strcmp(name, "ehci") == 0) {
115 cpu_establish_hardintr("ehci", filt, intr, arg, PIC_USB_IRQ, flags,
116 cookiep);
117 pic_setup_intr(PIC_USB_IRQ - PIC_IRQ_BASE, PIC_USB_IRQ, 0x1, 1);
118 } else if (strcmp(name, "ata") == 0) {
119 xlr_establish_intr("ata", filt, intr, arg, PIC_PCMCIA_IRQ, flags,
120 cookiep, bridge_pcmcia_ack);
121 pic_setup_intr(PIC_PCMCIA_IRQ - PIC_IRQ_BASE, PIC_PCMCIA_IRQ, 0x1, 1);
122 }
123 return (0);
124 }
125
126 static struct resource *
127 iodi_alloc_resource(device_t bus, device_t child, int type, int *rid,
128 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
129 {
130 struct resource *res = malloc(sizeof(*res), M_DEVBUF, M_WAITOK);
131 const char *name = device_get_name(child);
132 int unit;
133
134 #ifdef DEBUG
135 switch (type) {
136 case SYS_RES_IRQ:
137 device_printf(bus, "IRQ resource - for %s %jx-%jx\n",
138 device_get_nameunit(child), start, end);
139 break;
140
141 case SYS_RES_IOPORT:
142 device_printf(bus, "IOPORT resource - for %s %jx-%jx\n",
143 device_get_nameunit(child), start, end);
144 break;
145
146 case SYS_RES_MEMORY:
147 device_printf(bus, "MEMORY resource - for %s %jx-%jx\n",
148 device_get_nameunit(child), start, end);
149 break;
150 }
151 #endif
152
153 if (strcmp(name, "uart") == 0) {
154 if ((unit = device_get_unit(child)) == 0) { /* uart 0 */
155 res->r_bushandle = (xlr_io_base + XLR_IO_UART_0_OFFSET);
156 } else if (unit == 1) {
157 res->r_bushandle = (xlr_io_base + XLR_IO_UART_1_OFFSET);
158 } else
159 printf("%s: Unknown uart unit\n", __FUNCTION__);
160
161 res->r_bustag = uart_bus_space_mem;
162 } else if (strcmp(name, "ehci") == 0) {
163 res->r_bushandle = MIPS_PHYS_TO_KSEG1(0x1ef24000);
164 res->r_bustag = rmi_pci_bus_space;
165 } else if (strcmp(name, "cfi") == 0) {
166 res->r_bushandle = MIPS_PHYS_TO_KSEG1(0x1c000000);
167 res->r_bustag = 0;
168 } else if (strcmp(name, "ata") == 0) {
169 res->r_bushandle = MIPS_PHYS_TO_KSEG1(0x1d000000);
170 res->r_bustag = rmi_pci_bus_space; /* byte swapping (not really PCI) */
171 }
172 /* res->r_start = *rid; */
173 return (res);
174 }
175
176 static int
177 iodi_activate_resource(device_t bus, device_t child, int type, int rid,
178 struct resource *r)
179 {
180 return (0);
181 }
182
183 /* prototypes */
184 static int iodi_probe(device_t);
185 static int iodi_attach(device_t);
186 static int iodi_detach(device_t);
187 static void iodi_identify(driver_t *, device_t);
188
189 int
190 iodi_probe(device_t dev)
191 {
192 return (BUS_PROBE_NOWILDCARD);
193 }
194
195 void
196 iodi_identify(driver_t * driver, device_t parent)
197 {
198
199 BUS_ADD_CHILD(parent, 0, "iodi", 0);
200 }
201
202 int
203 iodi_attach(device_t dev)
204 {
205 device_t tmpd;
206 int i;
207
208 /*
209 * Attach each devices
210 */
211 device_add_child(dev, "uart", 0);
212 device_add_child(dev, "xlr_i2c", 0);
213 device_add_child(dev, "xlr_i2c", 1);
214 device_add_child(dev, "pcib", 0);
215 device_add_child(dev, "rmisec", -1);
216
217 if (xlr_board_info.usb)
218 device_add_child(dev, "ehci", 0);
219
220 if (xlr_board_info.cfi)
221 device_add_child(dev, "cfi", 0);
222
223 if (xlr_board_info.ata)
224 device_add_child(dev, "ata", 0);
225
226 for (i = 0; i < 3; i++) {
227 if (xlr_board_info.gmac_block[i].enabled == 0)
228 continue;
229 tmpd = device_add_child(dev, "nlna", i);
230 device_set_ivars(tmpd, &xlr_board_info.gmac_block[i]);
231 }
232
233 bus_generic_probe(dev);
234 bus_generic_attach(dev);
235 return 0;
236 }
237
238 int
239 iodi_detach(device_t dev)
240 {
241 device_t nlna_dev;
242 int error, i, ret;
243
244 error = 0;
245 ret = 0;
246 for (i = 0; i < 3; i++) {
247 nlna_dev = device_find_child(dev, "nlna", i);
248 if (nlna_dev != NULL)
249 error = bus_generic_detach(nlna_dev);
250 if (error)
251 ret = error;
252 }
253 return ret;
254 }
255
256 static device_method_t iodi_methods[] = {
257 DEVMETHOD(device_probe, iodi_probe),
258 DEVMETHOD(device_attach, iodi_attach),
259 DEVMETHOD(device_detach, iodi_detach),
260 DEVMETHOD(device_identify, iodi_identify),
261 DEVMETHOD(bus_alloc_resource, iodi_alloc_resource),
262 DEVMETHOD(bus_activate_resource, iodi_activate_resource),
263 DEVMETHOD(bus_add_child, bus_generic_add_child),
264 DEVMETHOD(bus_setup_intr, iodi_setup_intr),
265 {0, 0},
266 };
267
268 static driver_t iodi_driver = {
269 "iodi",
270 iodi_methods,
271 1 /* no softc */
272 };
273 static devclass_t iodi_devclass;
274
275 DRIVER_MODULE(iodi, nexus, iodi_driver, iodi_devclass, 0, 0);
Cache object: 90e26454fb31436dd997338de94fc2ec
|