]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/mips/rmi/iodi.c
I2C drivers for XLR/XLS processors.
[FreeBSD/FreeBSD.git] / 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/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
67 extern bus_space_tag_t uart_bus_space_mem;
68
69 static struct resource *
70 iodi_alloc_resource(device_t, device_t, int, int *,
71     u_long, u_long, u_long, u_int);
72
73 static int
74 iodi_activate_resource(device_t, device_t, int, int,
75     struct resource *);
76 static int
77 iodi_setup_intr(device_t, device_t, struct resource *, int,
78     driver_filter_t *, driver_intr_t *, void *, void **);
79
80 struct 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  */
88 static void
89 bridge_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
96 static int
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)
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, 1);
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, 1);
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, 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);
124         }
125         return (0);
126 }
127
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)
131 {
132         struct resource *res = malloc(sizeof(*res), M_DEVBUF, M_WAITOK);
133         const char *name = device_get_name(child);
134         int unit;
135
136 #ifdef DEBUG
137         switch (type) {
138         case SYS_RES_IRQ:
139                 device_printf(bus, "IRQ resource - for %s %lx-%lx\n",
140                     device_get_nameunit(child), start, end);
141                 break;
142
143         case SYS_RES_IOPORT:
144                 device_printf(bus, "IOPORT resource - for %s %lx-%lx\n",
145                     device_get_nameunit(child), start, end);
146                 break;
147
148         case SYS_RES_MEMORY:
149                 device_printf(bus, "MEMORY resource - for %s %lx-%lx\n",
150                     device_get_nameunit(child), start, end);
151                 break;
152         }
153 #endif
154
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);
160                 } else
161                         printf("%s: Unknown uart unit\n", __FUNCTION__);
162
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);
169                 res->r_bustag = 0;
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) */
173         }
174         /* res->r_start = *rid; */
175         return (res);
176 }
177
178 static int
179 iodi_activate_resource(device_t bus, device_t child, int type, int rid,
180     struct resource *r)
181 {
182         return (0);
183 }
184
185 /* prototypes */
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);
190
191 int
192 iodi_probe(device_t dev)
193 {
194         return 0;
195 }
196
197 void
198 iodi_identify(driver_t * driver, device_t parent)
199 {
200
201         BUS_ADD_CHILD(parent, 0, "iodi", 0);
202 }
203
204 int
205 iodi_attach(device_t dev)
206 {
207         device_t tmpd;
208         int i;
209
210         /*
211          * Attach each devices
212          */
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);
218
219         if (xlr_board_info.usb)
220                 device_add_child(dev, "ehci", 0);
221
222         if (xlr_board_info.cfi)
223                 device_add_child(dev, "cfi", 0);
224
225         if (xlr_board_info.ata)
226                 device_add_child(dev, "ata", 0);
227
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]);
231
232                 tmpd = device_add_child(dev, "rge", 1);
233                 device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
234
235                 tmpd = device_add_child(dev, "rge", 2);
236                 device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
237
238                 tmpd = device_add_child(dev, "rge", 3);
239                 device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
240         }
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]);
245
246                         tmpd = device_add_child(dev, "rge", 5);
247                         device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
248
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]);
252                         }
253
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]);
257                         }
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]);
262
263                         tmpd = device_add_child(dev, "rge", 5);
264                         device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
265 #endif
266                 } else 
267                         device_printf(dev, "Unknown type of gmac 1\n"); 
268         }
269
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)
276                         continue;
277                 tmpd = device_add_child(dev, "nlna", i);
278                 device_set_ivars(tmpd, &xlr_board_info.gmac_block[i]);
279         }
280         bus_generic_probe(dev);
281         bus_generic_attach(dev);
282         return 0;
283 }
284
285 int
286 iodi_detach(device_t dev)
287 {
288         device_t nlna_dev;
289         int error, i, ret;
290
291         error = 0;
292         ret = 0;
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);
297                 if (error)
298                         ret = error;
299         }
300         return ret;
301 }
302
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),
312         {0, 0},
313 };
314
315 static driver_t iodi_driver = {
316         "iodi",
317         iodi_methods,
318         1                       /* no softc */
319 };
320 static devclass_t iodi_devclass;
321
322 DRIVER_MODULE(iodi, nexus, iodi_driver, iodi_devclass, 0, 0);