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