Merge remote-tracking branch 'qemu/master'
[qemu/ar7.git] / hw / arm / arm_tt.c
blob7ce97155281611822700a8db62484121489539f9
1 /*
2 * TomTom GO 730 with Samsung S3C2443X emulation.
4 * Copyright (c) 2010, 2013 Stefan Weil
6 * Code based on hw/musicpal.c
7 * Copyright (c) 2008 Jan Kiszka
9 * This code is licensed under the GNU GPL v2 or later.
11 * References:
12 * http://www.opentom.org/TomTom_GO_730
13 * ARM 920T Technical Reference Manual
16 #include "qemu/osdep.h"
17 #include "hw/sysbus.h"
18 #include "hw/arm/arm.h"
19 #include "hw/devices.h"
20 #include "hw/boards.h"
21 #include "hw/i2c/i2c.h"
22 #include "hw/i386/pc.h"
23 #include "hw/ptimer.h" /* ptimer_state */
24 #include "exec/address-spaces.h" /* get_system_memory */
25 #include "net/net.h"
26 #include "sysemu/sysemu.h"
27 #include "qemu/timer.h"
28 #include "block/block.h"
29 #include "chardev/char.h" /* qemu_chr_new */
30 #include "ui/console.h"
32 #include "s3c2440.h"
34 #define logout(fmt, ...) \
35 fprintf(stderr, "S3C2443\t%-24s" fmt, __func__, ##__VA_ARGS__)
37 #define TODO() logout("%s:%u: missing\n", __FILE__, __LINE__)
39 #define MiB (1024 * 1024)
42 Base Address of Special Registers
43 Address Module
44 0x51000000 PWM
45 0x5B000000 AC97
46 0x50000000 UART
47 0x5A000000 SDI
48 0x4F800000 TIC
49 0x4F000000 SSMC
50 0x59000000 SPI
51 0x4E800000 MATRIX
52 0x58000000 TSADC
53 0x4E000000 NFCON
54 0x4D800000 CAM I/F
55 0x4D000000 STN-LCD
56 0x57000000 RTC
57 0x4C800000 TFT-LCD
58 0x4B800000 CF Card
59 0x4B000000 DMA
60 0x55000000 IIS
61 0x4A800000 HS-MMC
62 0x54000000 IIC
63 0x4A000000 INTC
64 0x49800000 USB Device
65 0x53000000 WDT
66 0x49000000 USB HOST
67 0x48800000 EBI
68 0x48000000 Module SDRAM
69 0x52000000 HS-SPI
72 #define S3C2443X_SYSCON 0x4c000000
73 #define S3C2443X_IO_PORT 0x56000000
75 typedef struct {
76 S3CState *soc;
77 } TTState;
79 typedef struct {
80 unsigned offset;
81 const char *name;
82 } OffsetNamePair;
84 #if 0
85 static const char *offset2name(const OffsetNamePair *o2n, unsigned offset)
87 static char buffer[12];
88 const char *name = buffer;
89 snprintf(buffer, sizeof(buffer), "0x%08x", offset);
90 for (; o2n->name; o2n++) {
91 if (offset == o2n->offset) {
92 name = o2n->name;
93 break;
96 return name;
98 #endif
100 #define MP_MISC_BASE 0x80002000
101 #define MP_MISC_SIZE 0x00001000
103 #define MP_GPIO_BASE 0x8000D000
104 #define MP_GPIO_SIZE 0x00001000
106 #define MP_AUDIO_BASE 0x90007000
108 #define MP_LCD_BASE 0x9000c000
109 #define MP_LCD_SIZE 0x00001000
111 #define TT_SRAM_BASE 0xC0000000
112 #define TT_SRAM_SIZE 0x00020000
114 #define MP_RAM_DEFAULT_SIZE (64 * MiB)
116 #define MP_TIMER1_IRQ 4
117 #define MP_TIMER2_IRQ 5
118 #define MP_TIMER3_IRQ 6
119 #define MP_TIMER4_IRQ 7
120 #define MP_EHCI_IRQ 8
121 #define MP_ETH_IRQ 9
122 #define MP_GPIO_IRQ 12
123 #define MP_RTC_IRQ 28
124 #define MP_AUDIO_IRQ 30
126 /* Wolfson 8750 I2C address */
127 #define MP_WM_ADDR 0x1A
129 /* LCD register offsets */
130 #define MP_LCD_IRQCTRL 0x180
131 #define MP_LCD_IRQSTAT 0x184
132 #define MP_LCD_SPICTRL 0x1ac
133 #define MP_LCD_INST 0x1bc
134 #define MP_LCD_DATA 0x1c0
136 /* Mode magics */
137 #define MP_LCD_SPI_DATA 0x00100011
138 #define MP_LCD_SPI_CMD 0x00104011
139 #define MP_LCD_SPI_INVALID 0x00000000
141 /* Commmands */
142 #define MP_LCD_INST_SETPAGE0 0xB0
143 /* ... */
144 #define MP_LCD_INST_SETPAGE7 0xB7
146 #define MP_LCD_TEXTCOLOR 0xe0e0ff /* RRGGBB */
148 #define TYPE_TT_LCD "tt_lcd"
149 #define TT_LCD(obj) OBJECT_CHECK(tt_lcd_state, (obj), TYPE_TT_LCD)
151 typedef struct {
152 SysBusDevice busdev;
153 MemoryRegion mmio;
154 QemuConsole *con;
155 uint32_t brightness;
156 uint32_t mode;
157 uint32_t irqctrl;
158 uint32_t page;
159 uint32_t page_off;
160 uint8_t video_ram[128*64/8];
161 } tt_lcd_state;
163 static uint8_t scale_lcd_color(tt_lcd_state *s, uint8_t col)
165 switch (s->brightness) {
166 case 7:
167 return col;
168 case 0:
169 return 0;
170 default:
171 return (col * s->brightness) / 7;
175 #define SET_LCD_PIXEL(depth, type) \
176 static inline void glue(set_lcd_pixel, depth) \
177 (tt_lcd_state *s, int x, int y, type col) \
179 int dx, dy; \
180 DisplaySurface *surface = qemu_console_surface(s->con); \
181 type *pixel = &((type *) surface_data(surface))[(y * 128 * 3 + x) * 3]; \
183 for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
184 for (dx = 0; dx < 3; dx++, pixel++) \
185 *pixel = col; \
187 SET_LCD_PIXEL(8, uint8_t)
188 SET_LCD_PIXEL(16, uint16_t)
189 SET_LCD_PIXEL(32, uint32_t)
191 #include "ui/pixel_ops.h"
193 static void lcd_refresh(void *opaque)
195 tt_lcd_state *s = opaque;
196 DisplaySurface *surface = qemu_console_surface(s->con);
197 int x, y, col;
199 switch (surface_bits_per_pixel(surface)) {
200 case 0:
201 return;
202 #define LCD_REFRESH(depth, func) \
203 case depth: \
204 col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
205 scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
206 scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
207 for (x = 0; x < 128; x++) { \
208 for (y = 0; y < 64; y++) { \
209 if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
210 glue(set_lcd_pixel, depth)(s, x, y, col); \
211 } else { \
212 glue(set_lcd_pixel, depth)(s, x, y, 0); \
216 break;
217 LCD_REFRESH(8, rgb_to_pixel8)
218 LCD_REFRESH(16, rgb_to_pixel16)
219 LCD_REFRESH(32, (is_surface_bgr(surface) ?
220 rgb_to_pixel32bgr : rgb_to_pixel32))
221 default:
222 hw_error("unsupported colour depth %i\n",
223 surface_bits_per_pixel(surface));
226 dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
229 static void lcd_invalidate(void *opaque)
233 static void tt_lcd_gpio_brigthness_in(void *opaque, int irq, int level)
235 tt_lcd_state *s = opaque;
236 s->brightness &= ~(1 << irq);
237 s->brightness |= level << irq;
240 static uint64_t tt_lcd_read(void *opaque, hwaddr offset,
241 unsigned size)
243 tt_lcd_state *s = opaque;
245 switch (offset) {
246 case MP_LCD_IRQCTRL:
247 return s->irqctrl;
249 default:
250 return 0;
254 static void tt_lcd_write(void *opaque, hwaddr offset,
255 uint64_t value, unsigned size)
257 tt_lcd_state *s = opaque;
259 switch (offset) {
260 case MP_LCD_IRQCTRL:
261 s->irqctrl = value;
262 break;
264 case MP_LCD_SPICTRL:
265 if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD) {
266 s->mode = value;
267 } else {
268 s->mode = MP_LCD_SPI_INVALID;
270 break;
272 case MP_LCD_INST:
273 if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
274 s->page = value - MP_LCD_INST_SETPAGE0;
275 s->page_off = 0;
277 break;
279 case MP_LCD_DATA:
280 if (s->mode == MP_LCD_SPI_CMD) {
281 if (value >= MP_LCD_INST_SETPAGE0 &&
282 value <= MP_LCD_INST_SETPAGE7) {
283 s->page = value - MP_LCD_INST_SETPAGE0;
284 s->page_off = 0;
286 } else if (s->mode == MP_LCD_SPI_DATA) {
287 s->video_ram[s->page*128 + s->page_off] = value;
288 s->page_off = (s->page_off + 1) & 127;
290 break;
294 static const MemoryRegionOps tt_lcd_ops = {
295 .read = tt_lcd_read,
296 .write = tt_lcd_write,
297 .endianness = DEVICE_NATIVE_ENDIAN,
298 .valid = {
299 .min_access_size = 4,
300 .max_access_size = 4
304 static const GraphicHwOps tt_gfx_ops = {
305 .invalidate = lcd_invalidate,
306 .gfx_update = lcd_refresh,
309 static int tt_lcd_init(SysBusDevice *sbd)
311 DeviceState *dev = DEVICE(sbd);
312 tt_lcd_state *s = TT_LCD(dev);
314 s->brightness = 7;
316 memory_region_init_io(&s->mmio, OBJECT(s),
317 &tt_lcd_ops, s, "tt-lcd", MP_LCD_SIZE);
318 sysbus_init_mmio(sbd, &s->mmio);
320 s->con = graphic_console_init(DEVICE(dev), 0, &tt_gfx_ops, s);
321 qemu_console_resize(s->con, 128*3, 64*3);
323 qdev_init_gpio_in(dev, tt_lcd_gpio_brigthness_in, 3);
325 return 0;
328 static const VMStateDescription tt_lcd_vmsd = {
329 .name = TYPE_TT_LCD,
330 .version_id = 1,
331 .minimum_version_id = 1,
332 .minimum_version_id_old = 1,
333 .fields = (VMStateField[]) {
334 VMSTATE_UINT32(brightness, tt_lcd_state),
335 VMSTATE_UINT32(mode, tt_lcd_state),
336 VMSTATE_UINT32(irqctrl, tt_lcd_state),
337 VMSTATE_UINT32(page, tt_lcd_state),
338 VMSTATE_UINT32(page_off, tt_lcd_state),
339 VMSTATE_BUFFER(video_ram, tt_lcd_state),
340 VMSTATE_END_OF_LIST()
344 static void tt_lcd_class_init(ObjectClass *klass, void *data)
346 DeviceClass *dc = DEVICE_CLASS(klass);
347 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
348 dc->desc = "TT LCD",
349 //~ dc->props = dp8381x_properties;
350 //~ dc->reset = qdev_dp8381x_reset;
351 dc->vmsd = &tt_lcd_vmsd;
352 k->init = tt_lcd_init;
355 static const TypeInfo tt_lcd_info = {
356 .name = TYPE_TT_LCD,
357 .parent = TYPE_SYS_BUS_DEVICE,
358 .instance_size = sizeof(tt_lcd_state),
359 .class_init = tt_lcd_class_init,
362 /******************************************************************************/
364 #define S3C2443_MPLLCON 0x10
365 #define S3C2443_CLKDIV0 0x24
367 /******************************************************************************/
369 /* SYSCON register offsets. */
370 #define SYSCON_MPLLCON 0x10
371 #define SYSCON_CLKDIV0 0x24
373 #if 0
374 static const OffsetNamePair tt_syscon_names[] = {
378 static uint64_t tt_syscon_read(void *opaque, hwaddr offset,
379 unsigned size)
381 uint32_t value = 0;
382 logout("%s\n", offset2name(tt_syscon_names, offset));
383 switch (offset) {
384 case SYSCON_MPLLCON:
385 case SYSCON_CLKDIV0:
386 default:
387 TODO();
389 return value;
392 static void tt_syscon_write(void *opaque, hwaddr offset,
393 uint64_t value, unsigned size)
395 logout("%s 0x%08" PRIx64 "\n", offset2name(tt_syscon_names, offset), value);
396 switch (offset) {
397 default:
398 TODO();
402 static const MemoryRegionOps tt_syscon_ops = {
403 .read = tt_syscon_read,
404 .write = tt_syscon_write,
405 .endianness = DEVICE_NATIVE_ENDIAN,
406 .valid = {
407 .min_access_size = 4,
408 .max_access_size = 4
411 #endif
413 /******************************************************************************/
415 /* I/O port register offsets. */
416 #define IOPORT_GPBCON 0x10
417 #define IOPORT_GPBDAT 0x14
418 #define IOPORT_GPBUDP 0x18
419 #define IOPORT_EXTINT0 0x88
420 #define IOPORT_EXTINT1 0x8c
421 #define IOPORT_EXTINT2 0x90
422 #define IOPORT_GSTATUS1 0xb0
425 tt_ioport_write: 0x00000010
426 tt_ioport_write: 0x00000018
427 tt_ioport_write: 0x00000010
428 tt_ioport_write: 0x00000018
431 #if 0
432 static const OffsetNamePair tt_ioport_names[] = {
436 static uint64_t tt_ioport_read(void *opaque, hwaddr offset,
437 unsigned size)
439 uint32_t value = 0;
440 logout("%s\n", offset2name(tt_ioport_names, offset));
441 switch (offset) {
442 case IOPORT_GPBCON:
443 TODO();
444 break;
445 case IOPORT_GPBDAT:
446 TODO();
447 break;
448 case IOPORT_GPBUDP:
449 value = 0x2aaaaa;
450 break;
451 //~ case IOPORT_EXTINT0:
452 //~ case IOPORT_EXTINT1:
453 //~ case IOPORT_EXTINT2:
454 case IOPORT_GSTATUS1:
455 value = 0x32443001;
456 break;
457 default:
458 TODO();
460 return value;
463 static void tt_ioport_write(void *opaque, hwaddr offset,
464 uint64_t value, unsigned size)
466 logout("%s 0x%08" PRIx64 "\n", offset2name(tt_ioport_names, offset), value);
467 switch (offset) {
468 case IOPORT_GPBCON:
469 TODO();
470 break;
471 //~ case IOPORT_GPBDAT:
472 case IOPORT_GPBUDP:
473 TODO();
474 break;
475 case IOPORT_EXTINT0:
476 TODO();
477 break;
478 case IOPORT_EXTINT1:
479 TODO();
480 break;
481 case IOPORT_EXTINT2:
482 TODO();
483 break;
484 //~ case IOPORT_GSTATUS1:
485 default:
486 TODO();
490 static const MemoryRegionOps tt_ioport_ops = {
491 .read = tt_ioport_read,
492 .write = tt_ioport_write,
493 .endianness = DEVICE_NATIVE_ENDIAN,
494 .valid = {
495 .min_access_size = 4,
496 .max_access_size = 4
499 #endif
501 /******************************************************************************/
503 #if 0
504 static void tt_syscon_init(void)
506 memory_region_init_io(&s->syscon, OBJECT(s), &tt_syscon_ops, s,
507 "tt-syscon", 0x10000);
508 memory_region_add_subregion(get_system_memory(), S3C2443X_SYSCON, &s->syscon);
511 static void tt_ioport_init(void)
513 memory_region_init_io(&s->ioport, OBJECT(s), &tt_ioport_ops, s,
514 "tt-ioport", 0x10000);
515 memory_region_add_subregion(get_system_memory(), S3C2443X_IO_PORT, &s->ioport);
517 #endif
519 /* GPIO register offsets */
520 #define MP_GPIO_OE_LO 0x008
521 #define MP_GPIO_OUT_LO 0x00c
522 #define MP_GPIO_IN_LO 0x010
523 #define MP_GPIO_IER_LO 0x014
524 #define MP_GPIO_IMR_LO 0x018
525 #define MP_GPIO_ISR_LO 0x020
526 #define MP_GPIO_OE_HI 0x508
527 #define MP_GPIO_OUT_HI 0x50c
528 #define MP_GPIO_IN_HI 0x510
529 #define MP_GPIO_IER_HI 0x514
530 #define MP_GPIO_IMR_HI 0x518
531 #define MP_GPIO_ISR_HI 0x520
533 /* GPIO bits & masks */
534 #define MP_GPIO_LCD_BRIGHTNESS 0x00070000
535 #define MP_GPIO_I2C_DATA_BIT 29
536 #define MP_GPIO_I2C_CLOCK_BIT 30
538 /* LCD brightness bits in GPIO_OE_HI */
539 #define MP_OE_LCD_BRIGHTNESS 0x0007
541 #define TYPE_TT_GPIO "tt_gpio"
542 #define TT_GPIO(obj) \
543 OBJECT_CHECK(tt_gpio_state, (obj), TYPE_TT_GPIO)
545 typedef struct {
546 SysBusDevice busdev;
547 MemoryRegion mmio;
548 uint32_t lcd_brightness;
549 uint32_t out_state;
550 uint32_t in_state;
551 uint32_t ier;
552 uint32_t imr;
553 uint32_t isr;
554 qemu_irq irq;
555 qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
556 } tt_gpio_state;
558 static void tt_gpio_brightness_update(tt_gpio_state *s) {
559 int i;
560 uint32_t brightness;
562 /* compute brightness ratio */
563 switch (s->lcd_brightness) {
564 case 0x00000007:
565 brightness = 0;
566 break;
568 case 0x00020000:
569 brightness = 1;
570 break;
572 case 0x00020001:
573 brightness = 2;
574 break;
576 case 0x00040000:
577 brightness = 3;
578 break;
580 case 0x00010006:
581 brightness = 4;
582 break;
584 case 0x00020005:
585 brightness = 5;
586 break;
588 case 0x00040003:
589 brightness = 6;
590 break;
592 case 0x00030004:
593 default:
594 brightness = 7;
597 /* set lcd brightness GPIOs */
598 for (i = 0; i <= 2; i++) {
599 qemu_set_irq(s->out[i], (brightness >> i) & 1);
603 static void tt_gpio_pin_event(void *opaque, int pin, int level)
605 tt_gpio_state *s = opaque;
606 uint32_t mask = 1 << pin;
607 uint32_t delta = level << pin;
608 uint32_t old = s->in_state & mask;
610 s->in_state &= ~mask;
611 s->in_state |= delta;
613 if ((old ^ delta) &&
614 ((level && (s->imr & mask)) || (!level && (s->ier & mask)))) {
615 s->isr = mask;
616 qemu_irq_raise(s->irq);
620 static uint64_t tt_gpio_read(void *opaque, hwaddr offset,
621 unsigned size)
623 tt_gpio_state *s = opaque;
625 switch (offset) {
626 case MP_GPIO_OE_HI: /* used for LCD brightness control */
627 return s->lcd_brightness & MP_OE_LCD_BRIGHTNESS;
629 case MP_GPIO_OUT_LO:
630 return s->out_state & 0xFFFF;
631 case MP_GPIO_OUT_HI:
632 return s->out_state >> 16;
634 case MP_GPIO_IN_LO:
635 return s->in_state & 0xFFFF;
636 case MP_GPIO_IN_HI:
637 return s->in_state >> 16;
639 case MP_GPIO_IER_LO:
640 return s->ier & 0xFFFF;
641 case MP_GPIO_IER_HI:
642 return s->ier >> 16;
644 case MP_GPIO_IMR_LO:
645 return s->imr & 0xFFFF;
646 case MP_GPIO_IMR_HI:
647 return s->imr >> 16;
649 case MP_GPIO_ISR_LO:
650 return s->isr & 0xFFFF;
651 case MP_GPIO_ISR_HI:
652 return s->isr >> 16;
654 default:
655 return 0;
659 static void tt_gpio_write(void *opaque, hwaddr offset,
660 uint64_t value, unsigned size)
662 tt_gpio_state *s = opaque;
663 switch (offset) {
664 case MP_GPIO_OE_HI: /* used for LCD brightness control */
665 s->lcd_brightness = (s->lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
666 (value & MP_OE_LCD_BRIGHTNESS);
667 tt_gpio_brightness_update(s);
668 break;
670 case MP_GPIO_OUT_LO:
671 s->out_state = (s->out_state & 0xFFFF0000) | (value & 0xFFFF);
672 break;
673 case MP_GPIO_OUT_HI:
674 s->out_state = (s->out_state & 0xFFFF) | (value << 16);
675 s->lcd_brightness = (s->lcd_brightness & 0xFFFF) |
676 (s->out_state & MP_GPIO_LCD_BRIGHTNESS);
677 tt_gpio_brightness_update(s);
678 qemu_set_irq(s->out[3], (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1);
679 qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
680 break;
682 case MP_GPIO_IER_LO:
683 s->ier = (s->ier & 0xFFFF0000) | (value & 0xFFFF);
684 break;
685 case MP_GPIO_IER_HI:
686 s->ier = (s->ier & 0xFFFF) | (value << 16);
687 break;
689 case MP_GPIO_IMR_LO:
690 s->imr = (s->imr & 0xFFFF0000) | (value & 0xFFFF);
691 break;
692 case MP_GPIO_IMR_HI:
693 s->imr = (s->imr & 0xFFFF) | (value << 16);
694 break;
698 static const MemoryRegionOps tt_gpio_ops = {
699 .read = tt_gpio_read,
700 .write = tt_gpio_write,
701 .endianness = DEVICE_NATIVE_ENDIAN,
702 .valid = {
703 .min_access_size = 4,
704 .max_access_size = 4
708 static void tt_gpio_reset(DeviceState *d)
710 tt_gpio_state *s = TT_GPIO(d);
712 s->lcd_brightness = 0;
713 s->out_state = 0;
714 s->in_state = 0xffffffff;
715 s->ier = 0;
716 s->imr = 0;
717 s->isr = 0;
720 static int tt_gpio_init(SysBusDevice *sbd)
722 DeviceState *dev = DEVICE(sbd);
723 tt_gpio_state *s = TT_GPIO(dev);
725 sysbus_init_irq(sbd, &s->irq);
727 memory_region_init_io(&s->mmio, OBJECT(s), &tt_gpio_ops, s,
728 "tt-gpio", MP_GPIO_SIZE);
729 sysbus_init_mmio(sbd, &s->mmio);
731 qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
733 qdev_init_gpio_in(dev, tt_gpio_pin_event, 32);
735 return 0;
738 static const VMStateDescription tt_gpio_vmsd = {
739 .name = TYPE_TT_GPIO,
740 .version_id = 1,
741 .minimum_version_id = 1,
742 .minimum_version_id_old = 1,
743 .fields = (VMStateField[]) {
744 VMSTATE_UINT32(lcd_brightness, tt_gpio_state),
745 VMSTATE_UINT32(out_state, tt_gpio_state),
746 VMSTATE_UINT32(in_state, tt_gpio_state),
747 VMSTATE_UINT32(ier, tt_gpio_state),
748 VMSTATE_UINT32(imr, tt_gpio_state),
749 VMSTATE_UINT32(isr, tt_gpio_state),
750 VMSTATE_END_OF_LIST()
754 static void tt_gpio_class_init(ObjectClass *klass, void *data)
756 DeviceClass *dc = DEVICE_CLASS(klass);
757 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
758 dc->reset = tt_gpio_reset;
759 dc->vmsd = &tt_gpio_vmsd;
760 k->init = tt_gpio_init;
763 static const TypeInfo tt_gpio_info = {
764 .name = TYPE_TT_GPIO,
765 .parent = TYPE_SYS_BUS_DEVICE,
766 .instance_size = sizeof(tt_gpio_state),
767 .class_init = tt_gpio_class_init,
770 /* Keyboard codes & masks */
771 #define KEY_RELEASED 0x80
772 #define KEY_CODE 0x7f
774 #define KEYCODE_TAB 0x0f
775 #define KEYCODE_ENTER 0x1c
776 #define KEYCODE_F 0x21
777 #define KEYCODE_M 0x32
779 #define KEYCODE_EXTENDED 0xe0
780 #define KEYCODE_UP 0x48
781 #define KEYCODE_DOWN 0x50
782 #define KEYCODE_LEFT 0x4b
783 #define KEYCODE_RIGHT 0x4d
785 #define MP_KEY_WHEEL_VOL (1 << 0)
786 #define MP_KEY_WHEEL_VOL_INV (1 << 1)
787 #define MP_KEY_WHEEL_NAV (1 << 2)
788 #define MP_KEY_WHEEL_NAV_INV (1 << 3)
789 #define MP_KEY_BTN_FAVORITS (1 << 4)
790 #define MP_KEY_BTN_MENU (1 << 5)
791 #define MP_KEY_BTN_VOLUME (1 << 6)
792 #define MP_KEY_BTN_NAVIGATION (1 << 7)
794 #define TYPE_TT_KEY "tt_key"
795 #define TT_KEY(obj) \
796 OBJECT_CHECK(tt_key_state, (obj), TYPE_TT_KEY)
798 typedef struct {
799 SysBusDevice busdev;
800 MemoryRegion mmio;
801 uint32_t kbd_extended;
802 uint32_t pressed_keys;
803 qemu_irq out[8];
804 } tt_key_state;
806 static void tt_key_event(void *opaque, int keycode)
808 tt_key_state *s = opaque;
809 uint32_t event = 0;
810 int i;
812 if (keycode == KEYCODE_EXTENDED) {
813 s->kbd_extended = 1;
814 return;
817 if (s->kbd_extended) {
818 switch (keycode & KEY_CODE) {
819 case KEYCODE_UP:
820 event = MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_NAV_INV;
821 break;
823 case KEYCODE_DOWN:
824 event = MP_KEY_WHEEL_NAV;
825 break;
827 case KEYCODE_LEFT:
828 event = MP_KEY_WHEEL_VOL | MP_KEY_WHEEL_VOL_INV;
829 break;
831 case KEYCODE_RIGHT:
832 event = MP_KEY_WHEEL_VOL;
833 break;
835 } else {
836 switch (keycode & KEY_CODE) {
837 case KEYCODE_F:
838 event = MP_KEY_BTN_FAVORITS;
839 break;
841 case KEYCODE_TAB:
842 event = MP_KEY_BTN_VOLUME;
843 break;
845 case KEYCODE_ENTER:
846 event = MP_KEY_BTN_NAVIGATION;
847 break;
849 case KEYCODE_M:
850 event = MP_KEY_BTN_MENU;
851 break;
853 /* Do not repeat already pressed buttons */
854 if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
855 event = 0;
859 if (event) {
860 /* Raise GPIO pin first if repeating a key */
861 if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
862 for (i = 0; i <= 7; i++) {
863 if (event & (1 << i)) {
864 qemu_set_irq(s->out[i], 1);
868 for (i = 0; i <= 7; i++) {
869 if (event & (1 << i)) {
870 qemu_set_irq(s->out[i], !!(keycode & KEY_RELEASED));
873 if (keycode & KEY_RELEASED) {
874 s->pressed_keys &= ~event;
875 } else {
876 s->pressed_keys |= event;
880 s->kbd_extended = 0;
883 static int tt_key_init(SysBusDevice *sbd)
885 DeviceState *dev = DEVICE(sbd);
886 tt_key_state *s = TT_KEY(dev);
888 sysbus_init_mmio(sbd, &s->mmio);
890 s->kbd_extended = 0;
891 s->pressed_keys = 0;
893 qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
895 qemu_add_kbd_event_handler(tt_key_event, s);
897 return 0;
900 static const VMStateDescription tt_key_vmsd = {
901 .name = TYPE_TT_KEY,
902 .version_id = 1,
903 .minimum_version_id = 1,
904 .minimum_version_id_old = 1,
905 .fields = (VMStateField[]) {
906 VMSTATE_UINT32(kbd_extended, tt_key_state),
907 VMSTATE_UINT32(pressed_keys, tt_key_state),
908 VMSTATE_END_OF_LIST()
912 static void tt_key_class_init(ObjectClass *klass, void *data)
914 DeviceClass *dc = DEVICE_CLASS(klass);
915 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
916 dc->vmsd = &tt_key_vmsd;
917 k->init = tt_key_init;
920 static const TypeInfo tt_key_info = {
921 .name = TYPE_TT_KEY,
922 .parent = TYPE_SYS_BUS_DEVICE,
923 .instance_size = sizeof(tt_key_state),
924 .class_init = tt_key_class_init,
927 static struct arm_boot_info tt_binfo = {
928 #if 0
929 .loader_start = 0,
930 #else
931 .loader_start = TT_SRAM_BASE,
932 #endif
933 /* GO 730 */
934 .board_id = 0x25d,
935 .atag_revision = 0x0004000a,
938 static void tt_init(MachineState *machine)
940 ARMCPU *cpu;
941 TTState *s;
942 #if 0
943 qemu_irq pic[32];
944 DeviceState *dev;
945 DeviceState *i2c_dev;
946 DeviceState *lcd_dev;
947 DeviceState *key_dev;
948 DeviceState *wm8750_dev;
949 SysBusDevice *s;
950 I2CBus *i2c;
951 unsigned long flash_size;
952 DriveInfo *dinfo;
953 ram_addr_t ram_off;
954 ram_addr_t sram_off;
955 #endif
956 unsigned i;
958 #if 0
959 if (machine->cpu_model && strcmp(machine->cpu_model, "arm920t")) {
960 fprintf(stderr, "only working with cpu arm920t\n");
961 exit(1);
963 #endif
965 /* Allocate storage for board state. */
966 s = g_new0(TTState, 1);
968 for (i = 0; i < serial_max_hds(); i++) {
969 #if 1
970 assert(i < 3);
971 assert(serial_hd(i));
972 #else
973 /* TODO: This code no longer works. Remove or replace. */
974 if (serial_hd(i) == NULL) {
975 char name[32];
976 snprintf(name, sizeof(name), "serial%u", i);
977 serial_hd(i) = qemu_chr_new(name, "vc:80Cx24C");
979 #endif
982 /* Initialise SOC. */
983 s->soc = s3c2440_init(ram_size);
985 cpu = s->soc->cpu;
987 //~ ram_off = qemu_ram_alloc(NULL, "arm920.ram", ram_size);
988 //~ cpu_register_physical_memory(0x00000000, ram_size, ram_off | IO_MEM_RAM);
989 //~ cpu_register_physical_memory(0x30000000, ram_size, ram_off | IO_MEM_RAM);
990 //~ cpu_register_physical_memory(0x80000000, ram_size, ram_off | IO_MEM_RAM);
991 //~ cpu_register_physical_memory(0xc0000000, ram_size, ram_off | IO_MEM_RAM);
993 //~ tt_syscon_init();
994 //~ tt_ioport_init();
996 #if 0
997 dev = sysbus_create_simple(TYPE_TT_GPIO, MP_GPIO_BASE, pic[MP_GPIO_IRQ]);
998 i2c_dev = sysbus_create_simple("gpio_i2c", 0, NULL);
999 i2c = (I2CBus *)qdev_get_child_bus(i2c_dev, "i2c");
1001 lcd_dev = sysbus_create_simple(TYPE_TT_LCD, MP_LCD_BASE, NULL);
1002 key_dev = sysbus_create_simple(TYPE_TT_KEY, 0, NULL);
1004 /* I2C read data */
1005 qdev_connect_gpio_out(i2c_dev, 0,
1006 qdev_get_gpio_in(dev, MP_GPIO_I2C_DATA_BIT));
1007 /* I2C data */
1008 qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0));
1009 /* I2C clock */
1010 qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1));
1012 for (i = 0; i < 3; i++) {
1013 qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i));
1015 for (i = 0; i < 4; i++) {
1016 qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 8));
1018 for (i = 4; i < 8; i++) {
1019 qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
1022 wm8750_dev = i2c_create_slave(i2c, "wm8750", MP_WM_ADDR);
1023 dev = qdev_create(NULL, "mv88w8618_audio");
1024 s = SYS_BUS_DEVICE(dev);
1025 qdev_prop_set_ptr(dev, "wm8750", wm8750_dev);
1026 qdev_init_nofail(dev);
1027 sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
1028 sysbus_connect_irq(s, 0, pic[MP_AUDIO_IRQ]);
1029 #endif
1031 tt_binfo.ram_size = ram_size;
1032 tt_binfo.kernel_filename = machine->kernel_filename;
1033 tt_binfo.kernel_cmdline = machine->kernel_cmdline;
1034 tt_binfo.initrd_filename = machine->initrd_filename;
1035 if (machine->kernel_filename != NULL) {
1036 /* TODO: load ttsystem. */
1037 //~ sect_size = 0x11b778, sect_addr = 0x31700000
1038 //~ sect_size = 0x6a3f45, sect_addr = 0x31000000
1039 arm_load_kernel(cpu, &tt_binfo);
1043 static void tt_init_go(MachineState *machine)
1045 tt_binfo.board_id = 0x25d;
1046 ram_size = 64 * MiB;
1047 tt_init(machine);
1050 static void tt_init_666(MachineState *machine)
1052 tt_binfo.board_id = 0x666;
1053 tt_init(machine);
1056 static void tt_init_smdk2443(MachineState *machine)
1058 tt_binfo.board_id = 0x43c;
1059 tt_init(machine);
1062 static void tt_machine_init(MachineClass *mc)
1064 mc->desc = "OpenTom (ARM920-T)";
1065 mc->init = tt_init_go;
1068 DEFINE_MACHINE("tt", tt_machine_init)
1070 static void tt_machine_666_init(MachineClass *mc)
1072 mc->desc = "OpenTom (ARM920-T)";
1073 mc->init = tt_init_666;
1076 DEFINE_MACHINE("tt666", tt_machine_666_init)
1078 static void tt_machine_smdk2443_init(MachineClass *mc)
1080 mc->desc = "smdk2443 (ARM920-T)";
1081 mc->init = tt_init_smdk2443;
1084 DEFINE_MACHINE("smdk2443", tt_machine_smdk2443_init)
1086 static void tt_register_types(void)
1088 type_register_static(&tt_lcd_info);
1089 type_register_static(&tt_gpio_info);
1090 type_register_static(&tt_key_info);
1093 type_init(tt_register_types)