Merge tag 'v9.0.0-rc3'
[qemu/ar7.git] / hw / arm / arm_tt.c
blob6cd86c2a4746c0c5a84071045e137a410b1c56dc
1 /*
2 * TomTom GO 730 with Samsung S3C2443X emulation.
4 * Copyright (c) 2010, 2013, 2019 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/boot.h"
19 #include "hw/boards.h"
20 #include "hw/hw.h" /* hw_error */
21 #include "hw/i2c/i2c.h"
22 #include "hw/i386/pc.h"
23 #include "hw/irq.h" /* qemu_irq_raise */
24 #include "hw/ptimer.h" /* ptimer_state */
25 #include "exec/address-spaces.h" /* get_system_memory */
26 #include "migration/vmstate.h" /* VMStateDescription */
27 #include "net/net.h"
28 #include "sysemu/sysemu.h"
29 #include "qemu/timer.h"
30 #include "block/block.h"
31 #include "chardev/char.h" /* qemu_chr_new */
32 #include "ui/console.h"
34 #include "s3c2440.h"
36 #define logout(fmt, ...) \
37 fprintf(stderr, "S3C2443\t%-24s" fmt, __func__, ##__VA_ARGS__)
39 #define TODO() logout("%s:%u: missing\n", __FILE__, __LINE__)
41 #define MiB (1024 * 1024)
44 Base Address of Special Registers
45 Address Module
46 0x51000000 PWM
47 0x5B000000 AC97
48 0x50000000 UART
49 0x5A000000 SDI
50 0x4F800000 TIC
51 0x4F000000 SSMC
52 0x59000000 SPI
53 0x4E800000 MATRIX
54 0x58000000 TSADC
55 0x4E000000 NFCON
56 0x4D800000 CAM I/F
57 0x4D000000 STN-LCD
58 0x57000000 RTC
59 0x4C800000 TFT-LCD
60 0x4B800000 CF Card
61 0x4B000000 DMA
62 0x55000000 IIS
63 0x4A800000 HS-MMC
64 0x54000000 IIC
65 0x4A000000 INTC
66 0x49800000 USB Device
67 0x53000000 WDT
68 0x49000000 USB HOST
69 0x48800000 EBI
70 0x48000000 Module SDRAM
71 0x52000000 HS-SPI
74 #define S3C2443X_SYSCON 0x4c000000
75 #define S3C2443X_IO_PORT 0x56000000
77 typedef struct {
78 S3CState *soc;
79 } TTState;
81 typedef struct {
82 unsigned offset;
83 const char *name;
84 } OffsetNamePair;
86 #if 0
87 static const char *offset2name(const OffsetNamePair *o2n, unsigned offset)
89 static char buffer[12];
90 const char *name = buffer;
91 snprintf(buffer, sizeof(buffer), "0x%08x", offset);
92 for (; o2n->name; o2n++) {
93 if (offset == o2n->offset) {
94 name = o2n->name;
95 break;
98 return name;
100 #endif
102 #define MP_MISC_BASE 0x80002000
103 #define MP_MISC_SIZE 0x00001000
105 #define MP_GPIO_BASE 0x8000D000
106 #define MP_GPIO_SIZE 0x00001000
108 #define MP_AUDIO_BASE 0x90007000
110 #define MP_LCD_BASE 0x9000c000
111 #define MP_LCD_SIZE 0x00001000
113 #define TT_SRAM_BASE 0xC0000000
114 #define TT_SRAM_SIZE 0x00020000
116 #define MP_RAM_DEFAULT_SIZE (64 * MiB)
118 #define MP_TIMER1_IRQ 4
119 #define MP_TIMER2_IRQ 5
120 #define MP_TIMER3_IRQ 6
121 #define MP_TIMER4_IRQ 7
122 #define MP_EHCI_IRQ 8
123 #define MP_ETH_IRQ 9
124 #define MP_GPIO_IRQ 12
125 #define MP_RTC_IRQ 28
126 #define MP_AUDIO_IRQ 30
128 /* Wolfson 8750 I2C address */
129 #define MP_WM_ADDR 0x1A
131 /* LCD register offsets */
132 #define MP_LCD_IRQCTRL 0x180
133 #define MP_LCD_IRQSTAT 0x184
134 #define MP_LCD_SPICTRL 0x1ac
135 #define MP_LCD_INST 0x1bc
136 #define MP_LCD_DATA 0x1c0
138 /* Mode magics */
139 #define MP_LCD_SPI_DATA 0x00100011
140 #define MP_LCD_SPI_CMD 0x00104011
141 #define MP_LCD_SPI_INVALID 0x00000000
143 /* Commands */
144 #define MP_LCD_INST_SETPAGE0 0xB0
145 /* ... */
146 #define MP_LCD_INST_SETPAGE7 0xB7
148 #define MP_LCD_TEXTCOLOR 0xe0e0ff /* RRGGBB */
150 #define TYPE_TT_LCD "tt_lcd"
151 #define TT_LCD(obj) OBJECT_CHECK(tt_lcd_state, (obj), TYPE_TT_LCD)
153 typedef struct {
154 SysBusDevice busdev;
155 MemoryRegion mmio;
156 QemuConsole *con;
157 uint32_t brightness;
158 uint32_t mode;
159 uint32_t irqctrl;
160 uint32_t page;
161 uint32_t page_off;
162 uint8_t video_ram[128*64/8];
163 } tt_lcd_state;
165 static uint8_t scale_lcd_color(tt_lcd_state *s, uint8_t col)
167 switch (s->brightness) {
168 case 7:
169 return col;
170 case 0:
171 return 0;
172 default:
173 return (col * s->brightness) / 7;
177 #define SET_LCD_PIXEL(depth, type) \
178 static inline void glue(set_lcd_pixel, depth) \
179 (tt_lcd_state *s, int x, int y, type col) \
181 int dx, dy; \
182 DisplaySurface *surface = qemu_console_surface(s->con); \
183 type *pixel = &((type *) surface_data(surface))[(y * 128 * 3 + x) * 3]; \
185 for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
186 for (dx = 0; dx < 3; dx++, pixel++) \
187 *pixel = col; \
189 SET_LCD_PIXEL(8, uint8_t)
190 SET_LCD_PIXEL(16, uint16_t)
191 SET_LCD_PIXEL(32, uint32_t)
193 #include "ui/pixel_ops.h"
195 static void lcd_refresh(void *opaque)
197 tt_lcd_state *s = opaque;
198 DisplaySurface *surface = qemu_console_surface(s->con);
199 int x, y, col;
201 switch (surface_bits_per_pixel(surface)) {
202 case 0:
203 return;
204 #define LCD_REFRESH(depth, func) \
205 case depth: \
206 col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
207 scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
208 scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
209 for (x = 0; x < 128; x++) { \
210 for (y = 0; y < 64; y++) { \
211 if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
212 glue(set_lcd_pixel, depth)(s, x, y, col); \
213 } else { \
214 glue(set_lcd_pixel, depth)(s, x, y, 0); \
218 break;
219 LCD_REFRESH(8, rgb_to_pixel8)
220 LCD_REFRESH(16, rgb_to_pixel16)
221 LCD_REFRESH(32, (is_surface_bgr(surface) ?
222 rgb_to_pixel32bgr : rgb_to_pixel32))
223 default:
224 hw_error("unsupported colour depth %i\n",
225 surface_bits_per_pixel(surface));
228 dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
231 static void lcd_invalidate(void *opaque)
235 static void tt_lcd_gpio_brigthness_in(void *opaque, int irq, int level)
237 tt_lcd_state *s = opaque;
238 s->brightness &= ~(1 << irq);
239 s->brightness |= level << irq;
242 static uint64_t tt_lcd_read(void *opaque, hwaddr offset,
243 unsigned size)
245 tt_lcd_state *s = opaque;
247 switch (offset) {
248 case MP_LCD_IRQCTRL:
249 return s->irqctrl;
251 default:
252 return 0;
256 static void tt_lcd_write(void *opaque, hwaddr offset,
257 uint64_t value, unsigned size)
259 tt_lcd_state *s = opaque;
261 switch (offset) {
262 case MP_LCD_IRQCTRL:
263 s->irqctrl = value;
264 break;
266 case MP_LCD_SPICTRL:
267 if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD) {
268 s->mode = value;
269 } else {
270 s->mode = MP_LCD_SPI_INVALID;
272 break;
274 case MP_LCD_INST:
275 if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
276 s->page = value - MP_LCD_INST_SETPAGE0;
277 s->page_off = 0;
279 break;
281 case MP_LCD_DATA:
282 if (s->mode == MP_LCD_SPI_CMD) {
283 if (value >= MP_LCD_INST_SETPAGE0 &&
284 value <= MP_LCD_INST_SETPAGE7) {
285 s->page = value - MP_LCD_INST_SETPAGE0;
286 s->page_off = 0;
288 } else if (s->mode == MP_LCD_SPI_DATA) {
289 s->video_ram[s->page*128 + s->page_off] = value;
290 s->page_off = (s->page_off + 1) & 127;
292 break;
296 static const MemoryRegionOps tt_lcd_ops = {
297 .read = tt_lcd_read,
298 .write = tt_lcd_write,
299 .endianness = DEVICE_NATIVE_ENDIAN,
300 .valid = {
301 .min_access_size = 4,
302 .max_access_size = 4
306 static const GraphicHwOps tt_gfx_ops = {
307 .invalidate = lcd_invalidate,
308 .gfx_update = lcd_refresh,
311 static void tt_lcd_realize(DeviceState *dev, Error **errp)
313 tt_lcd_state *s = TT_LCD(dev);
314 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
316 s->brightness = 7;
318 memory_region_init_io(&s->mmio, OBJECT(s),
319 &tt_lcd_ops, s, "tt-lcd", MP_LCD_SIZE);
320 sysbus_init_mmio(sbd, &s->mmio);
322 s->con = graphic_console_init(DEVICE(dev), 0, &tt_gfx_ops, s);
323 qemu_console_resize(s->con, 128*3, 64*3);
325 qdev_init_gpio_in(dev, tt_lcd_gpio_brigthness_in, 3);
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 dc->desc = "TT LCD",
348 //~ dc->props = dp8381x_properties;
349 dc->realize = tt_lcd_realize;
350 //~ dc->reset = qdev_dp8381x_reset;
351 dc->vmsd = &tt_lcd_vmsd;
354 static const TypeInfo tt_lcd_info = {
355 .name = TYPE_TT_LCD,
356 .parent = TYPE_SYS_BUS_DEVICE,
357 .instance_size = sizeof(tt_lcd_state),
358 .class_init = tt_lcd_class_init,
361 /******************************************************************************/
363 #define S3C2443_MPLLCON 0x10
364 #define S3C2443_CLKDIV0 0x24
366 /******************************************************************************/
368 /* SYSCON register offsets. */
369 #define SYSCON_MPLLCON 0x10
370 #define SYSCON_CLKDIV0 0x24
372 #if 0
373 static const OffsetNamePair tt_syscon_names[] = {
377 static uint64_t tt_syscon_read(void *opaque, hwaddr offset,
378 unsigned size)
380 uint32_t value = 0;
381 logout("%s\n", offset2name(tt_syscon_names, offset));
382 switch (offset) {
383 case SYSCON_MPLLCON:
384 case SYSCON_CLKDIV0:
385 default:
386 TODO();
388 return value;
391 static void tt_syscon_write(void *opaque, hwaddr offset,
392 uint64_t value, unsigned size)
394 logout("%s 0x%08" PRIx64 "\n", offset2name(tt_syscon_names, offset), value);
395 switch (offset) {
396 default:
397 TODO();
401 static const MemoryRegionOps tt_syscon_ops = {
402 .read = tt_syscon_read,
403 .write = tt_syscon_write,
404 .endianness = DEVICE_NATIVE_ENDIAN,
405 .valid = {
406 .min_access_size = 4,
407 .max_access_size = 4
410 #endif
412 /******************************************************************************/
414 /* I/O port register offsets. */
415 #define IOPORT_GPBCON 0x10
416 #define IOPORT_GPBDAT 0x14
417 #define IOPORT_GPBUDP 0x18
418 #define IOPORT_EXTINT0 0x88
419 #define IOPORT_EXTINT1 0x8c
420 #define IOPORT_EXTINT2 0x90
421 #define IOPORT_GSTATUS1 0xb0
424 tt_ioport_write: 0x00000010
425 tt_ioport_write: 0x00000018
426 tt_ioport_write: 0x00000010
427 tt_ioport_write: 0x00000018
430 #if 0
431 static const OffsetNamePair tt_ioport_names[] = {
435 static uint64_t tt_ioport_read(void *opaque, hwaddr offset,
436 unsigned size)
438 uint32_t value = 0;
439 logout("%s\n", offset2name(tt_ioport_names, offset));
440 switch (offset) {
441 case IOPORT_GPBCON:
442 TODO();
443 break;
444 case IOPORT_GPBDAT:
445 TODO();
446 break;
447 case IOPORT_GPBUDP:
448 value = 0x2aaaaa;
449 break;
450 //~ case IOPORT_EXTINT0:
451 //~ case IOPORT_EXTINT1:
452 //~ case IOPORT_EXTINT2:
453 case IOPORT_GSTATUS1:
454 value = 0x32443001;
455 break;
456 default:
457 TODO();
459 return value;
462 static void tt_ioport_write(void *opaque, hwaddr offset,
463 uint64_t value, unsigned size)
465 logout("%s 0x%08" PRIx64 "\n", offset2name(tt_ioport_names, offset), value);
466 switch (offset) {
467 case IOPORT_GPBCON:
468 TODO();
469 break;
470 //~ case IOPORT_GPBDAT:
471 case IOPORT_GPBUDP:
472 TODO();
473 break;
474 case IOPORT_EXTINT0:
475 TODO();
476 break;
477 case IOPORT_EXTINT1:
478 TODO();
479 break;
480 case IOPORT_EXTINT2:
481 TODO();
482 break;
483 //~ case IOPORT_GSTATUS1:
484 default:
485 TODO();
489 static const MemoryRegionOps tt_ioport_ops = {
490 .read = tt_ioport_read,
491 .write = tt_ioport_write,
492 .endianness = DEVICE_NATIVE_ENDIAN,
493 .valid = {
494 .min_access_size = 4,
495 .max_access_size = 4
498 #endif
500 /******************************************************************************/
502 #if 0
503 static void tt_syscon_init(void)
505 memory_region_init_io(&s->syscon, OBJECT(s), &tt_syscon_ops, s,
506 "tt-syscon", 0x10000);
507 memory_region_add_subregion(get_system_memory(), S3C2443X_SYSCON, &s->syscon);
510 static void tt_ioport_init(void)
512 memory_region_init_io(&s->ioport, OBJECT(s), &tt_ioport_ops, s,
513 "tt-ioport", 0x10000);
514 memory_region_add_subregion(get_system_memory(), S3C2443X_IO_PORT, &s->ioport);
516 #endif
518 /* GPIO register offsets */
519 #define MP_GPIO_OE_LO 0x008
520 #define MP_GPIO_OUT_LO 0x00c
521 #define MP_GPIO_IN_LO 0x010
522 #define MP_GPIO_IER_LO 0x014
523 #define MP_GPIO_IMR_LO 0x018
524 #define MP_GPIO_ISR_LO 0x020
525 #define MP_GPIO_OE_HI 0x508
526 #define MP_GPIO_OUT_HI 0x50c
527 #define MP_GPIO_IN_HI 0x510
528 #define MP_GPIO_IER_HI 0x514
529 #define MP_GPIO_IMR_HI 0x518
530 #define MP_GPIO_ISR_HI 0x520
532 /* GPIO bits & masks */
533 #define MP_GPIO_LCD_BRIGHTNESS 0x00070000
534 #define MP_GPIO_I2C_DATA_BIT 29
535 #define MP_GPIO_I2C_CLOCK_BIT 30
537 /* LCD brightness bits in GPIO_OE_HI */
538 #define MP_OE_LCD_BRIGHTNESS 0x0007
540 #define TYPE_TT_GPIO "tt_gpio"
541 #define TT_GPIO(obj) \
542 OBJECT_CHECK(tt_gpio_state, (obj), TYPE_TT_GPIO)
544 typedef struct {
545 SysBusDevice busdev;
546 MemoryRegion mmio;
547 uint32_t lcd_brightness;
548 uint32_t out_state;
549 uint32_t in_state;
550 uint32_t ier;
551 uint32_t imr;
552 uint32_t isr;
553 qemu_irq irq;
554 qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
555 } tt_gpio_state;
557 static void tt_gpio_brightness_update(tt_gpio_state *s) {
558 int i;
559 uint32_t brightness;
561 /* compute brightness ratio */
562 switch (s->lcd_brightness) {
563 case 0x00000007:
564 brightness = 0;
565 break;
567 case 0x00020000:
568 brightness = 1;
569 break;
571 case 0x00020001:
572 brightness = 2;
573 break;
575 case 0x00040000:
576 brightness = 3;
577 break;
579 case 0x00010006:
580 brightness = 4;
581 break;
583 case 0x00020005:
584 brightness = 5;
585 break;
587 case 0x00040003:
588 brightness = 6;
589 break;
591 case 0x00030004:
592 default:
593 brightness = 7;
596 /* set lcd brightness GPIOs */
597 for (i = 0; i <= 2; i++) {
598 qemu_set_irq(s->out[i], (brightness >> i) & 1);
602 static void tt_gpio_pin_event(void *opaque, int pin, int level)
604 tt_gpio_state *s = opaque;
605 uint32_t mask = 1 << pin;
606 uint32_t delta = level << pin;
607 uint32_t old = s->in_state & mask;
609 s->in_state &= ~mask;
610 s->in_state |= delta;
612 if ((old ^ delta) &&
613 ((level && (s->imr & mask)) || (!level && (s->ier & mask)))) {
614 s->isr = mask;
615 qemu_irq_raise(s->irq);
619 static uint64_t tt_gpio_read(void *opaque, hwaddr offset,
620 unsigned size)
622 tt_gpio_state *s = opaque;
624 switch (offset) {
625 case MP_GPIO_OE_HI: /* used for LCD brightness control */
626 return s->lcd_brightness & MP_OE_LCD_BRIGHTNESS;
628 case MP_GPIO_OUT_LO:
629 return s->out_state & 0xFFFF;
630 case MP_GPIO_OUT_HI:
631 return s->out_state >> 16;
633 case MP_GPIO_IN_LO:
634 return s->in_state & 0xFFFF;
635 case MP_GPIO_IN_HI:
636 return s->in_state >> 16;
638 case MP_GPIO_IER_LO:
639 return s->ier & 0xFFFF;
640 case MP_GPIO_IER_HI:
641 return s->ier >> 16;
643 case MP_GPIO_IMR_LO:
644 return s->imr & 0xFFFF;
645 case MP_GPIO_IMR_HI:
646 return s->imr >> 16;
648 case MP_GPIO_ISR_LO:
649 return s->isr & 0xFFFF;
650 case MP_GPIO_ISR_HI:
651 return s->isr >> 16;
653 default:
654 return 0;
658 static void tt_gpio_write(void *opaque, hwaddr offset,
659 uint64_t value, unsigned size)
661 tt_gpio_state *s = opaque;
662 switch (offset) {
663 case MP_GPIO_OE_HI: /* used for LCD brightness control */
664 s->lcd_brightness = (s->lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
665 (value & MP_OE_LCD_BRIGHTNESS);
666 tt_gpio_brightness_update(s);
667 break;
669 case MP_GPIO_OUT_LO:
670 s->out_state = (s->out_state & 0xFFFF0000) | (value & 0xFFFF);
671 break;
672 case MP_GPIO_OUT_HI:
673 s->out_state = (s->out_state & 0xFFFF) | (value << 16);
674 s->lcd_brightness = (s->lcd_brightness & 0xFFFF) |
675 (s->out_state & MP_GPIO_LCD_BRIGHTNESS);
676 tt_gpio_brightness_update(s);
677 qemu_set_irq(s->out[3], (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1);
678 qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
679 break;
681 case MP_GPIO_IER_LO:
682 s->ier = (s->ier & 0xFFFF0000) | (value & 0xFFFF);
683 break;
684 case MP_GPIO_IER_HI:
685 s->ier = (s->ier & 0xFFFF) | (value << 16);
686 break;
688 case MP_GPIO_IMR_LO:
689 s->imr = (s->imr & 0xFFFF0000) | (value & 0xFFFF);
690 break;
691 case MP_GPIO_IMR_HI:
692 s->imr = (s->imr & 0xFFFF) | (value << 16);
693 break;
697 static const MemoryRegionOps tt_gpio_ops = {
698 .read = tt_gpio_read,
699 .write = tt_gpio_write,
700 .endianness = DEVICE_NATIVE_ENDIAN,
701 .valid = {
702 .min_access_size = 4,
703 .max_access_size = 4
707 static void tt_gpio_reset(DeviceState *d)
709 tt_gpio_state *s = TT_GPIO(d);
711 s->lcd_brightness = 0;
712 s->out_state = 0;
713 s->in_state = 0xffffffff;
714 s->ier = 0;
715 s->imr = 0;
716 s->isr = 0;
719 static void tt_gpio_realize(DeviceState *dev, Error **errp)
721 tt_gpio_state *s = TT_GPIO(dev);
722 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
724 sysbus_init_irq(sbd, &s->irq);
726 memory_region_init_io(&s->mmio, OBJECT(s), &tt_gpio_ops, s,
727 "tt-gpio", MP_GPIO_SIZE);
728 sysbus_init_mmio(sbd, &s->mmio);
730 qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
732 qdev_init_gpio_in(dev, tt_gpio_pin_event, 32);
735 static const VMStateDescription tt_gpio_vmsd = {
736 .name = TYPE_TT_GPIO,
737 .version_id = 1,
738 .minimum_version_id = 1,
739 .minimum_version_id_old = 1,
740 .fields = (VMStateField[]) {
741 VMSTATE_UINT32(lcd_brightness, tt_gpio_state),
742 VMSTATE_UINT32(out_state, tt_gpio_state),
743 VMSTATE_UINT32(in_state, tt_gpio_state),
744 VMSTATE_UINT32(ier, tt_gpio_state),
745 VMSTATE_UINT32(imr, tt_gpio_state),
746 VMSTATE_UINT32(isr, tt_gpio_state),
747 VMSTATE_END_OF_LIST()
751 static void tt_gpio_class_init(ObjectClass *klass, void *data)
753 DeviceClass *dc = DEVICE_CLASS(klass);
754 dc->realize = tt_gpio_realize;
755 dc->reset = tt_gpio_reset;
756 dc->vmsd = &tt_gpio_vmsd;
759 static const TypeInfo tt_gpio_info = {
760 .name = TYPE_TT_GPIO,
761 .parent = TYPE_SYS_BUS_DEVICE,
762 .instance_size = sizeof(tt_gpio_state),
763 .class_init = tt_gpio_class_init,
766 /* Keyboard codes & masks */
767 #define KEY_RELEASED 0x80
768 #define KEY_CODE 0x7f
770 #define KEYCODE_TAB 0x0f
771 #define KEYCODE_ENTER 0x1c
772 #define KEYCODE_F 0x21
773 #define KEYCODE_M 0x32
775 #define KEYCODE_EXTENDED 0xe0
776 #define KEYCODE_UP 0x48
777 #define KEYCODE_DOWN 0x50
778 #define KEYCODE_LEFT 0x4b
779 #define KEYCODE_RIGHT 0x4d
781 #define MP_KEY_WHEEL_VOL (1 << 0)
782 #define MP_KEY_WHEEL_VOL_INV (1 << 1)
783 #define MP_KEY_WHEEL_NAV (1 << 2)
784 #define MP_KEY_WHEEL_NAV_INV (1 << 3)
785 #define MP_KEY_BTN_FAVORITS (1 << 4)
786 #define MP_KEY_BTN_MENU (1 << 5)
787 #define MP_KEY_BTN_VOLUME (1 << 6)
788 #define MP_KEY_BTN_NAVIGATION (1 << 7)
790 #define TYPE_TT_KEY "tt_key"
791 #define TT_KEY(obj) \
792 OBJECT_CHECK(tt_key_state, (obj), TYPE_TT_KEY)
794 typedef struct {
795 SysBusDevice busdev;
796 MemoryRegion mmio;
797 uint32_t kbd_extended;
798 uint32_t pressed_keys;
799 qemu_irq out[8];
800 } tt_key_state;
802 static void tt_key_event(void *opaque, int keycode)
804 tt_key_state *s = opaque;
805 uint32_t event = 0;
806 int i;
808 if (keycode == KEYCODE_EXTENDED) {
809 s->kbd_extended = 1;
810 return;
813 if (s->kbd_extended) {
814 switch (keycode & KEY_CODE) {
815 case KEYCODE_UP:
816 event = MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_NAV_INV;
817 break;
819 case KEYCODE_DOWN:
820 event = MP_KEY_WHEEL_NAV;
821 break;
823 case KEYCODE_LEFT:
824 event = MP_KEY_WHEEL_VOL | MP_KEY_WHEEL_VOL_INV;
825 break;
827 case KEYCODE_RIGHT:
828 event = MP_KEY_WHEEL_VOL;
829 break;
831 } else {
832 switch (keycode & KEY_CODE) {
833 case KEYCODE_F:
834 event = MP_KEY_BTN_FAVORITS;
835 break;
837 case KEYCODE_TAB:
838 event = MP_KEY_BTN_VOLUME;
839 break;
841 case KEYCODE_ENTER:
842 event = MP_KEY_BTN_NAVIGATION;
843 break;
845 case KEYCODE_M:
846 event = MP_KEY_BTN_MENU;
847 break;
849 /* Do not repeat already pressed buttons */
850 if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
851 event = 0;
855 if (event) {
856 /* Raise GPIO pin first if repeating a key */
857 if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
858 for (i = 0; i <= 7; i++) {
859 if (event & (1 << i)) {
860 qemu_set_irq(s->out[i], 1);
864 for (i = 0; i <= 7; i++) {
865 if (event & (1 << i)) {
866 qemu_set_irq(s->out[i], !!(keycode & KEY_RELEASED));
869 if (keycode & KEY_RELEASED) {
870 s->pressed_keys &= ~event;
871 } else {
872 s->pressed_keys |= event;
876 s->kbd_extended = 0;
879 static void tt_key_realize(DeviceState *dev, Error **errp)
881 tt_key_state *s = TT_KEY(dev);
882 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
884 sysbus_init_mmio(sbd, &s->mmio);
886 s->kbd_extended = 0;
887 s->pressed_keys = 0;
889 qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
891 qemu_add_kbd_event_handler(tt_key_event, s);
894 static const VMStateDescription tt_key_vmsd = {
895 .name = TYPE_TT_KEY,
896 .version_id = 1,
897 .minimum_version_id = 1,
898 .minimum_version_id_old = 1,
899 .fields = (VMStateField[]) {
900 VMSTATE_UINT32(kbd_extended, tt_key_state),
901 VMSTATE_UINT32(pressed_keys, tt_key_state),
902 VMSTATE_END_OF_LIST()
906 static void tt_key_class_init(ObjectClass *klass, void *data)
908 DeviceClass *dc = DEVICE_CLASS(klass);
909 dc->realize = tt_key_realize;
910 dc->vmsd = &tt_key_vmsd;
913 static const TypeInfo tt_key_info = {
914 .name = TYPE_TT_KEY,
915 .parent = TYPE_SYS_BUS_DEVICE,
916 .instance_size = sizeof(tt_key_state),
917 .class_init = tt_key_class_init,
920 static struct arm_boot_info tt_binfo = {
921 #if 0
922 .loader_start = 0,
923 #else
924 .loader_start = TT_SRAM_BASE,
925 #endif
926 /* GO 730 */
927 .board_id = 0x25d,
928 .atag_revision = 0x0004000a,
931 static void tt_init(MachineState *machine)
933 ARMCPU *cpu;
934 TTState *s;
935 #if 0
936 qemu_irq pic[32];
937 DeviceState *dev;
938 DeviceState *i2c_dev;
939 DeviceState *lcd_dev;
940 DeviceState *key_dev;
941 DeviceState *wm8750_dev;
942 SysBusDevice *s;
943 I2CBus *i2c;
944 unsigned long flash_size;
945 DriveInfo *dinfo;
946 ram_addr_t ram_off;
947 ram_addr_t sram_off;
948 #endif
949 unsigned i;
951 #if 0
952 if (machine->cpu_model && strcmp(machine->cpu_model, "arm920t")) {
953 fprintf(stderr, "only working with cpu arm920t\n");
954 exit(1);
956 #endif
958 /* Allocate storage for board state. */
959 s = g_new0(TTState, 1);
961 for (i = 0; i < serial_max_hds(); i++) {
962 #if 1
963 assert(i < 3);
964 assert(serial_hd(i));
965 #else
966 /* TODO: This code no longer works. Remove or replace. */
967 if (serial_hd(i) == NULL) {
968 char name[32];
969 snprintf(name, sizeof(name), "serial%u", i);
970 serial_hd(i) = qemu_chr_new(name, "vc:80Cx24C", NULL);
972 #endif
975 /* Initialise SOC. */
976 s->soc = s3c2440_init(ram_size);
978 cpu = s->soc->cpu;
980 //~ ram_off = qemu_ram_alloc(NULL, "arm920.ram", ram_size);
981 //~ cpu_register_physical_memory(0x00000000, ram_size, ram_off | IO_MEM_RAM);
982 //~ cpu_register_physical_memory(0x30000000, ram_size, ram_off | IO_MEM_RAM);
983 //~ cpu_register_physical_memory(0x80000000, ram_size, ram_off | IO_MEM_RAM);
984 //~ cpu_register_physical_memory(0xc0000000, ram_size, ram_off | IO_MEM_RAM);
986 //~ tt_syscon_init();
987 //~ tt_ioport_init();
989 #if 0
990 dev = sysbus_create_simple(TYPE_TT_GPIO, MP_GPIO_BASE, pic[MP_GPIO_IRQ]);
991 i2c_dev = sysbus_create_simple("gpio_i2c", 0, NULL);
992 i2c = (I2CBus *)qdev_get_child_bus(i2c_dev, "i2c");
994 lcd_dev = sysbus_create_simple(TYPE_TT_LCD, MP_LCD_BASE, NULL);
995 key_dev = sysbus_create_simple(TYPE_TT_KEY, 0, NULL);
997 /* I2C read data */
998 qdev_connect_gpio_out(i2c_dev, 0,
999 qdev_get_gpio_in(dev, MP_GPIO_I2C_DATA_BIT));
1000 /* I2C data */
1001 qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0));
1002 /* I2C clock */
1003 qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1));
1005 for (i = 0; i < 3; i++) {
1006 qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i));
1008 for (i = 0; i < 4; i++) {
1009 qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 8));
1011 for (i = 4; i < 8; i++) {
1012 qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
1015 wm8750_dev = i2c_create_slave(i2c, "wm8750", MP_WM_ADDR);
1016 dev = qdev_create(NULL, "mv88w8618_audio");
1017 s = SYS_BUS_DEVICE(dev);
1018 qdev_prop_set_ptr(dev, "wm8750", wm8750_dev);
1019 qdev_init_nofail(dev);
1020 sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
1021 sysbus_connect_irq(s, 0, pic[MP_AUDIO_IRQ]);
1022 #endif
1024 tt_binfo.ram_size = ram_size;
1025 tt_binfo.kernel_filename = machine->kernel_filename;
1026 tt_binfo.kernel_cmdline = machine->kernel_cmdline;
1027 tt_binfo.initrd_filename = machine->initrd_filename;
1028 if (machine->kernel_filename != NULL) {
1029 /* TODO: load ttsystem. */
1030 //~ sect_size = 0x11b778, sect_addr = 0x31700000
1031 //~ sect_size = 0x6a3f45, sect_addr = 0x31000000
1032 arm_load_kernel(cpu, machine, &tt_binfo);
1036 static void tt_init_go(MachineState *machine)
1038 tt_binfo.board_id = 0x25d;
1039 ram_size = 64 * MiB;
1040 tt_init(machine);
1043 static void tt_init_666(MachineState *machine)
1045 tt_binfo.board_id = 0x666;
1046 tt_init(machine);
1049 static void tt_init_smdk2443(MachineState *machine)
1051 tt_binfo.board_id = 0x43c;
1052 tt_init(machine);
1055 static void tt_machine_init(MachineClass *mc)
1057 mc->desc = "OpenTom (ARM920-T)";
1058 mc->init = tt_init_go;
1061 DEFINE_MACHINE("tt", tt_machine_init)
1063 static void tt_machine_666_init(MachineClass *mc)
1065 mc->desc = "OpenTom (ARM920-T)";
1066 mc->init = tt_init_666;
1069 DEFINE_MACHINE("tt666", tt_machine_666_init)
1071 static void tt_machine_smdk2443_init(MachineClass *mc)
1073 mc->desc = "smdk2443 (ARM920-T)";
1074 mc->init = tt_init_smdk2443;
1077 DEFINE_MACHINE("smdk2443", tt_machine_smdk2443_init)
1079 static void tt_register_types(void)
1081 type_register_static(&tt_lcd_info);
1082 type_register_static(&tt_gpio_info);
1083 type_register_static(&tt_key_info);
1086 type_init(tt_register_types)