2 * Functions to access the TSC2000 controller on TRAB board (used for scanning
5 * Copyright (C) 2003 Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de
7 * Copyright (C) 2002 DENX Software Engineering, Wolfgang Denk, wd@denx.de
9 * See file CREDITS for list of people who contributed to this
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.
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.
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,
32 #include "Pt1000_temp_data.h"
35 #define abs(value) (((value) < 0) ? ((value)*-1) : (value))
38 * Maximal allowed deviation between two immediate meassurments of an analog
39 * thermo channel. 1 DIGIT = 0.0276 °C. This is used to filter sporadic
40 * "jumps" in measurment.
42 #define MAX_DEVIATION 18 /* unit: DIGITs of adc; 18 DIGIT = 0.5 °C */
46 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
47 S3C24X0_SPI
* const spi
= S3C24X0_GetBase_SPI();
50 /* Configure I/O ports. */
51 gpio
->PDCON
= (gpio
->PDCON
& 0xF3FFFF) | 0x040000;
52 gpio
->PGCON
= (gpio
->PGCON
& 0x0F3FFF) | 0x008000;
53 gpio
->PGCON
= (gpio
->PGCON
& 0x0CFFFF) | 0x020000;
54 gpio
->PGCON
= (gpio
->PGCON
& 0x03FFFF) | 0x080000;
58 spi
->ch
[0].SPPRE
= 0x1F; /* Baud-rate ca. 514kHz */
59 spi
->ch
[0].SPPIN
= 0x01; /* SPI-MOSI holds Level after last bit */
60 spi
->ch
[0].SPCON
= 0x1A; /* Polling, Prescaler, Master, CPOL=0,
63 /* Dummy byte ensures clock to be low. */
64 for (i
= 0; i
< 10; i
++) {
65 spi
->ch
[0].SPTDAT
= 0xFF;
67 spi_wait_transmit_done();
71 void spi_wait_transmit_done(void)
73 S3C24X0_SPI
* const spi
= S3C24X0_GetBase_SPI();
75 while (!(spi
->ch
[0].SPSTA
& 0x01)); /* wait until transfer is done */
79 void tsc2000_write(unsigned short reg
, unsigned short data
)
81 S3C24X0_SPI
* const spi
= S3C24X0_GetBase_SPI();
86 spi
->ch
[0].SPTDAT
= (command
& 0xFF00) >> 8;
87 spi_wait_transmit_done();
88 spi
->ch
[0].SPTDAT
= (command
& 0x00FF);
89 spi_wait_transmit_done();
90 spi
->ch
[0].SPTDAT
= (data
& 0xFF00) >> 8;
91 spi_wait_transmit_done();
92 spi
->ch
[0].SPTDAT
= (data
& 0x00FF);
93 spi_wait_transmit_done();
99 unsigned short tsc2000_read (unsigned short reg
)
101 unsigned short command
, data
;
102 S3C24X0_SPI
* const spi
= S3C24X0_GetBase_SPI();
105 command
= 0x8000 | reg
;
107 spi
->ch
[0].SPTDAT
= (command
& 0xFF00) >> 8;
108 spi_wait_transmit_done();
109 spi
->ch
[0].SPTDAT
= (command
& 0x00FF);
110 spi_wait_transmit_done();
112 spi
->ch
[0].SPTDAT
= 0xFF;
113 spi_wait_transmit_done();
114 data
= spi
->ch
[0].SPRDAT
;
115 spi
->ch
[0].SPTDAT
= 0xFF;
116 spi_wait_transmit_done();
119 return (spi
->ch
[0].SPRDAT
& 0x0FF) | (data
<< 8);
123 void tsc2000_set_mux (unsigned int channel
)
125 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
127 CLR_MUX1_ENABLE
; CLR_MUX2_ENABLE
;
128 CLR_MUX3_ENABLE
; CLR_MUX4_ENABLE
;
200 void tsc2000_set_range (unsigned int range
)
202 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
206 CLR_SEL_TEMP_V_0
; SET_SEL_TEMP_V_1
;
207 CLR_SEL_TEMP_V_2
; CLR_SEL_TEMP_V_3
;
210 CLR_SEL_TEMP_V_0
; CLR_SEL_TEMP_V_1
;
211 CLR_SEL_TEMP_V_2
; SET_SEL_TEMP_V_3
;
214 SET_SEL_TEMP_V_0
; CLR_SEL_TEMP_V_1
;
215 SET_SEL_TEMP_V_2
; CLR_SEL_TEMP_V_3
;
221 u16
tsc2000_read_channel (unsigned int channel
)
225 tsc2000_set_mux(channel
);
226 udelay(20 * TSC2000_DELAY_BASE
);
228 tsc2000_write(TSC2000_REG_ADC
, 0x2036);
229 adc_wait_conversion_done ();
230 res
= tsc2000_read(TSC2000_REG_AUX1
);
235 s32
tsc2000_contact_temp (void)
237 long adc_pt1000
, offset
;
243 tsc2000_set_range (3);
246 * Because of sporadic "jumps" in the measured adc values every
247 * channel is read two times. If there is a significant difference
248 * between the two measurements, then print an error and do a third
249 * measurement, because it is very unlikely that a successive third
250 * measurement goes also wrong.
252 temp1
= tsc2000_read_channel (14);
253 temp2
= tsc2000_read_channel (14);
254 if (abs(temp2
- temp1
) < MAX_DEVIATION
)
257 printf ("%s: read adc value (channel 14) exceeded max allowed "
258 "deviation: %d * 0.0276 °C\n",
259 __FUNCTION__
, MAX_DEVIATION
);
260 printf ("adc value 1: %ld DIGITs\nadc value 2: %ld DIGITs\n",
262 adc_pt1000
= tsc2000_read_channel (14);
263 printf ("use (third read) adc value: adc_pt1000 = "
264 "%ld DIGITs\n", adc_pt1000
);
266 debug ("read channel 14 (pt1000 adc value): %ld\n", adc_pt1000
);
268 temp1
= tsc2000_read_channel (15);
269 temp2
= tsc2000_read_channel (15);
270 if (abs(temp2
- temp1
) < MAX_DEVIATION
)
273 printf ("%s: read adc value (channel 15) exceeded max allowed "
274 "deviation: %d * 0.0276 °C\n",
275 __FUNCTION__
, MAX_DEVIATION
);
276 printf ("adc value 1: %ld DIGITs\nadc value 2: %ld DIGITs\n",
278 offset
= tsc2000_read_channel (15);
279 printf ("use (third read) adc value: offset = %ld DIGITs\n",
282 debug ("read channel 15 (offset): %ld\n", offset
);
285 * Formula for calculating voltage drop on PT1000 resistor: u_pt1000 =
286 * x_range3 * (adc_raw - offset) / 10. Formula to calculate x_range3:
287 * x_range3 = (2500 * (1000000 + err_vref + err_amp3)) / (4095*6). The
288 * error correction Values err_vref and err_amp3 are assumed as 0 in
289 * u-boot, because this could cause only a very small error (< 1%).
291 u_pt1000
= (101750 * (adc_pt1000
- offset
)) / 10;
292 debug ("u_pt1000: %ld\n", u_pt1000
);
294 if (tsc2000_interpolate(u_pt1000
, Pt1000_temp_table
,
295 &contact_temp
) == -1) {
296 printf ("%s: error interpolating PT1000 vlaue\n",
300 debug ("contact_temp: %ld\n", contact_temp
);
306 void tsc2000_reg_init (void)
308 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
310 tsc2000_write(TSC2000_REG_ADC
, 0x2036);
311 tsc2000_write(TSC2000_REG_REF
, 0x0011);
312 tsc2000_write(TSC2000_REG_DACCTL
, 0x0000);
328 tsc2000_set_range(0);
332 int tsc2000_interpolate(long value
, long data
[][2], long *result
)
336 /* the data is sorted and the first element is upper
337 * limit so we can easily check for out-of-band values
339 if (data
[0][0] < value
|| data
[1][0] > value
)
343 while (data
[i
][0] < value
)
346 /* To prevent overflow we have to store the intermediate
347 result in 'long long'.
350 *result
= data
[i
-1][1] +
351 ((unsigned long long)(data
[i
][1] - data
[i
-1][1])
352 * (unsigned long long)(value
- data
[i
-1][0]))
353 / (data
[i
][0] - data
[i
-1][0]);
359 void adc_wait_conversion_done(void)
361 while (!(tsc2000_read(TSC2000_REG_ADC
) & (1 << 14)));