]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/allwinner/aw_ts.c
Fix LOCAL_MODULES and improve the make output.
[FreeBSD/FreeBSD.git] / sys / arm / allwinner / aw_ts.c
1 /*-
2  * Copyright (c) 2016 Emmanuel Vadot <manu@freebsd.org>
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  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 /*
28  * Allwinner Touch Sreen driver
29  * Touch screen part is not done, only the thermal sensor part is.
30  */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/bus.h>
38 #include <sys/kernel.h>
39 #include <sys/module.h>
40 #include <sys/rman.h>
41 #include <sys/sysctl.h>
42 #include <machine/bus.h>
43
44 #include <dev/ofw/openfirm.h>
45 #include <dev/ofw/ofw_bus.h>
46 #include <dev/ofw/ofw_bus_subr.h>
47
48 #define READ(_sc, _r) bus_read_4((_sc)->res[0], (_r))
49 #define WRITE(_sc, _r, _v) bus_write_4((_sc)->res[0], (_r), (_v))
50
51 /* Control register 0 */
52 #define TP_CTRL0        0x00
53 #define  TP_CTRL0_TACQ(x)       ((x & 0xFF) << 0)
54 #define  TP_CTRL0_FS_DIV(x)     ((x & 0xF) << 16)
55 #define  TP_CTRL0_CLK_DIV(x)    ((x & 0x3) << 20)
56 #define  TP_CTRL0_CLK_SELECT(x) ((x & 0x1) << 22)
57
58 /* Control register 1 */
59 #define TP_CTRL1        0x04
60 #define  TP_CTRL1_MODE_EN       (1 << 4)
61
62 /* Control register 2 */
63 #define TP_CTRL2        0x08
64
65 /* Control register 3 */
66 #define TP_CTRL3        0x0C
67
68 /* Int/FIFO control register */
69 #define TP_FIFOC        0x10
70 #define  TP_FIFOC_TEMP_IRQ_ENABLE       (1 << 18)
71
72 /* Int/FIFO status register */
73 #define TP_FIFOS        0x14
74 #define  TP_FIFOS_TEMP_IRQ_PENDING      (1 << 18)
75
76 /* Temperature Period Register */
77 #define TP_TPR          0x18
78 #define  TP_TPR_TEMP_EN         (1 << 16)
79 #define  TP_TPR_TEMP_PERIOD(x)  (x << 0)
80
81 /* Common data register */
82 #define TP_CDAT         0x1C
83
84 /* Temperature data register */
85 #define TEMP_DATA       0x20
86
87 /* TP Data register*/
88 #define TP_DATA         0x24
89
90 /* TP IO config register */
91 #define TP_IO_CONFIG    0x28
92
93 /* TP IO port data register */
94 #define TP_IO_DATA      0x2C
95
96 struct aw_ts_softc {
97         device_t                dev;
98         struct resource *       res[2];
99         void *                  intrhand;
100         int                     temp_data;
101         int                     temp_offset;
102         int                     temp_step;
103 };
104
105 static struct resource_spec aw_ts_spec[] = {
106         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
107         { SYS_RES_IRQ,          0,      RF_ACTIVE | RF_SHAREABLE },
108         { -1, 0 }
109 };
110
111 #define A10_TS  1
112 #define A13_TS  2
113
114 #define AW_TS_TEMP_SYSCTL       1
115
116 static struct ofw_compat_data compat_data[] = {
117         {"allwinner,sun4i-a10-ts", A10_TS},
118         {"allwinner,sun5i-a13-ts", A13_TS},
119         {NULL,             0}
120 };
121
122 static void
123 aw_ts_intr(void *arg)
124 {
125         struct aw_ts_softc *sc;
126         int val;
127
128         sc= (struct aw_ts_softc *)arg;
129
130         val = READ(sc, TP_FIFOS);
131         if (val & TP_FIFOS_TEMP_IRQ_PENDING) {
132                 /* Convert the value to millicelsius then millikelvin */
133                 sc->temp_data = (READ(sc, TEMP_DATA) * sc->temp_step - sc->temp_offset)
134                         + 273150;
135         }
136
137         WRITE(sc, TP_FIFOS, val);
138 }
139
140 static int
141 aw_ts_probe(device_t dev)
142 {
143
144         if (!ofw_bus_status_okay(dev))
145                 return (ENXIO);
146
147         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
148                 return (ENXIO);
149
150         device_set_desc(dev, "Allwinner Touch Screen controller");
151         return (BUS_PROBE_DEFAULT);
152 }
153
154 static int
155 aw_ts_attach(device_t dev)
156 {
157         struct aw_ts_softc *sc;
158
159         sc = device_get_softc(dev);
160         sc->dev = dev;
161
162         if (bus_alloc_resources(dev, aw_ts_spec, sc->res) != 0) {
163                 device_printf(dev, "could not allocate memory resource\n");
164                 return (ENXIO);
165         }
166
167         if (bus_setup_intr(dev, sc->res[1],
168             INTR_TYPE_MISC | INTR_MPSAFE, NULL, aw_ts_intr, sc,
169             &sc->intrhand)) {
170                 bus_release_resources(dev, aw_ts_spec, sc->res);
171                 device_printf(dev, "cannot setup interrupt handler\n");
172                 return (ENXIO);
173         }
174
175         /*
176          * Thoses magic values were taken from linux which take them from
177          * the allwinner SDK or found them by deduction
178          */
179         switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) {
180         case A10_TS:
181                 sc->temp_offset = 257000;
182                 sc->temp_step = 133;
183                 break;
184         case A13_TS:
185                 sc->temp_offset = 144700;
186                 sc->temp_step = 100;
187                 break;
188         }
189
190         /* Enable clock and set divisers */
191         WRITE(sc, TP_CTRL0, TP_CTRL0_CLK_SELECT(0) |
192           TP_CTRL0_CLK_DIV(2) |
193           TP_CTRL0_FS_DIV(7) |
194           TP_CTRL0_TACQ(63));
195
196         /* Enable TS module */
197         WRITE(sc, TP_CTRL1, TP_CTRL1_MODE_EN);
198
199         /* Enable Temperature, period is ~2s */
200         WRITE(sc, TP_TPR, TP_TPR_TEMP_EN | TP_TPR_TEMP_PERIOD(1953));
201
202         /* Enable temp irq */
203         WRITE(sc, TP_FIFOC, TP_FIFOC_TEMP_IRQ_ENABLE);
204
205         /* Add sysctl */
206         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
207             SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
208             OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD,
209             &sc->temp_data, 0, sysctl_handle_int,
210             "IK3", "CPU Temperature");
211
212         return (0);
213 }
214
215 static device_method_t aw_ts_methods[] = {
216         DEVMETHOD(device_probe, aw_ts_probe),
217         DEVMETHOD(device_attach, aw_ts_attach),
218
219         DEVMETHOD_END
220 };
221
222 static driver_t aw_ts_driver = {
223         "aw_ts",
224         aw_ts_methods,
225         sizeof(struct aw_ts_softc),
226 };
227 static devclass_t aw_ts_devclass;
228
229 DRIVER_MODULE(aw_ts, simplebus, aw_ts_driver, aw_ts_devclass, 0, 0);