blob: 940e12f25cf8d90ea9ae0b66b6adaca6beb158d1 [file] [log] [blame]
wdenkf5300ab2003-09-12 15:35:15 +00001/*
2 * (C) Copyright 2003
3 * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24#define DEBUG
25
26#include <common.h>
27#include <exports.h>
Peter Tyser561858e2008-11-03 09:30:59 -060028#include <timestamp.h>
kevin.morfitt@fearnside-systems.co.uk492fb1f2009-11-03 18:08:41 +090029#include <asm/arch/s3c2400.h>
wdenkf5300ab2003-09-12 15:35:15 +000030#include "tsc2000.h"
31#include "rs485.h"
32
wdenka0ff7f22003-10-09 13:16:55 +000033/*
34 * define, to wait for the touch to be pressed, before reading coordinates in
35 * command do_touch. If not defined, an error message is printed, when the
36 * command do_touch is invoked and the touch is not pressed within an specific
37 * interval.
38 */
wdenke86e5a02004-10-17 21:12:06 +000039#undef CONFIG_TOUCH_WAIT_PRESSED
wdenka0ff7f22003-10-09 13:16:55 +000040
41/* max time to wait for touch is pressed */
42#ifndef CONFIG_TOUCH_WAIT_PRESSED
43#define TOUCH_TIMEOUT 5
44#endif /* !CONFIG_TOUCH_WAIT_PRESSED */
45
wdenkf5300ab2003-09-12 15:35:15 +000046/* assignment of CPU internal ADC channels with TRAB hardware */
47#define VCC5V 2
48#define VCC12V 3
49
50/* CPLD-Register for controlling TRAB hardware functions */
51#define CPLD_BUTTONS ((volatile unsigned long *)0x04020000)
52#define CPLD_FILL_LEVEL ((volatile unsigned long *)0x04008000)
53#define CPLD_ROTARY_SWITCH ((volatile unsigned long *)0x04018000)
54#define CPLD_RS485_RE ((volatile unsigned long *)0x04028000)
55
56/* timer configuration bits for buzzer and PWM */
57#define START2 (1 << 12)
58#define UPDATE2 (1 << 13)
59#define INVERT2 (1 << 14)
60#define RELOAD2 (1 << 15)
61#define START3 (1 << 16)
62#define UPDATE3 (1 << 17)
63#define INVERT3 (1 << 18)
64#define RELOAD3 (1 << 19)
65
66#define PCLK 66000000
67#define BUZZER_FREQ 1000 /* frequency in Hz */
wdenkf5300ab2003-09-12 15:35:15 +000068#define PWM_FREQ 500
69
70
71/* definitions of I2C EEPROM device address */
72#define I2C_EEPROM_DEV_ADDR 0x54
73
74/* definition for touch panel calibration points */
75#define CALIB_TL 0 /* calibration point in (T)op (L)eft corner */
76#define CALIB_DR 1 /* calibration point in (D)own (R)ight corner */
77
wdenka0ff7f22003-10-09 13:16:55 +000078/* EEPROM address map */
wdenkf5300ab2003-09-12 15:35:15 +000079#define SERIAL_NUMBER 8
80#define TOUCH_X0 52
81#define TOUCH_Y0 54
82#define TOUCH_X1 56
83#define TOUCH_Y1 58
84#define CRC16 60
85
86/* EEPROM stuff */
87#define EEPROM_MAX_CRC_BUF 64
88
89/* RS485 stuff */
90#define RS485_MAX_RECEIVE_BUF_LEN 100
91
92/* Bit definitions for ADCCON */
93#define ADC_ENABLE_START 0x1
94#define ADC_READ_START 0x2
95#define ADC_STDBM 0x4
96#define ADC_INP_AIN0 (0x0 << 3)
97#define ADC_INP_AIN1 (0x1 << 3)
98#define ADC_INP_AIN2 (0x2 << 3)
99#define ADC_INP_AIN3 (0x3 << 3)
100#define ADC_INP_AIN4 (0x4 << 3)
101#define ADC_INP_AIN5 (0x5 << 3)
102#define ADC_INP_AIN6 (0x6 << 3)
103#define ADC_INP_AIN7 (0x7 << 3)
104#define ADC_PRSCEN 0x4000
105#define ADC_ECFLG 0x8000
106
107/* function test functions */
108int do_dip (void);
109int do_info (void);
110int do_vcc5v (void);
111int do_vcc12v (void);
112int do_buttons (void);
113int do_fill_level (void);
114int do_rotary_switch (void);
115int do_pressure (void);
116int do_v_bat (void);
117int do_vfd_id (void);
wdenka0ff7f22003-10-09 13:16:55 +0000118int do_buzzer (char **);
wdenkf5300ab2003-09-12 15:35:15 +0000119int do_led (char **);
120int do_full_bridge (char **);
121int do_dac (char **);
122int do_motor_contact (void);
123int do_motor (char **);
124int do_pwm (char **);
125int do_thermo (char **);
126int do_touch (char **);
127int do_rs485 (char **);
128int do_serial_number (char **);
129int do_crc16 (void);
wdenka0ff7f22003-10-09 13:16:55 +0000130int do_power_switch (void);
131int do_gain (char **);
132int do_eeprom (char **);
wdenkf5300ab2003-09-12 15:35:15 +0000133
134/* helper functions */
135static void adc_init (void);
136static int adc_read (unsigned int channel);
137static void print_identifier (void);
wdenka0ff7f22003-10-09 13:16:55 +0000138
139#ifdef CONFIG_TOUCH_WAIT_PRESSED
wdenkf5300ab2003-09-12 15:35:15 +0000140static void touch_wait_pressed (void);
wdenka0ff7f22003-10-09 13:16:55 +0000141#else
142static int touch_check_pressed (void);
143#endif /* CONFIG_TOUCH_WAIT_PRESSED */
144
wdenkf5300ab2003-09-12 15:35:15 +0000145static void touch_read_x_y (int *x, int *y);
146static int touch_write_clibration_values (int calib_point, int x, int y);
147static int rs485_send_line (const char *data);
148static int rs485_receive_chars (char *data, int timeout);
149static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
wdenka0ff7f22003-10-09 13:16:55 +0000150 unsigned int icnt);
wdenkf5300ab2003-09-12 15:35:15 +0000151
Jon Loeligerab3abcb2007-07-09 18:45:16 -0500152#if defined(CONFIG_CMD_I2C)
wdenka0ff7f22003-10-09 13:16:55 +0000153static int trab_eeprom_read (char **argv);
154static int trab_eeprom_write (char **argv);
155int i2c_write_multiple (uchar chip, uint addr, int alen, uchar *buffer,
156 int len);
157int i2c_read_multiple ( uchar chip, uint addr, int alen, uchar *buffer,
158 int len);
Jon Loeligerd39b5742007-07-10 10:48:22 -0500159#endif
wdenkf5300ab2003-09-12 15:35:15 +0000160
161/*
162 * TRAB board specific commands. Especially commands for burn-in and function
163 * test.
164 */
165
166int trab_fkt (int argc, char *argv[])
167{
wdenka0ff7f22003-10-09 13:16:55 +0000168 int i;
wdenkf5300ab2003-09-12 15:35:15 +0000169
wdenka0ff7f22003-10-09 13:16:55 +0000170 app_startup(argv);
171 if (get_version () != XF_VERSION) {
172 printf ("Wrong XF_VERSION. Please re-compile with actual "
173 "u-boot sources\n");
174 printf ("Example expects ABI version %d\n", XF_VERSION);
175 printf ("Actual U-Boot ABI version %d\n", (int)get_version());
176 return 1;
177 }
wdenkf5300ab2003-09-12 15:35:15 +0000178
wdenka0ff7f22003-10-09 13:16:55 +0000179 debug ("argc = %d\n", argc);
wdenkf5300ab2003-09-12 15:35:15 +0000180
181 for (i=0; i<=argc; ++i) {
182 debug ("argv[%d] = \"%s\"\n", i, argv[i] ? argv[i] : "<NULL>");
wdenka0ff7f22003-10-09 13:16:55 +0000183 }
wdenkf5300ab2003-09-12 15:35:15 +0000184
wdenka0ff7f22003-10-09 13:16:55 +0000185 adc_init ();
wdenkf5300ab2003-09-12 15:35:15 +0000186
187 switch (argc) {
188
189 case 0:
190 case 1:
191 break;
192
193 case 2:
194 if (strcmp (argv[1], "info") == 0) {
wdenka0ff7f22003-10-09 13:16:55 +0000195 return (do_info ());
wdenkf5300ab2003-09-12 15:35:15 +0000196 }
wdenka0ff7f22003-10-09 13:16:55 +0000197 if (strcmp (argv[1], "dip") == 0) {
198 return (do_dip ());
199 }
200 if (strcmp (argv[1], "vcc5v") == 0) {
201 return (do_vcc5v ());
202 }
203 if (strcmp (argv[1], "vcc12v") == 0) {
204 return (do_vcc12v ());
205 }
206 if (strcmp (argv[1], "buttons") == 0) {
207 return (do_buttons ());
208 }
209 if (strcmp (argv[1], "fill_level") == 0) {
210 return (do_fill_level ());
211 }
212 if (strcmp (argv[1], "rotary_switch") == 0) {
213 return (do_rotary_switch ());
214 }
215 if (strcmp (argv[1], "pressure") == 0) {
216 return (do_pressure ());
217 }
218 if (strcmp (argv[1], "v_bat") == 0) {
219 return (do_v_bat ());
220 }
221 if (strcmp (argv[1], "vfd_id") == 0) {
222 return (do_vfd_id ());
223 }
224 if (strcmp (argv[1], "motor_contact") == 0) {
225 return (do_motor_contact ());
226 }
227 if (strcmp (argv[1], "crc16") == 0) {
228 return (do_crc16 ());
229 }
230 if (strcmp (argv[1], "power_switch") == 0) {
231 return (do_power_switch ());
232 }
233 break;
wdenkf5300ab2003-09-12 15:35:15 +0000234
235 case 3:
wdenka0ff7f22003-10-09 13:16:55 +0000236 if (strcmp (argv[1], "full_bridge") == 0) {
237 return (do_full_bridge (argv));
238 }
239 if (strcmp (argv[1], "dac") == 0) {
240 return (do_dac (argv));
241 }
242 if (strcmp (argv[1], "motor") == 0) {
243 return (do_motor (argv));
244 }
245 if (strcmp (argv[1], "pwm") == 0) {
246 return (do_pwm (argv));
247 }
248 if (strcmp (argv[1], "thermo") == 0) {
249 return (do_thermo (argv));
250 }
251 if (strcmp (argv[1], "touch") == 0) {
252 return (do_touch (argv));
253 }
254 if (strcmp (argv[1], "serial_number") == 0) {
255 return (do_serial_number (argv));
256 }
257 if (strcmp (argv[1], "buzzer") == 0) {
258 return (do_buzzer (argv));
259 }
260 if (strcmp (argv[1], "gain") == 0) {
261 return (do_gain (argv));
262 }
263 break;
wdenkf5300ab2003-09-12 15:35:15 +0000264
wdenka0ff7f22003-10-09 13:16:55 +0000265 case 4:
266 if (strcmp (argv[1], "led") == 0) {
267 return (do_led (argv));
268 }
269 if (strcmp (argv[1], "rs485") == 0) {
270 return (do_rs485 (argv));
271 }
272 if (strcmp (argv[1], "serial_number") == 0) {
273 return (do_serial_number (argv));
274 }
275 break;
276
277 case 5:
278 if (strcmp (argv[1], "eeprom") == 0) {
279 return (do_eeprom (argv));
280 }
281 break;
282
283 case 6:
284 if (strcmp (argv[1], "eeprom") == 0) {
285 return (do_eeprom (argv));
286 }
287 break;
wdenkf5300ab2003-09-12 15:35:15 +0000288
289 default:
290 break;
291 }
292
293 printf ("Usage:\n<command> <parameter1> <parameter2> ...\n");
wdenka0ff7f22003-10-09 13:16:55 +0000294 return 1;
wdenkf5300ab2003-09-12 15:35:15 +0000295}
296
Wolfgang Denk6cdadcb2008-12-16 16:22:50 +0100297void hang (void)
298{
299 puts ("### ERROR ### Please RESET the board ###\n");
300 for (;;);
301}
302
wdenkf5300ab2003-09-12 15:35:15 +0000303int do_info (void)
304{
wdenka0ff7f22003-10-09 13:16:55 +0000305 printf ("Stand-alone application for TRAB board function test\n");
Peter Tyser561858e2008-11-03 09:30:59 -0600306 printf ("Built: %s at %s\n", U_BOOT_DATE, U_BOOT_TIME);
wdenkf5300ab2003-09-12 15:35:15 +0000307
308 return 0;
309}
310
311int do_dip (void)
312{
wdenka0ff7f22003-10-09 13:16:55 +0000313 unsigned int result = 0;
314 int adc_val;
315 int i;
wdenkf5300ab2003-09-12 15:35:15 +0000316
317 /***********************************************************
318 DIP switch connection (according to wa4-cpu.sp.301.pdf, page 3):
319 SW1 - AIN4
320 SW2 - AIN5
321 SW3 - AIN6
322 SW4 - AIN7
323
324 "On" DIP switch position short-circuits the voltage from
325 the input channel (i.e. '0' conversion result means "on").
326 *************************************************************/
327
328 for (i = 7; i > 3; i--) {
329
wdenka0ff7f22003-10-09 13:16:55 +0000330 if ((adc_val = adc_read (i)) == -1) {
331 printf ("Channel %d could not be read\n", i);
332 return 1;
333 }
wdenkf5300ab2003-09-12 15:35:15 +0000334
335 /*
336 * Input voltage (switch open) is 1.8 V.
337 * (Vin_High/VRef)*adc_res = (1,8V/2,5V)*1023) = 736
338 * Set trigger at halve that value.
339 */
340 if (adc_val < 368)
wdenka0ff7f22003-10-09 13:16:55 +0000341 result |= (1 << (i-4));
342 }
wdenkf5300ab2003-09-12 15:35:15 +0000343
wdenka0ff7f22003-10-09 13:16:55 +0000344 /* print result to console */
345 print_identifier ();
346 for (i = 0; i < 4; i++) {
347 if ((result & (1 << i)) == 0)
348 printf("0");
349 else
350 printf("1");
351 }
352 printf("\n");
wdenkf5300ab2003-09-12 15:35:15 +0000353
354 return 0;
355}
356
357
358int do_vcc5v (void)
359{
wdenka0ff7f22003-10-09 13:16:55 +0000360 int result;
wdenkf5300ab2003-09-12 15:35:15 +0000361
wdenka0ff7f22003-10-09 13:16:55 +0000362 /* VCC5V is connected to channel 2 */
wdenkf5300ab2003-09-12 15:35:15 +0000363
wdenka0ff7f22003-10-09 13:16:55 +0000364 if ((result = adc_read (VCC5V)) == -1) {
365 printf ("VCC5V could not be read\n");
366 return 1;
367 }
wdenkf5300ab2003-09-12 15:35:15 +0000368
wdenka0ff7f22003-10-09 13:16:55 +0000369 /*
370 * Calculate voltage value. Split in two parts because there is no
371 * floating point support. VCC5V is connected over an resistor divider:
372 * VCC5V=ADCval*2,5V/1023*(10K+30K)/10K.
373 */
374 print_identifier ();
375 printf ("%d", (result & 0x3FF)* 10 / 1023);
376 printf (".%d", ((result & 0x3FF)* 10 % 1023)* 10 / 1023);
377 printf ("%d V\n", (((result & 0x3FF) * 10 % 1023 ) * 10 % 1023)
378 * 10 / 1024);
wdenkf5300ab2003-09-12 15:35:15 +0000379
380 return 0;
381}
382
383
384int do_vcc12v (void)
385{
wdenka0ff7f22003-10-09 13:16:55 +0000386 int result;
wdenkf5300ab2003-09-12 15:35:15 +0000387
wdenka0ff7f22003-10-09 13:16:55 +0000388 if ((result = adc_read (VCC12V)) == -1) {
389 printf ("VCC12V could not be read\n");
390 return 1;
391 }
wdenkf5300ab2003-09-12 15:35:15 +0000392
wdenka0ff7f22003-10-09 13:16:55 +0000393 /*
394 * Calculate voltage value. Split in two parts because there is no
395 * floating point support. VCC5V is connected over an resistor divider:
396 * VCC12V=ADCval*2,5V/1023*(30K+270K)/30K.
397 */
398 print_identifier ();
399 printf ("%d", (result & 0x3FF)* 25 / 1023);
400 printf (".%d V\n", ((result & 0x3FF)* 25 % 1023) * 10 / 1023);
wdenkf5300ab2003-09-12 15:35:15 +0000401
wdenka0ff7f22003-10-09 13:16:55 +0000402 return 0;
wdenkf5300ab2003-09-12 15:35:15 +0000403}
404
405static int adc_read (unsigned int channel)
406{
wdenka0ff7f22003-10-09 13:16:55 +0000407 int j = 1000; /* timeout value for wait loop in us */
408 int result;
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900409 struct s3c2400_adc *padc;
wdenkf5300ab2003-09-12 15:35:15 +0000410
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900411 padc = s3c2400_get_base_adc();
wdenka0ff7f22003-10-09 13:16:55 +0000412 channel &= 0x7;
wdenkf5300ab2003-09-12 15:35:15 +0000413
wdenka0ff7f22003-10-09 13:16:55 +0000414 padc->ADCCON &= ~ADC_STDBM; /* select normal mode */
wdenkf5300ab2003-09-12 15:35:15 +0000415 padc->ADCCON &= ~(0x7 << 3); /* clear the channel bits */
wdenka0ff7f22003-10-09 13:16:55 +0000416 padc->ADCCON |= ((channel << 3) | ADC_ENABLE_START);
wdenkf5300ab2003-09-12 15:35:15 +0000417
wdenka0ff7f22003-10-09 13:16:55 +0000418 while (j--) {
419 if ((padc->ADCCON & ADC_ENABLE_START) == 0)
420 break;
421 udelay (1);
422 }
wdenkf5300ab2003-09-12 15:35:15 +0000423
wdenka0ff7f22003-10-09 13:16:55 +0000424 if (j == 0) {
425 printf("%s: ADC timeout\n", __FUNCTION__);
426 padc->ADCCON |= ADC_STDBM; /* select standby mode */
427 return -1;
428 }
wdenkf5300ab2003-09-12 15:35:15 +0000429
wdenka0ff7f22003-10-09 13:16:55 +0000430 result = padc->ADCDAT & 0x3FF;
wdenkf5300ab2003-09-12 15:35:15 +0000431
wdenka0ff7f22003-10-09 13:16:55 +0000432 padc->ADCCON |= ADC_STDBM; /* select standby mode */
wdenkf5300ab2003-09-12 15:35:15 +0000433
wdenka0ff7f22003-10-09 13:16:55 +0000434 debug ("%s: channel %d, result[DIGIT]=%d\n", __FUNCTION__,
435 (padc->ADCCON >> 3) & 0x7, result);
wdenkf5300ab2003-09-12 15:35:15 +0000436
wdenka0ff7f22003-10-09 13:16:55 +0000437 /*
438 * Wait for ADC to be ready for next conversion. This delay value was
439 * estimated, because the datasheet does not specify a value.
440 */
441 udelay (1000);
442
443 return (result);
wdenkf5300ab2003-09-12 15:35:15 +0000444}
445
446
447static void adc_init (void)
448{
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900449 struct s3c2400_adc *padc;
wdenkf5300ab2003-09-12 15:35:15 +0000450
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900451 padc = s3c2400_get_base_adc();
wdenkf5300ab2003-09-12 15:35:15 +0000452
453 padc->ADCCON &= ~(0xff << 6); /* clear prescaler bits */
454 padc->ADCCON |= ((65 << 6) | ADC_PRSCEN); /* set prescaler */
455
wdenka0ff7f22003-10-09 13:16:55 +0000456 /*
457 * Wait some time to avoid problem with very first call of
458 * adc_read(). Without * this delay, sometimes the first read adc
459 * value is 0. Perhaps because the * adjustment of prescaler takes
460 * some clock cycles?
461 */
462 udelay (1000);
463
464 return;
wdenkf5300ab2003-09-12 15:35:15 +0000465}
466
467
468int do_buttons (void)
469{
wdenka0ff7f22003-10-09 13:16:55 +0000470 int result;
471 int i;
wdenkf5300ab2003-09-12 15:35:15 +0000472
wdenka0ff7f22003-10-09 13:16:55 +0000473 result = *CPLD_BUTTONS; /* read CPLD */
474 debug ("%s: cpld_taster (32 bit) %#x\n", __FUNCTION__, result);
wdenkf5300ab2003-09-12 15:35:15 +0000475
wdenka0ff7f22003-10-09 13:16:55 +0000476 /* print result to console */
477 print_identifier ();
478 for (i = 16; i <= 19; i++) {
479 if ((result & (1 << i)) == 0)
480 printf("0");
481 else
482 printf("1");
483 }
484 printf("\n");
485 return 0;
486}
487
488
489int do_power_switch (void)
490{
491 int result;
492
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900493 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
wdenka0ff7f22003-10-09 13:16:55 +0000494
495 /* configure GPE7 as input */
496 gpio->PECON &= ~(0x3 << (2 * 7));
497
498 /* signal GPE7 from power switch is low active: 0=on , 1=off */
499 result = ((gpio->PEDAT & (1 << 7)) == (1 << 7)) ? 0 : 1;
500
501 print_identifier ();
502 printf("%d\n", result);
wdenkf5300ab2003-09-12 15:35:15 +0000503 return 0;
504}
505
506
507int do_fill_level (void)
508{
wdenka0ff7f22003-10-09 13:16:55 +0000509 int result;
wdenkf5300ab2003-09-12 15:35:15 +0000510
wdenka0ff7f22003-10-09 13:16:55 +0000511 result = *CPLD_FILL_LEVEL; /* read CPLD */
512 debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
wdenkf5300ab2003-09-12 15:35:15 +0000513
wdenka0ff7f22003-10-09 13:16:55 +0000514 /* print result to console */
515 print_identifier ();
516 if ((result & (1 << 16)) == 0)
517 printf("0\n");
518 else
519 printf("1\n");
wdenkf5300ab2003-09-12 15:35:15 +0000520 return 0;
521}
522
523
524int do_rotary_switch (void)
525{
wdenka0ff7f22003-10-09 13:16:55 +0000526 int result;
527 /*
528 * Please note, that the default values of the direction bits are
529 * undefined after reset. So it is a good idea, to make first a dummy
530 * call to this function, to clear the direction bits and set so to
531 * proper values.
532 */
wdenkf5300ab2003-09-12 15:35:15 +0000533
wdenka0ff7f22003-10-09 13:16:55 +0000534 result = *CPLD_ROTARY_SWITCH; /* read CPLD */
535 debug ("%s: cpld_inc (32 bit) %#x\n", __FUNCTION__, result);
wdenkf5300ab2003-09-12 15:35:15 +0000536
wdenka0ff7f22003-10-09 13:16:55 +0000537 *CPLD_ROTARY_SWITCH |= (3 << 16); /* clear direction bits in CPLD */
wdenkf5300ab2003-09-12 15:35:15 +0000538
wdenka0ff7f22003-10-09 13:16:55 +0000539 /* print result to console */
540 print_identifier ();
541 if ((result & (1 << 16)) == (1 << 16))
542 printf("R");
543 if ((result & (1 << 17)) == (1 << 17))
544 printf("L");
545 if (((result & (1 << 16)) == 0) && ((result & (1 << 17)) == 0))
546 printf("0");
547 if ((result & (1 << 18)) == 0)
548 printf("0\n");
549 else
550 printf("1\n");
wdenkf5300ab2003-09-12 15:35:15 +0000551 return 0;
552}
553
554
555int do_vfd_id (void)
556{
wdenka0ff7f22003-10-09 13:16:55 +0000557 int i;
558 long int pcup_old, pccon_old;
559 int vfd_board_id;
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900560 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
wdenkf5300ab2003-09-12 15:35:15 +0000561
562 /* try to red vfd board id from the value defined by pull-ups */
563
wdenka0ff7f22003-10-09 13:16:55 +0000564 pcup_old = gpio->PCUP;
565 pccon_old = gpio->PCCON;
wdenkf5300ab2003-09-12 15:35:15 +0000566
567 gpio->PCUP = (gpio->PCUP & 0xFFF0); /* activate GPC0...GPC3 pull-ups */
568 gpio->PCCON = (gpio->PCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as
wdenka0ff7f22003-10-09 13:16:55 +0000569 * inputs */
wdenkf5300ab2003-09-12 15:35:15 +0000570 udelay (10); /* allow signals to settle */
571 vfd_board_id = (~gpio->PCDAT) & 0x000F; /* read GPC0...GPC3 port pins */
572
wdenka0ff7f22003-10-09 13:16:55 +0000573 gpio->PCCON = pccon_old;
574 gpio->PCUP = pcup_old;
wdenkf5300ab2003-09-12 15:35:15 +0000575
wdenka0ff7f22003-10-09 13:16:55 +0000576 /* print vfd_board_id to console */
577 print_identifier ();
578 for (i = 0; i < 4; i++) {
579 if ((vfd_board_id & (1 << i)) == 0)
580 printf("0");
581 else
582 printf("1");
583 }
584 printf("\n");
wdenkf5300ab2003-09-12 15:35:15 +0000585 return 0;
586}
587
wdenka0ff7f22003-10-09 13:16:55 +0000588int do_buzzer (char **argv)
wdenkf5300ab2003-09-12 15:35:15 +0000589{
wdenka0ff7f22003-10-09 13:16:55 +0000590 int counter;
wdenkf5300ab2003-09-12 15:35:15 +0000591
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900592 struct s3c24x0_timers * const timers = s3c24x0_get_base_timers();
593 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
wdenkf5300ab2003-09-12 15:35:15 +0000594
wdenka0ff7f22003-10-09 13:16:55 +0000595 /* set prescaler for timer 2, 3 and 4 */
596 timers->TCFG0 &= ~0xFF00;
wdenkf5300ab2003-09-12 15:35:15 +0000597 timers->TCFG0 |= 0x0F00;
598
wdenka0ff7f22003-10-09 13:16:55 +0000599 /* set divider for timer 2 */
wdenkf5300ab2003-09-12 15:35:15 +0000600 timers->TCFG1 &= ~0xF00;
601 timers->TCFG1 |= 0x300;
602
wdenka0ff7f22003-10-09 13:16:55 +0000603 /* set frequency */
604 counter = (PCLK / BUZZER_FREQ) >> 9;
605 timers->ch[2].TCNTB = counter;
wdenkf5300ab2003-09-12 15:35:15 +0000606 timers->ch[2].TCMPB = counter / 2;
607
wdenka0ff7f22003-10-09 13:16:55 +0000608 if (strcmp (argv[2], "on") == 0) {
609 debug ("%s: frequency: %d\n", __FUNCTION__,
610 BUZZER_FREQ);
wdenkf5300ab2003-09-12 15:35:15 +0000611
wdenka0ff7f22003-10-09 13:16:55 +0000612 /* configure pin GPD7 as TOUT2 */
613 gpio->PDCON &= ~0xC000;
614 gpio->PDCON |= 0x8000;
wdenkf5300ab2003-09-12 15:35:15 +0000615
wdenka0ff7f22003-10-09 13:16:55 +0000616 /* start */
617 timers->TCON = (timers->TCON | UPDATE2 | RELOAD2) &
618 ~INVERT2;
619 timers->TCON = (timers->TCON | START2) & ~UPDATE2;
620 return (0);
621 }
622 else if (strcmp (argv[2], "off") == 0) {
623 /* stop */
624 timers->TCON &= ~(START2 | RELOAD2);
wdenkf5300ab2003-09-12 15:35:15 +0000625
wdenka0ff7f22003-10-09 13:16:55 +0000626 /* configure GPD7 as output and set to low */
627 gpio->PDCON &= ~0xC000;
628 gpio->PDCON |= 0x4000;
629 gpio->PDDAT &= ~0x80;
630 return (0);
631 }
wdenkf5300ab2003-09-12 15:35:15 +0000632
wdenka0ff7f22003-10-09 13:16:55 +0000633 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
634 return 1;
wdenkf5300ab2003-09-12 15:35:15 +0000635}
636
637
638int do_led (char **argv)
639{
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900640 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
wdenkf5300ab2003-09-12 15:35:15 +0000641
wdenka0ff7f22003-10-09 13:16:55 +0000642 /* configure PC14 and PC15 as output */
643 gpio->PCCON &= ~(0xF << 28);
644 gpio->PCCON |= (0x5 << 28);
wdenkf5300ab2003-09-12 15:35:15 +0000645
wdenka0ff7f22003-10-09 13:16:55 +0000646 /* configure PD0 and PD4 as output */
647 gpio->PDCON &= ~((0x3 << 8) | 0x3);
648 gpio->PDCON |= ((0x1 << 8) | 0x1);
wdenkf5300ab2003-09-12 15:35:15 +0000649
wdenka0ff7f22003-10-09 13:16:55 +0000650 switch (simple_strtoul(argv[2], NULL, 10)) {
wdenkf5300ab2003-09-12 15:35:15 +0000651
652 case 0:
653 case 1:
654 break;
655
wdenka0ff7f22003-10-09 13:16:55 +0000656 case 2:
657 if (strcmp (argv[3], "on") == 0)
658 gpio->PCDAT |= (1 << 14);
659 else
660 gpio->PCDAT &= ~(1 << 14);
661 return 0;
wdenkf5300ab2003-09-12 15:35:15 +0000662
wdenka0ff7f22003-10-09 13:16:55 +0000663 case 3:
664 if (strcmp (argv[3], "on") == 0)
665 gpio->PCDAT |= (1 << 15);
666 else
667 gpio->PCDAT &= ~(1 << 15);
668 return 0;
wdenkf5300ab2003-09-12 15:35:15 +0000669
wdenka0ff7f22003-10-09 13:16:55 +0000670 case 4:
671 if (strcmp (argv[3], "on") == 0)
672 gpio->PDDAT |= (1 << 0);
673 else
674 gpio->PDDAT &= ~(1 << 0);
675 return 0;
wdenkf5300ab2003-09-12 15:35:15 +0000676
wdenka0ff7f22003-10-09 13:16:55 +0000677 case 5:
678 if (strcmp (argv[3], "on") == 0)
679 gpio->PDDAT |= (1 << 4);
680 else
681 gpio->PDDAT &= ~(1 << 4);
682 return 0;
wdenkf5300ab2003-09-12 15:35:15 +0000683
wdenka0ff7f22003-10-09 13:16:55 +0000684 default:
685 break;
wdenkf5300ab2003-09-12 15:35:15 +0000686
wdenka0ff7f22003-10-09 13:16:55 +0000687 }
688 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
689 return 1;
wdenkf5300ab2003-09-12 15:35:15 +0000690}
691
692
693int do_full_bridge (char **argv)
694{
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900695 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
wdenkf5300ab2003-09-12 15:35:15 +0000696
wdenka0ff7f22003-10-09 13:16:55 +0000697 /* configure PD5 and PD6 as output */
698 gpio->PDCON &= ~((0x3 << 5*2) | (0x3 << 6*2));
699 gpio->PDCON |= ((0x1 << 5*2) | (0x1 << 6*2));
wdenkf5300ab2003-09-12 15:35:15 +0000700
wdenka0ff7f22003-10-09 13:16:55 +0000701 if (strcmp (argv[2], "+") == 0) {
702 gpio->PDDAT |= (1 << 5);
703 gpio->PDDAT |= (1 << 6);
704 return 0;
705 }
706 else if (strcmp (argv[2], "-") == 0) {
707 gpio->PDDAT &= ~(1 << 5);
708 gpio->PDDAT |= (1 << 6);
709 return 0;
710 }
711 else if (strcmp (argv[2], "off") == 0) {
712 gpio->PDDAT &= ~(1 << 5);
713 gpio->PDDAT &= ~(1 << 6);
714 return 0;
715 }
716 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
717 return 1;
wdenkf5300ab2003-09-12 15:35:15 +0000718}
719
720/* val must be in [0, 4095] */
721static inline unsigned long tsc2000_to_uv (u16 val)
722{
723 return ((250000 * val) / 4096) * 10;
724}
725
726
727int do_dac (char **argv)
728{
wdenka0ff7f22003-10-09 13:16:55 +0000729 int brightness;
wdenkf5300ab2003-09-12 15:35:15 +0000730
wdenka0ff7f22003-10-09 13:16:55 +0000731 /* initialize SPI */
Mike Frysingerf6e3a1f2009-08-13 00:32:14 -0400732 tsc2000_spi_init ();
wdenkf5300ab2003-09-12 15:35:15 +0000733
wdenka0ff7f22003-10-09 13:16:55 +0000734 if (((brightness = simple_strtoul (argv[2], NULL, 10)) < 0) ||
735 (brightness > 255)) {
736 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
737 return 1;
738 }
739 tsc2000_write(TSC2000_REG_DACCTL, 0x0); /* Power up DAC */
wdenkf5300ab2003-09-12 15:35:15 +0000740 tsc2000_write(TSC2000_REG_DAC, brightness & 0xff);
741
wdenka0ff7f22003-10-09 13:16:55 +0000742 return 0;
wdenkf5300ab2003-09-12 15:35:15 +0000743}
744
745
746int do_v_bat (void)
747{
wdenka0ff7f22003-10-09 13:16:55 +0000748 unsigned long ret, res;
wdenkf5300ab2003-09-12 15:35:15 +0000749
wdenka0ff7f22003-10-09 13:16:55 +0000750 /* initialize SPI */
751 spi_init ();
wdenkf5300ab2003-09-12 15:35:15 +0000752
753 tsc2000_write(TSC2000_REG_ADC, 0x1836);
754
wdenka0ff7f22003-10-09 13:16:55 +0000755 /* now wait for data available */
756 adc_wait_conversion_done();
wdenkf5300ab2003-09-12 15:35:15 +0000757
758 ret = tsc2000_read(TSC2000_REG_BAT1);
759 res = (tsc2000_to_uv(ret) + 1250) / 2500;
760 res += (ERROR_BATTERY * res) / 1000;
761
wdenka0ff7f22003-10-09 13:16:55 +0000762 print_identifier ();
763 printf ("%ld", (res / 100));
764 printf (".%ld", ((res % 100) / 10));
765 printf ("%ld V\n", (res % 10));
wdenkf5300ab2003-09-12 15:35:15 +0000766 return 0;
767}
768
769
770int do_pressure (void)
771{
wdenka0ff7f22003-10-09 13:16:55 +0000772 /* initialize SPI */
773 spi_init ();
wdenkf5300ab2003-09-12 15:35:15 +0000774
wdenka0ff7f22003-10-09 13:16:55 +0000775 tsc2000_write(TSC2000_REG_ADC, 0x2436);
wdenkf5300ab2003-09-12 15:35:15 +0000776
wdenka0ff7f22003-10-09 13:16:55 +0000777 /* now wait for data available */
778 adc_wait_conversion_done();
wdenkf5300ab2003-09-12 15:35:15 +0000779
wdenka0ff7f22003-10-09 13:16:55 +0000780 print_identifier ();
781 printf ("%d\n", tsc2000_read(TSC2000_REG_AUX2));
wdenkf5300ab2003-09-12 15:35:15 +0000782 return 0;
783}
784
785
786int do_motor_contact (void)
787{
wdenka0ff7f22003-10-09 13:16:55 +0000788 int result;
wdenkf5300ab2003-09-12 15:35:15 +0000789
wdenka0ff7f22003-10-09 13:16:55 +0000790 result = *CPLD_FILL_LEVEL; /* read CPLD */
791 debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
wdenkf5300ab2003-09-12 15:35:15 +0000792
wdenka0ff7f22003-10-09 13:16:55 +0000793 /* print result to console */
794 print_identifier ();
795 if ((result & (1 << 17)) == 0)
796 printf("0\n");
797 else
798 printf("1\n");
799 return 0;
wdenkf5300ab2003-09-12 15:35:15 +0000800}
801
802int do_motor (char **argv)
803{
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900804 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
wdenkf5300ab2003-09-12 15:35:15 +0000805
806 /* Configure I/O port */
807 gpio->PGCON &= ~(0x3 << 0);
808 gpio->PGCON |= (0x1 << 0);
809
wdenka0ff7f22003-10-09 13:16:55 +0000810 if (strcmp (argv[2], "on") == 0) {
811 gpio->PGDAT &= ~(1 << 0);
812 return 0;
813 }
814 if (strcmp (argv[2], "off") == 0) {
815 gpio->PGDAT |= (1 << 0);
816 return 0;
817 }
818 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
819 return 1;
wdenkf5300ab2003-09-12 15:35:15 +0000820}
821
822static void print_identifier (void)
823{
wdenka0ff7f22003-10-09 13:16:55 +0000824 printf ("## FKT: ");
wdenkf5300ab2003-09-12 15:35:15 +0000825}
826
827int do_pwm (char **argv)
828{
wdenka0ff7f22003-10-09 13:16:55 +0000829 int counter;
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900830 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
831 struct s3c24x0_timers * const timers = s3c24x0_get_base_timers();
wdenkf5300ab2003-09-12 15:35:15 +0000832
wdenka0ff7f22003-10-09 13:16:55 +0000833 if (strcmp (argv[2], "on") == 0) {
834 /* configure pin GPD8 as TOUT3 */
835 gpio->PDCON &= ~(0x3 << 8*2);
836 gpio->PDCON |= (0x2 << 8*2);
wdenkf5300ab2003-09-12 15:35:15 +0000837
wdenka0ff7f22003-10-09 13:16:55 +0000838 /* set prescaler for timer 2, 3 and 4 */
839 timers->TCFG0 &= ~0xFF00;
840 timers->TCFG0 |= 0x0F00;
wdenkf5300ab2003-09-12 15:35:15 +0000841
wdenka0ff7f22003-10-09 13:16:55 +0000842 /* set divider for timer 3 */
843 timers->TCFG1 &= ~(0xf << 12);
844 timers->TCFG1 |= (0x3 << 12);
wdenkf5300ab2003-09-12 15:35:15 +0000845
wdenka0ff7f22003-10-09 13:16:55 +0000846 /* set frequency */
847 counter = (PCLK / PWM_FREQ) >> 9;
848 timers->ch[3].TCNTB = counter;
849 timers->ch[3].TCMPB = counter / 2;
wdenkf5300ab2003-09-12 15:35:15 +0000850
wdenka0ff7f22003-10-09 13:16:55 +0000851 /* start timer */
852 timers->TCON = (timers->TCON | UPDATE3 | RELOAD3) & ~INVERT3;
853 timers->TCON = (timers->TCON | START3) & ~UPDATE3;
854 return 0;
855 }
856 if (strcmp (argv[2], "off") == 0) {
wdenkf5300ab2003-09-12 15:35:15 +0000857
wdenka0ff7f22003-10-09 13:16:55 +0000858 /* stop timer */
859 timers->TCON &= ~(START2 | RELOAD2);
wdenkf5300ab2003-09-12 15:35:15 +0000860
wdenka0ff7f22003-10-09 13:16:55 +0000861 /* configure pin GPD8 as output and set to 0 */
862 gpio->PDCON &= ~(0x3 << 8*2);
863 gpio->PDCON |= (0x1 << 8*2);
864 gpio->PDDAT &= ~(1 << 8);
865 return 0;
866 }
867 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
868 return 1;
wdenkf5300ab2003-09-12 15:35:15 +0000869}
870
871
872int do_thermo (char **argv)
873{
wdenka0ff7f22003-10-09 13:16:55 +0000874 int channel, res;
wdenkf5300ab2003-09-12 15:35:15 +0000875
wdenka0ff7f22003-10-09 13:16:55 +0000876 tsc2000_reg_init ();
wdenkf5300ab2003-09-12 15:35:15 +0000877
wdenka0ff7f22003-10-09 13:16:55 +0000878 if (strcmp (argv[2], "all") == 0) {
879 int i;
880 for (i=0; i <= 15; i++) {
881 res = tsc2000_read_channel(i);
882 print_identifier ();
883 printf ("c%d: %d\n", i, res);
884 }
885 return 0;
886 }
887 channel = simple_strtoul (argv[2], NULL, 10);
888 res = tsc2000_read_channel(channel);
889 print_identifier ();
890 printf ("%d\n", res);
891 return 0; /* return OK */
wdenkf5300ab2003-09-12 15:35:15 +0000892}
893
894
wdenkf5300ab2003-09-12 15:35:15 +0000895int do_touch (char **argv)
896{
wdenka0ff7f22003-10-09 13:16:55 +0000897 int x, y;
wdenkf5300ab2003-09-12 15:35:15 +0000898
wdenka0ff7f22003-10-09 13:16:55 +0000899 if (strcmp (argv[2], "tl") == 0) {
wdenk42dfe7a2004-03-14 22:25:36 +0000900#ifdef CONFIG_TOUCH_WAIT_PRESSED
wdenka0ff7f22003-10-09 13:16:55 +0000901 touch_wait_pressed();
902#else
903 {
904 int i;
905 for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
906 if (touch_check_pressed ()) {
907 break;
908 }
909 udelay (1000); /* pause 1 ms */
910 }
911 }
912 if (!touch_check_pressed()) {
913 print_identifier ();
914 printf ("error: touch not pressed\n");
915 return 1;
916 }
917#endif /* CONFIG_TOUCH_WAIT_PRESSED */
918 touch_read_x_y (&x, &y);
wdenkf5300ab2003-09-12 15:35:15 +0000919
wdenka0ff7f22003-10-09 13:16:55 +0000920 print_identifier ();
921 printf ("x=%d y=%d\n", x, y);
922 return touch_write_clibration_values (CALIB_TL, x, y);
923 }
924 else if (strcmp (argv[2], "dr") == 0) {
wdenk42dfe7a2004-03-14 22:25:36 +0000925#ifdef CONFIG_TOUCH_WAIT_PRESSED
wdenka0ff7f22003-10-09 13:16:55 +0000926 touch_wait_pressed();
927#else
928 {
929 int i;
930 for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
931 if (touch_check_pressed ()) {
932 break;
933 }
934 udelay (1000); /* pause 1 ms */
935 }
936 }
937 if (!touch_check_pressed()) {
938 print_identifier ();
939 printf ("error: touch not pressed\n");
940 return 1;
941 }
942#endif /* CONFIG_TOUCH_WAIT_PRESSED */
943 touch_read_x_y (&x, &y);
wdenkf5300ab2003-09-12 15:35:15 +0000944
wdenka0ff7f22003-10-09 13:16:55 +0000945 print_identifier ();
946 printf ("x=%d y=%d\n", x, y);
wdenkf5300ab2003-09-12 15:35:15 +0000947
wdenka0ff7f22003-10-09 13:16:55 +0000948 return touch_write_clibration_values (CALIB_DR, x, y);
949 }
950 return 1; /* not "tl", nor "dr", so return error */
wdenkf5300ab2003-09-12 15:35:15 +0000951}
952
953
wdenka0ff7f22003-10-09 13:16:55 +0000954#ifdef CONFIG_TOUCH_WAIT_PRESSED
wdenkf5300ab2003-09-12 15:35:15 +0000955static void touch_wait_pressed (void)
956{
wdenka0ff7f22003-10-09 13:16:55 +0000957 while (!(tsc2000_read(TSC2000_REG_ADC) & TC_PSM));
wdenkf5300ab2003-09-12 15:35:15 +0000958}
959
wdenka0ff7f22003-10-09 13:16:55 +0000960#else
961static int touch_check_pressed (void)
962{
963 return (tsc2000_read(TSC2000_REG_ADC) & TC_PSM);
964}
965#endif /* CONFIG_TOUCH_WAIT_PRESSED */
wdenkf5300ab2003-09-12 15:35:15 +0000966
967static int touch_write_clibration_values (int calib_point, int x, int y)
968{
Jon Loeligerab3abcb2007-07-09 18:45:16 -0500969#if defined(CONFIG_CMD_I2C)
wdenka0ff7f22003-10-09 13:16:55 +0000970 int x_verify = 0;
971 int y_verify = 0;
wdenkf5300ab2003-09-12 15:35:15 +0000972
wdenka0ff7f22003-10-09 13:16:55 +0000973 tsc2000_reg_init ();
974
975 if (calib_point == CALIB_TL) {
976 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200977 (unsigned char *)&x, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +0000978 return 1;
979 }
980 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200981 (unsigned char *)&y, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +0000982 return 1;
983 }
984
985 /* verify written values */
986 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200987 (unsigned char *)&x_verify, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +0000988 return 1;
989 }
990 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200991 (unsigned char *)&y_verify, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +0000992 return 1;
993 }
994 if ((y != y_verify) || (x != x_verify)) {
995 print_identifier ();
996 printf ("error: verify error\n");
997 return 1;
998 }
999 return 0; /* no error */
1000 }
1001 else if (calib_point == CALIB_DR) {
1002 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +02001003 (unsigned char *)&x, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +00001004 return 1;
1005 }
1006 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +02001007 (unsigned char *)&y, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +00001008 return 1;
1009 }
1010
1011 /* verify written values */
1012 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +02001013 (unsigned char *)&x_verify, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +00001014 return 1;
1015 }
1016 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +02001017 (unsigned char *)&y_verify, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +00001018 return 1;
1019 }
1020 if ((y != y_verify) || (x != x_verify)) {
1021 print_identifier ();
1022 printf ("error: verify error\n");
1023 return 1;
1024 }
1025 return 0;
1026 }
1027 return 1;
wdenkf5300ab2003-09-12 15:35:15 +00001028#else
Jon Loeligerd39b5742007-07-10 10:48:22 -05001029 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
wdenka0ff7f22003-10-09 13:16:55 +00001030 "to EEPROM\n");
1031 return (1);
Jon Loeligerd39b5742007-07-10 10:48:22 -05001032#endif
wdenkf5300ab2003-09-12 15:35:15 +00001033}
1034
1035
1036static void touch_read_x_y (int *px, int *py)
1037{
wdenka0ff7f22003-10-09 13:16:55 +00001038 tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD0 | TC_AD1);
1039 adc_wait_conversion_done();
1040 *px = tsc2000_read(TSC2000_REG_X);
wdenkf5300ab2003-09-12 15:35:15 +00001041
wdenka0ff7f22003-10-09 13:16:55 +00001042 tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD2);
1043 adc_wait_conversion_done();
1044 *py = tsc2000_read(TSC2000_REG_Y);
wdenkf5300ab2003-09-12 15:35:15 +00001045}
1046
1047
wdenkf5300ab2003-09-12 15:35:15 +00001048int do_rs485 (char **argv)
1049{
wdenka0ff7f22003-10-09 13:16:55 +00001050 int timeout;
1051 char data[RS485_MAX_RECEIVE_BUF_LEN];
wdenkf5300ab2003-09-12 15:35:15 +00001052
wdenka0ff7f22003-10-09 13:16:55 +00001053 if (strcmp (argv[2], "send") == 0) {
1054 return (rs485_send_line (argv[3]));
1055 }
1056 else if (strcmp (argv[2], "receive") == 0) {
1057 timeout = simple_strtoul(argv[3], NULL, 10);
1058 if (rs485_receive_chars (data, timeout) != 0) {
1059 print_identifier ();
1060 printf ("## nothing received\n");
1061 return (1);
1062 }
1063 else {
1064 print_identifier ();
1065 printf ("%s\n", data);
1066 return (0);
1067 }
1068 }
1069 printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1070 return (1); /* unknown command, return error */
wdenkf5300ab2003-09-12 15:35:15 +00001071}
1072
1073
1074static int rs485_send_line (const char *data)
1075{
wdenka0ff7f22003-10-09 13:16:55 +00001076 rs485_init ();
1077 trab_rs485_enable_tx ();
1078 rs485_puts (data);
1079 rs485_putc ('\n');
wdenkf5300ab2003-09-12 15:35:15 +00001080
wdenka0ff7f22003-10-09 13:16:55 +00001081 return (0);
wdenkf5300ab2003-09-12 15:35:15 +00001082}
1083
1084
1085static int rs485_receive_chars (char *data, int timeout)
1086{
wdenka0ff7f22003-10-09 13:16:55 +00001087 int i;
1088 int receive_count = 0;
wdenkf5300ab2003-09-12 15:35:15 +00001089
wdenka0ff7f22003-10-09 13:16:55 +00001090 rs485_init ();
1091 trab_rs485_enable_rx ();
wdenkf5300ab2003-09-12 15:35:15 +00001092
wdenka0ff7f22003-10-09 13:16:55 +00001093 /* test every 1 ms for received characters to avoid a receive FIFO
1094 * overrun (@ 38.400 Baud) */
1095 for (i = 0; i < (timeout * 1000); i++) {
1096 while (rs485_tstc ()) {
1097 if (receive_count >= RS485_MAX_RECEIVE_BUF_LEN-1)
1098 break;
1099 *data++ = rs485_getc ();
1100 receive_count++;
1101 }
1102 udelay (1000); /* pause 1 ms */
1103 }
1104 *data = '\0'; /* terminate string */
wdenkf5300ab2003-09-12 15:35:15 +00001105
wdenka0ff7f22003-10-09 13:16:55 +00001106 if (receive_count == 0)
1107 return (1);
1108 else
1109 return (0);
wdenkf5300ab2003-09-12 15:35:15 +00001110}
1111
1112
1113int do_serial_number (char **argv)
1114{
Jon Loeligerab3abcb2007-07-09 18:45:16 -05001115#if defined(CONFIG_CMD_I2C)
wdenka0ff7f22003-10-09 13:16:55 +00001116 unsigned int serial_number;
wdenkf5300ab2003-09-12 15:35:15 +00001117
wdenka0ff7f22003-10-09 13:16:55 +00001118 if (strcmp (argv[2], "read") == 0) {
1119 if (i2c_read (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +02001120 (unsigned char *)&serial_number, 4)) {
wdenka0ff7f22003-10-09 13:16:55 +00001121 printf ("could not read from eeprom\n");
1122 return (1);
1123 }
1124 print_identifier ();
1125 printf ("%08d\n", serial_number);
1126 return (0);
1127 }
1128 else if (strcmp (argv[2], "write") == 0) {
1129 serial_number = simple_strtoul(argv[3], NULL, 10);
1130 if (i2c_write (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +02001131 (unsigned char *)&serial_number, 4)) {
wdenka0ff7f22003-10-09 13:16:55 +00001132 printf ("could not write to eeprom\n");
1133 return (1);
1134 }
1135 return (0);
1136 }
1137 printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1138 return (1); /* unknown command, return error */
wdenkf5300ab2003-09-12 15:35:15 +00001139#else
Jon Loeligerd39b5742007-07-10 10:48:22 -05001140 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
wdenka0ff7f22003-10-09 13:16:55 +00001141 "to EEPROM\n");
1142 return (1);
Jon Loeligerd39b5742007-07-10 10:48:22 -05001143#endif
wdenkf5300ab2003-09-12 15:35:15 +00001144}
1145
1146
1147int do_crc16 (void)
1148{
Jon Loeligerab3abcb2007-07-09 18:45:16 -05001149#if defined(CONFIG_CMD_I2C)
wdenka0ff7f22003-10-09 13:16:55 +00001150 int crc;
Wolfgang Denka63c31c2006-06-26 10:54:52 +02001151 unsigned char buf[EEPROM_MAX_CRC_BUF];
wdenkf5300ab2003-09-12 15:35:15 +00001152
wdenka0ff7f22003-10-09 13:16:55 +00001153 if (i2c_read (I2C_EEPROM_DEV_ADDR, 0, 1, buf, 60)) {
1154 printf ("could not read from eeprom\n");
1155 return (1);
1156 }
1157 crc = 0; /* start value of crc calculation */
1158 crc = updcrc (crc, buf, 60);
wdenkf5300ab2003-09-12 15:35:15 +00001159
wdenka0ff7f22003-10-09 13:16:55 +00001160 print_identifier ();
1161 printf ("crc16=%#04x\n", crc);
wdenkf5300ab2003-09-12 15:35:15 +00001162
Wolfgang Denka63c31c2006-06-26 10:54:52 +02001163 if (i2c_write (I2C_EEPROM_DEV_ADDR, CRC16, 1, (unsigned char *)&crc,
wdenka0ff7f22003-10-09 13:16:55 +00001164 sizeof (crc))) {
1165 printf ("could not read from eeprom\n");
1166 return (1);
1167 }
1168 return (0);
wdenkf5300ab2003-09-12 15:35:15 +00001169#else
Jon Loeligerd39b5742007-07-10 10:48:22 -05001170 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
wdenka0ff7f22003-10-09 13:16:55 +00001171 "to EEPROM\n");
1172 return (1);
Jon Loeligerd39b5742007-07-10 10:48:22 -05001173#endif
wdenkf5300ab2003-09-12 15:35:15 +00001174}
1175
1176
1177/*
1178 * Calculate, intelligently, the CRC of a dataset incrementally given a
1179 * buffer full at a time.
1180 * Initialize crc to 0 for XMODEM, -1 for CCITT.
1181 *
1182 * Usage:
1183 * newcrc = updcrc( oldcrc, bufadr, buflen )
1184 * unsigned int oldcrc, buflen;
1185 * char *bufadr;
1186 *
1187 * Compile with -DTEST to generate program that prints CRC of stdin to stdout.
1188 * Compile with -DMAKETAB to print values for crctab to stdout
1189 */
1190
1191 /* the CRC polynomial. This is used by XMODEM (almost CCITT).
1192 * If you change P, you must change crctab[]'s initial value to what is
1193 * printed by initcrctab()
1194 */
1195#define P 0x1021
1196
1197 /* number of bits in CRC: don't change it. */
1198#define W 16
1199
1200 /* this the number of bits per char: don't change it. */
1201#define B 8
1202
1203static unsigned short crctab[1<<B] = { /* as calculated by initcrctab() */
1204 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1205 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1206 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1207 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1208 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1209 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1210 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1211 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1212 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1213 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1214 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1215 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1216 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1217 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1218 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1219 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1220 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1221 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1222 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1223 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1224 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1225 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1226 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1227 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1228 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1229 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1230 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1231 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1232 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1233 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1234 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1235 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1236 };
1237
1238static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
wdenka0ff7f22003-10-09 13:16:55 +00001239 unsigned int icnt )
wdenkf5300ab2003-09-12 15:35:15 +00001240{
wdenka0ff7f22003-10-09 13:16:55 +00001241 register unsigned short crc = icrc;
1242 register unsigned char *cp = icp;
1243 register unsigned int cnt = icnt;
wdenkf5300ab2003-09-12 15:35:15 +00001244
wdenka0ff7f22003-10-09 13:16:55 +00001245 while (cnt--)
1246 crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];
wdenkf5300ab2003-09-12 15:35:15 +00001247
wdenka0ff7f22003-10-09 13:16:55 +00001248 return (crc);
wdenkf5300ab2003-09-12 15:35:15 +00001249}
wdenka0ff7f22003-10-09 13:16:55 +00001250
1251
1252int do_gain (char **argv)
1253{
1254 int range;
1255
1256 range = simple_strtoul (argv[2], NULL, 10);
1257 if ((range < 1) || (range > 3))
1258 {
1259 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1260 return 1;
1261 }
1262
1263 tsc2000_set_range (range);
1264 return (0);
1265}
1266
1267
1268int do_eeprom (char **argv)
1269{
Jon Loeligerab3abcb2007-07-09 18:45:16 -05001270#if defined(CONFIG_CMD_I2C)
wdenka0ff7f22003-10-09 13:16:55 +00001271 if (strcmp (argv[2], "read") == 0) {
1272 return (trab_eeprom_read (argv));
1273 }
1274
1275 else if (strcmp (argv[2], "write") == 0) {
1276 return (trab_eeprom_write (argv));
1277 }
1278
1279 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1280 return (1);
1281#else
Jon Loeligerd39b5742007-07-10 10:48:22 -05001282 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
wdenka0ff7f22003-10-09 13:16:55 +00001283 "to EEPROM\n");
1284 return (1);
Jon Loeligerd39b5742007-07-10 10:48:22 -05001285#endif
wdenka0ff7f22003-10-09 13:16:55 +00001286}
1287
Jon Loeligerab3abcb2007-07-09 18:45:16 -05001288#if defined(CONFIG_CMD_I2C)
wdenka0ff7f22003-10-09 13:16:55 +00001289static int trab_eeprom_read (char **argv)
1290{
1291 int i;
1292 int len;
1293 unsigned int addr;
1294 long int value = 0;
1295 uchar *buffer;
1296
1297 buffer = (uchar *) &value;
1298 addr = simple_strtoul (argv[3], NULL, 10);
1299 addr &= 0xfff;
1300 len = simple_strtoul (argv[4], NULL, 10);
1301 if ((len < 1) || (len > 4)) {
1302 printf ("%s: invalid parameter %s\n", __FUNCTION__,
1303 argv[4]);
1304 return (1);
1305 }
1306 for (i = 0; i < len; i++) {
1307 if (i2c_read (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
1308 printf ("%s: could not read from i2c device %#x"
1309 ", addr %d\n", __FUNCTION__,
1310 I2C_EEPROM_DEV_ADDR, addr);
1311 return (1);
1312 }
1313 }
1314 print_identifier ();
1315 if (strcmp (argv[5], "-") == 0) {
1316 if (len == 1)
1317 printf ("%d\n", (signed char) value);
1318 else if (len == 2)
1319 printf ("%d\n", (signed short int) value);
1320 else
1321 printf ("%ld\n", value);
1322 }
1323 else {
1324 if (len == 1)
1325 printf ("%d\n", (unsigned char) value);
1326 else if (len == 2)
1327 printf ("%d\n", (unsigned short int) value);
1328 else
1329 printf ("%ld\n", (unsigned long int) value);
1330 }
1331 return (0);
1332}
1333
1334static int trab_eeprom_write (char **argv)
1335{
1336 int i;
1337 int len;
1338 unsigned int addr;
1339 long int value = 0;
1340 uchar *buffer;
1341
1342 buffer = (uchar *) &value;
1343 addr = simple_strtoul (argv[3], NULL, 10);
1344 addr &= 0xfff;
1345 len = simple_strtoul (argv[4], NULL, 10);
1346 if ((len < 1) || (len > 4)) {
1347 printf ("%s: invalid parameter %s\n", __FUNCTION__,
1348 argv[4]);
1349 return (1);
1350 }
1351 value = simple_strtol (argv[5], NULL, 10);
1352 debug ("value=%ld\n", value);
1353 for (i = 0; i < len; i++) {
1354 if (i2c_write (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
1355 printf ("%s: could not write to i2c device %d"
1356 ", addr %d\n", __FUNCTION__,
1357 I2C_EEPROM_DEV_ADDR, addr);
1358 return (1);
1359 }
1360#if 0
1361 printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
1362 "%#x+%d=%p=%#x \n",I2C_EEPROM_DEV_ADDR_DEV_ADDR , addr,
1363 i, addr+i, 1, buffer, i, buffer+i, *(buffer+i));
1364#endif
1365 udelay (30000); /* wait for EEPROM ready */
1366 }
1367 return (0);
1368}
1369
1370int i2c_write_multiple (uchar chip, uint addr, int alen,
1371 uchar *buffer, int len)
1372{
1373 int i;
1374
1375 if (alen != 1) {
1376 printf ("%s: addr len other than 1 not supported\n",
1377 __FUNCTION__);
1378 return (1);
1379 }
1380
1381 for (i = 0; i < len; i++) {
1382 if (i2c_write (chip, addr+i, alen, buffer+i, 1)) {
1383 printf ("%s: could not write to i2c device %d"
1384 ", addr %d\n", __FUNCTION__, chip, addr);
1385 return (1);
1386 }
1387#if 0
1388 printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
1389 "%#x+%d=%p=\"%.1s\"\n", chip, addr, i, addr+i,
1390 alen, buffer, i, buffer+i, buffer+i);
1391#endif
1392
1393 udelay (30000);
1394 }
1395 return (0);
1396}
1397
1398int i2c_read_multiple ( uchar chip, uint addr, int alen,
1399 uchar *buffer, int len)
1400{
1401 int i;
1402
1403 if (alen != 1) {
1404 printf ("%s: addr len other than 1 not supported\n",
1405 __FUNCTION__);
1406 return (1);
1407 }
1408
1409 for (i = 0; i < len; i++) {
1410 if (i2c_read (chip, addr+i, alen, buffer+i, 1)) {
1411 printf ("%s: could not read from i2c device %#x"
1412 ", addr %d\n", __FUNCTION__, chip, addr);
1413 return (1);
1414 }
1415 }
1416 return (0);
1417}
Jon Loeligerd39b5742007-07-10 10:48:22 -05001418#endif