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,
29 #include <asm/arch/s3c24x0_cpu.h>
34 #include "Pt1000_temp_data.h"
37 #define abs(value) (((value) < 0) ? ((value)*-1) : (value))
40 * Maximal allowed deviation between two immediate meassurments of an analog
41 * thermo channel. 1 DIGIT = 0.0276 °C. This is used to filter sporadic
42 * "jumps" in measurment.
44 #define MAX_DEVIATION 18 /* unit: DIGITs of adc; 18 DIGIT = 0.5 °C */
46 void tsc2000_spi_init(void)
48 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
49 struct s3c24x0_spi * const spi = s3c24x0_get_base_spi();
52 /* Configure I/O ports. */
53 gpio->PDCON = (gpio->PDCON & 0xF3FFFF) | 0x040000;
54 gpio->PGCON = (gpio->PGCON & 0x0F3FFF) | 0x008000;
55 gpio->PGCON = (gpio->PGCON & 0x0CFFFF) | 0x020000;
56 gpio->PGCON = (gpio->PGCON & 0x03FFFF) | 0x080000;
60 spi->ch[0].SPPRE = 0x1F; /* Baud-rate ca. 514kHz */
61 spi->ch[0].SPPIN = 0x01; /* SPI-MOSI holds Level after last bit */
62 spi->ch[0].SPCON = 0x1A; /* Polling, Prescaler, Master, CPOL=0,
65 /* Dummy byte ensures clock to be low. */
66 for (i = 0; i < 10; i++) {
67 spi->ch[0].SPTDAT = 0xFF;
69 spi_wait_transmit_done();
73 void spi_wait_transmit_done(void)
75 struct s3c24x0_spi * const spi = s3c24x0_get_base_spi();
77 while (!(spi->ch[0].SPSTA & 0x01)); /* wait until transfer is done */
81 void tsc2000_write(unsigned short reg, unsigned short data)
83 struct s3c24x0_spi * const spi = s3c24x0_get_base_spi();
88 spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;
89 spi_wait_transmit_done();
90 spi->ch[0].SPTDAT = (command & 0x00FF);
91 spi_wait_transmit_done();
92 spi->ch[0].SPTDAT = (data & 0xFF00) >> 8;
93 spi_wait_transmit_done();
94 spi->ch[0].SPTDAT = (data & 0x00FF);
95 spi_wait_transmit_done();
101 unsigned short tsc2000_read (unsigned short reg)
103 unsigned short command, data;
104 struct s3c24x0_spi * const spi = s3c24x0_get_base_spi();
107 command = 0x8000 | reg;
109 spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;
110 spi_wait_transmit_done();
111 spi->ch[0].SPTDAT = (command & 0x00FF);
112 spi_wait_transmit_done();
114 spi->ch[0].SPTDAT = 0xFF;
115 spi_wait_transmit_done();
116 data = spi->ch[0].SPRDAT;
117 spi->ch[0].SPTDAT = 0xFF;
118 spi_wait_transmit_done();
121 return (spi->ch[0].SPRDAT & 0x0FF) | (data << 8);
125 void tsc2000_set_mux (unsigned int channel)
127 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
129 CLR_MUX1_ENABLE; CLR_MUX2_ENABLE;
130 CLR_MUX3_ENABLE; CLR_MUX4_ENABLE;
202 void tsc2000_set_range (unsigned int range)
204 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
208 CLR_SEL_TEMP_V_0; SET_SEL_TEMP_V_1;
209 CLR_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
212 CLR_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
213 CLR_SEL_TEMP_V_2; SET_SEL_TEMP_V_3;
216 SET_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
217 SET_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
223 u16 tsc2000_read_channel (unsigned int channel)
227 tsc2000_set_mux(channel);
228 udelay(20 * TSC2000_DELAY_BASE);
230 tsc2000_write(TSC2000_REG_ADC, 0x2036);
231 adc_wait_conversion_done ();
232 res = tsc2000_read(TSC2000_REG_AUX1);
237 s32 tsc2000_contact_temp (void)
239 long adc_pt1000, offset;
245 tsc2000_set_range (3);
248 * Because of sporadic "jumps" in the measured adc values every
249 * channel is read two times. If there is a significant difference
250 * between the two measurements, then print an error and do a third
251 * measurement, because it is very unlikely that a successive third
252 * measurement goes also wrong.
254 temp1 = tsc2000_read_channel (14);
255 temp2 = tsc2000_read_channel (14);
256 if (abs(temp2 - temp1) < MAX_DEVIATION)
259 printf ("%s: read adc value (channel 14) exceeded max allowed "
260 "deviation: %d * 0.0276 °C\n",
261 __FUNCTION__, MAX_DEVIATION);
262 printf ("adc value 1: %ld DIGITs\nadc value 2: %ld DIGITs\n",
264 adc_pt1000 = tsc2000_read_channel (14);
265 printf ("use (third read) adc value: adc_pt1000 = "
266 "%ld DIGITs\n", adc_pt1000);
268 debug ("read channel 14 (pt1000 adc value): %ld\n", adc_pt1000);
270 temp1 = tsc2000_read_channel (15);
271 temp2 = tsc2000_read_channel (15);
272 if (abs(temp2 - temp1) < MAX_DEVIATION)
275 printf ("%s: read adc value (channel 15) exceeded max allowed "
276 "deviation: %d * 0.0276 °C\n",
277 __FUNCTION__, MAX_DEVIATION);
278 printf ("adc value 1: %ld DIGITs\nadc value 2: %ld DIGITs\n",
280 offset = tsc2000_read_channel (15);
281 printf ("use (third read) adc value: offset = %ld DIGITs\n",
284 debug ("read channel 15 (offset): %ld\n", offset);
287 * Formula for calculating voltage drop on PT1000 resistor: u_pt1000 =
288 * x_range3 * (adc_raw - offset) / 10. Formula to calculate x_range3:
289 * x_range3 = (2500 * (1000000 + err_vref + err_amp3)) / (4095*6). The
290 * error correction Values err_vref and err_amp3 are assumed as 0 in
291 * u-boot, because this could cause only a very small error (< 1%).
293 u_pt1000 = (101750 * (adc_pt1000 - offset)) / 10;
294 debug ("u_pt1000: %ld\n", u_pt1000);
296 if (tsc2000_interpolate(u_pt1000, Pt1000_temp_table,
297 &contact_temp) == -1) {
298 printf ("%s: error interpolating PT1000 vlaue\n",
302 debug ("contact_temp: %ld\n", contact_temp);
308 void tsc2000_reg_init (void)
310 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
312 tsc2000_write(TSC2000_REG_ADC, 0x2036);
313 tsc2000_write(TSC2000_REG_REF, 0x0011);
314 tsc2000_write(TSC2000_REG_DACCTL, 0x0000);
330 tsc2000_set_range(0);
334 int tsc2000_interpolate(long value, long data[][2], long *result)
337 unsigned long long val;
339 /* the data is sorted and the first element is upper
340 * limit so we can easily check for out-of-band values
342 if (data[0][0] < value || data[1][0] > value)
346 while (data[i][0] < value)
349 /* To prevent overflow we have to store the intermediate
350 result in 'long long'.
353 val = ((unsigned long long)(data[i][1] - data[i-1][1])
354 * (unsigned long long)(value - data[i-1][0]));
355 do_div(val, (data[i][0] - data[i-1][0]));
356 *result = data[i-1][1] + val;
362 void adc_wait_conversion_done(void)
364 while (!(tsc2000_read(TSC2000_REG_ADC) & (1 << 14)));