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