Tizen ARM: Add maru_arm board.
authorEvgeny Voevodin <e.voevodin@samsung.com>
Thu, 14 Jun 2012 06:44:10 +0000 (10:44 +0400)
committerEvgeny Voevodin <e.voevodin@samsung.com>
Fri, 15 Jun 2012 07:24:03 +0000 (11:24 +0400)
This commit adds basic maru_arm specific devices.
Few common files are modyfied to support ARM.
Also build.sh is modyfied to find out amount of
host CPUs and speed up compiling.

Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
14 files changed:
config.h
hw/pl050.c
hw/virtio-pci.c
tizen/build.sh
tizen/qemu_configure_arm.sh [new file with mode: 0755]
tizen/src/Makefile
tizen/src/Makefile.tizen
tizen/src/hw/maru_arm.c [new file with mode: 0644]
tizen/src/hw/maru_arm.h [new file with mode: 0644]
tizen/src/hw/maru_arm_board.c [new file with mode: 0644]
tizen/src/hw/maru_arm_pmu.c [new file with mode: 0644]
tizen/src/hw/maru_arm_vpci.c [new file with mode: 0644]
tizen/src/hw/maru_pm.h
vl.c

index 82c0ab265c29a707b698cdb2933b67d691f01a78..e20f78696a1b7c8c0c3b4d6b7b6c1c9dbdfad427 100644 (file)
--- a/config.h
+++ b/config.h
@@ -1,2 +1,2 @@
 #include "config-host.h"
-#include "i386-softmmu/config-target.h"
+#include "config-target.h"
index b13924a160a387842af91ae8acba8dcabeb94f33..119b5433217eaf962f2d0f684d0d11e2be4fa806 100644 (file)
@@ -121,6 +121,11 @@ static void pl050_write(void *opaque, target_phys_addr_t offset,
         break;
     case 3: /* KMICLKDIV */
         s->clk = value;
+#ifdef CONFIG_MARU
+        if (!s->is_mouse) {
+               ps2_keyboard_set_translation(s->dev, 1);
+        }
+#endif
         return;
     default:
         hw_error("pl050_write: Bad offset %x\n", (int)offset);
index 784f2d8132b03f10d0f99f44b5b8c9e6856ff9e8..5c02ca5988aa620e774eeb183cd289584d534c16 100644 (file)
@@ -811,6 +811,7 @@ static int virtio_balloon_exit_pci(PCIDevice *pci_dev)
 }
 
 #ifndef _WIN32
+#ifdef CONFIG_GL
 extern VirtIODevice *virtio_gl_init(DeviceState *dev);
 static int virtio_gl_init_pci(PCIDevice *pci_dev)
 {
@@ -825,6 +826,7 @@ static int virtio_gl_init_pci(PCIDevice *pci_dev)
     return 0;
 }
 #endif
+#endif
 
 static Property virtio_blk_properties[] = {
     DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
@@ -1010,6 +1012,7 @@ static TypeInfo virtio_scsi_info = {
 
 
 #ifndef _WIN32
+#ifdef CONFIG_GL
 static void virtio_gl_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -1031,6 +1034,7 @@ static TypeInfo virtio_gl_info = {
     .class_init    = virtio_gl_class_init,
 };
 #endif
+#endif
 
 static void virtio_pci_register_types(void)
 {
@@ -1040,8 +1044,10 @@ static void virtio_pci_register_types(void)
     type_register_static(&virtio_balloon_info);
     type_register_static(&virtio_scsi_info);
 #ifndef _WIN32
+#ifdef CONFIG_GL
     type_register_static(&virtio_gl_info);
 #endif
+#endif
 
 }
 
index dbc266c1fb0fe905af92d35c722a1fe90e693734..e44d22630fab574d578fae37934b1e46700b2e6c 100755 (executable)
@@ -1,4 +1,22 @@
-#!/bin/sh -xe
+#!/bin/sh
 
-./qemu_configure.sh
-make && make install
+UNAME=`uname`
+
+case "$UNAME" in
+Linux)
+    NUMCPU=`grep -c 'cpu cores' /proc/cpuinfo`
+    ;;
+MINGW*)
+    NUMCPU=`echo $NUMBER_OF_PROCESSORS`
+    ;;
+esac
+
+echo "Number of CPUs $NUMCPU"
+
+if [ "x$NUMCPU" != "x" ] ; then
+    NUMCPU=$(( NUMCPU + 1 ))
+else
+    NUMCPU=1
+fi
+
+./qemu_configure.sh && make -j$NUMCPU && ./qemu_configure_arm.sh && make -j$NUMCPU && make install
diff --git a/tizen/qemu_configure_arm.sh b/tizen/qemu_configure_arm.sh
new file mode 100755 (executable)
index 0000000..2c4f144
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/sh
+# OS specific
+#--target-list=i386-softmmu,arm-softmmu \
+targetos=`uname -s`
+
+cd ..
+case $targetos in
+Linux*)
+echo "checking for os... targetos $targetos"
+exec ./configure \
+ --target-list=arm-softmmu \
+ --disable-werror \
+ --audio-drv-list=alsa \
+ --disable-vnc-tls \
+ --audio-card-list=ac97 \
+ --enable-maru
+# --enable-mixemu \
+# --enable-ldst-optimization \
+# --enable-gl
+# --enable-ffmpeg
+# --enable-v4l2 \
+# --enable-debug \
+# --enable-profiler
+;;
+MINGW*)
+echo "checking for os... targetos $targetos"
+exec ./configure \
+ --target-list=arm-softmmu \
+ --audio-drv-list=winwave \
+ --enable-mixemu \
+ --disable-vnc-tls \
+ --audio-card-list=ac97 \
+ --enable-hax \
+ --enable-maru
+# --enable-ldst-optimization \
+# --enable-gl
+# --enable-ffmpeg
+# --disable-vnc-jpeg \
+# --disable-jpeg
+;;
+esac
index 45e7515e9f5d51717b0e8a2b85190105932aa02e..d38fdced6be17c0cd396cf1c2b41c306f2e3f48d 100755 (executable)
@@ -50,8 +50,10 @@ install: all
        mkdir -p $(EMUL_DIR)/x86
        mkdir -p $(EMUL_DIR)/x86/data 
        mkdir -p $(EMUL_DIR)/arm
+       mkdir -p $(EMUL_DIR)/arm/data
        mkdir -p $(EMUL_DIR)/x86/data/pc-bios
        cp ../../i386-softmmu/qemu-system-i386 $(EMUL_DIR)/bin/emulator-x86
+       cp ../../arm-softmmu/qemu-system-arm $(EMUL_DIR)/bin/emulator-arm
        cp skin/client/emulator-skin.jar $(EMUL_DIR)/bin
 ifdef CONFIG_WIN32
        cp check-hax.exe $(EMUL_DIR)/bin
index 006bf65069c31b0eb3ee994033fa47fe3bd8cb26..90e19b4b713cad24509a1e797fe8597db5102556 100755 (executable)
@@ -92,12 +92,25 @@ ifdef CONFIG_WIN32 # libs for maru camera on windows host
 LIBS += -lole32 -loleaut32 -luuid -lstrmiids
 endif
 
+obj-arm-y += maru_arm.o
+obj-arm-y += maru_arm_board.o
+obj-arm-y += maru_codec.o
+obj-arm-y += maru_brightness.o
+obj-arm-y += maru_touchscreen.o
+obj-arm-y += maru_arm_vpci.o
+obj-arm-y += maru_arm_pmu.o
+obj-arm-y += maru_camera_common_pci.o
+obj-arm-$(CONFIG_LINUX) += maru_camera_linux_pci.o
+obj-arm-$(CONFIG_WIN32) += maru_camera_win32_pci.o
+
 
 # maru skin
 obj-i386-y += maruskin_client.o maruskin_server.o maruskin_operation.o maruskin_keymap.o
+obj-arm-y += maruskin_client.o maruskin_server.o maruskin_operation.o maruskin_keymap.o
 
 # guest server
-obj-i386-y += guest_server.o 
+obj-i386-y += guest_server.o
+obj-arm-y += guest_server.o
 
 ifndef CONFIG_WIN32
 ###########################################################
diff --git a/tizen/src/hw/maru_arm.c b/tizen/src/hw/maru_arm.c
new file mode 100644 (file)
index 0000000..5eaf6c0
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ *  Samsung Maru ARM SoC emulation
+ *
+ *  Based on exynos4210.c
+ *
+ *  Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *    Maksim Kozlov <m.kozlov@samsung.com>
+ *    Evgeny Voevodin <e.voevodin@samsung.com>
+ *    Igor Mitsyanko  <i.mitsyanko@samsung.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "boards.h"
+#include "arm-misc.h"
+#include "sysbus.h"
+#include "pci.h"
+#include "maru_arm.h"
+#include "i2c.h"
+#include "exec-memory.h"
+
+#include "loader.h"
+#include "virtio-transport.h"
+#include "exynos4210_i2s.h"
+
+#define EXYNOS4210_CHIPID_ADDR         0x10000000
+
+/* CMUs */
+#define EXYNOS4210_CMU_LEFTBUS_BASE_ADDR     0x10034000
+#define EXYNOS4210_CMU_RIGHTBUS_BASE_ADDR    0x10038000
+#define EXYNOS4210_CMU_TOP_BASE_ADDR         0x1003C000
+#define EXYNOS4210_CMU_DMC_BASE_ADDR         0x10040000
+#define EXYNOS4210_CMU_CPU_BASE_ADDR         0x10044000
+
+/* PWM */
+#define EXYNOS4210_PWM_BASE_ADDR       0x139D0000
+
+/* RTC */
+#define EXYNOS4210_RTC_BASE_ADDR       0x10070000
+
+/* MCT */
+#define EXYNOS4210_MCT_BASE_ADDR       0x10050000
+
+/* DMA */
+#define EXYNOS4210_DMAMEM_BASE_ADDR    0x12840000
+#define EXYNOS4210_DMAPERI0_BASE_ADDR  0x12680000
+#define EXYNOS4210_DMAPERI1_BASE_ADDR  0x12690000
+
+/* I2C */
+#define EXYNOS4210_I2C_SHIFT           0x00010000
+#define EXYNOS4210_I2C_BASE_ADDR       0x13860000
+/* Interrupt Group of External Interrupt Combiner for I2C */
+#define EXYNOS4210_I2C_INTG            27
+#define EXYNOS4210_HDMI_INTG           16
+
+/* There are two set of touch screen interfaces, which share one ADC */
+#define EXYNOS4210_TS0_BASE_ADDR       0x13910000
+#define EXYNOS4210_TS1_BASE_ADDR       0x13911000
+#define EXYNOS4210_TS_INTG             19
+
+/* UART's definitions */
+#define EXYNOS4210_UART0_BASE_ADDR     0x13800000
+#define EXYNOS4210_UART1_BASE_ADDR     0x13810000
+#define EXYNOS4210_UART2_BASE_ADDR     0x13820000
+#define EXYNOS4210_UART3_BASE_ADDR     0x13830000
+#define EXYNOS4210_UART0_FIFO_SIZE     256
+#define EXYNOS4210_UART1_FIFO_SIZE     64
+#define EXYNOS4210_UART2_FIFO_SIZE     16
+#define EXYNOS4210_UART3_FIFO_SIZE     16
+/* Interrupt Group of External Interrupt Combiner for UART */
+#define EXYNOS4210_UART_INT_GRP        26
+
+/* External GIC */
+#define EXYNOS4210_EXT_GIC_CPU_BASE_ADDR    0x10480000
+#define EXYNOS4210_EXT_GIC_DIST_BASE_ADDR   0x10490000
+
+/* Combiner */
+#define EXYNOS4210_EXT_COMBINER_BASE_ADDR   0x10440000
+#define EXYNOS4210_INT_COMBINER_BASE_ADDR   0x10448000
+
+/* SD/MMC host controllers SFR base addresses */
+#define EXYNOS4210_SDHC0_BASE_ADDR          0x12510000
+#define EXYNOS4210_SDHC1_BASE_ADDR          0x12520000
+#define EXYNOS4210_SDHC2_BASE_ADDR          0x12530000
+#define EXYNOS4210_SDHC3_BASE_ADDR          0x12540000
+
+/* PMU SFR base address */
+#define EXYNOS4210_PMU_BASE_ADDR            0x10020000
+
+/* Display controllers (FIMD) */
+#define EXYNOS4210_FIMD0_BASE_ADDR          0x11C00000
+#define EXYNOS4210_FIMD1_BASE_ADDR          0x12000000
+
+/* MALI400 (G3D) */
+#define EXYNOS4210_G3D_BASE_ADDR            0x13000000
+#define EXYNOS4210_G3D_PIXEL_PROC_0_IRQ     0
+#define EXYNOS4210_G3D_PIXEL_PROC_1_IRQ     1
+#define EXYNOS4210_G3D_PIXEL_PROC_2_IRQ     2
+#define EXYNOS4210_G3D_PIXEL_PROC_3_IRQ     3
+#define EXYNOS4210_G3D_GEOM_PROC_IRQ        4
+#define EXYNOS4210_G3D_PMU_IRQ              5
+#define EXYNOS4210_G3D_PPMMU0_IRQ           0
+#define EXYNOS4210_G3D_PPMMU1_IRQ           1
+#define EXYNOS4210_G3D_PPMMU2_IRQ           2
+#define EXYNOS4210_G3D_PPMMU3_IRQ           3
+#define EXYNOS4210_G3D_GPMMU_IRQ            4
+
+/* PPMU */
+#define EXYNOS4210_PPMU_CPU_BASE_ADDR       0x106C0000
+/* DMC */
+#define EXYNOS4210_DMC0_BASE_ADDR           0x10400000
+#define EXYNOS4210_DMC1_BASE_ADDR           0x10410000
+
+/* I2S */
+#define EXYNOS4210_I2S0_BASE_ADDR           0x03830000
+
+/* VirtIO BLK */
+#define EXYNOS4210_VIRTIO_BLK_BASE_ADDR     0x10AD0000
+/* VirtIO NET */
+#define EXYNOS4210_VIRTIO_NET_BASE_ADDR     0x10AC0000
+
+/* pl050 ps/2 interface */
+#define EXYNOS4210_PL050_BASE_ADDR          0x12E30000
+
+static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
+                                    0x09, 0x00, 0x00, 0x00 };
+
+void maru_arm_write_secondary(CPUARMState *env,
+        const struct arm_boot_info *info)
+{
+    int n;
+    uint32_t smpboot[] = {
+        0xe59f3024, /* ldr r3, External gic_cpu_if */
+        0xe59f2024, /* ldr r2, Internal gic_cpu_if */
+        0xe59f0024, /* ldr r0, startaddr */
+        0xe3a01001, /* mov r1, #1 */
+        0xe5821000, /* str r1, [r2] */
+        0xe5831000, /* str r1, [r3] */
+        0xe320f003, /* wfi */
+        0xe5901000, /* ldr     r1, [r0] */
+        0xe1110001, /* tst     r1, r1 */
+        0x0afffffb, /* beq     <wfi> */
+        0xe12fff11, /* bx      r1 */
+        EXYNOS4210_EXT_GIC_CPU_BASE_ADDR,
+        0,          /* gic_cpu_if: base address of Internal GIC CPU interface */
+        0           /* bootreg: Boot register address is held here */
+    };
+    smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
+    smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
+    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+        smpboot[n] = tswap32(smpboot[n]);
+    }
+    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
+                       info->smp_loader_start);
+}
+
+Exynos4210State *maru_arm_init(MemoryRegion *system_mem,
+        unsigned long ram_size)
+{
+    qemu_irq cpu_irq[4];
+    int n;
+    Exynos4210State *s = g_new(Exynos4210State, 1);
+    qemu_irq *irqp;
+    qemu_irq gate_irq[EXYNOS4210_IRQ_GATE_NINPUTS];
+    unsigned long mem_size;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+
+    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
+        s->env[n] = cpu_init("cortex-a9");
+        if (!s->env[n]) {
+            fprintf(stderr, "Unable to find CPU %d definition\n", n);
+            exit(1);
+        }
+        /* Create PIC controller for each processor instance */
+        irqp = arm_pic_init_cpu(s->env[n]);
+
+        /*
+         * Get GICs gpio_in cpu_irq to connect a combiner to them later.
+         * Use only IRQ for a while.
+         */
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+    }
+
+    /*** IRQs ***/
+
+    s->irq_table = exynos4210_init_irq(&s->irqs);
+
+    /* IRQ Gate */
+    dev = qdev_create(NULL, "exynos4210.irq_gate");
+    qdev_prop_set_uint32(dev, "n_out", EXYNOS4210_NCPUS);
+    qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS);
+    qdev_init_nofail(dev);
+    /* Get IRQ Gate input in gate_irq */
+    for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) {
+        gate_irq[n] = qdev_get_gpio_in(dev, n);
+    }
+    busdev = sysbus_from_qdev(dev);
+    /* Connect IRQ Gate output to cpu_irq */
+    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+
+    /* Private memory region and Internal GIC */
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
+    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
+        sysbus_connect_irq(busdev, n, gate_irq[n * 4]);
+    }
+    for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
+        s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    /* Cache controller */
+    sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
+
+    /* External GIC */
+    dev = qdev_create(NULL, "exynos4210.gic");
+    qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    /* Map CPU interface */
+    sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR);
+    /* Map Distributer interface */
+    sysbus_mmio_map(busdev, 1, EXYNOS4210_EXT_GIC_DIST_BASE_ADDR);
+    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
+        sysbus_connect_irq(busdev, n, gate_irq[n * 4 + 1]);
+    }
+    for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
+        s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    /* Internal Interrupt Combiner */
+    dev = qdev_create(NULL, "exynos4210.combiner");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
+        sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]);
+    }
+    exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
+    sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
+
+    /* External Interrupt Combiner */
+    dev = qdev_create(NULL, "exynos4210.combiner");
+    qdev_prop_set_uint32(dev, "external", 1);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
+        sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]);
+    }
+    exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
+    sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
+
+    /* Initialize board IRQs. */
+    exynos4210_init_board_irqs(&s->irqs);
+
+    /*** Memory ***/
+
+    /* Chip-ID and OMR */
+    memory_region_init_ram_ptr(&s->chipid_mem, "exynos4210.chipid",
+            sizeof(chipid_and_omr), chipid_and_omr);
+    memory_region_set_readonly(&s->chipid_mem, true);
+    memory_region_add_subregion(system_mem, EXYNOS4210_CHIPID_ADDR,
+                                &s->chipid_mem);
+
+    /* Internal ROM */
+    memory_region_init_ram(&s->irom_mem, "exynos4210.irom",
+                           EXYNOS4210_IROM_SIZE);
+    memory_region_set_readonly(&s->irom_mem, true);
+    memory_region_add_subregion(system_mem, EXYNOS4210_IROM_BASE_ADDR,
+                                &s->irom_mem);
+    /* mirror of iROM */
+    memory_region_init_alias(&s->irom_alias_mem, "exynos4210.irom_alias",
+                             &s->irom_mem,
+                             EXYNOS4210_IROM_BASE_ADDR,
+                             EXYNOS4210_IROM_SIZE);
+    memory_region_set_readonly(&s->irom_alias_mem, true);
+    memory_region_add_subregion(system_mem, EXYNOS4210_IROM_MIRROR_BASE_ADDR,
+                                &s->irom_alias_mem);
+
+    /* Internal RAM */
+    memory_region_init_ram(&s->iram_mem, "exynos4210.iram",
+                           EXYNOS4210_IRAM_SIZE);
+    vmstate_register_ram_global(&s->iram_mem);
+    memory_region_add_subregion(system_mem, EXYNOS4210_IRAM_BASE_ADDR,
+                                &s->iram_mem);
+
+    /* DRAM */
+    mem_size = ram_size;
+    if (mem_size > EXYNOS4210_DRAM_MAX_SIZE) {
+        memory_region_init_ram(&s->dram1_mem, "exynos4210.dram1",
+                mem_size - EXYNOS4210_DRAM_MAX_SIZE);
+        vmstate_register_ram_global(&s->dram1_mem);
+        memory_region_add_subregion(system_mem, EXYNOS4210_DRAM1_BASE_ADDR,
+                &s->dram1_mem);
+        mem_size = EXYNOS4210_DRAM_MAX_SIZE;
+    }
+    memory_region_init_ram(&s->dram0_mem, "exynos4210.dram0", mem_size);
+    vmstate_register_ram_global(&s->dram0_mem);
+    memory_region_add_subregion(system_mem, EXYNOS4210_DRAM0_BASE_ADDR,
+            &s->dram0_mem);
+
+    /* Audio Subsystem Internal Memory */
+    memory_region_init_ram(&s->audss_intmem, "exynos4210.audss",
+                           EXYNOS4210_AUDSS_INTMEM_SIZE);
+    vmstate_register_ram_global(&s->audss_intmem);
+    memory_region_add_subregion(system_mem, EXYNOS4210_AUDSS_INTMEM_BASE_ADDR,
+                                &s->audss_intmem);
+
+    /*** Clock devices ***/
+
+    /* PMU. Must be initialized before CMU.
+     * The only reason of existence at the moment is that secondary CPU boot
+     * loader uses PMU INFORM5 register as a holding pen.
+     */
+    sysbus_create_simple("maru_arm.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
+
+    /* CMUs */
+    exynos4210_cmu_create(EXYNOS4210_CMU_LEFTBUS_BASE_ADDR,
+                                                       EXYNOS4210_CMU_LEFTBUS);
+    exynos4210_cmu_create(EXYNOS4210_CMU_RIGHTBUS_BASE_ADDR,
+                                                      EXYNOS4210_CMU_RIGHTBUS);
+    exynos4210_cmu_create(EXYNOS4210_CMU_TOP_BASE_ADDR, EXYNOS4210_CMU_TOP);
+    exynos4210_cmu_create(EXYNOS4210_CMU_DMC_BASE_ADDR, EXYNOS4210_CMU_DMC);
+    exynos4210_cmu_create(EXYNOS4210_CMU_CPU_BASE_ADDR, EXYNOS4210_CMU_CPU);
+
+    /* PWM */
+    sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
+            s->irq_table[exynos4210_get_irq(22, 0)],
+            s->irq_table[exynos4210_get_irq(22, 1)],
+            s->irq_table[exynos4210_get_irq(22, 2)],
+            s->irq_table[exynos4210_get_irq(22, 3)],
+            s->irq_table[exynos4210_get_irq(22, 4)],
+            NULL);
+
+    /* RTC */
+    sysbus_create_varargs("exynos4210.rtc", EXYNOS4210_RTC_BASE_ADDR,
+            s->irq_table[exynos4210_get_irq(23, 0)],
+            s->irq_table[exynos4210_get_irq(23, 1)],
+            NULL);
+
+    /* Multi Core Timer */
+    dev = qdev_create(NULL, "exynos4210.mct");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    for (n = 0; n < 4; n++) {
+        /* Connect global timer interrupts to Combiner gpio_in */
+        sysbus_connect_irq(busdev, n,
+                s->irq_table[exynos4210_get_irq(1, 4 + n)]);
+    }
+    /* Connect local timer interrupts to Combiner gpio_in */
+    sysbus_connect_irq(busdev, 4,
+            s->irq_table[exynos4210_get_irq(51, 0)]);
+    sysbus_connect_irq(busdev, 5,
+            s->irq_table[exynos4210_get_irq(35, 3)]);
+    sysbus_mmio_map(busdev, 0, EXYNOS4210_MCT_BASE_ADDR);
+
+    /*** I2C ***/
+    for (n = 0; n < EXYNOS4210_I2C_NUMBER; n++) {
+        uint32_t addr = EXYNOS4210_I2C_BASE_ADDR + EXYNOS4210_I2C_SHIFT * n;
+        qemu_irq i2c_irq;
+
+        if (n < 8) {
+            i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_I2C_INTG, n)];
+        } else {
+            i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_HDMI_INTG, 1)];
+        }
+
+        dev = qdev_create(NULL, "exynos4210.i2c");
+        qdev_init_nofail(dev);
+        busdev = sysbus_from_qdev(dev);
+        sysbus_connect_irq(busdev, 0, i2c_irq);
+        sysbus_mmio_map(busdev, 0, addr);
+        s->i2c_if[n] = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
+    }
+
+    /*** UARTs ***/
+    exynos4210_uart_create(EXYNOS4210_UART0_BASE_ADDR,
+                           EXYNOS4210_UART0_FIFO_SIZE, 0, NULL,
+                    s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 0)]);
+
+    exynos4210_uart_create(EXYNOS4210_UART1_BASE_ADDR,
+                           EXYNOS4210_UART1_FIFO_SIZE, 1, NULL,
+                    s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 1)]);
+
+    exynos4210_uart_create(EXYNOS4210_UART2_BASE_ADDR,
+                           EXYNOS4210_UART2_FIFO_SIZE, 2, NULL,
+                    s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 2)]);
+
+    exynos4210_uart_create(EXYNOS4210_UART3_BASE_ADDR,
+                           EXYNOS4210_UART3_FIFO_SIZE, 3, NULL,
+                    s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 3)]);
+
+
+    /*** Display controller (FIMD) ***/
+    sysbus_create_varargs("exynos4210.fimd", EXYNOS4210_FIMD0_BASE_ADDR,
+            s->irq_table[exynos4210_get_irq(11, 0)],
+            s->irq_table[exynos4210_get_irq(11, 1)],
+            s->irq_table[exynos4210_get_irq(11, 2)],
+            NULL);
+
+    /* I2S0 */
+    s->i2s_bus[0] = exynos4210_i2s_bus_new("exynos4210.i2s",
+                                 EXYNOS4210_I2S0_BASE_ADDR,
+                                 s->irqs.ext_gic_irq[97]);
+
+    sysbus_create_simple(VIRTIO_MMIO_TRANSPORT, EXYNOS4210_VIRTIO_BLK_BASE_ADDR,
+            s->irq_table[exynos4210_get_irq(37, 3)]);
+    sysbus_create_simple(VIRTIO_MMIO_TRANSPORT, EXYNOS4210_VIRTIO_NET_BASE_ADDR,
+            s->irq_table[exynos4210_get_irq(37, 2)]);
+
+    /* PL050 PS/2 if keyboard */
+    sysbus_create_simple("pl050_keyboard", EXYNOS4210_PL050_BASE_ADDR,
+               s->irq_table[exynos4210_get_irq(28, 2)]);
+
+    return s;
+}
diff --git a/tizen/src/hw/maru_arm.h b/tizen/src/hw/maru_arm.h
new file mode 100644 (file)
index 0000000..8cbe76a
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  Samsung Maru ARM SoC emulation
+ *
+ *  Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *    Evgeny Voevodin <e.voevodin@samsung.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MARU_ARM_H_
+#define MARU_ARM_H_
+
+#include "qemu-common.h"
+#include "memory.h"
+#include "exynos4210.h"
+
+void maru_arm_write_secondary(CPUARMState *env,
+        const struct arm_boot_info *info);
+
+Exynos4210State *maru_arm_init(MemoryRegion *system_mem,
+        unsigned long ram_size);
+
+#endif /* MARU_ARM_H_ */
diff --git a/tizen/src/hw/maru_arm_board.c b/tizen/src/hw/maru_arm_board.c
new file mode 100644 (file)
index 0000000..c0d5b34
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * TIZEN ARM base board
+ *
+ * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
+ *
+ * Based on maru_board.c, exynos4210.c and exynos4210_boards.c
+ *
+ * Author:
+ *  Evgeny Voevodin <e.voevodin@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+
+#include "boards.h"
+#include "arm-misc.h"
+#include "sysbus.h"
+#include "pci.h"
+#include "maru_arm.h"
+#include "i2c.h"
+#include "exec-memory.h"
+
+#undef DEBUG
+//#define DEBUG
+#ifdef DEBUG
+    #undef PRINT_DEBUG
+    #define  PRINT_DEBUG(fmt, args...) \
+        do { \
+            fprintf(stderr, "  [%s:%d]   "fmt, __func__, __LINE__, ##args); \
+        } while (0)
+#else
+    #define  PRINT_DEBUG(fmt, args...)  do {} while (0)
+#endif
+
+#ifndef DEBUG_LOG_PATH
+#define DEBUG_LOG_PATH              "./debug.log"
+#endif
+
+#define EXYNOS4210_WM8994_ADDR      0x1A
+
+int codec_init(PCIBus *bus);
+int maru_camera_pci_init(PCIBus *bus);
+
+static int maru_arm_board_id = 0xF3B;
+static int maru_arm_board_smp_bootreg_addr = EXYNOS4210_SECOND_CPU_BOOTREG;
+static unsigned long maru_arm_board_ram_size = 0x40000000;
+
+static struct arm_boot_info maru_arm_board_binfo = {
+    .loader_start     = EXYNOS4210_BASE_BOOT_ADDR,
+    .smp_loader_start = EXYNOS4210_SMP_BOOT_ADDR,
+    .nb_cpus          = EXYNOS4210_NCPUS,
+    .write_secondary_boot = maru_arm_write_secondary,
+};
+
+static Exynos4210State *maru_arm_board_init_common(
+        const char *kernel_filename,
+        const char *kernel_cmdline,
+        const char *initrd_filename)
+{
+    maru_arm_board_binfo.ram_size = maru_arm_board_ram_size;
+    maru_arm_board_binfo.board_id = maru_arm_board_id;
+    maru_arm_board_binfo.smp_bootreg_addr = maru_arm_board_smp_bootreg_addr;
+    maru_arm_board_binfo.kernel_filename = kernel_filename;
+    maru_arm_board_binfo.initrd_filename = initrd_filename;
+    maru_arm_board_binfo.kernel_cmdline = kernel_cmdline;
+    maru_arm_board_binfo.gic_cpu_if_addr =
+                        EXYNOS4210_SMP_PRIVATE_BASE_ADDR + 0x100;
+
+    PRINT_DEBUG("\n ram_size: %luMiB [0x%08lx]\n"
+            " kernel_filename: %s\n"
+            " kernel_cmdline: %s\n"
+            " initrd_filename: %s\n",
+            exynos4_board_ram_size[board_type] / 1048576,
+            exynos4_board_ram_size[board_type],
+            kernel_filename,
+            kernel_cmdline,
+            initrd_filename);
+
+    return maru_arm_init(get_system_memory(), maru_arm_board_ram_size);
+}
+
+static void maru_arm_machine_init(ram_addr_t ram_size,
+                        const char *boot_device,
+                        const char *kernel_filename,
+                        const char *kernel_cmdline,
+                        const char *initrd_filename,
+                        const char *cpu_model)
+{
+    Exynos4210State *s;
+    DeviceState *dev, *i2c_dev;
+    PCIBus *pci_bus;
+
+    s = maru_arm_board_init_common(kernel_filename,
+                kernel_cmdline, initrd_filename);
+
+    /* WM8994 */
+    i2c_dev = i2c_create_slave(s->i2c_if[1], "wm8994", EXYNOS4210_WM8994_ADDR);
+
+    /* Audio */
+    dev = qdev_create(s->i2s_bus[0], "exynos4210.audio");
+    qdev_prop_set_ptr(dev, "wm8994", i2c_dev);
+    qdev_init_nofail(dev);
+
+    /* PCI config */
+    dev = qdev_create(NULL, "tizen_vpci");
+    s->vpci_bus = sysbus_from_qdev(dev);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(s->vpci_bus, 0, EXYNOS4210_VPCI_CFG_BASE_ADDR);
+    sysbus_connect_irq(s->vpci_bus, 0, s->irq_table[exynos4210_get_irq(38, 0)]);
+    sysbus_connect_irq(s->vpci_bus, 1, s->irq_table[exynos4210_get_irq(38, 1)]);
+    sysbus_connect_irq(s->vpci_bus, 2, s->irq_table[exynos4210_get_irq(38, 2)]);
+    sysbus_connect_irq(s->vpci_bus, 3, s->irq_table[exynos4210_get_irq(38, 3)]);
+    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
+
+    pci_create_simple(pci_bus, -1, "pci-ohci");
+    maru_camera_pci_init(pci_bus);
+    codec_init(pci_bus);
+
+    arm_load_kernel(first_cpu, &maru_arm_board_binfo);
+}
+
+static void maru_common_init(ram_addr_t ram_size,
+                        const char *boot_device,
+                        const char *kernel_filename,
+                        const char *kernel_cmdline,
+                        const char *initrd_filename,
+                        const char *cpu_model)
+{
+// prepare for universal virtual board...
+#if defined(TARGET_I386)
+#elif defined(TARGET_ARM)
+#endif
+}
+static void maru_arm_board_init(ram_addr_t ram_size,
+                        const char *boot_device,
+                        const char *kernel_filename,
+                        const char *kernel_cmdline,
+                        const char *initrd_filename,
+                        const char *cpu_model)
+{
+    maru_arm_machine_init(ram_size, boot_device, kernel_filename,
+                        kernel_cmdline, initrd_filename, cpu_model);
+    maru_common_init(ram_size, boot_device, kernel_filename,
+                        kernel_cmdline, initrd_filename, cpu_model);
+}
+
+static QEMUMachine maru_arm_machine = {
+    .name = "maru-arm-machine",
+    .desc = "maru board(ARM)",
+    .init = maru_arm_board_init,
+    .max_cpus = 255,
+};
+
+static void maru_machine_init(void)
+{
+#if defined(TARGET_ARM)
+    qemu_register_machine(&maru_arm_machine);
+#else
+#error
+#endif
+}
+
+machine_init(maru_machine_init);
diff --git a/tizen/src/hw/maru_arm_pmu.c b/tizen/src/hw/maru_arm_pmu.c
new file mode 100644 (file)
index 0000000..4647d4e
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+ *  Tizen Power Management Unit (PMU) Emulation
+ *
+ *  Based on exynos4210_pmu.c
+ *  Copyright (C) 2011 Samsung Electronics Co Ltd.
+ *    Evgeny Voevodin <e.voevodin@samsung.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This model implements PMU registers just as a bulk of memory.
+ * Able to shutdown and restart only.
+ */
+
+#include "sysbus.h"
+#include "sysemu.h"
+#include "ptimer.h"
+
+#ifndef DEBUG_PMU
+#define DEBUG_PMU           0
+#endif
+
+#ifndef DEBUG_PMU_EXTEND
+#define DEBUG_PMU_EXTEND    0
+#endif
+
+#if DEBUG_PMU
+#define  PRINT_DEBUG(fmt, args...)  \
+        do { \
+            fprintf(stderr, "  [%s:%d]   "fmt, __func__, __LINE__, ##args); \
+        } while (0)
+
+#if DEBUG_PMU_EXTEND
+#define  PRINT_DEBUG_EXTEND(fmt, args...) \
+        do { \
+            fprintf(stderr, "  [%s:%d]   "fmt, __func__, __LINE__, ##args); \
+        } while (0)
+#else
+#define  PRINT_DEBUG_EXTEND(fmt, args...)  do {} while (0)
+#endif /* EXTEND */
+
+#else
+#define  PRINT_DEBUG(fmt, args...)   do {} while (0)
+#define  PRINT_DEBUG_EXTEND(fmt, args...)  do {} while (0)
+#endif
+
+#define  POWER_OFF_TIMER_FREQ   24000000
+
+/*
+ *  Offsets for PMU registers
+ */
+#define OM_STAT                  0x0000 /* OM status register */
+#define RTC_CLKO_SEL             0x000C /* Controls RTCCLKOUT */
+#define GNSS_RTC_OUT_CTRL        0x0010 /* Controls GNSS_RTC_OUT */
+/* Decides whether system-level low-power mode is used. */
+#define SYSTEM_POWER_DOWN_CTRL   0x0200
+/* Sets control options for CENTRAL_SEQ */
+#define SYSTEM_POWER_DOWN_OPTION 0x0208
+#define SWRESET                  0x0400 /* Generate software reset */
+#define RST_STAT                 0x0404 /* Reset status register */
+#define WAKEUP_STAT              0x0600 /* Wakeup status register  */
+#define EINT_WAKEUP_MASK         0x0604 /* Configure External INTerrupt mask */
+#define WAKEUP_MASK              0x0608 /* Configure wakeup source mask */
+#define HDMI_PHY_CONTROL         0x0700 /* HDMI PHY control register */
+#define USBDEVICE_PHY_CONTROL    0x0704 /* USB Device PHY control register */
+#define USBHOST_PHY_CONTROL      0x0708 /* USB HOST PHY control register */
+#define DAC_PHY_CONTROL          0x070C /* DAC control register  */
+#define MIPI_PHY0_CONTROL        0x0710 /* MIPI PHY control register */
+#define MIPI_PHY1_CONTROL        0x0714 /* MIPI PHY control register */
+#define ADC_PHY_CONTROL          0x0718 /* TS-ADC control register */
+#define PCIe_PHY_CONTROL         0x071C /* TS-PCIe control register */
+#define SATA_PHY_CONTROL         0x0720 /* TS-SATA control register */
+#define INFORM0                  0x0800 /* Information register 0  */
+#define INFORM1                  0x0804 /* Information register 1  */
+#define INFORM2                  0x0808 /* Information register 2  */
+#define INFORM3                  0x080C /* Information register 3  */
+#define INFORM4                  0x0810 /* Information register 4  */
+#define INFORM5                  0x0814 /* Information register 5  */
+#define INFORM6                  0x0818 /* Information register 6  */
+#define INFORM7                  0x081C /* Information register 7  */
+#define PMU_DEBUG                0x0A00 /* PMU debug register */
+/* Registers to set system-level low-power option */
+#define ARM_CORE0_SYS_PWR_REG              0x1000
+#define ARM_CORE1_SYS_PWR_REG              0x1010
+#define ARM_COMMON_SYS_PWR_REG             0x1080
+#define ARM_CPU_L2_0_SYS_PWR_REG           0x10C0
+#define ARM_CPU_L2_1_SYS_PWR_REG           0x10C4
+#define CMU_ACLKSTOP_SYS_PWR_REG           0x1100
+#define CMU_SCLKSTOP_SYS_PWR_REG           0x1104
+#define CMU_RESET_SYS_PWR_REG              0x110C
+#define APLL_SYSCLK_SYS_PWR_REG            0x1120
+#define MPLL_SYSCLK_SYS_PWR_REG            0x1124
+#define VPLL_SYSCLK_SYS_PWR_REG            0x1128
+#define EPLL_SYSCLK_SYS_PWR_REG            0x112C
+#define CMU_CLKSTOP_GPS_ALIVE_SYS_PWR_REG  0x1138
+#define CMU_RESET_GPS_ALIVE_SYS_PWR_REG    0x113C
+#define CMU_CLKSTOP_CAM_SYS_PWR_REG        0x1140
+#define CMU_CLKSTOP_TV_SYS_PWR_REG         0x1144
+#define CMU_CLKSTOP_MFC_SYS_PWR_REG        0x1148
+#define CMU_CLKSTOP_G3D_SYS_PWR_REG        0x114C
+#define CMU_CLKSTOP_LCD0_SYS_PWR_REG       0x1150
+#define CMU_CLKSTOP_LCD1_SYS_PWR_REG       0x1154
+#define CMU_CLKSTOP_MAUDIO_SYS_PWR_REG     0x1158
+#define CMU_CLKSTOP_GPS_SYS_PWR_REG        0x115C
+#define CMU_RESET_CAM_SYS_PWR_REG          0x1160
+#define CMU_RESET_TV_SYS_PWR_REG           0x1164
+#define CMU_RESET_MFC_SYS_PWR_REG          0x1168
+#define CMU_RESET_G3D_SYS_PWR_REG          0x116C
+#define CMU_RESET_LCD0_SYS_PWR_REG         0x1170
+#define CMU_RESET_LCD1_SYS_PWR_REG         0x1174
+#define CMU_RESET_MAUDIO_SYS_PWR_REG       0x1178
+#define CMU_RESET_GPS_SYS_PWR_REG          0x117C
+#define TOP_BUS_SYS_PWR_REG                0x1180
+#define TOP_RETENTION_SYS_PWR_REG          0x1184
+#define TOP_PWR_SYS_PWR_REG                0x1188
+#define LOGIC_RESET_SYS_PWR_REG            0x11A0
+#define OneNANDXL_MEM_SYS_PWR_REG          0x11C0
+#define MODEMIF_MEM_SYS_PWR_REG            0x11C4
+#define USBDEVICE_MEM_SYS_PWR_REG          0x11CC
+#define SDMMC_MEM_SYS_PWR_REG              0x11D0
+#define CSSYS_MEM_SYS_PWR_REG              0x11D4
+#define SECSS_MEM_SYS_PWR_REG              0x11D8
+#define PCIe_MEM_SYS_PWR_REG               0x11E0
+#define SATA_MEM_SYS_PWR_REG               0x11E4
+#define PAD_RETENTION_DRAM_SYS_PWR_REG     0x1200
+#define PAD_RETENTION_MAUDIO_SYS_PWR_REG   0x1204
+#define PAD_RETENTION_GPIO_SYS_PWR_REG     0x1220
+#define PAD_RETENTION_UART_SYS_PWR_REG     0x1224
+#define PAD_RETENTION_MMCA_SYS_PWR_REG     0x1228
+#define PAD_RETENTION_MMCB_SYS_PWR_REG     0x122C
+#define PAD_RETENTION_EBIA_SYS_PWR_REG     0x1230
+#define PAD_RETENTION_EBIB_SYS_PWR_REG     0x1234
+#define PAD_ISOLATION_SYS_PWR_REG          0x1240
+#define PAD_ALV_SEL_SYS_PWR_REG            0x1260
+#define XUSBXTI_SYS_PWR_REG                0x1280
+#define XXTI_SYS_PWR_REG                   0x1284
+#define EXT_REGULATOR_SYS_PWR_REG          0x12C0
+#define GPIO_MODE_SYS_PWR_REG              0x1300
+#define GPIO_MODE_MAUDIO_SYS_PWR_REG       0x1340
+#define CAM_SYS_PWR_REG                    0x1380
+#define TV_SYS_PWR_REG                     0x1384
+#define MFC_SYS_PWR_REG                    0x1388
+#define G3D_SYS_PWR_REG                    0x138C
+#define LCD0_SYS_PWR_REG                   0x1390
+#define LCD1_SYS_PWR_REG                   0x1394
+#define MAUDIO_SYS_PWR_REG                 0x1398
+#define GPS_SYS_PWR_REG                    0x139C
+#define GPS_ALIVE_SYS_PWR_REG              0x13A0
+#define ARM_CORE0_CONFIGURATION 0x2000 /* Configure power mode of ARM_CORE0 */
+#define ARM_CORE0_STATUS        0x2004 /* Check power mode of ARM_CORE0 */
+#define ARM_CORE0_OPTION        0x2008 /* Sets control options for ARM_CORE0 */
+#define ARM_CORE1_CONFIGURATION 0x2080 /* Configure power mode of ARM_CORE1 */
+#define ARM_CORE1_STATUS        0x2084 /* Check power mode of ARM_CORE1 */
+#define ARM_CORE1_OPTION        0x2088 /* Sets control options for ARM_CORE0 */
+#define ARM_COMMON_OPTION       0x2408 /* Sets control options for ARM_COMMON */
+/* Configure power mode of ARM_CPU_L2_0 */
+#define ARM_CPU_L2_0_CONFIGURATION 0x2600
+#define ARM_CPU_L2_0_STATUS        0x2604 /* Check power mode of ARM_CPU_L2_0 */
+/* Configure power mode of ARM_CPU_L2_1 */
+#define ARM_CPU_L2_1_CONFIGURATION 0x2620
+#define ARM_CPU_L2_1_STATUS        0x2624 /* Check power mode of ARM_CPU_L2_1 */
+/* Sets control options for PAD_RETENTION_MAUDIO */
+#define PAD_RETENTION_MAUDIO_OPTION 0x3028
+/* Sets control options for PAD_RETENTION_GPIO */
+#define PAD_RETENTION_GPIO_OPTION   0x3108
+/* Sets control options for PAD_RETENTION_UART */
+#define PAD_RETENTION_UART_OPTION   0x3128
+/* Sets control options for PAD_RETENTION_MMCA */
+#define PAD_RETENTION_MMCA_OPTION   0x3148
+/* Sets control options for PAD_RETENTION_MMCB */
+#define PAD_RETENTION_MMCB_OPTION   0x3168
+/* Sets control options for PAD_RETENTION_EBIA */
+#define PAD_RETENTION_EBIA_OPTION   0x3188
+/* Sets control options for PAD_RETENTION_EBIB */
+#define PAD_RETENTION_EBIB_OPTION   0x31A8
+#define PS_HOLD_CONTROL         0x330C /* PS_HOLD control register */
+#define XUSBXTI_CONFIGURATION   0x3400 /* Configure the pad of XUSBXTI */
+#define XUSBXTI_STATUS          0x3404 /* Check the pad of XUSBXTI */
+/* Sets time required for XUSBXTI to be stabilized */
+#define XUSBXTI_DURATION        0x341C
+#define XXTI_CONFIGURATION      0x3420 /* Configure the pad of XXTI */
+#define XXTI_STATUS             0x3424 /* Check the pad of XXTI */
+/* Sets time required for XXTI to be stabilized */
+#define XXTI_DURATION           0x343C
+/* Sets time required for EXT_REGULATOR to be stabilized */
+#define EXT_REGULATOR_DURATION  0x361C
+#define CAM_CONFIGURATION       0x3C00 /* Configure power mode of CAM */
+#define CAM_STATUS              0x3C04 /* Check power mode of CAM */
+#define CAM_OPTION              0x3C08 /* Sets control options for CAM */
+#define TV_CONFIGURATION        0x3C20 /* Configure power mode of TV */
+#define TV_STATUS               0x3C24 /* Check power mode of TV */
+#define TV_OPTION               0x3C28 /* Sets control options for TV */
+#define MFC_CONFIGURATION       0x3C40 /* Configure power mode of MFC */
+#define MFC_STATUS              0x3C44 /* Check power mode of MFC */
+#define MFC_OPTION              0x3C48 /* Sets control options for MFC */
+#define G3D_CONFIGURATION       0x3C60 /* Configure power mode of G3D */
+#define G3D_STATUS              0x3C64 /* Check power mode of G3D */
+#define G3D_OPTION              0x3C68 /* Sets control options for G3D */
+#define LCD0_CONFIGURATION      0x3C80 /* Configure power mode of LCD0 */
+#define LCD0_STATUS             0x3C84 /* Check power mode of LCD0 */
+#define LCD0_OPTION             0x3C88 /* Sets control options for LCD0 */
+#define LCD1_CONFIGURATION      0x3CA0 /* Configure power mode of LCD1 */
+#define LCD1_STATUS             0x3CA4 /* Check power mode of LCD1 */
+#define LCD1_OPTION             0x3CA8 /* Sets control options for LCD1 */
+#define GPS_CONFIGURATION       0x3CE0 /* Configure power mode of GPS */
+#define GPS_STATUS              0x3CE4 /* Check power mode of GPS */
+#define GPS_OPTION              0x3CE8 /* Sets control options for GPS */
+#define GPS_ALIVE_CONFIGURATION 0x3D00 /* Configure power mode of GPS */
+#define GPS_ALIVE_STATUS        0x3D04 /* Check power mode of GPS */
+#define GPS_ALIVE_OPTION        0x3D08 /* Sets control options for GPS */
+
+#define EXYNOS4210_PMU_REGS_MEM_SIZE 0x3d0c
+
+typedef struct Exynos4210PmuReg {
+    const char  *name; /* for debug only */
+    uint32_t     offset;
+    uint32_t     reset_value;
+} Exynos4210PmuReg;
+
+static const Exynos4210PmuReg exynos4210_pmu_regs[] = {
+    {"OM_STAT", OM_STAT, 0x00000000},
+    {"RTC_CLKO_SEL", RTC_CLKO_SEL, 0x00000000},
+    {"GNSS_RTC_OUT_CTRL", GNSS_RTC_OUT_CTRL, 0x00000001},
+    {"SYSTEM_POWER_DOWN_CTRL", SYSTEM_POWER_DOWN_CTRL, 0x00010000},
+    {"SYSTEM_POWER_DOWN_OPTION", SYSTEM_POWER_DOWN_OPTION, 0x03030000},
+    {"SWRESET", SWRESET, 0x00000000},
+    {"RST_STAT", RST_STAT, 0x00000000},
+    {"WAKEUP_STAT", WAKEUP_STAT, 0x00000000},
+    {"EINT_WAKEUP_MASK", EINT_WAKEUP_MASK, 0x00000000},
+    {"WAKEUP_MASK", WAKEUP_MASK, 0x00000000},
+    {"HDMI_PHY_CONTROL", HDMI_PHY_CONTROL, 0x00960000},
+    {"USBDEVICE_PHY_CONTROL", USBDEVICE_PHY_CONTROL, 0x00000000},
+    {"USBHOST_PHY_CONTROL", USBHOST_PHY_CONTROL, 0x00000000},
+    {"DAC_PHY_CONTROL", DAC_PHY_CONTROL, 0x00000000},
+    {"MIPI_PHY0_CONTROL", MIPI_PHY0_CONTROL, 0x00000000},
+    {"MIPI_PHY1_CONTROL", MIPI_PHY1_CONTROL, 0x00000000},
+    {"ADC_PHY_CONTROL", ADC_PHY_CONTROL, 0x00000001},
+    {"PCIe_PHY_CONTROL", PCIe_PHY_CONTROL, 0x00000000},
+    {"SATA_PHY_CONTROL", SATA_PHY_CONTROL, 0x00000000},
+    {"INFORM0", INFORM0, 0x00000000},
+    {"INFORM1", INFORM1, 0x00000000},
+    {"INFORM2", INFORM2, 0x00000000},
+    {"INFORM3", INFORM3, 0x00000000},
+    {"INFORM4", INFORM4, 0x00000000},
+    {"INFORM5", INFORM5, 0x00000000},
+    {"INFORM6", INFORM6, 0x00000000},
+    {"INFORM7", INFORM7, 0x00000000},
+    {"PMU_DEBUG", PMU_DEBUG, 0x00000000},
+    {"ARM_CORE0_SYS_PWR_REG", ARM_CORE0_SYS_PWR_REG, 0xFFFFFFFF},
+    {"ARM_CORE1_SYS_PWR_REG", ARM_CORE1_SYS_PWR_REG, 0xFFFFFFFF},
+    {"ARM_COMMON_SYS_PWR_REG", ARM_COMMON_SYS_PWR_REG, 0xFFFFFFFF},
+    {"ARM_CPU_L2_0_SYS_PWR_REG", ARM_CPU_L2_0_SYS_PWR_REG, 0xFFFFFFFF},
+    {"ARM_CPU_L2_1_SYS_PWR_REG", ARM_CPU_L2_1_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_ACLKSTOP_SYS_PWR_REG", CMU_ACLKSTOP_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_SCLKSTOP_SYS_PWR_REG", CMU_SCLKSTOP_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_RESET_SYS_PWR_REG", CMU_RESET_SYS_PWR_REG, 0xFFFFFFFF},
+    {"APLL_SYSCLK_SYS_PWR_REG", APLL_SYSCLK_SYS_PWR_REG, 0xFFFFFFFF},
+    {"MPLL_SYSCLK_SYS_PWR_REG", MPLL_SYSCLK_SYS_PWR_REG, 0xFFFFFFFF},
+    {"VPLL_SYSCLK_SYS_PWR_REG", VPLL_SYSCLK_SYS_PWR_REG, 0xFFFFFFFF},
+    {"EPLL_SYSCLK_SYS_PWR_REG", EPLL_SYSCLK_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_CLKSTOP_GPS_ALIVE_SYS_PWR_REG", CMU_CLKSTOP_GPS_ALIVE_SYS_PWR_REG,
+            0xFFFFFFFF},
+    {"CMU_RESET_GPS_ALIVE_SYS_PWR_REG", CMU_RESET_GPS_ALIVE_SYS_PWR_REG,
+            0xFFFFFFFF},
+    {"CMU_CLKSTOP_CAM_SYS_PWR_REG", CMU_CLKSTOP_CAM_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_CLKSTOP_TV_SYS_PWR_REG", CMU_CLKSTOP_TV_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_CLKSTOP_MFC_SYS_PWR_REG", CMU_CLKSTOP_MFC_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_CLKSTOP_G3D_SYS_PWR_REG", CMU_CLKSTOP_G3D_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_CLKSTOP_LCD0_SYS_PWR_REG", CMU_CLKSTOP_LCD0_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_CLKSTOP_LCD1_SYS_PWR_REG", CMU_CLKSTOP_LCD1_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_CLKSTOP_MAUDIO_SYS_PWR_REG", CMU_CLKSTOP_MAUDIO_SYS_PWR_REG,
+            0xFFFFFFFF},
+    {"CMU_CLKSTOP_GPS_SYS_PWR_REG", CMU_CLKSTOP_GPS_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_RESET_CAM_SYS_PWR_REG", CMU_RESET_CAM_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_RESET_TV_SYS_PWR_REG", CMU_RESET_TV_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_RESET_MFC_SYS_PWR_REG", CMU_RESET_MFC_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_RESET_G3D_SYS_PWR_REG", CMU_RESET_G3D_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_RESET_LCD0_SYS_PWR_REG", CMU_RESET_LCD0_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_RESET_LCD1_SYS_PWR_REG", CMU_RESET_LCD1_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_RESET_MAUDIO_SYS_PWR_REG", CMU_RESET_MAUDIO_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CMU_RESET_GPS_SYS_PWR_REG", CMU_RESET_GPS_SYS_PWR_REG, 0xFFFFFFFF},
+    {"TOP_BUS_SYS_PWR_REG", TOP_BUS_SYS_PWR_REG, 0xFFFFFFFF},
+    {"TOP_RETENTION_SYS_PWR_REG", TOP_RETENTION_SYS_PWR_REG, 0xFFFFFFFF},
+    {"TOP_PWR_SYS_PWR_REG", TOP_PWR_SYS_PWR_REG, 0xFFFFFFFF},
+    {"LOGIC_RESET_SYS_PWR_REG", LOGIC_RESET_SYS_PWR_REG, 0xFFFFFFFF},
+    {"OneNANDXL_MEM_SYS_PWR_REG", OneNANDXL_MEM_SYS_PWR_REG, 0xFFFFFFFF},
+    {"MODEMIF_MEM_SYS_PWR_REG", MODEMIF_MEM_SYS_PWR_REG, 0xFFFFFFFF},
+    {"USBDEVICE_MEM_SYS_PWR_REG", USBDEVICE_MEM_SYS_PWR_REG, 0xFFFFFFFF},
+    {"SDMMC_MEM_SYS_PWR_REG", SDMMC_MEM_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CSSYS_MEM_SYS_PWR_REG", CSSYS_MEM_SYS_PWR_REG, 0xFFFFFFFF},
+    {"SECSS_MEM_SYS_PWR_REG", SECSS_MEM_SYS_PWR_REG, 0xFFFFFFFF},
+    {"PCIe_MEM_SYS_PWR_REG", PCIe_MEM_SYS_PWR_REG, 0xFFFFFFFF},
+    {"SATA_MEM_SYS_PWR_REG", SATA_MEM_SYS_PWR_REG, 0xFFFFFFFF},
+    {"PAD_RETENTION_DRAM_SYS_PWR_REG", PAD_RETENTION_DRAM_SYS_PWR_REG,
+            0xFFFFFFFF},
+    {"PAD_RETENTION_MAUDIO_SYS_PWR_REG", PAD_RETENTION_MAUDIO_SYS_PWR_REG,
+            0xFFFFFFFF},
+    {"PAD_RETENTION_GPIO_SYS_PWR_REG", PAD_RETENTION_GPIO_SYS_PWR_REG,
+            0xFFFFFFFF},
+    {"PAD_RETENTION_UART_SYS_PWR_REG", PAD_RETENTION_UART_SYS_PWR_REG,
+            0xFFFFFFFF},
+    {"PAD_RETENTION_MMCA_SYS_PWR_REG", PAD_RETENTION_MMCA_SYS_PWR_REG,
+            0xFFFFFFFF},
+    {"PAD_RETENTION_MMCB_SYS_PWR_REG", PAD_RETENTION_MMCB_SYS_PWR_REG,
+            0xFFFFFFFF},
+    {"PAD_RETENTION_EBIA_SYS_PWR_REG", PAD_RETENTION_EBIA_SYS_PWR_REG,
+            0xFFFFFFFF},
+    {"PAD_RETENTION_EBIB_SYS_PWR_REG", PAD_RETENTION_EBIB_SYS_PWR_REG,
+            0xFFFFFFFF},
+    {"PAD_ISOLATION_SYS_PWR_REG", PAD_ISOLATION_SYS_PWR_REG, 0xFFFFFFFF},
+    {"PAD_ALV_SEL_SYS_PWR_REG", PAD_ALV_SEL_SYS_PWR_REG, 0xFFFFFFFF},
+    {"XUSBXTI_SYS_PWR_REG", XUSBXTI_SYS_PWR_REG, 0xFFFFFFFF},
+    {"XXTI_SYS_PWR_REG", XXTI_SYS_PWR_REG, 0xFFFFFFFF},
+    {"EXT_REGULATOR_SYS_PWR_REG", EXT_REGULATOR_SYS_PWR_REG, 0xFFFFFFFF},
+    {"GPIO_MODE_SYS_PWR_REG", GPIO_MODE_SYS_PWR_REG, 0xFFFFFFFF},
+    {"GPIO_MODE_MAUDIO_SYS_PWR_REG", GPIO_MODE_MAUDIO_SYS_PWR_REG, 0xFFFFFFFF},
+    {"CAM_SYS_PWR_REG", CAM_SYS_PWR_REG, 0xFFFFFFFF},
+    {"TV_SYS_PWR_REG", TV_SYS_PWR_REG, 0xFFFFFFFF},
+    {"MFC_SYS_PWR_REG", MFC_SYS_PWR_REG, 0xFFFFFFFF},
+    {"G3D_SYS_PWR_REG", G3D_SYS_PWR_REG, 0xFFFFFFFF},
+    {"LCD0_SYS_PWR_REG", LCD0_SYS_PWR_REG, 0xFFFFFFFF},
+    {"LCD1_SYS_PWR_REG", LCD1_SYS_PWR_REG, 0xFFFFFFFF},
+    {"MAUDIO_SYS_PWR_REG", MAUDIO_SYS_PWR_REG, 0xFFFFFFFF},
+    {"GPS_SYS_PWR_REG", GPS_SYS_PWR_REG, 0xFFFFFFFF},
+    {"GPS_ALIVE_SYS_PWR_REG", GPS_ALIVE_SYS_PWR_REG, 0xFFFFFFFF},
+    {"ARM_CORE0_CONFIGURATION", ARM_CORE0_CONFIGURATION, 0x00000003},
+    {"ARM_CORE0_STATUS", ARM_CORE0_STATUS, 0x00030003},
+    {"ARM_CORE0_OPTION", ARM_CORE0_OPTION, 0x01010001},
+    {"ARM_CORE1_CONFIGURATION", ARM_CORE1_CONFIGURATION, 0x00000003},
+    {"ARM_CORE1_STATUS", ARM_CORE1_STATUS, 0x00030003},
+    {"ARM_CORE1_OPTION", ARM_CORE1_OPTION, 0x01010001},
+    {"ARM_COMMON_OPTION", ARM_COMMON_OPTION, 0x00000001},
+    {"ARM_CPU_L2_0_CONFIGURATION", ARM_CPU_L2_0_CONFIGURATION, 0x00000003},
+    {"ARM_CPU_L2_0_STATUS", ARM_CPU_L2_0_STATUS, 0x00000003},
+    {"ARM_CPU_L2_1_CONFIGURATION", ARM_CPU_L2_1_CONFIGURATION, 0x00000003},
+    {"ARM_CPU_L2_1_STATUS", ARM_CPU_L2_1_STATUS, 0x00000003},
+    {"PAD_RETENTION_MAUDIO_OPTION", PAD_RETENTION_MAUDIO_OPTION, 0x00000000},
+    {"PAD_RETENTION_GPIO_OPTION", PAD_RETENTION_GPIO_OPTION, 0x00000000},
+    {"PAD_RETENTION_UART_OPTION", PAD_RETENTION_UART_OPTION, 0x00000000},
+    {"PAD_RETENTION_MMCA_OPTION", PAD_RETENTION_MMCA_OPTION, 0x00000000},
+    {"PAD_RETENTION_MMCB_OPTION", PAD_RETENTION_MMCB_OPTION, 0x00000000},
+    {"PAD_RETENTION_EBIA_OPTION", PAD_RETENTION_EBIA_OPTION, 0x00000000},
+    {"PAD_RETENTION_EBIB_OPTION", PAD_RETENTION_EBIB_OPTION, 0x00000000},
+    {"PS_HOLD_CONTROL", PS_HOLD_CONTROL, 0x00005200},
+    {"XUSBXTI_CONFIGURATION", XUSBXTI_CONFIGURATION, 0x00000001},
+    {"XUSBXTI_STATUS", XUSBXTI_STATUS, 0x00000001},
+    {"XUSBXTI_DURATION", XUSBXTI_DURATION, 0xFFF00000},
+    {"XXTI_CONFIGURATION", XXTI_CONFIGURATION, 0x00000001},
+    {"XXTI_STATUS", XXTI_STATUS, 0x00000001},
+    {"XXTI_DURATION", XXTI_DURATION, 0xFFF00000},
+    {"EXT_REGULATOR_DURATION", EXT_REGULATOR_DURATION, 0xFFF03FFF},
+    {"CAM_CONFIGURATION", CAM_CONFIGURATION, 0x00000007},
+    {"CAM_STATUS", CAM_STATUS, 0x00060007},
+    {"CAM_OPTION", CAM_OPTION, 0x00000001},
+    {"TV_CONFIGURATION", TV_CONFIGURATION, 0x00000007},
+    {"TV_STATUS", TV_STATUS, 0x00060007},
+    {"TV_OPTION", TV_OPTION, 0x00000001},
+    {"MFC_CONFIGURATION", MFC_CONFIGURATION, 0x00000007},
+    {"MFC_STATUS", MFC_STATUS, 0x00060007},
+    {"MFC_OPTION", MFC_OPTION, 0x00000001},
+    {"G3D_CONFIGURATION", G3D_CONFIGURATION, 0x00000007},
+    {"G3D_STATUS", G3D_STATUS, 0x00060007},
+    {"G3D_OPTION", G3D_OPTION, 0x00000001},
+    {"LCD0_CONFIGURATION", LCD0_CONFIGURATION, 0x00000007},
+    {"LCD0_STATUS", LCD0_STATUS, 0x00060007},
+    {"LCD0_OPTION", LCD0_OPTION, 0x00000001},
+    {"LCD1_CONFIGURATION", LCD1_CONFIGURATION, 0x00000007},
+    {"LCD1_STATUS", LCD1_STATUS, 0x00060007},
+    {"LCD1_OPTION", LCD1_OPTION, 0x00000001},
+    {"GPS_CONFIGURATION", GPS_CONFIGURATION, 0x00000007},
+    {"GPS_STATUS", GPS_STATUS, 0x00060007},
+    {"GPS_OPTION", GPS_OPTION, 0x00000001},
+    {"GPS_ALIVE_CONFIGURATION", GPS_ALIVE_CONFIGURATION, 0x00000007},
+    {"GPS_ALIVE_STATUS", GPS_ALIVE_STATUS, 0x00060007},
+    {"GPS_ALIVE_OPTION", GPS_ALIVE_OPTION, 0x00000001},
+};
+
+#define PMU_NUM_OF_REGISTERS     \
+    (sizeof(exynos4210_pmu_regs) / sizeof(Exynos4210PmuReg))
+
+typedef struct Exynos4210PmuState {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t reg[PMU_NUM_OF_REGISTERS];
+
+    ptimer_state *ptimer;
+} Exynos4210PmuState;
+
+static uint64_t exynos4210_pmu_read(void *opaque, target_phys_addr_t offset,
+                                    unsigned size)
+{
+    Exynos4210PmuState *s = (Exynos4210PmuState *)opaque;
+    unsigned i;
+    const Exynos4210PmuReg *reg_p = exynos4210_pmu_regs;
+
+    for (i = 0; i < PMU_NUM_OF_REGISTERS; i++) {
+        if (reg_p->offset == offset) {
+            PRINT_DEBUG_EXTEND("%s [0x%04x] -> 0x%04x\n", reg_p->name,
+                                   (uint32_t)offset, s->reg[i]);
+            return s->reg[i];
+        }
+        reg_p++;
+    }
+    PRINT_DEBUG("QEMU PMU ERROR: bad read offset 0x%04x\n", (uint32_t)offset);
+    return 0;
+}
+
+static void exynos4210_pmu_write(void *opaque, target_phys_addr_t offset,
+                                 uint64_t val, unsigned size)
+{
+    Exynos4210PmuState *s = (Exynos4210PmuState *)opaque;
+    unsigned i;
+    const Exynos4210PmuReg *reg_p = exynos4210_pmu_regs;
+
+    for (i = 0; i < PMU_NUM_OF_REGISTERS; i++) {
+        if (reg_p->offset == offset) {
+            PRINT_DEBUG_EXTEND("%s <0x%04x> <- 0x%04x\n", reg_p->name,
+                    (uint32_t)offset, (uint32_t)val);
+            s->reg[i] = val;
+            break;
+        }
+        reg_p++;
+    }
+
+    switch (offset) {
+    case SYSTEM_POWER_DOWN_CTRL:
+        if (!(val & (1 << 16))) {
+            qemu_system_powerdown_request();
+            return;
+        }
+    case SWRESET:
+        if (val & 1) {
+            qemu_system_reset_request();
+            return;
+        }
+    }
+}
+
+static const MemoryRegionOps exynos4210_pmu_ops = {
+    .read = exynos4210_pmu_read,
+    .write = exynos4210_pmu_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+        .unaligned = false
+    }
+};
+
+static void exynos4210_pmu_reset(DeviceState *dev)
+{
+    Exynos4210PmuState *s =
+            container_of(dev, Exynos4210PmuState, busdev.qdev);
+    unsigned i;
+
+    /* Set default values for registers */
+    for (i = 0; i < PMU_NUM_OF_REGISTERS; i++) {
+        s->reg[i] = exynos4210_pmu_regs[i].reset_value;
+    }
+}
+
+static void maru_arm_powerdown_tick(void *opaque)
+{
+    Exynos4210PmuState *s = opaque;
+    const Exynos4210PmuReg *reg_p = exynos4210_pmu_regs;
+    unsigned i;
+
+    for (i = 0; i < PMU_NUM_OF_REGISTERS; i++) {
+        if (reg_p->offset == SYSTEM_POWER_DOWN_CTRL) {
+            if (s->reg[i] & 0x00010000) {
+                /* Reset value arrived in register. Do not powerdown, we are in
+                 * the process of resetting. */
+                return;
+            }
+        }
+        reg_p++;
+    }
+    qemu_system_shutdown_request();
+}
+
+static void maru_arm_powerdown(void *opaque, int irq, int power_failing)
+{
+    Exynos4210PmuState *s = opaque;
+
+    assert(s != NULL);
+    /* Wait 100 ms */
+    ptimer_set_count(s->ptimer, POWER_OFF_TIMER_FREQ / 100);
+    ptimer_run(s->ptimer, 1);
+}
+
+static int exynos4210_pmu_init(SysBusDevice *dev)
+{
+    Exynos4210PmuState *s = FROM_SYSBUS(Exynos4210PmuState, dev);
+    QEMUBH *bh;
+
+    /* memory mapping */
+    memory_region_init_io(&s->iomem, &exynos4210_pmu_ops, s, "maru_arm.pmu",
+                          EXYNOS4210_PMU_REGS_MEM_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    /* We register powerdown handler here for the purpose to find out
+     * if reset was requested after powerdown. If so, then do reset.
+     * Here we hope that reset request will be set to the moment when
+     * timer allocated in maru_arm_powerdown shoots. */
+    bh = qemu_bh_new(maru_arm_powerdown_tick, s);
+    s->ptimer = ptimer_init(bh);
+    ptimer_set_freq(s->ptimer, POWER_OFF_TIMER_FREQ);
+    qemu_system_powerdown = *qemu_allocate_irqs(maru_arm_powerdown, s, 1);
+
+    return 0;
+}
+
+static const VMStateDescription exynos4210_pmu_vmstate = {
+    .name = "maru_arm.pmu",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(reg, Exynos4210PmuState, PMU_NUM_OF_REGISTERS),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void exynos4210_pmu_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = exynos4210_pmu_init;
+    dc->reset = exynos4210_pmu_reset;
+    dc->vmsd = &exynos4210_pmu_vmstate;
+}
+
+static TypeInfo exynos4210_pmu_info = {
+    .name          = "maru_arm.pmu",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(Exynos4210PmuState),
+    .class_init    = exynos4210_pmu_class_init,
+};
+
+static void exynos4210_pmu_register(void)
+{
+    type_register_static(&exynos4210_pmu_info);
+}
+
+type_init(exynos4210_pmu_register)
diff --git a/tizen/src/hw/maru_arm_vpci.c b/tizen/src/hw/maru_arm_vpci.c
new file mode 100644 (file)
index 0000000..aa0578c
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Samsung Tizen Virtual PCI driver
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *  Vorobiov Stanislav <s.vorobiov@samsung.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "sysbus.h"
+#include "pci.h"
+#include "pci_host.h"
+#include "exec-memory.h"
+
+#define TIZEN_VPCI_VENDOR_ID 0x10ee
+#define TIZEN_VPCI_DEVICE_ID 0x0300
+#define TIZEN_VPCI_CLASS_ID  PCI_CLASS_PROCESSOR_CO
+
+typedef struct {
+    SysBusDevice busdev;
+    qemu_irq irq[4];
+    MemoryRegion mem_config;
+} TizenVPCIState;
+
+static inline uint32_t tizen_vpci_config_addr(target_phys_addr_t addr)
+{
+    return addr & 0xffffff;
+}
+
+static void tizen_vpci_config_write(void *opaque, target_phys_addr_t addr,
+                                 uint64_t val, unsigned size)
+{
+    pci_data_write(opaque, tizen_vpci_config_addr(addr), val, size);
+}
+
+static uint64_t tizen_vpci_config_read(void *opaque, target_phys_addr_t addr,
+                                    unsigned size)
+{
+    uint32_t val;
+    val = pci_data_read(opaque, tizen_vpci_config_addr(addr), size);
+    return val;
+}
+
+static const MemoryRegionOps tizen_vpci_config_ops = {
+    .read = tizen_vpci_config_read,
+    .write = tizen_vpci_config_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int tizen_vpci_map_irq(PCIDevice *d, int irq_num)
+{
+    return irq_num;
+}
+
+static void tizen_vpci_set_irq(void *opaque, int irq_num, int level)
+{
+    qemu_irq *pic = opaque;
+
+    qemu_set_irq(pic[irq_num], level);
+}
+
+static int tizen_vpci_init(SysBusDevice *dev)
+{
+    TizenVPCIState *s = FROM_SYSBUS(TizenVPCIState, dev);
+    PCIBus *bus;
+    int i;
+
+    for (i = 0; i < 4; i++) {
+        sysbus_init_irq(dev, &s->irq[i]);
+    }
+
+    bus = pci_register_bus(&dev->qdev, "pci",
+                           tizen_vpci_set_irq, tizen_vpci_map_irq, s->irq,
+                           get_system_memory(), get_system_io(),
+                           0, 4);
+
+    memory_region_init_io(&s->mem_config, &tizen_vpci_config_ops, bus,
+                          "tizen-vpci-config", 0x1000000);
+    sysbus_init_mmio(dev, &s->mem_config);
+
+    pci_create_simple(bus, -1, "tizen_vpci_host");
+
+    return 0;
+}
+
+static int tizen_vpci_host_init(PCIDevice *d)
+{
+    pci_set_word(d->config + PCI_STATUS,
+         PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_FAST);
+    return 0;
+}
+
+static void tizen_vpci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = tizen_vpci_host_init;
+    k->vendor_id = TIZEN_VPCI_VENDOR_ID;
+    k->device_id = TIZEN_VPCI_DEVICE_ID;
+    k->class_id = TIZEN_VPCI_CLASS_ID;
+}
+
+static TypeInfo tizen_vpci_host_info = {
+    .name          = "tizen_vpci_host",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIDevice),
+    .class_init    = tizen_vpci_host_class_init,
+};
+
+static void tizen_vpci_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = tizen_vpci_init;
+}
+
+static TypeInfo tizen_vpci_info = {
+    .name          = "tizen_vpci",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(TizenVPCIState),
+    .class_init    = tizen_vpci_class_init,
+};
+
+static void tizen_vpci_register_types(void)
+{
+    type_register_static(&tizen_vpci_info);
+    type_register_static(&tizen_vpci_host_info);
+}
+
+type_init(tizen_vpci_register_types)
index beae7937c87239c75a835a0d6562dacf77957ca3..da9d8321cf141f812f252f04c561496ec8fd7e75 100644 (file)
@@ -39,6 +39,13 @@ i2c_bus *maru_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
 
 void resume( void );
 
+#ifdef TARGET_ARM
+static int is_suspended_state( void )
+{
+    return 0;
+}
+#else
 int is_suspended_state( void );
+#endif
 
 #endif /* MARU_PM_H_ */
diff --git a/vl.c b/vl.c
index a184b1bb3642e9aeab1fa5401db167f49fd2b315..9a137b8f628f93c97b19f559d3b29f3841660da3 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -3358,6 +3358,7 @@ int main(int argc, char **argv, char **envp)
     }
 
 #ifndef _WIN32
+#ifdef CONFIG_GL
        if (enable_gl && (gl_acceleration_capability_check () != 0)) {
                enable_gl = 0;
                fprintf (stderr, "Warn: GL acceleration was disabled due to the fail of GL check!\n");
@@ -3380,6 +3381,7 @@ int main(int argc, char **argv, char **envp)
             }
         }
     }
+#endif
 #endif
        
     /* Open the logfile at this point, if necessary. We can't open the logfile