Merge remote-tracking branch 'qemu/master'
[qemu/ar7.git] / hw / arm / arm_tt.c
blob279520d77bfabf58e03d65a0807b0a192e81ea4e
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 void tt_lcd_realize(DeviceState *dev, Error **errp)
311 tt_lcd_state *s = TT_LCD(dev);
312 SysBusDevice *sbd = SYS_BUS_DEVICE(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);
326 static const VMStateDescription tt_lcd_vmsd = {
327 .name = TYPE_TT_LCD,
328 .version_id = 1,
329 .minimum_version_id = 1,
330 .minimum_version_id_old = 1,
331 .fields = (VMStateField[]) {
332 VMSTATE_UINT32(brightness, tt_lcd_state),
333 VMSTATE_UINT32(mode, tt_lcd_state),
334 VMSTATE_UINT32(irqctrl, tt_lcd_state),
335 VMSTATE_UINT32(page, tt_lcd_state),
336 VMSTATE_UINT32(page_off, tt_lcd_state),
337 VMSTATE_BUFFER(video_ram, tt_lcd_state),
338 VMSTATE_END_OF_LIST()
342 static void tt_lcd_class_init(ObjectClass *klass, void *data)
344 DeviceClass *dc = DEVICE_CLASS(klass);
345 dc->desc = "TT LCD",
346 //~ dc->props = dp8381x_properties;
347 dc->realize = tt_lcd_realize;
348 //~ dc->reset = qdev_dp8381x_reset;
349 dc->vmsd = &tt_lcd_vmsd;
352 static const TypeInfo tt_lcd_info = {
353 .name = TYPE_TT_LCD,
354 .parent = TYPE_SYS_BUS_DEVICE,
355 .instance_size = sizeof(tt_lcd_state),
356 .class_init = tt_lcd_class_init,
359 /******************************************************************************/
361 #define S3C2443_MPLLCON 0x10
362 #define S3C2443_CLKDIV0 0x24
364 /******************************************************************************/
366 /* SYSCON register offsets. */
367 #define SYSCON_MPLLCON 0x10
368 #define SYSCON_CLKDIV0 0x24
370 #if 0
371 static const OffsetNamePair tt_syscon_names[] = {
375 static uint64_t tt_syscon_read(void *opaque, hwaddr offset,
376 unsigned size)
378 uint32_t value = 0;
379 logout("%s\n", offset2name(tt_syscon_names, offset));
380 switch (offset) {
381 case SYSCON_MPLLCON:
382 case SYSCON_CLKDIV0:
383 default:
384 TODO();
386 return value;
389 static void tt_syscon_write(void *opaque, hwaddr offset,
390 uint64_t value, unsigned size)
392 logout("%s 0x%08" PRIx64 "\n", offset2name(tt_syscon_names, offset), value);
393 switch (offset) {
394 default:
395 TODO();
399 static const MemoryRegionOps tt_syscon_ops = {
400 .read = tt_syscon_read,
401 .write = tt_syscon_write,
402 .endianness = DEVICE_NATIVE_ENDIAN,
403 .valid = {
404 .min_access_size = 4,
405 .max_access_size = 4
408 #endif
410 /******************************************************************************/
412 /* I/O port register offsets. */
413 #define IOPORT_GPBCON 0x10
414 #define IOPORT_GPBDAT 0x14
415 #define IOPORT_GPBUDP 0x18
416 #define IOPORT_EXTINT0 0x88
417 #define IOPORT_EXTINT1 0x8c
418 #define IOPORT_EXTINT2 0x90
419 #define IOPORT_GSTATUS1 0xb0
422 tt_ioport_write: 0x00000010
423 tt_ioport_write: 0x00000018
424 tt_ioport_write: 0x00000010
425 tt_ioport_write: 0x00000018
428 #if 0
429 static const OffsetNamePair tt_ioport_names[] = {
433 static uint64_t tt_ioport_read(void *opaque, hwaddr offset,
434 unsigned size)
436 uint32_t value = 0;
437 logout("%s\n", offset2name(tt_ioport_names, offset));
438 switch (offset) {
439 case IOPORT_GPBCON:
440 TODO();
441 break;
442 case IOPORT_GPBDAT:
443 TODO();
444 break;
445 case IOPORT_GPBUDP:
446 value = 0x2aaaaa;
447 break;
448 //~ case IOPORT_EXTINT0:
449 //~ case IOPORT_EXTINT1:
450 //~ case IOPORT_EXTINT2:
451 case IOPORT_GSTATUS1:
452 value = 0x32443001;
453 break;
454 default:
455 TODO();
457 return value;
460 static void tt_ioport_write(void *opaque, hwaddr offset,
461 uint64_t value, unsigned size)
463 logout("%s 0x%08" PRIx64 "\n", offset2name(tt_ioport_names, offset), value);
464 switch (offset) {
465 case IOPORT_GPBCON:
466 TODO();
467 break;
468 //~ case IOPORT_GPBDAT:
469 case IOPORT_GPBUDP:
470 TODO();
471 break;
472 case IOPORT_EXTINT0:
473 TODO();
474 break;
475 case IOPORT_EXTINT1:
476 TODO();
477 break;
478 case IOPORT_EXTINT2:
479 TODO();
480 break;
481 //~ case IOPORT_GSTATUS1:
482 default:
483 TODO();
487 static const MemoryRegionOps tt_ioport_ops = {
488 .read = tt_ioport_read,
489 .write = tt_ioport_write,
490 .endianness = DEVICE_NATIVE_ENDIAN,
491 .valid = {
492 .min_access_size = 4,
493 .max_access_size = 4
496 #endif
498 /******************************************************************************/
500 #if 0
501 static void tt_syscon_init(void)
503 memory_region_init_io(&s->syscon, OBJECT(s), &tt_syscon_ops, s,
504 "tt-syscon", 0x10000);
505 memory_region_add_subregion(get_system_memory(), S3C2443X_SYSCON, &s->syscon);
508 static void tt_ioport_init(void)
510 memory_region_init_io(&s->ioport, OBJECT(s), &tt_ioport_ops, s,
511 "tt-ioport", 0x10000);
512 memory_region_add_subregion(get_system_memory(), S3C2443X_IO_PORT, &s->ioport);
514 #endif
516 /* GPIO register offsets */
517 #define MP_GPIO_OE_LO 0x008
518 #define MP_GPIO_OUT_LO 0x00c
519 #define MP_GPIO_IN_LO 0x010
520 #define MP_GPIO_IER_LO 0x014
521 #define MP_GPIO_IMR_LO 0x018
522 #define MP_GPIO_ISR_LO 0x020
523 #define MP_GPIO_OE_HI 0x508
524 #define MP_GPIO_OUT_HI 0x50c
525 #define MP_GPIO_IN_HI 0x510
526 #define MP_GPIO_IER_HI 0x514
527 #define MP_GPIO_IMR_HI 0x518
528 #define MP_GPIO_ISR_HI 0x520
530 /* GPIO bits & masks */
531 #define MP_GPIO_LCD_BRIGHTNESS 0x00070000
532 #define MP_GPIO_I2C_DATA_BIT 29
533 #define MP_GPIO_I2C_CLOCK_BIT 30
535 /* LCD brightness bits in GPIO_OE_HI */
536 #define MP_OE_LCD_BRIGHTNESS 0x0007
538 #define TYPE_TT_GPIO "tt_gpio"
539 #define TT_GPIO(obj) \
540 OBJECT_CHECK(tt_gpio_state, (obj), TYPE_TT_GPIO)
542 typedef struct {
543 SysBusDevice busdev;
544 MemoryRegion mmio;
545 uint32_t lcd_brightness;
546 uint32_t out_state;
547 uint32_t in_state;
548 uint32_t ier;
549 uint32_t imr;
550 uint32_t isr;
551 qemu_irq irq;
552 qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
553 } tt_gpio_state;
555 static void tt_gpio_brightness_update(tt_gpio_state *s) {
556 int i;
557 uint32_t brightness;
559 /* compute brightness ratio */
560 switch (s->lcd_brightness) {
561 case 0x00000007:
562 brightness = 0;
563 break;
565 case 0x00020000:
566 brightness = 1;
567 break;
569 case 0x00020001:
570 brightness = 2;
571 break;
573 case 0x00040000:
574 brightness = 3;
575 break;
577 case 0x00010006:
578 brightness = 4;
579 break;
581 case 0x00020005:
582 brightness = 5;
583 break;
585 case 0x00040003:
586 brightness = 6;
587 break;
589 case 0x00030004:
590 default:
591 brightness = 7;
594 /* set lcd brightness GPIOs */
595 for (i = 0; i <= 2; i++) {
596 qemu_set_irq(s->out[i], (brightness >> i) & 1);
600 static void tt_gpio_pin_event(void *opaque, int pin, int level)
602 tt_gpio_state *s = opaque;
603 uint32_t mask = 1 << pin;
604 uint32_t delta = level << pin;
605 uint32_t old = s->in_state & mask;
607 s->in_state &= ~mask;
608 s->in_state |= delta;
610 if ((old ^ delta) &&
611 ((level && (s->imr & mask)) || (!level && (s->ier & mask)))) {
612 s->isr = mask;
613 qemu_irq_raise(s->irq);
617 static uint64_t tt_gpio_read(void *opaque, hwaddr offset,
618 unsigned size)
620 tt_gpio_state *s = opaque;
622 switch (offset) {
623 case MP_GPIO_OE_HI: /* used for LCD brightness control */
624 return s->lcd_brightness & MP_OE_LCD_BRIGHTNESS;
626 case MP_GPIO_OUT_LO:
627 return s->out_state & 0xFFFF;
628 case MP_GPIO_OUT_HI:
629 return s->out_state >> 16;
631 case MP_GPIO_IN_LO:
632 return s->in_state & 0xFFFF;
633 case MP_GPIO_IN_HI:
634 return s->in_state >> 16;
636 case MP_GPIO_IER_LO:
637 return s->ier & 0xFFFF;
638 case MP_GPIO_IER_HI:
639 return s->ier >> 16;
641 case MP_GPIO_IMR_LO:
642 return s->imr & 0xFFFF;
643 case MP_GPIO_IMR_HI:
644 return s->imr >> 16;
646 case MP_GPIO_ISR_LO:
647 return s->isr & 0xFFFF;
648 case MP_GPIO_ISR_HI:
649 return s->isr >> 16;
651 default:
652 return 0;
656 static void tt_gpio_write(void *opaque, hwaddr offset,
657 uint64_t value, unsigned size)
659 tt_gpio_state *s = opaque;
660 switch (offset) {
661 case MP_GPIO_OE_HI: /* used for LCD brightness control */
662 s->lcd_brightness = (s->lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
663 (value & MP_OE_LCD_BRIGHTNESS);
664 tt_gpio_brightness_update(s);
665 break;
667 case MP_GPIO_OUT_LO:
668 s->out_state = (s->out_state & 0xFFFF0000) | (value & 0xFFFF);
669 break;
670 case MP_GPIO_OUT_HI:
671 s->out_state = (s->out_state & 0xFFFF) | (value << 16);
672 s->lcd_brightness = (s->lcd_brightness & 0xFFFF) |
673 (s->out_state & MP_GPIO_LCD_BRIGHTNESS);
674 tt_gpio_brightness_update(s);
675 qemu_set_irq(s->out[3], (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1);
676 qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
677 break;
679 case MP_GPIO_IER_LO:
680 s->ier = (s->ier & 0xFFFF0000) | (value & 0xFFFF);
681 break;
682 case MP_GPIO_IER_HI:
683 s->ier = (s->ier & 0xFFFF) | (value << 16);
684 break;
686 case MP_GPIO_IMR_LO:
687 s->imr = (s->imr & 0xFFFF0000) | (value & 0xFFFF);
688 break;
689 case MP_GPIO_IMR_HI:
690 s->imr = (s->imr & 0xFFFF) | (value << 16);
691 break;
695 static const MemoryRegionOps tt_gpio_ops = {
696 .read = tt_gpio_read,
697 .write = tt_gpio_write,
698 .endianness = DEVICE_NATIVE_ENDIAN,
699 .valid = {
700 .min_access_size = 4,
701 .max_access_size = 4
705 static void tt_gpio_reset(DeviceState *d)
707 tt_gpio_state *s = TT_GPIO(d);
709 s->lcd_brightness = 0;
710 s->out_state = 0;
711 s->in_state = 0xffffffff;
712 s->ier = 0;
713 s->imr = 0;
714 s->isr = 0;
717 static void tt_gpio_realize(DeviceState *dev, Error **errp)
719 tt_gpio_state *s = TT_GPIO(dev);
720 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
722 sysbus_init_irq(sbd, &s->irq);
724 memory_region_init_io(&s->mmio, OBJECT(s), &tt_gpio_ops, s,
725 "tt-gpio", MP_GPIO_SIZE);
726 sysbus_init_mmio(sbd, &s->mmio);
728 qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
730 qdev_init_gpio_in(dev, tt_gpio_pin_event, 32);
733 static const VMStateDescription tt_gpio_vmsd = {
734 .name = TYPE_TT_GPIO,
735 .version_id = 1,
736 .minimum_version_id = 1,
737 .minimum_version_id_old = 1,
738 .fields = (VMStateField[]) {
739 VMSTATE_UINT32(lcd_brightness, tt_gpio_state),
740 VMSTATE_UINT32(out_state, tt_gpio_state),
741 VMSTATE_UINT32(in_state, tt_gpio_state),
742 VMSTATE_UINT32(ier, tt_gpio_state),
743 VMSTATE_UINT32(imr, tt_gpio_state),
744 VMSTATE_UINT32(isr, tt_gpio_state),
745 VMSTATE_END_OF_LIST()
749 static void tt_gpio_class_init(ObjectClass *klass, void *data)
751 DeviceClass *dc = DEVICE_CLASS(klass);
752 dc->realize = tt_gpio_realize;
753 dc->reset = tt_gpio_reset;
754 dc->vmsd = &tt_gpio_vmsd;
757 static const TypeInfo tt_gpio_info = {
758 .name = TYPE_TT_GPIO,
759 .parent = TYPE_SYS_BUS_DEVICE,
760 .instance_size = sizeof(tt_gpio_state),
761 .class_init = tt_gpio_class_init,
764 /* Keyboard codes & masks */
765 #define KEY_RELEASED 0x80
766 #define KEY_CODE 0x7f
768 #define KEYCODE_TAB 0x0f
769 #define KEYCODE_ENTER 0x1c
770 #define KEYCODE_F 0x21
771 #define KEYCODE_M 0x32
773 #define KEYCODE_EXTENDED 0xe0
774 #define KEYCODE_UP 0x48
775 #define KEYCODE_DOWN 0x50
776 #define KEYCODE_LEFT 0x4b
777 #define KEYCODE_RIGHT 0x4d
779 #define MP_KEY_WHEEL_VOL (1 << 0)
780 #define MP_KEY_WHEEL_VOL_INV (1 << 1)
781 #define MP_KEY_WHEEL_NAV (1 << 2)
782 #define MP_KEY_WHEEL_NAV_INV (1 << 3)
783 #define MP_KEY_BTN_FAVORITS (1 << 4)
784 #define MP_KEY_BTN_MENU (1 << 5)
785 #define MP_KEY_BTN_VOLUME (1 << 6)
786 #define MP_KEY_BTN_NAVIGATION (1 << 7)
788 #define TYPE_TT_KEY "tt_key"
789 #define TT_KEY(obj) \
790 OBJECT_CHECK(tt_key_state, (obj), TYPE_TT_KEY)
792 typedef struct {
793 SysBusDevice busdev;
794 MemoryRegion mmio;
795 uint32_t kbd_extended;
796 uint32_t pressed_keys;
797 qemu_irq out[8];
798 } tt_key_state;
800 static void tt_key_event(void *opaque, int keycode)
802 tt_key_state *s = opaque;
803 uint32_t event = 0;
804 int i;
806 if (keycode == KEYCODE_EXTENDED) {
807 s->kbd_extended = 1;
808 return;
811 if (s->kbd_extended) {
812 switch (keycode & KEY_CODE) {
813 case KEYCODE_UP:
814 event = MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_NAV_INV;
815 break;
817 case KEYCODE_DOWN:
818 event = MP_KEY_WHEEL_NAV;
819 break;
821 case KEYCODE_LEFT:
822 event = MP_KEY_WHEEL_VOL | MP_KEY_WHEEL_VOL_INV;
823 break;
825 case KEYCODE_RIGHT:
826 event = MP_KEY_WHEEL_VOL;
827 break;
829 } else {
830 switch (keycode & KEY_CODE) {
831 case KEYCODE_F:
832 event = MP_KEY_BTN_FAVORITS;
833 break;
835 case KEYCODE_TAB:
836 event = MP_KEY_BTN_VOLUME;
837 break;
839 case KEYCODE_ENTER:
840 event = MP_KEY_BTN_NAVIGATION;
841 break;
843 case KEYCODE_M:
844 event = MP_KEY_BTN_MENU;
845 break;
847 /* Do not repeat already pressed buttons */
848 if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
849 event = 0;
853 if (event) {
854 /* Raise GPIO pin first if repeating a key */
855 if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
856 for (i = 0; i <= 7; i++) {
857 if (event & (1 << i)) {
858 qemu_set_irq(s->out[i], 1);
862 for (i = 0; i <= 7; i++) {
863 if (event & (1 << i)) {
864 qemu_set_irq(s->out[i], !!(keycode & KEY_RELEASED));
867 if (keycode & KEY_RELEASED) {
868 s->pressed_keys &= ~event;
869 } else {
870 s->pressed_keys |= event;
874 s->kbd_extended = 0;
877 static void tt_key_realize(DeviceState *dev, Error **errp)
879 tt_key_state *s = TT_KEY(dev);
880 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
882 sysbus_init_mmio(sbd, &s->mmio);
884 s->kbd_extended = 0;
885 s->pressed_keys = 0;
887 qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
889 qemu_add_kbd_event_handler(tt_key_event, s);
892 static const VMStateDescription tt_key_vmsd = {
893 .name = TYPE_TT_KEY,
894 .version_id = 1,
895 .minimum_version_id = 1,
896 .minimum_version_id_old = 1,
897 .fields = (VMStateField[]) {
898 VMSTATE_UINT32(kbd_extended, tt_key_state),
899 VMSTATE_UINT32(pressed_keys, tt_key_state),
900 VMSTATE_END_OF_LIST()
904 static void tt_key_class_init(ObjectClass *klass, void *data)
906 DeviceClass *dc = DEVICE_CLASS(klass);
907 dc->realize = tt_key_realize;
908 dc->vmsd = &tt_key_vmsd;
911 static const TypeInfo tt_key_info = {
912 .name = TYPE_TT_KEY,
913 .parent = TYPE_SYS_BUS_DEVICE,
914 .instance_size = sizeof(tt_key_state),
915 .class_init = tt_key_class_init,
918 static struct arm_boot_info tt_binfo = {
919 #if 0
920 .loader_start = 0,
921 #else
922 .loader_start = TT_SRAM_BASE,
923 #endif
924 /* GO 730 */
925 .board_id = 0x25d,
926 .atag_revision = 0x0004000a,
929 static void tt_init(MachineState *machine)
931 ARMCPU *cpu;
932 TTState *s;
933 #if 0
934 qemu_irq pic[32];
935 DeviceState *dev;
936 DeviceState *i2c_dev;
937 DeviceState *lcd_dev;
938 DeviceState *key_dev;
939 DeviceState *wm8750_dev;
940 SysBusDevice *s;
941 I2CBus *i2c;
942 unsigned long flash_size;
943 DriveInfo *dinfo;
944 ram_addr_t ram_off;
945 ram_addr_t sram_off;
946 #endif
947 unsigned i;
949 #if 0
950 if (machine->cpu_model && strcmp(machine->cpu_model, "arm920t")) {
951 fprintf(stderr, "only working with cpu arm920t\n");
952 exit(1);
954 #endif
956 /* Allocate storage for board state. */
957 s = g_new0(TTState, 1);
959 for (i = 0; i < serial_max_hds(); i++) {
960 #if 1
961 assert(i < 3);
962 assert(serial_hd(i));
963 #else
964 /* TODO: This code no longer works. Remove or replace. */
965 if (serial_hd(i) == NULL) {
966 char name[32];
967 snprintf(name, sizeof(name), "serial%u", i);
968 serial_hd(i) = qemu_chr_new(name, "vc:80Cx24C");
970 #endif
973 /* Initialise SOC. */
974 s->soc = s3c2440_init(ram_size);
976 cpu = s->soc->cpu;
978 //~ ram_off = qemu_ram_alloc(NULL, "arm920.ram", ram_size);
979 //~ cpu_register_physical_memory(0x00000000, ram_size, ram_off | IO_MEM_RAM);
980 //~ cpu_register_physical_memory(0x30000000, ram_size, ram_off | IO_MEM_RAM);
981 //~ cpu_register_physical_memory(0x80000000, ram_size, ram_off | IO_MEM_RAM);
982 //~ cpu_register_physical_memory(0xc0000000, ram_size, ram_off | IO_MEM_RAM);
984 //~ tt_syscon_init();
985 //~ tt_ioport_init();
987 #if 0
988 dev = sysbus_create_simple(TYPE_TT_GPIO, MP_GPIO_BASE, pic[MP_GPIO_IRQ]);
989 i2c_dev = sysbus_create_simple("gpio_i2c", 0, NULL);
990 i2c = (I2CBus *)qdev_get_child_bus(i2c_dev, "i2c");
992 lcd_dev = sysbus_create_simple(TYPE_TT_LCD, MP_LCD_BASE, NULL);
993 key_dev = sysbus_create_simple(TYPE_TT_KEY, 0, NULL);
995 /* I2C read data */
996 qdev_connect_gpio_out(i2c_dev, 0,
997 qdev_get_gpio_in(dev, MP_GPIO_I2C_DATA_BIT));
998 /* I2C data */
999 qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0));
1000 /* I2C clock */
1001 qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1));
1003 for (i = 0; i < 3; i++) {
1004 qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i));
1006 for (i = 0; i < 4; i++) {
1007 qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 8));
1009 for (i = 4; i < 8; i++) {
1010 qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
1013 wm8750_dev = i2c_create_slave(i2c, "wm8750", MP_WM_ADDR);
1014 dev = qdev_create(NULL, "mv88w8618_audio");
1015 s = SYS_BUS_DEVICE(dev);
1016 qdev_prop_set_ptr(dev, "wm8750", wm8750_dev);
1017 qdev_init_nofail(dev);
1018 sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
1019 sysbus_connect_irq(s, 0, pic[MP_AUDIO_IRQ]);
1020 #endif
1022 tt_binfo.ram_size = ram_size;
1023 tt_binfo.kernel_filename = machine->kernel_filename;
1024 tt_binfo.kernel_cmdline = machine->kernel_cmdline;
1025 tt_binfo.initrd_filename = machine->initrd_filename;
1026 if (machine->kernel_filename != NULL) {
1027 /* TODO: load ttsystem. */
1028 //~ sect_size = 0x11b778, sect_addr = 0x31700000
1029 //~ sect_size = 0x6a3f45, sect_addr = 0x31000000
1030 arm_load_kernel(cpu, &tt_binfo);
1034 static void tt_init_go(MachineState *machine)
1036 tt_binfo.board_id = 0x25d;
1037 ram_size = 64 * MiB;
1038 tt_init(machine);
1041 static void tt_init_666(MachineState *machine)
1043 tt_binfo.board_id = 0x666;
1044 tt_init(machine);
1047 static void tt_init_smdk2443(MachineState *machine)
1049 tt_binfo.board_id = 0x43c;
1050 tt_init(machine);
1053 static void tt_machine_init(MachineClass *mc)
1055 mc->desc = "OpenTom (ARM920-T)";
1056 mc->init = tt_init_go;
1059 DEFINE_MACHINE("tt", tt_machine_init)
1061 static void tt_machine_666_init(MachineClass *mc)
1063 mc->desc = "OpenTom (ARM920-T)";
1064 mc->init = tt_init_666;
1067 DEFINE_MACHINE("tt666", tt_machine_666_init)
1069 static void tt_machine_smdk2443_init(MachineClass *mc)
1071 mc->desc = "smdk2443 (ARM920-T)";
1072 mc->init = tt_init_smdk2443;
1075 DEFINE_MACHINE("smdk2443", tt_machine_smdk2443_init)
1077 static void tt_register_types(void)
1079 type_register_static(&tt_lcd_info);
1080 type_register_static(&tt_gpio_info);
1081 type_register_static(&tt_key_info);
1084 type_init(tt_register_types)