Merge remote-tracking branch 'qemu/master'
[qemu/ar7.git] / hw / arm / arm_tt.c
blob5013f08afb9426e308f0fe69346fb6ced7d86620
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 "sysemu/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__)
40 Base Address of Special Registers
41 Address Module
42 0x51000000 PWM
43 0x5B000000 AC97
44 0x50000000 UART
45 0x5A000000 SDI
46 0x4F800000 TIC
47 0x4F000000 SSMC
48 0x59000000 SPI
49 0x4E800000 MATRIX
50 0x58000000 TSADC
51 0x4E000000 NFCON
52 0x4D800000 CAM I/F
53 0x4D000000 STN-LCD
54 0x57000000 RTC
55 0x4C800000 TFT-LCD
56 0x4B800000 CF Card
57 0x4B000000 DMA
58 0x55000000 IIS
59 0x4A800000 HS-MMC
60 0x54000000 IIC
61 0x4A000000 INTC
62 0x49800000 USB Device
63 0x53000000 WDT
64 0x49000000 USB HOST
65 0x48800000 EBI
66 0x48000000 Module SDRAM
67 0x52000000 HS-SPI
70 #define S3C2443X_SYSCON 0x4c000000
71 #define S3C2443X_IO_PORT 0x56000000
73 typedef struct {
74 S3CState *soc;
75 } TTState;
77 typedef struct {
78 unsigned offset;
79 const char *name;
80 } OffsetNamePair;
82 static const char *offset2name(const OffsetNamePair *o2n, unsigned offset)
84 static char buffer[12];
85 const char *name = buffer;
86 snprintf(buffer, sizeof(buffer), "0x%08x", offset);
87 for (; o2n->name; o2n++) {
88 if (offset == o2n->offset) {
89 name = o2n->name;
90 break;
93 return name;
96 #define MP_MISC_BASE 0x80002000
97 #define MP_MISC_SIZE 0x00001000
99 #define MP_GPIO_BASE 0x8000D000
100 #define MP_GPIO_SIZE 0x00001000
102 #define MP_AUDIO_BASE 0x90007000
104 #define MP_LCD_BASE 0x9000c000
105 #define MP_LCD_SIZE 0x00001000
107 #define TT_SRAM_BASE 0xC0000000
108 #define TT_SRAM_SIZE 0x00020000
110 #define MP_RAM_DEFAULT_SIZE (64 * MiB)
112 #define MP_TIMER1_IRQ 4
113 #define MP_TIMER2_IRQ 5
114 #define MP_TIMER3_IRQ 6
115 #define MP_TIMER4_IRQ 7
116 #define MP_EHCI_IRQ 8
117 #define MP_ETH_IRQ 9
118 #define MP_GPIO_IRQ 12
119 #define MP_RTC_IRQ 28
120 #define MP_AUDIO_IRQ 30
122 /* Wolfson 8750 I2C address */
123 #define MP_WM_ADDR 0x1A
125 /* LCD register offsets */
126 #define MP_LCD_IRQCTRL 0x180
127 #define MP_LCD_IRQSTAT 0x184
128 #define MP_LCD_SPICTRL 0x1ac
129 #define MP_LCD_INST 0x1bc
130 #define MP_LCD_DATA 0x1c0
132 /* Mode magics */
133 #define MP_LCD_SPI_DATA 0x00100011
134 #define MP_LCD_SPI_CMD 0x00104011
135 #define MP_LCD_SPI_INVALID 0x00000000
137 /* Commmands */
138 #define MP_LCD_INST_SETPAGE0 0xB0
139 /* ... */
140 #define MP_LCD_INST_SETPAGE7 0xB7
142 #define MP_LCD_TEXTCOLOR 0xe0e0ff /* RRGGBB */
144 #define TYPE_TT_LCD "tt_lcd"
145 #define TT_LCD(obj) OBJECT_CHECK(tt_lcd_state, (obj), TYPE_TT_LCD)
147 typedef struct {
148 SysBusDevice busdev;
149 MemoryRegion mmio;
150 QemuConsole *con;
151 uint32_t brightness;
152 uint32_t mode;
153 uint32_t irqctrl;
154 uint32_t page;
155 uint32_t page_off;
156 uint8_t video_ram[128*64/8];
157 } tt_lcd_state;
159 static uint8_t scale_lcd_color(tt_lcd_state *s, uint8_t col)
161 switch (s->brightness) {
162 case 7:
163 return col;
164 case 0:
165 return 0;
166 default:
167 return (col * s->brightness) / 7;
171 #define SET_LCD_PIXEL(depth, type) \
172 static inline void glue(set_lcd_pixel, depth) \
173 (tt_lcd_state *s, int x, int y, type col) \
175 int dx, dy; \
176 DisplaySurface *surface = qemu_console_surface(s->con); \
177 type *pixel = &((type *) surface_data(surface))[(y * 128 * 3 + x) * 3]; \
179 for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
180 for (dx = 0; dx < 3; dx++, pixel++) \
181 *pixel = col; \
183 SET_LCD_PIXEL(8, uint8_t)
184 SET_LCD_PIXEL(16, uint16_t)
185 SET_LCD_PIXEL(32, uint32_t)
187 #include "ui/pixel_ops.h"
189 static void lcd_refresh(void *opaque)
191 tt_lcd_state *s = opaque;
192 DisplaySurface *surface = qemu_console_surface(s->con);
193 int x, y, col;
195 switch (surface_bits_per_pixel(surface)) {
196 case 0:
197 return;
198 #define LCD_REFRESH(depth, func) \
199 case depth: \
200 col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
201 scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
202 scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
203 for (x = 0; x < 128; x++) { \
204 for (y = 0; y < 64; y++) { \
205 if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
206 glue(set_lcd_pixel, depth)(s, x, y, col); \
207 } else { \
208 glue(set_lcd_pixel, depth)(s, x, y, 0); \
212 break;
213 LCD_REFRESH(8, rgb_to_pixel8)
214 LCD_REFRESH(16, rgb_to_pixel16)
215 LCD_REFRESH(32, (is_surface_bgr(surface) ?
216 rgb_to_pixel32bgr : rgb_to_pixel32))
217 default:
218 hw_error("unsupported colour depth %i\n",
219 surface_bits_per_pixel(surface));
222 dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
225 static void lcd_invalidate(void *opaque)
229 static void tt_lcd_gpio_brigthness_in(void *opaque, int irq, int level)
231 tt_lcd_state *s = opaque;
232 s->brightness &= ~(1 << irq);
233 s->brightness |= level << irq;
236 static uint64_t tt_lcd_read(void *opaque, hwaddr offset,
237 unsigned size)
239 tt_lcd_state *s = opaque;
241 switch (offset) {
242 case MP_LCD_IRQCTRL:
243 return s->irqctrl;
245 default:
246 return 0;
250 static void tt_lcd_write(void *opaque, hwaddr offset,
251 uint64_t value, unsigned size)
253 tt_lcd_state *s = opaque;
255 switch (offset) {
256 case MP_LCD_IRQCTRL:
257 s->irqctrl = value;
258 break;
260 case MP_LCD_SPICTRL:
261 if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD) {
262 s->mode = value;
263 } else {
264 s->mode = MP_LCD_SPI_INVALID;
266 break;
268 case MP_LCD_INST:
269 if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
270 s->page = value - MP_LCD_INST_SETPAGE0;
271 s->page_off = 0;
273 break;
275 case MP_LCD_DATA:
276 if (s->mode == MP_LCD_SPI_CMD) {
277 if (value >= MP_LCD_INST_SETPAGE0 &&
278 value <= MP_LCD_INST_SETPAGE7) {
279 s->page = value - MP_LCD_INST_SETPAGE0;
280 s->page_off = 0;
282 } else if (s->mode == MP_LCD_SPI_DATA) {
283 s->video_ram[s->page*128 + s->page_off] = value;
284 s->page_off = (s->page_off + 1) & 127;
286 break;
290 static const MemoryRegionOps tt_lcd_ops = {
291 .read = tt_lcd_read,
292 .write = tt_lcd_write,
293 .endianness = DEVICE_NATIVE_ENDIAN,
294 .valid = {
295 .min_access_size = 4,
296 .max_access_size = 4
300 static const GraphicHwOps tt_gfx_ops = {
301 .invalidate = lcd_invalidate,
302 .gfx_update = lcd_refresh,
305 static int tt_lcd_init(SysBusDevice *sbd)
307 DeviceState *dev = DEVICE(sbd);
308 tt_lcd_state *s = TT_LCD(dev);
310 s->brightness = 7;
312 memory_region_init_io(&s->mmio, OBJECT(s),
313 &tt_lcd_ops, s, "tt-lcd", MP_LCD_SIZE);
314 sysbus_init_mmio(sbd, &s->mmio);
316 s->con = graphic_console_init(DEVICE(dev), 0, &tt_gfx_ops, s);
317 qemu_console_resize(s->con, 128*3, 64*3);
319 qdev_init_gpio_in(dev, tt_lcd_gpio_brigthness_in, 3);
321 return 0;
324 static const VMStateDescription tt_lcd_vmsd = {
325 .name = TYPE_TT_LCD,
326 .version_id = 1,
327 .minimum_version_id = 1,
328 .minimum_version_id_old = 1,
329 .fields = (VMStateField[]) {
330 VMSTATE_UINT32(brightness, tt_lcd_state),
331 VMSTATE_UINT32(mode, tt_lcd_state),
332 VMSTATE_UINT32(irqctrl, tt_lcd_state),
333 VMSTATE_UINT32(page, tt_lcd_state),
334 VMSTATE_UINT32(page_off, tt_lcd_state),
335 VMSTATE_BUFFER(video_ram, tt_lcd_state),
336 VMSTATE_END_OF_LIST()
340 static void tt_lcd_class_init(ObjectClass *klass, void *data)
342 DeviceClass *dc = DEVICE_CLASS(klass);
343 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
344 dc->desc = "TT LCD",
345 //~ dc->props = dp8381x_properties;
346 //~ dc->reset = qdev_dp8381x_reset;
347 dc->vmsd = &tt_lcd_vmsd;
348 k->init = tt_lcd_init;
351 static const TypeInfo tt_lcd_info = {
352 .name = TYPE_TT_LCD,
353 .parent = TYPE_SYS_BUS_DEVICE,
354 .instance_size = sizeof(tt_lcd_state),
355 .class_init = tt_lcd_class_init,
358 /******************************************************************************/
360 #define S3C2443_MPLLCON 0x10
361 #define S3C2443_CLKDIV0 0x24
363 /******************************************************************************/
365 /* SYSCON register offsets. */
366 #define SYSCON_MPLLCON 0x10
367 #define SYSCON_CLKDIV0 0x24
369 static const OffsetNamePair tt_syscon_names[] = {
373 static uint64_t tt_syscon_read(void *opaque, hwaddr offset,
374 unsigned size)
376 uint32_t value = 0;
377 logout("%s\n", offset2name(tt_syscon_names, offset));
378 switch (offset) {
379 case SYSCON_MPLLCON:
380 case SYSCON_CLKDIV0:
381 default:
382 TODO();
384 return value;
387 static void tt_syscon_write(void *opaque, hwaddr offset,
388 uint64_t value, unsigned size)
390 logout("%s 0x%08" PRIx64 "\n", offset2name(tt_syscon_names, offset), value);
391 switch (offset) {
392 default:
393 TODO();
397 static const MemoryRegionOps tt_syscon_ops = {
398 .read = tt_syscon_read,
399 .write = tt_syscon_write,
400 .endianness = DEVICE_NATIVE_ENDIAN,
401 .valid = {
402 .min_access_size = 4,
403 .max_access_size = 4
407 /******************************************************************************/
409 /* I/O port register offsets. */
410 #define IOPORT_GPBCON 0x10
411 #define IOPORT_GPBDAT 0x14
412 #define IOPORT_GPBUDP 0x18
413 #define IOPORT_EXTINT0 0x88
414 #define IOPORT_EXTINT1 0x8c
415 #define IOPORT_EXTINT2 0x90
416 #define IOPORT_GSTATUS1 0xb0
419 tt_ioport_write: 0x00000010
420 tt_ioport_write: 0x00000018
421 tt_ioport_write: 0x00000010
422 tt_ioport_write: 0x00000018
425 static const OffsetNamePair tt_ioport_names[] = {
429 static uint64_t tt_ioport_read(void *opaque, hwaddr offset,
430 unsigned size)
432 uint32_t value = 0;
433 logout("%s\n", offset2name(tt_ioport_names, offset));
434 switch (offset) {
435 case IOPORT_GPBCON:
436 TODO();
437 break;
438 case IOPORT_GPBDAT:
439 TODO();
440 break;
441 case IOPORT_GPBUDP:
442 value = 0x2aaaaa;
443 break;
444 //~ case IOPORT_EXTINT0:
445 //~ case IOPORT_EXTINT1:
446 //~ case IOPORT_EXTINT2:
447 case IOPORT_GSTATUS1:
448 value = 0x32443001;
449 break;
450 default:
451 TODO();
453 return value;
456 static void tt_ioport_write(void *opaque, hwaddr offset,
457 uint64_t value, unsigned size)
459 logout("%s 0x%08" PRIx64 "\n", offset2name(tt_ioport_names, offset), value);
460 switch (offset) {
461 case IOPORT_GPBCON:
462 TODO();
463 break;
464 //~ case IOPORT_GPBDAT:
465 case IOPORT_GPBUDP:
466 TODO();
467 break;
468 case IOPORT_EXTINT0:
469 TODO();
470 break;
471 case IOPORT_EXTINT1:
472 TODO();
473 break;
474 case IOPORT_EXTINT2:
475 TODO();
476 break;
477 //~ case IOPORT_GSTATUS1:
478 default:
479 TODO();
483 static const MemoryRegionOps tt_ioport_ops = {
484 .read = tt_ioport_read,
485 .write = tt_ioport_write,
486 .endianness = DEVICE_NATIVE_ENDIAN,
487 .valid = {
488 .min_access_size = 4,
489 .max_access_size = 4
493 /******************************************************************************/
495 #if 0
496 static void tt_syscon_init(void)
498 memory_region_init_io(&s->syscon, OBJECT(s), &tt_syscon_ops, s,
499 "tt-syscon", 0x10000);
500 memory_region_add_subregion(get_system_memory(), S3C2443X_SYSCON, &s->syscon);
503 static void tt_ioport_init(void)
505 memory_region_init_io(&s->ioport, OBJECT(s), &tt_ioport_ops, s,
506 "tt-ioport", 0x10000);
507 memory_region_add_subregion(get_system_memory(), S3C2443X_IO_PORT, &s->ioport);
509 #endif
511 /* GPIO register offsets */
512 #define MP_GPIO_OE_LO 0x008
513 #define MP_GPIO_OUT_LO 0x00c
514 #define MP_GPIO_IN_LO 0x010
515 #define MP_GPIO_IER_LO 0x014
516 #define MP_GPIO_IMR_LO 0x018
517 #define MP_GPIO_ISR_LO 0x020
518 #define MP_GPIO_OE_HI 0x508
519 #define MP_GPIO_OUT_HI 0x50c
520 #define MP_GPIO_IN_HI 0x510
521 #define MP_GPIO_IER_HI 0x514
522 #define MP_GPIO_IMR_HI 0x518
523 #define MP_GPIO_ISR_HI 0x520
525 /* GPIO bits & masks */
526 #define MP_GPIO_LCD_BRIGHTNESS 0x00070000
527 #define MP_GPIO_I2C_DATA_BIT 29
528 #define MP_GPIO_I2C_CLOCK_BIT 30
530 /* LCD brightness bits in GPIO_OE_HI */
531 #define MP_OE_LCD_BRIGHTNESS 0x0007
533 #define TYPE_TT_GPIO "tt_gpio"
534 #define TT_GPIO(obj) \
535 OBJECT_CHECK(tt_gpio_state, (obj), TYPE_TT_GPIO)
537 typedef struct {
538 SysBusDevice busdev;
539 MemoryRegion mmio;
540 uint32_t lcd_brightness;
541 uint32_t out_state;
542 uint32_t in_state;
543 uint32_t ier;
544 uint32_t imr;
545 uint32_t isr;
546 qemu_irq irq;
547 qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
548 } tt_gpio_state;
550 static void tt_gpio_brightness_update(tt_gpio_state *s) {
551 int i;
552 uint32_t brightness;
554 /* compute brightness ratio */
555 switch (s->lcd_brightness) {
556 case 0x00000007:
557 brightness = 0;
558 break;
560 case 0x00020000:
561 brightness = 1;
562 break;
564 case 0x00020001:
565 brightness = 2;
566 break;
568 case 0x00040000:
569 brightness = 3;
570 break;
572 case 0x00010006:
573 brightness = 4;
574 break;
576 case 0x00020005:
577 brightness = 5;
578 break;
580 case 0x00040003:
581 brightness = 6;
582 break;
584 case 0x00030004:
585 default:
586 brightness = 7;
589 /* set lcd brightness GPIOs */
590 for (i = 0; i <= 2; i++) {
591 qemu_set_irq(s->out[i], (brightness >> i) & 1);
595 static void tt_gpio_pin_event(void *opaque, int pin, int level)
597 tt_gpio_state *s = opaque;
598 uint32_t mask = 1 << pin;
599 uint32_t delta = level << pin;
600 uint32_t old = s->in_state & mask;
602 s->in_state &= ~mask;
603 s->in_state |= delta;
605 if ((old ^ delta) &&
606 ((level && (s->imr & mask)) || (!level && (s->ier & mask)))) {
607 s->isr = mask;
608 qemu_irq_raise(s->irq);
612 static uint64_t tt_gpio_read(void *opaque, hwaddr offset,
613 unsigned size)
615 tt_gpio_state *s = opaque;
617 switch (offset) {
618 case MP_GPIO_OE_HI: /* used for LCD brightness control */
619 return s->lcd_brightness & MP_OE_LCD_BRIGHTNESS;
621 case MP_GPIO_OUT_LO:
622 return s->out_state & 0xFFFF;
623 case MP_GPIO_OUT_HI:
624 return s->out_state >> 16;
626 case MP_GPIO_IN_LO:
627 return s->in_state & 0xFFFF;
628 case MP_GPIO_IN_HI:
629 return s->in_state >> 16;
631 case MP_GPIO_IER_LO:
632 return s->ier & 0xFFFF;
633 case MP_GPIO_IER_HI:
634 return s->ier >> 16;
636 case MP_GPIO_IMR_LO:
637 return s->imr & 0xFFFF;
638 case MP_GPIO_IMR_HI:
639 return s->imr >> 16;
641 case MP_GPIO_ISR_LO:
642 return s->isr & 0xFFFF;
643 case MP_GPIO_ISR_HI:
644 return s->isr >> 16;
646 default:
647 return 0;
651 static void tt_gpio_write(void *opaque, hwaddr offset,
652 uint64_t value, unsigned size)
654 tt_gpio_state *s = opaque;
655 switch (offset) {
656 case MP_GPIO_OE_HI: /* used for LCD brightness control */
657 s->lcd_brightness = (s->lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
658 (value & MP_OE_LCD_BRIGHTNESS);
659 tt_gpio_brightness_update(s);
660 break;
662 case MP_GPIO_OUT_LO:
663 s->out_state = (s->out_state & 0xFFFF0000) | (value & 0xFFFF);
664 break;
665 case MP_GPIO_OUT_HI:
666 s->out_state = (s->out_state & 0xFFFF) | (value << 16);
667 s->lcd_brightness = (s->lcd_brightness & 0xFFFF) |
668 (s->out_state & MP_GPIO_LCD_BRIGHTNESS);
669 tt_gpio_brightness_update(s);
670 qemu_set_irq(s->out[3], (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1);
671 qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
672 break;
674 case MP_GPIO_IER_LO:
675 s->ier = (s->ier & 0xFFFF0000) | (value & 0xFFFF);
676 break;
677 case MP_GPIO_IER_HI:
678 s->ier = (s->ier & 0xFFFF) | (value << 16);
679 break;
681 case MP_GPIO_IMR_LO:
682 s->imr = (s->imr & 0xFFFF0000) | (value & 0xFFFF);
683 break;
684 case MP_GPIO_IMR_HI:
685 s->imr = (s->imr & 0xFFFF) | (value << 16);
686 break;
690 static const MemoryRegionOps tt_gpio_ops = {
691 .read = tt_gpio_read,
692 .write = tt_gpio_write,
693 .endianness = DEVICE_NATIVE_ENDIAN,
694 .valid = {
695 .min_access_size = 4,
696 .max_access_size = 4
700 static void tt_gpio_reset(DeviceState *d)
702 tt_gpio_state *s = TT_GPIO(d);
704 s->lcd_brightness = 0;
705 s->out_state = 0;
706 s->in_state = 0xffffffff;
707 s->ier = 0;
708 s->imr = 0;
709 s->isr = 0;
712 static int tt_gpio_init(SysBusDevice *sbd)
714 DeviceState *dev = DEVICE(sbd);
715 tt_gpio_state *s = TT_GPIO(dev);
717 sysbus_init_irq(sbd, &s->irq);
719 memory_region_init_io(&s->mmio, OBJECT(s), &tt_gpio_ops, s,
720 "tt-gpio", MP_GPIO_SIZE);
721 sysbus_init_mmio(sbd, &s->mmio);
723 qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
725 qdev_init_gpio_in(dev, tt_gpio_pin_event, 32);
727 return 0;
730 static const VMStateDescription tt_gpio_vmsd = {
731 .name = TYPE_TT_GPIO,
732 .version_id = 1,
733 .minimum_version_id = 1,
734 .minimum_version_id_old = 1,
735 .fields = (VMStateField[]) {
736 VMSTATE_UINT32(lcd_brightness, tt_gpio_state),
737 VMSTATE_UINT32(out_state, tt_gpio_state),
738 VMSTATE_UINT32(in_state, tt_gpio_state),
739 VMSTATE_UINT32(ier, tt_gpio_state),
740 VMSTATE_UINT32(imr, tt_gpio_state),
741 VMSTATE_UINT32(isr, tt_gpio_state),
742 VMSTATE_END_OF_LIST()
746 static void tt_gpio_class_init(ObjectClass *klass, void *data)
748 DeviceClass *dc = DEVICE_CLASS(klass);
749 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
750 dc->reset = tt_gpio_reset;
751 dc->vmsd = &tt_gpio_vmsd;
752 k->init = tt_gpio_init;
755 static const TypeInfo tt_gpio_info = {
756 .name = TYPE_TT_GPIO,
757 .parent = TYPE_SYS_BUS_DEVICE,
758 .instance_size = sizeof(tt_gpio_state),
759 .class_init = tt_gpio_class_init,
762 /* Keyboard codes & masks */
763 #define KEY_RELEASED 0x80
764 #define KEY_CODE 0x7f
766 #define KEYCODE_TAB 0x0f
767 #define KEYCODE_ENTER 0x1c
768 #define KEYCODE_F 0x21
769 #define KEYCODE_M 0x32
771 #define KEYCODE_EXTENDED 0xe0
772 #define KEYCODE_UP 0x48
773 #define KEYCODE_DOWN 0x50
774 #define KEYCODE_LEFT 0x4b
775 #define KEYCODE_RIGHT 0x4d
777 #define MP_KEY_WHEEL_VOL (1 << 0)
778 #define MP_KEY_WHEEL_VOL_INV (1 << 1)
779 #define MP_KEY_WHEEL_NAV (1 << 2)
780 #define MP_KEY_WHEEL_NAV_INV (1 << 3)
781 #define MP_KEY_BTN_FAVORITS (1 << 4)
782 #define MP_KEY_BTN_MENU (1 << 5)
783 #define MP_KEY_BTN_VOLUME (1 << 6)
784 #define MP_KEY_BTN_NAVIGATION (1 << 7)
786 #define TYPE_TT_KEY "tt_key"
787 #define TT_KEY(obj) \
788 OBJECT_CHECK(tt_key_state, (obj), TYPE_TT_KEY)
790 typedef struct {
791 SysBusDevice busdev;
792 MemoryRegion mmio;
793 uint32_t kbd_extended;
794 uint32_t pressed_keys;
795 qemu_irq out[8];
796 } tt_key_state;
798 static void tt_key_event(void *opaque, int keycode)
800 tt_key_state *s = opaque;
801 uint32_t event = 0;
802 int i;
804 if (keycode == KEYCODE_EXTENDED) {
805 s->kbd_extended = 1;
806 return;
809 if (s->kbd_extended) {
810 switch (keycode & KEY_CODE) {
811 case KEYCODE_UP:
812 event = MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_NAV_INV;
813 break;
815 case KEYCODE_DOWN:
816 event = MP_KEY_WHEEL_NAV;
817 break;
819 case KEYCODE_LEFT:
820 event = MP_KEY_WHEEL_VOL | MP_KEY_WHEEL_VOL_INV;
821 break;
823 case KEYCODE_RIGHT:
824 event = MP_KEY_WHEEL_VOL;
825 break;
827 } else {
828 switch (keycode & KEY_CODE) {
829 case KEYCODE_F:
830 event = MP_KEY_BTN_FAVORITS;
831 break;
833 case KEYCODE_TAB:
834 event = MP_KEY_BTN_VOLUME;
835 break;
837 case KEYCODE_ENTER:
838 event = MP_KEY_BTN_NAVIGATION;
839 break;
841 case KEYCODE_M:
842 event = MP_KEY_BTN_MENU;
843 break;
845 /* Do not repeat already pressed buttons */
846 if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
847 event = 0;
851 if (event) {
852 /* Raise GPIO pin first if repeating a key */
853 if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
854 for (i = 0; i <= 7; i++) {
855 if (event & (1 << i)) {
856 qemu_set_irq(s->out[i], 1);
860 for (i = 0; i <= 7; i++) {
861 if (event & (1 << i)) {
862 qemu_set_irq(s->out[i], !!(keycode & KEY_RELEASED));
865 if (keycode & KEY_RELEASED) {
866 s->pressed_keys &= ~event;
867 } else {
868 s->pressed_keys |= event;
872 s->kbd_extended = 0;
875 static int tt_key_init(SysBusDevice *sbd)
877 DeviceState *dev = DEVICE(sbd);
878 tt_key_state *s = TT_KEY(dev);
880 sysbus_init_mmio(sbd, &s->mmio);
882 s->kbd_extended = 0;
883 s->pressed_keys = 0;
885 qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
887 qemu_add_kbd_event_handler(tt_key_event, s);
889 return 0;
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 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
908 dc->vmsd = &tt_key_vmsd;
909 k->init = tt_key_init;
912 static const TypeInfo tt_key_info = {
913 .name = TYPE_TT_KEY,
914 .parent = TYPE_SYS_BUS_DEVICE,
915 .instance_size = sizeof(tt_key_state),
916 .class_init = tt_key_class_init,
919 static struct arm_boot_info tt_binfo = {
920 #if 0
921 .loader_start = 0,
922 #else
923 .loader_start = TT_SRAM_BASE,
924 #endif
925 /* GO 730 */
926 .board_id = 0x25d,
927 .atag_revision = 0x0004000a,
930 static void tt_init(MachineState *machine)
932 ARMCPU *cpu;
933 TTState *s;
934 #if 0
935 qemu_irq pic[32];
936 DeviceState *dev;
937 DeviceState *i2c_dev;
938 DeviceState *lcd_dev;
939 DeviceState *key_dev;
940 DeviceState *wm8750_dev;
941 SysBusDevice *s;
942 I2CBus *i2c;
943 unsigned long flash_size;
944 DriveInfo *dinfo;
945 ram_addr_t ram_off;
946 ram_addr_t sram_off;
947 #endif
948 unsigned i;
950 if (machine->cpu_model && strcmp(machine->cpu_model, "arm920t")) {
951 fprintf(stderr, "only working with cpu arm920t\n");
952 exit(1);
955 /* Allocate storage for board state. */
956 s = g_new0(TTState, 1);
958 for (i = 0; i < 3; i++) {
959 if (serial_hds[i] == NULL) {
960 char name[32];
961 snprintf(name, sizeof(name), "serial%u", i);
962 serial_hds[i] = qemu_chr_new(name, "vc:80Cx24C", NULL);
966 /* Initialise SOC. */
967 s->soc = s3c2440_init(ram_size);
969 cpu = s->soc->cpu;
971 //~ ram_off = qemu_ram_alloc(NULL, "arm920.ram", ram_size);
972 //~ cpu_register_physical_memory(0x00000000, ram_size, ram_off | IO_MEM_RAM);
973 //~ cpu_register_physical_memory(0x30000000, ram_size, ram_off | IO_MEM_RAM);
974 //~ cpu_register_physical_memory(0x80000000, ram_size, ram_off | IO_MEM_RAM);
975 //~ cpu_register_physical_memory(0xc0000000, ram_size, ram_off | IO_MEM_RAM);
977 //~ tt_syscon_init();
978 //~ tt_ioport_init();
980 #if 0
981 dev = sysbus_create_simple(TYPE_TT_GPIO, MP_GPIO_BASE, pic[MP_GPIO_IRQ]);
982 i2c_dev = sysbus_create_simple("gpio_i2c", 0, NULL);
983 i2c = (I2CBus *)qdev_get_child_bus(i2c_dev, "i2c");
985 lcd_dev = sysbus_create_simple(TYPE_TT_LCD, MP_LCD_BASE, NULL);
986 key_dev = sysbus_create_simple(TYPE_TT_KEY, 0, NULL);
988 /* I2C read data */
989 qdev_connect_gpio_out(i2c_dev, 0,
990 qdev_get_gpio_in(dev, MP_GPIO_I2C_DATA_BIT));
991 /* I2C data */
992 qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0));
993 /* I2C clock */
994 qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1));
996 for (i = 0; i < 3; i++) {
997 qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i));
999 for (i = 0; i < 4; i++) {
1000 qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 8));
1002 for (i = 4; i < 8; i++) {
1003 qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
1006 wm8750_dev = i2c_create_slave(i2c, "wm8750", MP_WM_ADDR);
1007 dev = qdev_create(NULL, "mv88w8618_audio");
1008 s = SYS_BUS_DEVICE(dev);
1009 qdev_prop_set_ptr(dev, "wm8750", wm8750_dev);
1010 qdev_init_nofail(dev);
1011 sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
1012 sysbus_connect_irq(s, 0, pic[MP_AUDIO_IRQ]);
1013 #endif
1015 tt_binfo.ram_size = ram_size;
1016 tt_binfo.kernel_filename = machine->kernel_filename;
1017 tt_binfo.kernel_cmdline = machine->kernel_cmdline;
1018 tt_binfo.initrd_filename = machine->initrd_filename;
1019 if (machine->kernel_filename != NULL) {
1020 /* TODO: load ttsystem. */
1021 //~ sect_size = 0x11b778, sect_addr = 0x31700000
1022 //~ sect_size = 0x6a3f45, sect_addr = 0x31000000
1023 arm_load_kernel(cpu, &tt_binfo);
1027 static void tt_init_go(MachineState *machine)
1029 tt_binfo.board_id = 0x25d;
1030 ram_size = 64 * MiB;
1031 tt_init(machine);
1034 static void tt_init_666(MachineState *machine)
1036 tt_binfo.board_id = 0x666;
1037 tt_init(machine);
1040 static void tt_init_smdk2443(MachineState *machine)
1042 tt_binfo.board_id = 0x43c;
1043 tt_init(machine);
1046 static void tt_machine_init(MachineClass *mc)
1048 mc->desc = "OpenTom (ARM920-T)";
1049 mc->init = tt_init_go;
1052 DEFINE_MACHINE("tt", tt_machine_init)
1054 static void tt_machine_666_init(MachineClass *mc)
1056 mc->desc = "OpenTom (ARM920-T)";
1057 mc->init = tt_init_666;
1060 DEFINE_MACHINE("tt666", tt_machine_666_init)
1062 static void tt_machine_smdk2443_init(MachineClass *mc)
1064 mc->desc = "smdk2443 (ARM920-T)";
1065 mc->init = tt_init_smdk2443;
1068 DEFINE_MACHINE("smdk2443", tt_machine_smdk2443_init)
1070 static void tt_register_types(void)
1072 type_register_static(&tt_lcd_info);
1073 type_register_static(&tt_gpio_info);
1074 type_register_static(&tt_key_info);
1077 type_init(tt_register_types)