blob: 93b9490e1ce385436544609fc5641d672ff66bdd [file] [log] [blame]
wdenk708521a2003-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 Tyser62948502008-11-03 09:30:59 -060028#include <timestamp.h>
wdenk708521a2003-09-12 15:35:15 +000029#include <s3c2400.h>
30#include "tsc2000.h"
31#include "rs485.h"
32
wdenk61970fd2003-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 */
wdenkce4832c2004-10-17 21:12:06 +000039#undef CONFIG_TOUCH_WAIT_PRESSED
wdenk61970fd2003-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
wdenk708521a2003-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 */
wdenk708521a2003-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
wdenk61970fd2003-10-09 13:16:55 +000078/* EEPROM address map */
wdenk708521a2003-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);
wdenk61970fd2003-10-09 13:16:55 +0000118int do_buzzer (char **);
wdenk708521a2003-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);
wdenk61970fd2003-10-09 13:16:55 +0000130int do_power_switch (void);
131int do_gain (char **);
132int do_eeprom (char **);
wdenk708521a2003-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);
wdenk61970fd2003-10-09 13:16:55 +0000138
139#ifdef CONFIG_TOUCH_WAIT_PRESSED
wdenk708521a2003-09-12 15:35:15 +0000140static void touch_wait_pressed (void);
wdenk61970fd2003-10-09 13:16:55 +0000141#else
142static int touch_check_pressed (void);
143#endif /* CONFIG_TOUCH_WAIT_PRESSED */
144
wdenk708521a2003-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,
wdenk61970fd2003-10-09 13:16:55 +0000150 unsigned int icnt);
wdenk708521a2003-09-12 15:35:15 +0000151
Jon Loeligere11c1232007-07-09 18:45:16 -0500152#if defined(CONFIG_CMD_I2C)
wdenk61970fd2003-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 Loeliger761ea742007-07-10 10:48:22 -0500159#endif
wdenk708521a2003-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{
wdenk61970fd2003-10-09 13:16:55 +0000168 int i;
wdenk708521a2003-09-12 15:35:15 +0000169
wdenk61970fd2003-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 }
wdenk708521a2003-09-12 15:35:15 +0000178
wdenk61970fd2003-10-09 13:16:55 +0000179 debug ("argc = %d\n", argc);
wdenk708521a2003-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>");
wdenk61970fd2003-10-09 13:16:55 +0000183 }
wdenk708521a2003-09-12 15:35:15 +0000184
wdenk61970fd2003-10-09 13:16:55 +0000185 adc_init ();
wdenk708521a2003-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) {
wdenk61970fd2003-10-09 13:16:55 +0000195 return (do_info ());
196 }
197 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 ());
wdenk708521a2003-09-12 15:35:15 +0000232 }
wdenk61970fd2003-10-09 13:16:55 +0000233 break;
wdenk708521a2003-09-12 15:35:15 +0000234
235 case 3:
wdenk61970fd2003-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;
wdenk708521a2003-09-12 15:35:15 +0000264
wdenk61970fd2003-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;
wdenk708521a2003-09-12 15:35:15 +0000288
289 default:
290 break;
291 }
292
293 printf ("Usage:\n<command> <parameter1> <parameter2> ...\n");
wdenk61970fd2003-10-09 13:16:55 +0000294 return 1;
wdenk708521a2003-09-12 15:35:15 +0000295}
296
297int do_info (void)
298{
wdenk61970fd2003-10-09 13:16:55 +0000299 printf ("Stand-alone application for TRAB board function test\n");
Peter Tyser62948502008-11-03 09:30:59 -0600300 printf ("Built: %s at %s\n", U_BOOT_DATE, U_BOOT_TIME);
wdenk708521a2003-09-12 15:35:15 +0000301
302 return 0;
303}
304
305int do_dip (void)
306{
wdenk61970fd2003-10-09 13:16:55 +0000307 unsigned int result = 0;
308 int adc_val;
309 int i;
wdenk708521a2003-09-12 15:35:15 +0000310
311 /***********************************************************
312 DIP switch connection (according to wa4-cpu.sp.301.pdf, page 3):
313 SW1 - AIN4
314 SW2 - AIN5
315 SW3 - AIN6
316 SW4 - AIN7
317
318 "On" DIP switch position short-circuits the voltage from
319 the input channel (i.e. '0' conversion result means "on").
320 *************************************************************/
321
322 for (i = 7; i > 3; i--) {
323
wdenk61970fd2003-10-09 13:16:55 +0000324 if ((adc_val = adc_read (i)) == -1) {
325 printf ("Channel %d could not be read\n", i);
326 return 1;
327 }
wdenk708521a2003-09-12 15:35:15 +0000328
329 /*
330 * Input voltage (switch open) is 1.8 V.
331 * (Vin_High/VRef)*adc_res = (1,8V/2,5V)*1023) = 736
332 * Set trigger at halve that value.
333 */
334 if (adc_val < 368)
wdenk61970fd2003-10-09 13:16:55 +0000335 result |= (1 << (i-4));
336 }
wdenk708521a2003-09-12 15:35:15 +0000337
wdenk61970fd2003-10-09 13:16:55 +0000338 /* print result to console */
339 print_identifier ();
340 for (i = 0; i < 4; i++) {
341 if ((result & (1 << i)) == 0)
342 printf("0");
343 else
344 printf("1");
345 }
346 printf("\n");
wdenk708521a2003-09-12 15:35:15 +0000347
348 return 0;
349}
350
351
352int do_vcc5v (void)
353{
wdenk61970fd2003-10-09 13:16:55 +0000354 int result;
wdenk708521a2003-09-12 15:35:15 +0000355
wdenk61970fd2003-10-09 13:16:55 +0000356 /* VCC5V is connected to channel 2 */
wdenk708521a2003-09-12 15:35:15 +0000357
wdenk61970fd2003-10-09 13:16:55 +0000358 if ((result = adc_read (VCC5V)) == -1) {
359 printf ("VCC5V could not be read\n");
360 return 1;
361 }
wdenk708521a2003-09-12 15:35:15 +0000362
wdenk61970fd2003-10-09 13:16:55 +0000363 /*
364 * Calculate voltage value. Split in two parts because there is no
365 * floating point support. VCC5V is connected over an resistor divider:
366 * VCC5V=ADCval*2,5V/1023*(10K+30K)/10K.
367 */
368 print_identifier ();
369 printf ("%d", (result & 0x3FF)* 10 / 1023);
370 printf (".%d", ((result & 0x3FF)* 10 % 1023)* 10 / 1023);
371 printf ("%d V\n", (((result & 0x3FF) * 10 % 1023 ) * 10 % 1023)
372 * 10 / 1024);
wdenk708521a2003-09-12 15:35:15 +0000373
374 return 0;
375}
376
377
378int do_vcc12v (void)
379{
wdenk61970fd2003-10-09 13:16:55 +0000380 int result;
wdenk708521a2003-09-12 15:35:15 +0000381
wdenk61970fd2003-10-09 13:16:55 +0000382 if ((result = adc_read (VCC12V)) == -1) {
383 printf ("VCC12V could not be read\n");
384 return 1;
385 }
wdenk708521a2003-09-12 15:35:15 +0000386
wdenk61970fd2003-10-09 13:16:55 +0000387 /*
388 * Calculate voltage value. Split in two parts because there is no
389 * floating point support. VCC5V is connected over an resistor divider:
390 * VCC12V=ADCval*2,5V/1023*(30K+270K)/30K.
391 */
392 print_identifier ();
393 printf ("%d", (result & 0x3FF)* 25 / 1023);
394 printf (".%d V\n", ((result & 0x3FF)* 25 % 1023) * 10 / 1023);
wdenk708521a2003-09-12 15:35:15 +0000395
wdenk61970fd2003-10-09 13:16:55 +0000396 return 0;
wdenk708521a2003-09-12 15:35:15 +0000397}
398
399static int adc_read (unsigned int channel)
400{
wdenk61970fd2003-10-09 13:16:55 +0000401 int j = 1000; /* timeout value for wait loop in us */
402 int result;
403 S3C2400_ADC *padc;
wdenk708521a2003-09-12 15:35:15 +0000404
wdenk61970fd2003-10-09 13:16:55 +0000405 padc = S3C2400_GetBase_ADC();
406 channel &= 0x7;
wdenk708521a2003-09-12 15:35:15 +0000407
wdenk61970fd2003-10-09 13:16:55 +0000408 padc->ADCCON &= ~ADC_STDBM; /* select normal mode */
wdenk708521a2003-09-12 15:35:15 +0000409 padc->ADCCON &= ~(0x7 << 3); /* clear the channel bits */
wdenk61970fd2003-10-09 13:16:55 +0000410 padc->ADCCON |= ((channel << 3) | ADC_ENABLE_START);
411
412 while (j--) {
413 if ((padc->ADCCON & ADC_ENABLE_START) == 0)
414 break;
415 udelay (1);
416 }
wdenk708521a2003-09-12 15:35:15 +0000417
wdenk61970fd2003-10-09 13:16:55 +0000418 if (j == 0) {
419 printf("%s: ADC timeout\n", __FUNCTION__);
420 padc->ADCCON |= ADC_STDBM; /* select standby mode */
421 return -1;
422 }
wdenk708521a2003-09-12 15:35:15 +0000423
wdenk61970fd2003-10-09 13:16:55 +0000424 result = padc->ADCDAT & 0x3FF;
wdenk708521a2003-09-12 15:35:15 +0000425
wdenk61970fd2003-10-09 13:16:55 +0000426 padc->ADCCON |= ADC_STDBM; /* select standby mode */
wdenk708521a2003-09-12 15:35:15 +0000427
wdenk61970fd2003-10-09 13:16:55 +0000428 debug ("%s: channel %d, result[DIGIT]=%d\n", __FUNCTION__,
429 (padc->ADCCON >> 3) & 0x7, result);
wdenk708521a2003-09-12 15:35:15 +0000430
wdenk61970fd2003-10-09 13:16:55 +0000431 /*
432 * Wait for ADC to be ready for next conversion. This delay value was
433 * estimated, because the datasheet does not specify a value.
434 */
435 udelay (1000);
wdenk708521a2003-09-12 15:35:15 +0000436
wdenk61970fd2003-10-09 13:16:55 +0000437 return (result);
wdenk708521a2003-09-12 15:35:15 +0000438}
439
440
441static void adc_init (void)
442{
wdenk61970fd2003-10-09 13:16:55 +0000443 S3C2400_ADC *padc;
wdenk708521a2003-09-12 15:35:15 +0000444
wdenk61970fd2003-10-09 13:16:55 +0000445 padc = S3C2400_GetBase_ADC();
wdenk708521a2003-09-12 15:35:15 +0000446
447 padc->ADCCON &= ~(0xff << 6); /* clear prescaler bits */
448 padc->ADCCON |= ((65 << 6) | ADC_PRSCEN); /* set prescaler */
449
wdenk61970fd2003-10-09 13:16:55 +0000450 /*
451 * Wait some time to avoid problem with very first call of
452 * adc_read(). Without * this delay, sometimes the first read adc
453 * value is 0. Perhaps because the * adjustment of prescaler takes
454 * some clock cycles?
455 */
456 udelay (1000);
457
458 return;
wdenk708521a2003-09-12 15:35:15 +0000459}
460
461
462int do_buttons (void)
463{
wdenk61970fd2003-10-09 13:16:55 +0000464 int result;
465 int i;
wdenk708521a2003-09-12 15:35:15 +0000466
wdenk61970fd2003-10-09 13:16:55 +0000467 result = *CPLD_BUTTONS; /* read CPLD */
468 debug ("%s: cpld_taster (32 bit) %#x\n", __FUNCTION__, result);
wdenk708521a2003-09-12 15:35:15 +0000469
wdenk61970fd2003-10-09 13:16:55 +0000470 /* print result to console */
471 print_identifier ();
472 for (i = 16; i <= 19; i++) {
473 if ((result & (1 << i)) == 0)
474 printf("0");
475 else
476 printf("1");
477 }
478 printf("\n");
wdenk708521a2003-09-12 15:35:15 +0000479 return 0;
480}
481
482
wdenk61970fd2003-10-09 13:16:55 +0000483int do_power_switch (void)
484{
485 int result;
486
487 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
488
489 /* configure GPE7 as input */
490 gpio->PECON &= ~(0x3 << (2 * 7));
491
492 /* signal GPE7 from power switch is low active: 0=on , 1=off */
493 result = ((gpio->PEDAT & (1 << 7)) == (1 << 7)) ? 0 : 1;
494
495 print_identifier ();
496 printf("%d\n", result);
497 return 0;
498}
499
500
wdenk708521a2003-09-12 15:35:15 +0000501int do_fill_level (void)
502{
wdenk61970fd2003-10-09 13:16:55 +0000503 int result;
wdenk708521a2003-09-12 15:35:15 +0000504
wdenk61970fd2003-10-09 13:16:55 +0000505 result = *CPLD_FILL_LEVEL; /* read CPLD */
506 debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
wdenk708521a2003-09-12 15:35:15 +0000507
wdenk61970fd2003-10-09 13:16:55 +0000508 /* print result to console */
509 print_identifier ();
510 if ((result & (1 << 16)) == 0)
511 printf("0\n");
512 else
513 printf("1\n");
wdenk708521a2003-09-12 15:35:15 +0000514 return 0;
515}
516
517
518int do_rotary_switch (void)
519{
wdenk61970fd2003-10-09 13:16:55 +0000520 int result;
521 /*
522 * Please note, that the default values of the direction bits are
523 * undefined after reset. So it is a good idea, to make first a dummy
524 * call to this function, to clear the direction bits and set so to
525 * proper values.
526 */
wdenk708521a2003-09-12 15:35:15 +0000527
wdenk61970fd2003-10-09 13:16:55 +0000528 result = *CPLD_ROTARY_SWITCH; /* read CPLD */
529 debug ("%s: cpld_inc (32 bit) %#x\n", __FUNCTION__, result);
wdenk708521a2003-09-12 15:35:15 +0000530
wdenk61970fd2003-10-09 13:16:55 +0000531 *CPLD_ROTARY_SWITCH |= (3 << 16); /* clear direction bits in CPLD */
wdenk708521a2003-09-12 15:35:15 +0000532
wdenk61970fd2003-10-09 13:16:55 +0000533 /* print result to console */
534 print_identifier ();
535 if ((result & (1 << 16)) == (1 << 16))
536 printf("R");
537 if ((result & (1 << 17)) == (1 << 17))
538 printf("L");
539 if (((result & (1 << 16)) == 0) && ((result & (1 << 17)) == 0))
540 printf("0");
541 if ((result & (1 << 18)) == 0)
542 printf("0\n");
543 else
544 printf("1\n");
wdenk708521a2003-09-12 15:35:15 +0000545 return 0;
546}
547
548
549int do_vfd_id (void)
550{
wdenk61970fd2003-10-09 13:16:55 +0000551 int i;
552 long int pcup_old, pccon_old;
553 int vfd_board_id;
554 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
wdenk708521a2003-09-12 15:35:15 +0000555
556 /* try to red vfd board id from the value defined by pull-ups */
557
wdenk61970fd2003-10-09 13:16:55 +0000558 pcup_old = gpio->PCUP;
559 pccon_old = gpio->PCCON;
wdenk708521a2003-09-12 15:35:15 +0000560
561 gpio->PCUP = (gpio->PCUP & 0xFFF0); /* activate GPC0...GPC3 pull-ups */
562 gpio->PCCON = (gpio->PCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as
wdenk61970fd2003-10-09 13:16:55 +0000563 * inputs */
wdenk708521a2003-09-12 15:35:15 +0000564 udelay (10); /* allow signals to settle */
565 vfd_board_id = (~gpio->PCDAT) & 0x000F; /* read GPC0...GPC3 port pins */
566
wdenk61970fd2003-10-09 13:16:55 +0000567 gpio->PCCON = pccon_old;
568 gpio->PCUP = pcup_old;
wdenk708521a2003-09-12 15:35:15 +0000569
wdenk61970fd2003-10-09 13:16:55 +0000570 /* print vfd_board_id to console */
571 print_identifier ();
572 for (i = 0; i < 4; i++) {
573 if ((vfd_board_id & (1 << i)) == 0)
574 printf("0");
575 else
576 printf("1");
577 }
578 printf("\n");
wdenk708521a2003-09-12 15:35:15 +0000579 return 0;
580}
581
wdenk61970fd2003-10-09 13:16:55 +0000582int do_buzzer (char **argv)
wdenk708521a2003-09-12 15:35:15 +0000583{
wdenk61970fd2003-10-09 13:16:55 +0000584 int counter;
wdenk708521a2003-09-12 15:35:15 +0000585
586 S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
wdenk61970fd2003-10-09 13:16:55 +0000587 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
wdenk708521a2003-09-12 15:35:15 +0000588
wdenk61970fd2003-10-09 13:16:55 +0000589 /* set prescaler for timer 2, 3 and 4 */
590 timers->TCFG0 &= ~0xFF00;
wdenk708521a2003-09-12 15:35:15 +0000591 timers->TCFG0 |= 0x0F00;
592
wdenk61970fd2003-10-09 13:16:55 +0000593 /* set divider for timer 2 */
wdenk708521a2003-09-12 15:35:15 +0000594 timers->TCFG1 &= ~0xF00;
595 timers->TCFG1 |= 0x300;
596
wdenk61970fd2003-10-09 13:16:55 +0000597 /* set frequency */
598 counter = (PCLK / BUZZER_FREQ) >> 9;
599 timers->ch[2].TCNTB = counter;
wdenk708521a2003-09-12 15:35:15 +0000600 timers->ch[2].TCMPB = counter / 2;
601
wdenk61970fd2003-10-09 13:16:55 +0000602 if (strcmp (argv[2], "on") == 0) {
603 debug ("%s: frequency: %d\n", __FUNCTION__,
604 BUZZER_FREQ);
wdenk708521a2003-09-12 15:35:15 +0000605
wdenk61970fd2003-10-09 13:16:55 +0000606 /* configure pin GPD7 as TOUT2 */
607 gpio->PDCON &= ~0xC000;
608 gpio->PDCON |= 0x8000;
wdenk708521a2003-09-12 15:35:15 +0000609
wdenk61970fd2003-10-09 13:16:55 +0000610 /* start */
611 timers->TCON = (timers->TCON | UPDATE2 | RELOAD2) &
612 ~INVERT2;
613 timers->TCON = (timers->TCON | START2) & ~UPDATE2;
614 return (0);
615 }
616 else if (strcmp (argv[2], "off") == 0) {
617 /* stop */
618 timers->TCON &= ~(START2 | RELOAD2);
wdenk708521a2003-09-12 15:35:15 +0000619
wdenk61970fd2003-10-09 13:16:55 +0000620 /* configure GPD7 as output and set to low */
621 gpio->PDCON &= ~0xC000;
622 gpio->PDCON |= 0x4000;
623 gpio->PDDAT &= ~0x80;
624 return (0);
625 }
wdenk708521a2003-09-12 15:35:15 +0000626
wdenk61970fd2003-10-09 13:16:55 +0000627 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
628 return 1;
wdenk708521a2003-09-12 15:35:15 +0000629}
630
631
632int do_led (char **argv)
633{
wdenk61970fd2003-10-09 13:16:55 +0000634 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
wdenk708521a2003-09-12 15:35:15 +0000635
wdenk61970fd2003-10-09 13:16:55 +0000636 /* configure PC14 and PC15 as output */
637 gpio->PCCON &= ~(0xF << 28);
638 gpio->PCCON |= (0x5 << 28);
wdenk708521a2003-09-12 15:35:15 +0000639
wdenk61970fd2003-10-09 13:16:55 +0000640 /* configure PD0 and PD4 as output */
641 gpio->PDCON &= ~((0x3 << 8) | 0x3);
642 gpio->PDCON |= ((0x1 << 8) | 0x1);
wdenk708521a2003-09-12 15:35:15 +0000643
wdenk61970fd2003-10-09 13:16:55 +0000644 switch (simple_strtoul(argv[2], NULL, 10)) {
wdenk708521a2003-09-12 15:35:15 +0000645
646 case 0:
647 case 1:
648 break;
649
wdenk61970fd2003-10-09 13:16:55 +0000650 case 2:
651 if (strcmp (argv[3], "on") == 0)
652 gpio->PCDAT |= (1 << 14);
653 else
654 gpio->PCDAT &= ~(1 << 14);
655 return 0;
wdenk708521a2003-09-12 15:35:15 +0000656
wdenk61970fd2003-10-09 13:16:55 +0000657 case 3:
658 if (strcmp (argv[3], "on") == 0)
659 gpio->PCDAT |= (1 << 15);
660 else
661 gpio->PCDAT &= ~(1 << 15);
662 return 0;
wdenk708521a2003-09-12 15:35:15 +0000663
wdenk61970fd2003-10-09 13:16:55 +0000664 case 4:
665 if (strcmp (argv[3], "on") == 0)
666 gpio->PDDAT |= (1 << 0);
667 else
668 gpio->PDDAT &= ~(1 << 0);
669 return 0;
wdenk708521a2003-09-12 15:35:15 +0000670
wdenk61970fd2003-10-09 13:16:55 +0000671 case 5:
672 if (strcmp (argv[3], "on") == 0)
673 gpio->PDDAT |= (1 << 4);
674 else
675 gpio->PDDAT &= ~(1 << 4);
676 return 0;
wdenk708521a2003-09-12 15:35:15 +0000677
wdenk61970fd2003-10-09 13:16:55 +0000678 default:
679 break;
wdenk708521a2003-09-12 15:35:15 +0000680
wdenk61970fd2003-10-09 13:16:55 +0000681 }
682 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
683 return 1;
wdenk708521a2003-09-12 15:35:15 +0000684}
685
686
687int do_full_bridge (char **argv)
688{
wdenk61970fd2003-10-09 13:16:55 +0000689 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
wdenk708521a2003-09-12 15:35:15 +0000690
wdenk61970fd2003-10-09 13:16:55 +0000691 /* configure PD5 and PD6 as output */
692 gpio->PDCON &= ~((0x3 << 5*2) | (0x3 << 6*2));
693 gpio->PDCON |= ((0x1 << 5*2) | (0x1 << 6*2));
wdenk708521a2003-09-12 15:35:15 +0000694
wdenk61970fd2003-10-09 13:16:55 +0000695 if (strcmp (argv[2], "+") == 0) {
696 gpio->PDDAT |= (1 << 5);
697 gpio->PDDAT |= (1 << 6);
698 return 0;
699 }
700 else if (strcmp (argv[2], "-") == 0) {
701 gpio->PDDAT &= ~(1 << 5);
702 gpio->PDDAT |= (1 << 6);
703 return 0;
704 }
705 else if (strcmp (argv[2], "off") == 0) {
706 gpio->PDDAT &= ~(1 << 5);
707 gpio->PDDAT &= ~(1 << 6);
708 return 0;
709 }
710 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
711 return 1;
wdenk708521a2003-09-12 15:35:15 +0000712}
713
714/* val must be in [0, 4095] */
715static inline unsigned long tsc2000_to_uv (u16 val)
716{
717 return ((250000 * val) / 4096) * 10;
718}
719
720
721int do_dac (char **argv)
722{
wdenk61970fd2003-10-09 13:16:55 +0000723 int brightness;
wdenk708521a2003-09-12 15:35:15 +0000724
wdenk61970fd2003-10-09 13:16:55 +0000725 /* initialize SPI */
726 spi_init ();
wdenk708521a2003-09-12 15:35:15 +0000727
wdenk61970fd2003-10-09 13:16:55 +0000728 if (((brightness = simple_strtoul (argv[2], NULL, 10)) < 0) ||
729 (brightness > 255)) {
730 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
731 return 1;
732 }
733 tsc2000_write(TSC2000_REG_DACCTL, 0x0); /* Power up DAC */
wdenk708521a2003-09-12 15:35:15 +0000734 tsc2000_write(TSC2000_REG_DAC, brightness & 0xff);
735
wdenk61970fd2003-10-09 13:16:55 +0000736 return 0;
wdenk708521a2003-09-12 15:35:15 +0000737}
738
739
740int do_v_bat (void)
741{
wdenk61970fd2003-10-09 13:16:55 +0000742 unsigned long ret, res;
wdenk708521a2003-09-12 15:35:15 +0000743
wdenk61970fd2003-10-09 13:16:55 +0000744 /* initialize SPI */
745 spi_init ();
wdenk708521a2003-09-12 15:35:15 +0000746
747 tsc2000_write(TSC2000_REG_ADC, 0x1836);
748
wdenk61970fd2003-10-09 13:16:55 +0000749 /* now wait for data available */
750 adc_wait_conversion_done();
wdenk708521a2003-09-12 15:35:15 +0000751
752 ret = tsc2000_read(TSC2000_REG_BAT1);
753 res = (tsc2000_to_uv(ret) + 1250) / 2500;
754 res += (ERROR_BATTERY * res) / 1000;
755
wdenk61970fd2003-10-09 13:16:55 +0000756 print_identifier ();
757 printf ("%ld", (res / 100));
758 printf (".%ld", ((res % 100) / 10));
759 printf ("%ld V\n", (res % 10));
wdenk708521a2003-09-12 15:35:15 +0000760 return 0;
761}
762
763
764int do_pressure (void)
765{
wdenk61970fd2003-10-09 13:16:55 +0000766 /* initialize SPI */
767 spi_init ();
wdenk708521a2003-09-12 15:35:15 +0000768
wdenk61970fd2003-10-09 13:16:55 +0000769 tsc2000_write(TSC2000_REG_ADC, 0x2436);
wdenk708521a2003-09-12 15:35:15 +0000770
wdenk61970fd2003-10-09 13:16:55 +0000771 /* now wait for data available */
772 adc_wait_conversion_done();
wdenk708521a2003-09-12 15:35:15 +0000773
wdenk61970fd2003-10-09 13:16:55 +0000774 print_identifier ();
775 printf ("%d\n", tsc2000_read(TSC2000_REG_AUX2));
wdenk708521a2003-09-12 15:35:15 +0000776 return 0;
777}
778
779
780int do_motor_contact (void)
781{
wdenk61970fd2003-10-09 13:16:55 +0000782 int result;
wdenk708521a2003-09-12 15:35:15 +0000783
wdenk61970fd2003-10-09 13:16:55 +0000784 result = *CPLD_FILL_LEVEL; /* read CPLD */
785 debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
wdenk708521a2003-09-12 15:35:15 +0000786
wdenk61970fd2003-10-09 13:16:55 +0000787 /* print result to console */
788 print_identifier ();
789 if ((result & (1 << 17)) == 0)
790 printf("0\n");
791 else
792 printf("1\n");
793 return 0;
wdenk708521a2003-09-12 15:35:15 +0000794}
795
796int do_motor (char **argv)
797{
798 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
799
800 /* Configure I/O port */
801 gpio->PGCON &= ~(0x3 << 0);
802 gpio->PGCON |= (0x1 << 0);
803
wdenk61970fd2003-10-09 13:16:55 +0000804 if (strcmp (argv[2], "on") == 0) {
805 gpio->PGDAT &= ~(1 << 0);
806 return 0;
807 }
808 if (strcmp (argv[2], "off") == 0) {
809 gpio->PGDAT |= (1 << 0);
810 return 0;
811 }
812 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
813 return 1;
wdenk708521a2003-09-12 15:35:15 +0000814}
815
816static void print_identifier (void)
817{
wdenk61970fd2003-10-09 13:16:55 +0000818 printf ("## FKT: ");
wdenk708521a2003-09-12 15:35:15 +0000819}
820
821int do_pwm (char **argv)
822{
wdenk61970fd2003-10-09 13:16:55 +0000823 int counter;
824 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
wdenk708521a2003-09-12 15:35:15 +0000825 S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
826
wdenk61970fd2003-10-09 13:16:55 +0000827 if (strcmp (argv[2], "on") == 0) {
828 /* configure pin GPD8 as TOUT3 */
829 gpio->PDCON &= ~(0x3 << 8*2);
830 gpio->PDCON |= (0x2 << 8*2);
wdenk708521a2003-09-12 15:35:15 +0000831
wdenk61970fd2003-10-09 13:16:55 +0000832 /* set prescaler for timer 2, 3 and 4 */
833 timers->TCFG0 &= ~0xFF00;
834 timers->TCFG0 |= 0x0F00;
wdenk708521a2003-09-12 15:35:15 +0000835
wdenk61970fd2003-10-09 13:16:55 +0000836 /* set divider for timer 3 */
837 timers->TCFG1 &= ~(0xf << 12);
838 timers->TCFG1 |= (0x3 << 12);
wdenk708521a2003-09-12 15:35:15 +0000839
wdenk61970fd2003-10-09 13:16:55 +0000840 /* set frequency */
841 counter = (PCLK / PWM_FREQ) >> 9;
842 timers->ch[3].TCNTB = counter;
843 timers->ch[3].TCMPB = counter / 2;
wdenk708521a2003-09-12 15:35:15 +0000844
wdenk61970fd2003-10-09 13:16:55 +0000845 /* start timer */
846 timers->TCON = (timers->TCON | UPDATE3 | RELOAD3) & ~INVERT3;
847 timers->TCON = (timers->TCON | START3) & ~UPDATE3;
848 return 0;
849 }
850 if (strcmp (argv[2], "off") == 0) {
wdenk708521a2003-09-12 15:35:15 +0000851
wdenk61970fd2003-10-09 13:16:55 +0000852 /* stop timer */
853 timers->TCON &= ~(START2 | RELOAD2);
wdenk708521a2003-09-12 15:35:15 +0000854
wdenk61970fd2003-10-09 13:16:55 +0000855 /* configure pin GPD8 as output and set to 0 */
856 gpio->PDCON &= ~(0x3 << 8*2);
857 gpio->PDCON |= (0x1 << 8*2);
858 gpio->PDDAT &= ~(1 << 8);
859 return 0;
860 }
861 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
862 return 1;
wdenk708521a2003-09-12 15:35:15 +0000863}
864
865
866int do_thermo (char **argv)
867{
wdenk61970fd2003-10-09 13:16:55 +0000868 int channel, res;
wdenk708521a2003-09-12 15:35:15 +0000869
wdenk61970fd2003-10-09 13:16:55 +0000870 tsc2000_reg_init ();
wdenk708521a2003-09-12 15:35:15 +0000871
wdenk61970fd2003-10-09 13:16:55 +0000872 if (strcmp (argv[2], "all") == 0) {
873 int i;
874 for (i=0; i <= 15; i++) {
875 res = tsc2000_read_channel(i);
876 print_identifier ();
877 printf ("c%d: %d\n", i, res);
878 }
879 return 0;
880 }
881 channel = simple_strtoul (argv[2], NULL, 10);
882 res = tsc2000_read_channel(channel);
883 print_identifier ();
884 printf ("%d\n", res);
885 return 0; /* return OK */
wdenk708521a2003-09-12 15:35:15 +0000886}
887
888
wdenk708521a2003-09-12 15:35:15 +0000889int do_touch (char **argv)
890{
wdenk61970fd2003-10-09 13:16:55 +0000891 int x, y;
wdenk708521a2003-09-12 15:35:15 +0000892
wdenk61970fd2003-10-09 13:16:55 +0000893 if (strcmp (argv[2], "tl") == 0) {
wdenkc35ba4e2004-03-14 22:25:36 +0000894#ifdef CONFIG_TOUCH_WAIT_PRESSED
wdenk61970fd2003-10-09 13:16:55 +0000895 touch_wait_pressed();
896#else
897 {
898 int i;
899 for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
900 if (touch_check_pressed ()) {
901 break;
902 }
903 udelay (1000); /* pause 1 ms */
904 }
905 }
906 if (!touch_check_pressed()) {
907 print_identifier ();
908 printf ("error: touch not pressed\n");
909 return 1;
910 }
911#endif /* CONFIG_TOUCH_WAIT_PRESSED */
912 touch_read_x_y (&x, &y);
wdenk708521a2003-09-12 15:35:15 +0000913
wdenk61970fd2003-10-09 13:16:55 +0000914 print_identifier ();
915 printf ("x=%d y=%d\n", x, y);
916 return touch_write_clibration_values (CALIB_TL, x, y);
917 }
918 else if (strcmp (argv[2], "dr") == 0) {
wdenkc35ba4e2004-03-14 22:25:36 +0000919#ifdef CONFIG_TOUCH_WAIT_PRESSED
wdenk61970fd2003-10-09 13:16:55 +0000920 touch_wait_pressed();
921#else
922 {
923 int i;
924 for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
925 if (touch_check_pressed ()) {
926 break;
927 }
928 udelay (1000); /* pause 1 ms */
929 }
930 }
931 if (!touch_check_pressed()) {
932 print_identifier ();
933 printf ("error: touch not pressed\n");
934 return 1;
935 }
936#endif /* CONFIG_TOUCH_WAIT_PRESSED */
937 touch_read_x_y (&x, &y);
wdenk708521a2003-09-12 15:35:15 +0000938
wdenk61970fd2003-10-09 13:16:55 +0000939 print_identifier ();
940 printf ("x=%d y=%d\n", x, y);
wdenk708521a2003-09-12 15:35:15 +0000941
wdenk61970fd2003-10-09 13:16:55 +0000942 return touch_write_clibration_values (CALIB_DR, x, y);
943 }
944 return 1; /* not "tl", nor "dr", so return error */
wdenk708521a2003-09-12 15:35:15 +0000945}
946
947
wdenk61970fd2003-10-09 13:16:55 +0000948#ifdef CONFIG_TOUCH_WAIT_PRESSED
wdenk708521a2003-09-12 15:35:15 +0000949static void touch_wait_pressed (void)
950{
wdenk61970fd2003-10-09 13:16:55 +0000951 while (!(tsc2000_read(TSC2000_REG_ADC) & TC_PSM));
wdenk708521a2003-09-12 15:35:15 +0000952}
953
wdenk61970fd2003-10-09 13:16:55 +0000954#else
955static int touch_check_pressed (void)
956{
957 return (tsc2000_read(TSC2000_REG_ADC) & TC_PSM);
958}
959#endif /* CONFIG_TOUCH_WAIT_PRESSED */
wdenk708521a2003-09-12 15:35:15 +0000960
961static int touch_write_clibration_values (int calib_point, int x, int y)
962{
Jon Loeligere11c1232007-07-09 18:45:16 -0500963#if defined(CONFIG_CMD_I2C)
wdenk61970fd2003-10-09 13:16:55 +0000964 int x_verify = 0;
965 int y_verify = 0;
966
967 tsc2000_reg_init ();
968
969 if (calib_point == CALIB_TL) {
970 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
Wolfgang Denk031621b2006-06-26 10:54:52 +0200971 (unsigned char *)&x, 2)) {
wdenk61970fd2003-10-09 13:16:55 +0000972 return 1;
973 }
974 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
Wolfgang Denk031621b2006-06-26 10:54:52 +0200975 (unsigned char *)&y, 2)) {
wdenk61970fd2003-10-09 13:16:55 +0000976 return 1;
977 }
978
979 /* verify written values */
980 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
Wolfgang Denk031621b2006-06-26 10:54:52 +0200981 (unsigned char *)&x_verify, 2)) {
wdenk61970fd2003-10-09 13:16:55 +0000982 return 1;
983 }
984 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
Wolfgang Denk031621b2006-06-26 10:54:52 +0200985 (unsigned char *)&y_verify, 2)) {
wdenk61970fd2003-10-09 13:16:55 +0000986 return 1;
987 }
988 if ((y != y_verify) || (x != x_verify)) {
989 print_identifier ();
990 printf ("error: verify error\n");
991 return 1;
992 }
993 return 0; /* no error */
994 }
995 else if (calib_point == CALIB_DR) {
996 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
Wolfgang Denk031621b2006-06-26 10:54:52 +0200997 (unsigned char *)&x, 2)) {
wdenk61970fd2003-10-09 13:16:55 +0000998 return 1;
999 }
1000 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
Wolfgang Denk031621b2006-06-26 10:54:52 +02001001 (unsigned char *)&y, 2)) {
wdenk61970fd2003-10-09 13:16:55 +00001002 return 1;
1003 }
wdenk708521a2003-09-12 15:35:15 +00001004
wdenk61970fd2003-10-09 13:16:55 +00001005 /* verify written values */
1006 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
Wolfgang Denk031621b2006-06-26 10:54:52 +02001007 (unsigned char *)&x_verify, 2)) {
wdenk61970fd2003-10-09 13:16:55 +00001008 return 1;
1009 }
1010 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
Wolfgang Denk031621b2006-06-26 10:54:52 +02001011 (unsigned char *)&y_verify, 2)) {
wdenk61970fd2003-10-09 13:16:55 +00001012 return 1;
1013 }
1014 if ((y != y_verify) || (x != x_verify)) {
1015 print_identifier ();
1016 printf ("error: verify error\n");
1017 return 1;
1018 }
1019 return 0;
1020 }
1021 return 1;
wdenk708521a2003-09-12 15:35:15 +00001022#else
Jon Loeliger761ea742007-07-10 10:48:22 -05001023 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
wdenk61970fd2003-10-09 13:16:55 +00001024 "to EEPROM\n");
1025 return (1);
Jon Loeliger761ea742007-07-10 10:48:22 -05001026#endif
wdenk708521a2003-09-12 15:35:15 +00001027}
1028
1029
1030static void touch_read_x_y (int *px, int *py)
1031{
wdenk61970fd2003-10-09 13:16:55 +00001032 tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD0 | TC_AD1);
1033 adc_wait_conversion_done();
1034 *px = tsc2000_read(TSC2000_REG_X);
wdenk708521a2003-09-12 15:35:15 +00001035
wdenk61970fd2003-10-09 13:16:55 +00001036 tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD2);
1037 adc_wait_conversion_done();
1038 *py = tsc2000_read(TSC2000_REG_Y);
wdenk708521a2003-09-12 15:35:15 +00001039}
1040
1041
wdenk708521a2003-09-12 15:35:15 +00001042int do_rs485 (char **argv)
1043{
wdenk61970fd2003-10-09 13:16:55 +00001044 int timeout;
1045 char data[RS485_MAX_RECEIVE_BUF_LEN];
wdenk708521a2003-09-12 15:35:15 +00001046
wdenk61970fd2003-10-09 13:16:55 +00001047 if (strcmp (argv[2], "send") == 0) {
1048 return (rs485_send_line (argv[3]));
1049 }
1050 else if (strcmp (argv[2], "receive") == 0) {
1051 timeout = simple_strtoul(argv[3], NULL, 10);
1052 if (rs485_receive_chars (data, timeout) != 0) {
1053 print_identifier ();
1054 printf ("## nothing received\n");
1055 return (1);
1056 }
1057 else {
1058 print_identifier ();
1059 printf ("%s\n", data);
1060 return (0);
1061 }
1062 }
1063 printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1064 return (1); /* unknown command, return error */
wdenk708521a2003-09-12 15:35:15 +00001065}
1066
1067
1068static int rs485_send_line (const char *data)
1069{
wdenk61970fd2003-10-09 13:16:55 +00001070 rs485_init ();
1071 trab_rs485_enable_tx ();
1072 rs485_puts (data);
1073 rs485_putc ('\n');
wdenk708521a2003-09-12 15:35:15 +00001074
wdenk61970fd2003-10-09 13:16:55 +00001075 return (0);
wdenk708521a2003-09-12 15:35:15 +00001076}
1077
1078
1079static int rs485_receive_chars (char *data, int timeout)
1080{
wdenk61970fd2003-10-09 13:16:55 +00001081 int i;
1082 int receive_count = 0;
wdenk708521a2003-09-12 15:35:15 +00001083
wdenk61970fd2003-10-09 13:16:55 +00001084 rs485_init ();
1085 trab_rs485_enable_rx ();
wdenk708521a2003-09-12 15:35:15 +00001086
wdenk61970fd2003-10-09 13:16:55 +00001087 /* test every 1 ms for received characters to avoid a receive FIFO
1088 * overrun (@ 38.400 Baud) */
1089 for (i = 0; i < (timeout * 1000); i++) {
1090 while (rs485_tstc ()) {
1091 if (receive_count >= RS485_MAX_RECEIVE_BUF_LEN-1)
1092 break;
1093 *data++ = rs485_getc ();
1094 receive_count++;
1095 }
1096 udelay (1000); /* pause 1 ms */
1097 }
1098 *data = '\0'; /* terminate string */
wdenk708521a2003-09-12 15:35:15 +00001099
wdenk61970fd2003-10-09 13:16:55 +00001100 if (receive_count == 0)
1101 return (1);
1102 else
1103 return (0);
wdenk708521a2003-09-12 15:35:15 +00001104}
1105
1106
1107int do_serial_number (char **argv)
1108{
Jon Loeligere11c1232007-07-09 18:45:16 -05001109#if defined(CONFIG_CMD_I2C)
wdenk61970fd2003-10-09 13:16:55 +00001110 unsigned int serial_number;
wdenk708521a2003-09-12 15:35:15 +00001111
wdenk61970fd2003-10-09 13:16:55 +00001112 if (strcmp (argv[2], "read") == 0) {
1113 if (i2c_read (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
Wolfgang Denk031621b2006-06-26 10:54:52 +02001114 (unsigned char *)&serial_number, 4)) {
wdenk61970fd2003-10-09 13:16:55 +00001115 printf ("could not read from eeprom\n");
1116 return (1);
1117 }
1118 print_identifier ();
1119 printf ("%08d\n", serial_number);
1120 return (0);
1121 }
1122 else if (strcmp (argv[2], "write") == 0) {
1123 serial_number = simple_strtoul(argv[3], NULL, 10);
1124 if (i2c_write (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
Wolfgang Denk031621b2006-06-26 10:54:52 +02001125 (unsigned char *)&serial_number, 4)) {
wdenk61970fd2003-10-09 13:16:55 +00001126 printf ("could not write to eeprom\n");
1127 return (1);
1128 }
1129 return (0);
1130 }
1131 printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1132 return (1); /* unknown command, return error */
wdenk708521a2003-09-12 15:35:15 +00001133#else
Jon Loeliger761ea742007-07-10 10:48:22 -05001134 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
wdenk61970fd2003-10-09 13:16:55 +00001135 "to EEPROM\n");
1136 return (1);
Jon Loeliger761ea742007-07-10 10:48:22 -05001137#endif
wdenk708521a2003-09-12 15:35:15 +00001138}
1139
1140
1141int do_crc16 (void)
1142{
Jon Loeligere11c1232007-07-09 18:45:16 -05001143#if defined(CONFIG_CMD_I2C)
wdenk61970fd2003-10-09 13:16:55 +00001144 int crc;
Wolfgang Denk031621b2006-06-26 10:54:52 +02001145 unsigned char buf[EEPROM_MAX_CRC_BUF];
wdenk708521a2003-09-12 15:35:15 +00001146
wdenk61970fd2003-10-09 13:16:55 +00001147 if (i2c_read (I2C_EEPROM_DEV_ADDR, 0, 1, buf, 60)) {
1148 printf ("could not read from eeprom\n");
1149 return (1);
1150 }
1151 crc = 0; /* start value of crc calculation */
1152 crc = updcrc (crc, buf, 60);
wdenk708521a2003-09-12 15:35:15 +00001153
wdenk61970fd2003-10-09 13:16:55 +00001154 print_identifier ();
1155 printf ("crc16=%#04x\n", crc);
wdenk708521a2003-09-12 15:35:15 +00001156
Wolfgang Denk031621b2006-06-26 10:54:52 +02001157 if (i2c_write (I2C_EEPROM_DEV_ADDR, CRC16, 1, (unsigned char *)&crc,
wdenk61970fd2003-10-09 13:16:55 +00001158 sizeof (crc))) {
1159 printf ("could not read from eeprom\n");
1160 return (1);
1161 }
1162 return (0);
wdenk708521a2003-09-12 15:35:15 +00001163#else
Jon Loeliger761ea742007-07-10 10:48:22 -05001164 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
wdenk61970fd2003-10-09 13:16:55 +00001165 "to EEPROM\n");
1166 return (1);
Jon Loeliger761ea742007-07-10 10:48:22 -05001167#endif
wdenk708521a2003-09-12 15:35:15 +00001168}
1169
1170
1171/*
1172 * Calculate, intelligently, the CRC of a dataset incrementally given a
1173 * buffer full at a time.
1174 * Initialize crc to 0 for XMODEM, -1 for CCITT.
1175 *
1176 * Usage:
1177 * newcrc = updcrc( oldcrc, bufadr, buflen )
1178 * unsigned int oldcrc, buflen;
1179 * char *bufadr;
1180 *
1181 * Compile with -DTEST to generate program that prints CRC of stdin to stdout.
1182 * Compile with -DMAKETAB to print values for crctab to stdout
1183 */
1184
1185 /* the CRC polynomial. This is used by XMODEM (almost CCITT).
1186 * If you change P, you must change crctab[]'s initial value to what is
1187 * printed by initcrctab()
1188 */
1189#define P 0x1021
1190
1191 /* number of bits in CRC: don't change it. */
1192#define W 16
1193
1194 /* this the number of bits per char: don't change it. */
1195#define B 8
1196
1197static unsigned short crctab[1<<B] = { /* as calculated by initcrctab() */
1198 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1199 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1200 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1201 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1202 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1203 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1204 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1205 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1206 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1207 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1208 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1209 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1210 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1211 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1212 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1213 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1214 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1215 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1216 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1217 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1218 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1219 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1220 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1221 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1222 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1223 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1224 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1225 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1226 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1227 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1228 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1229 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1230 };
1231
1232static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
wdenk61970fd2003-10-09 13:16:55 +00001233 unsigned int icnt )
1234{
1235 register unsigned short crc = icrc;
1236 register unsigned char *cp = icp;
1237 register unsigned int cnt = icnt;
1238
1239 while (cnt--)
1240 crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];
1241
1242 return (crc);
1243}
1244
1245
1246int do_gain (char **argv)
1247{
1248 int range;
1249
1250 range = simple_strtoul (argv[2], NULL, 10);
1251 if ((range < 1) || (range > 3))
1252 {
1253 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1254 return 1;
1255 }
1256
1257 tsc2000_set_range (range);
1258 return (0);
1259}
1260
1261
1262int do_eeprom (char **argv)
1263{
Jon Loeligere11c1232007-07-09 18:45:16 -05001264#if defined(CONFIG_CMD_I2C)
wdenk61970fd2003-10-09 13:16:55 +00001265 if (strcmp (argv[2], "read") == 0) {
1266 return (trab_eeprom_read (argv));
1267 }
1268
1269 else if (strcmp (argv[2], "write") == 0) {
1270 return (trab_eeprom_write (argv));
1271 }
1272
1273 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1274 return (1);
1275#else
Jon Loeliger761ea742007-07-10 10:48:22 -05001276 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
wdenk61970fd2003-10-09 13:16:55 +00001277 "to EEPROM\n");
1278 return (1);
Jon Loeliger761ea742007-07-10 10:48:22 -05001279#endif
wdenk61970fd2003-10-09 13:16:55 +00001280}
1281
Jon Loeligere11c1232007-07-09 18:45:16 -05001282#if defined(CONFIG_CMD_I2C)
wdenk61970fd2003-10-09 13:16:55 +00001283static int trab_eeprom_read (char **argv)
1284{
1285 int i;
1286 int len;
1287 unsigned int addr;
1288 long int value = 0;
1289 uchar *buffer;
1290
1291 buffer = (uchar *) &value;
1292 addr = simple_strtoul (argv[3], NULL, 10);
1293 addr &= 0xfff;
1294 len = simple_strtoul (argv[4], NULL, 10);
1295 if ((len < 1) || (len > 4)) {
1296 printf ("%s: invalid parameter %s\n", __FUNCTION__,
1297 argv[4]);
1298 return (1);
1299 }
1300 for (i = 0; i < len; i++) {
1301 if (i2c_read (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
1302 printf ("%s: could not read from i2c device %#x"
1303 ", addr %d\n", __FUNCTION__,
1304 I2C_EEPROM_DEV_ADDR, addr);
1305 return (1);
1306 }
1307 }
1308 print_identifier ();
1309 if (strcmp (argv[5], "-") == 0) {
1310 if (len == 1)
1311 printf ("%d\n", (signed char) value);
1312 else if (len == 2)
1313 printf ("%d\n", (signed short int) value);
1314 else
1315 printf ("%ld\n", value);
1316 }
1317 else {
1318 if (len == 1)
1319 printf ("%d\n", (unsigned char) value);
1320 else if (len == 2)
1321 printf ("%d\n", (unsigned short int) value);
1322 else
1323 printf ("%ld\n", (unsigned long int) value);
1324 }
1325 return (0);
1326}
1327
1328static int trab_eeprom_write (char **argv)
1329{
1330 int i;
1331 int len;
1332 unsigned int addr;
1333 long int value = 0;
1334 uchar *buffer;
1335
1336 buffer = (uchar *) &value;
1337 addr = simple_strtoul (argv[3], NULL, 10);
1338 addr &= 0xfff;
1339 len = simple_strtoul (argv[4], NULL, 10);
1340 if ((len < 1) || (len > 4)) {
1341 printf ("%s: invalid parameter %s\n", __FUNCTION__,
1342 argv[4]);
1343 return (1);
1344 }
1345 value = simple_strtol (argv[5], NULL, 10);
1346 debug ("value=%ld\n", value);
1347 for (i = 0; i < len; i++) {
1348 if (i2c_write (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
1349 printf ("%s: could not write to i2c device %d"
1350 ", addr %d\n", __FUNCTION__,
1351 I2C_EEPROM_DEV_ADDR, addr);
1352 return (1);
1353 }
1354#if 0
1355 printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
1356 "%#x+%d=%p=%#x \n",I2C_EEPROM_DEV_ADDR_DEV_ADDR , addr,
1357 i, addr+i, 1, buffer, i, buffer+i, *(buffer+i));
1358#endif
1359 udelay (30000); /* wait for EEPROM ready */
1360 }
1361 return (0);
1362}
1363
1364int i2c_write_multiple (uchar chip, uint addr, int alen,
1365 uchar *buffer, int len)
wdenk708521a2003-09-12 15:35:15 +00001366{
wdenk61970fd2003-10-09 13:16:55 +00001367 int i;
wdenk708521a2003-09-12 15:35:15 +00001368
wdenk61970fd2003-10-09 13:16:55 +00001369 if (alen != 1) {
1370 printf ("%s: addr len other than 1 not supported\n",
1371 __FUNCTION__);
1372 return (1);
1373 }
wdenk708521a2003-09-12 15:35:15 +00001374
wdenk61970fd2003-10-09 13:16:55 +00001375 for (i = 0; i < len; i++) {
1376 if (i2c_write (chip, addr+i, alen, buffer+i, 1)) {
1377 printf ("%s: could not write to i2c device %d"
1378 ", addr %d\n", __FUNCTION__, chip, addr);
1379 return (1);
1380 }
1381#if 0
1382 printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
1383 "%#x+%d=%p=\"%.1s\"\n", chip, addr, i, addr+i,
1384 alen, buffer, i, buffer+i, buffer+i);
1385#endif
1386
1387 udelay (30000);
1388 }
1389 return (0);
wdenk708521a2003-09-12 15:35:15 +00001390}
wdenk61970fd2003-10-09 13:16:55 +00001391
1392int i2c_read_multiple ( uchar chip, uint addr, int alen,
1393 uchar *buffer, int len)
1394{
1395 int i;
1396
1397 if (alen != 1) {
1398 printf ("%s: addr len other than 1 not supported\n",
1399 __FUNCTION__);
1400 return (1);
1401 }
1402
1403 for (i = 0; i < len; i++) {
1404 if (i2c_read (chip, addr+i, alen, buffer+i, 1)) {
1405 printf ("%s: could not read from i2c device %#x"
1406 ", addr %d\n", __FUNCTION__, chip, addr);
1407 return (1);
1408 }
1409 }
1410 return (0);
1411}
Jon Loeliger761ea742007-07-10 10:48:22 -05001412#endif