~ubuntu-branches/ubuntu/trusty/apex/trusty

« back to all changes in this revision

Viewing changes to src/mach-lh7a40x/cmd-karmaaccel.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2009-11-10 11:55:15 UTC
  • mfrom: (2.2.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091110115515-6jjsf6rc8py35awe
Tags: 1.6.10ubuntu1
* Merge from debian testing, remaining changes:
  - Move apex VMA address to 4MiB to leave enough space for the ubuntu
  kernel and not overwrite apex in ram when loading.
  - nslu2 configuration: set CONFIG_RAMDISK_SIZE=0x0055FFF0 instead of
  0x005FFFF0 to make enough room for ubuntu initramfs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* cmd-karmaaccel.c
 
2
 
 
3
   written by Marc Singer
 
4
   23 August 2006
 
5
 
 
6
   Copyright (C) 2006 Marc Singer
 
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
 
10
   version 2 as published by the Free Software Foundation.
 
11
   Please refer to the file debian/copyright for further details.
 
12
 
 
13
   -----------
 
14
   DESCRIPTION
 
15
   -----------
 
16
 
 
17
 Processing:
 
18
  Initialize the adc to its default state.
 
19
  Map all touchscreen pins to ADC input
 
20
  Set up the idle step to prevent false pen auto-triggering.
 
21
  Flush the result FIFO.
 
22
  Clear the pen and end of sequence interrupts.
 
23
  Set up the sequence as follows:
 
24
      0. Strong pullup on X+ pin, other pins float.
 
25
         Measure on pin x+. This measurement will be discarded.
 
26
         This step de-glitches any partial triggers.
 
27
      1. Weak pullup on X+ pin, X- floats, Y- to Ground and neg
 
28
         ref, Y+ floats (ratiometric).
 
29
         Measure on X+ pin. This measurement is used to verify
 
30
         the pen was down at the beginning of the coordinate
 
31
         measurement.
 
32
      2. X+ and X- float, Y- to Ground and neg
 
33
         ref, Y+ to VDDA_ADC and positive reference (ratiometric).
 
34
         Measure on pin x+. This is the X measurement.
 
35
      3. Repeat the X measurement 3 more times (we will average
 
36
         4 measurements to improve signal-to-noise.
 
37
      4. Y+ and Y- float, X- to Ground and neg
 
38
         ref, X+ to VDDA_ADC and positive reference (ratiometric).
 
39
         Measure on pin Y+. This is the Y measurement.
 
40
      5. Repeat the Y measurement 3 more times (we will average
 
41
         4 measurements to improve signal-to-noise.
 
42
      6. Strong pullup on X+ pin, other pins float.
 
43
         Measure on pin x+. This measurement will be discarded.
 
44
         This step de-glitches any partial triggers.
 
45
      7. Weak pullup on X+ pin, X- floats, Y- to Ground and neg
 
46
         ref, Y+ floats (ratiometric).
 
47
         Measure on X+ pin. This measurement is used to verify
 
48
         the pen was down at the end of the coordinate
 
49
         measurement.
 
50
 
 
51
 
 
52
*/
 
53
 
 
54
#include <config.h>
 
55
#include <driver.h>
 
56
#include <service.h>
 
57
#include <linux/string.h>
 
58
#include <apex.h>
 
59
#include <command.h>
 
60
#include <mach/hardware.h>
 
61
#include <console.h>
 
62
 
 
63
 
 
64
//#define TALK 1
 
65
 
 
66
#if defined (TALK)
 
67
#define PRINTF(f...)            printf (f)
 
68
#define ENTRY(l)                printf ("%s\n", __FUNCTION__)
 
69
#define DBG(l,f...)             do { if (TALK >= l) printf (f); } while (0)
 
70
#else
 
71
#define PRINTF(f...)            do {} while (0)
 
72
#define ENTRY(l)                do {} while (0)
 
73
#define DBG(l,f...)             do {} while (0)
 
74
#endif
 
75
 
 
76
#define ADC_FS_FFF              (1<<3)
 
77
#define ADC_FS_FEMPTY           (1<<2)
 
78
 
 
79
#define ADC_IC_BOI              (1<<2)
 
80
#define ADC_IC_PEN              (1<<1)
 
81
#define ADC_IC_EOS              (1<<0)
 
82
 
 
83
#define ADC_IS_BROWNOUT         (1<<4)
 
84
#define ADC_IS_PEN              (1<<3)
 
85
#define ADC_IS_EOS              (1<<2)
 
86
 
 
87
#define ADC_PC_CLKSEL_SHIFT     (8)
 
88
#define ADC_PC_CLKSEL_MASK      (7<<ADC_PC_CLKSEL_SHIFT)
 
89
#define ADC_PC_REFEN            (1<<5)
 
90
#define ADC_PC_BATEN            (1<<4)
 
91
#define ADC_PC_NOC_SHIFT        (0)
 
92
#define ADC_PC_NOC_MASK         (0xf)
 
93
#define ADC_PC_PWM_MASK         (3<<6)
 
94
#define ADC_PC_PWM_OFF          (0<<6)
 
95
#define ADC_PC_PWM_STANDBY      (1<<6)
 
96
#define ADC_PC_PWM_RUN          (2<<6)
 
97
 
 
98
#define ADC_HW_SETTIME_SHIFT    (7)
 
99
#define ADC_HW_SETTIME_MASK     (0x1ff<<ADC_HW_SETTIME_SHIFT)
 
100
#define ADC_HW_INP_SHIFT        (3)
 
101
#define ADC_HW_INP_MASK         (0xf<<ADC_HW_INP_SHIFT)
 
102
#define ADC_HW_INP_AN0          (0<<3)          /* UL/X+ */
 
103
#define ADC_HW_INP_AN1          (1<<3)          /* UR/X- */
 
104
#define ADC_HW_INP_AN2          (2<<3)          /* LL/Y+ */
 
105
#define ADC_HW_INP_AN3          (3<<3)          /* LR/Y- */
 
106
#define ADC_HW_INP_AN4          (4<<3)          /* Wiper */
 
107
#define ADC_HW_INP_AN5          (5<<3)
 
108
#define ADC_HW_INP_AN6          (6<<3)
 
109
#define ADC_HW_INP_AN7          (7<<3)
 
110
#define ADC_HW_INP_AN8          (8<<3)
 
111
#define ADC_HW_INP_AN9          (9<<3)
 
112
#define ADC_HW_INP_VREFN        (10<<3)         /* VREF- */
 
113
#define ADC_HW_INN_GND          (1<<2)
 
114
#define ADC_HW_INN_REFN         (0<<2)          /* VREF- */
 
115
#define ADC_HW_REFP_MASK        (3<<0)
 
116
#define ADC_HW_REFP_VREFP       (0<<0)          /* VREF+ */
 
117
#define ADC_HW_REFP_AN0         (1<<0)          /* UL/X+ */
 
118
#define ADC_HW_REFP_AN2         (2<<0)          /* LL/Y+ */
 
119
#define ADC_HW_REFP_AN8         (3<<0)
 
120
#define ADC_LW_REFN_VREFN       (0<<0)
 
121
#define ADC_LW_REFN_AN1         (1<<0)
 
122
#define ADC_LW_REFN_AN3         (2<<0)
 
123
#define ADC_LW_REFN_AN9         (3<<0)
 
124
#define ADC_LW_BIASCON_SHIFT    (2)
 
125
#define ADC_LW_BIASCON_MASK     (0xfff<<2)
 
126
 
 
127
#define ADC_LW_FET_AN0_VDD      (1<<2)
 
128
#define ADC_LW_FET_AN0_VDD100K  (1<<12)
 
129
#define ADC_LW_FET_AN1_VDD      (1<<3)
 
130
#define ADC_LW_FET_AN1_GND      (1<<4)
 
131
#define ADC_LW_FET_AN2_VDD      (1<<5)
 
132
#define ADC_LW_FET_AN2_GND      (1<<6)
 
133
#define ADC_LW_FET_AN3_GND      (1<<7)
 
134
#define ADC_LW_FET_AN4_VDD100K  (1<<13)
 
135
#define ADC_LW_FET_AN4_GND      (1<<8)
 
136
 
 
137
#define ADC_GC_SSM_MASK         (3<<0)
 
138
#define ADC_GC_SSM_SSB_PEN      (0<<0)
 
139
#define ADC_GC_SSM_PEN          (1<<0)
 
140
#define ADC_GC_SSM_SSB          (2<<0)
 
141
#define ADC_GC_SSM_CONT         (3<<0)
 
142
#define ADC_GC_SSB              (1<<2)
 
143
#define ADC_GC_FIFOWMK_SHIFT    (3)
 
144
#define ADC_GC_FIFOWMK_MASK     (0xf<<ADC_GC_FIFOWMK_SHIFT)
 
145
 
 
146
# define US_SETTLING            (20)            /* Signal stablization */
 
147
 
 
148
        /* We're aiming for sampling at about 400KHz */
 
149
 
 
150
#if defined (CONFIG_ARCH_LH79524) || defined (CONFIG_ARCH_LH79525)
 
151
# define ADC_CLKSEL             (0x7)
 
152
# define CLKSEL                 (1<<ADC_CLKSEL)
 
153
# define RCPC_ADCPRE_V          (1)
 
154
# define A2DCLK                 (50803200/RCPC_ADCPRE_V/CLKSEL)
 
155
#endif
 
156
 
 
157
#if defined (CONFIG_ARCH_LH7A404)
 
158
# define ADC_CLKSEL             (0x2)
 
159
# define CLKSEL                 (1<<ADC_CLKSEL)
 
160
# define A2DCLK                 (1843200/CLKSEL)
 
161
#endif
 
162
 
 
163
#define ADC_PC_CLKSEL_V         (ADC_CLKSEL<<ADC_PC_CLKSEL_SHIFT)
 
164
 
 
165
#define SETTIME(us)             (((A2DCLK*(us) + 1000000/2)/1000000)\
 
166
                                 <<ADC_HW_SETTIME_SHIFT)
 
167
 
 
168
#define SAMPLES                  (12)
 
169
 
 
170
static void accel_setup (void)
 
171
{
 
172
  int i;
 
173
 
 
174
  ENTRY (0);
 
175
 
 
176
  PRINTF ("adc: A2DCLK %d  SETTIME(US) %0xx\n", A2DCLK, SETTIME(US_SETTLING));
 
177
 
 
178
  ADC_IC = ADC_IC_BOI | ADC_IC_PEN | ADC_IC_EOS;
 
179
 
 
180
                                /* Flush the results FIFO */
 
181
  while ((ADC_FS & ADC_FS_FEMPTY) == 0)
 
182
    ADC_RR;
 
183
 
 
184
  MASK_AND_SET (ADC_PC,
 
185
                ADC_PC_NOC_MASK | ADC_PC_PWM_MASK,
 
186
                ((SAMPLES - 1)<<ADC_PC_NOC_SHIFT)|(ADC_PC_PWM_OFF)
 
187
                | ADC_PC_REFEN
 
188
                );
 
189
 
 
190
  MASK_AND_SET (ADC_GC,
 
191
                ADC_GC_SSM_MASK | ADC_GC_FIFOWMK_MASK,
 
192
//              ADC_GC_SSM_SSB
 
193
                ADC_GC_SSM_SSB_PEN
 
194
                //              | (12<<ADC_GC_FIFOWMK_SHIFT)
 
195
                );
 
196
 
 
197
//  ADC_PC |= ADC_PC_REFEN;
 
198
 
 
199
#define _HI(p)  (SETTIME (US_SETTLING) | (p) | ADC_HW_INN_REFN)
 
200
#define _LO(f)  (f)
 
201
 
 
202
        /* Idle */
 
203
  ADC_IHWCTRL = _HI (ADC_HW_INP_AN9);
 
204
  ADC_ILWCTRL = _LO (ADC_LW_REFN_AN9);  /* No bias control necessary */
 
205
 
 
206
        /* Sampling */
 
207
  for (i = 0; i < 16; ++i) {
 
208
    switch (i) {
 
209
    case 0:
 
210
    case 2:
 
211
    case 4:
 
212
    case 6:
 
213
    case 8:
 
214
    case 10:
 
215
    case 12:
 
216
    case 14:
 
217
      __REG(ADC_HWC_BASE_PHYS + i*4) = _HI (ADC_HW_INP_AN0 | ADC_HW_REFP_AN8);
 
218
      __REG(ADC_LWC_BASE_PHYS + i*4) = _LO (ADC_LW_REFN_AN9);
 
219
      break;
 
220
    case 1:
 
221
    case 3:
 
222
    case 5:
 
223
    case 7:
 
224
    case 9:
 
225
    case 11:
 
226
    case 13:
 
227
    case 15:
 
228
      __REG(ADC_HWC_BASE_PHYS + i*4) = _HI (ADC_HW_INP_AN1 | ADC_HW_REFP_AN8);
 
229
      __REG(ADC_LWC_BASE_PHYS + i*4) = _LO (ADC_LW_REFN_AN9);
 
230
      break;
 
231
    default:
 
232
      __REG(ADC_HWC_BASE_PHYS + i*4) = 0;
 
233
      __REG(ADC_LWC_BASE_PHYS + i*4) = 0;
 
234
      break;
 
235
    }
 
236
  }
 
237
 
 
238
  MASK_AND_SET (ADC_PC, ADC_PC_PWM_MASK, ADC_PC_PWM_STANDBY);
 
239
}
 
240
 
 
241
static void accel_init (void)
 
242
{
 
243
  int i;
 
244
 
 
245
  ENTRY (0);
 
246
 
 
247
  ADC_IM = 0; /* Disable all interrupts */
 
248
 
 
249
  ADC_PC = ADC_PC_CLKSEL_V | ADC_PC_PWM_OFF | (1<<ADC_PC_NOC_SHIFT);
 
250
  ADC_GC =
 
251
    ADC_GC_SSM_SSB
 
252
    | (0xf<<ADC_GC_FIFOWMK_SHIFT);
 
253
 
 
254
 
 
255
  for (i = 0; i < SAMPLES; ++i) {
 
256
    __REG(ADC_HWC_BASE_PHYS + i*4) = (0x1ff << ADC_HW_SETTIME_SHIFT)
 
257
      | (i << ADC_HW_INP_SHIFT) | ADC_HW_INN_GND | ADC_HW_REFP_VREFP;
 
258
    __REG(ADC_LWC_BASE_PHYS + i*4) = ADC_LW_REFN_VREFN;
 
259
  }
 
260
 
 
261
  ADC_IHWCTRL = (0x1ff << ADC_HW_SETTIME_SHIFT)
 
262
    | ADC_HW_INP_AN0 | ADC_HW_INN_GND | ADC_HW_REFP_VREFP;
 
263
  ADC_ILWCTRL = ADC_LW_REFN_VREFN;
 
264
 
 
265
                                /* Flush the results FIFO */
 
266
  while ((ADC_FS & ADC_FS_FEMPTY) == 0)
 
267
    ADC_RR;
 
268
 
 
269
  ADC_IC = ADC_IC_BOI | ADC_IC_PEN | ADC_IC_EOS;
 
270
 
 
271
  accel_setup ();
 
272
}
 
273
 
 
274
#define MS_TIMEOUT 2*1000
 
275
#define MS_ADC_DELAY 600
 
276
 
 
277
#define REF          ((1023*33)/10)
 
278
 
 
279
static int cmd_accel (int argc, const char** argv)
 
280
{
 
281
  unsigned long status;
 
282
  int i;
 
283
  unsigned long timeStart;
 
284
  int x = 0;
 
285
  int y = 0;
 
286
 
 
287
  while (1) {
 
288
//    printf ("\n\n\n\n\n");
 
289
 
 
290
    status = ADC_GS;
 
291
                                /* Flush the results FIFO */
 
292
    while ((ADC_FS & ADC_FS_FEMPTY) == 0)
 
293
      ADC_RR;
 
294
 
 
295
    PRINTF ("[%4lx %4lx] ", ADC_FS, status);
 
296
//    printf ("start %lx\n", status);
 
297
 
 
298
    ADC_IC |= ADC_IC_EOS | ADC_IC_PEN;
 
299
    ADC_GC |= (1<<2);           /* Start sampling */
 
300
 
 
301
    timeStart = timer_read ();
 
302
 
 
303
    do {
 
304
      if (ADC_IS & ADC_IS_EOS)
 
305
        break;
 
306
#if 0
 
307
      unsigned long l = ADC_GS;
 
308
      if ((l & (0xf<<4)) != (status & (0xf<<4)))
 
309
        printf ("state %lx\n", (l >> 4) & 0xf);
 
310
      status = l;
 
311
      if (((status >> 4) & 0xf) == 0x4) /* End of sequence */
 
312
        break;
 
313
      if (((status >> 4) & 0xf) == 0x1) /* Idle, which is really an error */
 
314
        break;
 
315
#endif
 
316
    } while (timer_delta (timeStart, timer_read ()) < MS_TIMEOUT);
 
317
 
 
318
    PRINTF ("-> [gs %lx %lx]\n", ADC_GS, ADC_FS);
 
319
//    printf ("fifo %lx\n", ADC_FS);
 
320
 
 
321
    for (i = 0; i < SAMPLES; ++i) {
 
322
      unsigned long v = ADC_RR;
 
323
      if (i == 0)
 
324
        x = v>>6;
 
325
      if (i == 1)
 
326
        y = v>>6;
 
327
//      printf ("%2d rr %5ld (%lx) - (%lx)\n", i, (v >> 6), (v & 0xf), ADC_FS);
 
328
      PRINTF (" %4ld", (v >> 6));
 
329
    }
 
330
 
 
331
    PRINTF ("\n");
 
332
 
 
333
    printf ("x %d.%d (%d)  y %d.%d (%d)\n",
 
334
            33*x/(1023*10),
 
335
            (33*x/1023)%10,
 
336
            x,
 
337
            33*y/(1023*10),
 
338
            (33*y/1023)%10,
 
339
            y);
 
340
 
 
341
 
 
342
    PRINTF ("fifo %4lx ", ADC_FS);
 
343
    PRINTF ("hw 0x%4lx  lw 0x%4lx\n", ADC_HW, ADC_LW);
 
344
 
 
345
    timeStart = timer_read ();
 
346
    while (timer_delta (timeStart, timer_read ()) < MS_ADC_DELAY)
 
347
      if (console->poll (0, 0))
 
348
        goto done;
 
349
//    printf ("\n\n\n\n\n");
 
350
  }
 
351
 
 
352
 done:
 
353
 
 
354
  return 0;
 
355
}
 
356
 
 
357
 
 
358
static __command struct command_d c_accel = {
 
359
  .command = "accel",
 
360
  .description = "test accelerometer",
 
361
  .func = cmd_accel,
 
362
};
 
363
 
 
364
static __service_7 struct service_d karma_accel_service = {
 
365
  .init = accel_init,
 
366
};