]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/dev/terasic/mtl/terasic_mtl_nexus.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / dev / terasic / mtl / terasic_mtl_nexus.c
1 /*-
2  * Copyright (c) 2012 Robert N. M. Watson
3  * All rights reserved.
4  *
5  * This software was developed by SRI International and the University of
6  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7  * ("CTSRD"), as part of the DARPA CRASH research programme.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/param.h>
35 #include <sys/bus.h>
36 #include <sys/condvar.h>
37 #include <sys/conf.h>
38 #include <sys/consio.h>                         /* struct vt_mode */
39 #include <sys/fbio.h>                           /* video_adapter_t */
40 #include <sys/kernel.h>
41 #include <sys/lock.h>
42 #include <sys/malloc.h>
43 #include <sys/module.h>
44 #include <sys/mutex.h>
45 #include <sys/rman.h>
46 #include <sys/systm.h>
47
48 #include <machine/bus.h>
49 #include <machine/resource.h>
50
51 #include <dev/terasic/mtl/terasic_mtl.h>
52
53 static int
54 terasic_mtl_nexus_probe(device_t dev)
55 {
56
57         device_set_desc(dev, "Terasic Multi-touch LCD (MTL)");
58         return (BUS_PROBE_NOWILDCARD);
59 }
60
61 static int
62 terasic_mtl_nexus_attach(device_t dev)
63 {
64         struct terasic_mtl_softc *sc;
65         u_long pixel_maddr, text_maddr, reg_maddr;
66         u_long pixel_msize, text_msize, reg_msize;
67         int error;
68
69         sc = device_get_softc(dev);
70         sc->mtl_dev = dev;
71         sc->mtl_unit = device_get_unit(dev);
72
73         /*
74          * Query non-standard hints to find the locations of our two memory
75          * regions.  Enforce certain alignment and size requirements.
76          */
77         if (resource_long_value(device_get_name(dev), device_get_unit(dev),
78             "reg_maddr", &reg_maddr) != 0 || (reg_maddr % PAGE_SIZE != 0)) {
79                 device_printf(dev, "improper register address");
80                 return (ENXIO);
81         }
82         if (resource_long_value(device_get_name(dev), device_get_unit(dev),
83             "reg_msize", &reg_msize) != 0 || (reg_msize % PAGE_SIZE != 0)) {
84                 device_printf(dev, "improper register size");
85                 return (ENXIO);
86         }
87         if (resource_long_value(device_get_name(dev), device_get_unit(dev),
88             "pixel_maddr", &pixel_maddr) != 0 ||
89             (pixel_maddr % PAGE_SIZE != 0)) {
90                 device_printf(dev, "improper pixel frame buffer address");
91                 return (ENXIO);
92         }
93         if (resource_long_value(device_get_name(dev), device_get_unit(dev),
94             "pixel_msize", &pixel_msize) != 0 ||
95             (pixel_msize % PAGE_SIZE != 0)) {
96                 device_printf(dev, "improper pixel frame buffer size");
97                 return (ENXIO);
98         }
99         if (resource_long_value(device_get_name(dev), device_get_unit(dev),
100             "text_maddr", &text_maddr) != 0 ||
101             (text_maddr % PAGE_SIZE != 0)) {
102                 device_printf(dev, "improper text frame buffer address");
103                 return (ENXIO);
104         }
105         if (resource_long_value(device_get_name(dev), device_get_unit(dev),
106             "text_msize", &text_msize) != 0 ||
107             (text_msize % PAGE_SIZE != 0)) {
108                 device_printf(dev, "improper text frame buffer size");
109                 return (ENXIO);
110         }
111
112         /*
113          * Allocate resources.
114          */
115         sc->mtl_reg_rid = 0;
116         sc->mtl_reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
117             &sc->mtl_reg_rid, reg_maddr, reg_maddr + reg_msize - 1,
118             reg_msize, RF_ACTIVE);
119         if (sc->mtl_reg_res == NULL) {
120                 device_printf(dev, "couldn't map register memory\n");
121                 error = ENXIO;
122                 goto error;
123         }
124         device_printf(sc->mtl_dev, "registers at mem %p-%p\n",
125             (void *)reg_maddr, (void *)(reg_maddr + reg_msize));
126         sc->mtl_pixel_rid = 0;
127         sc->mtl_pixel_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
128             &sc->mtl_pixel_rid, pixel_maddr, pixel_maddr + pixel_msize - 1,
129             pixel_msize, RF_ACTIVE);
130         if (sc->mtl_pixel_res == NULL) {
131                 device_printf(dev, "couldn't map pixel memory\n");
132                 error = ENXIO;
133                 goto error;
134         }
135         device_printf(sc->mtl_dev, "pixel frame buffer at mem %p-%p\n",
136             (void *)pixel_maddr, (void *)(pixel_maddr + pixel_msize));
137         sc->mtl_text_rid = 0;
138         sc->mtl_text_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
139             &sc->mtl_text_rid, text_maddr, text_maddr + text_msize - 1,
140             text_msize, RF_ACTIVE);
141         if (sc->mtl_text_res == NULL) {
142                 device_printf(dev, "couldn't map text memory\n");
143                 error = ENXIO;
144                 goto error;
145         }
146         device_printf(sc->mtl_dev, "text frame buffer at mem %p-%p\n",
147             (void *)text_maddr, (void *)(text_maddr + text_msize));
148         error = terasic_mtl_attach(sc);
149         if (error == 0)
150                 return (0);
151 error:
152         if (sc->mtl_text_res != NULL)
153                 bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_text_rid,
154                     sc->mtl_text_res);
155         if (sc->mtl_pixel_res != NULL)
156                 bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_pixel_rid,
157                     sc->mtl_pixel_res);
158         if (sc->mtl_reg_res != NULL)
159                 bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_reg_rid,
160                     sc->mtl_reg_res);
161         return (error);
162 }
163
164 static int
165 terasic_mtl_nexus_detach(device_t dev)
166 {
167         struct terasic_mtl_softc *sc;
168
169         sc = device_get_softc(dev);
170         terasic_mtl_detach(sc);
171         bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_text_rid,
172             sc->mtl_text_res);
173         bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_pixel_rid,
174             sc->mtl_pixel_res);
175         bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_reg_rid,
176             sc->mtl_reg_res);
177         return (0);
178 }
179
180 static device_method_t terasic_mtl_nexus_methods[] = {
181         DEVMETHOD(device_probe,         terasic_mtl_nexus_probe),
182         DEVMETHOD(device_attach,        terasic_mtl_nexus_attach),
183         DEVMETHOD(device_detach,        terasic_mtl_nexus_detach),
184         { 0, 0 }
185 };
186
187 static driver_t terasic_mtl_nexus_driver = {
188         "terasic_mtl",
189         terasic_mtl_nexus_methods,
190         sizeof(struct terasic_mtl_softc),
191 };
192
193 DRIVER_MODULE(mtl, nexus, terasic_mtl_nexus_driver, terasic_mtl_devclass, 0,
194     0);