block_am335x_adc.c 8.77 KB
Newer Older
Jeroen Vreeken's avatar
Jeroen Vreeken committed
1
/*
Jeroen Vreeken's avatar
Jeroen Vreeken committed
2
	Copyright Jeroen Vreeken (jeroen@vreeken.net), 2014
Jeroen Vreeken's avatar
Jeroen Vreeken committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.

 */

Jeroen Vreeken's avatar
Jeroen Vreeken committed
19
#include "am335x.h"
Jeroen Vreeken's avatar
Jeroen Vreeken committed
20

Jeroen Vreeken's avatar
Jeroen Vreeken committed
21
#include <controller/controller_block.h>
Jeroen Vreeken's avatar
Jeroen Vreeken committed
22
23
#include <log/log.h>

Jeroen Vreeken's avatar
Jeroen Vreeken committed
24
25

struct controller_block_private {
Jeroen Vreeken's avatar
Jeroen Vreeken committed
26
27
28
29
30
31
	float ain[8];

	float gain[8];
	float offset[8];
	
	void *base;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
32
33
34
35
};

static void adc_calculate(struct controller_block *adc)
{
Jeroen Vreeken's avatar
Jeroen Vreeken committed
36
37
38
39
40
41
	struct controller_block_private *priv = adc->private;
	void *base = priv->base;
	uint32_t data;
	uint32_t count;
	
	do {
Jeroen Vreeken's avatar
Jeroen Vreeken committed
42
		count = am335x_read32(base, AM335X_ADC_REG_FIFO0COUNT);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
43
44
45
46
47
	} while (count != 8);
	
	for (; count; count--) {
		int id;
		
Jeroen Vreeken's avatar
Jeroen Vreeken committed
48
		data = am335x_read32(base, AM335X_ADC_REG_FIFO0DATA);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
49
50
51
52
53
54
55
		id = AM335X_ADC_FIFODATA_ID_GET(data);
		
		priv->ain[id] = 
		    AM335X_ADC_FIFODATA_DATA_GET(data) * priv->gain[id] +
		    priv->offset[id];
	}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
56
	am335x_write32(base, AM335X_ADC_REG_STEPENABLE, 
Jeroen Vreeken's avatar
Jeroen Vreeken committed
57
58
59
60
	    AM335X_ADC_STEPENABLE_STEP1 | AM335X_ADC_STEPENABLE_STEP2 |
	    AM335X_ADC_STEPENABLE_STEP3 | AM335X_ADC_STEPENABLE_STEP4 |
	    AM335X_ADC_STEPENABLE_STEP5 | AM335X_ADC_STEPENABLE_STEP6 |
	    AM335X_ADC_STEPENABLE_STEP7 | AM335X_ADC_STEPENABLE_STEP8 );
Jeroen Vreeken's avatar
Jeroen Vreeken committed
61
62
63
}

static struct controller_block_outterm_list outterms[] = {
Jeroen Vreeken's avatar
Jeroen Vreeken committed
64
65
66
67
68
69
70
71
	{ "ain0", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[0]) },
	{ "ain1", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[1]) },
	{ "ain2", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[2]) },
	{ "ain3", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[3]) },
	{ "ain4", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[4]) },
	{ "ain5", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[5]) },
	{ "ain6", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[6]) },
	{ "ain7", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[7]) },
Jeroen Vreeken's avatar
Jeroen Vreeken committed
72
73
74
	{ NULL }
};

75
76
77
78
79
80
81
static int param_set_gain(struct controller_block *adc, char *param, int argc,
    va_list val)
{
	adc->private->gain[param[4]-'0'] = va_arg(val, double) * AM335X_ADC_FACTOR;
	return 0;
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
82
static int param_set_offset(struct controller_block *adc, char *param, int argc,
83
84
85
86
87
88
    va_list val)
{
	adc->private->offset[param[6]-'0'] = va_arg(val, double);
	return 0;
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
89
static struct controller_block_param_list params[] = {
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
	{ "gain0", false, param_set_gain, .args = { "double", NULL } },
	{ "gain1", false, param_set_gain, .args = { "double", NULL } },
	{ "gain2", false, param_set_gain, .args = { "double", NULL } },
	{ "gain3", false, param_set_gain, .args = { "double", NULL } },
	{ "gain4", false, param_set_gain, .args = { "double", NULL } },
	{ "gain5", false, param_set_gain, .args = { "double", NULL } },
	{ "gain6", false, param_set_gain, .args = { "double", NULL } },
	{ "gain7", false, param_set_gain, .args = { "double", NULL } },
	{ "offset0", false, param_set_offset, .args = { "double", NULL } },
	{ "offset1", false, param_set_offset, .args = { "double", NULL } },
	{ "offset2", false, param_set_offset, .args = { "double", NULL } },
	{ "offset3", false, param_set_offset, .args = { "double", NULL } },
	{ "offset4", false, param_set_offset, .args = { "double", NULL } },
	{ "offset5", false, param_set_offset, .args = { "double", NULL } },
	{ "offset6", false, param_set_offset, .args = { "double", NULL } },
	{ "offset7", false, param_set_offset, .args = { "double", NULL } },
Jeroen Vreeken's avatar
Jeroen Vreeken committed
106
107
108
109
	{ NULL },
};


Jeroen Vreeken's avatar
Jeroen Vreeken committed
110
static struct controller_block * block_am335x_adc_create(char *name, int argc, va_list val)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
111
112
{
	struct controller_block *adc;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
113
114
	void *base;
	uint32_t reg;
115
116
117
118
119
120

	if (am335x_cm_enable(AM335X_CM_WKUP_ADC_TSC_CLKCTRL)) {
		log_send(LOG_T_ERROR, "%s: Enabling module failed", name);
		return NULL;
	}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
121
	base = am335x_mem(AM335X_ADC_BASE, AM335X_ADC_SIZE);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
122
	if (!base) {
Jeroen Vreeken's avatar
Jeroen Vreeken committed
123
		log_send(LOG_T_ERROR, "%s: Mapping ADC failed", name);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
124
125
126
127
		return NULL;
	}
	log_send(LOG_T_DEBUG, "%s: ADC mapped @ %p", name, base);
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
128
	reg = am335x_read32(base, AM335X_ADC_REG_REVISION);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
129
130
131
132
133
134
135
136
137
138
	log_send(LOG_T_DEBUG, 
	    "%s: REVISION: 0x%" PRIx32 ": func: 0x%03x rev: %d.%d",
	    name, reg, AM335X_ADC_REVISION_FUNC_GET(reg),
	    AM335X_ADC_REVISION_X_MAJOR_GET(reg),
	    AM335X_ADC_REVISION_Y_MINOR_GET(reg));
	if (AM335X_ADC_REVISION_FUNC_GET(reg) != AM335X_ADC_REVISION_FUNC) {
		log_send(LOG_T_ERROR, "Unexpected functional number");
		goto err_rev;
	}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
139
	am335x_write32(base, AM335X_ADC_REG_CTRL, AM335X_ADC_CTRL_SC_WP_N);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
140

Jeroen Vreeken's avatar
Jeroen Vreeken committed
141
	am335x_write32(base, AM335X_ADC_REG_IRQENABLE_CLR, 
Jeroen Vreeken's avatar
Jeroen Vreeken committed
142
143
	    AM335X_ADC_IRQENABLE_CLR_ALL);

Jeroen Vreeken's avatar
Jeroen Vreeken committed
144
	am335x_write32(base, AM335X_ADC_REG_DMAENABLE_CLR, 
Jeroen Vreeken's avatar
Jeroen Vreeken committed
145
146
	    AM335X_ADC_DMAENABLE_CLR_ALL);

Jeroen Vreeken's avatar
Jeroen Vreeken committed
147
	am335x_write32(base, AM335X_ADC_REG_ADC_CLKDIV, 0);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
148

Jeroen Vreeken's avatar
Jeroen Vreeken committed
149
150
	am335x_write32(base, AM335X_ADC_REG_IDLECONFIG, 0);
	am335x_write32(base, AM335X_ADC_REG_TS_CHARGE_DELAY, 1);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
151

Jeroen Vreeken's avatar
Jeroen Vreeken committed
152
	am335x_write32(base, AM335X_ADC_REG_STEPCONFIG1, 
Jeroen Vreeken's avatar
Jeroen Vreeken committed
153
154
155
156
	    AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_INP_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
Jeroen Vreeken's avatar
Jeroen Vreeken committed
157
	am335x_write32(base, AM335X_ADC_REG_STEPDELAY1, 0);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
158

Jeroen Vreeken's avatar
Jeroen Vreeken committed
159
	am335x_write32(base, AM335X_ADC_REG_STEPCONFIG2, 
Jeroen Vreeken's avatar
Jeroen Vreeken committed
160
161
162
163
	    AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_INP_SET(1) |
	    AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
Jeroen Vreeken's avatar
Jeroen Vreeken committed
164
	am335x_write32(base, AM335X_ADC_REG_STEPDELAY2, 0);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
165

Jeroen Vreeken's avatar
Jeroen Vreeken committed
166
	am335x_write32(base, AM335X_ADC_REG_STEPCONFIG3, 
Jeroen Vreeken's avatar
Jeroen Vreeken committed
167
168
169
170
	    AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_INP_SET(2) |
	    AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
Jeroen Vreeken's avatar
Jeroen Vreeken committed
171
	am335x_write32(base, AM335X_ADC_REG_STEPDELAY3, 0);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
172

Jeroen Vreeken's avatar
Jeroen Vreeken committed
173
	am335x_write32(base, AM335X_ADC_REG_STEPCONFIG4, 
Jeroen Vreeken's avatar
Jeroen Vreeken committed
174
175
176
177
	    AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_INP_SET(3) |
	    AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
Jeroen Vreeken's avatar
Jeroen Vreeken committed
178
	am335x_write32(base, AM335X_ADC_REG_STEPDELAY4, 0);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
179

Jeroen Vreeken's avatar
Jeroen Vreeken committed
180
	am335x_write32(base, AM335X_ADC_REG_STEPCONFIG5, 
Jeroen Vreeken's avatar
Jeroen Vreeken committed
181
182
183
184
	    AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_INP_SET(4) |
	    AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
Jeroen Vreeken's avatar
Jeroen Vreeken committed
185
	am335x_write32(base, AM335X_ADC_REG_STEPDELAY5, 0);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
186

Jeroen Vreeken's avatar
Jeroen Vreeken committed
187
	am335x_write32(base, AM335X_ADC_REG_STEPCONFIG6, 
Jeroen Vreeken's avatar
Jeroen Vreeken committed
188
189
190
191
	    AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_INP_SET(5) |
	    AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
Jeroen Vreeken's avatar
Jeroen Vreeken committed
192
	am335x_write32(base, AM335X_ADC_REG_STEPDELAY6, 0);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
193

Jeroen Vreeken's avatar
Jeroen Vreeken committed
194
	am335x_write32(base, AM335X_ADC_REG_STEPCONFIG7, 
Jeroen Vreeken's avatar
Jeroen Vreeken committed
195
196
197
198
	    AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_INP_SET(6) |
	    AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
Jeroen Vreeken's avatar
Jeroen Vreeken committed
199
	am335x_write32(base, AM335X_ADC_REG_STEPDELAY7, 0);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
200

Jeroen Vreeken's avatar
Jeroen Vreeken committed
201
	am335x_write32(base, AM335X_ADC_REG_STEPCONFIG8, 
Jeroen Vreeken's avatar
Jeroen Vreeken committed
202
203
204
205
	    AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
	    AM335X_ADC_STEPCONFIG_SEL_INP_SET(7) |
	    AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
Jeroen Vreeken's avatar
Jeroen Vreeken committed
206
	am335x_write32(base, AM335X_ADC_REG_STEPDELAY8, 0);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
207

Jeroen Vreeken's avatar
Jeroen Vreeken committed
208
	am335x_write32(base, AM335X_ADC_REG_CTRL, 
Jeroen Vreeken's avatar
Jeroen Vreeken committed
209
210
211
212
	    AM335X_ADC_CTRL_SC_WP_N |
	    AM335X_ADC_CTRL_SID |
	    AM335X_ADC_CTRL_ENABLE);

Jeroen Vreeken's avatar
Jeroen Vreeken committed
213
	am335x_write32(base, AM335X_ADC_REG_STEPENABLE, 
Jeroen Vreeken's avatar
Jeroen Vreeken committed
214
215
216
217
218
219
220
	    AM335X_ADC_STEPENABLE_STEP1 | AM335X_ADC_STEPENABLE_STEP2 |
	    AM335X_ADC_STEPENABLE_STEP3 | AM335X_ADC_STEPENABLE_STEP4 |
	    AM335X_ADC_STEPENABLE_STEP5 | AM335X_ADC_STEPENABLE_STEP6 |
	    AM335X_ADC_STEPENABLE_STEP7 | AM335X_ADC_STEPENABLE_STEP8 );

	if (!(adc = controller_block_alloc("am355x_adc", name, sizeof(struct controller_block_private))))
		goto err_alloc;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
221
222

	if (controller_block_outterm_list_init(adc, outterms))
Jeroen Vreeken's avatar
Jeroen Vreeken committed
223
224
225
226
227
228
229
230
231
232
233
234
		goto err_outterm;

	adc->private->base = base;

	adc->private->gain[0] = AM335X_ADC_FACTOR;
	adc->private->gain[1] = AM335X_ADC_FACTOR;
	adc->private->gain[2] = AM335X_ADC_FACTOR;
	adc->private->gain[3] = AM335X_ADC_FACTOR;
	adc->private->gain[4] = AM335X_ADC_FACTOR;
	adc->private->gain[5] = AM335X_ADC_FACTOR;
	adc->private->gain[6] = AM335X_ADC_FACTOR;
	adc->private->gain[7] = AM335X_ADC_FACTOR;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
235
236
237

	adc->calculate = adc_calculate;

Jeroen Vreeken's avatar
Jeroen Vreeken committed
238
	if (controller_block_param_list_add(adc, params))
Jeroen Vreeken's avatar
Jeroen Vreeken committed
239
		goto err_param;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
240

241
242
243
	if (controller_block_add(adc))
		goto err_add;
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
244
245
	return adc;

246
err_add:
Jeroen Vreeken's avatar
Jeroen Vreeken committed
247
248
err_param:
err_outterm:
Jeroen Vreeken's avatar
Jeroen Vreeken committed
249
	controller_block_free(adc);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
250
251
err_alloc:
err_rev:
Jeroen Vreeken's avatar
Jeroen Vreeken committed
252
253
	return NULL;
}
254
255
256
257
258

BLOCK_CREATE(am335x_adc) = {
	.create = block_am335x_adc_create,
	.args = { NULL },
};