Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm/freescale/vybrid/vf_adc.c
39537 views
1
/*-
2
* Copyright (c) 2014 Ruslan Bukin <[email protected]>
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
* Vybrid Family 12-bit Analog to Digital Converter (ADC)
29
* Chapter 37, Vybrid Reference Manual, Rev. 5, 07/2013
30
*/
31
32
#include <sys/param.h>
33
#include <sys/systm.h>
34
#include <sys/bus.h>
35
#include <sys/kernel.h>
36
#include <sys/module.h>
37
#include <sys/malloc.h>
38
#include <sys/rman.h>
39
#include <sys/timeet.h>
40
#include <sys/timetc.h>
41
42
#include <dev/ofw/openfirm.h>
43
#include <dev/ofw/ofw_bus.h>
44
#include <dev/ofw/ofw_bus_subr.h>
45
46
#include <machine/bus.h>
47
#include <machine/cpu.h>
48
#include <machine/intr.h>
49
50
#include <arm/freescale/vybrid/vf_common.h>
51
#include <arm/freescale/vybrid/vf_adc.h>
52
53
#define ADC_HC0 0x00 /* Ctrl reg for hardware triggers */
54
#define ADC_HC1 0x04 /* Ctrl reg for hardware triggers */
55
#define HC_AIEN (1 << 7) /* Conversion Complete Int Control */
56
#define HC_ADCH_M 0x1f /* Input Channel Select Mask */
57
#define HC_ADCH_S 0 /* Input Channel Select Shift */
58
#define ADC_HS 0x08 /* Status register for HW triggers */
59
#define HS_COCO0 (1 << 0) /* Conversion Complete Flag */
60
#define HS_COCO1 (1 << 1) /* Conversion Complete Flag */
61
#define ADC_R0 0x0C /* Data result reg for HW triggers */
62
#define ADC_R1 0x10 /* Data result reg for HW triggers */
63
#define ADC_CFG 0x14 /* Configuration register */
64
#define CFG_OVWREN (1 << 16) /* Data Overwrite Enable */
65
#define CFG_AVGS_M 0x3 /* Hardware Average select Mask */
66
#define CFG_AVGS_S 14 /* Hardware Average select Shift */
67
#define CFG_ADTRG (1 << 13) /* Conversion Trigger Select */
68
#define CFG_REFSEL_M 0x3 /* Voltage Reference Select Mask */
69
#define CFG_REFSEL_S 11 /* Voltage Reference Select Shift */
70
#define CFG_ADHSC (1 << 10) /* High Speed Configuration */
71
#define CFG_ADSTS_M 0x3 /* Defines the sample time duration */
72
#define CFG_ADSTS_S 8 /* Defines the sample time duration */
73
#define CFG_ADLPC (1 << 7) /* Low-Power Configuration */
74
#define CFG_ADIV_M 0x3 /* Clock Divide Select */
75
#define CFG_ADIV_S 5 /* Clock Divide Select */
76
#define CFG_ADLSMP (1 << 4) /* Long Sample Time Configuration */
77
#define CFG_MODE_M 0x3 /* Conversion Mode Selection Mask */
78
#define CFG_MODE_S 2 /* Conversion Mode Selection Shift */
79
#define CFG_MODE_12 0x2 /* 12-bit mode */
80
#define CFG_ADICLK_M 0x3 /* Input Clock Select Mask */
81
#define CFG_ADICLK_S 0 /* Input Clock Select Shift */
82
#define ADC_GC 0x18 /* General control register */
83
#define GC_CAL (1 << 7) /* Calibration */
84
#define GC_ADCO (1 << 6) /* Continuous Conversion Enable */
85
#define GC_AVGE (1 << 5) /* Hardware average enable */
86
#define GC_ACFE (1 << 4) /* Compare Function Enable */
87
#define GC_ACFGT (1 << 3) /* Compare Function Greater Than En */
88
#define GC_ACREN (1 << 2) /* Compare Function Range En */
89
#define GC_DMAEN (1 << 1) /* DMA Enable */
90
#define GC_ADACKEN (1 << 0) /* Asynchronous clock output enable */
91
#define ADC_GS 0x1C /* General status register */
92
#define GS_AWKST (1 << 2) /* Asynchronous wakeup int status */
93
#define GS_CALF (1 << 1) /* Calibration Failed Flag */
94
#define GS_ADACT (1 << 0) /* Conversion Active */
95
#define ADC_CV 0x20 /* Compare value register */
96
#define CV_CV2_M 0xfff /* Compare Value 2 Mask */
97
#define CV_CV2_S 16 /* Compare Value 2 Shift */
98
#define CV_CV1_M 0xfff /* Compare Value 1 Mask */
99
#define CV_CV1_S 0 /* Compare Value 1 Shift */
100
#define ADC_OFS 0x24 /* Offset correction value register */
101
#define OFS_SIGN 12 /* Sign bit */
102
#define OFS_M 0xfff /* Offset value Mask */
103
#define OFS_S 0 /* Offset value Shift */
104
#define ADC_CAL 0x28 /* Calibration value register */
105
#define CAL_CODE_M 0xf /* Calibration Result Value Mask */
106
#define CAL_CODE_S 0 /* Calibration Result Value Shift */
107
#define ADC_PCTL 0x30 /* Pin control register */
108
109
struct adc_softc {
110
struct resource *res[2];
111
bus_space_tag_t bst;
112
bus_space_handle_t bsh;
113
void *ih;
114
};
115
116
struct adc_softc *adc_sc;
117
118
static struct resource_spec adc_spec[] = {
119
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
120
{ SYS_RES_IRQ, 0, RF_ACTIVE },
121
{ -1, 0 }
122
};
123
124
static int
125
adc_probe(device_t dev)
126
{
127
128
if (!ofw_bus_status_okay(dev))
129
return (ENXIO);
130
131
if (!ofw_bus_is_compatible(dev, "fsl,mvf600-adc"))
132
return (ENXIO);
133
134
device_set_desc(dev, "Vybrid Family "
135
"12-bit Analog to Digital Converter");
136
return (BUS_PROBE_DEFAULT);
137
}
138
139
static void
140
adc_intr(void *arg)
141
{
142
143
/* Conversation complete */
144
}
145
146
uint32_t
147
adc_read(void)
148
{
149
struct adc_softc *sc;
150
151
sc = adc_sc;
152
if (sc == NULL)
153
return (0);
154
155
return (READ4(sc, ADC_R0));
156
}
157
158
uint32_t
159
adc_enable(int channel)
160
{
161
struct adc_softc *sc;
162
int reg;
163
164
sc = adc_sc;
165
if (sc == NULL)
166
return (1);
167
168
reg = READ4(sc, ADC_HC0);
169
reg &= ~(HC_ADCH_M << HC_ADCH_S);
170
reg |= (channel << HC_ADCH_S);
171
WRITE4(sc, ADC_HC0, reg);
172
173
return (0);
174
}
175
176
static int
177
adc_attach(device_t dev)
178
{
179
struct adc_softc *sc;
180
int err;
181
int reg;
182
183
sc = device_get_softc(dev);
184
185
if (bus_alloc_resources(dev, adc_spec, sc->res)) {
186
device_printf(dev, "could not allocate resources\n");
187
return (ENXIO);
188
}
189
190
/* Memory interface */
191
sc->bst = rman_get_bustag(sc->res[0]);
192
sc->bsh = rman_get_bushandle(sc->res[0]);
193
194
adc_sc = sc;
195
196
/* Setup interrupt handler */
197
err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_BIO | INTR_MPSAFE,
198
NULL, adc_intr, sc, &sc->ih);
199
if (err) {
200
device_printf(dev, "Unable to alloc interrupt resource.\n");
201
return (ENXIO);
202
}
203
204
/* Configure 12-bit mode */
205
reg = READ4(sc, ADC_CFG);
206
reg &= ~(CFG_MODE_M << CFG_MODE_S);
207
reg |= (CFG_MODE_12 << CFG_MODE_S); /* 12bit */
208
WRITE4(sc, ADC_CFG, reg);
209
210
/* Configure for continuous conversion */
211
reg = READ4(sc, ADC_GC);
212
reg |= (GC_ADCO | GC_AVGE);
213
WRITE4(sc, ADC_GC, reg);
214
215
/* Disable interrupts */
216
reg = READ4(sc, ADC_HC0);
217
reg &= HC_AIEN;
218
WRITE4(sc, ADC_HC0, reg);
219
220
return (0);
221
}
222
223
static device_method_t adc_methods[] = {
224
DEVMETHOD(device_probe, adc_probe),
225
DEVMETHOD(device_attach, adc_attach),
226
{ 0, 0 }
227
};
228
229
static driver_t adc_driver = {
230
"adc",
231
adc_methods,
232
sizeof(struct adc_softc),
233
};
234
235
DRIVER_MODULE(adc, simplebus, adc_driver, 0, 0);
236
237