~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to hw/spitz.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2008-08-25 04:38:35 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825043835-8e3tftavy8bujdch
Tags: 0.9.1-6
[ Aurelien Jarno ]
* debian/control: 
  - Update list of supported targets (Closes: bug#488339).
* debian/qemu-make-debian-root:
  - Use mktemp instead of $$ to create temporary directories (Closes: 
    bug#496394).
* debian/links:
  - Add missing links to manpages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * PXA270-based Clamshell PDA platforms.
 
3
 *
 
4
 * Copyright (c) 2006 Openedhand Ltd.
 
5
 * Written by Andrzej Zaborowski <balrog@zabor.org>
 
6
 *
 
7
 * This code is licensed under the GNU GPL v2.
 
8
 */
 
9
 
 
10
#include "hw.h"
 
11
#include "pxa.h"
 
12
#include "arm-misc.h"
 
13
#include "sysemu.h"
 
14
#include "pcmcia.h"
 
15
#include "i2c.h"
 
16
#include "flash.h"
 
17
#include "qemu-timer.h"
 
18
#include "devices.h"
 
19
#include "console.h"
 
20
#include "block.h"
 
21
#include "audio/audio.h"
 
22
#include "boards.h"
 
23
 
 
24
#define spitz_printf(format, ...)       \
 
25
    fprintf(stderr, "%s: " format, __FUNCTION__, ##__VA_ARGS__)
 
26
#undef REG_FMT
 
27
#if TARGET_PHYS_ADDR_BITS == 32
 
28
#define REG_FMT                 "0x%02x"
 
29
#else
 
30
#define REG_FMT                 "0x%02lx"
 
31
#endif
 
32
 
 
33
/* Spitz Flash */
 
34
#define FLASH_BASE              0x0c000000
 
35
#define FLASH_ECCLPLB           0x00    /* Line parity 7 - 0 bit */
 
36
#define FLASH_ECCLPUB           0x04    /* Line parity 15 - 8 bit */
 
37
#define FLASH_ECCCP             0x08    /* Column parity 5 - 0 bit */
 
38
#define FLASH_ECCCNTR           0x0c    /* ECC byte counter */
 
39
#define FLASH_ECCCLRR           0x10    /* Clear ECC */
 
40
#define FLASH_FLASHIO           0x14    /* Flash I/O */
 
41
#define FLASH_FLASHCTL          0x18    /* Flash Control */
 
42
 
 
43
#define FLASHCTL_CE0            (1 << 0)
 
44
#define FLASHCTL_CLE            (1 << 1)
 
45
#define FLASHCTL_ALE            (1 << 2)
 
46
#define FLASHCTL_WP             (1 << 3)
 
47
#define FLASHCTL_CE1            (1 << 4)
 
48
#define FLASHCTL_RYBY           (1 << 5)
 
49
#define FLASHCTL_NCE            (FLASHCTL_CE0 | FLASHCTL_CE1)
 
50
 
 
51
struct sl_nand_s {
 
52
    target_phys_addr_t target_base;
 
53
    struct nand_flash_s *nand;
 
54
    uint8_t ctl;
 
55
    struct ecc_state_s ecc;
 
56
};
 
57
 
 
58
static uint32_t sl_readb(void *opaque, target_phys_addr_t addr)
 
59
{
 
60
    struct sl_nand_s *s = (struct sl_nand_s *) opaque;
 
61
    int ryby;
 
62
    addr -= s->target_base;
 
63
 
 
64
    switch (addr) {
 
65
#define BSHR(byte, from, to)    ((s->ecc.lp[byte] >> (from - to)) & (1 << to))
 
66
    case FLASH_ECCLPLB:
 
67
        return BSHR(0, 4, 0) | BSHR(0, 5, 2) | BSHR(0, 6, 4) | BSHR(0, 7, 6) |
 
68
                BSHR(1, 4, 1) | BSHR(1, 5, 3) | BSHR(1, 6, 5) | BSHR(1, 7, 7);
 
69
 
 
70
#define BSHL(byte, from, to)    ((s->ecc.lp[byte] << (to - from)) & (1 << to))
 
71
    case FLASH_ECCLPUB:
 
72
        return BSHL(0, 0, 0) | BSHL(0, 1, 2) | BSHL(0, 2, 4) | BSHL(0, 3, 6) |
 
73
                BSHL(1, 0, 1) | BSHL(1, 1, 3) | BSHL(1, 2, 5) | BSHL(1, 3, 7);
 
74
 
 
75
    case FLASH_ECCCP:
 
76
        return s->ecc.cp;
 
77
 
 
78
    case FLASH_ECCCNTR:
 
79
        return s->ecc.count & 0xff;
 
80
 
 
81
    case FLASH_FLASHCTL:
 
82
        nand_getpins(s->nand, &ryby);
 
83
        if (ryby)
 
84
            return s->ctl | FLASHCTL_RYBY;
 
85
        else
 
86
            return s->ctl;
 
87
 
 
88
    case FLASH_FLASHIO:
 
89
        return ecc_digest(&s->ecc, nand_getio(s->nand));
 
90
 
 
91
    default:
 
92
        spitz_printf("Bad register offset " REG_FMT "\n", addr);
 
93
    }
 
94
    return 0;
 
95
}
 
96
 
 
97
static uint32_t sl_readl(void *opaque, target_phys_addr_t addr)
 
98
{
 
99
    struct sl_nand_s *s = (struct sl_nand_s *) opaque;
 
100
    addr -= s->target_base;
 
101
 
 
102
    if (addr == FLASH_FLASHIO)
 
103
        return ecc_digest(&s->ecc, nand_getio(s->nand)) |
 
104
                (ecc_digest(&s->ecc, nand_getio(s->nand)) << 16);
 
105
 
 
106
    return sl_readb(opaque, addr);
 
107
}
 
108
 
 
109
static void sl_writeb(void *opaque, target_phys_addr_t addr,
 
110
                uint32_t value)
 
111
{
 
112
    struct sl_nand_s *s = (struct sl_nand_s *) opaque;
 
113
    addr -= s->target_base;
 
114
 
 
115
    switch (addr) {
 
116
    case FLASH_ECCCLRR:
 
117
        /* Value is ignored.  */
 
118
        ecc_reset(&s->ecc);
 
119
        break;
 
120
 
 
121
    case FLASH_FLASHCTL:
 
122
        s->ctl = value & 0xff & ~FLASHCTL_RYBY;
 
123
        nand_setpins(s->nand,
 
124
                        s->ctl & FLASHCTL_CLE,
 
125
                        s->ctl & FLASHCTL_ALE,
 
126
                        s->ctl & FLASHCTL_NCE,
 
127
                        s->ctl & FLASHCTL_WP,
 
128
                        0);
 
129
        break;
 
130
 
 
131
    case FLASH_FLASHIO:
 
132
        nand_setio(s->nand, ecc_digest(&s->ecc, value & 0xff));
 
133
        break;
 
134
 
 
135
    default:
 
136
        spitz_printf("Bad register offset " REG_FMT "\n", addr);
 
137
    }
 
138
}
 
139
 
 
140
static void sl_save(QEMUFile *f, void *opaque)
 
141
{
 
142
    struct sl_nand_s *s = (struct sl_nand_s *) opaque;
 
143
 
 
144
    qemu_put_8s(f, &s->ctl);
 
145
    ecc_put(f, &s->ecc);
 
146
}
 
147
 
 
148
static int sl_load(QEMUFile *f, void *opaque, int version_id)
 
149
{
 
150
    struct sl_nand_s *s = (struct sl_nand_s *) opaque;
 
151
 
 
152
    qemu_get_8s(f, &s->ctl);
 
153
    ecc_get(f, &s->ecc);
 
154
 
 
155
    return 0;
 
156
}
 
157
 
 
158
enum {
 
159
    FLASH_128M,
 
160
    FLASH_1024M,
 
161
};
 
162
 
 
163
static void sl_flash_register(struct pxa2xx_state_s *cpu, int size)
 
164
{
 
165
    int iomemtype;
 
166
    struct sl_nand_s *s;
 
167
    CPUReadMemoryFunc *sl_readfn[] = {
 
168
        sl_readb,
 
169
        sl_readb,
 
170
        sl_readl,
 
171
    };
 
172
    CPUWriteMemoryFunc *sl_writefn[] = {
 
173
        sl_writeb,
 
174
        sl_writeb,
 
175
        sl_writeb,
 
176
    };
 
177
 
 
178
    s = (struct sl_nand_s *) qemu_mallocz(sizeof(struct sl_nand_s));
 
179
    s->target_base = FLASH_BASE;
 
180
    s->ctl = 0;
 
181
    if (size == FLASH_128M)
 
182
        s->nand = nand_init(NAND_MFR_SAMSUNG, 0x73);
 
183
    else if (size == FLASH_1024M)
 
184
        s->nand = nand_init(NAND_MFR_SAMSUNG, 0xf1);
 
185
 
 
186
    iomemtype = cpu_register_io_memory(0, sl_readfn,
 
187
                    sl_writefn, s);
 
188
    cpu_register_physical_memory(s->target_base, 0x40, iomemtype);
 
189
 
 
190
    register_savevm("sl_flash", 0, 0, sl_save, sl_load, s);
 
191
}
 
192
 
 
193
/* Spitz Keyboard */
 
194
 
 
195
#define SPITZ_KEY_STROBE_NUM    11
 
196
#define SPITZ_KEY_SENSE_NUM     7
 
197
 
 
198
static const int spitz_gpio_key_sense[SPITZ_KEY_SENSE_NUM] = {
 
199
    12, 17, 91, 34, 36, 38, 39
 
200
};
 
201
 
 
202
static const int spitz_gpio_key_strobe[SPITZ_KEY_STROBE_NUM] = {
 
203
    88, 23, 24, 25, 26, 27, 52, 103, 107, 108, 114
 
204
};
 
205
 
 
206
/* Eighth additional row maps the special keys */
 
207
static int spitz_keymap[SPITZ_KEY_SENSE_NUM + 1][SPITZ_KEY_STROBE_NUM] = {
 
208
    { 0x1d, 0x02, 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0e, 0x3f, 0x40 },
 
209
    {  -1 , 0x03, 0x05, 0x13, 0x15, 0x09, 0x17, 0x18, 0x19, 0x41, 0x42 },
 
210
    { 0x0f, 0x10, 0x12, 0x14, 0x22, 0x16, 0x24, 0x25,  -1 ,  -1 ,  -1  },
 
211
    { 0x3c, 0x11, 0x1f, 0x21, 0x2f, 0x23, 0x32, 0x26,  -1 , 0x36,  -1  },
 
212
    { 0x3b, 0x1e, 0x20, 0x2e, 0x30, 0x31, 0x34,  -1 , 0x1c, 0x2a,  -1  },
 
213
    { 0x44, 0x2c, 0x2d, 0x0c, 0x39, 0x33,  -1 , 0x48,  -1 ,  -1 , 0x38 },
 
214
    { 0x37, 0x3d,  -1 , 0x45, 0x57, 0x58, 0x4b, 0x50, 0x4d,  -1 ,  -1  },
 
215
    { 0x52, 0x43, 0x01, 0x47, 0x49,  -1 ,  -1 ,  -1 ,  -1 ,  -1 ,  -1  },
 
216
};
 
217
 
 
218
#define SPITZ_GPIO_AK_INT       13      /* Remote control */
 
219
#define SPITZ_GPIO_SYNC         16      /* Sync button */
 
220
#define SPITZ_GPIO_ON_KEY       95      /* Power button */
 
221
#define SPITZ_GPIO_SWA          97      /* Lid */
 
222
#define SPITZ_GPIO_SWB          96      /* Tablet mode */
 
223
 
 
224
/* The special buttons are mapped to unused keys */
 
225
static const int spitz_gpiomap[5] = {
 
226
    SPITZ_GPIO_AK_INT, SPITZ_GPIO_SYNC, SPITZ_GPIO_ON_KEY,
 
227
    SPITZ_GPIO_SWA, SPITZ_GPIO_SWB,
 
228
};
 
229
static int spitz_gpio_invert[5] = { 0, 0, 0, 0, 0, };
 
230
 
 
231
struct spitz_keyboard_s {
 
232
    qemu_irq sense[SPITZ_KEY_SENSE_NUM];
 
233
    qemu_irq *strobe;
 
234
    qemu_irq gpiomap[5];
 
235
    int keymap[0x80];
 
236
    uint16_t keyrow[SPITZ_KEY_SENSE_NUM];
 
237
    uint16_t strobe_state;
 
238
    uint16_t sense_state;
 
239
 
 
240
    uint16_t pre_map[0x100];
 
241
    uint16_t modifiers;
 
242
    uint16_t imodifiers;
 
243
    uint8_t fifo[16];
 
244
    int fifopos, fifolen;
 
245
    QEMUTimer *kbdtimer;
 
246
};
 
247
 
 
248
static void spitz_keyboard_sense_update(struct spitz_keyboard_s *s)
 
249
{
 
250
    int i;
 
251
    uint16_t strobe, sense = 0;
 
252
    for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++) {
 
253
        strobe = s->keyrow[i] & s->strobe_state;
 
254
        if (strobe) {
 
255
            sense |= 1 << i;
 
256
            if (!(s->sense_state & (1 << i)))
 
257
                qemu_irq_raise(s->sense[i]);
 
258
        } else if (s->sense_state & (1 << i))
 
259
            qemu_irq_lower(s->sense[i]);
 
260
    }
 
261
 
 
262
    s->sense_state = sense;
 
263
}
 
264
 
 
265
static void spitz_keyboard_strobe(void *opaque, int line, int level)
 
266
{
 
267
    struct spitz_keyboard_s *s = (struct spitz_keyboard_s *) opaque;
 
268
 
 
269
    if (level)
 
270
        s->strobe_state |= 1 << line;
 
271
    else
 
272
        s->strobe_state &= ~(1 << line);
 
273
    spitz_keyboard_sense_update(s);
 
274
}
 
275
 
 
276
static void spitz_keyboard_keydown(struct spitz_keyboard_s *s, int keycode)
 
277
{
 
278
    int spitz_keycode = s->keymap[keycode & 0x7f];
 
279
    if (spitz_keycode == -1)
 
280
        return;
 
281
 
 
282
    /* Handle the additional keys */
 
283
    if ((spitz_keycode >> 4) == SPITZ_KEY_SENSE_NUM) {
 
284
        qemu_set_irq(s->gpiomap[spitz_keycode & 0xf], (keycode < 0x80) ^
 
285
                        spitz_gpio_invert[spitz_keycode & 0xf]);
 
286
        return;
 
287
    }
 
288
 
 
289
    if (keycode & 0x80)
 
290
        s->keyrow[spitz_keycode >> 4] &= ~(1 << (spitz_keycode & 0xf));
 
291
    else
 
292
        s->keyrow[spitz_keycode >> 4] |= 1 << (spitz_keycode & 0xf);
 
293
 
 
294
    spitz_keyboard_sense_update(s);
 
295
}
 
296
 
 
297
#define SHIFT   (1 << 7)
 
298
#define CTRL    (1 << 8)
 
299
#define FN      (1 << 9)
 
300
 
 
301
#define QUEUE_KEY(c)    s->fifo[(s->fifopos + s->fifolen ++) & 0xf] = c
 
302
 
 
303
static void spitz_keyboard_handler(struct spitz_keyboard_s *s, int keycode)
 
304
{
 
305
    uint16_t code;
 
306
    int mapcode;
 
307
    switch (keycode) {
 
308
    case 0x2a:  /* Left Shift */
 
309
        s->modifiers |= 1;
 
310
        break;
 
311
    case 0xaa:
 
312
        s->modifiers &= ~1;
 
313
        break;
 
314
    case 0x36:  /* Right Shift */
 
315
        s->modifiers |= 2;
 
316
        break;
 
317
    case 0xb6:
 
318
        s->modifiers &= ~2;
 
319
        break;
 
320
    case 0x1d:  /* Control */
 
321
        s->modifiers |= 4;
 
322
        break;
 
323
    case 0x9d:
 
324
        s->modifiers &= ~4;
 
325
        break;
 
326
    case 0x38:  /* Alt */
 
327
        s->modifiers |= 8;
 
328
        break;
 
329
    case 0xb8:
 
330
        s->modifiers &= ~8;
 
331
        break;
 
332
    }
 
333
 
 
334
    code = s->pre_map[mapcode = ((s->modifiers & 3) ?
 
335
            (keycode | SHIFT) :
 
336
            (keycode & ~SHIFT))];
 
337
 
 
338
    if (code != mapcode) {
 
339
#if 0
 
340
        if ((code & SHIFT) && !(s->modifiers & 1))
 
341
            QUEUE_KEY(0x2a | (keycode & 0x80));
 
342
        if ((code & CTRL ) && !(s->modifiers & 4))
 
343
            QUEUE_KEY(0x1d | (keycode & 0x80));
 
344
        if ((code & FN   ) && !(s->modifiers & 8))
 
345
            QUEUE_KEY(0x38 | (keycode & 0x80));
 
346
        if ((code & FN   ) && (s->modifiers & 1))
 
347
            QUEUE_KEY(0x2a | (~keycode & 0x80));
 
348
        if ((code & FN   ) && (s->modifiers & 2))
 
349
            QUEUE_KEY(0x36 | (~keycode & 0x80));
 
350
#else
 
351
        if (keycode & 0x80) {
 
352
            if ((s->imodifiers & 1   ) && !(s->modifiers & 1))
 
353
                QUEUE_KEY(0x2a | 0x80);
 
354
            if ((s->imodifiers & 4   ) && !(s->modifiers & 4))
 
355
                QUEUE_KEY(0x1d | 0x80);
 
356
            if ((s->imodifiers & 8   ) && !(s->modifiers & 8))
 
357
                QUEUE_KEY(0x38 | 0x80);
 
358
            if ((s->imodifiers & 0x10) && (s->modifiers & 1))
 
359
                QUEUE_KEY(0x2a);
 
360
            if ((s->imodifiers & 0x20) && (s->modifiers & 2))
 
361
                QUEUE_KEY(0x36);
 
362
            s->imodifiers = 0;
 
363
        } else {
 
364
            if ((code & SHIFT) && !((s->modifiers | s->imodifiers) & 1)) {
 
365
                QUEUE_KEY(0x2a);
 
366
                s->imodifiers |= 1;
 
367
            }
 
368
            if ((code & CTRL ) && !((s->modifiers | s->imodifiers) & 4)) {
 
369
                QUEUE_KEY(0x1d);
 
370
                s->imodifiers |= 4;
 
371
            }
 
372
            if ((code & FN   ) && !((s->modifiers | s->imodifiers) & 8)) {
 
373
                QUEUE_KEY(0x38);
 
374
                s->imodifiers |= 8;
 
375
            }
 
376
            if ((code & FN   ) && (s->modifiers & 1) &&
 
377
                            !(s->imodifiers & 0x10)) {
 
378
                QUEUE_KEY(0x2a | 0x80);
 
379
                s->imodifiers |= 0x10;
 
380
            }
 
381
            if ((code & FN   ) && (s->modifiers & 2) &&
 
382
                            !(s->imodifiers & 0x20)) {
 
383
                QUEUE_KEY(0x36 | 0x80);
 
384
                s->imodifiers |= 0x20;
 
385
            }
 
386
        }
 
387
#endif
 
388
    }
 
389
 
 
390
    QUEUE_KEY((code & 0x7f) | (keycode & 0x80));
 
391
}
 
392
 
 
393
static void spitz_keyboard_tick(void *opaque)
 
394
{
 
395
    struct spitz_keyboard_s *s = (struct spitz_keyboard_s *) opaque;
 
396
 
 
397
    if (s->fifolen) {
 
398
        spitz_keyboard_keydown(s, s->fifo[s->fifopos ++]);
 
399
        s->fifolen --;
 
400
        if (s->fifopos >= 16)
 
401
            s->fifopos = 0;
 
402
    }
 
403
 
 
404
    qemu_mod_timer(s->kbdtimer, qemu_get_clock(vm_clock) + ticks_per_sec / 32);
 
405
}
 
406
 
 
407
static void spitz_keyboard_pre_map(struct spitz_keyboard_s *s)
 
408
{
 
409
    int i;
 
410
    for (i = 0; i < 0x100; i ++)
 
411
        s->pre_map[i] = i;
 
412
    s->pre_map[0x02 | SHIFT     ] = 0x02 | SHIFT;       /* exclam */
 
413
    s->pre_map[0x28 | SHIFT     ] = 0x03 | SHIFT;       /* quotedbl */
 
414
    s->pre_map[0x04 | SHIFT     ] = 0x04 | SHIFT;       /* numbersign */
 
415
    s->pre_map[0x05 | SHIFT     ] = 0x05 | SHIFT;       /* dollar */
 
416
    s->pre_map[0x06 | SHIFT     ] = 0x06 | SHIFT;       /* percent */
 
417
    s->pre_map[0x08 | SHIFT     ] = 0x07 | SHIFT;       /* ampersand */
 
418
    s->pre_map[0x28             ] = 0x08 | SHIFT;       /* apostrophe */
 
419
    s->pre_map[0x0a | SHIFT     ] = 0x09 | SHIFT;       /* parenleft */
 
420
    s->pre_map[0x0b | SHIFT     ] = 0x0a | SHIFT;       /* parenright */
 
421
    s->pre_map[0x29 | SHIFT     ] = 0x0b | SHIFT;       /* asciitilde */
 
422
    s->pre_map[0x03 | SHIFT     ] = 0x0c | SHIFT;       /* at */
 
423
    s->pre_map[0xd3             ] = 0x0e | FN;          /* Delete */
 
424
    s->pre_map[0x3a             ] = 0x0f | FN;          /* Caps_Lock */
 
425
    s->pre_map[0x07 | SHIFT     ] = 0x11 | FN;          /* asciicircum */
 
426
    s->pre_map[0x0d             ] = 0x12 | FN;          /* equal */
 
427
    s->pre_map[0x0d | SHIFT     ] = 0x13 | FN;          /* plus */
 
428
    s->pre_map[0x1a             ] = 0x14 | FN;          /* bracketleft */
 
429
    s->pre_map[0x1b             ] = 0x15 | FN;          /* bracketright */
 
430
    s->pre_map[0x1a | SHIFT     ] = 0x16 | FN;          /* braceleft */
 
431
    s->pre_map[0x1b | SHIFT     ] = 0x17 | FN;          /* braceright */
 
432
    s->pre_map[0x27             ] = 0x22 | FN;          /* semicolon */
 
433
    s->pre_map[0x27 | SHIFT     ] = 0x23 | FN;          /* colon */
 
434
    s->pre_map[0x09 | SHIFT     ] = 0x24 | FN;          /* asterisk */
 
435
    s->pre_map[0x2b             ] = 0x25 | FN;          /* backslash */
 
436
    s->pre_map[0x2b | SHIFT     ] = 0x26 | FN;          /* bar */
 
437
    s->pre_map[0x0c | SHIFT     ] = 0x30 | FN;          /* underscore */
 
438
    s->pre_map[0x33 | SHIFT     ] = 0x33 | FN;          /* less */
 
439
    s->pre_map[0x35             ] = 0x33 | SHIFT;       /* slash */
 
440
    s->pre_map[0x34 | SHIFT     ] = 0x34 | FN;          /* greater */
 
441
    s->pre_map[0x35 | SHIFT     ] = 0x34 | SHIFT;       /* question */
 
442
    s->pre_map[0x49             ] = 0x48 | FN;          /* Page_Up */
 
443
    s->pre_map[0x51             ] = 0x50 | FN;          /* Page_Down */
 
444
 
 
445
    s->modifiers = 0;
 
446
    s->imodifiers = 0;
 
447
    s->fifopos = 0;
 
448
    s->fifolen = 0;
 
449
    s->kbdtimer = qemu_new_timer(vm_clock, spitz_keyboard_tick, s);
 
450
    spitz_keyboard_tick(s);
 
451
}
 
452
 
 
453
#undef SHIFT
 
454
#undef CTRL
 
455
#undef FN
 
456
 
 
457
static void spitz_keyboard_save(QEMUFile *f, void *opaque)
 
458
{
 
459
    struct spitz_keyboard_s *s = (struct spitz_keyboard_s *) opaque;
 
460
    int i;
 
461
 
 
462
    qemu_put_be16s(f, &s->sense_state);
 
463
    qemu_put_be16s(f, &s->strobe_state);
 
464
    for (i = 0; i < 5; i ++)
 
465
        qemu_put_byte(f, spitz_gpio_invert[i]);
 
466
}
 
467
 
 
468
static int spitz_keyboard_load(QEMUFile *f, void *opaque, int version_id)
 
469
{
 
470
    struct spitz_keyboard_s *s = (struct spitz_keyboard_s *) opaque;
 
471
    int i;
 
472
 
 
473
    qemu_get_be16s(f, &s->sense_state);
 
474
    qemu_get_be16s(f, &s->strobe_state);
 
475
    for (i = 0; i < 5; i ++)
 
476
        spitz_gpio_invert[i] = qemu_get_byte(f);
 
477
 
 
478
    /* Release all pressed keys */
 
479
    memset(s->keyrow, 0, sizeof(s->keyrow));
 
480
    spitz_keyboard_sense_update(s);
 
481
    s->modifiers = 0;
 
482
    s->imodifiers = 0;
 
483
    s->fifopos = 0;
 
484
    s->fifolen = 0;
 
485
 
 
486
    return 0;
 
487
}
 
488
 
 
489
static void spitz_keyboard_register(struct pxa2xx_state_s *cpu)
 
490
{
 
491
    int i, j;
 
492
    struct spitz_keyboard_s *s;
 
493
 
 
494
    s = (struct spitz_keyboard_s *)
 
495
            qemu_mallocz(sizeof(struct spitz_keyboard_s));
 
496
    memset(s, 0, sizeof(struct spitz_keyboard_s));
 
497
 
 
498
    for (i = 0; i < 0x80; i ++)
 
499
        s->keymap[i] = -1;
 
500
    for (i = 0; i < SPITZ_KEY_SENSE_NUM + 1; i ++)
 
501
        for (j = 0; j < SPITZ_KEY_STROBE_NUM; j ++)
 
502
            if (spitz_keymap[i][j] != -1)
 
503
                s->keymap[spitz_keymap[i][j]] = (i << 4) | j;
 
504
 
 
505
    for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++)
 
506
        s->sense[i] = pxa2xx_gpio_in_get(cpu->gpio)[spitz_gpio_key_sense[i]];
 
507
 
 
508
    for (i = 0; i < 5; i ++)
 
509
        s->gpiomap[i] = pxa2xx_gpio_in_get(cpu->gpio)[spitz_gpiomap[i]];
 
510
 
 
511
    s->strobe = qemu_allocate_irqs(spitz_keyboard_strobe, s,
 
512
                    SPITZ_KEY_STROBE_NUM);
 
513
    for (i = 0; i < SPITZ_KEY_STROBE_NUM; i ++)
 
514
        pxa2xx_gpio_out_set(cpu->gpio, spitz_gpio_key_strobe[i], s->strobe[i]);
 
515
 
 
516
    spitz_keyboard_pre_map(s);
 
517
    qemu_add_kbd_event_handler((QEMUPutKBDEvent *) spitz_keyboard_handler, s);
 
518
 
 
519
    register_savevm("spitz_keyboard", 0, 0,
 
520
                    spitz_keyboard_save, spitz_keyboard_load, s);
 
521
}
 
522
 
 
523
/* SCOOP devices */
 
524
 
 
525
struct scoop_info_s {
 
526
    target_phys_addr_t target_base;
 
527
    qemu_irq handler[16];
 
528
    qemu_irq *in;
 
529
    uint16_t status;
 
530
    uint16_t power;
 
531
    uint32_t gpio_level;
 
532
    uint32_t gpio_dir;
 
533
    uint32_t prev_level;
 
534
 
 
535
    uint16_t mcr;
 
536
    uint16_t cdr;
 
537
    uint16_t ccr;
 
538
    uint16_t irr;
 
539
    uint16_t imr;
 
540
    uint16_t isr;
 
541
    uint16_t gprr;
 
542
};
 
543
 
 
544
#define SCOOP_MCR       0x00
 
545
#define SCOOP_CDR       0x04
 
546
#define SCOOP_CSR       0x08
 
547
#define SCOOP_CPR       0x0c
 
548
#define SCOOP_CCR       0x10
 
549
#define SCOOP_IRR_IRM   0x14
 
550
#define SCOOP_IMR       0x18
 
551
#define SCOOP_ISR       0x1c
 
552
#define SCOOP_GPCR      0x20
 
553
#define SCOOP_GPWR      0x24
 
554
#define SCOOP_GPRR      0x28
 
555
 
 
556
static inline void scoop_gpio_handler_update(struct scoop_info_s *s) {
 
557
    uint32_t level, diff;
 
558
    int bit;
 
559
    level = s->gpio_level & s->gpio_dir;
 
560
 
 
561
    for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
 
562
        bit = ffs(diff) - 1;
 
563
        qemu_set_irq(s->handler[bit], (level >> bit) & 1);
 
564
    }
 
565
 
 
566
    s->prev_level = level;
 
567
}
 
568
 
 
569
static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr)
 
570
{
 
571
    struct scoop_info_s *s = (struct scoop_info_s *) opaque;
 
572
    addr -= s->target_base;
 
573
 
 
574
    switch (addr) {
 
575
    case SCOOP_MCR:
 
576
        return s->mcr;
 
577
    case SCOOP_CDR:
 
578
        return s->cdr;
 
579
    case SCOOP_CSR:
 
580
        return s->status;
 
581
    case SCOOP_CPR:
 
582
        return s->power;
 
583
    case SCOOP_CCR:
 
584
        return s->ccr;
 
585
    case SCOOP_IRR_IRM:
 
586
        return s->irr;
 
587
    case SCOOP_IMR:
 
588
        return s->imr;
 
589
    case SCOOP_ISR:
 
590
        return s->isr;
 
591
    case SCOOP_GPCR:
 
592
        return s->gpio_dir;
 
593
    case SCOOP_GPWR:
 
594
        return s->gpio_level;
 
595
    case SCOOP_GPRR:
 
596
        return s->gprr;
 
597
    default:
 
598
        spitz_printf("Bad register offset " REG_FMT "\n", addr);
 
599
    }
 
600
 
 
601
    return 0;
 
602
}
 
603
 
 
604
static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
 
605
{
 
606
    struct scoop_info_s *s = (struct scoop_info_s *) opaque;
 
607
    addr -= s->target_base;
 
608
    value &= 0xffff;
 
609
 
 
610
    switch (addr) {
 
611
    case SCOOP_MCR:
 
612
        s->mcr = value;
 
613
        break;
 
614
    case SCOOP_CDR:
 
615
        s->cdr = value;
 
616
        break;
 
617
    case SCOOP_CPR:
 
618
        s->power = value;
 
619
        if (value & 0x80)
 
620
            s->power |= 0x8040;
 
621
        break;
 
622
    case SCOOP_CCR:
 
623
        s->ccr = value;
 
624
        break;
 
625
    case SCOOP_IRR_IRM:
 
626
        s->irr = value;
 
627
        break;
 
628
    case SCOOP_IMR:
 
629
        s->imr = value;
 
630
        break;
 
631
    case SCOOP_ISR:
 
632
        s->isr = value;
 
633
        break;
 
634
    case SCOOP_GPCR:
 
635
        s->gpio_dir = value;
 
636
        scoop_gpio_handler_update(s);
 
637
        break;
 
638
    case SCOOP_GPWR:
 
639
        s->gpio_level = value & s->gpio_dir;
 
640
        scoop_gpio_handler_update(s);
 
641
        break;
 
642
    case SCOOP_GPRR:
 
643
        s->gprr = value;
 
644
        break;
 
645
    default:
 
646
        spitz_printf("Bad register offset " REG_FMT "\n", addr);
 
647
    }
 
648
}
 
649
 
 
650
CPUReadMemoryFunc *scoop_readfn[] = {
 
651
    scoop_readb,
 
652
    scoop_readb,
 
653
    scoop_readb,
 
654
};
 
655
CPUWriteMemoryFunc *scoop_writefn[] = {
 
656
    scoop_writeb,
 
657
    scoop_writeb,
 
658
    scoop_writeb,
 
659
};
 
660
 
 
661
static void scoop_gpio_set(void *opaque, int line, int level)
 
662
{
 
663
    struct scoop_info_s *s = (struct scoop_info_s *) s;
 
664
 
 
665
    if (level)
 
666
        s->gpio_level |= (1 << line);
 
667
    else
 
668
        s->gpio_level &= ~(1 << line);
 
669
}
 
670
 
 
671
static inline qemu_irq *scoop_gpio_in_get(struct scoop_info_s *s)
 
672
{
 
673
    return s->in;
 
674
}
 
675
 
 
676
static inline void scoop_gpio_out_set(struct scoop_info_s *s, int line,
 
677
                qemu_irq handler) {
 
678
    if (line >= 16) {
 
679
        spitz_printf("No GPIO pin %i\n", line);
 
680
        return;
 
681
    }
 
682
 
 
683
    s->handler[line] = handler;
 
684
}
 
685
 
 
686
static void scoop_save(QEMUFile *f, void *opaque)
 
687
{
 
688
    struct scoop_info_s *s = (struct scoop_info_s *) opaque;
 
689
    qemu_put_be16s(f, &s->status);
 
690
    qemu_put_be16s(f, &s->power);
 
691
    qemu_put_be32s(f, &s->gpio_level);
 
692
    qemu_put_be32s(f, &s->gpio_dir);
 
693
    qemu_put_be32s(f, &s->prev_level);
 
694
    qemu_put_be16s(f, &s->mcr);
 
695
    qemu_put_be16s(f, &s->cdr);
 
696
    qemu_put_be16s(f, &s->ccr);
 
697
    qemu_put_be16s(f, &s->irr);
 
698
    qemu_put_be16s(f, &s->imr);
 
699
    qemu_put_be16s(f, &s->isr);
 
700
    qemu_put_be16s(f, &s->gprr);
 
701
}
 
702
 
 
703
static int scoop_load(QEMUFile *f, void *opaque, int version_id)
 
704
{
 
705
    struct scoop_info_s *s = (struct scoop_info_s *) opaque;
 
706
    qemu_get_be16s(f, &s->status);
 
707
    qemu_get_be16s(f, &s->power);
 
708
    qemu_get_be32s(f, &s->gpio_level);
 
709
    qemu_get_be32s(f, &s->gpio_dir);
 
710
    qemu_get_be32s(f, &s->prev_level);
 
711
    qemu_get_be16s(f, &s->mcr);
 
712
    qemu_get_be16s(f, &s->cdr);
 
713
    qemu_get_be16s(f, &s->ccr);
 
714
    qemu_get_be16s(f, &s->irr);
 
715
    qemu_get_be16s(f, &s->imr);
 
716
    qemu_get_be16s(f, &s->isr);
 
717
    qemu_get_be16s(f, &s->gprr);
 
718
 
 
719
    return 0;
 
720
}
 
721
 
 
722
static struct scoop_info_s *spitz_scoop_init(struct pxa2xx_state_s *cpu,
 
723
                int count) {
 
724
    int iomemtype;
 
725
    struct scoop_info_s *s;
 
726
 
 
727
    s = (struct scoop_info_s *)
 
728
            qemu_mallocz(sizeof(struct scoop_info_s) * 2);
 
729
    memset(s, 0, sizeof(struct scoop_info_s) * count);
 
730
    s[0].target_base = 0x10800000;
 
731
    s[1].target_base = 0x08800040;
 
732
 
 
733
    /* Ready */
 
734
    s[0].status = 0x02;
 
735
    s[1].status = 0x02;
 
736
 
 
737
    s[0].in = qemu_allocate_irqs(scoop_gpio_set, &s[0], 16);
 
738
    iomemtype = cpu_register_io_memory(0, scoop_readfn,
 
739
                    scoop_writefn, &s[0]);
 
740
    cpu_register_physical_memory(s[0].target_base, 0x1000, iomemtype);
 
741
    register_savevm("scoop", 0, 0, scoop_save, scoop_load, &s[0]);
 
742
 
 
743
    if (count < 2)
 
744
        return s;
 
745
 
 
746
    s[1].in = qemu_allocate_irqs(scoop_gpio_set, &s[1], 16);
 
747
    iomemtype = cpu_register_io_memory(0, scoop_readfn,
 
748
                    scoop_writefn, &s[1]);
 
749
    cpu_register_physical_memory(s[1].target_base, 0x1000, iomemtype);
 
750
    register_savevm("scoop", 1, 0, scoop_save, scoop_load, &s[1]);
 
751
 
 
752
    return s;
 
753
}
 
754
 
 
755
/* LCD backlight controller */
 
756
 
 
757
#define LCDTG_RESCTL    0x00
 
758
#define LCDTG_PHACTRL   0x01
 
759
#define LCDTG_DUTYCTRL  0x02
 
760
#define LCDTG_POWERREG0 0x03
 
761
#define LCDTG_POWERREG1 0x04
 
762
#define LCDTG_GPOR3     0x05
 
763
#define LCDTG_PICTRL    0x06
 
764
#define LCDTG_POLCTRL   0x07
 
765
 
 
766
static int bl_intensity, bl_power;
 
767
 
 
768
static void spitz_bl_update(struct pxa2xx_state_s *s)
 
769
{
 
770
    if (bl_power && bl_intensity)
 
771
        spitz_printf("LCD Backlight now at %i/63\n", bl_intensity);
 
772
    else
 
773
        spitz_printf("LCD Backlight now off\n");
 
774
}
 
775
 
 
776
static inline void spitz_bl_bit5(void *opaque, int line, int level)
 
777
{
 
778
    int prev = bl_intensity;
 
779
 
 
780
    if (level)
 
781
        bl_intensity &= ~0x20;
 
782
    else
 
783
        bl_intensity |= 0x20;
 
784
 
 
785
    if (bl_power && prev != bl_intensity)
 
786
        spitz_bl_update((struct pxa2xx_state_s *) opaque);
 
787
}
 
788
 
 
789
static inline void spitz_bl_power(void *opaque, int line, int level)
 
790
{
 
791
    bl_power = !!level;
 
792
    spitz_bl_update((struct pxa2xx_state_s *) opaque);
 
793
}
 
794
 
 
795
static void spitz_lcdtg_dac_put(void *opaque, uint8_t cmd)
 
796
{
 
797
    int addr, value;
 
798
    addr = cmd >> 5;
 
799
    value = cmd & 0x1f;
 
800
 
 
801
    switch (addr) {
 
802
    case LCDTG_RESCTL:
 
803
        if (value)
 
804
            spitz_printf("LCD in QVGA mode\n");
 
805
        else
 
806
            spitz_printf("LCD in VGA mode\n");
 
807
        break;
 
808
 
 
809
    case LCDTG_DUTYCTRL:
 
810
        bl_intensity &= ~0x1f;
 
811
        bl_intensity |= value;
 
812
        if (bl_power)
 
813
            spitz_bl_update((struct pxa2xx_state_s *) opaque);
 
814
        break;
 
815
 
 
816
    case LCDTG_POWERREG0:
 
817
        /* Set common voltage to M62332FP */
 
818
        break;
 
819
    }
 
820
}
 
821
 
 
822
/* SSP devices */
 
823
 
 
824
#define CORGI_SSP_PORT          2
 
825
 
 
826
#define SPITZ_GPIO_LCDCON_CS    53
 
827
#define SPITZ_GPIO_ADS7846_CS   14
 
828
#define SPITZ_GPIO_MAX1111_CS   20
 
829
#define SPITZ_GPIO_TP_INT       11
 
830
 
 
831
static int lcd_en, ads_en, max_en;
 
832
static struct max111x_s *max1111;
 
833
static struct ads7846_state_s *ads7846;
 
834
 
 
835
/* "Demux" the signal based on current chipselect */
 
836
static uint32_t corgi_ssp_read(void *opaque)
 
837
{
 
838
    if (lcd_en)
 
839
        return 0;
 
840
    if (ads_en)
 
841
        return ads7846_read(ads7846);
 
842
    if (max_en)
 
843
        return max111x_read(max1111);
 
844
    return 0;
 
845
}
 
846
 
 
847
static void corgi_ssp_write(void *opaque, uint32_t value)
 
848
{
 
849
    if (lcd_en)
 
850
        spitz_lcdtg_dac_put(opaque, value);
 
851
    if (ads_en)
 
852
        ads7846_write(ads7846, value);
 
853
    if (max_en)
 
854
        max111x_write(max1111, value);
 
855
}
 
856
 
 
857
static void corgi_ssp_gpio_cs(void *opaque, int line, int level)
 
858
{
 
859
    switch (line) {
 
860
    case 0:
 
861
        lcd_en = !level;
 
862
        break;
 
863
    case 1:
 
864
        ads_en = !level;
 
865
        break;
 
866
    case 2:
 
867
        max_en = !level;
 
868
        break;
 
869
    }
 
870
}
 
871
 
 
872
#define MAX1111_BATT_VOLT       1
 
873
#define MAX1111_BATT_TEMP       2
 
874
#define MAX1111_ACIN_VOLT       3
 
875
 
 
876
#define SPITZ_BATTERY_TEMP      0xe0    /* About 2.9V */
 
877
#define SPITZ_BATTERY_VOLT      0xd0    /* About 4.0V */
 
878
#define SPITZ_CHARGEON_ACIN     0x80    /* About 5.0V */
 
879
 
 
880
static void spitz_adc_temp_on(void *opaque, int line, int level)
 
881
{
 
882
    if (!max1111)
 
883
        return;
 
884
 
 
885
    if (level)
 
886
        max111x_set_input(max1111, MAX1111_BATT_TEMP, SPITZ_BATTERY_TEMP);
 
887
    else
 
888
        max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
 
889
}
 
890
 
 
891
static void spitz_ssp_save(QEMUFile *f, void *opaque)
 
892
{
 
893
    qemu_put_be32(f, lcd_en);
 
894
    qemu_put_be32(f, ads_en);
 
895
    qemu_put_be32(f, max_en);
 
896
    qemu_put_be32(f, bl_intensity);
 
897
    qemu_put_be32(f, bl_power);
 
898
}
 
899
 
 
900
static int spitz_ssp_load(QEMUFile *f, void *opaque, int version_id)
 
901
{
 
902
    lcd_en = qemu_get_be32(f);
 
903
    ads_en = qemu_get_be32(f);
 
904
    max_en = qemu_get_be32(f);
 
905
    bl_intensity = qemu_get_be32(f);
 
906
    bl_power = qemu_get_be32(f);
 
907
 
 
908
    return 0;
 
909
}
 
910
 
 
911
static void spitz_ssp_attach(struct pxa2xx_state_s *cpu)
 
912
{
 
913
    qemu_irq *chipselects;
 
914
 
 
915
    lcd_en = ads_en = max_en = 0;
 
916
 
 
917
    ads7846 = ads7846_init(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_TP_INT]);
 
918
 
 
919
    max1111 = max1111_init(0);
 
920
    max111x_set_input(max1111, MAX1111_BATT_VOLT, SPITZ_BATTERY_VOLT);
 
921
    max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
 
922
    max111x_set_input(max1111, MAX1111_ACIN_VOLT, SPITZ_CHARGEON_ACIN);
 
923
 
 
924
    pxa2xx_ssp_attach(cpu->ssp[CORGI_SSP_PORT - 1], corgi_ssp_read,
 
925
                    corgi_ssp_write, cpu);
 
926
 
 
927
    chipselects = qemu_allocate_irqs(corgi_ssp_gpio_cs, cpu, 3);
 
928
    pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_LCDCON_CS,  chipselects[0]);
 
929
    pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_ADS7846_CS, chipselects[1]);
 
930
    pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_MAX1111_CS, chipselects[2]);
 
931
 
 
932
    bl_intensity = 0x20;
 
933
    bl_power = 0;
 
934
 
 
935
    register_savevm("spitz_ssp", 0, 0, spitz_ssp_save, spitz_ssp_load, cpu);
 
936
}
 
937
 
 
938
/* CF Microdrive */
 
939
 
 
940
static void spitz_microdrive_attach(struct pxa2xx_state_s *cpu)
 
941
{
 
942
    struct pcmcia_card_s *md;
 
943
    int index;
 
944
    BlockDriverState *bs;
 
945
 
 
946
    index = drive_get_index(IF_IDE, 0, 0);
 
947
    if (index == -1)
 
948
        return;
 
949
    bs = drives_table[index].bdrv;
 
950
    if (bdrv_is_inserted(bs) && !bdrv_is_removable(bs)) {
 
951
        md = dscm1xxxx_init(bs);
 
952
        pxa2xx_pcmcia_attach(cpu->pcmcia[1], md);
 
953
    }
 
954
}
 
955
 
 
956
/* Wm8750 and Max7310 on I2C */
 
957
 
 
958
#define AKITA_MAX_ADDR  0x18
 
959
#define SPITZ_WM_ADDRL  0x1b
 
960
#define SPITZ_WM_ADDRH  0x1a
 
961
 
 
962
#define SPITZ_GPIO_WM   5
 
963
 
 
964
#ifdef HAS_AUDIO
 
965
static void spitz_wm8750_addr(void *opaque, int line, int level)
 
966
{
 
967
    i2c_slave *wm = (i2c_slave *) opaque;
 
968
    if (level)
 
969
        i2c_set_slave_address(wm, SPITZ_WM_ADDRH);
 
970
    else
 
971
        i2c_set_slave_address(wm, SPITZ_WM_ADDRL);
 
972
}
 
973
#endif
 
974
 
 
975
static void spitz_i2c_setup(struct pxa2xx_state_s *cpu)
 
976
{
 
977
    /* Attach the CPU on one end of our I2C bus.  */
 
978
    i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
 
979
 
 
980
#ifdef HAS_AUDIO
 
981
    AudioState *audio;
 
982
    i2c_slave *wm;
 
983
 
 
984
    audio = AUD_init();
 
985
    if (!audio)
 
986
        return;
 
987
    /* Attach a WM8750 to the bus */
 
988
    wm = wm8750_init(bus, audio);
 
989
 
 
990
    spitz_wm8750_addr(wm, 0, 0);
 
991
    pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_WM,
 
992
                    qemu_allocate_irqs(spitz_wm8750_addr, wm, 1)[0]);
 
993
    /* .. and to the sound interface.  */
 
994
    cpu->i2s->opaque = wm;
 
995
    cpu->i2s->codec_out = wm8750_dac_dat;
 
996
    cpu->i2s->codec_in = wm8750_adc_dat;
 
997
    wm8750_data_req_set(wm, cpu->i2s->data_req, cpu->i2s);
 
998
#endif
 
999
}
 
1000
 
 
1001
static void spitz_akita_i2c_setup(struct pxa2xx_state_s *cpu)
 
1002
{
 
1003
    /* Attach a Max7310 to Akita I2C bus.  */
 
1004
    i2c_set_slave_address(max7310_init(pxa2xx_i2c_bus(cpu->i2c[0])),
 
1005
                    AKITA_MAX_ADDR);
 
1006
}
 
1007
 
 
1008
/* Other peripherals */
 
1009
 
 
1010
static void spitz_out_switch(void *opaque, int line, int level)
 
1011
{
 
1012
    switch (line) {
 
1013
    case 0:
 
1014
        spitz_printf("Charging %s.\n", level ? "off" : "on");
 
1015
        break;
 
1016
    case 1:
 
1017
        spitz_printf("Discharging %s.\n", level ? "on" : "off");
 
1018
        break;
 
1019
    case 2:
 
1020
        spitz_printf("Green LED %s.\n", level ? "on" : "off");
 
1021
        break;
 
1022
    case 3:
 
1023
        spitz_printf("Orange LED %s.\n", level ? "on" : "off");
 
1024
        break;
 
1025
    case 4:
 
1026
        spitz_bl_bit5(opaque, line, level);
 
1027
        break;
 
1028
    case 5:
 
1029
        spitz_bl_power(opaque, line, level);
 
1030
        break;
 
1031
    case 6:
 
1032
        spitz_adc_temp_on(opaque, line, level);
 
1033
        break;
 
1034
    }
 
1035
}
 
1036
 
 
1037
#define SPITZ_SCP_LED_GREEN             1
 
1038
#define SPITZ_SCP_JK_B                  2
 
1039
#define SPITZ_SCP_CHRG_ON               3
 
1040
#define SPITZ_SCP_MUTE_L                4
 
1041
#define SPITZ_SCP_MUTE_R                5
 
1042
#define SPITZ_SCP_CF_POWER              6
 
1043
#define SPITZ_SCP_LED_ORANGE            7
 
1044
#define SPITZ_SCP_JK_A                  8
 
1045
#define SPITZ_SCP_ADC_TEMP_ON           9
 
1046
#define SPITZ_SCP2_IR_ON                1
 
1047
#define SPITZ_SCP2_AKIN_PULLUP          2
 
1048
#define SPITZ_SCP2_BACKLIGHT_CONT       7
 
1049
#define SPITZ_SCP2_BACKLIGHT_ON         8
 
1050
#define SPITZ_SCP2_MIC_BIAS             9
 
1051
 
 
1052
static void spitz_scoop_gpio_setup(struct pxa2xx_state_s *cpu,
 
1053
                struct scoop_info_s *scp, int num)
 
1054
{
 
1055
    qemu_irq *outsignals = qemu_allocate_irqs(spitz_out_switch, cpu, 8);
 
1056
 
 
1057
    scoop_gpio_out_set(&scp[0], SPITZ_SCP_CHRG_ON, outsignals[0]);
 
1058
    scoop_gpio_out_set(&scp[0], SPITZ_SCP_JK_B, outsignals[1]);
 
1059
    scoop_gpio_out_set(&scp[0], SPITZ_SCP_LED_GREEN, outsignals[2]);
 
1060
    scoop_gpio_out_set(&scp[0], SPITZ_SCP_LED_ORANGE, outsignals[3]);
 
1061
 
 
1062
    if (num >= 2) {
 
1063
        scoop_gpio_out_set(&scp[1], SPITZ_SCP2_BACKLIGHT_CONT, outsignals[4]);
 
1064
        scoop_gpio_out_set(&scp[1], SPITZ_SCP2_BACKLIGHT_ON, outsignals[5]);
 
1065
    }
 
1066
 
 
1067
    scoop_gpio_out_set(&scp[0], SPITZ_SCP_ADC_TEMP_ON, outsignals[6]);
 
1068
}
 
1069
 
 
1070
#define SPITZ_GPIO_HSYNC                22
 
1071
#define SPITZ_GPIO_SD_DETECT            9
 
1072
#define SPITZ_GPIO_SD_WP                81
 
1073
#define SPITZ_GPIO_ON_RESET             89
 
1074
#define SPITZ_GPIO_BAT_COVER            90
 
1075
#define SPITZ_GPIO_CF1_IRQ              105
 
1076
#define SPITZ_GPIO_CF1_CD               94
 
1077
#define SPITZ_GPIO_CF2_IRQ              106
 
1078
#define SPITZ_GPIO_CF2_CD               93
 
1079
 
 
1080
static int spitz_hsync;
 
1081
 
 
1082
static void spitz_lcd_hsync_handler(void *opaque, int line, int level)
 
1083
{
 
1084
    struct pxa2xx_state_s *cpu = (struct pxa2xx_state_s *) opaque;
 
1085
    qemu_set_irq(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_HSYNC], spitz_hsync);
 
1086
    spitz_hsync ^= 1;
 
1087
}
 
1088
 
 
1089
static void spitz_gpio_setup(struct pxa2xx_state_s *cpu, int slots)
 
1090
{
 
1091
    qemu_irq lcd_hsync;
 
1092
    /*
 
1093
     * Bad hack: We toggle the LCD hsync GPIO on every GPIO status
 
1094
     * read to satisfy broken guests that poll-wait for hsync.
 
1095
     * Simulating a real hsync event would be less practical and
 
1096
     * wouldn't guarantee that a guest ever exits the loop.
 
1097
     */
 
1098
    spitz_hsync = 0;
 
1099
    lcd_hsync = qemu_allocate_irqs(spitz_lcd_hsync_handler, cpu, 1)[0];
 
1100
    pxa2xx_gpio_read_notifier(cpu->gpio, lcd_hsync);
 
1101
    pxa2xx_lcd_vsync_notifier(cpu->lcd, lcd_hsync);
 
1102
 
 
1103
    /* MMC/SD host */
 
1104
    pxa2xx_mmci_handlers(cpu->mmc,
 
1105
                    pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_SD_WP],
 
1106
                    pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_SD_DETECT]);
 
1107
 
 
1108
    /* Battery lock always closed */
 
1109
    qemu_irq_raise(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_BAT_COVER]);
 
1110
 
 
1111
    /* Handle reset */
 
1112
    pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_ON_RESET, cpu->reset);
 
1113
 
 
1114
    /* PCMCIA signals: card's IRQ and Card-Detect */
 
1115
    if (slots >= 1)
 
1116
        pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
 
1117
                        pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF1_IRQ],
 
1118
                        pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF1_CD]);
 
1119
    if (slots >= 2)
 
1120
        pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
 
1121
                        pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF2_IRQ],
 
1122
                        pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF2_CD]);
 
1123
 
 
1124
    /* Initialise the screen rotation related signals */
 
1125
    spitz_gpio_invert[3] = 0;   /* Always open */
 
1126
    if (graphic_rotate) {       /* Tablet mode */
 
1127
        spitz_gpio_invert[4] = 0;
 
1128
    } else {                    /* Portrait mode */
 
1129
        spitz_gpio_invert[4] = 1;
 
1130
    }
 
1131
    qemu_set_irq(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_SWA],
 
1132
                    spitz_gpio_invert[3]);
 
1133
    qemu_set_irq(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_SWB],
 
1134
                    spitz_gpio_invert[4]);
 
1135
}
 
1136
 
 
1137
/* Write the bootloader parameters memory area.  */
 
1138
 
 
1139
#define MAGIC_CHG(a, b, c, d)   ((d << 24) | (c << 16) | (b << 8) | a)
 
1140
 
 
1141
struct __attribute__ ((__packed__)) sl_param_info {
 
1142
    uint32_t comadj_keyword;
 
1143
    int32_t comadj;
 
1144
 
 
1145
    uint32_t uuid_keyword;
 
1146
    char uuid[16];
 
1147
 
 
1148
    uint32_t touch_keyword;
 
1149
    int32_t touch_xp;
 
1150
    int32_t touch_yp;
 
1151
    int32_t touch_xd;
 
1152
    int32_t touch_yd;
 
1153
 
 
1154
    uint32_t adadj_keyword;
 
1155
    int32_t adadj;
 
1156
 
 
1157
    uint32_t phad_keyword;
 
1158
    int32_t phadadj;
 
1159
} spitz_bootparam = {
 
1160
    .comadj_keyword     = MAGIC_CHG('C', 'M', 'A', 'D'),
 
1161
    .comadj             = 125,
 
1162
    .uuid_keyword       = MAGIC_CHG('U', 'U', 'I', 'D'),
 
1163
    .uuid               = { -1 },
 
1164
    .touch_keyword      = MAGIC_CHG('T', 'U', 'C', 'H'),
 
1165
    .touch_xp           = -1,
 
1166
    .adadj_keyword      = MAGIC_CHG('B', 'V', 'A', 'D'),
 
1167
    .adadj              = -1,
 
1168
    .phad_keyword       = MAGIC_CHG('P', 'H', 'A', 'D'),
 
1169
    .phadadj            = 0x01,
 
1170
};
 
1171
 
 
1172
static void sl_bootparam_write(uint32_t ptr)
 
1173
{
 
1174
    memcpy(phys_ram_base + ptr, &spitz_bootparam,
 
1175
                    sizeof(struct sl_param_info));
 
1176
}
 
1177
 
 
1178
#define SL_PXA_PARAM_BASE       0xa0000a00
 
1179
 
 
1180
/* Board init.  */
 
1181
enum spitz_model_e { spitz, akita, borzoi, terrier };
 
1182
 
 
1183
static void spitz_common_init(int ram_size, int vga_ram_size,
 
1184
                DisplayState *ds, const char *kernel_filename,
 
1185
                const char *kernel_cmdline, const char *initrd_filename,
 
1186
                const char *cpu_model, enum spitz_model_e model, int arm_id)
 
1187
{
 
1188
    uint32_t spitz_ram = 0x04000000;
 
1189
    uint32_t spitz_rom = 0x00800000;
 
1190
    struct pxa2xx_state_s *cpu;
 
1191
    struct scoop_info_s *scp;
 
1192
 
 
1193
    if (!cpu_model)
 
1194
        cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
 
1195
 
 
1196
    /* Setup CPU & memory */
 
1197
    if (ram_size < spitz_ram + spitz_rom + PXA2XX_INTERNAL_SIZE) {
 
1198
        fprintf(stderr, "This platform requires %i bytes of memory\n",
 
1199
                        spitz_ram + spitz_rom + PXA2XX_INTERNAL_SIZE);
 
1200
        exit(1);
 
1201
    }
 
1202
    cpu = pxa270_init(spitz_ram, ds, cpu_model);
 
1203
 
 
1204
    sl_flash_register(cpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
 
1205
 
 
1206
    cpu_register_physical_memory(0, spitz_rom,
 
1207
                    qemu_ram_alloc(spitz_rom) | IO_MEM_ROM);
 
1208
 
 
1209
    /* Setup peripherals */
 
1210
    spitz_keyboard_register(cpu);
 
1211
 
 
1212
    spitz_ssp_attach(cpu);
 
1213
 
 
1214
    scp = spitz_scoop_init(cpu, (model == akita) ? 1 : 2);
 
1215
 
 
1216
    spitz_scoop_gpio_setup(cpu, scp, (model == akita) ? 1 : 2);
 
1217
 
 
1218
    spitz_gpio_setup(cpu, (model == akita) ? 1 : 2);
 
1219
 
 
1220
    spitz_i2c_setup(cpu);
 
1221
 
 
1222
    if (model == akita)
 
1223
        spitz_akita_i2c_setup(cpu);
 
1224
 
 
1225
    if (model == terrier)
 
1226
        /* A 6.0 GB microdrive is permanently sitting in CF slot 1.  */
 
1227
        spitz_microdrive_attach(cpu);
 
1228
    else if (model != akita)
 
1229
        /* A 4.0 GB microdrive is permanently sitting in CF slot 1.  */
 
1230
        spitz_microdrive_attach(cpu);
 
1231
 
 
1232
    /* Setup initial (reset) machine state */
 
1233
    cpu->env->regs[15] = PXA2XX_SDRAM_BASE;
 
1234
 
 
1235
    arm_load_kernel(cpu->env, spitz_ram, kernel_filename, kernel_cmdline,
 
1236
                    initrd_filename, arm_id, PXA2XX_SDRAM_BASE);
 
1237
    sl_bootparam_write(SL_PXA_PARAM_BASE - PXA2XX_SDRAM_BASE);
 
1238
}
 
1239
 
 
1240
static void spitz_init(int ram_size, int vga_ram_size,
 
1241
                const char *boot_device, DisplayState *ds,
 
1242
                const char *kernel_filename, const char *kernel_cmdline,
 
1243
                const char *initrd_filename, const char *cpu_model)
 
1244
{
 
1245
    spitz_common_init(ram_size, vga_ram_size, ds, kernel_filename,
 
1246
                kernel_cmdline, initrd_filename, cpu_model, spitz, 0x2c9);
 
1247
}
 
1248
 
 
1249
static void borzoi_init(int ram_size, int vga_ram_size,
 
1250
                const char *boot_device, DisplayState *ds,
 
1251
                const char *kernel_filename, const char *kernel_cmdline,
 
1252
                const char *initrd_filename, const char *cpu_model)
 
1253
{
 
1254
    spitz_common_init(ram_size, vga_ram_size, ds, kernel_filename,
 
1255
                kernel_cmdline, initrd_filename, cpu_model, borzoi, 0x33f);
 
1256
}
 
1257
 
 
1258
static void akita_init(int ram_size, int vga_ram_size,
 
1259
                const char *boot_device, DisplayState *ds,
 
1260
                const char *kernel_filename, const char *kernel_cmdline,
 
1261
                const char *initrd_filename, const char *cpu_model)
 
1262
{
 
1263
    spitz_common_init(ram_size, vga_ram_size, ds, kernel_filename,
 
1264
                kernel_cmdline, initrd_filename, cpu_model, akita, 0x2e8);
 
1265
}
 
1266
 
 
1267
static void terrier_init(int ram_size, int vga_ram_size,
 
1268
                const char *boot_device, DisplayState *ds,
 
1269
                const char *kernel_filename, const char *kernel_cmdline,
 
1270
                const char *initrd_filename, const char *cpu_model)
 
1271
{
 
1272
    spitz_common_init(ram_size, vga_ram_size, ds, kernel_filename,
 
1273
                kernel_cmdline, initrd_filename, cpu_model, terrier, 0x33f);
 
1274
}
 
1275
 
 
1276
QEMUMachine akitapda_machine = {
 
1277
    "akita",
 
1278
    "Akita PDA (PXA270)",
 
1279
    akita_init,
 
1280
};
 
1281
 
 
1282
QEMUMachine spitzpda_machine = {
 
1283
    "spitz",
 
1284
    "Spitz PDA (PXA270)",
 
1285
    spitz_init,
 
1286
};
 
1287
 
 
1288
QEMUMachine borzoipda_machine = {
 
1289
    "borzoi",
 
1290
    "Borzoi PDA (PXA270)",
 
1291
    borzoi_init,
 
1292
};
 
1293
 
 
1294
QEMUMachine terrierpda_machine = {
 
1295
    "terrier",
 
1296
    "Terrier PDA (PXA270)",
 
1297
    terrier_init,
 
1298
};