source: SVN/rincon/u-boot/board/trab/tsc2000.c

Last change on this file was 55, checked in by Tim Harvey, 2 years ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 8.4 KB
RevLine 
[55]1/*
2 * Functions to access the TSC2000 controller on TRAB board (used for scanning
3 * thermo sensors)
4 *
5 * Copyright (C) 2003 Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de
6 *
7 * Copyright (C) 2002 DENX Software Engineering, Wolfgang Denk, wd@denx.de
8 *
9 * See file CREDITS for list of people who contributed to this
10 * project.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * MA 02111-1307 USA
26 */
27
28#include <common.h>
29#include <s3c2400.h>
30#include <div64.h>
31#include "tsc2000.h"
32
33#include "Pt1000_temp_data.h"
34
35/* helper function */
36#define abs(value) (((value) < 0) ? ((value)*-1) : (value))
37
38/*
39 * Maximal allowed deviation between two immediate meassurments of an analog
40 * thermo channel. 1 DIGIT = 0.0276 °C. This is used to filter sporadic
41 * "jumps" in measurment.
42 */
43#define MAX_DEVIATION   18      /* unit: DIGITs of adc; 18 DIGIT = 0.5 °C */
44
45void spi_init(void)
46{
47        S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
48        S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
49        int i;
50
51        /* Configure I/O ports. */
52        gpio->PDCON = (gpio->PDCON & 0xF3FFFF) | 0x040000;
53        gpio->PGCON = (gpio->PGCON & 0x0F3FFF) | 0x008000;
54        gpio->PGCON = (gpio->PGCON & 0x0CFFFF) | 0x020000;
55        gpio->PGCON = (gpio->PGCON & 0x03FFFF) | 0x080000;
56
57        CLR_CS_TOUCH();
58
59        spi->ch[0].SPPRE = 0x1F; /* Baud-rate ca. 514kHz */
60        spi->ch[0].SPPIN = 0x01; /* SPI-MOSI holds Level after last bit */
61        spi->ch[0].SPCON = 0x1A; /* Polling, Prescaler, Master, CPOL=0,
62                                    CPHA=1 */
63
64        /* Dummy byte ensures clock to be low. */
65        for (i = 0; i < 10; i++) {
66                spi->ch[0].SPTDAT = 0xFF;
67        }
68        spi_wait_transmit_done();
69}
70
71
72void spi_wait_transmit_done(void)
73{
74        S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
75
76        while (!(spi->ch[0].SPSTA & 0x01)); /* wait until transfer is done */
77}
78
79
80void tsc2000_write(unsigned short reg, unsigned short data)
81{
82        S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
83        unsigned int command;
84
85        SET_CS_TOUCH();
86        command = reg;
87        spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;
88        spi_wait_transmit_done();
89        spi->ch[0].SPTDAT = (command & 0x00FF);
90        spi_wait_transmit_done();
91        spi->ch[0].SPTDAT = (data & 0xFF00) >> 8;
92        spi_wait_transmit_done();
93        spi->ch[0].SPTDAT = (data & 0x00FF);
94        spi_wait_transmit_done();
95
96        CLR_CS_TOUCH();
97}
98
99
100unsigned short tsc2000_read (unsigned short reg)
101{
102        unsigned short command, data;
103        S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
104
105        SET_CS_TOUCH();
106        command = 0x8000 | reg;
107
108        spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;
109        spi_wait_transmit_done();
110        spi->ch[0].SPTDAT = (command & 0x00FF);
111        spi_wait_transmit_done();
112
113        spi->ch[0].SPTDAT = 0xFF;
114        spi_wait_transmit_done();
115        data = spi->ch[0].SPRDAT;
116        spi->ch[0].SPTDAT = 0xFF;
117        spi_wait_transmit_done();
118
119        CLR_CS_TOUCH();
120        return (spi->ch[0].SPRDAT & 0x0FF) | (data << 8);
121}
122
123
124void tsc2000_set_mux (unsigned int channel)
125{
126        S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
127
128        CLR_MUX1_ENABLE; CLR_MUX2_ENABLE;
129        CLR_MUX3_ENABLE; CLR_MUX4_ENABLE;
130        switch (channel) {
131        case 0:
132                CLR_MUX0; CLR_MUX1;
133                SET_MUX1_ENABLE;
134                break;
135        case 1:
136                SET_MUX0; CLR_MUX1;
137                SET_MUX1_ENABLE;
138                break;
139        case 2:
140                CLR_MUX0; SET_MUX1;
141                SET_MUX1_ENABLE;
142                break;
143        case 3:
144                SET_MUX0; SET_MUX1;
145                SET_MUX1_ENABLE;
146                break;
147        case 4:
148                CLR_MUX0; CLR_MUX1;
149                SET_MUX2_ENABLE;
150                break;
151        case 5:
152                SET_MUX0; CLR_MUX1;
153                SET_MUX2_ENABLE;
154                break;
155        case 6:
156                CLR_MUX0; SET_MUX1;
157                SET_MUX2_ENABLE;
158                break;
159        case 7:
160                SET_MUX0; SET_MUX1;
161                SET_MUX2_ENABLE;
162                break;
163        case 8:
164                CLR_MUX0; CLR_MUX1;
165                SET_MUX3_ENABLE;
166                break;
167        case 9:
168                SET_MUX0; CLR_MUX1;
169                SET_MUX3_ENABLE;
170                break;
171        case 10:
172                CLR_MUX0; SET_MUX1;
173                SET_MUX3_ENABLE;
174                break;
175        case 11:
176                SET_MUX0; SET_MUX1;
177                SET_MUX3_ENABLE;
178                break;
179        case 12:
180                CLR_MUX0; CLR_MUX1;
181                SET_MUX4_ENABLE;
182                break;
183        case 13:
184                SET_MUX0; CLR_MUX1;
185                SET_MUX4_ENABLE;
186                break;
187        case 14:
188                CLR_MUX0; SET_MUX1;
189                SET_MUX4_ENABLE;
190                break;
191        case 15:
192                SET_MUX0; SET_MUX1;
193                SET_MUX4_ENABLE;
194                break;
195        default:
196                CLR_MUX0; CLR_MUX1;
197        }
198}
199
200
201void tsc2000_set_range (unsigned int range)
202{
203        S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
204
205        switch (range) {
206        case 1:
207                CLR_SEL_TEMP_V_0; SET_SEL_TEMP_V_1;
208                CLR_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
209                break;
210        case 2:
211                CLR_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
212                CLR_SEL_TEMP_V_2; SET_SEL_TEMP_V_3;
213                break;
214        case 3:
215                SET_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
216                SET_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
217                break;
218        }
219}
220
221
222u16 tsc2000_read_channel (unsigned int channel)
223{
224        u16 res;
225
226        tsc2000_set_mux(channel);
227        udelay(20 * TSC2000_DELAY_BASE);
228
229        tsc2000_write(TSC2000_REG_ADC, 0x2036);
230        adc_wait_conversion_done ();
231        res = tsc2000_read(TSC2000_REG_AUX1);
232        return res;
233}
234
235
236s32 tsc2000_contact_temp (void)
237{
238        long adc_pt1000, offset;
239        long u_pt1000;
240        long contact_temp;
241        long temp1, temp2;
242
243        tsc2000_reg_init ();
244        tsc2000_set_range (3);
245
246        /*
247         * Because of sporadic "jumps" in the measured adc values every
248         * channel is read two times. If there is a significant difference
249         * between the two measurements, then print an error and do a third
250         * measurement, because it is very unlikely that a successive third
251         * measurement goes also wrong.
252         */
253        temp1 = tsc2000_read_channel (14);
254        temp2 = tsc2000_read_channel (14);
255        if (abs(temp2 - temp1) < MAX_DEVIATION)
256                adc_pt1000 = temp2;
257        else {
258                printf ("%s: read adc value (channel 14) exceeded max allowed "
259                        "deviation: %d * 0.0276 °C\n",
260                        __FUNCTION__, MAX_DEVIATION);
261                printf ("adc value 1: %ld DIGITs\nadc value 2: %ld DIGITs\n",
262                        temp1, temp2);
263                adc_pt1000 = tsc2000_read_channel (14);
264                printf ("use (third read) adc value: adc_pt1000 = "
265                        "%ld DIGITs\n", adc_pt1000);
266        }
267        debug ("read channel 14 (pt1000 adc value): %ld\n", adc_pt1000);
268
269        temp1 = tsc2000_read_channel (15);
270        temp2 = tsc2000_read_channel (15);
271        if (abs(temp2 - temp1) < MAX_DEVIATION)
272                offset = temp2;
273        else {
274                printf ("%s: read adc value (channel 15) exceeded max allowed "
275                        "deviation: %d * 0.0276 °C\n",
276                        __FUNCTION__, MAX_DEVIATION);
277                printf ("adc value 1: %ld DIGITs\nadc value 2: %ld DIGITs\n",
278                        temp1, temp2);
279                offset = tsc2000_read_channel (15);
280                printf ("use (third read) adc value: offset = %ld DIGITs\n",
281                        offset);
282        }
283        debug ("read channel 15 (offset): %ld\n", offset);
284
285        /*
286         * Formula for calculating voltage drop on PT1000 resistor: u_pt1000 =
287         * x_range3 * (adc_raw - offset) / 10. Formula to calculate x_range3:
288         * x_range3 = (2500 * (1000000 + err_vref + err_amp3)) / (4095*6). The
289         * error correction Values err_vref and err_amp3 are assumed as 0 in
290         * u-boot, because this could cause only a very small error (< 1%).
291         */
292        u_pt1000 = (101750 * (adc_pt1000 - offset)) / 10;
293        debug ("u_pt1000: %ld\n", u_pt1000);
294
295        if (tsc2000_interpolate(u_pt1000, Pt1000_temp_table,
296                                &contact_temp) == -1) {
297                printf ("%s: error interpolating PT1000 vlaue\n",
298                         __FUNCTION__);
299                return (-1000);
300        }
301        debug ("contact_temp: %ld\n", contact_temp);
302
303        return contact_temp;
304}
305
306
307void tsc2000_reg_init (void)
308{
309        S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
310
311        tsc2000_write(TSC2000_REG_ADC, 0x2036);
312        tsc2000_write(TSC2000_REG_REF, 0x0011);
313        tsc2000_write(TSC2000_REG_DACCTL, 0x0000);
314
315        CON_MUX0;
316        CON_MUX1;
317
318        CON_MUX1_ENABLE;
319        CON_MUX2_ENABLE;
320        CON_MUX3_ENABLE;
321        CON_MUX4_ENABLE;
322
323        CON_SEL_TEMP_V_0;
324        CON_SEL_TEMP_V_1;
325        CON_SEL_TEMP_V_2;
326        CON_SEL_TEMP_V_3;
327
328        tsc2000_set_mux(0);
329        tsc2000_set_range(0);
330}
331
332
333int tsc2000_interpolate(long value, long data[][2], long *result)
334{
335        int i;
336        unsigned long long val;
337
338        /* the data is sorted and the first element is upper
339         * limit so we can easily check for out-of-band values
340         */
341        if (data[0][0] < value || data[1][0] > value)
342                return -1;
343
344        i = 1;
345        while (data[i][0] < value)
346                i++;
347
348        /* To prevent overflow we have to store the intermediate
349           result in 'long long'.
350        */
351
352        val = ((unsigned long long)(data[i][1] - data[i-1][1])
353                   * (unsigned long long)(value - data[i-1][0]));
354        do_div(val, (data[i][0] - data[i-1][0]));
355        *result = data[i-1][1] + val;
356
357        return 0;
358}
359
360
361void adc_wait_conversion_done(void)
362{
363        while (!(tsc2000_read(TSC2000_REG_ADC) & (1 << 14)));
364}
Note: See TracBrowser for help on using the repository browser.