Fix some compiler warnings related to format strings
[qemu/ar7.git] / hw / arm / arm_tt.c
blobd098c398e08e2d3f0ffa29f23c201b19616d1502
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__)
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 #if 0
83 static const char *offset2name(const OffsetNamePair *o2n, unsigned offset)
85 static char buffer[12];
86 const char *name = buffer;
87 snprintf(buffer, sizeof(buffer), "0x%08x", offset);
88 for (; o2n->name; o2n++) {
89 if (offset == o2n->offset) {
90 name = o2n->name;
91 break;
94 return name;
96 #endif
98 #define MP_MISC_BASE 0x80002000
99 #define MP_MISC_SIZE 0x00001000
101 #define MP_GPIO_BASE 0x8000D000
102 #define MP_GPIO_SIZE 0x00001000
104 #define MP_AUDIO_BASE 0x90007000
106 #define MP_LCD_BASE 0x9000c000
107 #define MP_LCD_SIZE 0x00001000
109 #define TT_SRAM_BASE 0xC0000000
110 #define TT_SRAM_SIZE 0x00020000
112 #define MP_RAM_DEFAULT_SIZE (64 * MiB)
114 #define MP_TIMER1_IRQ 4
115 #define MP_TIMER2_IRQ 5
116 #define MP_TIMER3_IRQ 6
117 #define MP_TIMER4_IRQ 7
118 #define MP_EHCI_IRQ 8
119 #define MP_ETH_IRQ 9
120 #define MP_GPIO_IRQ 12
121 #define MP_RTC_IRQ 28
122 #define MP_AUDIO_IRQ 30
124 /* Wolfson 8750 I2C address */
125 #define MP_WM_ADDR 0x1A
127 /* LCD register offsets */
128 #define MP_LCD_IRQCTRL 0x180
129 #define MP_LCD_IRQSTAT 0x184
130 #define MP_LCD_SPICTRL 0x1ac
131 #define MP_LCD_INST 0x1bc
132 #define MP_LCD_DATA 0x1c0
134 /* Mode magics */
135 #define MP_LCD_SPI_DATA 0x00100011
136 #define MP_LCD_SPI_CMD 0x00104011
137 #define MP_LCD_SPI_INVALID 0x00000000
139 /* Commmands */
140 #define MP_LCD_INST_SETPAGE0 0xB0
141 /* ... */
142 #define MP_LCD_INST_SETPAGE7 0xB7
144 #define MP_LCD_TEXTCOLOR 0xe0e0ff /* RRGGBB */
146 #define TYPE_TT_LCD "tt_lcd"
147 #define TT_LCD(obj) OBJECT_CHECK(tt_lcd_state, (obj), TYPE_TT_LCD)
149 typedef struct {
150 SysBusDevice busdev;
151 MemoryRegion mmio;
152 QemuConsole *con;
153 uint32_t brightness;
154 uint32_t mode;
155 uint32_t irqctrl;
156 uint32_t page;
157 uint32_t page_off;
158 uint8_t video_ram[128*64/8];
159 } tt_lcd_state;
161 static uint8_t scale_lcd_color(tt_lcd_state *s, uint8_t col)
163 switch (s->brightness) {
164 case 7:
165 return col;
166 case 0:
167 return 0;
168 default:
169 return (col * s->brightness) / 7;
173 #define SET_LCD_PIXEL(depth, type) \
174 static inline void glue(set_lcd_pixel, depth) \
175 (tt_lcd_state *s, int x, int y, type col) \
177 int dx, dy; \
178 DisplaySurface *surface = qemu_console_surface(s->con); \
179 type *pixel = &((type *) surface_data(surface))[(y * 128 * 3 + x) * 3]; \
181 for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
182 for (dx = 0; dx < 3; dx++, pixel++) \
183 *pixel = col; \
185 SET_LCD_PIXEL(8, uint8_t)
186 SET_LCD_PIXEL(16, uint16_t)
187 SET_LCD_PIXEL(32, uint32_t)
189 #include "ui/pixel_ops.h"
191 static void lcd_refresh(void *opaque)
193 tt_lcd_state *s = opaque;
194 DisplaySurface *surface = qemu_console_surface(s->con);
195 int x, y, col;
197 switch (surface_bits_per_pixel(surface)) {
198 case 0:
199 return;
200 #define LCD_REFRESH(depth, func) \
201 case depth: \
202 col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
203 scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
204 scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
205 for (x = 0; x < 128; x++) { \
206 for (y = 0; y < 64; y++) { \
207 if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
208 glue(set_lcd_pixel, depth)(s, x, y, col); \
209 } else { \
210 glue(set_lcd_pixel, depth)(s, x, y, 0); \
214 break;
215 LCD_REFRESH(8, rgb_to_pixel8)
216 LCD_REFRESH(16, rgb_to_pixel16)
217 LCD_REFRESH(32, (is_surface_bgr(surface) ?
218 rgb_to_pixel32bgr : rgb_to_pixel32))
219 default:
220 hw_error("unsupported colour depth %i\n",
221 surface_bits_per_pixel(surface));
224 dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
227 static void lcd_invalidate(void *opaque)
231 static void tt_lcd_gpio_brigthness_in(void *opaque, int irq, int level)
233 tt_lcd_state *s = opaque;
234 s->brightness &= ~(1 << irq);
235 s->brightness |= level << irq;
238 static uint64_t tt_lcd_read(void *opaque, hwaddr offset,
239 unsigned size)
241 tt_lcd_state *s = opaque;
243 switch (offset) {
244 case MP_LCD_IRQCTRL:
245 return s->irqctrl;
247 default:
248 return 0;
252 static void tt_lcd_write(void *opaque, hwaddr offset,
253 uint64_t value, unsigned size)
255 tt_lcd_state *s = opaque;
257 switch (offset) {
258 case MP_LCD_IRQCTRL:
259 s->irqctrl = value;
260 break;
262 case MP_LCD_SPICTRL:
263 if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD) {
264 s->mode = value;
265 } else {
266 s->mode = MP_LCD_SPI_INVALID;
268 break;
270 case MP_LCD_INST:
271 if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
272 s->page = value - MP_LCD_INST_SETPAGE0;
273 s->page_off = 0;
275 break;
277 case MP_LCD_DATA:
278 if (s->mode == MP_LCD_SPI_CMD) {
279 if (value >= MP_LCD_INST_SETPAGE0 &&
280 value <= MP_LCD_INST_SETPAGE7) {
281 s->page = value - MP_LCD_INST_SETPAGE0;
282 s->page_off = 0;
284 } else if (s->mode == MP_LCD_SPI_DATA) {
285 s->video_ram[s->page*128 + s->page_off] = value;
286 s->page_off = (s->page_off + 1) & 127;
288 break;
292 static const MemoryRegionOps tt_lcd_ops = {
293 .read = tt_lcd_read,
294 .write = tt_lcd_write,
295 .endianness = DEVICE_NATIVE_ENDIAN,
296 .valid = {
297 .min_access_size = 4,
298 .max_access_size = 4
302 static const GraphicHwOps tt_gfx_ops = {
303 .invalidate = lcd_invalidate,
304 .gfx_update = lcd_refresh,
307 static int tt_lcd_init(SysBusDevice *sbd)
309 DeviceState *dev = DEVICE(sbd);
310 tt_lcd_state *s = TT_LCD(dev);
312 s->brightness = 7;
314 memory_region_init_io(&s->mmio, OBJECT(s),
315 &tt_lcd_ops, s, "tt-lcd", MP_LCD_SIZE);
316 sysbus_init_mmio(sbd, &s->mmio);
318 s->con = graphic_console_init(DEVICE(dev), 0, &tt_gfx_ops, s);
319 qemu_console_resize(s->con, 128*3, 64*3);
321 qdev_init_gpio_in(dev, tt_lcd_gpio_brigthness_in, 3);
323 return 0;
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 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
346 dc->desc = "TT LCD",
347 //~ dc->props = dp8381x_properties;
348 //~ dc->reset = qdev_dp8381x_reset;
349 dc->vmsd = &tt_lcd_vmsd;
350 k->init = tt_lcd_init;
353 static const TypeInfo tt_lcd_info = {
354 .name = TYPE_TT_LCD,
355 .parent = TYPE_SYS_BUS_DEVICE,
356 .instance_size = sizeof(tt_lcd_state),
357 .class_init = tt_lcd_class_init,
360 /******************************************************************************/
362 #define S3C2443_MPLLCON 0x10
363 #define S3C2443_CLKDIV0 0x24
365 /******************************************************************************/
367 /* SYSCON register offsets. */
368 #define SYSCON_MPLLCON 0x10
369 #define SYSCON_CLKDIV0 0x24
371 #if 0
372 static const OffsetNamePair tt_syscon_names[] = {
376 static uint64_t tt_syscon_read(void *opaque, hwaddr offset,
377 unsigned size)
379 uint32_t value = 0;
380 logout("%s\n", offset2name(tt_syscon_names, offset));
381 switch (offset) {
382 case SYSCON_MPLLCON:
383 case SYSCON_CLKDIV0:
384 default:
385 TODO();
387 return value;
390 static void tt_syscon_write(void *opaque, hwaddr offset,
391 uint64_t value, unsigned size)
393 logout("%s 0x%08" PRIx64 "\n", offset2name(tt_syscon_names, offset), value);
394 switch (offset) {
395 default:
396 TODO();
400 static const MemoryRegionOps tt_syscon_ops = {
401 .read = tt_syscon_read,
402 .write = tt_syscon_write,
403 .endianness = DEVICE_NATIVE_ENDIAN,
404 .valid = {
405 .min_access_size = 4,
406 .max_access_size = 4
409 #endif
411 /******************************************************************************/
413 /* I/O port register offsets. */
414 #define IOPORT_GPBCON 0x10
415 #define IOPORT_GPBDAT 0x14
416 #define IOPORT_GPBUDP 0x18
417 #define IOPORT_EXTINT0 0x88
418 #define IOPORT_EXTINT1 0x8c
419 #define IOPORT_EXTINT2 0x90
420 #define IOPORT_GSTATUS1 0xb0
423 tt_ioport_write: 0x00000010
424 tt_ioport_write: 0x00000018
425 tt_ioport_write: 0x00000010
426 tt_ioport_write: 0x00000018
429 #if 0
430 static const OffsetNamePair tt_ioport_names[] = {
434 static uint64_t tt_ioport_read(void *opaque, hwaddr offset,
435 unsigned size)
437 uint32_t value = 0;
438 logout("%s\n", offset2name(tt_ioport_names, offset));
439 switch (offset) {
440 case IOPORT_GPBCON:
441 TODO();
442 break;
443 case IOPORT_GPBDAT:
444 TODO();
445 break;
446 case IOPORT_GPBUDP:
447 value = 0x2aaaaa;
448 break;
449 //~ case IOPORT_EXTINT0:
450 //~ case IOPORT_EXTINT1:
451 //~ case IOPORT_EXTINT2:
452 case IOPORT_GSTATUS1:
453 value = 0x32443001;
454 break;
455 default:
456 TODO();
458 return value;
461 static void tt_ioport_write(void *opaque, hwaddr offset,
462 uint64_t value, unsigned size)
464 logout("%s 0x%08" PRIx64 "\n", offset2name(tt_ioport_names, offset), value);
465 switch (offset) {
466 case IOPORT_GPBCON:
467 TODO();
468 break;
469 //~ case IOPORT_GPBDAT:
470 case IOPORT_GPBUDP:
471 TODO();
472 break;
473 case IOPORT_EXTINT0:
474 TODO();
475 break;
476 case IOPORT_EXTINT1:
477 TODO();
478 break;
479 case IOPORT_EXTINT2:
480 TODO();
481 break;
482 //~ case IOPORT_GSTATUS1:
483 default:
484 TODO();
488 static const MemoryRegionOps tt_ioport_ops = {
489 .read = tt_ioport_read,
490 .write = tt_ioport_write,
491 .endianness = DEVICE_NATIVE_ENDIAN,
492 .valid = {
493 .min_access_size = 4,
494 .max_access_size = 4
497 #endif
499 /******************************************************************************/
501 #if 0
502 static void tt_syscon_init(void)
504 memory_region_init_io(&s->syscon, OBJECT(s), &tt_syscon_ops, s,
505 "tt-syscon", 0x10000);
506 memory_region_add_subregion(get_system_memory(), S3C2443X_SYSCON, &s->syscon);
509 static void tt_ioport_init(void)
511 memory_region_init_io(&s->ioport, OBJECT(s), &tt_ioport_ops, s,
512 "tt-ioport", 0x10000);
513 memory_region_add_subregion(get_system_memory(), S3C2443X_IO_PORT, &s->ioport);
515 #endif
517 /* GPIO register offsets */
518 #define MP_GPIO_OE_LO 0x008
519 #define MP_GPIO_OUT_LO 0x00c
520 #define MP_GPIO_IN_LO 0x010
521 #define MP_GPIO_IER_LO 0x014
522 #define MP_GPIO_IMR_LO 0x018
523 #define MP_GPIO_ISR_LO 0x020
524 #define MP_GPIO_OE_HI 0x508
525 #define MP_GPIO_OUT_HI 0x50c
526 #define MP_GPIO_IN_HI 0x510
527 #define MP_GPIO_IER_HI 0x514
528 #define MP_GPIO_IMR_HI 0x518
529 #define MP_GPIO_ISR_HI 0x520
531 /* GPIO bits & masks */
532 #define MP_GPIO_LCD_BRIGHTNESS 0x00070000
533 #define MP_GPIO_I2C_DATA_BIT 29
534 #define MP_GPIO_I2C_CLOCK_BIT 30
536 /* LCD brightness bits in GPIO_OE_HI */
537 #define MP_OE_LCD_BRIGHTNESS 0x0007
539 #define TYPE_TT_GPIO "tt_gpio"
540 #define TT_GPIO(obj) \
541 OBJECT_CHECK(tt_gpio_state, (obj), TYPE_TT_GPIO)
543 typedef struct {
544 SysBusDevice busdev;
545 MemoryRegion mmio;
546 uint32_t lcd_brightness;
547 uint32_t out_state;
548 uint32_t in_state;
549 uint32_t ier;
550 uint32_t imr;
551 uint32_t isr;
552 qemu_irq irq;
553 qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
554 } tt_gpio_state;
556 static void tt_gpio_brightness_update(tt_gpio_state *s) {
557 int i;
558 uint32_t brightness;
560 /* compute brightness ratio */
561 switch (s->lcd_brightness) {
562 case 0x00000007:
563 brightness = 0;
564 break;
566 case 0x00020000:
567 brightness = 1;
568 break;
570 case 0x00020001:
571 brightness = 2;
572 break;
574 case 0x00040000:
575 brightness = 3;
576 break;
578 case 0x00010006:
579 brightness = 4;
580 break;
582 case 0x00020005:
583 brightness = 5;
584 break;
586 case 0x00040003:
587 brightness = 6;
588 break;
590 case 0x00030004:
591 default:
592 brightness = 7;
595 /* set lcd brightness GPIOs */
596 for (i = 0; i <= 2; i++) {
597 qemu_set_irq(s->out[i], (brightness >> i) & 1);
601 static void tt_gpio_pin_event(void *opaque, int pin, int level)
603 tt_gpio_state *s = opaque;
604 uint32_t mask = 1 << pin;
605 uint32_t delta = level << pin;
606 uint32_t old = s->in_state & mask;
608 s->in_state &= ~mask;
609 s->in_state |= delta;
611 if ((old ^ delta) &&
612 ((level && (s->imr & mask)) || (!level && (s->ier & mask)))) {
613 s->isr = mask;
614 qemu_irq_raise(s->irq);
618 static uint64_t tt_gpio_read(void *opaque, hwaddr offset,
619 unsigned size)
621 tt_gpio_state *s = opaque;
623 switch (offset) {
624 case MP_GPIO_OE_HI: /* used for LCD brightness control */
625 return s->lcd_brightness & MP_OE_LCD_BRIGHTNESS;
627 case MP_GPIO_OUT_LO:
628 return s->out_state & 0xFFFF;
629 case MP_GPIO_OUT_HI:
630 return s->out_state >> 16;
632 case MP_GPIO_IN_LO:
633 return s->in_state & 0xFFFF;
634 case MP_GPIO_IN_HI:
635 return s->in_state >> 16;
637 case MP_GPIO_IER_LO:
638 return s->ier & 0xFFFF;
639 case MP_GPIO_IER_HI:
640 return s->ier >> 16;
642 case MP_GPIO_IMR_LO:
643 return s->imr & 0xFFFF;
644 case MP_GPIO_IMR_HI:
645 return s->imr >> 16;
647 case MP_GPIO_ISR_LO:
648 return s->isr & 0xFFFF;
649 case MP_GPIO_ISR_HI:
650 return s->isr >> 16;
652 default:
653 return 0;
657 static void tt_gpio_write(void *opaque, hwaddr offset,
658 uint64_t value, unsigned size)
660 tt_gpio_state *s = opaque;
661 switch (offset) {
662 case MP_GPIO_OE_HI: /* used for LCD brightness control */
663 s->lcd_brightness = (s->lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
664 (value & MP_OE_LCD_BRIGHTNESS);
665 tt_gpio_brightness_update(s);
666 break;
668 case MP_GPIO_OUT_LO:
669 s->out_state = (s->out_state & 0xFFFF0000) | (value & 0xFFFF);
670 break;
671 case MP_GPIO_OUT_HI:
672 s->out_state = (s->out_state & 0xFFFF) | (value << 16);
673 s->lcd_brightness = (s->lcd_brightness & 0xFFFF) |
674 (s->out_state & MP_GPIO_LCD_BRIGHTNESS);
675 tt_gpio_brightness_update(s);
676 qemu_set_irq(s->out[3], (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1);
677 qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
678 break;
680 case MP_GPIO_IER_LO:
681 s->ier = (s->ier & 0xFFFF0000) | (value & 0xFFFF);
682 break;
683 case MP_GPIO_IER_HI:
684 s->ier = (s->ier & 0xFFFF) | (value << 16);
685 break;
687 case MP_GPIO_IMR_LO:
688 s->imr = (s->imr & 0xFFFF0000) | (value & 0xFFFF);
689 break;
690 case MP_GPIO_IMR_HI:
691 s->imr = (s->imr & 0xFFFF) | (value << 16);
692 break;
696 static const MemoryRegionOps tt_gpio_ops = {
697 .read = tt_gpio_read,
698 .write = tt_gpio_write,
699 .endianness = DEVICE_NATIVE_ENDIAN,
700 .valid = {
701 .min_access_size = 4,
702 .max_access_size = 4
706 static void tt_gpio_reset(DeviceState *d)
708 tt_gpio_state *s = TT_GPIO(d);
710 s->lcd_brightness = 0;
711 s->out_state = 0;
712 s->in_state = 0xffffffff;
713 s->ier = 0;
714 s->imr = 0;
715 s->isr = 0;
718 static int tt_gpio_init(SysBusDevice *sbd)
720 DeviceState *dev = DEVICE(sbd);
721 tt_gpio_state *s = TT_GPIO(dev);
723 sysbus_init_irq(sbd, &s->irq);
725 memory_region_init_io(&s->mmio, OBJECT(s), &tt_gpio_ops, s,
726 "tt-gpio", MP_GPIO_SIZE);
727 sysbus_init_mmio(sbd, &s->mmio);
729 qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
731 qdev_init_gpio_in(dev, tt_gpio_pin_event, 32);
733 return 0;
736 static const VMStateDescription tt_gpio_vmsd = {
737 .name = TYPE_TT_GPIO,
738 .version_id = 1,
739 .minimum_version_id = 1,
740 .minimum_version_id_old = 1,
741 .fields = (VMStateField[]) {
742 VMSTATE_UINT32(lcd_brightness, tt_gpio_state),
743 VMSTATE_UINT32(out_state, tt_gpio_state),
744 VMSTATE_UINT32(in_state, tt_gpio_state),
745 VMSTATE_UINT32(ier, tt_gpio_state),
746 VMSTATE_UINT32(imr, tt_gpio_state),
747 VMSTATE_UINT32(isr, tt_gpio_state),
748 VMSTATE_END_OF_LIST()
752 static void tt_gpio_class_init(ObjectClass *klass, void *data)
754 DeviceClass *dc = DEVICE_CLASS(klass);
755 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
756 dc->reset = tt_gpio_reset;
757 dc->vmsd = &tt_gpio_vmsd;
758 k->init = tt_gpio_init;
761 static const TypeInfo tt_gpio_info = {
762 .name = TYPE_TT_GPIO,
763 .parent = TYPE_SYS_BUS_DEVICE,
764 .instance_size = sizeof(tt_gpio_state),
765 .class_init = tt_gpio_class_init,
768 /* Keyboard codes & masks */
769 #define KEY_RELEASED 0x80
770 #define KEY_CODE 0x7f
772 #define KEYCODE_TAB 0x0f
773 #define KEYCODE_ENTER 0x1c
774 #define KEYCODE_F 0x21
775 #define KEYCODE_M 0x32
777 #define KEYCODE_EXTENDED 0xe0
778 #define KEYCODE_UP 0x48
779 #define KEYCODE_DOWN 0x50
780 #define KEYCODE_LEFT 0x4b
781 #define KEYCODE_RIGHT 0x4d
783 #define MP_KEY_WHEEL_VOL (1 << 0)
784 #define MP_KEY_WHEEL_VOL_INV (1 << 1)
785 #define MP_KEY_WHEEL_NAV (1 << 2)
786 #define MP_KEY_WHEEL_NAV_INV (1 << 3)
787 #define MP_KEY_BTN_FAVORITS (1 << 4)
788 #define MP_KEY_BTN_MENU (1 << 5)
789 #define MP_KEY_BTN_VOLUME (1 << 6)
790 #define MP_KEY_BTN_NAVIGATION (1 << 7)
792 #define TYPE_TT_KEY "tt_key"
793 #define TT_KEY(obj) \
794 OBJECT_CHECK(tt_key_state, (obj), TYPE_TT_KEY)
796 typedef struct {
797 SysBusDevice busdev;
798 MemoryRegion mmio;
799 uint32_t kbd_extended;
800 uint32_t pressed_keys;
801 qemu_irq out[8];
802 } tt_key_state;
804 static void tt_key_event(void *opaque, int keycode)
806 tt_key_state *s = opaque;
807 uint32_t event = 0;
808 int i;
810 if (keycode == KEYCODE_EXTENDED) {
811 s->kbd_extended = 1;
812 return;
815 if (s->kbd_extended) {
816 switch (keycode & KEY_CODE) {
817 case KEYCODE_UP:
818 event = MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_NAV_INV;
819 break;
821 case KEYCODE_DOWN:
822 event = MP_KEY_WHEEL_NAV;
823 break;
825 case KEYCODE_LEFT:
826 event = MP_KEY_WHEEL_VOL | MP_KEY_WHEEL_VOL_INV;
827 break;
829 case KEYCODE_RIGHT:
830 event = MP_KEY_WHEEL_VOL;
831 break;
833 } else {
834 switch (keycode & KEY_CODE) {
835 case KEYCODE_F:
836 event = MP_KEY_BTN_FAVORITS;
837 break;
839 case KEYCODE_TAB:
840 event = MP_KEY_BTN_VOLUME;
841 break;
843 case KEYCODE_ENTER:
844 event = MP_KEY_BTN_NAVIGATION;
845 break;
847 case KEYCODE_M:
848 event = MP_KEY_BTN_MENU;
849 break;
851 /* Do not repeat already pressed buttons */
852 if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
853 event = 0;
857 if (event) {
858 /* Raise GPIO pin first if repeating a key */
859 if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
860 for (i = 0; i <= 7; i++) {
861 if (event & (1 << i)) {
862 qemu_set_irq(s->out[i], 1);
866 for (i = 0; i <= 7; i++) {
867 if (event & (1 << i)) {
868 qemu_set_irq(s->out[i], !!(keycode & KEY_RELEASED));
871 if (keycode & KEY_RELEASED) {
872 s->pressed_keys &= ~event;
873 } else {
874 s->pressed_keys |= event;
878 s->kbd_extended = 0;
881 static int tt_key_init(SysBusDevice *sbd)
883 DeviceState *dev = DEVICE(sbd);
884 tt_key_state *s = TT_KEY(dev);
886 sysbus_init_mmio(sbd, &s->mmio);
888 s->kbd_extended = 0;
889 s->pressed_keys = 0;
891 qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
893 qemu_add_kbd_event_handler(tt_key_event, s);
895 return 0;
898 static const VMStateDescription tt_key_vmsd = {
899 .name = TYPE_TT_KEY,
900 .version_id = 1,
901 .minimum_version_id = 1,
902 .minimum_version_id_old = 1,
903 .fields = (VMStateField[]) {
904 VMSTATE_UINT32(kbd_extended, tt_key_state),
905 VMSTATE_UINT32(pressed_keys, tt_key_state),
906 VMSTATE_END_OF_LIST()
910 static void tt_key_class_init(ObjectClass *klass, void *data)
912 DeviceClass *dc = DEVICE_CLASS(klass);
913 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
914 dc->vmsd = &tt_key_vmsd;
915 k->init = tt_key_init;
918 static const TypeInfo tt_key_info = {
919 .name = TYPE_TT_KEY,
920 .parent = TYPE_SYS_BUS_DEVICE,
921 .instance_size = sizeof(tt_key_state),
922 .class_init = tt_key_class_init,
925 static struct arm_boot_info tt_binfo = {
926 #if 0
927 .loader_start = 0,
928 #else
929 .loader_start = TT_SRAM_BASE,
930 #endif
931 /* GO 730 */
932 .board_id = 0x25d,
933 .atag_revision = 0x0004000a,
936 static void tt_init(MachineState *machine)
938 ARMCPU *cpu;
939 TTState *s;
940 #if 0
941 qemu_irq pic[32];
942 DeviceState *dev;
943 DeviceState *i2c_dev;
944 DeviceState *lcd_dev;
945 DeviceState *key_dev;
946 DeviceState *wm8750_dev;
947 SysBusDevice *s;
948 I2CBus *i2c;
949 unsigned long flash_size;
950 DriveInfo *dinfo;
951 ram_addr_t ram_off;
952 ram_addr_t sram_off;
953 #endif
954 unsigned i;
956 if (machine->cpu_model && strcmp(machine->cpu_model, "arm920t")) {
957 fprintf(stderr, "only working with cpu arm920t\n");
958 exit(1);
961 /* Allocate storage for board state. */
962 s = g_new0(TTState, 1);
964 for (i = 0; i < 3; i++) {
965 if (serial_hds[i] == NULL) {
966 char name[32];
967 snprintf(name, sizeof(name), "serial%u", i);
968 serial_hds[i] = qemu_chr_new(name, "vc:80Cx24C");
972 /* Initialise SOC. */
973 s->soc = s3c2440_init(ram_size);
975 cpu = s->soc->cpu;
977 //~ ram_off = qemu_ram_alloc(NULL, "arm920.ram", ram_size);
978 //~ cpu_register_physical_memory(0x00000000, ram_size, ram_off | IO_MEM_RAM);
979 //~ cpu_register_physical_memory(0x30000000, ram_size, ram_off | IO_MEM_RAM);
980 //~ cpu_register_physical_memory(0x80000000, ram_size, ram_off | IO_MEM_RAM);
981 //~ cpu_register_physical_memory(0xc0000000, ram_size, ram_off | IO_MEM_RAM);
983 //~ tt_syscon_init();
984 //~ tt_ioport_init();
986 #if 0
987 dev = sysbus_create_simple(TYPE_TT_GPIO, MP_GPIO_BASE, pic[MP_GPIO_IRQ]);
988 i2c_dev = sysbus_create_simple("gpio_i2c", 0, NULL);
989 i2c = (I2CBus *)qdev_get_child_bus(i2c_dev, "i2c");
991 lcd_dev = sysbus_create_simple(TYPE_TT_LCD, MP_LCD_BASE, NULL);
992 key_dev = sysbus_create_simple(TYPE_TT_KEY, 0, NULL);
994 /* I2C read data */
995 qdev_connect_gpio_out(i2c_dev, 0,
996 qdev_get_gpio_in(dev, MP_GPIO_I2C_DATA_BIT));
997 /* I2C data */
998 qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0));
999 /* I2C clock */
1000 qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1));
1002 for (i = 0; i < 3; i++) {
1003 qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i));
1005 for (i = 0; i < 4; i++) {
1006 qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 8));
1008 for (i = 4; i < 8; i++) {
1009 qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
1012 wm8750_dev = i2c_create_slave(i2c, "wm8750", MP_WM_ADDR);
1013 dev = qdev_create(NULL, "mv88w8618_audio");
1014 s = SYS_BUS_DEVICE(dev);
1015 qdev_prop_set_ptr(dev, "wm8750", wm8750_dev);
1016 qdev_init_nofail(dev);
1017 sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
1018 sysbus_connect_irq(s, 0, pic[MP_AUDIO_IRQ]);
1019 #endif
1021 tt_binfo.ram_size = ram_size;
1022 tt_binfo.kernel_filename = machine->kernel_filename;
1023 tt_binfo.kernel_cmdline = machine->kernel_cmdline;
1024 tt_binfo.initrd_filename = machine->initrd_filename;
1025 if (machine->kernel_filename != NULL) {
1026 /* TODO: load ttsystem. */
1027 //~ sect_size = 0x11b778, sect_addr = 0x31700000
1028 //~ sect_size = 0x6a3f45, sect_addr = 0x31000000
1029 arm_load_kernel(cpu, &tt_binfo);
1033 static void tt_init_go(MachineState *machine)
1035 tt_binfo.board_id = 0x25d;
1036 ram_size = 64 * MiB;
1037 tt_init(machine);
1040 static void tt_init_666(MachineState *machine)
1042 tt_binfo.board_id = 0x666;
1043 tt_init(machine);
1046 static void tt_init_smdk2443(MachineState *machine)
1048 tt_binfo.board_id = 0x43c;
1049 tt_init(machine);
1052 static void tt_machine_init(MachineClass *mc)
1054 mc->desc = "OpenTom (ARM920-T)";
1055 mc->init = tt_init_go;
1058 DEFINE_MACHINE("tt", tt_machine_init)
1060 static void tt_machine_666_init(MachineClass *mc)
1062 mc->desc = "OpenTom (ARM920-T)";
1063 mc->init = tt_init_666;
1066 DEFINE_MACHINE("tt666", tt_machine_666_init)
1068 static void tt_machine_smdk2443_init(MachineClass *mc)
1070 mc->desc = "smdk2443 (ARM920-T)";
1071 mc->init = tt_init_smdk2443;
1074 DEFINE_MACHINE("smdk2443", tt_machine_smdk2443_init)
1076 static void tt_register_types(void)
1078 type_register_static(&tt_lcd_info);
1079 type_register_static(&tt_gpio_info);
1080 type_register_static(&tt_key_info);
1083 type_init(tt_register_types)