Merge with /home/hs/U-Boot/u-boot-dev
[platform/kernel/u-boot.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 /* helper function */
35 #define abs(value) (((value) < 0) ? ((value)*-1) : (value))
36
37 /*
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.
41  */
42 #define MAX_DEVIATION   18      /* unit: DIGITs of adc; 18 DIGIT = 0.5 °C */
43
44 void spi_init(void)
45 {
46         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
47         S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
48         int i;
49
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;
55
56         CLR_CS_TOUCH();
57
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,
61                                     CPHA=1 */
62
63         /* Dummy byte ensures clock to be low. */
64         for (i = 0; i < 10; i++) {
65                 spi->ch[0].SPTDAT = 0xFF;
66         }
67         spi_wait_transmit_done();
68 }
69
70
71 void spi_wait_transmit_done(void)
72 {
73         S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
74
75         while (!(spi->ch[0].SPSTA & 0x01)); /* wait until transfer is done */
76 }
77
78
79 void tsc2000_write(unsigned short reg, unsigned short data)
80 {
81         S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
82         unsigned int command;
83
84         SET_CS_TOUCH();
85         command = reg;
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();
94
95         CLR_CS_TOUCH();
96 }
97
98
99 unsigned short tsc2000_read (unsigned short reg)
100 {
101         unsigned short command, data;
102         S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
103
104         SET_CS_TOUCH();
105         command = 0x8000 | reg;
106
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();
111
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();
117
118         CLR_CS_TOUCH();
119         return (spi->ch[0].SPRDAT & 0x0FF) | (data << 8);
120 }
121
122
123 void tsc2000_set_mux (unsigned int channel)
124 {
125         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
126
127         CLR_MUX1_ENABLE; CLR_MUX2_ENABLE;
128         CLR_MUX3_ENABLE; CLR_MUX4_ENABLE;
129         switch (channel) {
130         case 0:
131                 CLR_MUX0; CLR_MUX1;
132                 SET_MUX1_ENABLE;
133                 break;
134         case 1:
135                 SET_MUX0; CLR_MUX1;
136                 SET_MUX1_ENABLE;
137                 break;
138         case 2:
139                 CLR_MUX0; SET_MUX1;
140                 SET_MUX1_ENABLE;
141                 break;
142         case 3:
143                 SET_MUX0; SET_MUX1;
144                 SET_MUX1_ENABLE;
145                 break;
146         case 4:
147                 CLR_MUX0; CLR_MUX1;
148                 SET_MUX2_ENABLE;
149                 break;
150         case 5:
151                 SET_MUX0; CLR_MUX1;
152                 SET_MUX2_ENABLE;
153                 break;
154         case 6:
155                 CLR_MUX0; SET_MUX1;
156                 SET_MUX2_ENABLE;
157                 break;
158         case 7:
159                 SET_MUX0; SET_MUX1;
160                 SET_MUX2_ENABLE;
161                 break;
162         case 8:
163                 CLR_MUX0; CLR_MUX1;
164                 SET_MUX3_ENABLE;
165                 break;
166         case 9:
167                 SET_MUX0; CLR_MUX1;
168                 SET_MUX3_ENABLE;
169                 break;
170         case 10:
171                 CLR_MUX0; SET_MUX1;
172                 SET_MUX3_ENABLE;
173                 break;
174         case 11:
175                 SET_MUX0; SET_MUX1;
176                 SET_MUX3_ENABLE;
177                 break;
178         case 12:
179                 CLR_MUX0; CLR_MUX1;
180                 SET_MUX4_ENABLE;
181                 break;
182         case 13:
183                 SET_MUX0; CLR_MUX1;
184                 SET_MUX4_ENABLE;
185                 break;
186         case 14:
187                 CLR_MUX0; SET_MUX1;
188                 SET_MUX4_ENABLE;
189                 break;
190         case 15:
191                 SET_MUX0; SET_MUX1;
192                 SET_MUX4_ENABLE;
193                 break;
194         default:
195                 CLR_MUX0; CLR_MUX1;
196         }
197 }
198
199
200 void tsc2000_set_range (unsigned int range)
201 {
202         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
203
204         switch (range) {
205         case 1:
206                 CLR_SEL_TEMP_V_0; SET_SEL_TEMP_V_1;
207                 CLR_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
208                 break;
209         case 2:
210                 CLR_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
211                 CLR_SEL_TEMP_V_2; SET_SEL_TEMP_V_3;
212                 break;
213         case 3:
214                 SET_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
215                 SET_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
216                 break;
217         }
218 }
219
220
221 u16 tsc2000_read_channel (unsigned int channel)
222 {
223         u16 res;
224
225         tsc2000_set_mux(channel);
226         udelay(20 * TSC2000_DELAY_BASE);
227
228         tsc2000_write(TSC2000_REG_ADC, 0x2036);
229         adc_wait_conversion_done ();
230         res = tsc2000_read(TSC2000_REG_AUX1);
231         return res;
232 }
233
234
235 s32 tsc2000_contact_temp (void)
236 {
237         long adc_pt1000, offset;
238         long u_pt1000;
239         long contact_temp;
240         long temp1, temp2;
241
242         tsc2000_reg_init ();
243         tsc2000_set_range (3);
244
245         /*
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.
251          */
252         temp1 = tsc2000_read_channel (14);
253         temp2 = tsc2000_read_channel (14);
254         if (abs(temp2 - temp1) < MAX_DEVIATION)
255                 adc_pt1000 = temp2;
256         else {
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",
261                         temp1, temp2);
262                 adc_pt1000 = tsc2000_read_channel (14);
263                 printf ("use (third read) adc value: adc_pt1000 = "
264                         "%ld DIGITs\n", adc_pt1000);
265         }
266         debug ("read channel 14 (pt1000 adc value): %ld\n", adc_pt1000);
267
268         temp1 = tsc2000_read_channel (15);
269         temp2 = tsc2000_read_channel (15);
270         if (abs(temp2 - temp1) < MAX_DEVIATION)
271                 offset = temp2;
272         else {
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",
277                         temp1, temp2);
278                 offset = tsc2000_read_channel (15);
279                 printf ("use (third read) adc value: offset = %ld DIGITs\n",
280                         offset);
281         }
282         debug ("read channel 15 (offset): %ld\n", offset);
283
284         /*
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%).
290          */
291         u_pt1000 = (101750 * (adc_pt1000 - offset)) / 10;
292         debug ("u_pt1000: %ld\n", u_pt1000);
293
294         if (tsc2000_interpolate(u_pt1000, Pt1000_temp_table,
295                                 &contact_temp) == -1) {
296                 printf ("%s: error interpolating PT1000 vlaue\n",
297                          __FUNCTION__);
298                 return (-1000);
299         }
300         debug ("contact_temp: %ld\n", contact_temp);
301
302         return contact_temp;
303 }
304
305
306 void tsc2000_reg_init (void)
307 {
308         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
309
310         tsc2000_write(TSC2000_REG_ADC, 0x2036);
311         tsc2000_write(TSC2000_REG_REF, 0x0011);
312         tsc2000_write(TSC2000_REG_DACCTL, 0x0000);
313
314         CON_MUX0;
315         CON_MUX1;
316
317         CON_MUX1_ENABLE;
318         CON_MUX2_ENABLE;
319         CON_MUX3_ENABLE;
320         CON_MUX4_ENABLE;
321
322         CON_SEL_TEMP_V_0;
323         CON_SEL_TEMP_V_1;
324         CON_SEL_TEMP_V_2;
325         CON_SEL_TEMP_V_3;
326
327         tsc2000_set_mux(0);
328         tsc2000_set_range(0);
329 }
330
331
332 int tsc2000_interpolate(long value, long data[][2], long *result)
333 {
334         int i;
335
336         /* the data is sorted and the first element is upper
337          * limit so we can easily check for out-of-band values
338          */
339         if (data[0][0] < value || data[1][0] > value)
340                 return -1;
341
342         i = 1;
343         while (data[i][0] < value)
344                 i++;
345
346         /* To prevent overflow we have to store the intermediate
347            result in 'long long'.
348         */
349
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]);
354
355         return 0;
356 }
357
358
359 void adc_wait_conversion_done(void)
360 {
361         while (!(tsc2000_read(TSC2000_REG_ADC) & (1 << 14)));
362 }