]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/trab/tsc2000.c
* Patches by Xianghua Xiao, 15 Oct 2003:
[karo-tx-uboot.git] / board / trab / tsc2000.c
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 "tsc2000.h"
31
32 #include "Pt1000_temp_data.h"
33
34 void spi_init(void)
35 {
36         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
37         S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
38         int i;
39
40         /* Configure I/O ports. */
41         gpio->PDCON = (gpio->PDCON & 0xF3FFFF) | 0x040000;
42         gpio->PGCON = (gpio->PGCON & 0x0F3FFF) | 0x008000;
43         gpio->PGCON = (gpio->PGCON & 0x0CFFFF) | 0x020000;
44         gpio->PGCON = (gpio->PGCON & 0x03FFFF) | 0x080000;
45
46         CLR_CS_TOUCH();
47
48         spi->ch[0].SPPRE = 0x1F; /* Baud-rate ca. 514kHz */
49         spi->ch[0].SPPIN = 0x01; /* SPI-MOSI holds Level after last bit */
50         spi->ch[0].SPCON = 0x1A; /* Polling, Prescaler, Master, CPOL=0,
51                                     CPHA=1 */
52
53         /* Dummy byte ensures clock to be low. */
54         for (i = 0; i < 10; i++) {
55                 spi->ch[0].SPTDAT = 0xFF;
56         }
57         spi_wait_transmit_done();
58 }
59
60
61 void spi_wait_transmit_done(void)
62 {
63         S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
64
65         while (!(spi->ch[0].SPSTA & 0x01)); /* wait until transfer is done */
66 }
67
68
69 void tsc2000_write(unsigned short reg, unsigned short data)
70 {
71         S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
72         unsigned int command;
73
74         SET_CS_TOUCH();
75         command = reg;
76         spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;
77         spi_wait_transmit_done();
78         spi->ch[0].SPTDAT = (command & 0x00FF);
79         spi_wait_transmit_done();
80         spi->ch[0].SPTDAT = (data & 0xFF00) >> 8;
81         spi_wait_transmit_done();
82         spi->ch[0].SPTDAT = (data & 0x00FF);
83         spi_wait_transmit_done();
84
85         CLR_CS_TOUCH();
86 }
87
88
89 unsigned short tsc2000_read (unsigned short reg)
90 {
91         unsigned short command, data;
92         S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
93
94         SET_CS_TOUCH();
95         command = 0x8000 | reg;
96
97         spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;
98         spi_wait_transmit_done();
99         spi->ch[0].SPTDAT = (command & 0x00FF);
100         spi_wait_transmit_done();
101
102         spi->ch[0].SPTDAT = 0xFF;
103         spi_wait_transmit_done();
104         data = spi->ch[0].SPRDAT;
105         spi->ch[0].SPTDAT = 0xFF;
106         spi_wait_transmit_done();
107
108         CLR_CS_TOUCH();
109         return (spi->ch[0].SPRDAT & 0x0FF) | (data << 8);
110 }
111
112
113 void tsc2000_set_mux (unsigned int channel)
114 {
115         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
116
117         CLR_MUX1_ENABLE; CLR_MUX2_ENABLE;
118         CLR_MUX3_ENABLE; CLR_MUX4_ENABLE;
119         switch (channel) {
120         case 0:
121                 CLR_MUX0; CLR_MUX1;
122                 SET_MUX1_ENABLE;
123                 break;
124         case 1:
125                 SET_MUX0; CLR_MUX1;
126                 SET_MUX1_ENABLE;
127                 break;
128         case 2:
129                 CLR_MUX0; SET_MUX1;
130                 SET_MUX1_ENABLE;
131                 break;
132         case 3:
133                 SET_MUX0; SET_MUX1;
134                 SET_MUX1_ENABLE;
135                 break;
136         case 4:
137                 CLR_MUX0; CLR_MUX1;
138                 SET_MUX2_ENABLE;
139                 break;
140         case 5:
141                 SET_MUX0; CLR_MUX1;
142                 SET_MUX2_ENABLE;
143                 break;
144         case 6:
145                 CLR_MUX0; SET_MUX1;
146                 SET_MUX2_ENABLE;
147                 break;
148         case 7:
149                 SET_MUX0; SET_MUX1;
150                 SET_MUX2_ENABLE;
151                 break;
152         case 8:
153                 CLR_MUX0; CLR_MUX1;
154                 SET_MUX3_ENABLE;
155                 break;
156         case 9:
157                 SET_MUX0; CLR_MUX1;
158                 SET_MUX3_ENABLE;
159                 break;
160         case 10:
161                 CLR_MUX0; SET_MUX1;
162                 SET_MUX3_ENABLE;
163                 break;
164         case 11:
165                 SET_MUX0; SET_MUX1;
166                 SET_MUX3_ENABLE;
167                 break;
168         case 12:
169                 CLR_MUX0; CLR_MUX1;
170                 SET_MUX4_ENABLE;
171                 break;
172         case 13:
173                 SET_MUX0; CLR_MUX1;
174                 SET_MUX4_ENABLE;
175                 break;
176         case 14:
177                 CLR_MUX0; SET_MUX1;
178                 SET_MUX4_ENABLE;
179                 break;
180         case 15:
181                 SET_MUX0; SET_MUX1;
182                 SET_MUX4_ENABLE;
183                 break;
184         default:
185                 CLR_MUX0; CLR_MUX1;
186         }
187 }
188
189
190 void tsc2000_set_range (unsigned int range)
191 {
192         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
193
194         switch (range) {
195         case 1:
196                 CLR_SEL_TEMP_V_0; SET_SEL_TEMP_V_1;
197                 CLR_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
198                 break;
199         case 2:
200                 CLR_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
201                 CLR_SEL_TEMP_V_2; SET_SEL_TEMP_V_3;
202                 break;
203         case 3:
204                 SET_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
205                 SET_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
206                 break;
207         }
208 }
209
210
211 u16 tsc2000_read_channel (unsigned int channel)
212 {
213         u16 res;
214
215         tsc2000_set_mux(channel);
216         udelay(3 * TSC2000_DELAY_BASE);
217
218         tsc2000_write(TSC2000_REG_ADC, 0x2036);
219         adc_wait_conversion_done ();
220         res = tsc2000_read(TSC2000_REG_AUX1);
221         return res;
222 }
223
224
225 s32 tsc2000_contact_temp (void)
226 {
227         long adc_pt1000, offset;
228         long u_pt1000;
229         long contact_temp;
230
231
232         tsc2000_reg_init ();
233         tsc2000_set_range (3);
234
235         adc_pt1000 = tsc2000_read_channel (14);
236         debug ("read channel 14 (pt1000 adc value): %ld\n", adc_pt1000);
237
238         offset = tsc2000_read_channel (15);
239         debug ("read channel 15 (offset): %ld\n", offset);
240
241         /*
242          * Formula for calculating voltage drop on PT1000 resistor: u_pt1000 =
243          * x_range3 * (adc_raw - offset) / 10. Formula to calculate x_range3:
244          * x_range3 = (2500 * (1000000 + err_vref + err_amp3)) / (4095*6). The
245          * error correction Values err_vref and err_amp3 are assumed as 0 in
246          * u-boot, because this could cause only a very small error (< 1%).
247          */
248         u_pt1000 = (101750 * (adc_pt1000 - offset)) / 10;
249         debug ("u_pt1000: %ld\n", u_pt1000);
250
251         if (tsc2000_interpolate(u_pt1000, Pt1000_temp_table,
252                                 &contact_temp) == -1) {
253                 printf ("%s: error interpolating PT1000 vlaue\n",
254                          __FUNCTION__);
255                 return (-1000);
256         }
257         debug ("contact_temp: %ld\n", contact_temp);
258
259         return contact_temp;
260 }
261
262
263 void tsc2000_reg_init (void)
264 {
265         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
266
267         tsc2000_write(TSC2000_REG_ADC, 0x2036);
268         tsc2000_write(TSC2000_REG_REF, 0x0011);
269         tsc2000_write(TSC2000_REG_DACCTL, 0x0000);
270
271         CON_MUX0;
272         CON_MUX1;
273
274         CON_MUX1_ENABLE;
275         CON_MUX2_ENABLE;
276         CON_MUX3_ENABLE;
277         CON_MUX4_ENABLE;
278
279         CON_SEL_TEMP_V_0;
280         CON_SEL_TEMP_V_1;
281         CON_SEL_TEMP_V_2;
282         CON_SEL_TEMP_V_3;
283
284         tsc2000_set_mux(0);
285         tsc2000_set_range(0);
286 }
287
288
289 int tsc2000_interpolate(long value, long data[][2], long *result)
290 {
291         int i;
292
293         /* the data is sorted and the first element is upper
294          * limit so we can easily check for out-of-band values
295          */
296         if (data[0][0] < value || data[1][0] > value)
297                 return -1;
298
299         i = 1;
300         while (data[i][0] < value)
301                 i++;
302
303         /* To prevent overflow we have to store the intermediate
304            result in 'long long'.
305         */
306
307         *result = data[i-1][1] +
308                 ((unsigned long long)(data[i][1] - data[i-1][1])
309                  * (unsigned long long)(value - data[i-1][0]))
310                 / (data[i][0] - data[i-1][0]);
311
312         return 0;
313 }
314
315
316 void adc_wait_conversion_done(void)
317 {
318         while (!(tsc2000_read(TSC2000_REG_ADC) & (1 << 14)));
319 }