Commit b00052e496395a9cd38b7efb558aa78855a1e179

Authored by balrog
1 parent c824cacd

Spitz PDA, example PXA270 machine (four similar models).


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2756 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
... ... @@ -371,7 +371,7 @@ VL_OBJS+=tap-win32.o
371 371 endif
372 372  
373 373 SOUND_HW = sb16.o es1370.o
374   -AUDIODRV = audio.o noaudio.o wavaudio.o
  374 +AUDIODRV = audio.o noaudio.o wavaudio.o mixeng.o
375 375 ifdef CONFIG_SDL
376 376 AUDIODRV += sdlaudio.o
377 377 endif
... ... @@ -418,16 +418,16 @@ ifeq ($(TARGET_BASE_ARCH), i386)
418 418 # Hardware support
419 419 VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
420 420 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
421   -VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o acpi.o piix_pci.o
  421 +VL_OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o
422 422 VL_OBJS+= usb-uhci.o smbus_eeprom.o vmmouse.o vmware_vga.o
423   -CPPFLAGS += -DHAS_AUDIO
  423 +CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
424 424 endif
425 425 ifeq ($(TARGET_BASE_ARCH), ppc)
426 426 VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
427 427 VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o pflash_cfi02.o
428   -VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
  428 +VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o
429 429 VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o ppc405_uc.o ppc405_boards.o
430   -CPPFLAGS += -DHAS_AUDIO
  430 +CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
431 431 endif
432 432 ifeq ($(TARGET_BASE_ARCH), mips)
433 433 VL_OBJS+= mips_r4k.o mips_malta.o mips_pica61.o
... ... @@ -453,6 +453,10 @@ VL_OBJS+= arm_boot.o pl011.o pl050.o pl080.o pl110.o pl181.o pl190.o
453 453 VL_OBJS+= versatile_pci.o sd.o
454 454 VL_OBJS+= arm_gic.o realview.o arm_sysctl.o
455 455 VL_OBJS+= arm-semi.o
  456 +VL_OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
  457 +VL_OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o max111x.o
  458 +VL_OBJS+= spitz.o ads7846.o ide.o serial.o nand.o $(AUDIODRV)
  459 +CPPFLAGS += -DHAS_AUDIO -DHIGH_LATENCY
456 460 endif
457 461 ifeq ($(TARGET_BASE_ARCH), sh4)
458 462 VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o
... ...
hw/spitz.c 0 → 100644
  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 "vl.h"
  11 +
  12 +#define spitz_printf(format, ...) \
  13 + fprintf(stderr, "%s: " format, __FUNCTION__, ##__VA_ARGS__)
  14 +#undef REG_FMT
  15 +#define REG_FMT "0x%02lx"
  16 +
  17 +/* Spitz Flash */
  18 +#define FLASH_BASE 0x0c000000
  19 +#define FLASH_ECCLPLB 0x00 /* Line parity 7 - 0 bit */
  20 +#define FLASH_ECCLPUB 0x04 /* Line parity 15 - 8 bit */
  21 +#define FLASH_ECCCP 0x08 /* Column parity 5 - 0 bit */
  22 +#define FLASH_ECCCNTR 0x0c /* ECC byte counter */
  23 +#define FLASH_ECCCLRR 0x10 /* Clear ECC */
  24 +#define FLASH_FLASHIO 0x14 /* Flash I/O */
  25 +#define FLASH_FLASHCTL 0x18 /* Flash Control */
  26 +
  27 +#define FLASHCTL_CE0 (1 << 0)
  28 +#define FLASHCTL_CLE (1 << 1)
  29 +#define FLASHCTL_ALE (1 << 2)
  30 +#define FLASHCTL_WP (1 << 3)
  31 +#define FLASHCTL_CE1 (1 << 4)
  32 +#define FLASHCTL_RYBY (1 << 5)
  33 +#define FLASHCTL_NCE (FLASHCTL_CE0 | FLASHCTL_CE1)
  34 +
  35 +struct sl_nand_s {
  36 + target_phys_addr_t target_base;
  37 + struct nand_flash_s *nand;
  38 + uint8_t ctl;
  39 + struct ecc_state_s ecc;
  40 +};
  41 +
  42 +static uint32_t sl_readb(void *opaque, target_phys_addr_t addr)
  43 +{
  44 + struct sl_nand_s *s = (struct sl_nand_s *) opaque;
  45 + int ryby;
  46 + addr -= s->target_base;
  47 +
  48 + switch (addr) {
  49 +#define BSHR(byte, from, to) ((s->ecc.lp[byte] >> (from - to)) & (1 << to))
  50 + case FLASH_ECCLPLB:
  51 + return BSHR(0, 4, 0) | BSHR(0, 5, 2) | BSHR(0, 6, 4) | BSHR(0, 7, 6) |
  52 + BSHR(1, 4, 1) | BSHR(1, 5, 3) | BSHR(1, 6, 5) | BSHR(1, 7, 7);
  53 +
  54 +#define BSHL(byte, from, to) ((s->ecc.lp[byte] << (to - from)) & (1 << to))
  55 + case FLASH_ECCLPUB:
  56 + return BSHL(0, 0, 0) | BSHL(0, 1, 2) | BSHL(0, 2, 4) | BSHL(0, 3, 6) |
  57 + BSHL(1, 0, 1) | BSHL(1, 1, 3) | BSHL(1, 2, 5) | BSHL(1, 3, 7);
  58 +
  59 + case FLASH_ECCCP:
  60 + return s->ecc.cp;
  61 +
  62 + case FLASH_ECCCNTR:
  63 + return s->ecc.count & 0xff;
  64 +
  65 + case FLASH_FLASHCTL:
  66 + nand_getpins(s->nand, &ryby);
  67 + if (ryby)
  68 + return s->ctl | FLASHCTL_RYBY;
  69 + else
  70 + return s->ctl;
  71 +
  72 + case FLASH_FLASHIO:
  73 + return ecc_digest(&s->ecc, nand_getio(s->nand));
  74 +
  75 + default:
  76 + spitz_printf("Bad register offset " REG_FMT "\n", addr);
  77 + }
  78 + return 0;
  79 +}
  80 +
  81 +static void sl_writeb(void *opaque, target_phys_addr_t addr,
  82 + uint32_t value)
  83 +{
  84 + struct sl_nand_s *s = (struct sl_nand_s *) opaque;
  85 + addr -= s->target_base;
  86 +
  87 + switch (addr) {
  88 + case FLASH_ECCCLRR:
  89 + /* Value is ignored. */
  90 + ecc_reset(&s->ecc);
  91 + break;
  92 +
  93 + case FLASH_FLASHCTL:
  94 + s->ctl = value & 0xff & ~FLASHCTL_RYBY;
  95 + nand_setpins(s->nand,
  96 + s->ctl & FLASHCTL_CLE,
  97 + s->ctl & FLASHCTL_ALE,
  98 + s->ctl & FLASHCTL_NCE,
  99 + s->ctl & FLASHCTL_WP,
  100 + 0);
  101 + break;
  102 +
  103 + case FLASH_FLASHIO:
  104 + nand_setio(s->nand, ecc_digest(&s->ecc, value & 0xff));
  105 + break;
  106 +
  107 + default:
  108 + spitz_printf("Bad register offset " REG_FMT "\n", addr);
  109 + }
  110 +}
  111 +
  112 +enum {
  113 + FLASH_128M,
  114 + FLASH_1024M,
  115 +};
  116 +
  117 +static void sl_flash_register(struct pxa2xx_state_s *cpu, int size)
  118 +{
  119 + int iomemtype;
  120 + struct sl_nand_s *s;
  121 + CPUReadMemoryFunc *sl_readfn[] = {
  122 + sl_readb,
  123 + sl_readb,
  124 + sl_readb,
  125 + };
  126 + CPUWriteMemoryFunc *sl_writefn[] = {
  127 + sl_writeb,
  128 + sl_writeb,
  129 + sl_writeb,
  130 + };
  131 +
  132 + s = (struct sl_nand_s *) qemu_mallocz(sizeof(struct sl_nand_s));
  133 + s->target_base = FLASH_BASE;
  134 + s->ctl = 0;
  135 + if (size == FLASH_128M)
  136 + s->nand = nand_init(NAND_MFR_SAMSUNG, 0x73);
  137 + else if (size == FLASH_1024M)
  138 + s->nand = nand_init(NAND_MFR_SAMSUNG, 0xf1);
  139 +
  140 + iomemtype = cpu_register_io_memory(0, sl_readfn,
  141 + sl_writefn, s);
  142 + cpu_register_physical_memory(s->target_base, 0x40, iomemtype);
  143 +}
  144 +
  145 +/* Spitz Keyboard */
  146 +
  147 +#define SPITZ_KEY_STROBE_NUM 11
  148 +#define SPITZ_KEY_SENSE_NUM 7
  149 +
  150 +static const int spitz_gpio_key_sense[SPITZ_KEY_SENSE_NUM] = {
  151 + 12, 17, 91, 34, 36, 38, 39
  152 +};
  153 +
  154 +static const int spitz_gpio_key_strobe[SPITZ_KEY_STROBE_NUM] = {
  155 + 88, 23, 24, 25, 26, 27, 52, 103, 107, 108, 114
  156 +};
  157 +
  158 +/* Eighth additional row maps the special keys */
  159 +static int spitz_keymap[SPITZ_KEY_SENSE_NUM + 1][SPITZ_KEY_STROBE_NUM] = {
  160 + { 0x1d, 0x02, 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0e, 0x3f, 0x40 },
  161 + { -1 , 0x03, 0x05, 0x13, 0x15, 0x09, 0x17, 0x18, 0x19, 0x41, 0x42 },
  162 + { 0x0f, 0x10, 0x12, 0x14, 0x22, 0x16, 0x24, 0x25, -1 , -1 , -1 },
  163 + { 0x3c, 0x11, 0x1f, 0x21, 0x2f, 0x23, 0x32, 0x26, -1 , 0x36, -1 },
  164 + { 0x3b, 0x1e, 0x20, 0x2e, 0x30, 0x31, 0x34, -1 , 0x1c, 0x2a, -1 },
  165 + { 0x44, 0x2c, 0x2d, 0x0c, 0x39, 0x33, -1 , 0x48, -1 , -1 , 0x3d },
  166 + { 0x37, 0x38, -1 , 0x45, 0x57, 0x58, 0x4b, 0x50, 0x4d, -1 , -1 },
  167 + { 0x52, 0x43, 0x01, 0x47, 0x49, -1 , -1 , -1 , -1 , -1 , -1 },
  168 +};
  169 +
  170 +#define SPITZ_GPIO_AK_INT 13 /* Remote control */
  171 +#define SPITZ_GPIO_SYNC 16 /* Sync button */
  172 +#define SPITZ_GPIO_ON_KEY 95 /* Power button */
  173 +#define SPITZ_GPIO_SWA 97 /* Lid */
  174 +#define SPITZ_GPIO_SWB 96 /* Tablet mode */
  175 +
  176 +/* The special buttons are mapped to unused keys */
  177 +static const int spitz_gpiomap[5] = {
  178 + SPITZ_GPIO_AK_INT, SPITZ_GPIO_SYNC, SPITZ_GPIO_ON_KEY,
  179 + SPITZ_GPIO_SWA, SPITZ_GPIO_SWB,
  180 +};
  181 +static int spitz_gpio_invert[5] = { 0, 0, 0, 0, 0, };
  182 +
  183 +struct spitz_keyboard_s {
  184 + struct pxa2xx_state_s *cpu;
  185 + int keymap[0x80];
  186 + uint16_t keyrow[SPITZ_KEY_SENSE_NUM];
  187 + uint16_t strobe_state;
  188 + uint16_t sense_state;
  189 +
  190 + uint16_t pre_map[0x100];
  191 + uint16_t modifiers;
  192 + uint16_t imodifiers;
  193 + uint8_t fifo[16];
  194 + int fifopos, fifolen;
  195 + QEMUTimer *kbdtimer;
  196 +};
  197 +
  198 +static void spitz_keyboard_sense_update(struct spitz_keyboard_s *s)
  199 +{
  200 + int i;
  201 + uint16_t strobe, sense = 0;
  202 + for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++) {
  203 + strobe = s->keyrow[i] & s->strobe_state;
  204 + if (strobe) {
  205 + sense |= 1 << i;
  206 + if (!(s->sense_state & (1 << i)))
  207 + pxa2xx_gpio_set(s->cpu->gpio, spitz_gpio_key_sense[i], 1);
  208 + } else if (s->sense_state & (1 << i))
  209 + pxa2xx_gpio_set(s->cpu->gpio, spitz_gpio_key_sense[i], 0);
  210 + }
  211 +
  212 + s->sense_state = sense;
  213 +}
  214 +
  215 +static void spitz_keyboard_strobe(int line, int level,
  216 + struct spitz_keyboard_s *s)
  217 +{
  218 + int i;
  219 + for (i = 0; i < SPITZ_KEY_STROBE_NUM; i ++)
  220 + if (spitz_gpio_key_strobe[i] == line) {
  221 + if (level)
  222 + s->strobe_state |= 1 << i;
  223 + else
  224 + s->strobe_state &= ~(1 << i);
  225 +
  226 + spitz_keyboard_sense_update(s);
  227 + break;
  228 + }
  229 +}
  230 +
  231 +static void spitz_keyboard_keydown(struct spitz_keyboard_s *s, int keycode)
  232 +{
  233 + int spitz_keycode = s->keymap[keycode & 0x7f];
  234 + if (spitz_keycode == -1)
  235 + return;
  236 +
  237 + /* Handle the additional keys */
  238 + if ((spitz_keycode >> 4) == SPITZ_KEY_SENSE_NUM) {
  239 + pxa2xx_gpio_set(s->cpu->gpio, spitz_gpiomap[spitz_keycode & 0xf],
  240 + (keycode < 0x80) ^
  241 + spitz_gpio_invert[spitz_keycode & 0xf]);
  242 + return;
  243 + }
  244 +
  245 + if (keycode & 0x80)
  246 + s->keyrow[spitz_keycode >> 4] &= ~(1 << (spitz_keycode & 0xf));
  247 + else
  248 + s->keyrow[spitz_keycode >> 4] |= 1 << (spitz_keycode & 0xf);
  249 +
  250 + spitz_keyboard_sense_update(s);
  251 +}
  252 +
  253 +#define SHIFT (1 << 7)
  254 +#define CTRL (1 << 8)
  255 +#define FN (1 << 9)
  256 +
  257 +#define QUEUE_KEY(c) s->fifo[(s->fifopos + s->fifolen ++) & 0xf] = c
  258 +
  259 +static void spitz_keyboard_handler(struct spitz_keyboard_s *s, int keycode)
  260 +{
  261 + uint16_t code;
  262 + int mapcode;
  263 + switch (keycode) {
  264 + case 0x2a: /* Left Shift */
  265 + s->modifiers |= 1;
  266 + break;
  267 + case 0xaa:
  268 + s->modifiers &= ~1;
  269 + break;
  270 + case 0x36: /* Right Shift */
  271 + s->modifiers |= 2;
  272 + break;
  273 + case 0xb6:
  274 + s->modifiers &= ~2;
  275 + break;
  276 + case 0x1d: /* Control */
  277 + s->modifiers |= 4;
  278 + break;
  279 + case 0x9d:
  280 + s->modifiers &= ~4;
  281 + break;
  282 + case 0x38: /* Alt */
  283 + s->modifiers |= 8;
  284 + break;
  285 + case 0xb8:
  286 + s->modifiers &= ~8;
  287 + break;
  288 + }
  289 +
  290 + code = s->pre_map[mapcode = ((s->modifiers & 3) ?
  291 + (keycode | SHIFT) :
  292 + (keycode & ~SHIFT))];
  293 +
  294 + if (code != mapcode) {
  295 +#if 0
  296 + if ((code & SHIFT) && !(s->modifiers & 1))
  297 + QUEUE_KEY(0x2a | (keycode & 0x80));
  298 + if ((code & CTRL ) && !(s->modifiers & 4))
  299 + QUEUE_KEY(0x1d | (keycode & 0x80));
  300 + if ((code & FN ) && !(s->modifiers & 8))
  301 + QUEUE_KEY(0x38 | (keycode & 0x80));
  302 + if ((code & FN ) && (s->modifiers & 1))
  303 + QUEUE_KEY(0x2a | (~keycode & 0x80));
  304 + if ((code & FN ) && (s->modifiers & 2))
  305 + QUEUE_KEY(0x36 | (~keycode & 0x80));
  306 +#else
  307 + if (keycode & 0x80) {
  308 + if ((s->imodifiers & 1 ) && !(s->modifiers & 1))
  309 + QUEUE_KEY(0x2a | 0x80);
  310 + if ((s->imodifiers & 4 ) && !(s->modifiers & 4))
  311 + QUEUE_KEY(0x1d | 0x80);
  312 + if ((s->imodifiers & 8 ) && !(s->modifiers & 8))
  313 + QUEUE_KEY(0x38 | 0x80);
  314 + if ((s->imodifiers & 0x10) && (s->modifiers & 1))
  315 + QUEUE_KEY(0x2a);
  316 + if ((s->imodifiers & 0x20) && (s->modifiers & 2))
  317 + QUEUE_KEY(0x36);
  318 + s->imodifiers = 0;
  319 + } else {
  320 + if ((code & SHIFT) && !((s->modifiers | s->imodifiers) & 1)) {
  321 + QUEUE_KEY(0x2a);
  322 + s->imodifiers |= 1;
  323 + }
  324 + if ((code & CTRL ) && !((s->modifiers | s->imodifiers) & 4)) {
  325 + QUEUE_KEY(0x1d);
  326 + s->imodifiers |= 4;
  327 + }
  328 + if ((code & FN ) && !((s->modifiers | s->imodifiers) & 8)) {
  329 + QUEUE_KEY(0x38);
  330 + s->imodifiers |= 8;
  331 + }
  332 + if ((code & FN ) && (s->modifiers & 1) &&
  333 + !(s->imodifiers & 0x10)) {
  334 + QUEUE_KEY(0x2a | 0x80);
  335 + s->imodifiers |= 0x10;
  336 + }
  337 + if ((code & FN ) && (s->modifiers & 2) &&
  338 + !(s->imodifiers & 0x20)) {
  339 + QUEUE_KEY(0x36 | 0x80);
  340 + s->imodifiers |= 0x20;
  341 + }
  342 + }
  343 +#endif
  344 + }
  345 +
  346 + QUEUE_KEY((code & 0x7f) | (keycode & 0x80));
  347 +}
  348 +
  349 +static void spitz_keyboard_tick(void *opaque)
  350 +{
  351 + struct spitz_keyboard_s *s = (struct spitz_keyboard_s *) opaque;
  352 +
  353 + if (s->fifolen) {
  354 + spitz_keyboard_keydown(s, s->fifo[s->fifopos ++]);
  355 + s->fifolen --;
  356 + if (s->fifopos >= 16)
  357 + s->fifopos = 0;
  358 + }
  359 +
  360 + qemu_mod_timer(s->kbdtimer, qemu_get_clock(vm_clock) + ticks_per_sec / 32);
  361 +}
  362 +
  363 +static void spitz_keyboard_pre_map(struct spitz_keyboard_s *s)
  364 +{
  365 + int i;
  366 + for (i = 0; i < 0x100; i ++)
  367 + s->pre_map[i] = i;
  368 + s->pre_map[0x02 | SHIFT ] = 0x02 | SHIFT; /* exclam */
  369 + s->pre_map[0x28 | SHIFT ] = 0x03 | SHIFT; /* quotedbl */
  370 + s->pre_map[0x04 | SHIFT ] = 0x04 | SHIFT; /* numbersign */
  371 + s->pre_map[0x05 | SHIFT ] = 0x05 | SHIFT; /* dollar */
  372 + s->pre_map[0x06 | SHIFT ] = 0x06 | SHIFT; /* percent */
  373 + s->pre_map[0x08 | SHIFT ] = 0x07 | SHIFT; /* ampersand */
  374 + s->pre_map[0x28 ] = 0x08 | SHIFT; /* apostrophe */
  375 + s->pre_map[0x0a | SHIFT ] = 0x09 | SHIFT; /* parenleft */
  376 + s->pre_map[0x0b | SHIFT ] = 0x0a | SHIFT; /* parenright */
  377 + s->pre_map[0x29 | SHIFT ] = 0x0b | SHIFT; /* asciitilde */
  378 + s->pre_map[0x03 | SHIFT ] = 0x0c | SHIFT; /* at */
  379 + s->pre_map[0xd3 ] = 0x0e | FN; /* Delete */
  380 + s->pre_map[0x3a ] = 0x0f | FN; /* Caps_Lock */
  381 + s->pre_map[0x07 | SHIFT ] = 0x11 | FN; /* asciicircum */
  382 + s->pre_map[0x0d ] = 0x12 | FN; /* equal */
  383 + s->pre_map[0x0d | SHIFT ] = 0x13 | FN; /* plus */
  384 + s->pre_map[0x1a ] = 0x14 | FN; /* bracketleft */
  385 + s->pre_map[0x1b ] = 0x15 | FN; /* bracketright */
  386 + s->pre_map[0x27 ] = 0x22 | FN; /* semicolon */
  387 + s->pre_map[0x27 | SHIFT ] = 0x23 | FN; /* colon */
  388 + s->pre_map[0x09 | SHIFT ] = 0x24 | FN; /* asterisk */
  389 + s->pre_map[0x2b ] = 0x25 | FN; /* backslash */
  390 + s->pre_map[0x2b | SHIFT ] = 0x26 | FN; /* bar */
  391 + s->pre_map[0x0c | SHIFT ] = 0x30 | FN; /* underscore */
  392 + s->pre_map[0x35 ] = 0x33 | SHIFT; /* slash */
  393 + s->pre_map[0x35 | SHIFT ] = 0x34 | SHIFT; /* question */
  394 + s->pre_map[0x49 ] = 0x48 | FN; /* Page_Up */
  395 + s->pre_map[0x51 ] = 0x50 | FN; /* Page_Down */
  396 +
  397 + s->modifiers = 0;
  398 + s->imodifiers = 0;
  399 + s->fifopos = 0;
  400 + s->fifolen = 0;
  401 + s->kbdtimer = qemu_new_timer(vm_clock, spitz_keyboard_tick, s);
  402 + spitz_keyboard_tick(s);
  403 +}
  404 +
  405 +#undef SHIFT
  406 +#undef CTRL
  407 +#undef FN
  408 +
  409 +static void spitz_keyboard_register(struct pxa2xx_state_s *cpu)
  410 +{
  411 + int i, j;
  412 + struct spitz_keyboard_s *s;
  413 +
  414 + s = (struct spitz_keyboard_s *)
  415 + qemu_mallocz(sizeof(struct spitz_keyboard_s));
  416 + memset(s, 0, sizeof(struct spitz_keyboard_s));
  417 + s->cpu = cpu;
  418 +
  419 + for (i = 0; i < 0x80; i ++)
  420 + s->keymap[i] = -1;
  421 + for (i = 0; i < SPITZ_KEY_SENSE_NUM + 1; i ++)
  422 + for (j = 0; j < SPITZ_KEY_STROBE_NUM; j ++)
  423 + if (spitz_keymap[i][j] != -1)
  424 + s->keymap[spitz_keymap[i][j]] = (i << 4) | j;
  425 +
  426 + for (i = 0; i < SPITZ_KEY_STROBE_NUM; i ++)
  427 + pxa2xx_gpio_handler_set(cpu->gpio, spitz_gpio_key_strobe[i],
  428 + (gpio_handler_t) spitz_keyboard_strobe, s);
  429 +
  430 + spitz_keyboard_pre_map(s);
  431 + qemu_add_kbd_event_handler((QEMUPutKBDEvent *) spitz_keyboard_handler, s);
  432 +}
  433 +
  434 +/* SCOOP devices */
  435 +
  436 +struct scoop_info_s {
  437 + target_phys_addr_t target_base;
  438 + uint16_t status;
  439 + uint16_t power;
  440 + uint32_t gpio_level;
  441 + uint32_t gpio_dir;
  442 + uint32_t prev_level;
  443 + struct {
  444 + gpio_handler_t fn;
  445 + void *opaque;
  446 + } handler[16];
  447 +
  448 + uint16_t mcr;
  449 + uint16_t cdr;
  450 + uint16_t ccr;
  451 + uint16_t irr;
  452 + uint16_t imr;
  453 + uint16_t isr;
  454 + uint16_t gprr;
  455 +};
  456 +
  457 +#define SCOOP_MCR 0x00
  458 +#define SCOOP_CDR 0x04
  459 +#define SCOOP_CSR 0x08
  460 +#define SCOOP_CPR 0x0c
  461 +#define SCOOP_CCR 0x10
  462 +#define SCOOP_IRR_IRM 0x14
  463 +#define SCOOP_IMR 0x18
  464 +#define SCOOP_ISR 0x1c
  465 +#define SCOOP_GPCR 0x20
  466 +#define SCOOP_GPWR 0x24
  467 +#define SCOOP_GPRR 0x28
  468 +
  469 +static inline void scoop_gpio_handler_update(struct scoop_info_s *s) {
  470 + uint32_t level, diff;
  471 + int bit;
  472 + level = s->gpio_level & s->gpio_dir;
  473 +
  474 + for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
  475 + bit = ffs(diff) - 1;
  476 + if (s->handler[bit].fn)
  477 + s->handler[bit].fn(bit, (level >> bit) & 1,
  478 + s->handler[bit].opaque);
  479 + }
  480 +
  481 + s->prev_level = level;
  482 +}
  483 +
  484 +static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr)
  485 +{
  486 + struct scoop_info_s *s = (struct scoop_info_s *) opaque;
  487 + addr -= s->target_base;
  488 +
  489 + switch (addr) {
  490 + case SCOOP_MCR:
  491 + return s->mcr;
  492 + case SCOOP_CDR:
  493 + return s->cdr;
  494 + case SCOOP_CSR:
  495 + return s->status;
  496 + case SCOOP_CPR:
  497 + return s->power;
  498 + case SCOOP_CCR:
  499 + return s->ccr;
  500 + case SCOOP_IRR_IRM:
  501 + return s->irr;
  502 + case SCOOP_IMR:
  503 + return s->imr;
  504 + case SCOOP_ISR:
  505 + return s->isr;
  506 + case SCOOP_GPCR:
  507 + return s->gpio_dir;
  508 + case SCOOP_GPWR:
  509 + return s->gpio_level;
  510 + case SCOOP_GPRR:
  511 + return s->gprr;
  512 + default:
  513 + spitz_printf("Bad register offset " REG_FMT "\n", addr);
  514 + }
  515 +
  516 + return 0;
  517 +}
  518 +
  519 +static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
  520 +{
  521 + struct scoop_info_s *s = (struct scoop_info_s *) opaque;
  522 + addr -= s->target_base;
  523 + value &= 0xffff;
  524 +
  525 + switch (addr) {
  526 + case SCOOP_MCR:
  527 + s->mcr = value;
  528 + break;
  529 + case SCOOP_CDR:
  530 + s->cdr = value;
  531 + break;
  532 + case SCOOP_CPR:
  533 + s->power = value;
  534 + if (value & 0x80)
  535 + s->power |= 0x8040;
  536 + break;
  537 + case SCOOP_CCR:
  538 + s->ccr = value;
  539 + break;
  540 + case SCOOP_IRR_IRM:
  541 + s->irr = value;
  542 + break;
  543 + case SCOOP_IMR:
  544 + s->imr = value;
  545 + break;
  546 + case SCOOP_ISR:
  547 + s->isr = value;
  548 + break;
  549 + case SCOOP_GPCR:
  550 + s->gpio_dir = value;
  551 + scoop_gpio_handler_update(s);
  552 + break;
  553 + case SCOOP_GPWR:
  554 + s->gpio_level = value & s->gpio_dir;
  555 + scoop_gpio_handler_update(s);
  556 + break;
  557 + case SCOOP_GPRR:
  558 + s->gprr = value;
  559 + break;
  560 + default:
  561 + spitz_printf("Bad register offset " REG_FMT "\n", addr);
  562 + }
  563 +}
  564 +
  565 +CPUReadMemoryFunc *scoop_readfn[] = {
  566 + scoop_readb,
  567 + scoop_readb,
  568 + scoop_readb,
  569 +};
  570 +CPUWriteMemoryFunc *scoop_writefn[] = {
  571 + scoop_writeb,
  572 + scoop_writeb,
  573 + scoop_writeb,
  574 +};
  575 +
  576 +static inline void scoop_gpio_set(struct scoop_info_s *s, int line, int level)
  577 +{
  578 + if (line >= 16) {
  579 + spitz_printf("No GPIO pin %i\n", line);
  580 + return;
  581 + }
  582 +
  583 + if (level)
  584 + s->gpio_level |= (1 << line);
  585 + else
  586 + s->gpio_level &= ~(1 << line);
  587 +}
  588 +
  589 +static inline void scoop_gpio_handler_set(struct scoop_info_s *s, int line,
  590 + gpio_handler_t handler, void *opaque) {
  591 + if (line >= 16) {
  592 + spitz_printf("No GPIO pin %i\n", line);
  593 + return;
  594 + }
  595 +
  596 + s->handler[line].fn = handler;
  597 + s->handler[line].opaque = opaque;
  598 +}
  599 +
  600 +static struct scoop_info_s *spitz_scoop_init(struct pxa2xx_state_s *cpu,
  601 + int count) {
  602 + int iomemtype;
  603 + struct scoop_info_s *s;
  604 +
  605 + s = (struct scoop_info_s *)
  606 + qemu_mallocz(sizeof(struct scoop_info_s) * 2);
  607 + memset(s, 0, sizeof(struct scoop_info_s) * count);
  608 + s[0].target_base = 0x10800000;
  609 + s[1].target_base = 0x08800040;
  610 +
  611 + /* Ready */
  612 + s[0].status = 0x02;
  613 + s[1].status = 0x02;
  614 +
  615 + iomemtype = cpu_register_io_memory(0, scoop_readfn,
  616 + scoop_writefn, &s[0]);
  617 + cpu_register_physical_memory(s[0].target_base, 0xfff, iomemtype);
  618 +
  619 + if (count < 2)
  620 + return s;
  621 +
  622 + iomemtype = cpu_register_io_memory(0, scoop_readfn,
  623 + scoop_writefn, &s[1]);
  624 + cpu_register_physical_memory(s[1].target_base, 0xfff, iomemtype);
  625 +
  626 + return s;
  627 +}
  628 +
  629 +/* LCD backlight controller */
  630 +
  631 +#define LCDTG_RESCTL 0x00
  632 +#define LCDTG_PHACTRL 0x01
  633 +#define LCDTG_DUTYCTRL 0x02
  634 +#define LCDTG_POWERREG0 0x03
  635 +#define LCDTG_POWERREG1 0x04
  636 +#define LCDTG_GPOR3 0x05
  637 +#define LCDTG_PICTRL 0x06
  638 +#define LCDTG_POLCTRL 0x07
  639 +
  640 +static int bl_intensity, bl_power;
  641 +
  642 +static void spitz_bl_update(struct pxa2xx_state_s *s)
  643 +{
  644 + if (bl_power && bl_intensity)
  645 + spitz_printf("LCD Backlight now at %i/63\n", bl_intensity);
  646 + else
  647 + spitz_printf("LCD Backlight now off\n");
  648 +}
  649 +
  650 +static void spitz_bl_bit5(int line, int level, void *opaque)
  651 +{
  652 + int prev = bl_intensity;
  653 +
  654 + if (level)
  655 + bl_intensity &= ~0x20;
  656 + else
  657 + bl_intensity |= 0x20;
  658 +
  659 + if (bl_power && prev != bl_intensity)
  660 + spitz_bl_update((struct pxa2xx_state_s *) opaque);
  661 +}
  662 +
  663 +static void spitz_bl_power(int line, int level, void *opaque)
  664 +{
  665 + bl_power = !!level;
  666 + spitz_bl_update((struct pxa2xx_state_s *) opaque);
  667 +}
  668 +
  669 +static void spitz_lcdtg_dac_put(void *opaque, uint8_t cmd)
  670 +{
  671 + int addr, value;
  672 + addr = cmd >> 5;
  673 + value = cmd & 0x1f;
  674 +
  675 + switch (addr) {
  676 + case LCDTG_RESCTL:
  677 + if (value)
  678 + spitz_printf("LCD in QVGA mode\n");
  679 + else
  680 + spitz_printf("LCD in VGA mode\n");
  681 + break;
  682 +
  683 + case LCDTG_DUTYCTRL:
  684 + bl_intensity &= ~0x1f;
  685 + bl_intensity |= value;
  686 + if (bl_power)
  687 + spitz_bl_update((struct pxa2xx_state_s *) opaque);
  688 + break;
  689 +
  690 + case LCDTG_POWERREG0:
  691 + /* Set common voltage to M62332FP */
  692 + break;
  693 + }
  694 +}
  695 +
  696 +/* SSP devices */
  697 +
  698 +#define CORGI_SSP_PORT 2
  699 +
  700 +#define SPITZ_GPIO_LCDCON_CS 53
  701 +#define SPITZ_GPIO_ADS7846_CS 14
  702 +#define SPITZ_GPIO_MAX1111_CS 20
  703 +#define SPITZ_GPIO_TP_INT 11
  704 +
  705 +static int lcd_en, ads_en, max_en;
  706 +static struct max111x_s *max1111;
  707 +static struct ads7846_state_s *ads7846;
  708 +
  709 +/* "Demux" the signal based on current chipselect */
  710 +static uint32_t corgi_ssp_read(void *opaque)
  711 +{
  712 + if (lcd_en)
  713 + return 0;
  714 + if (ads_en)
  715 + return ads7846_read(ads7846);
  716 + if (max_en)
  717 + return max111x_read(max1111);
  718 + return 0;
  719 +}
  720 +
  721 +static void corgi_ssp_write(void *opaque, uint32_t value)
  722 +{
  723 + if (lcd_en)
  724 + spitz_lcdtg_dac_put(opaque, value);
  725 + if (ads_en)
  726 + ads7846_write(ads7846, value);
  727 + if (max_en)
  728 + max111x_write(max1111, value);
  729 +}
  730 +
  731 +static void corgi_ssp_gpio_cs(int line, int level, struct pxa2xx_state_s *s)
  732 +{
  733 + if (line == SPITZ_GPIO_LCDCON_CS)
  734 + lcd_en = !level;
  735 + else if (line == SPITZ_GPIO_ADS7846_CS)
  736 + ads_en = !level;
  737 + else if (line == SPITZ_GPIO_MAX1111_CS)
  738 + max_en = !level;
  739 +}
  740 +
  741 +#define MAX1111_BATT_VOLT 1
  742 +#define MAX1111_BATT_TEMP 2
  743 +#define MAX1111_ACIN_VOLT 3
  744 +
  745 +#define SPITZ_BATTERY_TEMP 0xe0 /* About 2.9V */
  746 +#define SPITZ_BATTERY_VOLT 0xd0 /* About 4.0V */
  747 +#define SPITZ_CHARGEON_ACIN 0x80 /* About 5.0V */
  748 +
  749 +static void spitz_adc_temp_on(int line, int level, void *opaque)
  750 +{
  751 + if (!max1111)
  752 + return;
  753 +
  754 + if (level)
  755 + max111x_set_input(max1111, MAX1111_BATT_TEMP, SPITZ_BATTERY_TEMP);
  756 + else
  757 + max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
  758 +}
  759 +
  760 +static void spitz_pendown_set(void *opaque, int line, int level)
  761 +{
  762 + struct pxa2xx_state_s *cpu = (struct pxa2xx_state_s *) opaque;
  763 + pxa2xx_gpio_set(cpu->gpio, SPITZ_GPIO_TP_INT, level);
  764 +}
  765 +
  766 +static void spitz_ssp_attach(struct pxa2xx_state_s *cpu)
  767 +{
  768 + lcd_en = ads_en = max_en = 0;
  769 +
  770 + ads7846 = ads7846_init(qemu_allocate_irqs(spitz_pendown_set, cpu, 1)[0]);
  771 +
  772 + max1111 = max1111_init(0);
  773 + max111x_set_input(max1111, MAX1111_BATT_VOLT, SPITZ_BATTERY_VOLT);
  774 + max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
  775 + max111x_set_input(max1111, MAX1111_ACIN_VOLT, SPITZ_CHARGEON_ACIN);
  776 +
  777 + pxa2xx_ssp_attach(cpu->ssp[CORGI_SSP_PORT - 1], corgi_ssp_read,
  778 + corgi_ssp_write, cpu);
  779 +
  780 + pxa2xx_gpio_handler_set(cpu->gpio, SPITZ_GPIO_LCDCON_CS,
  781 + (gpio_handler_t) corgi_ssp_gpio_cs, cpu);
  782 + pxa2xx_gpio_handler_set(cpu->gpio, SPITZ_GPIO_ADS7846_CS,
  783 + (gpio_handler_t) corgi_ssp_gpio_cs, cpu);
  784 + pxa2xx_gpio_handler_set(cpu->gpio, SPITZ_GPIO_MAX1111_CS,
  785 + (gpio_handler_t) corgi_ssp_gpio_cs, cpu);
  786 +
  787 + bl_intensity = 0x20;
  788 + bl_power = 0;
  789 +}
  790 +
  791 +/* CF Microdrive */
  792 +
  793 +static void spitz_microdrive_attach(struct pxa2xx_state_s *cpu)
  794 +{
  795 + struct pcmcia_card_s *md;
  796 + BlockDriverState *bs = bs_table[0];
  797 +
  798 + if (bs && bdrv_is_inserted(bs) && !bdrv_is_removable(bs)) {
  799 + md = dscm1xxxx_init(bs);
  800 + pxa2xx_pcmcia_attach(cpu->pcmcia[0], md);
  801 + }
  802 +}
  803 +
  804 +/* Other peripherals */
  805 +
  806 +static void spitz_charge_switch(int line, int level, void *opaque)
  807 +{
  808 + spitz_printf("Charging %s.\n", level ? "off" : "on");
  809 +}
  810 +
  811 +static void spitz_discharge_switch(int line, int level, void *opaque)
  812 +{
  813 + spitz_printf("Discharging %s.\n", level ? "on" : "off");
  814 +}
  815 +
  816 +static void spitz_greenled_switch(int line, int level, void *opaque)
  817 +{
  818 + spitz_printf("Green LED %s.\n", level ? "on" : "off");
  819 +}
  820 +
  821 +static void spitz_orangeled_switch(int line, int level, void *opaque)
  822 +{
  823 + spitz_printf("Orange LED %s.\n", level ? "on" : "off");
  824 +}
  825 +
  826 +#define SPITZ_SCP_LED_GREEN 1
  827 +#define SPITZ_SCP_JK_B 2
  828 +#define SPITZ_SCP_CHRG_ON 3
  829 +#define SPITZ_SCP_MUTE_L 4
  830 +#define SPITZ_SCP_MUTE_R 5
  831 +#define SPITZ_SCP_CF_POWER 6
  832 +#define SPITZ_SCP_LED_ORANGE 7
  833 +#define SPITZ_SCP_JK_A 8
  834 +#define SPITZ_SCP_ADC_TEMP_ON 9
  835 +#define SPITZ_SCP2_IR_ON 1
  836 +#define SPITZ_SCP2_AKIN_PULLUP 2
  837 +#define SPITZ_SCP2_BACKLIGHT_CONT 7
  838 +#define SPITZ_SCP2_BACKLIGHT_ON 8
  839 +#define SPITZ_SCP2_MIC_BIAS 9
  840 +
  841 +static void spitz_scoop_gpio_setup(struct pxa2xx_state_s *cpu,
  842 + struct scoop_info_s *scp, int num)
  843 +{
  844 + scoop_gpio_handler_set(&scp[0], SPITZ_SCP_CHRG_ON,
  845 + spitz_charge_switch, cpu);
  846 + scoop_gpio_handler_set(&scp[0], SPITZ_SCP_JK_B,
  847 + spitz_discharge_switch, cpu);
  848 + scoop_gpio_handler_set(&scp[0], SPITZ_SCP_LED_GREEN,
  849 + spitz_greenled_switch, cpu);
  850 + scoop_gpio_handler_set(&scp[0], SPITZ_SCP_LED_ORANGE,
  851 + spitz_orangeled_switch, cpu);
  852 +
  853 + if (num >= 2) {
  854 + scoop_gpio_handler_set(&scp[1], SPITZ_SCP2_BACKLIGHT_CONT,
  855 + spitz_bl_bit5, cpu);
  856 + scoop_gpio_handler_set(&scp[1], SPITZ_SCP2_BACKLIGHT_ON,
  857 + spitz_bl_power, cpu);
  858 + }
  859 +
  860 + scoop_gpio_handler_set(&scp[0], SPITZ_SCP_ADC_TEMP_ON,
  861 + spitz_adc_temp_on, cpu);
  862 +}
  863 +
  864 +#define SPITZ_GPIO_HSYNC 22
  865 +#define SPITZ_GPIO_SD_DETECT 9
  866 +#define SPITZ_GPIO_SD_WP 81
  867 +#define SPITZ_GPIO_ON_RESET 89
  868 +#define SPITZ_GPIO_BAT_COVER 90
  869 +#define SPITZ_GPIO_CF1_IRQ 105
  870 +#define SPITZ_GPIO_CF1_CD 94
  871 +#define SPITZ_GPIO_CF2_IRQ 106
  872 +#define SPITZ_GPIO_CF2_CD 93
  873 +
  874 +int spitz_hsync;
  875 +
  876 +static void spitz_lcd_hsync_handler(void *opaque)
  877 +{
  878 + struct pxa2xx_state_s *cpu = (struct pxa2xx_state_s *) opaque;
  879 + pxa2xx_gpio_set(cpu->gpio, SPITZ_GPIO_HSYNC, spitz_hsync);
  880 + spitz_hsync ^= 1;
  881 +}
  882 +
  883 +static void spitz_mmc_coverswitch_change(void *opaque, int in)
  884 +{
  885 + struct pxa2xx_state_s *cpu = (struct pxa2xx_state_s *) opaque;
  886 + pxa2xx_gpio_set(cpu->gpio, SPITZ_GPIO_SD_DETECT, in);
  887 +}
  888 +
  889 +static void spitz_mmc_writeprotect_change(void *opaque, int wp)
  890 +{
  891 + struct pxa2xx_state_s *cpu = (struct pxa2xx_state_s *) opaque;
  892 + pxa2xx_gpio_set(cpu->gpio, SPITZ_GPIO_SD_WP, wp);
  893 +}
  894 +
  895 +static void spitz_pcmcia_cb(void *opaque, int line, int level)
  896 +{
  897 + struct pxa2xx_state_s *cpu = (struct pxa2xx_state_s *) opaque;
  898 + static const int gpio_map[] = {
  899 + SPITZ_GPIO_CF1_IRQ, SPITZ_GPIO_CF1_CD,
  900 + SPITZ_GPIO_CF2_IRQ, SPITZ_GPIO_CF2_CD,
  901 + };
  902 + pxa2xx_gpio_set(cpu->gpio, gpio_map[line], level);
  903 +}
  904 +
  905 +static void spitz_gpio_setup(struct pxa2xx_state_s *cpu, int slots)
  906 +{
  907 + qemu_irq *pcmcia_cb;
  908 + /*
  909 + * Bad hack: We toggle the LCD hsync GPIO on every GPIO status
  910 + * read to satisfy broken guests that poll-wait for hsync.
  911 + * Simulating a real hsync event would be less practical and
  912 + * wouldn't guarantee that a guest ever exits the loop.
  913 + */
  914 + spitz_hsync = 0;
  915 + pxa2xx_gpio_read_notifier(cpu->gpio, spitz_lcd_hsync_handler, cpu);
  916 + pxa2xx_lcd_vsync_cb(cpu->lcd, spitz_lcd_hsync_handler, cpu);
  917 +
  918 + /* MMC/SD host */
  919 + pxa2xx_mmci_handlers(cpu->mmc, cpu, spitz_mmc_writeprotect_change,
  920 + spitz_mmc_coverswitch_change);
  921 +
  922 + /* Battery lock always closed */
  923 + pxa2xx_gpio_set(cpu->gpio, SPITZ_GPIO_BAT_COVER, 1);
  924 +
  925 + /* Handle reset */
  926 + pxa2xx_gpio_handler_set(cpu->gpio, SPITZ_GPIO_ON_RESET, pxa2xx_reset, cpu);
  927 +
  928 + /* PCMCIA signals: card's IRQ and Card-Detect */
  929 + pcmcia_cb = qemu_allocate_irqs(spitz_pcmcia_cb, cpu, slots * 2);
  930 + if (slots >= 1)
  931 + pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0], pcmcia_cb[0], pcmcia_cb[1]);
  932 + if (slots >= 2)
  933 + pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1], pcmcia_cb[2], pcmcia_cb[3]);
  934 +
  935 + /* Initialise the screen rotation related signals */
  936 + spitz_gpio_invert[3] = 0; /* Always open */
  937 + if (graphic_rotate) { /* Tablet mode */
  938 + spitz_gpio_invert[4] = 0;
  939 + } else { /* Portrait mode */
  940 + spitz_gpio_invert[4] = 1;
  941 + }
  942 + pxa2xx_gpio_set(cpu->gpio, SPITZ_GPIO_SWA, spitz_gpio_invert[3]);
  943 + pxa2xx_gpio_set(cpu->gpio, SPITZ_GPIO_SWB, spitz_gpio_invert[4]);
  944 +}
  945 +
  946 +/* Write the bootloader parameters memory area. */
  947 +
  948 +#define MAGIC_CHG(a, b, c, d) ((d << 24) | (c << 16) | (b << 8) | a)
  949 +
  950 +struct __attribute__ ((__packed__)) sl_param_info {
  951 + uint32_t comadj_keyword;
  952 + int32_t comadj;
  953 +
  954 + uint32_t uuid_keyword;
  955 + char uuid[16];
  956 +
  957 + uint32_t touch_keyword;
  958 + int32_t touch_xp;
  959 + int32_t touch_yp;
  960 + int32_t touch_xd;
  961 + int32_t touch_yd;
  962 +
  963 + uint32_t adadj_keyword;
  964 + int32_t adadj;
  965 +
  966 + uint32_t phad_keyword;
  967 + int32_t phadadj;
  968 +} spitz_bootparam = {
  969 + .comadj_keyword = MAGIC_CHG('C', 'M', 'A', 'D'),
  970 + .comadj = 125,
  971 + .uuid_keyword = MAGIC_CHG('U', 'U', 'I', 'D'),
  972 + .uuid = { -1 },
  973 + .touch_keyword = MAGIC_CHG('T', 'U', 'C', 'H'),
  974 + .touch_xp = -1,
  975 + .adadj_keyword = MAGIC_CHG('B', 'V', 'A', 'D'),
  976 + .adadj = -1,
  977 + .phad_keyword = MAGIC_CHG('P', 'H', 'A', 'D'),
  978 + .phadadj = 0x01,
  979 +};
  980 +
  981 +static void sl_bootparam_write(uint32_t ptr)
  982 +{
  983 + memcpy(phys_ram_base + ptr, &spitz_bootparam,
  984 + sizeof(struct sl_param_info));
  985 +}
  986 +
  987 +#define SL_PXA_PARAM_BASE 0xa0000a00
  988 +
  989 +/* Board init. */
  990 +enum spitz_model_e { spitz, akita, borzoi, terrier };
  991 +
  992 +static void spitz_common_init(int ram_size, int vga_ram_size,
  993 + DisplayState *ds, const char *kernel_filename,
  994 + const char *kernel_cmdline, const char *initrd_filename,
  995 + enum spitz_model_e model, int arm_id)
  996 +{
  997 + uint32_t spitz_ram = 0x04000000;
  998 + uint32_t spitz_rom = 0x00800000;
  999 + struct pxa2xx_state_s *cpu;
  1000 + struct scoop_info_s *scp;
  1001 +
  1002 + cpu = pxa270_init(ds, (model == terrier) ? "c5" : "c0");
  1003 +
  1004 + /* Setup memory */
  1005 + if (ram_size < spitz_ram + spitz_rom) {
  1006 + fprintf(stderr, "This platform requires %i bytes of memory\n",
  1007 + spitz_ram + spitz_rom);
  1008 + exit(1);
  1009 + }
  1010 + cpu_register_physical_memory(PXA2XX_RAM_BASE, spitz_ram, IO_MEM_RAM);
  1011 +
  1012 + sl_flash_register(cpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
  1013 +
  1014 + cpu_register_physical_memory(0, spitz_rom, spitz_ram | IO_MEM_ROM);
  1015 +
  1016 + /* Setup peripherals */
  1017 + spitz_keyboard_register(cpu);
  1018 +
  1019 + spitz_ssp_attach(cpu);
  1020 +
  1021 + scp = spitz_scoop_init(cpu, (model == akita) ? 1 : 2);
  1022 +
  1023 + spitz_scoop_gpio_setup(cpu, scp, (model == akita) ? 1 : 2);
  1024 +
  1025 + spitz_gpio_setup(cpu, (model == akita) ? 1 : 2);
  1026 +
  1027 + if (model == terrier)
  1028 + /* A 6.0 GB microdrive is permanently sitting in CF slot 0. */
  1029 + spitz_microdrive_attach(cpu);
  1030 + else if (model != akita)
  1031 + /* A 4.0 GB microdrive is permanently sitting in CF slot 0. */
  1032 + spitz_microdrive_attach(cpu);
  1033 +
  1034 + /* Setup initial (reset) machine state */
  1035 + cpu->env->regs[15] = PXA2XX_RAM_BASE;
  1036 +
  1037 + arm_load_kernel(cpu->env, ram_size, kernel_filename, kernel_cmdline,
  1038 + initrd_filename, arm_id);
  1039 + sl_bootparam_write(SL_PXA_PARAM_BASE - PXA2XX_RAM_BASE);
  1040 +}
  1041 +
  1042 +static void spitz_init(int ram_size, int vga_ram_size, int boot_device,
  1043 + DisplayState *ds, const char **fd_filename, int snapshot,
  1044 + const char *kernel_filename, const char *kernel_cmdline,
  1045 + const char *initrd_filename, const char *cpu_model)
  1046 +{
  1047 + spitz_common_init(ram_size, vga_ram_size, ds, kernel_filename,
  1048 + kernel_cmdline, initrd_filename, spitz, 0x2c9);
  1049 +}
  1050 +
  1051 +static void borzoi_init(int ram_size, int vga_ram_size, int boot_device,
  1052 + DisplayState *ds, const char **fd_filename, int snapshot,
  1053 + const char *kernel_filename, const char *kernel_cmdline,
  1054 + const char *initrd_filename, const char *cpu_model)
  1055 +{
  1056 + spitz_common_init(ram_size, vga_ram_size, ds, kernel_filename,
  1057 + kernel_cmdline, initrd_filename, borzoi, 0x33f);
  1058 +}
  1059 +
  1060 +static void akita_init(int ram_size, int vga_ram_size, int boot_device,
  1061 + DisplayState *ds, const char **fd_filename, int snapshot,
  1062 + const char *kernel_filename, const char *kernel_cmdline,
  1063 + const char *initrd_filename, const char *cpu_model)
  1064 +{
  1065 + spitz_common_init(ram_size, vga_ram_size, ds, kernel_filename,
  1066 + kernel_cmdline, initrd_filename, akita, 0x2e8);
  1067 +}
  1068 +
  1069 +static void terrier_init(int ram_size, int vga_ram_size, int boot_device,
  1070 + DisplayState *ds, const char **fd_filename, int snapshot,
  1071 + const char *kernel_filename, const char *kernel_cmdline,
  1072 + const char *initrd_filename, const char *cpu_model)
  1073 +{
  1074 + spitz_common_init(ram_size, vga_ram_size, ds, kernel_filename,
  1075 + kernel_cmdline, initrd_filename, terrier, 0x33f);
  1076 +}
  1077 +
  1078 +QEMUMachine akitapda_machine = {
  1079 + "akita",
  1080 + "Akita PDA (PXA270)",
  1081 + akita_init,
  1082 +};
  1083 +
  1084 +QEMUMachine spitzpda_machine = {
  1085 + "spitz",
  1086 + "Spitz PDA (PXA270)",
  1087 + spitz_init,
  1088 +};
  1089 +
  1090 +QEMUMachine borzoipda_machine = {
  1091 + "borzoi",
  1092 + "Borzoi PDA (PXA270)",
  1093 + borzoi_init,
  1094 +};
  1095 +
  1096 +QEMUMachine terrierpda_machine = {
  1097 + "terrier",
  1098 + "Terrier PDA (PXA270)",
  1099 + terrier_init,
  1100 +};
... ...
qemu-doc.texi
... ... @@ -80,6 +80,7 @@ For system emulation, the following hardware targets are supported:
80 80 @item ARM Integrator/CP (ARM926E or 1026E processor)
81 81 @item ARM Versatile baseboard (ARM926E)
82 82 @item ARM RealView Emulation baseboard (ARM926EJ-S)
  83 +@item Spitz, Akita, Borzoi and Terrier PDAs (PXA270 processor)
83 84 @end itemize
84 85  
85 86 For user emulation, x86, PowerPC, ARM, MIPS, Sparc32/64 and ColdFire(m68k) CPUs are supported.
... ... @@ -1777,6 +1778,36 @@ LSI53C895A PCI SCSI Host Bus Adapter with hard disk and CD-ROM devices
1777 1778 PL181 MultiMedia Card Interface with SD card.
1778 1779 @end itemize
1779 1780  
  1781 +The XScale-based clamshell PDA models ("Spitz", "Akita", "Borzoi"
  1782 +and "Terrier") emulation includes the following peripherals:
  1783 +
  1784 +@itemize @minus
  1785 +@item
  1786 +Intel PXA270 System-on-chip (ARM V5TE core)
  1787 +@item
  1788 +NAND Flash memory
  1789 +@item
  1790 +IBM/Hitachi DSCM microdrive in a PXA PCMCIA slot - not in "Akita"
  1791 +@item
  1792 +On-chip OHCI USB controller
  1793 +@item
  1794 +On-chip LCD controller
  1795 +@item
  1796 +On-chip Real Time Clock
  1797 +@item
  1798 +TI ADS7846 touchscreen controller on SSP bus
  1799 +@item
  1800 +Maxim MAX1111 analog-digital converter on I@math{^2}C bus
  1801 +@item
  1802 +GPIO-connected keyboard controller and LEDs
  1803 +@item
  1804 +Secure Digital card conntected to PXA MMC/SD host
  1805 +@item
  1806 +Three on-chip UARTs
  1807 +@item
  1808 +WM8750 audio CODEC on I@math{^2}C and I@math{^2}S busses
  1809 +@end itemize
  1810 +
1780 1811 A Linux 2.6 test image is available on the QEMU web site. More
1781 1812 information is available in the QEMU mailing-list archive.
1782 1813  
... ...
... ... @@ -6804,6 +6804,10 @@ void register_machines(void)
6804 6804 qemu_register_machine(&versatilepb_machine);
6805 6805 qemu_register_machine(&versatileab_machine);
6806 6806 qemu_register_machine(&realview_machine);
  6807 + qemu_register_machine(&akitapda_machine);
  6808 + qemu_register_machine(&spitzpda_machine);
  6809 + qemu_register_machine(&borzoipda_machine);
  6810 + qemu_register_machine(&terrierpda_machine);
6807 6811 #elif defined(TARGET_SH4)
6808 6812 qemu_register_machine(&shix_machine);
6809 6813 #elif defined(TARGET_ALPHA)
... ... @@ -6815,6 +6819,7 @@ void register_machines(void)
6815 6819  
6816 6820 #ifdef HAS_AUDIO
6817 6821 struct soundhw soundhw[] = {
  6822 +#ifdef HAS_AUDIO_CHOICE
6818 6823 #ifdef TARGET_I386
6819 6824 {
6820 6825 "pcspk",
... ... @@ -6863,6 +6868,7 @@ struct soundhw soundhw[] = {
6863 6868 0,
6864 6869 { .init_pci = es1370_init }
6865 6870 },
  6871 +#endif
6866 6872  
6867 6873 { NULL, NULL, 0, 0, { NULL } }
6868 6874 };
... ...
... ... @@ -1398,6 +1398,12 @@ extern QEMUMachine versatileab_machine;
1398 1398 /* realview.c */
1399 1399 extern QEMUMachine realview_machine;
1400 1400  
  1401 +/* spitz.c */
  1402 +extern QEMUMachine akitapda_machine;
  1403 +extern QEMUMachine spitzpda_machine;
  1404 +extern QEMUMachine borzoipda_machine;
  1405 +extern QEMUMachine terrierpda_machine;
  1406 +
1401 1407 /* ps2.c */
1402 1408 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg);
1403 1409 void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg);
... ...