Merge commit 'origin/master' into maemo-test
authorRiku Voipio <riku.voipio@nokia.com>
Thu, 5 Mar 2009 09:14:29 +0000 (11:14 +0200)
committerRiku Voipio <riku.voipio@nokia.com>
Thu, 5 Mar 2009 09:14:29 +0000 (11:14 +0200)
50 files changed:
Makefile.target
cocoa.m
configure
debian/README.Debian [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/cputransp-methods [new file with mode: 0644]
debian/overrides/qemu [new file with mode: 0644]
debian/qemu-user.1 [new file with mode: 0644]
debian/qemu.dirs [new file with mode: 0644]
debian/qemu.doc-base [new file with mode: 0644]
debian/qemu.docs [new file with mode: 0644]
debian/qemu.install [new file with mode: 0644]
debian/qemu.links [new file with mode: 0644]
debian/qemu.manpages [new file with mode: 0644]
debian/rules [new file with mode: 0755]
debian/tundev.c [new file with mode: 0644]
debian/watch [new file with mode: 0644]
hw/beagle.c [new file with mode: 0644]
hw/boards.h
hw/flash.h
hw/i2c.h
hw/nand_bpage.c [new file with mode: 0644]
hw/nseries.c
hw/omap.h
hw/omap1.c
hw/omap2.c
hw/omap3.c [new file with mode: 0644]
hw/omap3_lcd_panel_template.h [new file with mode: 0644]
hw/omap3_mmc.c [new file with mode: 0644]
hw/omap_clk.c
hw/omap_dma.c
hw/omap_dss.c
hw/omap_i2c.c
hw/sd.c
hw/tsc2005.c
hw/twl4030.c [new file with mode: 0644]
linux-user/main.c
linux-user/mmap.c
linux-user/path.c
linux-user/signal.c
linux-user/strace.list
linux-user/syscall.c
linux-user/syscall_defs.h
target-arm/cpu.h
target-arm/helper.c
target-arm/machine.c
target-arm/translate.c

index f33f762..efbb4f8 100644 (file)
@@ -235,8 +235,10 @@ endif
 VPATH+=:$(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)
 CPPFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)
 
+#sbox hack
 ifdef CONFIG_STATIC
-LDFLAGS+=-static
+LDFLAGS+=-static -L/scratchbox/tools/lib
+LIBS+=-lsb -ldl
 endif
 
 ifeq ($(ARCH),i386)
@@ -659,9 +661,10 @@ OBJS+= arm-semi.o
 OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
 OBJS+= pflash_cfi01.o gumstix.o
-OBJS+= zaurus.o ide.o serial.o nand.o ecc.o spitz.o tosa.o tc6393xb.o
-OBJS+= omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o
+OBJS+= zaurus.o ide.o serial.o nand.o nand_bpage.o ecc.o spitz.o tosa.o tc6393xb.o
+OBJS+= omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap3_mmc.o omap_i2c.o
 OBJS+= omap2.o omap_dss.o soc_dma.o
+OBJS+= omap3.o beagle.o twl4030.o
 OBJS+= omap_sx1.o palm.o tsc210x.o
 OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 OBJS+= tsc2005.o bt-hci-csr.o
diff --git a/cocoa.m b/cocoa.m
index 55ff2b4..c5764e9 100644 (file)
--- a/cocoa.m
+++ b/cocoa.m
@@ -229,7 +229,7 @@ int keymap[] =
 */
 };
 
-int cocoa_keycode_to_qemu(int keycode)
+static int cocoa_keycode_to_qemu(int keycode)
 {
     if((sizeof(keymap)/sizeof(int)) <= keycode)
     {
@@ -298,6 +298,11 @@ int cocoa_keycode_to_qemu(int keycode)
     [super dealloc];
 }
 
+- (BOOL) isOpaque
+{
+    return YES;
+}
+
 - (void) drawRect:(NSRect) rect
 {
     COCOA_DEBUG("QemuCocoaView: drawRect\n");
@@ -327,6 +332,7 @@ int cocoa_keycode_to_qemu(int keycode)
             0, //interpolate
             kCGRenderingIntentDefault //intent
         );
+
 // test if host support "CGImageCreateWithImageInRect" at compiletime
 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
         if (CGImageCreateWithImageInRect == NULL) { // test if "CGImageCreateWithImageInRect" is supported on host at runtime
@@ -348,12 +354,9 @@ int cocoa_keycode_to_qemu(int keycode)
                 clipRect.origin.y = (float)screen.height - (rectList[i].origin.y + rectList[i].size.height) / cdy;
                 clipRect.size.width = rectList[i].size.width / cdx;
                 clipRect.size.height = rectList[i].size.height / cdy;
-                clipImageRef = CGImageCreateWithImageInRect(
-                    imageRef,
-                    clipRect
-                );
-                CGContextDrawImage (viewContextRef, cgrect(rectList[i]), clipImageRef);
-                CGImageRelease (clipImageRef);
+                clipImageRef = CGImageCreateWithImageInRect(imageRef, clipRect);
+                CGContextDrawImage(viewContextRef, cgrect(rectList[i]), clipImageRef);
+                CGImageRelease(clipImageRef);
             }
         }
 #endif
@@ -403,7 +406,7 @@ int cocoa_keycode_to_qemu(int keycode)
     } else {
         if (qemu_name)
             [normalWindow setTitle:[NSString stringWithFormat:@"QEMU %s", qemu_name]];
-        [normalWindow setFrame:NSMakeRect([normalWindow frame].origin.x, [normalWindow frame].origin.y - h + screen.height, w, h + [normalWindow frame].size.height - screen.height) display:YES animate:YES];
+        [normalWindow setFrame:NSMakeRect([normalWindow frame].origin.x, [normalWindow frame].origin.y - h + screen.height, w, h + [normalWindow frame].size.height - screen.height) display:YES animate:NO];
     }
     screen.width = w;
     screen.height = h;
@@ -568,12 +571,12 @@ int cocoa_keycode_to_qemu(int keycode)
             if (isAbsoluteEnabled) {
                 if (p.x < 0 || p.x > screen.width || p.y < 0 || p.y > screen.height || ![[self window] isKeyWindow]) {
                     if (isTabletEnabled) { // if we leave the window, deactivate the tablet
-                        [NSCursor unhide];
+                        if (cursor_hide) [NSCursor unhide];
                         isTabletEnabled = FALSE;
                     }
                 } else {
                     if (!isTabletEnabled) { // if we enter the window, activate the tablet
-                        [NSCursor hide];
+                        if (cursor_hide) [NSCursor hide];
                         isTabletEnabled = TRUE;
                     }
                 }
@@ -653,7 +656,7 @@ int cocoa_keycode_to_qemu(int keycode)
         else
             [normalWindow setTitle:@"QEMU - (Press ctrl + alt to release Mouse)"];
     }
-    [NSCursor hide];
+    if (cursor_hide) [NSCursor hide];
     CGAssociateMouseAndMouseCursorPosition(FALSE);
     isMouseGrabed = TRUE; // while isMouseGrabed = TRUE, QemuCocoaApp sends all events to [cocoaView handleEvent:]
 }
@@ -668,7 +671,7 @@ int cocoa_keycode_to_qemu(int keycode)
         else
             [normalWindow setTitle:@"QEMU"];
     }
-    [NSCursor unhide];
+    if (cursor_hide) [NSCursor unhide];
     CGAssociateMouseAndMouseCursorPosition(TRUE);
     isMouseGrabed = FALSE;
 }
@@ -783,7 +786,7 @@ int cocoa_keycode_to_qemu(int keycode)
     if(returnCode == NSCancelButton) {
         exit(0);
     } else if(returnCode == NSOKButton) {
-        char *bin = "qemu";
+        const char *bin = "qemu";
         char *img = (char*)[ [ sheet filename ] cStringUsingEncoding:NSASCIIStringEncoding];
 
         char **argv = (char**)malloc( sizeof(char*)*3 );
@@ -906,7 +909,6 @@ int main (int argc, const char * argv[]) {
 }
 
 
-
 #pragma mark qemu
 static void cocoa_update(DisplayState *ds, int x, int y, int w, int h)
 {
@@ -922,7 +924,7 @@ static void cocoa_update(DisplayState *ds, int x, int y, int w, int h)
             w * [cocoaView cdx],
             h * [cocoaView cdy]);
     }
-    [cocoaView displayRect:rect];
+    [cocoaView setNeedsDisplayInRect:rect];
 }
 
 static void cocoa_resize(DisplayState *ds)
index faacb8d..ee8e446 100755 (executable)
--- a/configure
+++ b/configure
@@ -1064,6 +1064,32 @@ EOF
   fi
 fi
 
+#
+# Check for xxxat() functions when we are building linux-user
+# emulator.  This is done because older glibc versions don't
+# have syscall stubs for these implemented.  In that case we
+# don't provide them even if kernel supports them.
+#
+atfile=no
+if [ "$linux_user" = "yes" ] ; then
+  cat > $TMPC << EOF
+#define _ATFILE_SOURCE
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+int
+main(void)
+{ 
+       /* try to unlink nonexisting file */
+       return (unlinkat(AT_FDCWD, "nonexistent_file", 0));
+}
+EOF
+  if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then
+    atfile=yes
+  fi
+fi
+
 # Check if tools are available to build documentation.
 if [ -x "`which texi2html 2>/dev/null`" ] && \
    [ -x "`which pod2man 2>/dev/null`" ]; then
@@ -1137,6 +1163,7 @@ if test "$sdl" != "no" ; then
     echo "SDL static link   $sdl_static"
 fi
 echo "curses support    $curses"
+echo "atfile support    $atfile"
 echo "mingw32 support   $mingw32"
 echo "Audio drivers     $audio_drv_list"
 echo "Extra audio cards $audio_card_list"
@@ -1429,6 +1456,9 @@ if test "$curses" = "yes" ; then
   echo "CONFIG_CURSES=yes" >> $config_mak
   echo "CURSES_LIBS=-lcurses" >> $config_mak
 fi
+if test "$atfile" = "yes" ; then
+  echo "#define CONFIG_ATFILE 1" >> $config_h
+fi
 if test "$brlapi" = "yes" ; then
   echo "CONFIG_BRLAPI=yes" >> $config_mak
   echo "#define CONFIG_BRLAPI 1" >> $config_h
diff --git a/debian/README.Debian b/debian/README.Debian
new file mode 100644 (file)
index 0000000..de0b0ab
--- /dev/null
@@ -0,0 +1,25 @@
+qemu for Debian
+---------------
+
+The qemu debian package does not include the video.x file, which is 
+needed by qemu-system-ppc for some systems. The file is available from
+the mac-on-linux project, and the sources are available on:
+  http://mac-on-linux.svn.sourceforge.net/viewvc/mac-on-linux/mac-drivers/video_driver/Makefile?revision=HEAD&view=markup
+
+They are not buildable on a Debian system though, hence video.x is not
+present in the package. The qemu-system-ppc binary is still useful for
+emulating a PReP platform, which does not need video.x.
+
+ -- Aurelien Jarno <aurel32@debian.org>  Sun, 16 Mar 2008 19:17:39 +0100
+
+
+The qemu debian package includes a simple script called qemu-make-debian-root
+under /usr/sbin, which uses debootstrap to create an image suitable for qemu
+with a fresh Debian installation inside.
+
+If you just want a test system, not wanting to go through any installation
+process, that might be just ideal. Take a look at the manual page
+qemu-make-debian-root (8) for further usage instructions.
+
+ -- Guilherme de S. Pastore <gpastore@colband.com.br>, Sun May 15 09:49:11 2005
+
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..1f19d42
--- /dev/null
@@ -0,0 +1,1123 @@
+qemu (0.9.1+svn20090113-0maemo1) unstable; urgency=low
+
+  * maemo patched version
+
+ -- Riku Voipio <riku.voipio@iki.fi>  Wed, 28 Jan 2009 11:18:41 +0200
+
+qemu (0.9.1+svn20090104-1) experimental; urgency=low
+
+  [ Aurelien Jarno ]
+  * New upstream snapshot.
+  * Disable security/CVE-2008-0928-fedora.patch, it still breaks qcow 
+    format.
+
+ -- Aurelien Jarno <aurel32@debian.org>  Sun, 04 Jan 2009 16:31:40 +0100
+
+qemu (0.9.1+svn20081223-1) experimental; urgency=low
+
+  [ Aurelien Jarno ]
+  * New upstream snapshot.
+    - Fix CVE-2008-2382
+  * Update patches/48_signal_terminate.patch.
+  * debian/rules: remove upstream flags from CFLAGS.
+
+ -- Aurelien Jarno <aurel32@debian.org>  Tue, 23 Dec 2008 14:51:25 +0100
+
+qemu (0.9.1+svn20081214-1) experimental; urgency=low
+
+  [ Aurelien Jarno ]
+  * New upstream snapshot.
+    - Fix jmp im on x86_64 when executing 32-bit code. Fix grub
+      installation (Closes: bug#467148).
+
+ -- Aurelien Jarno <aurel32@debian.org>  Sun, 14 Dec 2008 23:26:04 +0100
+
+qemu (0.9.1+svn20081207-1) experimental; urgency=low
+  [ Aurelien Jarno ]
+  * New upstream snapshot.
+    - Do not depend on gcc-3.4 anymore (Closes: bug#440425, bug#463066).
+    - Fix broken display introduced by CVE-2007-1320 (Closes: bug#422578).
+  * debian/control: remove build-dependency on gcc-3.4.
+  * debian/rules: remove code for dyngen targets.
+  * Split 90_security.patch into
+    - security/CVE-2007-5730.patch
+    - security/leftover.patch
+  * Replace 91_security.patch by security/CVE-2008-0928-fedora.patch taken
+    from fedora repository and enable it (Closes: #469649).
+
+  [ Riku Voipio ]
+  * 2 patches gone, 19 to go:
+    - 10_signal_jobs.patch: drop, merged upstream
+    - 11_signal_sigaction.patch: drop, merged upstream
+    - series: update
+
+ -- Aurelien Jarno <aurel32@debian.org>  Sun, 07 Dec 2008 19:40:09 +0100
+
+qemu (0.9.1+svn20081128-1) experimental; urgency=low
+
+  [ Aurelien Jarno ]
+  * New upstream snapshot.
+    - Include documentation for network downscript option (Closes: 
+      bug#506994). 
+    - Drop 00_bios.patch and pass --disable-blobs instead.
+    - Update 12_signal_powerpc_support.patch.
+  
+  [ Riku Voipio ]
+  * Drop 31_syscalls.patch as it makes no sense using host uselib to 
+    load target code into qemu's host memoryspace.
+
+ -- Aurelien Jarno <aurel32@debian.org>  Sat, 29 Nov 2008 09:04:41 +0100
+
+qemu (0.9.1+svn20081112-1) experimental; urgency=low
+
+  [ Aurelien Jarno ]
+  * New upstream snapshot.
+    - does not need a disk image anymore (Closes: bug#260935).
+    - 53_openbios_size.patch: drop (merged upstream).
+    - 90_security: update.
+  * debian/control: depend on openbios-sparc (>= 1.0~alpha2+20081109)
+    (Closes: bug#502411, bug#502414).
+
+ -- Aurelien Jarno <aurel32@debian.org>  Sun, 09 Nov 2008 14:42:37 +0100
+
+qemu (0.9.1+svn20081101-1) experimental; urgency=low
+
+  [ Aurelien Jarno ]
+  * New upstream snapshot.
+    - fix a heap overflow in Cirrus emulation (CVE-2008-4539).
+    - 50_linuxbios_isa_bios_ram.patch: update.
+    - 90_security.patch: update.
+
+ -- Aurelien Jarno <aurel32@debian.org>  Sat, 01 Nov 2008 09:26:45 +0100
+
+qemu (0.9.1+svn20081023-1) experimental; urgency=low
+
+  [ Aurelien Jarno ]
+  * New upstream snapshot.
+    - 12_signal_powerpc_support.patch: update.
+    - 50_linuxbios_isa_bios_ram.patch: update.
+
+ -- Aurelien Jarno <aurel32@debian.org>  Thu, 23 Oct 2008 21:34:26 +0200
+
+qemu (0.9.1+svn20081016-1) experimental; urgency=low
+
+  [ Aurelien Jarno ]
+  * New upstream snapshot.
+  * patches/31_syscalls.patch: remove parts merged upstream.
+  * debian/qemu-make-debian-root:
+    - Fix bug introduced when fixing bug#496394 (Closes: bug#502325).
+
+ -- Aurelien Jarno <aurel32@debian.org>  Mon, 13 Oct 2008 23:11:15 +0200
+
+qemu (0.9.1+svn20081012-1) experimental; urgency=low
+
+  [ Riku Voipio ]
+  * Add a bunch of patches from scratchbox
+    - 44_socklen_t_check work better with badbehavin net apps
+    - 48_signal_terminate make qemu binary terminate on signals as expected
+    - 49_null_checks don't bother some syscalls when null/zero is passed
+
+  [ Aurelien Jarno ]
+  * New upstream snapshot.
+    - alpha is now a TCG target.
+    - comma has been added to sendkey (closes: bug#414342).
+  * patches/31_syscalls.patch: remove parts merged upstream.
+  * patches/39_syscall_fadvise64.patch: remove (merged upstream).
+  * patches/90_security.patch: remove parts merged upstream.
+  * debian/control: build-depends on libbluetooth-dev.
+
+ -- Aurelien Jarno <aurel32@debian.org>  Sun, 12 Oct 2008 18:46:54 +0200
+
+qemu (0.9.1+svn20080905-1) experimental; urgency=low
+
+  * New upstream snapshot.
+    - SH4 is now a TCG target.
+  * debian/watch: update URL location.
+
+ -- Aurelien Jarno <aurel32@debian.org>  Tue, 02 Sep 2008 01:43:24 +0200
+
+qemu (0.9.1+svn20080826-1) experimental; urgency=low
+
+  * New upstream snapshot.
+  * debian/qemu-make-debian-root:
+    - Use mktemp instead of $$ to create temporary directories (Closes: 
+      bug#496394).
+  * Ship a libqemu-dev package (Closes: bug#451618).
+
+ -- Aurelien Jarno <aurel32@debian.org>  Tue, 26 Aug 2008 09:55:36 +0200
+
+qemu (0.9.1+svn20080822-1) experimental; urgency=low
+
+  * New upstream snapshot.
+    - Focus to monitor to ask password (Closes: bug#473240).
+    - TCG SPARC host support (Closes: bug#450817).
+    - Check KQEMU availability before allocating memory (Closes: bug#414566).
+    - Fix dead keys (Closes: bug#489594).
+    - Fix ES1370 emulation (Closes: bug#494462).
+    - New USB UHCI implemnation (Closes: bug#457651).
+    - Add debian/patches/00_bios.patch.
+    - Remove debian/patches/02_snapshot_use_tmpdir.patch (merged).
+    - Remove debian/patches/04_do_not_print_rtc_freq_if_ok.patch (merged).
+    - Remove patches/05_non-fatal_if_linux_hd_missing.patch (merged).
+    - Update debian/patches/07_i386_exec_name.patch
+    - Update debian/patches/12_signal_powerpc_support.patch 
+    - Remove debian/patches/33_syscall_ppc_clone.patch (merged differently).
+    - Remove debian/patches/41_arm_fpa_sigfpe.patch (merged).
+    - Remove debian/patches/42_arm_tls.patch (merged differently).
+    - Update debian/patches/55_unmux_socketcall.patch.
+    - Remove debian/patches/63_sparc_build.patch (useless).
+    - Update debian/patches/65_kfreebsd.patch.
+    - Update debian/patches/66_tls_ld.patch.
+    - Remove debian/patches/70_manpage.patch (merged).
+    - Remove debian/patches/71_doc.patch  (merged).
+    - Remove debian/patches/80_ui_curses.patch (merged).
+    - Remove debian/patches/81_mips32r2_fpu.patch (merged).
+    - Remove debian/patches/82_mips_abs.patch (merged).
+    - Remove debian/patches/83_usb-serial.patch (merged).
+    - Remove debian/patches/84_rtl8139.patch (merged).
+    - Remove debian/patches/85_vvfat.patch (merged).
+    - Remove debian/patches/86_df.patch (merged).
+    - Remove debian/patches/87_eoi.patch (merged).
+    - Remove debian/patches/88_dma.patch (merged).
+    - Remove debian/patches/89_braille.patch (merged).
+    - Remove debian/patches/92_no_shutdown.patch (merged).
+    - Remove debian/patches/93_tmpfs.patch (merged).
+    - Remove debian/patches/94_security.patch (merged).
+  * debian/README.source: new file.
+  * debian/patches/*: convert to patchlevel 1 (Closes: bug#484963).
+  * debian/control:
+    - Add build-depends on libesd0-dev.
+    - Add build-depends on libpulse-dev.
+    - Add build-depends on libvdeplug2-dev.
+    - Add build-depends on etherboot.
+    - Update list of supported targets (Closes: bug#488339).
+    - Suggests kqemu-source.
+    - Bump Standards-Version to 3.8.0.
+  * debian/links:
+    - Add missing manpage symlinks.
+  * debian/rules:
+    - Enable audio drivers depending on the system.
+    - Enable DYNGEN targets depending on the system.
+    - Install PXE bios from etherboot (Closes: bug#412010).
+    - Don't ignore make clean errors.
+    - Don't build DYNGEN targets on kfreebsd-amd64 (Closes: bug#494353).
+  * debian/patches/22_net_tuntap_stall.patch: remove (outdated).
+
+ -- Aurelien Jarno <aurel32@debian.org>  Fri, 22 Aug 2008 01:00:54 +0200
+
+qemu (0.9.1-5) unstable; urgency=high
+
+  [ Guillem Jover ]
+  * Add Homepage field.
+  * Add Vcs-Browser and Vcs-Svn fields.
+  * Remove packaging repository information from debian/copyright.
+  * Add former package co-maintainers to debian/copyright.
+  * Serialize patch and configure steps in debian/rules to support parallel
+    builds, as we are patching configure.
+  * Remove myself from Uploaders.
+
+  [ Aurelien Jarno ]
+  * debian/patches/70_manpage.patch: remove curses documentation, it is already
+    in debian/patches/80_ui_curses.patch (Closes: bug#477369).
+  * debian/patches/94_security.patch: add format= to drive options
+    (CVE-2008-2004).
+
+ -- Aurelien Jarno <aurel32@debian.org>  Mon, 28 Apr 2008 21:54:12 +0200
+
+qemu (0.9.1-4) unstable; urgency=high
+
+  * debian/patches/52_ne2000_return.patch: drop, the patch is wrong.  
+  * Backports from upstream:
+    - Typo in curses_keys.h
+    - Documentation for the -curses option
+    - Fix broken absoluteness check for cabs.d.*.
+    - USB-to-serial device.
+    - rtl8139: fix endianness on big endian targets
+    - restore rw support for vvfat
+    - x86-64: recompute DF after eflags has been modified when emulating 
+      SYSCALL
+    - ignore reads to the EOI register
+    - IDE: Improve DMA transfers by increasing the buffer size
+    - Braille device support
+    - Add -no-shutdown option (Closes: #326406)
+    - Ask to use "mount -o remount" instead of "umount" and "mount" 
+      /dev/shm (Closes: #476539).
+  * debian/qemu.doc-base: fix section. 
+
+ -- Aurelien Jarno <aurel32@debian.org>  Sun, 20 Apr 2008 23:29:42 +0200
+
+qemu (0.9.1-3) unstable; urgency=low
+
+  [ Aurelien Jarno ]
+  * debian/patches/42_arm_tls.patch: fix to get qemu-system-arm working
+    again. (Closes: #471722).
+  * debian/patches/56_dhcp.patch: fix DHCP server to correctly support 
+    MS-Windows guests. (Closes: #471452).
+
+ -- Aurelien Jarno <aurel32@debian.org>  Wed, 19 Mar 2008 18:58:29 +0100
+
+qemu (0.9.1-2) unstable; urgency=low
+
+  [ Aurelien Jarno ]
+  * debian/patches/80_ui_curses.patch: pull new patch from upstream CVS
+    (Closes: #442274).
+  * debian/patches/65_kfreebsd.patch: link with -lfreebsd. (Closes: 
+    #465932).
+  * debian/patches/81_mips32r2_fpu.patch: patch pulled from upstream
+    to fix FPU issue on MIPS32R2.
+  * debian/patches/42_arm_tls.patch: reenable, mistakenly disabled in the
+    previous upload. (Closes: #469743).
+  * debian/rules: fix parallel building. (Closes: #469981). 
+  * debian/patches/07_i386_exec_name.patch: install the i386 emulator as
+    qemu-system-i386, and change qemu into a link pointing to the i386
+    version.
+  * debian/README.Debian: add notes about qemu-system-ppc and video.x
+    (Closes: #388735).
+  * debian/patches/70_manpage.patch: describe the -curses option.
+    (Closes: #433658).
+  * debian/patches/71_doc.patch: fix the monitor change option. (Closes: 
+    #467106).
+  * debian/patches/35_syscall_sockaddr.patch: fix sockaddr (Closes: 
+    #469351).
+  * debian/patches/43_arm_cpustate.patch: disable (Closes: #444171).
+
+ -- Aurelien Jarno <aurel32@debian.org>  Mon, 17 Mar 2008 01:29:03 +0100
+
+qemu (0.9.1-1) unstable; urgency=low
+
+  [ Aurelien Jarno ]
+  * New upstream version. (Closes: #459801)
+    - Supports s390 host. (Closes: #441119)
+    - Fix PCI bar allocation. (Closes: #413315)
+    - Fix typo in keys name. (Closes: #426181)
+    - Fix segfault of qemu-i386 (Closes: #446868).
+    - debian/control: bump depends on openbios-sparc to
+      >= 1.0~alpha2+20080106.
+    - debian/patches/02_snapshot_use_tmpdir.patch: Refreshed.
+    - debian/patches/04_do_not_print_rtc_freq_if_ok.patch: Likewise.
+    - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Likewise.
+    - debian/patches/06_exit_segfault.patch: Likewise.
+    - debian/patches/10_signal_jobs.patch: Likewise.
+    - debian/patches/11_signal_sigaction.patch: Likewise.
+    - debian/patches/12_signal_powerpc_support.patch: Likewise.
+    - debian/patches/21_net_soopts.patch: Likewise.
+    - debian/patches/30_syscall_ipc.patch: Likewise.
+    - debian/patches/31_syscalls.patch: Likewise.
+    - debian/patches/32_syscall_sysctl.patch: Likewise.
+    - debian/patches/33_syscall_ppc_clone.patch: Likewise.
+    - debian/patches/35_syscall_sockaddr.patch: Likewise.
+    - debian/patches/41_arm_fpa_sigfpe.patch: Likewise.
+    - debian/patches/42_arm_tls.patch: Likewise.
+    - debian/patches/50_linuxbios_isa_bios_ram.patch: Likewise
+    - debian/patches/51_linuxbios_piix_ram_size.patch: Likewise
+    - debian/patches/61_safe_64bit_int.patch: Removed, merged upstream.
+    - debian/patches/63_sparc_build.patch: Refreshed.
+    - debian/patches/80_ui_curses.patch: Likewise.
+  * debian/patches/90_security.patch: fix 64-bit overflow. (Closes:
+    #425634)
+  * debian/qemu-make-debian-root: add a -s option to create sparse
+    image. (Closes: #322325)
+  * debian/control: bump depends on bochsbios to >= 2.3.5-1. Use
+    BIOS-qemu-latest instead of BIOS-bochs-latest. (Closes: #402289,
+    #442822)
+  * debian/rules: build the non-dyngen part with default gcc.
+  * debian/rules: support DEB_BUILD_OPTIONS="parallel=n".
+  * debian/patches/70_manpage.patch: describe the arguments of the
+    -usbdevice option in the manpage. (Closes: #443801)
+  * debian/control: now using Standards-Version 3.7.3 (no changes needed).
+  * debian/control: build-depends on libgnutls-dev to enable TLS support
+    in VNC.
+  * debian/patches/01_nostrip.patch: don't strip binaries during make
+    install. (Closes: #437866)
+  * debian/patches/53_openbios_size.patch: increase maximum prom size to
+    support latest openbios.
+
+ -- Aurelien Jarno <aurel32@debian.org>  Mon, 28 Jan 2008 21:24:14 +0100
+
+qemu (0.9.0+20070816-1) unstable; urgency=low
+
+  [ Guillem Jover ]
+  * New upstream snapshot.
+    - Fix hang on ARM during Etch installation. (Closes: #430164)
+    - Fix data corruption with qcow 2. (Closes: #440296)
+    - Fix errors with raw images > 4 GiB. (Closes: #425634)
+    - debian/patches/01_typo_qemu-img.patch: Removed, merged upstream.
+    - debian/patches/03_machines_list_no_error.patch: Likewise.
+    - debian/patches/36_syscall_prctl.patch: Likewise.
+    - debian/patches/37_syscall_mount.patch: Likewise.
+    - debian/patches/38_syscall_semctl.patch: Likewise.
+    - debian/patches/40_sparc_fp_to_int.patch: Likewise.
+    - debian/patches/44_arm_eabi_built_on_64bit_arches.patch: Likewise.
+    - debian/patches/62_linux_boot_nasm.patch: Likewise.
+    - debian/patches/04_do_not_print_rtc_freq_if_ok.patch: Synced.
+    - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Likewise.
+    - debian/patches/31_syscalls.patch: Likewise.
+    - debian/patches/35_syscall_sockaddr.patch: Likewise.
+    - debian/patches/42_arm_tls.patch: Likewise.
+    - debian/patches/43_arm_cpustate.patch: Likewise.
+    - debian/patches/51_linuxbios_piix_ram_size.patch: Likewise.
+    - debian/patches/55_unmux_socketcall.patch: Likewise.
+    - debian/patches/60_ppc_ld.patch: Likewise.
+    - debian/patches/65_kfreebsd.patch: Likewise.
+    - debian/patches/80_ui_curses.patch: Likewise.
+    - debian/patches/90_security.patch: Likewise.
+  * Remove Elrond and Guilherme de S. Pastore from Uploaders, with their
+    permission, and add Aurelien Jarno and Riku Voipio.
+  * Remove Tag field, this is better maintained outside of the package.
+  * Add openbios-sparc64 to qemu_bios_files in debian/rules.
+
+  [ Aurelien Jarno ]
+  * Fix FTBFS on amd64. (Closes: #434296)
+    - Drop debian/patches/34_syscalls_types.patch
+  * debian/control:
+    - Suggest samba. (Closes: #430368)
+  * Add OpenBIOS for sparc. (Closes: #407076)
+    - debian/control: depends on openbios-sparc.
+    - debian/links: provide symlinks in /usr/share/qemu.
+
+ -- Guillem Jover <guillem@debian.org>  Tue, 04 Sep 2007 04:04:47 +0300
+
+qemu (0.9.0-2) unstable; urgency=high
+
+  [ Guillem Jover ]
+  * Fix several security issues. (Closes: #424070)
+    Thanks to Tavis Ormandy <taviso@google.com>.
+    - Cirrus LGD-54XX "bitblt" heap overflow. CVE-2007-1320
+    - NE2000 "mtu" heap overflow.
+    - QEMU "net socket" heap overflow.
+    - QEMU NE2000 "receive" integer signedness error. CVE-2007-1321
+    - Infinite loop in the emulated SB16 device.
+    - Unprivileged "aam" instruction does not correctly handle the
+      undocumented divisor operand. CVE-2007-1322
+    - Unprivileged "icebp" instruction will halt emulation. CVE-2007-1322
+    - debian/patches/90_security.patch: New file.
+  * Enable adlib audio emulation. (Closes: #419170)
+  * Fix structure padding for target_eabi_flock64 when built for a 64 bit
+    architecture. (Closes: #414799)
+    Thanks to Stuart Anderson <anderson@netsweng.com>.
+    - debian/patches/44_arm_eabi_built_on_64bit_arches.patch: New file.
+  * Fix qemu to be able to use LinuxBios. (Closes: #412212)
+    Thanks to Ed Swierk <eswierk@cs.stanford.edu>.
+    - debian/patches/50_linuxbios_isa_bios_ram.patch: New file.
+    - 51_linuxbios_piix_ram_size.patch: Likewise.
+  * Fix segfault when booting a Linux kernel w/o a disk image, by exiting but
+    clarifying the message, as to use '/dev/null'. (Closes: #409817, #411780)
+    Thanks to Robert Millan <rmh@aybabtu.com>.
+    - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Updated.
+  * Fix segfault by using addrlen instead of target_addrlen in
+    do_getpeername()/do_getsockname(). (Closes: #411910)
+    Thanks to Stuart Anderson <anderson@netsweng.com>.
+    - debian/patches/35_syscall_sockaddr.patch: Updated.
+  * Fix semctl() for 32 bit targets on 64 bit hosts. (Closes: #414809)
+    Thanks to Stuart Anderson <anderson@netsweng.com>.
+    - debian/patches/38_syscall_semctl.patch: New file.
+  * Remove Elrond from Uploaders with consent, always welcome to join
+    back anytime.
+
+ -- Guillem Jover <guillem@debian.org>  Wed, 16 May 2007 08:08:31 +0300
+
+qemu (0.9.0-1) experimental; urgency=low
+
+  [ Guillem Jover ]
+  * New upstream release. (Closes: #409989)
+    - Support for relative paths in backing files for disk images.
+      (Closes: #390446)
+    - debian/patches/01_doc_typos.patch: Removed, merged upstream.
+    - debian/patches/38_syscall_arm_statfs64.patch: Likewise.
+    - debian/patches/51_serial_small_divider.patch: Likewise.
+    - debian/patches/67_ppc_ftbfs.patch: Likewise.
+    - debian/patches/21_net_soopts.patch: Synced.
+    - debian/patches/30_syscall_ipc.patch: Likewise.
+    - debian/patches/31_syscalls.patch: Likewise.
+    - debian/patches/35_syscall_sockaddr.patch: Likewise.
+    - debian/patches/39_syscall_fadvise64.patch: Likewise.
+    - debian/patches/42_arm_tls.patch: Likewise.
+    - debian/patches/55_unmux_socketcall.patch: Likewise.
+    - debian/patches/80_ui_curses.patch: Likewise.
+  * Update the copyright information.
+  * The ACPI initialization code has been moved to bochsbios.
+    - debian/patches/acpi-dsdt.hex: Removed.
+    - debian/rules: Do not install acpi-dsdt.hex.
+  * Add more files to the list of roms removed from the tarball needed to
+    be touched so that upstream 'make install' does not fail.
+  * Added armeb and armel to Architecture fields and libgpmg1-dev
+    Build-Depends.
+  * Recommend vde2 instead of the transitional vde package. (Closes: #407251)
+  * Fix typo in qemu-img output. (Closes: #408542)
+    - debian/patches/01_typo_qemu-img.patch: New file.
+    Thanks to Adam Buchbinder <adam.buchbinder@gmail.com>.
+  * Symlink qemu-user(1) to qemu-m68k(1).
+  * Reduce redundancy in qemu-user(1) synopsis.
+  * Fix rounding in sparc floating point to integer conversions.
+    - debian/patches/40_sparc_fp_to_int.patch: New file.
+    Thanks to Aurelien Jarno <aurelien@aurel32.net>.
+
+ -- Guillem Jover <guillem@debian.org>  Thu,  8 Feb 2007 01:01:29 +0200
+
+qemu (0.8.2-5) unstable; urgency=low
+
+  [ Guillem Jover ]
+  * Added a missing part to the ARM NPTL support patch, initially lost.
+    - debian/patches/42_arm_tls.patch: Updated.
+
+ -- Guillem Jover <guillem@debian.org>  Tue, 16 Jan 2007 11:44:00 +0200
+
+qemu (0.8.2-4) unstable; urgency=medium
+
+  [ Guillem Jover ]
+  * Disable using iasl for now until it's ported to big-endian systems and
+    include a locally built acpi-dsdt.hex file.
+
+ -- Guillem Jover <guillem@debian.org>  Sun,  3 Dec 2006 21:10:23 +0200
+
+qemu (0.8.2-3) unstable; urgency=low
+
+  [ Guillem Jover ]
+  * Hopefully really fix powerpc FTBFS.
+
+ -- Guillem Jover <guillem@debian.org>  Sun,  5 Nov 2006 17:09:53 +0200
+
+qemu (0.8.2-2) unstable; urgency=low
+
+  [ Guillem Jover ]
+  * Update Tag field to match new debtags vocabulary.
+  * Clean properly. (Closes: #390166)
+    - Remove the acpi generated files and the docs.
+    - Revert the docs regeneration forcing logic.
+    Thanks to Anderson Lizardo <anderson.lizardo@gmail.com>.
+  * On install use DESTDIR instead of specifying all paths. (Closes: #396139)
+    Thanks to Anderson Lizardo <anderson.lizardo@gmail.com>.
+  * Port to GNU/kFreeBSD. (Closes: #327622)
+    - Disable ALSA on non-linux systems.
+    - Add a Build-Depends on libfreebsd-dev on kfreebsd systems.
+    - Add kfreebsd-i386 and kfreebsd-amd64 to the Architecture field.
+    - debian/patches/65_kfreebsd.patch: New file.
+    Thanks Petr Salinger <Petr.Salinger@seznam.cz>.
+  * In qemu-make-debian-root do not explicitely install in aptitude and
+    libsigc++-1.2-5c102, they are pulled now by default. And do not remove
+    aptitude afterwards. (Closes: #392481)
+    Thanks to Ted Percival <ted@midg3t.net>.
+  * Add experimental ncurses ui support. (Closes: #369462)
+    - debian/patches/80_ui_curses.patch: New file.
+    Thanks to Andrzej Zaborowski <balrog@zabor.org>.
+  * Add SO_PEERCRED and SO_SNDTIMEO support, and fix accept syscall when
+    being passed NULL pointers.
+    - debian/patches/21_net_sockopts.patch: Renamed to ...
+    - debian/patches/21_net_soopts.patch: ... here. Modify.
+    Thanks to Pablo Virolainen.
+  * Add a fadvise64 syscall stub.
+    - debian/patches/39_syscall_fadvise64.patch: New file.
+    Thanks to Pablo Virolainen.
+  * Add EABI unmuxed socket syscalls.
+    - debian/patches/55_unmux_socketcall.patch: New file.
+    Thanks to Riku Voipio.
+  * Add TLS sections to the ARM and x86 linker scripts so that qemu user
+    emulators can be linked statically.
+    - debian/patches/66_tls_ld.patch: New file.
+  * Move the documentation of the binary blob removals from the original
+    upstream tarball from README.Debian to debian/copyright.
+  * Reword the emphasis on "FAST!" from the package description.
+  * Fix FTBFS on powerpc by adding the missing fp_status variable to the
+    int32_to_float32 function calls.
+    - debian/patches/67_ppc_ftbfs.patch: New file.
+
+ -- Guillem Jover <guillem@debian.org>  Sun,  5 Nov 2006 08:48:27 +0200
+
+qemu (0.8.2-1) unstable; urgency=low
+
+  [ Guillem Jover ]
+  * New upstream release. (Closes: #379461, #385029, #388810)
+    - Add ACPI BIOS emulation support. (Closes: #372533)
+    - Fix mouse invisible wall when using Windows XP. (Closes: #384666)
+    - debian/patches/01_doc_typos.patch: Sync.
+    - debian/patches/03_machines_list_no_error.patch: Likewise.
+    - debian/patches/04_do_not_print_rtc_freq_if_ok.patch: Likewise.
+    - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Likewise.
+    - debian/patches/06_exit_segfault.patch: Likewise.
+    - debian/patches/12_signal_powerpc_support.patch: Likewise.
+    - debian/patches/21_net_sockopt.patch: Likewise.
+    - debian/patches/22_net_tuntap_stall.patch: Likewise.
+    - debian/patches/30_syscall_ipc.patch: Likewise.
+    - debian/patches/31_syscalls.patch: Likewise.
+    - debian/patches/32_syscall_sysctl.patch: Likewise.
+    - debian/patches/33_syscall_ppc_clone.patch: Likewise.
+    - debian/patches/35_syscall_sockaddr.patch: Likewise.
+    - debian/patches/36_syscall_prctl.patch: Likewise.
+    - debian/patches/37_syscall_mount.patch: Likewise.
+    - debian/patches/41_arm_fpa_sigfpe.patch: Likewise.
+    - debian/patches/42_arm_tls.patch: Likewise.
+    - debian/patches/61_safe_64bit_int.patch: Likewise.
+    - debian/patches/63_sparc_build.patch: Likewise.
+    - debian/patches/50_missing_keycodes.patch: Removed, integrated upstream.
+  * Switch to quilt:
+    - debian/control: Add quilt (>= 0.40) to Build-Depends.
+    - debian/patches/series: New file.
+    - debian/patch.mk: Removed.
+    - debian/rules: Include '/usr/share/quilt/quilt.make' instead of
+      'debian/patch.mk'.
+  * Build the ACPI Source Language files with iasl.
+  * Add a Tag field to the binary package, using data from debtags.
+  * Add 2006 to the debian/copyright years.
+  * Add a Recommends on vde. (Closes: #386780)
+  * Fix spelling error in package description (peripherials -> peripherals).
+    (Closes: #388700)
+    Thanks to Rakesh 'arky' Ambati <rakesh_ambati@yahoo.com>.
+  * Fix ne2000_can_receive return code to 0 when the command is STOP.
+    (Closes: #386209)
+    - debian/patches/52_ne2000_return.patch: New file.
+    Thanks to Samuel Thibault <samuel.thibault@ens-lyon.org>.
+  * Document the binary blob removals from the original upstream tarball in
+    README.Debian. (Closes: #388740)
+
+ -- Guillem Jover <guillem@debian.org>  Mon, 25 Sep 2006 04:16:25 +0300
+
+qemu (0.8.1-1) unstable; urgency=low
+
+  [ Guillem Jover ]
+  * New upstream release. (Closes: #366955, #366637)
+    - debian/patches/01_doc_typos.patch: Sync.
+    - debian/patches/04_do_not_print_rtc_freq_if_ok.patch: Likewise.
+    - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Likewise.
+    - debian/patches/12_signal_powerpc_support.patch: Likewise.
+    - debian/patches/21_net_sockopt.patch: Likewise.
+    - debian/patches/22_net_tuntap_stall.patch: Likewise.
+    - debian/patches/30_syscall_ipc.patch: Likewise.
+    - debian/patches/31_syscalls.patch: Likewise.
+    - debian/patches/32_syscall_sysctl.patch: Likewise.
+    - debian/patches/33_syscall_ppc_clone.patch: Likewise.
+    - debian/patches/35_syscall_sockaddr.patch: Likewise.
+    - debian/patches/36_syscall_prctl.patch: Likewise.
+    - debian/patches/37_syscall_mount.patch: Likewise.
+    - debian/patches/41_arm_fpa_sigfpe.patch: Likewise.
+    - debian/patches/42_arm_tls.patch: Likewise.
+    - debian/patches/43_arm_cpustate.patch: Likewise.
+    - debian/patches/50_missing_keycodes.patch: Likewise.
+    - debian/patches/51_serial_small_divider.patch: Likewise.
+    - debian/patches/61_safe_64bit_int.patch: Likewise.
+    - debian/patches/63_sparc_build.patch: Likewise.
+    - debian/patches/40_arm_nwfpe_cpsr.patch: Removed, integrated upstream.
+  * Make the patch system apply the patch on the first run.
+    - debian/patches/64_ppc_asm_constraints.patch: Add DPATCHLEVEL.
+  * Document how to use the images created with qemu-make-debian-root in the
+    man page. Thanks to Jacobo <jacobo221@hotmail.com>. (Closes: #343450)
+  * Add support for the -snapshot option to use the TMPDIR evironment
+    variable. (Closes: #353880)
+    - debian/patches/02_snapshot_use_tmpdir.patch: New file.
+  * Do not exit with an error when using '-M ?'. (Closes: #365209)
+    - debian/patches/03_machines_list_no_error.patch: New file.
+  * Added symlink for system-mipsel emulator man page.
+  * Build and clean the pc-bios directory.
+  * Avoid segfaulting by using _exit(2) instead of exit(3) in qemu user
+    emulators. (Closes: #338289)
+    - debian/patches/06_exit_segfault.patch: New file.
+  * Enable ALSA audio support and add libasound2-dev to the Build-Depends.
+  * Now using Standards-Version 3.7.2 (no changes needed).
+
+ -- Guillem Jover <guillem@debian.org>  Sun, 28 May 2006 20:51:10 +0300
+
+qemu (0.8.0-3) unstable; urgency=low
+
+  [ Josh Triplett ]
+  * Fix FTBFS on PowerPC caused by asm constraint problem. (Closes: #361727)
+    - debian/patches/64_ppc_asm_constraints.patch.
+
+  [ Guillem Jover ]
+  * Clamp addrlen from host to target when using AF_UNIX. This fixes
+    socket problems when using EABI.
+    - debian/patches/35_syscall_sockaddr.patch: New file.
+  * Fix floating point comparison on ARM NWFPE, due to glue code missmatch.
+    (Closes: #356287)
+    - debian/patches/40_arm_nwfpe_cpsr.patch: New file.
+    - debian/patches/40_fpu_arm_sigfpe.patch: Rename to ...
+    - debian/patches/41_arm_fpa_sigfpe.patch: ... this. Resync.
+    Thanks to Ulrich Hecht.
+  * Fix POSIX threads creation on ARM hanging when initializing the cpu
+    structure being it cyclic.
+    - debian/patches/43_arm_cpustate.patch: New file.
+  * Add TLS support for ARM. Stolen from Scratchbox.
+    - debian/patches/42_arm_tls.patch: New file.
+  * Fix sysctl endian problem.
+    - debian/patches/32_syscall_sysctl.patch: Update.
+    Thanks to Timo Savola <tsavola@movial.fi>.
+  * Remove now default '--enable-slirp' build option. (Closes: #356284)
+    Thanks to Anderson Lizardo <anderson.lizardo@gmail.com>.
+  * Remove unused sharedir to 'make install'. (Closes: #356418)
+    Thanks to Anderson Lizardo <anderson.lizardo@gmail.com>.
+  * Fix package not cleaning properly. (Closes: #356279)
+    Thanks to Anderson Lizardo <anderson.lizardo@gmail.com> for the initial
+    patch.
+  * Add needed syscalls to make debootstrap work. (Closes: #356291)
+    - debian/patches/36_syscall_prctl.patch: New file.
+    - debian/patches/37_syscall_mount.patch: Likewise.
+    - debian/patches/38_syscall_arm_statfs64.patch: Likewise.
+    Thanks to Anderson Lizardo <anderson.lizardo@gmail.com>.
+  * Remove obsolete Build-Dependency xlibs-dev.
+
+ -- Guillem Jover <guillem@debian.org>  Thu, 13 Apr 2006 11:53:00 +0300
+
+qemu (0.8.0-2) unstable; urgency=low
+
+  [ Guillem Jover ]
+  * Switch away from cdbs to plain debhelper.
+  * Upgrade to debhelper compat level 5.
+  * Allow overriding CC compiler variable. (Closes: #345772)
+  * Do not redefine 64 bit types on 64 bit arches.
+    - debian/patches/61_safe_64bit_int.patch: New file.
+  * Allow linux_boot.bin to be built on any arch by switching to nasm,
+    and Build-Depending on it.
+    - debian/patches/62_linux_boot_nasm.patch: New file.
+  * The serial hw driver uses a small divider that gets zeroed when shifting
+    bits to the right. (Closes: #276276, #348098)
+    - debian/patches/51_serial_small_divider.patch: New file.
+    Thanks to Samuel Thibault <samuel.thibault@ens-lyon.org>.
+  * Escaped hyphens in qemu-user manpage, use italics for filenames and
+    parameters and bold for options.
+  * Partial build failure fix for Sparc. (Bugs: #317145, #336970)
+    Thanks to Jurij Smakov <jurij@wooyd.org>.
+
+ -- Guillem Jover <guillem@debian.org>  Mon, 20 Feb 2006 09:17:46 +0200
+
+qemu (0.8.0-1) unstable; urgency=low
+
+  [ Guillem Jover ]
+  * New upstream release. (Closes: #344339)
+    - Added support for Virtual FAT. (Closes: #313123)
+    - Emulate repeated keystrokes when holding a key. (Closes: #298864)
+    - debian/patches/01_doc_typos.patch: Sync.
+    - debian/patches/04_do_not_print_rtc_freq_if_ok.patch: Likewise.
+    - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Likewise.
+    - debian/patches/12_signal_powerpc_support.patch: Likewise.
+    - debian/patches/21_net_sockopt.patch: Likewise.
+    - debian/patches/22_net_tuntap_stall.patch: Likewise.
+    - debian/patches/30_syscall_ipc.patch: Likewise.
+    - debian/patches/31_syscalls.patch: Likewise.
+    - debian/patches/32_syscall_sysctl.patch: Likewise.
+    - debian/patches/33_syscall_ppc_clone.patch: Likewise.
+    - debian/patches/40_fpu_arm_sigfpe.patch: Likewise.
+    - debian/patches/50_missing_keycodes.patch: Likewise.
+  * Added mips and mipsel to the lintian overrides for the user emulators
+    being shlib-with-non-pic-code.
+  * Added symlinks for mips, mipsel and system-arm emulator manpages.
+
+ -- Guillem Jover <guillem@debian.org>  Fri, 30 Dec 2005 05:44:53 +0200
+
+qemu (0.7.2-2) unstable; urgency=low
+
+  [ Josh Triplett ]
+  * Add support for signal handling on PowerPC. (Closes: #335509)
+    - debian/patches/12_signal_powerpc_support.patch: New file.
+
+  [ Guillem Jover ]
+  * Add Josh Triplett <josh@psas.pdx.edu> to Uploaders and packaging team.
+  * Fix PowerPC build failure by reintroducing the ppc linker script and
+    adding the missing _SDA_BASE_ and _SDA2_BASE_ symbols. (Closes: #336983)
+  * Remove invalid patch making X11 fail at runtime.
+    - debian/patches/20_net_socket.patch: Remove.
+    - debian/patches/32_syscall_sysctl.patch: Sync.
+    Thanks to Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>.
+  * Avoid the patch system to try until it applies.
+    - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Added patch level.
+    - debian/patches/12_signal_powerpc_support.patch: Likewise.
+
+ -- Guillem Jover <guillem@debian.org>  Wed, 21 Dec 2005 22:11:34 +0200
+
+qemu (0.7.2-1) unstable; urgency=low
+
+  [ Guillem Jover ]
+  * New upstream release. (Closes: #321232, #327168)
+    - debian/patches/12_signal_silent.patch: Integrated upstream, remove.
+    - debian/patches/50_ppc_ldscript.patch: Likewise.
+    - debian/patches/33_syscall_truncate64.patch: Likewise.
+    - debian/patches/01_doc_typos.patch: Resync with upstream.
+    - debian/patches/04_do_not_print_rtc_freq_if_ok.patch: Likewise.
+    - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Likewise.
+    - debian/patches/10_signal_jobs.patch: Likewise.
+    - debian/patches/11_signal_sigaction.patch: Likewise.
+    - debian/patches/20_net_socket.patch: Likewise.
+    - debian/patches/21_net_sockopt.patch: Likewise.
+    - debian/patches/22_net_tuntap_stall.patch: Likewise.
+    - debian/patches/30_syscall_ipc.patch: Likewise.
+    - debian/patches/31_syscalls.patch: Likewise.
+    - debian/patches/32_syscall_sysctl.patch: Likewise.
+    - debian/patches/40_fpu_arm_sigfpe.patch: Likewise.
+  * Repackaged upstream source to deal with binaries w/o sources.
+    - pc-bios/video.x: New file removed.
+  * Create a new qemu-user(1) manpage and link all user emulator manpages
+    to it. (Closes: #335163)
+  * Add missing '-' and '=' keycodes for sendkey command.
+    - debian/patches/50_missing_keycodes.patch: New file. (Closes: #334071)
+    Thanks to Robert Millan <rmh@aybabtu.com>.
+  * Add manpage link for qemu-system-mips.
+  * Make sysctl byte-swap the name values.
+    - debian/patches/32_syscall_sysctl.patch: Merge patch. (Closes: #334458)
+    Thanks to Josh Triplett <josh@psas.pdx.edu>.
+  * Change documentation menu section to "Apps/Emulators". (Closes: #335062)
+    Thanks to Frans Pop <aragorn@tiscali.nl>.
+  * On PowerPC, do not zero registers r7-r31 in do_fork and zero register r3.
+    Fixing segfaults on programs using the clone syscall.
+    - debian/patches/33_syscall_ppc_clone.patch: New file. (Closes: #335159)
+    Thanks to Josh Triplett <josh@psas.pdx.edu>
+    and Paul Brook <paul@codesourcery.com>.
+  * Tighten vgabios and bochsbios versioned Depends.
+  * Add video.x to the list of roms to touch to make qemu Makefile happy.
+  * Add lintian overrides for the user emulators being shlib-with-non-pic-code.
+  * Wrap lines in debian/control fields (knowingly breaking policy).
+
+  [ Guilherme de S. Pastore ]
+  * debian/control:
+    - Updated my e-mail address.
+  * debian/copyright:
+    - Dropped André from team members list, not a single contribution ever.
+
+ -- Guillem Jover <guillem@debian.org>  Mon, 31 Oct 2005 05:01:45 +0200
+
+qemu (0.7.0-4) unstable; urgency=low
+
+  [ Guillem Jover ]
+  * Rebuild source with locally deborked dpkg-source. (Closes: #321019)
+  * Added the location of the Subversion repo used for the packages and
+    fixed the upstream URL in debian/copyright.
+  * Lower case title header in qemu-make-debian-root man page.
+  * Use dd instead of cat to generate the qemu debian root image.
+    (Closes: #315952)
+
+ -- Guillem Jover <guillem@debian.org>  Wed,  3 Aug 2005 05:53:30 +0300
+
+qemu (0.7.0-3) unstable; urgency=low
+
+  [ Guillem Jover ]
+  * Update watch file to version 3, use perlre and new upstream site.
+  * Now using Standards-Version 3.6.2 (no changes needed).
+  * Fix TUN/TAP network interface stalling the connection. (Closes: #290569)
+    Thanks to Vitaly Belostotsky <byly.useless@tochka.ru>.
+  * Link against librt, needed by the new clock_gettime syscall.
+    - debian/patches/31_syscalls.patch: Update. (Closes: #315388)
+    Thanks to Timo Savola <tsavola@movial.fi> for noticing.
+  * Force Build-Dependency on binutils >= 2.16-1 needed by the amd64 and
+    powerpc linker scripts. (Closes: #262655)
+  * Force usage of gcc-3.4. (Closes: #319527)
+  * Add missing Build-Dependency on zlib1g-dev.
+    Thanks to Reinhard Tartler <siretart@tauware.de>.
+  * Include <linux/types.h> in syscall.c to avoid the broken headers in 
+    linux-kernel-headers 2.6.12.
+    - debian/patches/34_syscalls_types.patch: New file.
+    Thanks to Octavian Cerna <tavy@ylabs.com>.
+  * Fix powerpc linker script.
+    - debian/patches/50_ppc_ldscript.patch: New file.
+    Thanks to Octavian Cerna <tavy@ylabs.com>.
+
+ -- Guillem Jover <guillem@debian.org>  Mon,  1 Aug 2005 02:48:09 +0300
+
+qemu (0.7.0-2) unstable; urgency=low
+
+  [ Guillem Jover ]
+  * Add alpha, sparc, arm and s390 to Architectures (and to the
+    libgpmg1-dev Build-Depends).
+
+  * Forward SIGSTOP and SIGCONT sent to QEMU to the emulated application.
+    - debian/patches/10_signal_jobs.patch: New file.
+    Thanks to Ulrich Hecht.
+  * Return EINVAL on emulated sigaction when given invalid signal
+    parameters SIGKILL and SIGSTOP.
+    - debian/patches/11_signal_sigaction.patch: New fle.
+    Thanks to Valtteri Rahkonen.
+  * Do not print messsages for uncaught signal, thus fixing the case
+    were some applications want to kill their siblings.
+    - debian/patches/12_signal_silent.patch: New file.
+    Thanks to Valtteri Rahkonen
+
+  * Fix Unix sockets by handling correctly AF_UNIX socket address
+    structure length.
+    - debian/patches/20_net_socket.patch: New file.
+    Thanks to Timo Savola.
+  * Implement SO_LINGER, SO_RCVTIMEO, SO_SNDTIMEO, SO_PEERNAME and
+    SO_PEERCRED getsockoptions.
+    - debian/patches/21_net_sockopt.patch: New file.
+    Thanks to Valtteri Rahkonen.
+
+  * Implement SysV IPC message and semaphore syscalls.
+    - debian/patches/30_syscall_ipc.patch: New file.
+    Thanks to Valtteri Rahkonen.
+  * Implement acct, umount2, uselib, swapon, syslog, ftruncate64,
+    mincore, madvise, readahead and clock_gettime syscalls.
+    - debian/patches/31_syscalls.patch: New file.
+    Thanks to Ulrich Hecht.
+  * Implement sysctl CTL_KERN/KERN_VERSION
+    - debian/patches/32_syscall_sysctl.patch: New file.
+    Thanks to Timo Savola.
+  * Implement truncate64 syscall.
+    - debian/patches/33_syscall_truncate64.patch: New file.
+    Thanks to Valtteri Rahkonen.
+
+  * Implement ARM floating point exeption emulation.
+    - debian/patches/40_fpu_arm_sigfpe.patch: New file.
+    Thanks to Ulrich Hecht.
+
+ -- Guillem Jover <guillem@debian.org>  Sun, 19 Jun 2005 15:05:37 +0300
+
+qemu (0.7.0-1) experimental; urgency=low
+
+  [ Guillem Jover ]
+  * New upstream release. (Closes: #308459, #308494)
+  * Do not require a disk image when booting a Linux kernel. (Closes: #260935)
+    Thanks to Jonas Smedegaard <dr@jones.dk>.
+
+  [ Guilherme de S. Pastore ]
+  * Rewrote README.Debian for more clarity
+  * Add support for amd64 as a host architecture. (Closes: #262655)
+    - Add build-depend on libgpmg1-dev on amd64.
+  * Fixed qemu-make-debian-root so that it shows the name by which
+    it was called on the usage notice, not "%s". (Closes: #303507)
+    Thanks to Micah Anderson <micah@riseup.net>.
+
+  [ Elrond ]
+  * Clean up more files, so they don't end up in the final .diff.gz
+  * Switch to external proll and openhackware:
+    - Instead of patching qemu's Makefile, trick it by giving it empty
+      files to install and remove them straight after install.
+    - Don't ship the roms in debian/roms any more!
+    - Instead add more symlinks.
+    - Update Depends: apropiately.
+
+ -- Guillem Jover <guillem@debian.org>  Fri, 27 May 2005 02:06:20 +0300
+
+qemu (0.6.1+20050407-1) unstable; urgency=low
+
+  [ Guillem Jover ]
+  * New upstream snapshot.
+    - Fix -user-net. (Closes: #295019)
+    - Fix win2k and winxp image booting. (Closes: #285170, #292707)
+    - Fix installation of outdated documentation. (Closes: #286931)
+    - Provide qemu-img instead of qemu-mkcow. (Closes: #290713)
+    - Remove debian/patches/05_fix_openpic_timer_test.patch, integrated
+      upstream.
+    - Remove debian/patches/02_selectable_sdl_keyboard.patch, superseded
+      by new keyboard implementation. (Closes: #284510, #299432)
+    - Remove debian/patches/01_mkcow_section_and_hyphens.patch.
+    - Conditionalize qemu -g option for some architectures. (Closes: #298988)
+  * Added new copyright year to debian/copyright.
+  * Added initial qemu-make-debian-root man page. (Closes: #286932)
+  * Fixed typos in qemu documentation. (Closes: #301933)
+    Thanks to A Costa <agcosta@gis.net>.
+  * Added Elrond <elrond@samba-tng.org> to Uploaders and packaging team.
+  * Use the default target list:
+    - Do not build qemu-fast anymore as it is deprecated upstream anyway.
+    (Closes: #278602, #281510)
+    - New targets armeb and system-x86_64.
+  * Updated ROM images under debian/roms/:
+    - OpenHackWare 0.4.
+    - Proll 18 with qemu specific patches.
+  * Remove uudecoded files from pc-bios/ on clean.
+  * Fix qemu-make-debian-root to behave correctly even if the needed
+    Recommends are not installed.
+
+  [ Guilherme de S. Pastore ]
+  * Create a doc-base entry for the package (Closes: #290669)
+  * debian/control:
+    - Add debootstrap to the 'Recommends: ' line, as needed by
+      qemu-make-debian-root (Closes: #302848)
+    - Moved sharutils from dependency to recommendation, as it is only
+      needed by qemu-make-debian-root
+  * debian/docs:
+    - Do not include README.distrib in the binary package (Closes: #302853)
+
+  [ Elrond ]
+  * Replace "libgpmg1-dev | not+linux-gnu" by "libgpmg1-dev [i386 powerpc]"
+    in Build-Depends. qemu should not need to build-depend on it anyway, the
+    real problem is described in Bug#267174. When it is solved, we can
+    remove our dependency. Until then please remember to add any arch, which
+    we will build on and that has gpm. This change hopefully calms:
+    <http://qa.debian.org/debcheck.php?dist=unstable&package=qemu>
+  * Add versions to the dependencies on bochsbios and vgabios
+    (Closes: #288997):
+    - vgabios: Use the current version from testing/unstable (0.4c+20041014-1),
+      according to Frans Pop <aragorn@tiscali.nl>, this fixed those
+      "blank screen" problems.
+    - bochsbios: Use the current version from unstable (2.1.1+20041109-3), as
+      Guillem Jover fixed the networking in that version.
+
+ -- Guillem Jover <guillem@debian.org>  Thu,  7 Apr 2005 01:26:01 +0300
+
+qemu (0.6.1-1) unstable; urgency=low
+
+  [ Guillem Jover ]
+  * New upstream release. (Closes: #281626)
+    - Booting from drive b is not supported anymore. (Closes: #275679)
+    - Fix ne2k network interface that was not working in some situations.
+      (Closes: #281862)
+    - Remove debian/patches/06_build_gcc3.4.patch, fixed upstream.
+    - Remove debian/patches/04_lfs.patch, fixed upstream.
+    - Remove debian/patches/02_fix_powerpc_FTBFS.patch, fixed upstream.
+    - Remove debian/patches/00_escape_manpage_hyphens.patch, not needed.
+    - Sync debian/patches/03_use_external_bios.patch.
+  * Include uuencoded source for proll 18, some build fixes and its binary
+    proll.bin on debian/roms/.
+  * Suggests sudo to be used by the qemu-ifup script.
+    Thanks to Elrond <elrond@samba-tng.org>.
+  * Make sudo in qemu-ifup explain what the password is for. (Closes: #281380)
+  * Add an option to select the method to convert keyevent to keycode
+    in the SDL keyboard handling code. Added support for Right Shift in the
+    generic handler. (Closes: #282658)
+    Thanks to Elrond <elrond@samba-tng.org>.
+  * Do not set RTC frequency to 1024 or warn about this if it has already
+    the correct value. (Closes: #281403)
+  * Enabled sparc-softmmu support.
+
+ -- Guillem Jover <guillem@debian.org>  Sat, 27 Nov 2004 23:23:49 +0100
+
+qemu (0.6.0.dfsg.2-1) unstable; urgency=low
+
+  [ Guillem Jover ]
+  * Repackaged upstream source to remove external included files.
+    - pc-bios/ppc-rom.bin: Removed.
+    - pc-bios/OpenHackWare_0.3.tar.bz2: Likewise.
+    - pc-bios/vgabios.bin: Likewise.
+    - pc-bios/vgabios-cirrus.bin: Likewise.
+    - pc-bios/vgabios-cvs-2004-06-17.tgz: Likewise.
+  * Include uuencoded source for OpenHackWare 0.3.1 and its binary
+    ppc-rom.bin on debian/roms/. Add a Build-Depends on sharutils.
+  * Update tundev.c. Pass -tun-dev to qemu without the equal sign.
+    Thanks to Isaac Clerencia <isaac@sindominio.net>.
+  * Fix README.Debian to point to the renamed qemu-make-debian-root.
+  * Add Depends on sharutils needed by qemu-make-debian-root.
+    (Closes: #272130)
+  * Use and depend on vgabios package, which is in sync with bochsbios
+    that checks for rom bios checksums. (Closes: #281202)
+  * Enable LFS globally, thus fixing problems with qemu-mkcow when using
+    an existing large image.
+    (Closes: #279925)
+  * Fix openpic timer write test, catched from a warning about a constant
+    value larger than the type it was casted to.
+  * Fix build failure with gcc 3.4. Patch stolen from Gentoo BTS.
+
+ -- Guillem Jover <guillem@debian.org>  Mon, 15 Nov 2004 10:46:54 +0100
+
+qemu (0.6.0.dfsg.1-1) unstable; urgency=high
+
+  [ Guillem Jover ]
+  * Repackaged upstream source to deal with binaries w/o sources.
+    (Closes: #268780)
+    - pc-bios/bios.bin: Removed binary without source. Now using
+      bochsbios package.
+    - pc-bios/vgabios.bin: Rebuilt from vgabios cvs 2004-06-17 snapshot,
+      source included.
+    - pc-bios/vgabios-cirrus.bin: Likewise.
+    - pc-bios/ppc-rom.bin: Rebuilt on voltaire, source included.
+    - pc-bios/linux_boot.bin: Rebuilt from source.
+  * Move make-debian-root.sh to /usr/sbin/qemu-make-debian-root.
+    (Closes: #268705)
+
+ -- Guillem Jover <guillem@debian.org>  Mon, 13 Sep 2004 01:28:54 +0200
+
+qemu (0.6.0-2) unstable; urgency=high
+
+  [ Guilherme de S. Pastore ]
+  * Fixed dangling symlinks under /usr/share/man/man1. (Closes: #264764)
+
+  [ Guillem Jover ]
+  * Fix FTBFS on powerpc.
+    - debian/patches/02_fix_powerpc_FTBFS.patch: New file.
+
+ -- Guillem Jover <guillem@debian.org>  Wed, 18 Aug 2004 15:50:43 +0200
+
+qemu (0.6.0-1) unstable; urgency=medium
+
+  * New maintainers. (Closes: #258900)
+  * New upstream release. (Closes: #258732)
+    - Installs ppc BIOS ROM file. (Closes: #257492)
+    - Builds with -fno-strict-aliasing. (Closes: #257123)
+
+  [ Guilherme de S. Pastore ]
+  * debian/rules:
+    - Cleaned up.
+    - Ported to use CDBS.
+  * 00_escape_manpage_hyphens.patch:
+    - Correct a little typo and escape hyphens in upstream manpage.
+  * 01_mkcow_section_and_hyphens.patch:
+    - Fix section mismatch and escape hyphens in the qemu-mkcow manpage.
+  * Added simple /etc/qemu-ifup helper script. (Closes: #245281)
+    Thanks to Martin Michlmayr <tbm@cyrius.com>.
+  * Cleaned debian/watch.
+  * UTF-8'ed debian/changelog.
+  * Updated Standards-Version to 3.6.1.1.
+  * Removed outdated and unnecessary debian/qemu-i386.sgml.
+    - Removed build dependency on docbook-to-man.
+  * Removed "x86" part from the description (hey, qemu is not x86-only
+    in any way). Deserves a complete rewrite, shall be done soon.
+
+  [ Guillem Jover ]
+  * Lower-case package short description.
+  * Added missing CPU emulations to the description.
+  * Cleaned and updated debian/copyright.
+  * Removed manually added libx11-6 dependency.
+  * Only Build-Depends on libgpmg1-dev on GNU/Linux systems.
+  * Cosmetic unification to debian/changelog.
+  * debian/rules:
+    - Remove generated files.
+    - Give exec perms to qemu-ifup.
+
+ -- Guillem Jover <guillem@debian.org>  Sun,  8 Aug 2004 17:24:08 +0200
+
+qemu (0.5.5-2) unstable; urgency=low
+
+  * Re-enable SDL disabled while I was bugchasing. (Closes: #255014)
+  * Yes, this is really 0.5.5. (Closes: #254655)
+  * Enable slirp networking. (Closes: #253573)
+  * Add Build-Depends on libgpmg1-dev (found by Bastian Blank, probably breaks
+    Hurd but that's a problem for another day).
+
+ -- Paul Russell <prussell@debian.org>  Thu, 24 Jun 2004 06:26:42 +0200
+
+qemu (0.5.5-1) unstable; urgency=low
+
+  * New upstream release. (Closes: #237556, #237556)
+  * Applied patch to add options to make_debian_root.sh. (Closes: #238787)
+  * Applied patch for other archs: hmmm... (Closes: #251420)
+  * Do umount -d in make_debian_root.sh. (Closes: #251775)
+
+ -- Paul Russell <prussell@debian.org>  Tue,  1 Jun 2004 03:50:05 +0200
+
+qemu (0.5.4-1) unstable; urgency=low
+
+  * New upstream release. (Closes: #246634)
+  * qemu-mkcow included in upstream.
+  * Added tundev program source in doc, to see if people find it useful.
+
+ -- Paul Russell <prussell@debian.org>  Mon,  3 May 2004 08:14:49 +0200
+
+qemu (0.5.3-1) unstable; urgency=low
+
+  * New upstream release. (Closes: #237556)
+  * Use aalib-config --static-libs. (Closes: #243325)
+  * Document Control-Shift to release mouse pointer. (Closes: #238074)
+
+ -- Paul Russell <prussell@debian.org>  Tue, 13 Apr 2004 02:58:49 +0200
+
+qemu (0.5.2-4) unstable; urgency=low
+
+  * Fix PPC install (Michel Daenzer patch). (Closes: #238431)
+  * Simplify deps (might be wrong, but it's neater). (Closes: #238430)
+
+ -- Paul Russell <prussell@debian.org>  Wed, 17 Mar 2004 01:35:47 +0100
+
+qemu (0.5.2-3) unstable; urgency=low
+
+  * Make compile on woody. (Closes: #238163)
+  * Include qemu-doc.html. (Closes: #238076)
+  * Wrote qemu-i386 man page. (Closes: #238077)
+
+ -- Paul Russell <prussell@debian.org>  Mon, 15 Mar 2004 23:56:25 +0100
+
+qemu (0.5.2-2) unstable; urgency=low
+
+  * Fix build problem so bios.bin etc. can be found. (Closes: #237553)
+
+ -- Paul Russell <prussell@debian.org>  Fri, 12 Mar 2004 05:43:00 +0100
+
+qemu (0.5.2-1) unstable; urgency=low
+
+  * Initial Release. (Closes: #187407)
+
+ -- Paul Russell <prussell@debian.org>  Wed,  3 Mar 2004 02:18:54 +0100
+
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..7ed6ff8
--- /dev/null
@@ -0,0 +1 @@
+5
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..950b305
--- /dev/null
@@ -0,0 +1,31 @@
+Source: qemu
+Section: misc
+Priority: optional
+Maintainer: Debian QEMU Team <pkg-qemu-devel@lists.alioth.debian.org>
+Uploaders: Aurelien Jarno <aurel32@debian.org>, Riku Voipio <riku@debian.org>,
+ Josh Triplett <josh@psas.pdx.edu>
+Build-Depends: debhelper (>= 5), quilt (>= 0.40), binutils (>= 2.16), nasm,
+ libx11-dev, libsdl1.2-dev (>> 1.2.1), libncurses5-dev, zlib1g-dev,
+ texi2html, sharutils, libgnutls-dev, libesd0-dev, etherboot,
+ libpulse-dev,
+ libfreebsd-dev [kfreebsd-i386 kfreebsd-amd64], 
+ libasound2-dev [!kfreebsd-i386 !kfreebsd-amd64],
+ libbluetooth-dev [!kfreebsd-i386 !kfreebsd-amd64],
+ libgpmg1-dev [amd64 arm armel hppa i386 powerpc sparc ppc64],
+ scratchbox-core (>= 1.0.12) [i386]
+Standards-Version: 3.8.0
+
+Package: sb2-qemu
+Architecture: amd64 i386 powerpc
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Qemu for scratchbox2
+ Qemu packaging for sb2. This should become eventually temporary
+ when mainstream qemu merges any remaining patches.
+
+Package: sb1-qemu
+Architecture: i386
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Replaces: scratchbox-devkit-cputransp
+Conflicts: scratchbox-devkit-cputransp
+Description: Qemu scratchbox devkit
+ The qemu for the scratchbox1 lovers.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..35348bd
--- /dev/null
@@ -0,0 +1,53 @@
+This package was debianized by Paul Russell <prussell@debian.org> on
+Wed,  3 Mar 2004 02:18:54 +0100.
+
+Then maintained as part of the team by:
+
+    Guilherme de S. Pastore <gpastore@debian.org>
+    Elrond <elrond@samba-tng.org>
+    Guillem Jover <guillem@debian.org>
+
+Now maintained as a team by:
+
+    Aurelien Jarno <aurel32@debian.org>
+    Josh Triplett <josh@psas.pdx.edu>
+    Riku Voipio <riku@debian.org>
+
+The upstream source was downloaded from:
+
+    <http://www.qemu.org/download.html>
+
+    All the binary blobs without sources contained in the pc-bios/ directory
+    in the original upstream tarball have been removed starting from Debian
+    package version 0.6.0.dfsg.1-1. Those roms which are free can be found
+    in split packages of their own, represented accordingly in the dependecy
+    relationships.
+
+Upstream Author:
+
+    Fabrice Bellard <fabrice.bellard@free.fr>
+
+Copyright:
+
+    Copyright (C) 2003, 2004, 2005, 2006, 2007  Fabrice Bellard
+
+License:
+
+    QEMU as a whole is released under the GNU General Public License.
+    On Debian systems, the complete text of the GNU General Public License
+    can be found in the file /usr/share/common-licenses/GPL.
+
+    Parts of QEMU have specific licenses which are compatible with the
+    GNU General Public License. Hence each source file contains its own
+    licensing information.
+
+    In particular, the QEMU virtual CPU core library (libqemu.a) is
+    released under the GNU Lesser General Public License. On Debian systems,
+    the complete text of the GNU Lesser General Public License can be found
+    in the file /usr/share/common-licenses/LGPL.
+
+    Many hardware device emulation sources are released under the BSD license.
+    On Debian systems, the complete text of the BSD license be found in the
+    file /usr/share/common-licenses/BSD.
+
+
diff --git a/debian/cputransp-methods b/debian/cputransp-methods
new file mode 100644 (file)
index 0000000..6e79c83
--- /dev/null
@@ -0,0 +1,2 @@
+qemu-arm-cvs-m
+sbrsh
diff --git a/debian/overrides/qemu b/debian/overrides/qemu
new file mode 100644 (file)
index 0000000..5e81b13
--- /dev/null
@@ -0,0 +1,7 @@
+qemu: shlib-with-non-pic-code usr/bin/qemu-ppc
+qemu: shlib-with-non-pic-code usr/bin/qemu-sparc
+qemu: shlib-with-non-pic-code usr/bin/qemu-i386
+qemu: shlib-with-non-pic-code usr/bin/qemu-arm
+qemu: shlib-with-non-pic-code usr/bin/qemu-armeb
+qemu: shlib-with-non-pic-code usr/bin/qemu-mips
+qemu: shlib-with-non-pic-code usr/bin/qemu-mipsel
diff --git a/debian/qemu-user.1 b/debian/qemu-user.1
new file mode 100644 (file)
index 0000000..c9e1e9e
--- /dev/null
@@ -0,0 +1,38 @@
+.\" $Id: qemu-user.1 325 2008-08-09 21:39:16Z aurel32 $
+.TH qemu\-user 1 2007-02-08 "0.9.0" Debian
+.SH NAME
+qemu\-user \- QEMU User Emulator
+.SH SYNOPSIS
+.B qemu\-user
+.RI [ options ]
+.I program
+.RI [ program-arguments... ]
+.SH DESCRIPTION
+The
+.B qemu\-user
+emulator can run binaries for other architectures but with the same operating
+system as the current one.
+.SH OPTIONS
+.TP
+.BR \-h
+Print this help.
+.TP
+.BR \-g
+Wait gdb connection to port 1234.
+.TP
+.BR \-L " \fI<path>\fP"
+Set the elf interpreter prefix (default=\fI/usr/gnemul/qemu\-arm\fP).
+.TP
+.BR \-s " \fI<size>\fP"
+Set the stack size in bytes (default=\fI524288\fP).
+.TP
+.BR \-d " \fI<options>\fP"
+Activate log (logfile=\fI/tmp/qemu.log\fP)
+.TP
+.BR \-p " \fI<pagesize>\fP"
+Set the host page size to 'pagesize'.
+.SH SEE ALSO
+.BR qemu (1),
+.BR qemu\-img (1).
+.SH AUTHOR
+This manual page was written by Guillem Jover <guillem@debian.org>.
diff --git a/debian/qemu.dirs b/debian/qemu.dirs
new file mode 100644 (file)
index 0000000..58660d4
--- /dev/null
@@ -0,0 +1 @@
+usr/share/qemu/
diff --git a/debian/qemu.doc-base b/debian/qemu.doc-base
new file mode 100644 (file)
index 0000000..d3b0f8a
--- /dev/null
@@ -0,0 +1,12 @@
+Document: qemu-doc
+Title: QEMU User Manual
+Author: Fabrice Bellard
+Abstract: The QEMU user manual intends to make the user understand what
+ qemu is/does, and to guide them through the first steps of getting
+ the emulator to work, documenting parameters and commands, among other
+ useful things.
+Section: Emulators
+
+Format: HTML
+Index: /usr/share/doc/qemu/qemu-doc.html
+Files: /usr/share/doc/qemu/qemu-doc.html
diff --git a/debian/qemu.docs b/debian/qemu.docs
new file mode 100644 (file)
index 0000000..d227b95
--- /dev/null
@@ -0,0 +1,4 @@
+README
+TODO
+qemu-doc.html
+debian/tundev.c
diff --git a/debian/qemu.install b/debian/qemu.install
new file mode 100644 (file)
index 0000000..f3da625
--- /dev/null
@@ -0,0 +1,3 @@
+debian/qemu-ifup etc/
+debian/qemu-make-debian-root usr/sbin/
+debian/overrides/qemu usr/share/lintian/overrides/
diff --git a/debian/qemu.links b/debian/qemu.links
new file mode 100644 (file)
index 0000000..8f0732b
--- /dev/null
@@ -0,0 +1,40 @@
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-alpha.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-cris.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-arm.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-armeb.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-i386.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-m68k.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-mips.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-mipsel.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-ppc.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-ppc64.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-ppc64abi32.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-sh4.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-sh4eb.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-sparc.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-sparc32plus.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-sparc64.1
+usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-x86_64.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-arm.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-cris.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-i386.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-m68k.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-mips.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-mips64.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-mips64el.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-mipsel.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-ppc.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-ppc64.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-ppcemb.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-sh4.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-sh4eb.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-sparc.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-sparc64.1
+usr/share/man/man1/qemu.1 usr/share/man/man1/qemu-system-x86_64.1
+usr/share/bochs/BIOS-qemu-latest usr/share/qemu/bios.bin
+usr/share/vgabios/vgabios.bin usr/share/qemu/vgabios.bin
+usr/share/vgabios/vgabios.cirrus.bin usr/share/qemu/vgabios-cirrus.bin
+usr/share/proll/proll-qemu.elf usr/share/qemu/proll.elf
+usr/share/openhackware/ppc_rom.bin usr/share/qemu/ppc_rom.bin
+usr/share/openbios/openbios-sparc32 usr/share/qemu/openbios-sparc32
+usr/share/openbios/openbios-sparc64 usr/share/qemu/openbios-sparc64
diff --git a/debian/qemu.manpages b/debian/qemu.manpages
new file mode 100644 (file)
index 0000000..ae4f28d
--- /dev/null
@@ -0,0 +1,2 @@
+debian/qemu-make-debian-root.8
+debian/qemu-user.1
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..6e7179a
--- /dev/null
@@ -0,0 +1,133 @@
+#!/usr/bin/make -f
+#
+# $Id: rules 366 2008-12-23 16:19:26Z aurel32 $
+#
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+       CFLAGS = -O0
+endif
+
+# Support multiple makes at once
+ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
+NJOBS := -j $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
+endif
+
+# Architecture/system specific configuration
+DEB_HOST_ARCH_OS = $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)
+DEB_HOST_ARCH_CPU = $(shell dpkg-architecture -qDEB_HOST_ARCH_CPU)
+
+
+TARGET_SYSTEM_TCG    = arm-softmmu i386-softmmu
+TARGET_LINUX_TCG     = arm-linux-user i386-linux-user
+package_list            = obj-sb2/config-host.mak
+install_list            = sb2-qemu-install
+sb1_prefix                      = /scratchbox/devkits/cputransp
+
+target_system_list = $(TARGET_SYSTEM_TCG)
+
+ifeq ($(DEB_HOST_ARCH_OS),linux)
+       conf_arch += --audio-drv-list=sdl
+       target_linux_list += $(TARGET_LINUX_TCG)
+endif
+ifeq ($(DEB_HOST_ARCH_OS),kfreebsd)
+       conf_arch += --audio-drv-list=oss,sdl,esd,pa
+endif
+
+ifeq ($(DEB_HOST_ARCH_CPU),i386)
+       conf_arch += --cpu=i386
+       package_list += obj-sb1/config-host.mak
+       install_list += sb1-qemu-install
+endif
+ifeq ($(DEB_HOST_ARCH_CPU),sparc)
+       conf_arch += --cpu=sparc
+endif
+
+qemu_docs = \
+       qemu-doc.html \
+       qemu-tech.html \
+       qemu.1 \
+       qemu-img.1
+
+obj-sb2/config-host.mak: configure
+       dh_testdir
+       mkdir obj-sb2
+       ( cd obj-sb2; CFLAGS="$(CFLAGS)" ../configure \
+               --prefix=/usr \
+               --interp-prefix=/ \
+               --disable-blobs \
+               --target-list="$(target_system_list) $(target_linux_list)" \
+               $(conf_arch) )
+       ( cd obj-sb2; $(MAKE) $(NJOBS) )
+
+obj-sb1/config-host.mak: configure
+       dh_testdir
+       mkdir obj-sb1
+       ( cd obj-sb1; CFLAGS="$(CFLAGS) $(SB1_CFLAGS)"  ../configure \
+               --prefix=$(sb1_prefix) \
+               --interp-prefix=/ \
+               --static \
+               --target-list="arm-linux-user" \
+               --disable-kqemu --disable-sdl )
+       ( cd obj-sb1; $(MAKE) $(NJOBS) )
+
+build: $(package_list)
+
+clean:
+       dh_testdir
+       dh_testroot
+       
+       [ ! -f config-host.mak ] || $(MAKE) distclean
+       
+       rm -rf obj-sb1 obj-sb2
+       rm -f $(qemu_docs)
+       
+       dh_clean
+
+# cputransp-methods should be generated at postinst
+sb1-qemu-install:
+       mkdir -p debian/sb1-qemu/$(sb1_prefix)/{bin,etc}
+       cp debian/cputransp-methods debian/sb1-qemu/$(sb1_prefix)/etc
+       cp obj-sb1/*-linux-user/qemu-* debian/sb1-qemu/$(sb1_prefix)/bin
+       ln -sf $(sb1_prefix)/bin/qemu-arm debian/sb1-qemu/$(sb1_prefix)/bin/qemu-arm-cvs-m
+
+sb2-qemu-install:
+       mkdir -p debian/sb2-qemu/usr/bin
+       cp obj-sb2/arm-linux-user/qemu-arm debian/sb2-qemu/usr/bin/sb2-qemu-arm
+       cp obj-sb2/i386-linux-user/qemu-i386  debian/sb2-qemu/usr/bin/sb2-qemu-i386
+       cp obj-sb2/arm-softmmu/qemu-system-arm  debian/sb2-qemu/usr/bin/sb2-qemu-system-arm
+       cp obj-sb2/i386-softmmu/qemu  debian/sb2-qemu/usr/bin/sb2-qemu-system-i386
+
+install: build $(install_list)
+       dh_testdir
+       dh_testroot
+#      dh_clean -k
+       dh_installdirs -a
+
+binary-indep:
+# Nothing to do.
+
+binary-arch: install
+       dh_testdir
+       dh_testroot
+#      dh_install -a
+#      dh_installdebconf -a
+       dh_installdocs -s
+       dh_installexamples -s
+#      dh_installlogrotate -a
+       dh_installman -s
+       dh_installinfo -s
+       dh_installchangelogs -s Changelog
+       dh_link -s
+       dh_strip -s
+       dh_compress -s
+       dh_fixperms -s
+       dh_installdeb -s
+       dh_shlibdeps -s
+       dh_gencontrol -s
+       dh_md5sums -s
+       dh_builddeb -s
+
+binary: binary-indep binary-arch
+
+.PHONY: build clean binary-indep binary-arch binary install
+
diff --git a/debian/tundev.c b/debian/tundev.c
new file mode 100644 (file)
index 0000000..43ed62a
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * $Id: tundev.c 325 2008-08-09 21:39:16Z aurel32 $
+ */
+
+#define _GNU_SOURCE /* asprintf */
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <net/if.h>
+#include <linux/if_tun.h>
+
+/* Tiny code to open tap/tun device, and hand the fd to qemu.
+   Run as root, drops to given user. */
+int main(int argc, char *argv[])
+{
+       struct ifreq ifr;
+       struct passwd *p;
+       unsigned int i;
+       char *newargs[argc + 1];
+       int fd;
+
+       if (argc < 4) {
+               fprintf(stderr,
+                       "Usage: tundev user logfile qemu <qemu options>...\n");
+               exit(1);
+       }
+
+       fd = open("/dev/net/tun", O_RDWR);
+       if (fd < 0) {
+               perror("Could not open /dev/net/tun");
+               exit(1);
+       }
+
+       memset(&ifr, 0, sizeof(ifr));
+       ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+       strncpy(ifr.ifr_name, "tun%d", IFNAMSIZ);
+       if (ioctl(fd, TUNSETIFF, (void *) &ifr) != 0) {
+               perror("Could not get tun device");
+               exit(1);
+       }
+
+       /* Set userid. */
+       p = getpwnam(argv[1]);
+       if (!p) {
+               fprintf(stderr, "No user '%s'\n", argv[1]);
+               exit(1);
+       }
+       setgroups(0, NULL);
+       setgid(p->pw_gid);
+       if (setuid(p->pw_uid) != 0) {
+               perror("setting uid");
+               exit(1);
+       }
+
+       /* Insert -tun-fd */
+       newargs[0] = argv[3];
+       newargs[1] = "-tun-fd";
+       asprintf(&newargs[2], "%d", fd);
+       for (i = 4; i <= argc; i++)
+               newargs[i-1] = argv[i];
+
+       if (strcmp(argv[2], "-") == 0) {
+               execvp(newargs[0], newargs);
+               exit(1);
+       }
+
+       switch (fork()) {
+       case 0: {
+               close(1);
+               close(2);
+               open(argv[2], O_WRONLY|O_APPEND);
+               open(argv[2], O_WRONLY|O_APPEND);
+               close(0);
+               execvp(newargs[0], newargs);
+               exit(1);
+       }
+       case -1:
+               perror("fork failed");
+               exit(1);
+       }
+       printf("%s\n", ifr.ifr_name);
+       exit(0);
+}
diff --git a/debian/watch b/debian/watch
new file mode 100644 (file)
index 0000000..b33ee8e
--- /dev/null
@@ -0,0 +1,3 @@
+version=3
+
+http://bellard.org/qemu/download.html  qemu-([\d.]*).tar.gz    debian  uupdate
diff --git a/hw/beagle.c b/hw/beagle.c
new file mode 100644 (file)
index 0000000..d679de9
--- /dev/null
@@ -0,0 +1,279 @@
+/*\r
+ * Beagle board emulation. http://beagleboard.org/\r
+ * \r
+ * Copyright (C) 2008 yajin(yajin@vm-kernel.org)\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License as\r
+ * published by the Free Software Foundation; either version 2 or\r
+ * (at your option) version 3 of the License.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,\r
+ * MA 02111-1307 USA\r
+ */\r
+\r
+#include "qemu-common.h"\r
+#include "sysemu.h"\r
+#include "omap.h"\r
+#include "arm-misc.h"\r
+#include "irq.h"\r
+#include "console.h"\r
+#include "boards.h"\r
+#include "i2c.h"\r
+#include "devices.h"\r
+#include "flash.h"\r
+#include "hw.h"\r
+#include "block.h"\r
+\r
+#define BEAGLE_NAND_CS                 0\r
+\r
+#define GPMC_NOR             0\r
+#define GPMC_NAND           1\r
+#define GPMC_MDOC           2\r
+#define GPMC_ONENAND    3\r
+#define MMC_NAND            4\r
+#define MMC_ONENAND     5\r
+\r
+\r
+#define TST_DEVICE              0x0\r
+#define EMU_DEVICE              0x1\r
+#define HS_DEVICE               0x2\r
+#define GP_DEVICE               0x3\r
+\r
+#define DEBUG_BEAGLE\r
+\r
+#ifdef DEBUG_BEAGLE\r
+#define BEAGLE_DEBUG(...)    do { fprintf(stderr, __VA_ARGS__); } while(0)\r
+#else\r
+#define BEAGLE_DEBUG(x)    \r
+#endif\r
+\r
+/* Beagle board support */\r
+struct beagle_s {\r
+    struct omap_mpu_state_s *cpu;\r
+    \r
+    struct nand_bflash_s *nand;\r
+    struct omap3_lcd_panel_s *lcd_panel;\r
+    i2c_bus *i2c;\r
+    struct twl4030_s *twl4030;\r
+};\r
+\r
+\r
+\r
+static struct arm_boot_info beagle_binfo = {\r
+    .ram_size = 0x08000000,\r
+};\r
+\r
+\r
+static uint32_t beagle_nand_read16(void *opaque, target_phys_addr_t addr)\r
+{\r
+       struct beagle_s *s = (struct beagle_s *) opaque;\r
+    //BEAGLE_DEBUG("beagle_nand_read16 offset %x\n",addr);\r
+\r
+       switch (addr)\r
+       {\r
+               case 0x7C: /*NAND_COMMAND*/\r
+               case 0x80: /*NAND_ADDRESS*/\r
+                       OMAP_BAD_REG(addr);\r
+                       break;\r
+               case 0x84: /*NAND_DATA*/\r
+                       return nandb_read_data16(s->nand);\r
+                       break;\r
+               default:\r
+                       OMAP_BAD_REG(addr);\r
+                       break;\r
+       }\r
+    return 0;\r
+}\r
+\r
+static void beagle_nand_write16(void *opaque, target_phys_addr_t addr,\r
+                uint32_t value)\r
+{\r
+       struct beagle_s *s = (struct beagle_s *) opaque;\r
+    switch (addr)\r
+       {\r
+               case 0x7C: /*NAND_COMMAND*/\r
+                       nandb_write_command(s->nand,value);\r
+                       break;\r
+               case 0x80: /*NAND_ADDRESS*/\r
+                       nandb_write_address(s->nand,value);\r
+                       break;\r
+               case 0x84: /*NAND_DATA*/\r
+                       nandb_write_data16(s->nand,value);\r
+                       break;\r
+               default:\r
+                       OMAP_BAD_REG(addr);\r
+                       break;\r
+       }\r
+}\r
+\r
+\r
+static CPUReadMemoryFunc *beagle_nand_readfn[] = {\r
+        beagle_nand_read16,\r
+        beagle_nand_read16,\r
+        omap_badwidth_read32,\r
+};\r
+\r
+static CPUWriteMemoryFunc *beagle_nand_writefn[] = {\r
+        beagle_nand_write16,\r
+        beagle_nand_write16,\r
+        omap_badwidth_write32,\r
+};\r
+\r
+static void beagle_nand_setup(struct beagle_s *s)\r
+{\r
+       //int iomemtype;\r
+       \r
+       /*MT29F2G16ABC*/\r
+       s->nand = nandb_init(NAND_MFR_MICRON,0xba);\r
+       /*wp=1, no write protect!!! */\r
+       //nand_set_wp(s->nand, 1);\r
+\r
+/*     iomemtype = cpu_register_io_memory(0, beagle_nand_readfn,\r
+                    beagle_nand_writefn, s);\r
+    cpu_register_physical_memory(0x6e00007c, 0xc, iomemtype);*/\r
+    omap_gpmc_attach(s->cpu->gpmc, 0, 0, NULL, NULL, s, beagle_nand_readfn, beagle_nand_writefn);\r
+\r
+        /*BOOT from nand*/\r
+    omap3_set_mem_type(s->cpu,GPMC_NAND);\r
+\r
+}\r
+\r
+static int beagle_nand_read_page(struct beagle_s *s,uint8_t *buf, uint16_t page_addr)\r
+{\r
+       uint16_t *p;\r
+       int i;\r
+\r
+       p=(uint16_t *)buf;\r
+\r
+       /*send command 0x0*/\r
+       beagle_nand_write16(s,0x7C,0);\r
+       /*send page address */\r
+       beagle_nand_write16(s,0x80,page_addr&0xff);\r
+       beagle_nand_write16(s,0x80,(page_addr>>8)&0x7);\r
+       beagle_nand_write16(s,0x80,(page_addr>>11)&0xff);\r
+       beagle_nand_write16(s,0x80,(page_addr>>19)&0xff);\r
+       beagle_nand_write16(s,0x80,(page_addr>>27)&0xff);\r
+       /*send command 0x30*/\r
+       beagle_nand_write16(s,0x7C,0x30);\r
+\r
+       for (i=0;i<0x800/2;i++)\r
+       {\r
+               *p++ = beagle_nand_read16(s,0x84);\r
+       }\r
+       return 1;\r
+}\r
+\r
+/*read the xloader from NAND Flash into internal RAM*/\r
+static int beagle_boot_from_nand(struct beagle_s *s)\r
+{\r
+       uint32_t        loadaddr, len;\r
+       uint8_t nand_page[0x800],*load_dest;\r
+       uint32_t nand_pages,i;\r
+\r
+       /* The first two words(8 bytes) in first nand flash page have special meaning.\r
+               First word:x-loader len\r
+               Second word: x-load address in internal ram */\r
+       beagle_nand_read_page(s,nand_page,0);\r
+       len = *((uint32_t*)nand_page);\r
+       loadaddr =  *((uint32_t*)(nand_page+4));\r
+       if ((len==0)||(loadaddr==0)||(len==0xffffffff)||(loadaddr==0xffffffff))\r
+               return (-1);\r
+\r
+       /*put the first page into internal ram*/\r
+       load_dest = phys_ram_base +beagle_binfo.ram_size;\r
+       load_dest += loadaddr-OMAP3_SRAM_BASE;\r
+       \r
+       BEAGLE_DEBUG("load_dest %x phys_ram_base %x \n",(unsigned)load_dest,(unsigned)phys_ram_base);\r
+       \r
+       memcpy(load_dest,nand_page+8,0x800-8);\r
+       load_dest += 0x800-8;\r
+\r
+       nand_pages = len/0x800;\r
+       if (len%0x800!=0)\r
+               nand_pages++;\r
+\r
+       for (i=1;i<nand_pages;i++)\r
+       {\r
+               beagle_nand_read_page(s,nand_page,i*0x800);\r
+               memcpy(load_dest,nand_page,0x800);\r
+               load_dest += 0x800;\r
+       }\r
+       s->cpu->env->regs[15] = loadaddr;\r
+       return 0;\r
+\r
+}\r
+\r
+static int beagle_rom_emu(struct beagle_s *s)\r
+{\r
+    if (!omap3_mmc_boot(s->cpu))\r
+        if (beagle_boot_from_nand(s) < 0)\r
+            return -1;\r
+       return 0;\r
+}\r
+\r
+static void beagle_dss_setup(struct beagle_s *s)\r
+{\r
+       s->lcd_panel = omap3_lcd_panel_init();\r
+       omap3_lcd_panel_attach(s->cpu->dss, 0, s->lcd_panel);\r
+       s->lcd_panel->dss = s->cpu->dss;\r
+}\r
+\r
+static void beagle_mmc_cs_cb(void *opaque, int line, int level)\r
+{\r
+    /* TODO: this seems to actually be connected to the menelaus, to\r
+     * which also both MMC slots connect.  */\r
+    omap_mmc_enable((struct omap_mmc_s *) opaque, !level);\r
+\r
+    printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);\r
+}\r
+\r
+static void beagle_i2c_setup(struct beagle_s *s)\r
+{\r
+    /* Attach the CPU on one end of our I2C bus.  */\r
+    s->i2c = omap_i2c_bus(s->cpu->i2c[0]);\r
+\r
+    s->twl4030 = twl4030_init(s->i2c, s->cpu->irq[0][OMAP_INT_35XX_SYS_NIRQ]);\r
+}\r
+\r
+\r
+static void beagle_init(ram_addr_t ram_size, int vga_ram_size,\r
+                const char *boot_device,\r
+                const char *kernel_filename, const char *kernel_cmdline,\r
+                const char *initrd_filename, const char *cpu_model)\r
+{\r
+    struct beagle_s *s = (struct beagle_s *) qemu_mallocz(sizeof(*s));\r
+    int sdram_size = beagle_binfo.ram_size;\r
+\r
+       if (ram_size < sdram_size +  OMAP3530_SRAM_SIZE) {\r
+        fprintf(stderr, "This architecture uses %i bytes of memory\n",\r
+                        sdram_size + OMAP3530_SRAM_SIZE);\r
+        exit(1);\r
+    }\r
+       s->cpu = omap3530_mpu_init(sdram_size, NULL);\r
+       beagle_nand_setup(s);\r
+       beagle_i2c_setup(s);\r
+       beagle_dss_setup(s);\r
+       omap3_set_device_type(s->cpu,GP_DEVICE);\r
+    if (beagle_rom_emu(s) < 0) {\r
+               fprintf(stderr,"boot from MMC and nand failed \n");\r
+               exit(-1);\r
+       }\r
+}\r
+\r
+\r
+\r
+QEMUMachine beagle_machine = {\r
+    .name = "beagle",\r
+    .desc =     "Beagle board (OMAP3530)",\r
+    .init =     beagle_init,\r
+    .ram_require =     (0x08000000 +  OMAP3530_SRAM_SIZE) | RAMSIZE_FIXED,\r
+};\r
+\r
index 1e62594..8654f03 100644 (file)
@@ -128,4 +128,7 @@ extern QEMUMachine musicpal_machine;
 /* tosa.c */
 extern QEMUMachine tosapda_machine;
 
+/* beagle.c */
+extern QEMUMachine beagle_machine;
+
 #endif
index faba93d..2d1784f 100644 (file)
@@ -26,6 +26,14 @@ void nand_getpins(struct nand_flash_s *s, int *rb);
 void nand_setio(struct nand_flash_s *s, uint8_t value);
 uint8_t nand_getio(struct nand_flash_s *s);
 
+/* nand_bpage.c */
+struct nand_bflash_s;
+struct nand_bflash_s *nandb_init(int manf_id, int chip_id);
+void nandb_write_data16(struct nand_bflash_s *s, uint16_t value);
+uint16_t nandb_read_data16(struct nand_bflash_s *s);
+void nandb_write_address(struct nand_bflash_s *s, uint16_t value);
+void nandb_write_command(struct nand_bflash_s *s, uint16_t value);
+
 #define NAND_MFR_TOSHIBA       0x98
 #define NAND_MFR_SAMSUNG       0xec
 #define NAND_MFR_FUJITSU       0x04
index 396c562..7a80bcb 100644 (file)
--- a/hw/i2c.h
+++ b/hw/i2c.h
@@ -87,4 +87,8 @@ void tmp105_set(i2c_slave *i2c, int temp);
 struct i2c_slave *lm8323_init(i2c_bus *bus, qemu_irq nirq);
 void lm832x_key_event(struct i2c_slave *i2c, int key, int state);
 
+/* twl4030.c */
+struct twl4030_s;
+struct twl4030_s *twl4030_init(i2c_bus *bus, qemu_irq irq);
+
 #endif
diff --git a/hw/nand_bpage.c b/hw/nand_bpage.c
new file mode 100644 (file)
index 0000000..586b914
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+ * Big page NAND flash memory emulation.  based on 256M/16 bit flash datasheet from micro(MT29F2G16ABC)
+ *
+ * Copyright (C) 2008 yajin(yajin@vm-kernel.org)
+ *
+ * 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 or
+ * (at your option) version 3 of the License.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "hw.h"
+#include "flash.h"
+#include "block.h"
+#include "sysemu.h"
+
+
+#define MAX_PAGE               0x800
+#define MAX_OOB                0x40
+#define PAGE_MASK              (0xffff)
+#define BUS_WIDTH_16  2
+#define BUS_WIDTH_8 1
+
+//#define DEBUG
+
+struct nand_flash_info_s
+{
+    uint8_t  manf_id,chip_id;
+    uint32_t size;;
+    int bus_width;
+    int page_shift;
+    int oob_shift;
+    int block_shift;
+};
+struct nand_flash_info_s nand_flash_info[1] =
+{
+    {0x2c, 0xba, 256,2, 11, 6, 6}
+};
+
+
+struct nand_bflash_s
+{
+       BlockDriverState *bdrv;
+    uint8_t manf_id, chip_id;
+    uint32_t size, pages;
+    uint32_t page_size, page_shift;
+    uint32_t oob_size, oob_shift;
+    uint32_t page_oob_size;
+    uint32_t page_sectors;      /*sector = 512 bytes */
+    uint32_t block_shift, block_pages;  /*how many pages in a block */
+    uint32_t bus_width;         /*bytes */
+
+    //uint8_t *internal_buf;
+    uint8_t io[MAX_PAGE + MAX_OOB + 0x400];
+    uint8_t *ioaddr;
+    int iolen;
+
+
+    uint32 addr_low, addr_high;
+    uint32 addr_cycle;
+
+    uint32 cmd, status;
+  #ifdef DEBUG  
+    FILE *fp;
+  #endif
+};
+
+
+#ifdef DEBUG
+static void debug_init(struct nand_bflash_s *s)
+{
+       s->fp=fopen("nandflash_debug.txt","w+");
+       if (s->fp==NULL)
+       {
+               fprintf(stderr,"can not open nandflash_debug.txt \n");
+               exit(-1);
+       }
+               
+}
+static void debug_out(struct nand_bflash_s *s,const char* format, ...)
+{
+       va_list ap;
+       if (s->fp)
+       {
+                va_start(ap, format);
+        vfprintf(s->fp, format, ap);
+        fflush(s->fp);
+       va_end(ap);
+       }
+}
+
+#else
+static void debug_init(struct nand_bflash_s *s)
+{
+       
+}
+static void debug_out(struct nand_bflash_s *s,const char* format, ...)
+{
+       
+}
+
+#endif
+
+static inline uint32_t get_page_number(struct nand_bflash_s *s,
+                                       uint32_t addr_low, uint32 addr_high)
+{
+    return (addr_high << 16) + ((addr_low >> 16) & PAGE_MASK);
+}
+
+
+
+/* Program a single page */
+static void nand_blk_write(struct nand_bflash_s *s)
+{
+    uint32_t page_number, off,  sector, soff;
+    uint8_t *iobuf=NULL;
+
+       if (!iobuf)
+       iobuf = qemu_mallocz((s->page_sectors + 2) * 0x200);
+    if (!iobuf)
+    {
+        fprintf(stderr, "can not alloc io buffer size 0x%x \n",
+                (s->page_sectors + 2) * 0x200);
+        cpu_abort(cpu_single_env, "%s: can not alloc io buffer size 0x%x \n",
+                  __FUNCTION__, (s->page_sectors + 2) * 0x200);
+    }
+
+    page_number = get_page_number(s, s->addr_low, s->addr_high);
+
+    debug_out(s,"nand_blk_write page number %x s->addr_low %x s->addr_high %x\n",page_number,s->addr_low,s->addr_high);
+
+    if (page_number >= s->pages)
+        return;
+
+    off = page_number * s->page_oob_size + (s->addr_low & PAGE_MASK);
+    sector = off >> 9;
+    soff = off & 0x1ff;
+    if (bdrv_read(s->bdrv, sector, iobuf, s->page_sectors + 2) == -1)
+    {
+        printf("%s: read error in sector %i\n", __FUNCTION__, sector);
+        return;
+    }
+
+    memcpy(iobuf + soff, s->io, s->iolen);
+
+    if (bdrv_write(s->bdrv, sector, iobuf, s->page_sectors + 2) == -1)
+        printf("%s: write error in sector %i\n", __FUNCTION__, sector);
+
+    //qemu_free(iobuf);
+}
+
+
+static void nandb_blk_load(struct nand_bflash_s *s)
+{
+    uint32_t page_number, offset;
+    offset = s->addr_low & PAGE_MASK;
+
+    page_number = get_page_number(s, s->addr_low, s->addr_high);
+       debug_out(s,"nandb_blk_load page number %x s->addr_low %x s->addr_high %x\n",page_number,s->addr_low,s->addr_high);
+    if (page_number >= s->pages)
+        return;
+       
+    if (bdrv_read(s->bdrv, (page_number * s->page_oob_size + offset) >> 9,
+                  s->io, (s->page_sectors + 2)) == -1)
+        printf("%s: read error in sector %i\n",
+               __FUNCTION__, page_number * s->page_oob_size);
+    s->ioaddr = s->io + ((page_number * s->page_oob_size + offset) & 0x1ff);
+}
+
+
+/* Erase a single block */
+static void nandb_blk_erase(struct nand_bflash_s *s)
+{
+    uint32_t page_number,  sector, addr, i;
+
+    uint8_t iobuf[0x200];
+
+        memset(iobuf,0xff,sizeof(iobuf));
+        s->addr_low = s->addr_low & ~((1 << (16 + s->block_shift)) - 1);
+    page_number = get_page_number(s, s->addr_low, s->addr_high);
+    debug_out(s,"nandb_blk_erase page number %x s->addr_low %x s->addr_high %x\n",page_number,s->addr_low,s->addr_high);
+    if (page_number >= s->pages)
+        return;
+
+    addr = page_number * s->page_oob_size;
+    
+    sector = addr >> 9;
+    if (bdrv_read(s->bdrv, sector, iobuf, 1) == -1)
+        printf("%s: read error in sector %i\n", __FUNCTION__, sector);
+    memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1);
+    if (bdrv_write(s->bdrv, sector, iobuf, 1) == -1)
+        printf("%s: write error in sector %i\n", __FUNCTION__, sector);
+
+    memset(iobuf, 0xff, 0x200);
+    i = (addr & ~0x1ff) + 0x200;
+    for (addr += (s->page_oob_size*s->block_pages - 0x200); i < addr; i += 0x200)
+        if (bdrv_write(s->bdrv, i >> 9, iobuf, 1) == -1)
+            printf("%s: write error in sector %i\n", __FUNCTION__, i >> 9);
+
+    sector = i >> 9;
+    if (bdrv_read(s->bdrv, sector, iobuf, 1) == -1)
+        printf("%s: read error in sector %i\n", __FUNCTION__, sector);
+    memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1);
+    if (bdrv_write(s->bdrv, sector, iobuf, 1) == -1)
+        printf("%s: write error in sector %i\n", __FUNCTION__, sector);
+}
+
+static void nandb_next_page(struct nand_bflash_s *s)
+{
+    if ((s->addr_low + 0x10000) < s->addr_low)
+        s->addr_high++;
+    s->addr_low += 0x10000;
+}
+
+void nandb_write_command(struct nand_bflash_s *s, uint16_t value)
+{
+    int id_index[4] = { 0, 1, 2, 3 };
+
+    debug_out(s,"nandb_write_command %x\n",value);
+
+    switch (value)
+    {
+    case 0x00: /* PAGE READ (cycle 1) */
+    case 0x05: /* RANDOM DATA READ (cycle 1) */
+       s->iolen = 0;
+        s->addr_cycle = 0;
+        break;
+    case 0x10: /* PROGRAM xxx / OTP PROTECT (cycle 2) */
+        nand_blk_write(s);
+        break;
+    case 0x30: /* PAGE READ / OTP DATA READ (cycle 2) */
+    case 0xe0: /* RANDOM DATA READ (cycle 2) */
+        s->iolen = s->page_oob_size - (s->addr_low & PAGE_MASK);
+        nandb_blk_load(s);
+        s->addr_cycle = 0;
+        break;
+    case 0x31: /* PAGE READ CACHE MODE START */
+    case 0x3f: /* PAGE READ CACHE MODE START LAST */
+        nandb_next_page(s);
+        s->iolen = s->page_oob_size - (s->addr_low & PAGE_MASK);
+        nandb_blk_load(s);
+        break;
+    case 0x60: /* BLOCK ERASE (cycle 1) */
+        /*erase only needs 3 address cycles. Its address is block address*/
+        s->addr_low &= ~PAGE_MASK;
+        s->addr_high =0;
+        s->addr_cycle = 2;
+        break;
+    case 0x70: /* READ STATUS */
+        if ((s->manf_id == NAND_MFR_MICRON) && (s->chip_id == 0xba))
+        {
+            s->status |= 0x60;  /*flash is ready */
+            s->status |= 0x80;  /*not protect */
+        }
+        s->io[0] = s->status;
+        s->ioaddr = s->io;
+        s->iolen = 1;
+        break;
+    case 0x80: /* PROGRAM PAGE / PROGRAM PAGE CACHE MODE (cycle 1) */
+    case 0x85: /* PROGRAM for INTERNAL DATA MOVE (cycle 1) / RANDOM DATA INPUT */
+        s->addr_cycle = 0;
+        s->ioaddr = s->io;
+        s->iolen = 0;
+        break;
+    case 0x90: /* READ ID */
+        s->iolen = 4 * s->bus_width;
+        memset(s->io, 0x0, s->iolen);
+        if (s->bus_width == BUS_WIDTH_16)
+        {
+            id_index[0] = 0;
+            id_index[1] = 2;
+            id_index[2] = 4;
+            id_index[3] = 6;
+        }
+        s->io[id_index[0]] = s->manf_id;
+        s->io[id_index[1]] = s->chip_id;
+        s->io[id_index[2]] = 'Q';       /* Don't-care byte (often 0xa5) */
+        if ((s->manf_id == NAND_MFR_MICRON) && (s->chip_id == 0xba))
+            s->io[id_index[3]] = 0x55;
+        s->ioaddr = s->io;
+        break;
+    case 0xa0: /* OTP DATA PROGRAM (cycle 1) */
+    case 0xa5: /* OTP DATA PROTECT (cycle 1) */
+    case 0xaf: /* OTP DATA READ (cycle 1) */
+        fprintf(stderr, "%s: OTP command 0x%x not implemented\n", __FUNCTION__, value);
+        break;
+    case 0xd0: /* BLOCK ERASE (cycle 2) */
+        nandb_blk_erase(s);
+        break;
+    case 0xff: /* RESET */
+       s->addr_cycle =0;
+       s->iolen=0;
+       s->addr_low =0;
+       s->addr_high =0;
+       s->ioaddr = NULL;
+       break;
+    default:
+        fprintf(stderr, "%s: unknown nand command 0x%x \n", __FUNCTION__, value);
+        exit(-1);
+    }
+    s->cmd = value;
+}
+
+void nandb_write_address(struct nand_bflash_s *s, uint16_t value)
+{
+    uint32_t mask;
+    uint32_t colum_addr;
+    
+    /*fprintf(stderr, "%s: addr_cycle=%d, value=0x%04x, addr_low=0x%08x, addr_high=0x%08x\n",
+            __FUNCTION__, s->addr_cycle, value, s->addr_low, s->addr_high );*/
+    
+    if (s->cmd==0x60)
+        debug_out(s,"value %x addr_cycle %x \n",value,s->addr_cycle);
+  
+    if (s->addr_cycle < 5) {
+        if (s->addr_cycle < 4) {
+            mask = ~(0xff << (s->addr_cycle * 8));
+            s->addr_low &= mask;
+            s->addr_low |= value << (s->addr_cycle * 8);
+        } else {
+            mask = ~(0xff << ((s->addr_cycle-4) * 8));
+            s->addr_high &= mask;
+            s->addr_high |= value << ((s->addr_cycle-4) * 8);
+        }
+    }
+    else {
+        fprintf(stderr,"%s wrong addr cycle\n",__FUNCTION__);
+        exit(-1);
+    }
+    if ((s->addr_cycle==1)&&(s->bus_width!=1)) {
+       colum_addr = s->addr_low & PAGE_MASK;
+       colum_addr *= s->bus_width;
+       s->addr_low &= ~PAGE_MASK;
+       s->addr_low += colum_addr;
+    }
+    s->addr_cycle++;
+}
+
+
+uint16_t nandb_read_data16(struct nand_bflash_s *s)
+{
+       uint16_t ret;
+       if ((s->iolen==0)&&(s->cmd==0x31))
+       {
+               nandb_next_page(s);
+        s->iolen = s->page_oob_size - (s->addr_low & PAGE_MASK);
+        nandb_blk_load(s);
+       }
+       if (s->iolen <= 0)
+       {
+               fprintf(stderr,"iolen <0 \n");
+               exit(-1);
+       }
+       if (s->cmd!=0x70)       
+       s->iolen -=2 ;
+    ret = *((uint16_t *)s->ioaddr);
+    if (s->cmd!=0x70)          
+       s->ioaddr += 2;         
+    return ret;
+}
+
+void nandb_write_data16(struct nand_bflash_s *s, uint16_t value)
+{
+        if ((s->cmd == 0x80) )
+        {
+        if (s->iolen < s->page_oob_size)
+        {
+               s->io[s->iolen ++] = value&0xff;
+               s->io[s->iolen ++] = (value>>8)&0xff;
+        }
+    }
+}
+
+struct nand_bflash_s *nandb_init(int manf_id, int chip_id)
+{
+    //int pagesize;
+    struct nand_bflash_s *s;
+    int index;
+    int i;
+
+    s = (struct nand_bflash_s *) qemu_mallocz(sizeof(struct nand_bflash_s));
+    for (i = 0; i < sizeof(nand_flash_info); i++)
+    {
+        if ((nand_flash_info[i].manf_id == manf_id)
+            && (nand_flash_info[i].chip_id == chip_id))
+        {
+            s->manf_id = manf_id;
+            s->chip_id = chip_id;
+            s->page_shift = nand_flash_info[i].page_shift;
+            s->oob_shift = nand_flash_info[i].oob_shift;
+            s->bus_width = nand_flash_info[i].bus_width;
+            s->page_size = 1 << s->page_shift;
+            s->oob_size = 1 << s->oob_shift;
+            s->block_shift = nand_flash_info[i].block_shift;
+            s->block_pages = 1 << s->block_shift;
+            s->page_oob_size = s->page_size + s->oob_size;
+            s->page_sectors = 1 << (s->page_shift - 9);
+            /*TODO: size overflow */
+            s->size = nand_flash_info[i].size << 20;
+            s->pages = (s->size / s->page_size);
+
+            break;
+        }
+
+    }
+    if (i >= sizeof(nand_flash_info))
+    {
+        fprintf(stderr, "%s: Unsupported NAND chip ID.\n",
+                  __FUNCTION__);
+        exit(-1);
+    }
+
+    
+    index = drive_get_index(IF_MTD, 0, 0);
+    if (index != -1)
+        s->bdrv = drives_table[index].bdrv;
+    else
+    {
+       fprintf(stderr, "%s: Please use -mtdblock to specify flash image.\n",
+                  __FUNCTION__);
+        exit(-1);
+    }
+
+    if (bdrv_getlength(s->bdrv) != (s->pages*s->page_oob_size))
+    {
+       fprintf(stderr,  "%s: Invalid flash image size.\n",
+                  __FUNCTION__);
+        exit(-1);
+
+    }
+
+       debug_init(s);
+    return s;
+
+}
index 32aaead..65f1169 100644 (file)
@@ -169,7 +169,8 @@ static void n8x0_nand_setup(struct n800_s *s)
                     onenand_base_unmap,
                     (s->nand = onenand_init(0xec4800, 1,
                                             omap2_gpio_in_get(s->cpu->gpif,
-                                                    N8X0_ONENAND_GPIO)[0])));
+                                                    N8X0_ONENAND_GPIO)[0])),
+                     NULL, NULL);
     otp_region = onenand_raw_otp(s->nand);
 
     memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac));
@@ -769,9 +770,11 @@ static void n8x0_usb_setup(struct n800_s *s)
 
     /* Using the NOR interface */
     omap_gpmc_attach(s->cpu->gpmc, N8X0_USB_ASYNC_CS,
-                    tusb6010_async_io(tusb), 0, 0, tusb);
+                    tusb6010_async_io(tusb), 0, 0, tusb,
+                    NULL, NULL);
     omap_gpmc_attach(s->cpu->gpmc, N8X0_USB_SYNC_CS,
-                    tusb6010_sync_io(tusb), 0, 0, tusb);
+                    tusb6010_sync_io(tusb), 0, 0, tusb,
+                    NULL, NULL);
 
     s->usb = tusb;
     omap2_gpio_out_set(s->cpu->gpif, N8X0_TUSB_ENABLE_GPIO, tusb_pwr);
index 7965eb2..30aa955 100644 (file)
--- a/hw/omap.h
+++ b/hw/omap.h
 # define OMAP2_L3_BASE         0x68000000
 # define OMAP2_Q2_BASE         0x80000000
 # define OMAP2_Q3_BASE         0xc0000000
+# define OMAP3_Q1_BASE      0x40000000
+# define OMAP3_L4_BASE      0x48000000
+# define OMAP3_SRAM_BASE    0x40200000
+# define OMAP3_L3_BASE      0x68000000
+# define OMAP3_Q2_BASE      0x80000000
+# define OMAP3_Q3_BASE      0xc0000000
 # define OMAP_MPUI_BASE                0xe1000000
 
 # define OMAP730_SRAM_SIZE     0x00032000
@@ -43,6 +49,7 @@
 # define OMAP1611_SRAM_SIZE    0x0003e800
 # define OMAP242X_SRAM_SIZE    0x000a0000
 # define OMAP243X_SRAM_SIZE    0x00010000
+# define OMAP3530_SRAM_SIZE 0x00010000
 # define OMAP_CS0_SIZE         0x04000000
 # define OMAP_CS1_SIZE         0x04000000
 # define OMAP_CS2_SIZE         0x04000000
@@ -76,7 +83,8 @@ struct omap_intr_handler_s;
 struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
                 unsigned long size, unsigned char nbanks, qemu_irq **pins,
                 qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk);
-struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
+struct omap_intr_handler_s *omap2_inth_init(struct omap_mpu_state_s *mpu,
+                target_phys_addr_t base,
                 int size, int nbanks, qemu_irq **pins,
                 qemu_irq parent_irq, qemu_irq parent_fiq,
                 omap_clk fclk, omap_clk iclk);
@@ -87,18 +95,32 @@ struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
                 qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
                 struct omap_mpu_state_s *mpu);
 
+struct omap3_prm_s;
+struct omap3_prm_s *omap3_prm_init(struct omap_target_agent_s *ta,
+                                   qemu_irq mpu_int, qemu_irq iva_int,
+                                   struct omap_mpu_state_s *mpu);
+
+struct omap3_cm_s;
+struct omap3_cm_s *omap3_cm_init(struct omap_target_agent_s *ta,
+                qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
+                struct omap_mpu_state_s *mpu);
+
 struct omap_sysctl_s;
 struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
                 omap_clk iclk, struct omap_mpu_state_s *mpu);
 
 struct omap_sdrc_s;
 struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base);
+void omap_sdrc_write_mcfg(struct omap_sdrc_s *s, uint32_t value, uint32_t cs);
 
 struct omap_gpmc_s;
-struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq);
+struct omap_gpmc_s *omap_gpmc_init(struct omap_mpu_state_s *mpu,
+                                   target_phys_addr_t base, qemu_irq irq);
 void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
                 void (*base_upd)(void *opaque, target_phys_addr_t new),
-                void (*unmap)(void *opaque), void *opaque);
+                void (*unmap)(void *opaque), void *opaque,
+                CPUReadMemoryFunc **nand_readfn,
+                CPUWriteMemoryFunc **nand_writefn);
 
 /*
  * Common IRQ numbers for level 1 interrupt handler
@@ -408,6 +430,71 @@ void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
 # define OMAP_INT_243X_CARKIT          94
 # define OMAP_INT_34XX_GPTIMER12       95
 
+/*
+ * OMAP-35XX common IRQ numbers
+ */
+# define OMAP_INT_35XX_SYS_NIRQ                7
+# define OMAP_INT_35XX_PRCM_MPU_IRQ    11
+# define OMAP_INT_35XX_SDMA_IRQ0       12
+# define OMAP_INT_35XX_SDMA_IRQ1       13
+# define OMAP_INT_35XX_SDMA_IRQ2       14
+# define OMAP_INT_35XX_SDMA_IRQ3       15
+# define OMAP_INT_35XX_MCBSP1_IRQ      16
+# define OMAP_INT_35XX_MCBSP2_IRQ      17
+# define OMAP_INT_35XX_GPMC_IRQ                20
+# define OMAP_INT_35XX_MCBSP3_IRQ      22
+# define OMAP_INT_35XX_MCBSP4_IRQ      23
+# define OMAP_INT_35XX_CAM_IRQ         24
+# define OMAP_INT_35XX_DSS_IRQ         25
+# define OMAP_INT_35XX_MAIL_U0_MPU     26
+# define OMAP_INT_35XX_MCBSP5_IRQ      27
+# define OMAP_INT_35XX_DSP_MMU         28
+# define OMAP_INT_35XX_GPIO_BANK1      29
+# define OMAP_INT_35XX_GPIO_BANK2      30
+# define OMAP_INT_35XX_GPIO_BANK3      31
+# define OMAP_INT_35XX_GPIO_BANK4      32
+# define OMAP_INT_35XX_GPIO_BANK5      33
+# define OMAP_INT_35XX_GPIO_BANK6      34
+# define OMAP_INT_35XX_WDT3            36
+# define OMAP_INT_35XX_GPTIMER1                37
+# define OMAP_INT_35XX_GPTIMER2                38
+# define OMAP_INT_35XX_GPTIMER3                39
+# define OMAP_INT_35XX_GPTIMER4                40
+# define OMAP_INT_35XX_GPTIMER5                41
+# define OMAP_INT_35XX_GPTIMER6                42
+# define OMAP_INT_35XX_GPTIMER7                43
+# define OMAP_INT_35XX_GPTIMER8                44
+# define OMAP_INT_35XX_GPTIMER9                45
+# define OMAP_INT_35XX_GPTIMER10       46
+# define OMAP_INT_35XX_GPTIMER11       47
+# define OMAP_INT_35XX_MG_IRQ          53
+# define OMAP_INT_35XX_MCBSP4_IRQ_TX   54
+# define OMAP_INT_35XX_MCBSP4_IRQ_RX   55
+# define OMAP_INT_35XX_I2C1_IRQ                56
+# define OMAP_INT_35XX_I2C2_IRQ                57
+# define OMAP_INT_35XX_MCBSP1_IRQ_TX   59
+# define OMAP_INT_35XX_MCBSP1_IRQ_RX   60
+# define OMAP_INT_35XX_I2C3_IRQ                61
+# define OMAP_INT_35XX_MCBSP2_IRQ_TX   62
+# define OMAP_INT_35XX_MCBSP2_IRQ_RX   63
+# define OMAP_INT_35XX_MCSPI1_IRQ      65
+# define OMAP_INT_35XX_MCSPI2_IRQ      66
+# define OMAP_INT_35XX_UART1_IRQ       72
+# define OMAP_INT_35XX_UART2_IRQ       73
+# define OMAP_INT_35XX_UART3_IRQ       74
+# define OMAP_INT_35XX_MCBSP5_IRQ_TX   81
+# define OMAP_INT_35XX_MCBSP5_IRQ_RX   82
+# define OMAP_INT_35XX_MMC1_IRQ                83
+# define OMAP_INT_35XX_MS_IRQ          84
+# define OMAP_INT_35XX_MMC2_IRQ                86
+# define OMAP_INT_35XX_MCBSP3_IRQ_TX   89
+# define OMAP_INT_35XX_MCBSP3_IRQ_RX   90
+# define OMAP_INT_35XX_MCSPI3_IRQ      91
+# define OMAP_INT_35XX_HS_USB_MC       92
+# define OMAP_INT_35XX_HS_USB_DMA      93
+# define OMAP_INT_35XX_MMC3_IRQ                94
+# define OMAP_INT_35XX_GPTIMER12       95
+
 /* omap_dma.c */
 enum omap_dma_model {
     omap_dma_3_0,
@@ -627,6 +714,79 @@ struct omap_dma_lcd_channel_s {
 # define OMAP24XX_DMA_MS               63      /* Not in OMAP2420 */
 # define OMAP24XX_DMA_EXT_DMAREQ5      64
 
+/*
+ * DMA request numbers for the OMAP3
+ * Note that the numbers have to match the values that are
+ * written to CCRi SYNCHRO_CONTROL bits, i.e. actual line
+ * number plus one! Zero is a reserved value (defined as
+ * NO_DEVICE here). Other missing values are reserved.
+ */
+#define OMAP35XX_DMA_NO_DEVICE        0
+
+#define OMAP35XX_DMA_EXT_DMAREQ0      2
+#define OMAP35XX_DMA_EXT_DMAREQ1      3
+#define OMAP35XX_DMA_GPMC             4
+
+#define OMAP35XX_DMA_DSS_LINETRIGGER  6
+#define OMAP35XX_DMA_EXT_DMAREQ2      7
+
+#define OMAP35XX_DMA_SPI3_TX0         15
+#define OMAP35XX_DMA_SPI3_RX0         16
+#define OMAP35XX_DMA_MCBSP3_TX        17
+#define OMAP35XX_DMA_MCBSP3_RX        18
+#define OMAP35XX_DMA_MCBSP4_TX        19
+#define OMAP35XX_DMA_MCBSP4_RX        20
+#define OMAP35XX_DMA_MCBSP5_TX        21
+#define OMAP35XX_DMA_MCBSP5_RX        22
+#define OMAP35XX_DMA_SPI3_TX1         23
+#define OMAP35XX_DMA_SPI3_RX1         24
+#define OMAP35XX_DMA_I2C3_TX          25
+#define OMAP35XX_DMA_I2C3_RX          26
+#define OMAP35XX_DMA_I2C1_TX          27
+#define OMAP35XX_DMA_I2C1_RX          28
+#define OMAP35XX_DMA_I2C2_TX          29
+#define OMAP35XX_DMA_I2C2_RX          30
+#define OMAP35XX_DMA_MCBSP1_TX        31
+#define OMAP35XX_DMA_MCBSP1_RX        32
+#define OMAP35XX_DMA_MCBSP2_TX        33
+#define OMAP35XX_DMA_MCBSP2_RX        34
+#define OMAP35XX_DMA_SPI1_TX0         35
+#define OMAP35XX_DMA_SPI1_RX0         36
+#define OMAP35XX_DMA_SPI1_TX1         37
+#define OMAP35XX_DMA_SPI1_RX1         38
+#define OMAP35XX_DMA_SPI1_TX2         39
+#define OMAP35XX_DMA_SPI1_RX2         40
+#define OMAP35XX_DMA_SPI1_TX3         41
+#define OMAP35XX_DMA_SPI1_RX4         42
+#define OMAP35XX_DMA_SPI2_TX0         43
+#define OMAP35XX_DMA_SPI2_RX0         44
+#define OMAP35XX_DMA_SPI2_TX1         45
+#define OMAP35XX_DMA_SPI2_RX1         46
+#define OMAP35XX_DMA_MMC2_TX          47
+#define OMAP35XX_DMA_MMC2_RX          48
+#define OMAP35XX_DMA_UART1_TX         49
+#define OMAP35XX_DMA_UART1_RX         50
+#define OMAP35XX_DMA_UART2_TX         51
+#define OMAP35XX_DMA_UART2_RX         52
+#define OMAP35XX_DMA_UART3_TX         53
+#define OMAP35XX_DMA_UART3_RX         54
+
+#define OMAP35XX_DMA_MMC1_TX          61
+#define OMAP35XX_DMA_MMC1_RX          62
+#define OMAP35XX_DMA_MS               63
+#define OMAP35XX_DMA_EXT_DMAREQ3      64
+
+#define OMAP35XX_DMA_SPI4_TX0         70
+#define OMAP35XX_DMA_SPI4_RX0         71
+#define OMAP35XX_DMA_DSS0             72
+#define OMAP35XX_DMA_DSS1             73
+#define OMAP35XX_DMA_DSS2             74
+#define OMAP35XX_DMA_DSS3             75
+
+#define OMAP35XX_DMA_MMC3_TX          77
+#define OMAP35XX_DMA_MMC3_RX          78
+
+
 /* omap[123].c */
 struct omap_mpu_timer_s;
 struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
@@ -635,6 +795,7 @@ struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
 struct omap_gp_timer_s;
 struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
                 qemu_irq irq, omap_clk fclk, omap_clk iclk);
+void omap_gp_timer_change_clk(struct omap_gp_timer_s *timer);
 
 struct omap_watchdog_timer_s;
 struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
@@ -676,8 +837,13 @@ qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
 void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
 
 struct omap_gpif_s;
-struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
+struct omap_gpif_s *omap2_gpio_init(struct omap_mpu_state_s *mpu,
+                struct omap_target_agent_s *ta,
                 qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules);
+struct omap_gpif_s *omap3_gpif_init(void);
+void omap3_gpio_init(struct omap_mpu_state_s *mpu,
+                     struct omap_gpif_s *s, struct omap_target_agent_s *ta,
+                     qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int module_index);
 qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start);
 void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler);
 
@@ -756,14 +922,24 @@ struct rfbi_chip_s {
     void (*block)(void *opaque, int dc, void *buf, size_t len, int pitch);
     uint16_t (*read)(void *opaque, int dc);
 };
+typedef void (*omap3_lcd_panel_fn_t)(uint8_t *, const uint8_t *, unsigned int);
+struct omap3_lcd_panel_s {
+    struct omap_dss_s *dss;
+    DisplayState *state;
+    omap3_lcd_panel_fn_t *line_fn_tab[2];
+    omap3_lcd_panel_fn_t line_fn;
+    uint32_t invalidate;
+};
 struct omap_dss_s;
 void omap_dss_reset(struct omap_dss_s *s);
 struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
                 target_phys_addr_t l3_base,
                 qemu_irq irq, qemu_irq drq,
                 omap_clk fck1, omap_clk fck2, omap_clk ck54m,
-                omap_clk ick1, omap_clk ick2);
+                omap_clk ick1, omap_clk ick2, int region_start);
 void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip);
+void omap3_lcd_panel_attach(struct omap_dss_s *s, int cs, struct omap3_lcd_panel_s *lcd_panel);
+void *omap3_lcd_panel_init();
 
 /* omap_mmc.c */
 struct omap_mmc_s;
@@ -777,15 +953,25 @@ void omap_mmc_reset(struct omap_mmc_s *s);
 void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover);
 void omap_mmc_enable(struct omap_mmc_s *s, int enable);
 
+/* omap3_mmc.c */
+struct omap3_mmc_s;
+struct omap3_mmc_s *omap3_mmc_init(struct omap_target_agent_s *ta,
+                BlockDriverState *bd, qemu_irq irq, qemu_irq dma[],
+                omap_clk fclk, omap_clk iclk);
+
 /* omap_i2c.c */
 struct omap_i2c_s;
 struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
                 qemu_irq irq, qemu_irq *dma, omap_clk clk);
 struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
                 qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk);
+struct omap_i2c_s *omap3_i2c_init(struct omap_target_agent_s *ta,
+                qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk,
+                int fifosize);
 void omap_i2c_reset(struct omap_i2c_s *s);
 i2c_bus *omap_i2c_bus(struct omap_i2c_s *s);
 
+
 # define cpu_is_omap310(cpu)           (cpu->mpu_model == omap310)
 # define cpu_is_omap1510(cpu)          (cpu->mpu_model == omap1510)
 # define cpu_is_omap1610(cpu)          (cpu->mpu_model == omap1610)
@@ -794,6 +980,7 @@ i2c_bus *omap_i2c_bus(struct omap_i2c_s *s);
 # define cpu_is_omap2420(cpu)          (cpu->mpu_model == omap2420)
 # define cpu_is_omap2430(cpu)          (cpu->mpu_model == omap2430)
 # define cpu_is_omap3430(cpu)          (cpu->mpu_model == omap3430)
+# define cpu_is_omap3530(cpu)       (cpu->mpu_model == omap3530)
 
 # define cpu_is_omap15xx(cpu)          \
         (cpu_is_omap310(cpu) || cpu_is_omap1510(cpu))
@@ -805,7 +992,8 @@ i2c_bus *omap_i2c_bus(struct omap_i2c_s *s);
 # define cpu_class_omap1(cpu)          \
         (cpu_is_omap15xx(cpu) || cpu_is_omap16xx(cpu))
 # define cpu_class_omap2(cpu)          cpu_is_omap24xx(cpu)
-# define cpu_class_omap3(cpu)          cpu_is_omap3430(cpu)
+# define cpu_class_omap3(cpu)          \
+        (cpu_is_omap3430(cpu) || cpu_is_omap3530(cpu))
 
 struct omap_mpu_state_s {
     enum omap_mpu_model {
@@ -819,6 +1007,7 @@ struct omap_mpu_state_s {
         omap2423,
         omap2430,
         omap3430,
+        omap3530,
     } mpu_model;
 
     CPUState *env;
@@ -871,7 +1060,7 @@ struct omap_mpu_state_s {
         omap_clk clk;
     } pwt;
 
-    struct omap_i2c_s *i2c[2];
+    struct omap_i2c_s *i2c[3];
 
     struct omap_rtc_s *rtc;
 
@@ -938,6 +1127,7 @@ struct omap_mpu_state_s {
     struct omap_synctimer_s {
         uint32_t val;
         uint16_t readh;
+        uint32_t sysconfig; /*OMAP3*/
     } synctimer;
 
     struct omap_prcm_s *prcm;
@@ -952,6 +1142,45 @@ struct omap_mpu_state_s {
     struct omap_dss_s *dss;
 
     struct omap_eac_s *eac;
+    
+    /* OMAP3-only */
+    struct omap3_prm_s *omap3_prm;
+    struct omap3_cm_s *omap3_cm;
+    struct omap3_wdt_s *omap3_mpu_wdt;
+    struct omap3_scm_s *omap3_scm;
+    struct omap3_pm_s *omap3_pm;
+    struct omap3_sms_s *omap3_sms;
+    struct omap3_mmc_s *omap3_mmc[3];
+};
+
+struct omap_target_agent_s {
+    struct omap_l4_s *bus;
+    int regions;
+    struct omap_l4_region_s *start;
+    target_phys_addr_t base;
+    uint32_t component;
+    uint32_t control;
+    uint32_t control_h; /* OMAP3 */
+    uint32_t status;
+};
+
+struct omap_l4_s {
+    target_phys_addr_t base;
+    int ta_num;
+    struct omap_target_agent_s ta[0];
+};
+
+struct omap_l4_region_s {
+    target_phys_addr_t offset;
+    size_t size;
+    int access;
+};
+
+struct omap_l4_agent_info_s {
+    int ta;
+    int region;
+    int regions;
+    int ta_region;
 };
 
 /* omap1.c */
@@ -962,10 +1191,17 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
 struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
                 const char *core);
 
+/* omap3.c */
+struct omap_mpu_state_s *omap3530_mpu_init(unsigned long sdram_size,
+                const char *core);
+void omap3_set_mem_type(struct omap_mpu_state_s *s, int bootfrom);
+void omap3_set_device_type(struct omap_mpu_state_s *s, int device_type);
+int omap3_mmc_boot(struct omap_mpu_state_s *s);
+
 # if TARGET_PHYS_ADDR_BITS == 32
-#  define OMAP_FMT_plx "%#08x"
+#  define OMAP_FMT_plx "0x%08x"
 # elif TARGET_PHYS_ADDR_BITS == 64
-#  define OMAP_FMT_plx "%#08" PRIx64
+#  define OMAP_FMT_plx "0x%08" PRIx64
 # else
 #  error TARGET_PHYS_ADDR_BITS undefined
 # endif
@@ -985,9 +1221,15 @@ void omap_mpu_wakeup(void *opaque, int irq, int req);
 # define OMAP_BAD_REG(paddr)           \
         fprintf(stderr, "%s: Bad register " OMAP_FMT_plx "\n", \
                         __FUNCTION__, paddr)
+# define OMAP_BAD_REGV(paddr, value) \
+        fprintf(stderr, "%s: Bad register " OMAP_FMT_plx " (value " OMAP_FMT_plx ")\n", \
+                __FUNCTION__, paddr, value)
 # define OMAP_RO_REG(paddr)            \
         fprintf(stderr, "%s: Read-only register " OMAP_FMT_plx "\n",   \
                         __FUNCTION__, paddr)
+# define OMAP_RO_REGV(paddr, value) \
+        fprintf(stderr, "%s: Read-only register " OMAP_FMT_plx " (value " OMAP_FMT_plx ")\n", \
+                __FUNCTION__, paddr, value)
 
 /* OMAP-specific Linux bootloader tags for the ATAG_BOARD area
    (Board-specifc tags are not here)  */
index c32d3f7..9d065cd 100644 (file)
@@ -96,6 +96,7 @@ struct omap_intr_handler_s {
     qemu_irq parent_intr[2];
     unsigned char nbanks;
     int level_only;
+    uint8_t revision;
 
     /* state */
     uint32_t new_agr[2];
@@ -449,7 +450,7 @@ static uint32_t omap2_inth_read(void *opaque, target_phys_addr_t addr)
 
     switch (offset) {
     case 0x00: /* INTC_REVISION */
-        return 0x21;
+        return s->revision;
 
     case 0x10: /* INTC_SYSCONFIG */
         return (s->autoidle >> 2) & 1;
@@ -625,7 +626,9 @@ static CPUWriteMemoryFunc *omap2_inth_writefn[] = {
     omap2_inth_write,
 };
 
-struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
+struct omap_intr_handler_s *omap2_inth_init(
+                struct omap_mpu_state_s *mpu,
+                target_phys_addr_t base,
                 int size, int nbanks, qemu_irq **pins,
                 qemu_irq parent_irq, qemu_irq parent_fiq,
                 omap_clk fclk, omap_clk iclk)
@@ -635,6 +638,7 @@ struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
             qemu_mallocz(sizeof(struct omap_intr_handler_s) +
                             sizeof(struct omap_intr_handler_bank_s) * nbanks);
 
+    s->revision = cpu_class_omap3(mpu) ? 0x40 : 0x21;
     s->parent_intr[0] = parent_irq;
     s->parent_intr[1] = parent_fiq;
     s->nbanks = nbanks;
index 20b3811..4eeab9c 100644 (file)
@@ -81,6 +81,12 @@ struct omap_gp_timer_s {
 #define GPT_OVF_IT     (1 << 1)
 #define GPT_MAT_IT     (1 << 0)
 
+/*if the clock source of gptimer changes, rate must be regenerated*/
+void omap_gp_timer_change_clk(struct omap_gp_timer_s *timer)
+{
+    timer->rate = omap_clk_getrate(timer->clk);
+}
+
 static inline void omap_gp_timer_intr(struct omap_gp_timer_s *timer, int it)
 {
     if (timer->it_ena & it) {
@@ -106,11 +112,18 @@ static inline void omap_gp_timer_out(struct omap_gp_timer_s *timer, int level)
 
 static inline uint32_t omap_gp_timer_read(struct omap_gp_timer_s *timer)
 {
-    uint64_t distance;
+    uint64_t distance, rate;
 
     if (timer->st && timer->rate) {
         distance = qemu_get_clock(vm_clock) - timer->time;
-        distance = muldiv64(distance, timer->rate, timer->ticks_per_sec);
+        
+        /*if ticks_per_sec is bigger than 32bit we cannot use muldiv64*/
+        if (timer->ticks_per_sec > 0xffffffff) {
+            distance /= ticks_per_sec / 1000; /*distance ms*/
+            rate = timer->rate >> (timer->pre ? timer->ptv + 1 : 0);
+            distance = muldiv64(distance, rate, 1000);
+        } else
+            distance = muldiv64(distance, timer->rate, timer->ticks_per_sec);
 
         if (distance >= 0xffffffff - timer->val)
             return 0xffffffff;
@@ -130,15 +143,23 @@ static inline void omap_gp_timer_sync(struct omap_gp_timer_s *timer)
 
 static inline void omap_gp_timer_update(struct omap_gp_timer_s *timer)
 {
-    int64_t expires, matches;
+    int64_t expires, matches, rate;
 
     if (timer->st && timer->rate) {
-        expires = muldiv64(0x100000000ll - timer->val,
+        if (timer->ticks_per_sec > 0xffffffff) {
+            rate = timer->rate >> (timer->pre ? timer->ptv + 1 : 0); /*1s -> rate ticks*/
+            expires = muldiv64(0x100000000ll - timer->val, ticks_per_sec, rate);
+        } else
+            expires = muldiv64(0x100000000ll - timer->val,
                         timer->ticks_per_sec, timer->rate);
         qemu_mod_timer(timer->timer, timer->time + expires);
 
         if (timer->ce && timer->match_val >= timer->val) {
-            matches = muldiv64(timer->match_val - timer->val,
+            if (timer->ticks_per_sec > 0xffffffff) {
+                rate = timer->rate >> (timer->pre ? timer->ptv + 1 : 0); /*1s -> rate ticks*/
+                matches = muldiv64(timer->match_val - timer->val, ticks_per_sec, rate);
+            } else
+                matches = muldiv64(timer->match_val - timer->val,
                             timer->ticks_per_sec, timer->rate);
             qemu_mod_timer(timer->match, timer->time + matches);
         } else
@@ -235,6 +256,7 @@ static void omap_gp_timer_clk_setup(struct omap_gp_timer_s *timer)
     omap_clk_adduser(timer->clk,
                     qemu_allocate_irqs(omap_gp_timer_clk_update, timer, 1)[0]);
     timer->rate = omap_clk_getrate(timer->clk);
+    //fprintf(stderr, "omap gptimer clk rate 0x%llx\n", timer->rate);
 }
 
 static void omap_gp_timer_reset(struct omap_gp_timer_s *s)
@@ -503,11 +525,10 @@ static void omap_synctimer_reset(struct omap_synctimer_s *s)
 static uint32_t omap_synctimer_readw(void *opaque, target_phys_addr_t addr)
 {
     struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
-
+    
     switch (addr) {
     case 0x00: /* 32KSYNCNT_REV */
         return 0x21;
-
     case 0x10: /* CR */
         return omap_synctimer_read(s) - s->val;
     }
@@ -516,6 +537,14 @@ static uint32_t omap_synctimer_readw(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
+static uint32_t omap3_synctimer_readw(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_synctimer_s *s = (struct omap_synctimer_s *)opaque;
+    return (addr == 0x04) 
+        ? s->sysconfig 
+        : omap_synctimer_readw(opaque, addr);
+}
+
 static uint32_t omap_synctimer_readh(void *opaque, target_phys_addr_t addr)
 {
     struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
@@ -523,11 +552,23 @@ static uint32_t omap_synctimer_readh(void *opaque, target_phys_addr_t addr)
 
     if (addr & 2)
         return s->readh;
-    else {
-        ret = omap_synctimer_readw(opaque, addr);
-        s->readh = ret >> 16;
-        return ret & 0xffff;
-    }
+
+    ret = omap_synctimer_readw(opaque, addr);
+    s->readh = ret >> 16;
+    return ret & 0xffff;
+}
+
+static uint32_t omap3_synctimer_readh(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
+    uint32_t ret;
+    
+    if (addr & 2)
+        return s->readh;
+    
+    ret = omap3_synctimer_readw(opaque, addr);
+    s->readh = ret >> 16;
+    return ret & 0xffff;
 }
 
 static CPUReadMemoryFunc *omap_synctimer_readfn[] = {
@@ -536,26 +577,52 @@ static CPUReadMemoryFunc *omap_synctimer_readfn[] = {
     omap_synctimer_readw,
 };
 
+static CPUReadMemoryFunc *omap3_synctimer_readfn[] = {
+    omap_badwidth_read32,
+    omap3_synctimer_readh,
+    omap3_synctimer_readw,
+};
+
 static void omap_synctimer_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     OMAP_BAD_REG(addr);
 }
 
+static void omap3_synctimer_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_synctimer_s *s = (struct omap_synctimer_s *)opaque;
+    if (addr == 0x04) /* SYSCONFIG */
+        s->sysconfig = value & 0x0c;
+    else
+        OMAP_BAD_REG(addr);
+}
+
 static CPUWriteMemoryFunc *omap_synctimer_writefn[] = {
     omap_badwidth_write32,
     omap_synctimer_write,
     omap_synctimer_write,
 };
 
+static CPUWriteMemoryFunc *omap3_synctimer_writefn[] = {
+    omap_badwidth_write32,
+    omap3_synctimer_write,
+    omap3_synctimer_write,
+};
+
 void omap_synctimer_init(struct omap_target_agent_s *ta,
                 struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk)
 {
     struct omap_synctimer_s *s = &mpu->synctimer;
 
     omap_synctimer_reset(s);
-    omap_l4_attach(ta, 0, l4_register_io_memory(0,
-                      omap_synctimer_readfn, omap_synctimer_writefn, s));
+    if (cpu_class_omap3(mpu))
+        omap_l4_attach(ta, 0, l4_register_io_memory(0,
+                    omap3_synctimer_readfn, omap3_synctimer_writefn, s));
+    else
+        omap_l4_attach(ta, 0, l4_register_io_memory(0,
+                    omap_synctimer_readfn, omap_synctimer_writefn, s));
 }
 
 /* General-Purpose Interface of OMAP2 */
@@ -565,6 +632,7 @@ struct omap2_gpio_s {
     qemu_irq *in;
     qemu_irq handler[32];
 
+    uint8_t revision;
     uint8_t config[2];
     uint32_t inputs;
     uint32_t outputs;
@@ -665,7 +733,7 @@ static uint32_t omap_gpio_module_read(void *opaque, target_phys_addr_t addr)
 
     switch (addr) {
     case 0x00: /* GPIO_REVISION */
-        return 0x18;
+        return s->revision;
 
     case 0x10: /* GPIO_SYSCONFIG */
         return s->config[0];
@@ -742,7 +810,7 @@ static void omap_gpio_module_write(void *opaque, target_phys_addr_t addr,
     case 0x00: /* GPIO_REVISION */
     case 0x14: /* GPIO_SYSSTATUS */
     case 0x38: /* GPIO_DATAIN */
-        OMAP_RO_REG(addr);
+        OMAP_RO_REGV(addr, value);
         break;
 
     case 0x10: /* GPIO_SYSCONFIG */
@@ -868,7 +936,7 @@ static void omap_gpio_module_write(void *opaque, target_phys_addr_t addr,
         break;
 
     default:
-        OMAP_BAD_REG(addr);
+        OMAP_BAD_REGV(addr, value);
         return;
     }
 }
@@ -940,16 +1008,18 @@ static CPUWriteMemoryFunc *omap_gpio_module_writefn[] = {
     omap_gpio_module_write,
 };
 
-static void omap_gpio_module_init(struct omap2_gpio_s *s,
+static void omap_gpio_module_init(struct omap_mpu_state_s *mpu,
+                struct omap2_gpio_s *s,
                 struct omap_target_agent_s *ta, int region,
-                qemu_irq mpu, qemu_irq dsp, qemu_irq wkup,
+                qemu_irq mpu_irq, qemu_irq dsp_irq, qemu_irq wkup_irq,
                 omap_clk fclk, omap_clk iclk)
 {
     int iomemtype;
 
-    s->irq[0] = mpu;
-    s->irq[1] = dsp;
-    s->wkup = wkup;
+    s->revision = cpu_class_omap3(mpu) ? 0x25 : 0x18;
+    s->irq[0] = mpu_irq;
+    s->irq[1] = dsp_irq;
+    s->wkup = wkup_irq;
     s->in = qemu_allocate_irqs(omap_gpio_module_set, s, 32);
 
     iomemtype = l4_register_io_memory(0, omap_gpio_module_readfn,
@@ -958,7 +1028,7 @@ static void omap_gpio_module_init(struct omap2_gpio_s *s,
 }
 
 struct omap_gpif_s {
-    struct omap2_gpio_s module[5];
+    struct omap2_gpio_s module[6];
     int modules;
 
     int autoidle;
@@ -1045,7 +1115,8 @@ static CPUWriteMemoryFunc *omap_gpif_top_writefn[] = {
     omap_gpif_top_write,
 };
 
-struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
+struct omap_gpif_s *omap2_gpio_init(struct omap_mpu_state_s *mpu,
+                struct omap_target_agent_s *ta,
                 qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules)
 {
     int iomemtype, i;
@@ -1055,7 +1126,7 @@ struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
 
     s->modules = modules;
     for (i = 0; i < modules; i ++)
-        omap_gpio_module_init(s->module + i, ta, region[i],
+        omap_gpio_module_init(mpu, s->module + i, ta, region[i],
                         irq[i], 0, 0, fclk[i], iclk);
 
     omap_gpif_reset(s);
@@ -1067,6 +1138,23 @@ struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
     return s;
 }
 
+struct omap_gpif_s *omap3_gpif_init()
+{
+    struct omap_gpif_s *s = (struct omap_gpif_s *)
+        qemu_mallocz(sizeof(struct omap_gpif_s));
+    omap_gpif_reset(s);
+    return s;
+}
+
+void omap3_gpio_init(struct omap_mpu_state_s *mpu,
+                     struct omap_gpif_s *s,struct omap_target_agent_s *ta,
+                     qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int module_index)
+{
+    s->modules++;
+    omap_gpio_module_init(mpu, s->module + module_index, ta, 0,
+                          irq[module_index], 0, 0, NULL,NULL);
+}
+
 qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start)
 {
     if (start >= s->modules * 32 || start < 0)
@@ -2175,22 +2263,6 @@ static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
 }
 
 /* L4 Interconnect */
-struct omap_target_agent_s {
-    struct omap_l4_s *bus;
-    int regions;
-    struct omap_l4_region_s *start;
-    target_phys_addr_t base;
-    uint32_t component;
-    uint32_t control;
-    uint32_t status;
-};
-
-struct omap_l4_s {
-    target_phys_addr_t base;
-    int ta_num;
-    struct omap_target_agent_s ta[0];
-};
-
 #ifdef L4_MUX_HACK
 static int omap_l4_io_entries;
 static int omap_cpu_io_entry;
@@ -2359,11 +2431,7 @@ static CPUWriteMemoryFunc *omap_l4ta_writefn[] = {
 #define L4TA(n)                (n)
 #define L4TAO(n)       ((n) + 39)
 
-static struct omap_l4_region_s {
-    target_phys_addr_t offset;
-    size_t size;
-    int access;
-} omap_l4_region[125] = {
+static struct omap_l4_region_s omap_l4_region[125] = {
     [  1] = { 0x40800,  0x800, 32          }, /* Initiator agent */
     [  2] = { 0x41000, 0x1000, 32          }, /* Link agent */
     [  0] = { 0x40000,  0x800, 32          }, /* Address and protection */
@@ -2491,12 +2559,7 @@ static struct omap_l4_region_s {
     [124] = { 0xb3000, 0x1000, 32 | 16 | 8 }, /* L4TA39 */
 };
 
-static struct omap_l4_agent_info_s {
-    int ta;
-    int region;
-    int regions;
-    int ta_region;
-} omap_l4_agent_info[54] = {
+static struct omap_l4_agent_info_s omap_l4_agent_info[54] = {
     { 0,           0, 3, 2 }, /* L4IA initiatior agent */
     { L4TAO(1),    3, 2, 1 }, /* Control and pinout module */
     { L4TAO(2),    5, 2, 1 }, /* 32K timer */
@@ -2641,6 +2704,8 @@ static uint32_t omap_tap_read(void *opaque, target_phys_addr_t addr)
             return 0x5b68a02f; /* ES 2.2 */
         case omap3430:
             return 0x1b7ae02f; /* ES 2 */
+        case omap3530:
+            return 0x3b7ae02f;  /* ES 3.0 */
         default:
             cpu_abort(cpu_single_env, "%s: Bad mpu model\n", __FUNCTION__);
         }
@@ -2658,6 +2723,8 @@ static uint32_t omap_tap_read(void *opaque, target_phys_addr_t addr)
             return 0x000000f0;
         case omap3430:
             return 0x000000f0;
+        case omap3530:
+            return 0x000f00f0;
         default:
             cpu_abort(cpu_single_env, "%s: Bad mpu model\n", __FUNCTION__);
         }
@@ -2671,6 +2738,7 @@ static uint32_t omap_tap_read(void *opaque, target_phys_addr_t addr)
         case omap2430:
             return 0xcafeb68a; /* ES 2.2 */
         case omap3430:
+        case omap3530:
             return 0xcafeb7ae; /* ES 2 */
         default:
             cpu_abort(cpu_single_env, "%s: Bad mpu model\n", __FUNCTION__);
@@ -3904,16 +3972,41 @@ struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
 /* SDRAM Controller Subsystem */
 struct omap_sdrc_s {
     uint8_t config;
+    uint32_t cscfg;
+    uint32_t sharing;
+    uint32_t dlla_ctrl;
+    uint32_t power_reg;
+    struct {
+        uint32_t mcfg;
+        uint32_t mr;
+        uint32_t emr2;
+        uint32_t actim_ctrla;
+        uint32_t actim_ctrlb;
+        uint32_t rfr_ctrl;
+        uint32_t manual;
+    } cs[2];
 };
 
 static void omap_sdrc_reset(struct omap_sdrc_s *s)
 {
-    s->config = 0x10;
+    s->config    = 0x10;
+    s->cscfg     = 0x4;
+    s->sharing   = 0; // TODO: copy from system control module
+    s->dlla_ctrl = 0;
+    s->power_reg = 0x85;
+    s->cs[0].mcfg        = s->cs[1].mcfg        = 0; // TODO: copy from system control module!
+    s->cs[0].mr          = s->cs[1].mr          = 0x0024;
+    s->cs[0].emr2        = s->cs[1].emr2        = 0;
+    s->cs[0].actim_ctrla = s->cs[1].actim_ctrla = 0;
+    s->cs[0].actim_ctrlb = s->cs[1].actim_ctrlb = 0;
+    s->cs[0].rfr_ctrl    = s->cs[1].rfr_ctrl    = 0;
+    s->cs[0].manual      = s->cs[1].manual      = 0;
 }
 
 static uint32_t omap_sdrc_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
+    int cs = 0;
 
     switch (addr) {
     case 0x00: /* SDRC_REVISION */
@@ -3923,38 +4016,77 @@ static uint32_t omap_sdrc_read(void *opaque, target_phys_addr_t addr)
         return s->config;
 
     case 0x14: /* SDRC_SYSSTATUS */
-        return 1;                                              /* RESETDONE */
+        return 1; /* RESETDONE */
 
     case 0x40: /* SDRC_CS_CFG */
+        return s->cscfg;
+
     case 0x44: /* SDRC_SHARING */
+        return s->sharing;
+            
     case 0x48: /* SDRC_ERR_ADDR */
+        return 0;
+
     case 0x4c: /* SDRC_ERR_TYPE */
+        return 0x8;
+            
     case 0x60: /* SDRC_DLLA_SCTRL */
+        return s->dlla_ctrl;
+        
     case 0x64: /* SDRC_DLLA_STATUS */
+        return ~(s->dlla_ctrl & 0x4);
+
     case 0x68: /* SDRC_DLLB_CTRL */
     case 0x6c: /* SDRC_DLLB_STATUS */
-    case 0x70: /* SDRC_POWER */
-    case 0x80: /* SDRC_MCFG_0 */
-    case 0x84: /* SDRC_MR_0 */
-    case 0x88: /* SDRC_EMR1_0 */
-    case 0x8c: /* SDRC_EMR2_0 */
-    case 0x90: /* SDRC_EMR3_0 */
-    case 0x94: /* SDRC_DCDL1_CTRL */
-    case 0x98: /* SDRC_DCDL2_CTRL */
-    case 0x9c: /* SDRC_ACTIM_CTRLA_0 */
-    case 0xa0: /* SDRC_ACTIM_CTRLB_0 */
-    case 0xa4: /* SDRC_RFR_CTRL_0 */
-    case 0xa8: /* SDRC_MANUAL_0 */
-    case 0xb0: /* SDRC_MCFG_1 */
-    case 0xb4: /* SDRC_MR_1 */
-    case 0xb8: /* SDRC_EMR1_1 */
-    case 0xbc: /* SDRC_EMR2_1 */
-    case 0xc0: /* SDRC_EMR3_1 */
-    case 0xc4: /* SDRC_ACTIM_CTRLA_1 */
-    case 0xc8: /* SDRC_ACTIM_CTRLB_1 */
-    case 0xd4: /* SDRC_RFR_CTRL_1 */
-    case 0xd8: /* SDRC_MANUAL_1 */
         return 0x00;
+    
+    case 0x70: /* SDRC_POWER */
+        return s->power_reg;
+
+    case 0xb0 ... 0xd8:
+        cs = 1;
+        addr -= 0x30;
+        /* fall through */
+    case 0x80 ... 0xa8:
+        switch (addr & 0x3f) {
+        case 0x00: /* SDRC_MCFG_x */
+            return s->cs[cs].mcfg;
+        case 0x04: /* SDRC_MR_x */
+            return s->cs[cs].mr;
+        case 0x08: /* SDRC_EMR1_x */
+            return 0x00;
+        case 0x0c: /* SDRC_EMR2_x */
+            return s->cs[cs].emr2;
+        case 0x10: /* SDRC_EMR3_x */
+            return 0x00;
+        case 0x14:
+            if (cs)
+                return s->cs[1].actim_ctrla; /* SDRC_ACTIM_CTRLA_1 */
+            return 0x00;                     /* SDRC_DCDL1_CTRL */
+        case 0x18:
+            if (cs)
+                return s->cs[1].actim_ctrlb; /* SDRC_ACTIM_CTRLB_1 */
+            return 0x00;                     /* SDRC_DCDL2_CTRL */
+        case 0x1c:
+            if (!cs)
+                return s->cs[0].actim_ctrla; /* SDRC_ACTIM_CTRLA_0 */
+            break;
+        case 0x20:
+            if (!cs)
+                return s->cs[0].actim_ctrlb; /* SDRC_ACTIM_CTRLB_0 */
+            break;
+        case 0x24: /* SDRC_RFR_CTRL_x */
+            return s->cs[cs].rfr_ctrl;
+        case 0x28: /* SDRC_MANUAL_x */
+            return s->cs[cs].manual;
+        default:
+            break;
+        }
+        addr += cs * 0x30; // restore address to get correct error messages
+        break;
+
+    default:
+        break;
     }
 
     OMAP_BAD_REG(addr);
@@ -3965,6 +4097,7 @@ static void omap_sdrc_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
+    int cs = 0;
 
     switch (addr) {
     case 0x00: /* SDRC_REVISION */
@@ -3972,49 +4105,103 @@ static void omap_sdrc_write(void *opaque, target_phys_addr_t addr,
     case 0x48: /* SDRC_ERR_ADDR */
     case 0x64: /* SDRC_DLLA_STATUS */
     case 0x6c: /* SDRC_DLLB_STATUS */
-        OMAP_RO_REG(addr);
-        return;
+        OMAP_RO_REGV(addr, value);
+        break;
 
     case 0x10: /* SDRC_SYSCONFIG */
         if ((value >> 3) != 0x2)
-            fprintf(stderr, "%s: bad SDRAM idle mode %i\n",
-                            __FUNCTION__, value >> 3);
+            fprintf(stderr, "%s: bad SDRAM idle mode %i for SDRC_SYSCONFIG (full value 0x%08x)\n",
+                            __FUNCTION__, value >> 3, value);
         if (value & 2)
             omap_sdrc_reset(s);
         s->config = value & 0x18;
         break;
 
     case 0x40: /* SDRC_CS_CFG */
+        s->cscfg = value & 0x30f;
+        fprintf(stderr, "%s: SDRC_CS_CFG = 0x%08x\n", __FUNCTION__, s->cscfg);
+        break;
+
     case 0x44: /* SDRC_SHARING */
+        if (!(s->sharing & 0x40000000)) /* LOCK */
+            s->sharing = value & 0x40007f00;
+        break;
+
     case 0x4c: /* SDRC_ERR_TYPE */
-    case 0x60: /* SDRC_DLLA_SCTRL */
+        OMAP_BAD_REGV(addr, value);
+        break;
+
+    case 0x60: /* SDRC_DLLA_CTRL */
+        s->dlla_ctrl = value & 0xffff00fe;
+        break;
+
     case 0x68: /* SDRC_DLLB_CTRL */
-    case 0x70: /* SDRC_POWER */
-    case 0x80: /* SDRC_MCFG_0 */
-    case 0x84: /* SDRC_MR_0 */
-    case 0x88: /* SDRC_EMR1_0 */
-    case 0x8c: /* SDRC_EMR2_0 */
-    case 0x90: /* SDRC_EMR3_0 */
-    case 0x94: /* SDRC_DCDL1_CTRL */
-    case 0x98: /* SDRC_DCDL2_CTRL */
-    case 0x9c: /* SDRC_ACTIM_CTRLA_0 */
-    case 0xa0: /* SDRC_ACTIM_CTRLB_0 */
-    case 0xa4: /* SDRC_RFR_CTRL_0 */
-    case 0xa8: /* SDRC_MANUAL_0 */
-    case 0xb0: /* SDRC_MCFG_1 */
-    case 0xb4: /* SDRC_MR_1 */
-    case 0xb8: /* SDRC_EMR1_1 */
-    case 0xbc: /* SDRC_EMR2_1 */
-    case 0xc0: /* SDRC_EMR3_1 */
-    case 0xc4: /* SDRC_ACTIM_CTRLA_1 */
-    case 0xc8: /* SDRC_ACTIM_CTRLB_1 */
-    case 0xd4: /* SDRC_RFR_CTRL_1 */
-    case 0xd8: /* SDRC_MANUAL_1 */
+        OMAP_BAD_REGV(addr, value);
+        break;
+        
+    case 0x70: /* SDRC_POWER_REG */
+        s->power_reg = value & 0x04fffffd;
+        break;
+
+    case 0xb0 ... 0xd8:
+        cs = 1;
+        addr -= 0x30;
+        /* fall through */
+    case 0x80 ... 0xa8:
+        switch (addr & 0x3f) {
+        case 0x00: /* SDRC_MCFG_x */
+            if (!(s->cs[cs].mcfg & 0x40000000)) { /* LOCKSTATUS */
+                if (value & 0x00080000) /* ADDRMUXLEGACY */
+                    s->cs[cs].mcfg = value & 0x477bffdf;
+                else
+                    s->cs[cs].mcfg = value & 0x41fbffdf; // ????
+            }
+            break;
+        case 0x04: /* SDRC_MR_x */
+            s->cs[cs].mr = value & 0xfff;
+            break;
+        case 0x08: /* SDRC_EMR1_x */
+            break;
+        case 0x0c: /* SDRC_EMR2_x */
+            s->cs[cs].emr2 = value & 0xfff;
+            break;
+        case 0x10: /* SDRC_EMR3_x */
+            break;
+        case 0x14:
+            if (cs)
+                s->cs[1].actim_ctrla = value & 0xffffffdf; /* SDRC_ACTIM_CTRLA_1 */
+            break;                                         /* SDRC_DCDL1_CTRL */
+        case 0x18:
+            if (cs)
+                s->cs[1].actim_ctrlb = value & 0x000377ff; /* SDRC_ACTIM_CTRLB_1 */
+            break;                                         /* SDRC_DCDL2_CTRL */
+        case 0x1c:
+            if (!cs)
+                s->cs[0].actim_ctrla = value & 0xffffffdf; /* SDRC_ACTIM_CTRLA_0 */
+            else
+                OMAP_BAD_REGV(addr + 0x30, value);
+            break;
+        case 0x20:
+            if (!cs)
+                s->cs[0].actim_ctrlb = value & 0x000377ff; /* SDRC_ACTIM_CTRLB_0 */
+            else
+                OMAP_BAD_REGV(addr + 0x30, value);
+            break;
+        case 0x24: /* SDRC_RFR_CTRL_x */
+            s->cs[cs].rfr_ctrl = value & 0x00ffff03;
+            break;
+        case 0x28: /* SDRC_MANUAL_x */
+            s->cs[cs].manual = value & 0xffff000f;
+            break;
+        default:
+            OMAP_BAD_REGV(addr + cs * 0x30, value);
+            break;
+        }
         break;
 
     default:
-        OMAP_BAD_REG(addr);
-        return;
+        OMAP_BAD_REGV(addr, value);
+        break;
     }
 }
 
@@ -4049,6 +4236,7 @@ struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base)
 struct omap_gpmc_s {
     qemu_irq irq;
 
+    uint8_t revision;
     uint8_t sysconfig;
     uint16_t irqst;
     uint16_t irqen;
@@ -4066,6 +4254,8 @@ struct omap_gpmc_s {
         void (*base_update)(void *opaque, target_phys_addr_t new);
         void (*unmap)(void *opaque);
         void *opaque;
+        CPUReadMemoryFunc **nand_readfn;
+        CPUWriteMemoryFunc **nand_writefn;
     } cs_file[8];
     int ecc_cs;
     int ecc_ptr;
@@ -4144,7 +4334,7 @@ static void omap_gpmc_reset(struct omap_gpmc_s *s)
         s->cs_file[i].config[6] = 0xf00 | (i ? 0 : 1 << 6);
         if (s->cs_file[i].config[6] & (1 << 6))                        /* CSVALID */
             omap_gpmc_cs_map(&s->cs_file[i],
-                            s->cs_file[i].config[6] & 0x1f,    /* MASKADDR */
+                            s->cs_file[i].config[6] & 0x3f,    /* MASKADDR */
                         (s->cs_file[i].config[6] >> 8 & 0xf)); /* BASEADDR */
     }
     omap_gpmc_cs_map(s->cs_file, 0, 0xf);
@@ -4163,7 +4353,7 @@ static uint32_t omap_gpmc_read(void *opaque, target_phys_addr_t addr)
 
     switch (addr) {
     case 0x000:        /* GPMC_REVISION */
-        return 0x20;
+        return s->revision;
 
     case 0x010:        /* GPMC_SYSCONFIG */
         return s->sysconfig;
@@ -4210,6 +4400,8 @@ static uint32_t omap_gpmc_read(void *opaque, target_phys_addr_t addr)
             case 0x78: /* GPMC_CONFIG7 */
                 return f->config[6];
             case 0x84: /* GPMC_NAND_DATA */
+                if (f->nand_readfn)
+                    return f->nand_readfn[2](f->opaque, addr);
                 return 0;
         }
         break;
@@ -4252,6 +4444,56 @@ static uint32_t omap_gpmc_read(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
+static uint32_t omap_gpmc_read8(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
+    int cs;
+    struct omap_gpmc_cs_file_s *f;
+    
+    switch (addr) {
+        case 0x060 ... 0x1d4:
+            cs = (addr - 0x060) / 0x30;
+            addr -= cs * 0x30;
+            f = s->cs_file + cs;
+            switch (addr) {
+                case 0x84:     /* GPMC_NAND_DATA */
+                    if (f->nand_readfn)
+                        return f->nand_readfn[0](f->opaque, addr);
+                    return 0;
+            }
+            break;
+    default:
+        break;
+    }
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static uint32_t omap_gpmc_read16(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
+    int cs;
+    struct omap_gpmc_cs_file_s *f;
+    
+    switch (addr) {
+        case 0x060 ... 0x1d4:
+            cs = (addr - 0x060) / 0x30;
+            addr -= cs * 0x30;
+            f = s->cs_file + cs;
+            switch (addr) {
+                case 0x84:     /* GPMC_NAND_DATA */
+                    if (f->nand_readfn)
+                        return f->nand_readfn[1](f->opaque, addr);
+                    return 0;
+            }
+            break;
+        default:
+            break;
+    }
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
 static void omap_gpmc_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
@@ -4267,7 +4509,7 @@ static void omap_gpmc_write(void *opaque, target_phys_addr_t addr,
     case 0x200 ... 0x220:      /* GPMC_ECC_RESULT */
     case 0x234:        /* GPMC_PSA_LSB */
     case 0x238:        /* GPMC_PSA_MSB */
-        OMAP_RO_REG(addr);
+        OMAP_RO_REGV(addr, value);
         break;
 
     case 0x010:        /* GPMC_SYSCONFIG */
@@ -4329,7 +4571,7 @@ static void omap_gpmc_write(void *opaque, target_phys_addr_t addr,
                     if (f->config[6] & (1 << 6))               /* CSVALID */
                         omap_gpmc_cs_unmap(f);
                     if (value & (1 << 6))                      /* CSVALID */
-                        omap_gpmc_cs_map(f, value & 0x1f,      /* MASKADDR */
+                        omap_gpmc_cs_map(f, value & 0x3f,      /* MASKADDR */
                                         (value >> 8 & 0xf));   /* BASEADDR */
                 }
                 f->config[6] = value & 0x00000f7f;
@@ -4337,6 +4579,8 @@ static void omap_gpmc_write(void *opaque, target_phys_addr_t addr,
             case 0x7c: /* GPMC_NAND_COMMAND */
             case 0x80: /* GPMC_NAND_ADDRESS */
             case 0x84: /* GPMC_NAND_DATA */
+                if (f->nand_writefn)
+                    f->nand_writefn[2](f->opaque, addr, value);
                 break;
 
             default:
@@ -4387,29 +4631,93 @@ static void omap_gpmc_write(void *opaque, target_phys_addr_t addr,
 
     default:
     bad_reg:
-        OMAP_BAD_REG(addr);
+        OMAP_BAD_REGV(addr, value);
+        return;
+    }
+}
+
+static void omap_gpmc_write8(void *opaque, target_phys_addr_t addr,
+                             uint32_t value)
+{
+    struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
+    int cs;
+    struct omap_gpmc_cs_file_s *f;
+
+    switch (addr)
+    {
+    case 0x060 ... 0x1d4:
+        cs = (addr - 0x060) / 0x30;
+        addr -= cs * 0x30;
+        f = s->cs_file + cs;
+        switch (addr) {
+        case 0x7c:     /* GPMC_NAND_COMMAND */
+        case 0x80:     /* GPMC_NAND_ADDRESS */
+        case 0x84:     /* GPMC_NAND_DATA */
+            if (f->nand_writefn)
+                f->nand_writefn[0](f->opaque, addr, value);
+            break;
+        default:
+            goto bad_reg;
+        }
+        break;
+    default:
+    bad_reg:
+        OMAP_BAD_REGV(addr, value);
+        return;
+    }
+}
+
+static void omap_gpmc_write16(void *opaque, target_phys_addr_t addr,
+                              uint32_t value)
+{
+    struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
+    int cs;
+    struct omap_gpmc_cs_file_s *f;
+    
+    switch (addr)
+    {
+    case 0x060 ... 0x1d4:
+        cs = (addr - 0x060) / 0x30;
+        addr -= cs * 0x30;
+        f = s->cs_file + cs;
+        switch (addr) {
+        case 0x7c:     /* GPMC_NAND_COMMAND */
+        case 0x80:     /* GPMC_NAND_ADDRESS */
+        case 0x84:     /* GPMC_NAND_DATA */
+            if (f->nand_writefn)
+                f->nand_writefn[1](f->opaque, addr, value);
+            break;
+        default:
+        goto bad_reg;
+        }
+        break;
+    default:
+    bad_reg:
+        OMAP_BAD_REGV(addr, value);
         return;
     }
 }
 
 static CPUReadMemoryFunc *omap_gpmc_readfn[] = {
-    omap_badwidth_read32,      /* TODO */
-    omap_badwidth_read32,      /* TODO */
+    omap_gpmc_read8,
+    omap_gpmc_read16,
     omap_gpmc_read,
 };
 
 static CPUWriteMemoryFunc *omap_gpmc_writefn[] = {
-    omap_badwidth_write32,     /* TODO */
-    omap_badwidth_write32,     /* TODO */
+    omap_gpmc_write8,
+    omap_gpmc_write16,
     omap_gpmc_write,
 };
 
-struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq)
+struct omap_gpmc_s *omap_gpmc_init(struct omap_mpu_state_s *mpu,
+                                   target_phys_addr_t base, qemu_irq irq)
 {
     int iomemtype;
     struct omap_gpmc_s *s = (struct omap_gpmc_s *)
             qemu_mallocz(sizeof(struct omap_gpmc_s));
 
+    s->revision = cpu_class_omap3(mpu) ? 0x50 : 0x20;
     omap_gpmc_reset(s);
 
     iomemtype = cpu_register_io_memory(0, omap_gpmc_readfn,
@@ -4421,7 +4729,9 @@ struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq)
 
 void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
                 void (*base_upd)(void *opaque, target_phys_addr_t new),
-                void (*unmap)(void *opaque), void *opaque)
+                void (*unmap)(void *opaque), void *opaque,
+                CPUReadMemoryFunc **nand_readfn,
+                CPUWriteMemoryFunc **nand_writefn)
 {
     struct omap_gpmc_cs_file_s *f;
 
@@ -4435,9 +4745,11 @@ void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
     f->base_update = base_upd;
     f->unmap = unmap;
     f->opaque = opaque;
+    f->nand_readfn = nand_readfn;
+    f->nand_writefn = nand_writefn;
 
     if (f->config[6] & (1 << 6))                               /* CSVALID */
-        omap_gpmc_cs_map(f, f->config[6] & 0x1f,               /* MASKADDR */
+        omap_gpmc_cs_map(f, f->config[6] & 0x3f,               /* MASKADDR */
                         (f->config[6] >> 8 & 0xf));            /* BASEADDR */
 }
 
@@ -4528,7 +4840,8 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
 
     /* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
     cpu_irq = arm_pic_init_cpu(s->env);
-    s->ih[0] = omap2_inth_init(0x480fe000, 0x1000, 3, &s->irq[0],
+    s->ih[0] = omap2_inth_init(s,
+                    0x480fe000, 0x1000, 3, &s->irq[0],
                     cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ],
                     omap_findclk(s, "mpu_intc_fclk"),
                     omap_findclk(s, "mpu_intc_iclk"));
@@ -4642,12 +4955,12 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
     gpio_clks[1] = omap_findclk(s, "gpio2_dbclk");
     gpio_clks[2] = omap_findclk(s, "gpio3_dbclk");
     gpio_clks[3] = omap_findclk(s, "gpio4_dbclk");
-    s->gpif = omap2_gpio_init(omap_l4ta(s->l4, 3),
+    s->gpif = omap2_gpio_init(s, omap_l4ta(s->l4, 3),
                     &s->irq[0][OMAP_INT_24XX_GPIO_BANK1],
                     gpio_clks, omap_findclk(s, "gpio_iclk"), 4);
 
     s->sdrc = omap_sdrc_init(0x68009000);
-    s->gpmc = omap_gpmc_init(0x6800a000, s->irq[0][OMAP_INT_24XX_GPMC_IRQ]);
+    s->gpmc = omap_gpmc_init(s, 0x6800a000, s->irq[0][OMAP_INT_24XX_GPMC_IRQ]);
 
     sdindex = drive_get_index(IF_SD, 0, 0);
     if (sdindex == -1) {
@@ -4676,7 +4989,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
                     omap_findclk(s, "dss_clk1"), omap_findclk(s, "dss_clk2"),
                     omap_findclk(s, "dss_54m_clk"),
                     omap_findclk(s, "dss_l3_iclk"),
-                    omap_findclk(s, "dss_l4_iclk"));
+                    omap_findclk(s, "dss_l4_iclk"),0);
 
     omap_sti_init(omap_l4ta(s->l4, 18), 0x54000000,
                     s->irq[0][OMAP_INT_24XX_STI], omap_findclk(s, "emul_ck"),
diff --git a/hw/omap3.c b/hw/omap3.c
new file mode 100644 (file)
index 0000000..d75e282
--- /dev/null
@@ -0,0 +1,4441 @@
+/*
+ * TI OMAP3 processors emulation.
+ *
+ * Copyright (C) 2008 yajin <yajin@vm-kernel.org>
+ *
+ * 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 or
+ * (at your option) version 3 of the License.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "hw.h"
+#include "arm-misc.h"
+#include "omap.h"
+#include "sysemu.h"
+#include "qemu-timer.h"
+#include "qemu-char.h"
+#include "flash.h"
+#include "soc_dma.h"
+#include "audio/audio.h"
+#include "block.h"
+
+//#define OMAP3_DEBUG_
+
+#ifdef OMAP3_DEBUG_
+#define TRACE(fmt, ...) fprintf(stderr, "%s " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
+#else
+#define TRACE(...) 
+#endif
+
+static uint32_t omap3_l4ta_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_target_agent_s *s = (struct omap_target_agent_s *)opaque;
+
+    switch (addr) {
+        case 0x00: /* COMPONENT_L */
+            return s->component;
+        case 0x04: /* COMPONENT_H */
+            return 0;
+        case 0x18: /* CORE_L */
+            return s->component;
+        case 0x1c: /* CORE_H */
+            return (s->component >> 16);
+        case 0x20: /* AGENT_CONTROL_L */
+            return s->control;
+        case 0x24: /* AGENT_CONTROL_H */
+            return s->control_h;
+        case 0x28: /* AGENT_STATUS_L */
+            return s->status;
+        case 0x2c: /* AGENT_STATUS_H */
+            return 0;
+        default:
+            break;
+    }
+
+    OMAP_BAD_REG(s->base + addr);
+    return 0;
+}
+
+static void omap3_l4ta_write(void *opaque, target_phys_addr_t addr,
+                             uint32_t value)
+{
+    struct omap_target_agent_s *s = (struct omap_target_agent_s *)opaque;
+
+    switch (addr) {
+        case 0x00: /* COMPONENT_L */
+        case 0x04: /* COMPONENT_H */
+        case 0x18: /* CORE_L */
+        case 0x1c: /* CORE_H */
+            OMAP_RO_REG(s->base + addr);
+            break;
+        case 0x20: /* AGENT_CONTROL_L */
+            s->control = value & 0x00000701;
+            break;
+        case 0x24: /* AGENT_CONTROL_H */
+            s->control_h = value & 0x100; /* TODO: shouldn't this be read-only? */
+            break;
+        case 0x28: /* AGENT_STATUS_L */
+            if (value & 0x100)
+                s->status &= ~0x100; /* REQ_TIMEOUT */
+            break;
+        case 0x2c: /* AGENT_STATUS_H */
+            /* no writable bits although the register is listed as RW */
+            break;
+        default:
+            OMAP_BAD_REG(s->base + addr);
+            break;
+    }
+}
+
+static CPUReadMemoryFunc *omap3_l4ta_readfn[] = {
+    omap_badwidth_read16,
+    omap3_l4ta_read,
+    omap_badwidth_read16,
+};
+
+static CPUWriteMemoryFunc *omap3_l4ta_writefn[] = {
+    omap_badwidth_write32,
+    omap_badwidth_write32,
+    omap3_l4ta_write,
+};
+
+enum omap3_l4_region_id_t {
+    /* 48000000-48001FFF */
+    /* 48002000-48002FFF */ L4ID_SCM = 0,
+    /* 48003000-48003FFF */ L4ID_SCM_TA,
+    /* 48004000-48005FFF */ L4ID_CM_A,
+    /* 48006000-480067FF */ L4ID_CM_B,
+    /* 48006800-48006FFF */
+    /* 48007000-48007FFF */ L4ID_CM_TA,
+    /* 48008000-48023FFF */
+    /* 48024000-48024FFF */
+    /* 48025000-48025FFF */
+    /* 48026000-4803FFFF */
+    /* 48040000-480407FF */ L4ID_CORE_AP,
+    /* 48040800-48040FFF */ L4ID_CORE_IP,
+    /* 48041000-48041FFF */ L4ID_CORE_LA,
+    /* 48042000-4804FBFF */
+    /* 4804FC00-4804FFFF */ L4ID_DSI,
+    /* 48050000-480503FF */ L4ID_DSS,
+    /* 48050400-480507FF */ L4ID_DISPC,
+    /* 48050800-48050BFF */ L4ID_RFBI,
+    /* 48050C00-48050FFF */ L4ID_VENC,
+    /* 48051000-48051FFF */ L4ID_DSS_TA,
+    /* 48052000-48055FFF */
+    /* 48056000-48056FFF */ L4ID_SDMA,
+    /* 48057000-48057FFF */ L4ID_SDMA_TA,
+    /* 48058000-4805FFFF */
+    /* 48060000-48060FFF */ L4ID_I2C3,
+    /* 48061000-48061FFF */ L4ID_I2C3_TA,
+    /* 48062000-48062FFF */ L4ID_USBTLL,
+    /* 48063000-48063FFF */ L4ID_USBTLL_TA,
+    /* 48064000-48064FFF */ L4ID_HSUSBHOST,
+    /* 48065000-48065FFF */ L4ID_HSUSBHOST_TA,
+    /* 48066000-48069FFF */
+    /* 4806A000-4806AFFF */ L4ID_UART1,
+    /* 4806B000-4806BFFF */ L4ID_UART1_TA,
+    /* 4806C000-4806CFFF */ L4ID_UART2,
+    /* 4806D000-4806DFFF */ L4ID_UART2_TA,
+    /* 4806E000-4806FFFF */
+    /* 48070000-48070FFF */ L4ID_I2C1,
+    /* 48071000-48071FFF */ L4ID_I2C1_TA,
+    /* 48072000-48072FFF */ L4ID_I2C2,
+    /* 48073000-48073FFF */ L4ID_I2C2_TA,
+    /* 48074000-48074FFF */ L4ID_MCBSP1,
+    /* 48075000-48075FFF */ L4ID_MCBSP1_TA,
+    /* 48076000-48085FFF */
+    /* 48086000-48086FFF */ L4ID_GPTIMER10,
+    /* 48087000-48087FFF */ L4ID_GPTIMER10_TA,
+    /* 48088000-48088FFF */ L4ID_GPTIMER11,
+    /* 48089000-48089FFF */ L4ID_GPTIMER11_TA,
+    /* 4808A000-4808AFFF */
+    /* 4808B000-4808BFFF */
+    /* 4808C000-48093FFF */
+    /* 48094000-48094FFF */ L4ID_MAILBOX,
+    /* 48095000-48095FFF */ L4ID_MAILBOX_TA,
+    /* 48096000-48096FFF */ L4ID_MCBSP5,
+    /* 48097000-48097FFF */ L4ID_MCBSP5_TA,
+    /* 48098000-48098FFF */ L4ID_MCSPI1,
+    /* 48099000-48099FFF */ L4ID_MCSPI1_TA,
+    /* 4809A000-4809AFFF */ L4ID_MCSPI2,
+    /* 4809B000-4809BFFF */ L4ID_MCSPI2_TA,
+    /* 4809C000-4809CFFF */ L4ID_MMCSDIO1,
+    /* 4809D000-4809DFFF */ L4ID_MMCSDIO1_TA,
+    /* 4809E000-4809EFFF */ L4ID_MSPRO,
+    /* 4809F000-4809FFFF */ L4ID_MSPRO_TA,
+    /* 480A0000-480AAFFF */
+    /* 480AB000-480ABFFF */ L4ID_HSUSBOTG,
+    /* 480AC000-480ACFFF */ L4ID_HSUSBOTG_TA,
+    /* 480AD000-480ADFFF */ L4ID_MMCSDIO3,
+    /* 480AE000-480AEFFF */ L4ID_MMCSDIO3_TA,
+    /* 480AF000-480AFFFF */
+    /* 480B0000-480B0FFF */
+    /* 480B1000-480B1FFF */
+    /* 480B2000-480B2FFF */ L4ID_HDQ1WIRE,
+    /* 480B3000-480B2FFF */ L4ID_HDQ1WIRE_TA,
+    /* 480B4000-480B4FFF */ L4ID_MMCSDIO2,
+    /* 480B5000-480B5FFF */ L4ID_MMCSDIO2_TA,
+    /* 480B6000-480B6FFF */ L4ID_ICRMPU,
+    /* 480B7000-480B7FFF */ L4ID_ICRMPU_TA,
+    /* 480B8000-480B8FFF */ L4ID_MCSPI3,
+    /* 480B9000-480B9FFF */ L4ID_MCSPI3_TA,
+    /* 480BA000-480BAFFF */ L4ID_MCSPI4,
+    /* 480BB000-480BBFFF */ L4ID_MCSPI4_TA,
+    /* 480BC000-480BFFFF */ L4ID_CAMERAISP,
+    /* 480C0000-480C0FFF */ L4ID_CAMERAISP_TA,
+    /* 480C1000-480CCFFF */
+    /* 480CD000-480CDFFF */ L4ID_ICRMODEM,
+    /* 480CE000-480CEFFF */ L4ID_ICRMODEM_TA,
+    /* 480CF000-482FFFFF */
+    /* 48300000-48303FFF */
+    /* 48304000-48304FFF */ L4ID_GPTIMER12,
+    /* 48305000-48305FFF */ L4ID_GPTIMER12_TA,
+    /* 48306000-48307FFF */ L4ID_PRM_A,
+    /* 48308000-483087FF */ L4ID_PRM_B,
+    /* 48308800-48308FFF */
+    /* 48309000-48309FFF */ L4ID_PRM_TA,
+    /* 4830A000-4830AFFF */ L4ID_TAP,
+    /* 4830B000-4830BFFF */ L4ID_TAP_TA,
+    /* 4830C000-4830FFFF */
+    /* 48310000-48310FFF */ L4ID_GPIO1,
+    /* 48311000-48311FFF */ L4ID_GPIO1_TA,
+    /* 48312000-48313FFF */
+    /* 48314000-48314FFF */ L4ID_WDTIMER2,
+    /* 48315000-48315FFF */ L4ID_WDTIMER2_TA,
+    /* 48316000-48317FFF */
+    /* 48318000-48318FFF */ L4ID_GPTIMER1,
+    /* 48319000-48319FFF */ L4ID_GPTIMER1_TA,
+    /* 4831A000-4831FFFF */
+    /* 48320000-48320FFF */ L4ID_32KTIMER,
+    /* 48321000-48321FFF */ L4ID_32KTIMER_TA,
+    /* 48322000-48327FFF */
+    /* 48328000-483287FF */ L4ID_WAKEUP_AP,
+    /* 48328800-48328FFF */ L4ID_WAKEUP_C_IP,
+    /* 48329000-48329FFF */ L4ID_WAKEUP_LA,
+    /* 4832A000-4832A7FF */ L4ID_WAKEUP_E_IP,
+    /* 4832A800-4833FFFF */
+    /* 48340000-48340FFF */
+    /* 48341000-48FFFFFF */
+    /* 49000000-490007FF */ L4ID_PER_AP,
+    /* 49000800-49000FFF */ L4ID_PER_IP,
+    /* 49001000-49001FFF */ L4ID_PER_LA,
+    /* 49002000-4901FFFF */
+    /* 49020000-49020FFF */ L4ID_UART3,
+    /* 49021000-49021FFF */ L4ID_UART3_TA,
+    /* 49022000-49022FFF */ L4ID_MCBSP2,
+    /* 49023000-49023FFF */ L4ID_MCBSP2_TA,
+    /* 49024000-49024FFF */ L4ID_MCBSP3,
+    /* 49025000-49025FFF */ L4ID_MCBSP3_TA,
+    /* 49026000-49026FFF */ L4ID_MCBSP4,
+    /* 49027000-49027FFF */ L4ID_MCBSP4_TA,
+    /* 49028000-49028FFF */ L4ID_MCBSP2S,
+    /* 49029000-49029FFF */ L4ID_MCBSP2S_TA,
+    /* 4902A000-4902AFFF */ L4ID_MCBSP3S,
+    /* 4902B000-4902BFFF */ L4ID_MCBSP3S_TA,
+    /* 4902C000-4902FFFF */
+    /* 49030000-49030FFF */ L4ID_WDTIMER3,
+    /* 49031000-49031FFF */ L4ID_WDTIMER3_TA,
+    /* 49032000-49032FFF */ L4ID_GPTIMER2,
+    /* 49033000-49033FFF */ L4ID_GPTIMER2_TA,
+    /* 49034000-49034FFF */ L4ID_GPTIMER3,
+    /* 49035000-49035FFF */ L4ID_GPTIMER3_TA,
+    /* 49036000-49036FFF */ L4ID_GPTIMER4,
+    /* 49037000-49037FFF */ L4ID_GPTIMER4_TA,
+    /* 49038000-49038FFF */ L4ID_GPTIMER5,
+    /* 49039000-49039FFF */ L4ID_GPTIMER5_TA,
+    /* 4903A000-4903AFFF */ L4ID_GPTIMER6,
+    /* 4903B000-4903BFFF */ L4ID_GPTIMER6_TA,
+    /* 4903C000-4903CFFF */ L4ID_GPTIMER7,
+    /* 4903D000-4903DFFF */ L4ID_GPTIMER7_TA,
+    /* 4903E000-4903EFFF */ L4ID_GPTIMER8,
+    /* 4903F000-4903FFFF */ L4ID_GPTIMER8_TA,
+    /* 49040000-49040FFF */ L4ID_GPTIMER9,
+    /* 49041000-49041FFF */ L4ID_GPTIMER9_TA,
+    /* 49042000-4904FFFF */
+    /* 49050000-49050FFF */ L4ID_GPIO2,
+    /* 49051000-49051FFF */ L4ID_GPIO2_TA,
+    /* 49052000-49052FFF */ L4ID_GPIO3,
+    /* 49053000-49053FFF */ L4ID_GPIO3_TA,
+    /* 49054000-49054FFF */ L4ID_GPIO4,
+    /* 49055000-49055FFF */ L4ID_GPIO4_TA,
+    /* 49056000-49056FFF */ L4ID_GPIO5,
+    /* 49057000-49057FFF */ L4ID_GPIO5_TA,
+    /* 49058000-49058FFF */ L4ID_GPIO6,
+    /* 49059000-49059FFF */ L4ID_GPIO6_TA,
+    /* 4905A000-490FFFFF */
+    /* 54000000-54003FFF */
+    /* 54004000-54005FFF */
+    /* 54006000-540067FF */ L4ID_EMU_AP,
+    /* 54006800-54006FFF */ L4ID_EMU_IP_C,
+    /* 54007000-54007FFF */ L4ID_EMU_LA,
+    /* 54008000-540087FF */ L4ID_EMU_IP_DAP,
+    /* 54008800-5400FFFF */
+    /* 54010000-54017FFF */ L4ID_MPUEMU,
+    /* 54018000-54018FFF */ L4ID_MPUEMU_TA,
+    /* 54019000-54019FFF */ L4ID_TPIU,
+    /* 5401A000-5401AFFF */ L4ID_TPIU_TA,
+    /* 5401B000-5401BFFF */ L4ID_ETB,
+    /* 5401C000-5401CFFF */ L4ID_ETB_TA,
+    /* 5401D000-5401DFFF */ L4ID_DAPCTL,
+    /* 5401E000-5401EFFF */ L4ID_DAPCTL_TA,
+    /* 5401F000-5401FFFF */ L4ID_SDTI_TA,
+    /* 54020000-544FFFFF */
+    /* 54500000-5450FFFF */ L4ID_SDTI_CFG,
+    /* 54510000-545FFFFF */
+    /* 54600000-546FFFFF */ L4ID_SDTI,
+    /* 54700000-54705FFF */
+    /* 54706000-54707FFF */ L4ID_EMU_PRM_A,
+    /* 54708000-547087FF */ L4ID_EMU_PRM_B,
+    /* 54708800-54708FFF */
+    /* 54709000-54709FFF */ L4ID_EMU_PRM_TA,
+    /* 5470A000-5470FFFF */
+    /* 54710000-54710FFF */ L4ID_EMU_GPIO1,
+    /* 54711000-54711FFF */ L4ID_EMU_GPIO1_TA,
+    /* 54712000-54713FFF */
+    /* 54714000-54714FFF */ L4ID_EMU_WDTM2,
+    /* 54715000-54715FFF */ L4ID_EMU_WDTM2_TA,
+    /* 54716000-54717FFF */
+    /* 54718000-54718FFF */ L4ID_EMU_GPTM1,
+    /* 54719000-54719FFF */ L4ID_EMU_GPTM1_TA,
+    /* 5471A000-5471FFFF */
+    /* 54720000-54720FFF */ L4ID_EMU_32KTM,
+    /* 54721000-54721FFF */ L4ID_EMU_32KTM_TA,
+    /* 54722000-54727FFF */
+    /* 54728000-547287FF */ L4ID_EMU_WKUP_AP,
+    /* 54728800-54728FFF */ L4ID_EMU_WKUP_IPC,
+    /* 54729000-54729FFF */ L4ID_EMU_WKUP_LA,
+    /* 5472A000-5472A7FF */ L4ID_EMU_WKUP_IPE,
+    /* 5472A800-547FFFFF */
+};
+
+static struct omap_l4_region_s omap3_l4_region[] = {
+    /* L4-Core */
+    [L4ID_SCM         ] = {0x00002000, 0x1000, 32 | 16 | 8},
+    [L4ID_SCM_TA      ] = {0x00003000, 0x1000, 32 | 16 | 8},
+    [L4ID_CM_A        ] = {0x00004000, 0x2000, 32         },
+    [L4ID_CM_B        ] = {0x00006000, 0x0800, 32         },
+    [L4ID_CM_TA       ] = {0x00007000, 0x1000, 32 | 16 | 8},
+    [L4ID_CORE_AP     ] = {0x00040000, 0x0800, 32         },
+    [L4ID_CORE_IP     ] = {0x00040800, 0x0800, 32         },
+    [L4ID_CORE_LA     ] = {0x00041000, 0x1000, 32         },
+    [L4ID_DSI         ] = {0x0004fc00, 0x0400, 32 | 16 | 8},
+    [L4ID_DSS         ] = {0x00050000, 0x0400, 32 | 16 | 8},
+    [L4ID_DISPC       ] = {0x00050400, 0x0400, 32 | 16 | 8},
+    [L4ID_RFBI        ] = {0x00050800, 0x0400, 32 | 16 | 8},
+    [L4ID_VENC        ] = {0x00050c00, 0x0400, 32 | 16 | 8},
+    [L4ID_DSS_TA      ] = {0x00051000, 0x1000, 32 | 16 | 8},
+    [L4ID_SDMA        ] = {0x00056000, 0x1000, 32         },
+    [L4ID_SDMA_TA     ] = {0x00057000, 0x1000, 32 | 16 | 8},
+    [L4ID_I2C3        ] = {0x00060000, 0x1000,      16 | 8},
+    [L4ID_I2C3_TA     ] = {0x00061000, 0x1000, 32 | 16 | 8},
+    [L4ID_USBTLL      ] = {0x00062000, 0x1000, 32         },
+    [L4ID_USBTLL_TA   ] = {0x00063000, 0x1000, 32 | 16 | 8},
+    [L4ID_HSUSBHOST   ] = {0x00064000, 0x1000, 32         },
+    [L4ID_HSUSBHOST_TA] = {0x00065000, 0x1000, 32 | 16 | 8},
+    [L4ID_UART1       ] = {0x0006a000, 0x1000, 32 | 16 | 8},
+    [L4ID_UART1_TA    ] = {0x0006b000, 0x1000, 32 | 16 | 8},
+    [L4ID_UART2       ] = {0x0006c000, 0x1000, 32 | 16 | 8},
+    [L4ID_UART2_TA    ] = {0x0006d000, 0x1000, 32 | 16 | 8},
+    [L4ID_I2C1        ] = {0x00070000, 0x1000,      16 | 8},
+    [L4ID_I2C1_TA     ] = {0x00071000, 0x1000, 32 | 16 | 8},
+    [L4ID_I2C2        ] = {0x00072000, 0x1000,      16 | 8},
+    [L4ID_I2C2_TA     ] = {0x00073000, 0x1000, 32 | 16 | 8},
+    [L4ID_MCBSP1      ] = {0x00074000, 0x1000, 32         },
+    [L4ID_MCBSP1_TA   ] = {0x00075000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPTIMER10   ] = {0x00086000, 0x1000, 32 | 16    },
+    [L4ID_GPTIMER10_TA] = {0x00087000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPTIMER11   ] = {0x00088000, 0x1000, 32 | 16    },
+    [L4ID_GPTIMER11_TA] = {0x00089000, 0x1000, 32 | 16 | 8},
+    [L4ID_MAILBOX     ] = {0x00094000, 0x1000, 32 | 16 | 8},
+    [L4ID_MAILBOX_TA  ] = {0x00095000, 0x1000, 32 | 16 | 8},
+    [L4ID_MCBSP5      ] = {0x00096000, 0x1000, 32         },
+    [L4ID_MCBSP5_TA   ] = {0x00097000, 0x1000, 32 | 16 | 8},
+    [L4ID_MCSPI1      ] = {0x00098000, 0x1000, 32 | 16 | 8},
+    [L4ID_MCSPI1_TA   ] = {0x00099000, 0x1000, 32 | 16 | 8},
+    [L4ID_MCSPI2      ] = {0x0009a000, 0x1000, 32 | 16 | 8},
+    [L4ID_MCSPI2_TA   ] = {0x0009b000, 0x1000, 32 | 16 | 8},
+    [L4ID_MMCSDIO1    ] = {0x0009c000, 0x1000, 32         },
+    [L4ID_MMCSDIO1_TA ] = {0x0009d000, 0x1000, 32 | 16 | 8},
+    [L4ID_MSPRO       ] = {0x0009e000, 0x1000, 32         },
+    [L4ID_MSPRO_TA    ] = {0x0009f000, 0x1000, 32 | 16 | 8},
+    [L4ID_HSUSBOTG    ] = {0x000ab000, 0x1000, 32         },
+    [L4ID_HSUSBOTG_TA ] = {0x000ac000, 0x1000, 32 | 16 | 8},
+    [L4ID_MMCSDIO3    ] = {0x000ad000, 0x1000, 32         },
+    [L4ID_MMCSDIO3_TA ] = {0x000ae000, 0x1000, 32 | 16 | 8},
+    [L4ID_HDQ1WIRE    ] = {0x000b2000, 0x1000, 32         },
+    [L4ID_HDQ1WIRE_TA ] = {0x000b3000, 0x1000, 32 | 16 | 8},
+    [L4ID_MMCSDIO2    ] = {0x000b4000, 0x1000, 32         },
+    [L4ID_MMCSDIO2_TA ] = {0x000b5000, 0x1000, 32 | 16 | 8},
+    [L4ID_ICRMPU      ] = {0x000b6000, 0x1000, 32         },
+    [L4ID_ICRMPU_TA   ] = {0x000b7000, 0x1000, 32 | 16 | 8},
+    [L4ID_MCSPI3      ] = {0x000b8000, 0x1000, 32 | 16 | 8},
+    [L4ID_MCSPI3_TA   ] = {0x000b9000, 0x1000, 32 | 16 | 8},
+    [L4ID_MCSPI4      ] = {0x000ba000, 0x1000, 32 | 16 | 8},
+    [L4ID_MCSPI4_TA   ] = {0x000bb000, 0x1000, 32 | 16 | 8},
+    [L4ID_CAMERAISP   ] = {0x000bc000, 0x4000, 32 | 16 | 8},
+    [L4ID_CAMERAISP_TA] = {0x000c0000, 0x1000, 32 | 16 | 8},
+    [L4ID_ICRMODEM    ] = {0x000cd000, 0x1000, 32         },
+    [L4ID_ICRMODEM_TA ] = {0x000ce000, 0x1000, 32 | 16 | 8},
+    /* L4-Wakeup interconnect region A */
+    [L4ID_GPTIMER12   ] = {0x00304000, 0x1000, 32 | 16    },
+    [L4ID_GPTIMER12_TA] = {0x00305000, 0x1000, 32 | 16 | 8},
+    [L4ID_PRM_A       ] = {0x00306000, 0x2000, 32         },
+    [L4ID_PRM_B       ] = {0x00308000, 0x0800, 32         },
+    [L4ID_PRM_TA      ] = {0x00309000, 0x1000, 32 | 16 | 8},
+    /* L4-Core */
+    [L4ID_TAP         ] = {0x0030a000, 0x1000, 32 | 16 | 8},
+    [L4ID_TAP_TA      ] = {0x0030b000, 0x1000, 32 | 16 | 8},
+    /* L4-Wakeup interconnect region B */
+    [L4ID_GPIO1       ] = {0x00310000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPIO1_TA    ] = {0x00311000, 0x1000, 32 | 16 | 8},
+    [L4ID_WDTIMER2    ] = {0x00314000, 0x1000, 32 | 16    },
+    [L4ID_WDTIMER2_TA ] = {0x00315000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPTIMER1    ] = {0x00318000, 0x1000, 32 | 16    },
+    [L4ID_GPTIMER1_TA ] = {0x00319000, 0x1000, 32 | 16 | 8},
+    [L4ID_32KTIMER    ] = {0x00320000, 0x1000, 32 | 16    },
+    [L4ID_32KTIMER_TA ] = {0x00321000, 0x1000, 32 | 16 | 8},
+    [L4ID_WAKEUP_AP   ] = {0x00328000, 0x0800, 32 | 16 | 8},
+    [L4ID_WAKEUP_C_IP ] = {0x00328800, 0x0800, 32 | 16 | 8},
+    [L4ID_WAKEUP_LA   ] = {0x00329000, 0x1000, 32 | 16 | 8},
+    [L4ID_WAKEUP_E_IP ] = {0x0032a000, 0x0800, 32 | 16 | 8},
+    /* L4-Per */
+    [L4ID_PER_AP      ] = {0x01000000, 0x0800, 32 | 16 | 8},
+    [L4ID_PER_IP      ] = {0x01000800, 0x0800, 32 | 16 | 8},
+    [L4ID_PER_LA      ] = {0x01001000, 0x1000, 32 | 16 | 8},
+    [L4ID_UART3       ] = {0x01020000, 0x1000, 32 | 16 | 8},
+    [L4ID_UART3_TA    ] = {0x01021000, 0x1000, 32 | 16 | 8},
+    [L4ID_MCBSP2      ] = {0x01022000, 0x1000, 32         },
+    [L4ID_MCBSP2_TA   ] = {0x01023000, 0x1000, 32 | 16 | 8},
+    [L4ID_MCBSP3      ] = {0x01024000, 0x1000, 32         },
+    [L4ID_MCBSP3_TA   ] = {0x01025000, 0x1000, 32 | 16 | 8},
+    [L4ID_MCBSP4      ] = {0x01026000, 0x1000, 32         },
+    [L4ID_MCBSP4_TA   ] = {0x01027000, 0x1000, 32 | 16 | 8},
+    [L4ID_MCBSP2S     ] = {0x01028000, 0x1000, 32         },
+    [L4ID_MCBSP2S_TA  ] = {0x01029000, 0x1000, 32 | 16 | 8},
+    [L4ID_MCBSP3S     ] = {0x0102a000, 0x1000, 32         },
+    [L4ID_MCBSP3S_TA  ] = {0x0102b000, 0x1000, 32 | 16 | 8},
+    [L4ID_WDTIMER3    ] = {0x01030000, 0x1000, 32 | 16    },
+    [L4ID_WDTIMER3_TA ] = {0x01031000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPTIMER2    ] = {0x01032000, 0x1000, 32 | 16    },
+    [L4ID_GPTIMER2_TA ] = {0x01033000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPTIMER3    ] = {0x01034000, 0x1000, 32 | 16    },
+    [L4ID_GPTIMER3_TA ] = {0x01035000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPTIMER4    ] = {0x01036000, 0x1000, 32 | 16    },
+    [L4ID_GPTIMER4_TA ] = {0x01037000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPTIMER5    ] = {0x01038000, 0x1000, 32 | 16    },
+    [L4ID_GPTIMER5_TA ] = {0x01039000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPTIMER6    ] = {0x0103a000, 0x1000, 32 | 16    },
+    [L4ID_GPTIMER6_TA ] = {0x0103b000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPTIMER7    ] = {0x0103c000, 0x1000, 32 | 16    },
+    [L4ID_GPTIMER7_TA ] = {0x0103d000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPTIMER8    ] = {0x0103e000, 0x1000, 32 | 16    },
+    [L4ID_GPTIMER8_TA ] = {0x0103f000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPTIMER9    ] = {0x01040000, 0x1000, 32 | 16    },
+    [L4ID_GPTIMER9_TA ] = {0x01041000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPIO2       ] = {0x01050000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPIO2_TA    ] = {0x01051000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPIO3       ] = {0x01052000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPIO3_TA    ] = {0x01053000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPIO4       ] = {0x01054000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPIO4_TA    ] = {0x01055000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPIO5       ] = {0x01056000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPIO5_TA    ] = {0x01057000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPIO6       ] = {0x01058000, 0x1000, 32 | 16 | 8},
+    [L4ID_GPIO6_TA    ] = {0x01059000, 0x1000, 32 | 16 | 8},
+    /* L4-Emu */
+    [L4ID_EMU_AP      ] = {0x0c006000, 0x0800, 32 | 16 | 8},
+    [L4ID_EMU_IP_C    ] = {0x0c006800, 0x0800, 32 | 16 | 8},
+    [L4ID_EMU_LA      ] = {0x0c007000, 0x1000, 32 | 16 | 8},
+    [L4ID_EMU_IP_DAP  ] = {0x0c008000, 0x0800, 32 | 16 | 8},
+    [L4ID_MPUEMU      ] = {0x0c010000, 0x8000, 32 | 16 | 8},
+    [L4ID_MPUEMU_TA   ] = {0x0c018000, 0x1000, 32 | 16 | 8},
+    [L4ID_TPIU        ] = {0x0c019000, 0x1000, 32         },
+    [L4ID_TPIU_TA     ] = {0x0c01a000, 0x1000, 32 | 16 | 8},
+    [L4ID_ETB         ] = {0x0c01b000, 0x1000, 32         },
+    [L4ID_ETB_TA      ] = {0x0c01c000, 0x1000, 32 | 16 | 8},
+    [L4ID_DAPCTL      ] = {0x0c01d000, 0x1000, 32         },
+    [L4ID_DAPCTL_TA   ] = {0x0c01e000, 0x1000, 32 | 16 | 8},
+    [L4ID_EMU_PRM_A   ] = {0x0c706000, 0x2000, 32         },
+    [L4ID_EMU_PRM_B   ] = {0x0c706800, 0x0800, 32         },
+    [L4ID_EMU_PRM_TA  ] = {0x0c709000, 0x1000, 32 | 16 | 8},
+    [L4ID_EMU_GPIO1   ] = {0x0c710000, 0x1000, 32 | 16 | 8},
+    [L4ID_EMU_GPIO1_TA] = {0x0c711000, 0x1000, 32 | 16 | 8},
+    [L4ID_EMU_WDTM2   ] = {0x0c714000, 0x1000, 32 | 16    },
+    [L4ID_EMU_WDTM2_TA] = {0x0c715000, 0x1000, 32 | 16 | 8},
+    [L4ID_EMU_GPTM1   ] = {0x0c718000, 0x1000, 32 | 16 | 8},
+    [L4ID_EMU_GPTM1_TA] = {0x0c719000, 0x1000, 32 | 16 | 8},
+    [L4ID_EMU_32KTM   ] = {0x0c720000, 0x1000, 32 | 16    },
+    [L4ID_EMU_32KTM_TA] = {0x0c721000, 0x1000, 32 | 16 | 8},
+    [L4ID_EMU_WKUP_AP ] = {0x0c728000, 0x0800, 32 | 16 | 8},
+    [L4ID_EMU_WKUP_IPC] = {0x0c728800, 0x0800, 32 | 16 | 8},
+    [L4ID_EMU_WKUP_LA ] = {0x0c729000, 0x1000, 32 | 16 | 8},
+    [L4ID_EMU_WKUP_IPE] = {0x0c72a000, 0x0800, 32 | 16 | 8},
+};
+
+enum omap3_agent_info_id_t {
+    L4A_SCM = 0,
+    L4A_CM,
+    L4A_PRM,
+    L4A_GPTIMER1,
+    L4A_GPTIMER2,
+    L4A_GPTIMER3,
+    L4A_GPTIMER4,
+    L4A_GPTIMER5,
+    L4A_GPTIMER6,
+    L4A_GPTIMER7,
+    L4A_GPTIMER8,
+    L4A_GPTIMER9,
+    L4A_GPTIMER10,
+    L4A_GPTIMER11,
+    L4A_GPTIMER12,
+    L4A_WDTIMER2,
+    L4A_32KTIMER,
+    L4A_UART1,
+    L4A_UART2,
+    L4A_UART3,
+    L4A_DSS,
+    L4A_GPIO1,
+    L4A_GPIO2,
+    L4A_GPIO3,
+    L4A_GPIO4,
+    L4A_GPIO5,
+    L4A_GPIO6,
+    L4A_MMC1,
+    L4A_MMC2,
+    L4A_MMC3,
+    L4A_I2C1,
+    L4A_I2C2,
+    L4A_I2C3,
+    L4A_TAP
+};
+
+static struct omap_l4_agent_info_s omap3_l4_agent_info[] = {
+    /* L4-Core Target Agents */
+    {L4A_DSS,       L4ID_DSI,       6, 4},
+    /* TODO: camera */
+    /* TODO: USBHS OTG */
+    /* TODO: USBHS host */
+    /* TODO: USBTLL */
+    {L4A_UART1,     L4ID_UART1,     2, 1},
+    {L4A_UART2,     L4ID_UART2,     2, 1},
+    {L4A_I2C1,      L4ID_I2C1,      2, 1},
+    {L4A_I2C2,      L4ID_I2C2,      2, 1},
+    {L4A_I2C3,      L4ID_I2C3,      2, 1},
+    /* TODO: McBSP1 */
+    /* TODO: McBSP5 */
+    {L4A_GPTIMER10, L4ID_GPTIMER10, 2, 1},
+    {L4A_GPTIMER11, L4ID_GPTIMER11, 2, 1},
+    /* TODO: SPI1 */
+    /* TODO: SPI2 */
+    {L4A_MMC1,      L4ID_MMCSDIO1,  2, 1},
+    {L4A_MMC2,      L4ID_MMCSDIO2,  2, 1},
+    {L4A_MMC3,      L4ID_MMCSDIO3,  2, 1},
+    /* TODO: HDQ/1-Wire */
+    /* TODO: Mailbox */
+    /* TODO: SPI3 */
+    /* TODO: SPI4 */
+    /* TODO: SDMA */
+    {L4A_CM,        L4ID_CM_A,      3, 2},
+    {L4A_SCM,       L4ID_SCM,       2, 1},
+    {L4A_TAP,       L4ID_TAP,       2, 1},
+    /* L4-Wakeup Target Agents */
+    {L4A_GPTIMER12, L4ID_GPTIMER12, 2, 1},
+    {L4A_PRM,       L4ID_PRM_A,     3, 2},
+    {L4A_GPIO1,     L4ID_GPIO1,     2, 1},
+    {L4A_WDTIMER2,  L4ID_WDTIMER2,  2, 1},
+    {L4A_GPTIMER1,  L4ID_GPTIMER1,  2, 1},
+    {L4A_32KTIMER,  L4ID_32KTIMER,  2, 1},
+    /* L4-Per Target Agents */
+    {L4A_UART3,     L4ID_UART3,     2, 1},
+    /* TODO: McBSP2 */
+    /* TODO: McBSP3 */
+    {L4A_GPTIMER2,  L4ID_GPTIMER2,  2, 1},
+    {L4A_GPTIMER3,  L4ID_GPTIMER3,  2, 1},
+    {L4A_GPTIMER4,  L4ID_GPTIMER4,  2, 1},
+    {L4A_GPTIMER5,  L4ID_GPTIMER5,  2, 1},
+    {L4A_GPTIMER6,  L4ID_GPTIMER6,  2, 1},
+    {L4A_GPTIMER7,  L4ID_GPTIMER7,  2, 1},
+    {L4A_GPTIMER8,  L4ID_GPTIMER8,  2, 1},
+    {L4A_GPTIMER9,  L4ID_GPTIMER9,  2, 1},
+    {L4A_GPIO2,     L4ID_GPIO2,     2, 1},
+    {L4A_GPIO3,     L4ID_GPIO3,     2, 1},
+    {L4A_GPIO4,     L4ID_GPIO4,     2, 1},
+    {L4A_GPIO5,     L4ID_GPIO5,     2, 1},
+    {L4A_GPIO6,     L4ID_GPIO6,     2, 1},
+};
+
+static struct omap_target_agent_s *omap3_l4ta_get(struct omap_l4_s *bus, int cs)
+{
+    int i, iomemtype;
+    struct omap_target_agent_s *ta = 0;
+    struct omap_l4_agent_info_s *info = 0;
+
+    for (i = 0; i < bus->ta_num; i++)
+        if (omap3_l4_agent_info[i].ta == cs)
+        {
+            ta = &bus->ta[i];
+            info = &omap3_l4_agent_info[i];
+            break;
+        }
+    if (!ta)
+    {
+        fprintf(stderr, "%s: bad target agent (%i)\n", __FUNCTION__, cs);
+        exit(-1);
+    }
+
+    ta->bus = bus;
+    ta->start = &omap3_l4_region[info->region];
+    ta->regions = info->regions;
+
+    ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
+    ta->status = 0x00000000;
+    ta->control = 0x00000200;   /* XXX 01000200 for L4TAO */
+
+    iomemtype = l4_register_io_memory(0, omap3_l4ta_readfn,
+                                      omap3_l4ta_writefn, ta);
+    ta->base = omap_l4_attach(ta, info->ta_region, iomemtype);
+
+    return ta;
+}
+
+
+struct omap3_prm_s
+{
+    qemu_irq mpu_irq;
+    qemu_irq iva_irq;
+    struct omap_mpu_state_s *mpu;
+
+    /*IVA2_PRM Register */
+    uint32_t rm_rstctrl_iva2;    /*0x4830 6050 */
+    uint32_t rm_rstst_iva2;      /*0x4830 6058 */
+    uint32_t pm_wkdep_iva2;      /*0x4830 60C8 */
+    uint32_t pm_pwstctrl_iva2;   /*0x4830 60E0 */
+    uint32_t pm_pwstst_iva2;     /*0x4830 60E4 */
+    uint32_t pm_prepwstst_iva2;  /*0x4830 60E8 */
+    uint32_t prm_irqstatus_iva2; /*0x4830 60F8 */
+    uint32_t prm_irqenable_iva2; /*0x4830 60FC */
+
+    /*OCP_System_Reg_PRM Register */
+    uint32_t prm_revision;      /*0x4830 6804 */
+    uint32_t prm_sysconfig;     /*0x4830 6814 */
+    uint32_t prm_irqstatus_mpu; /*0x4830 6818 */
+    uint32_t prm_irqenable_mpu; /*0x4830 681c */
+
+    /*MPU_PRM Register */
+    uint32_t rm_rstst_mpu;      /*0x4830 6958 */
+    uint32_t pm_wkdep_mpu;      /*0x4830 69c8 */
+    uint32_t pm_evgenctrl_mpu;  /*0x4830 69d4 */
+    uint32_t pm_evgenontim_mpu; /*0x4830 69d8 */
+    uint32_t pm_evgenofftim_mpu;        /*0x4830 69dc */
+    uint32_t pm_pwstctrl_mpu;   /*0x4830 69e0 */
+    uint32_t pm_pwstst_mpu;     /*0x4830 69e4 */
+    uint32_t pm_perpwstst_mpu;  /*0x4830 69e8 */
+
+    /*CORE_PRM Register */
+    uint32_t rm_rstst_core;     /*0x4830 6a58 */
+    uint32_t pm_wken1_core;     /*0x4830 6aa0 */
+    uint32_t pm_mpugrpsel1_core;        /*0x4830 6aa4 */
+    uint32_t pm_iva2grpsel1_core;       /*0x4830 6aa8 */
+    uint32_t pm_wkst1_core;     /*0x4830 6ab0 */
+    uint32_t pm_wkst3_core;     /*0x4830 6ab8 */
+    uint32_t pm_pwstctrl_core;  /*0x4830 6ae0 */
+    uint32_t pm_pwstst_core;    /*0x4830 6ae4 */
+    uint32_t pm_prepwstst_core; /*0x4830 6ae8 */
+    uint32_t pm_wken3_core;     /*0x4830 6af0 */
+    uint32_t pm_iva2grpsel3_core;       /*0x4830 6af4 */
+    uint32_t pm_mpugrpsel3_core;        /*0x4830 6af8 */
+
+    /*SGX_PRM Register */
+    uint32_t rm_rstst_sgx;      /*0x4830 6b58 */
+    uint32_t pm_wkdep_sgx;      /*0x4830 6bc8 */
+    uint32_t pm_pwstctrl_sgx;   /*0x4830 6be0 */
+    uint32_t pm_pwstst_sgx;     /*0x4830 6be4 */
+    uint32_t pm_prepwstst_sgx;  /*0x4830 6be8 */
+
+    /*WKUP_PRM Register */
+    uint32_t pm_wken_wkup;      /*0x4830 6ca0 */
+    uint32_t pm_mpugrpsel_wkup; /*0x4830 6ca4 */
+    uint32_t pm_iva2grpsel_wkup;        /*0x4830 6ca8 */
+    uint32_t pm_wkst_wkup;      /*0x4830 6cb0 */
+
+    /*Clock_Control_Reg_PRM Register */
+    uint32_t prm_clksel;        /*0x4830 6D40 */
+    uint32_t prm_clkout_ctrl;   /*0x4830 6D70 */
+
+    /*DSS_PRM Register */
+    uint32_t rm_rstst_dss;      /*0x4830 6e58 */
+    uint32_t pm_wken_dss;       /*0x4830 6ea0 */
+    uint32_t pm_wkdep_dss;      /*0x4830 6ec8 */
+    uint32_t pm_pwstctrl_dss;   /*0x4830 6ee0 */
+    uint32_t pm_pwstst_dss;     /*0x4830 6ee4 */
+    uint32_t pm_prepwstst_dss;  /*0x4830 6ee8 */
+
+    /*CAM_PRM Register */
+    uint32_t rm_rstst_cam;      /*0x4830 6f58 */
+    uint32_t pm_wkdep_cam;      /*0x4830 6fc8 */
+    uint32_t pm_pwstctrl_cam;   /*0x4830 6fe0 */
+    uint32_t pm_pwstst_cam;     /*0x4830 6fe4 */
+    uint32_t pm_prepwstst_cam;  /*0x4830 6fe8 */
+
+    /*PER_PRM Register */
+    uint32_t rm_rstst_per;      /*0x4830 7058 */
+    uint32_t pm_wken_per;       /*0x4830 70a0 */
+    uint32_t pm_mpugrpsel_per;  /*0x4830 70a4 */
+    uint32_t pm_iva2grpsel_per; /*0x4830 70a8 */
+    uint32_t pm_wkst_per;       /*0x4830 70b0 */
+    uint32_t pm_wkdep_per;      /*0x4830 70c8 */
+    uint32_t pm_pwstctrl_per;   /*0x4830 70e0 */
+    uint32_t pm_pwstst_per;     /*0x4830 70e4 */
+    uint32_t pm_perpwstst_per;  /*0x4830 70e8 */
+
+    /*EMU_PRM Register */
+    uint32_t rm_rstst_emu;      /*0x4830 7158 */
+    uint32_t pm_pwstst_emu;     /*0x4830 71e4 */
+
+    /*Global_Reg_PRM Register */
+    uint32_t prm_vc_smps_sa;    /*0x4830 7220 */
+    uint32_t prm_vc_smps_vol_ra;        /*0x4830 7224 */
+    uint32_t prm_vc_smps_cmd_ra;        /*0x4830 7228 */
+    uint32_t prm_vc_cmd_val_0;  /*0x4830 722c */
+    uint32_t prm_vc_cmd_val_1;  /*0x4830 7230 */
+    uint32_t prm_vc_hc_conf;    /*0x4830 7234 */
+    uint32_t prm_vc_i2c_cfg;    /*0x4830 7238 */
+    uint32_t prm_vc_bypass_val; /*0x4830 723c */
+    uint32_t prm_rstctrl;       /*0x4830 7250 */
+    uint32_t prm_rsttimer;      /*0x4830 7254 */
+    uint32_t prm_rstst;         /*0x4830 7258 */
+    uint32_t prm_voltctrl;      /*0x4830 7260 */
+    uint32_t prm_sram_pcharge;  /*0x4830 7264 */
+    uint32_t prm_clksrc_ctrl;   /*0x4830 7270 */
+    uint32_t prm_obs;           /*0x4830 7280 */
+    uint32_t prm_voltsetup1;    /*0x4830 7290 */
+    uint32_t prm_voltoffset;    /*0x4830 7294 */
+    uint32_t prm_clksetup;      /*0x4830 7298 */
+    uint32_t prm_polctrl;       /*0x4830 729c */
+    uint32_t prm_voltsetup2;    /*0x4830 72a0 */
+
+    /*NEON_PRM Register */
+    uint32_t rm_rstst_neon;     /*0x4830 7358 */
+    uint32_t pm_wkdep_neon;     /*0x4830 73c8 */
+    uint32_t pm_pwstctrl_neon;  /*0x4830 73e0 */
+    uint32_t pm_pwstst_neon;    /*0x4830 73e4 */
+    uint32_t pm_prepwstst_neon; /*0x4830 73e8 */
+
+    /*USBHOST_PRM Register */
+    uint32_t rm_rstst_usbhost;  /*0x4830 7458 */
+    uint32_t pm_wken_usbhost;   /*0x4830 74a0 */
+    uint32_t pm_mpugrpsel_usbhost;      /*0x4830 74a4 */
+    uint32_t pm_iva2grpsel_usbhost;     /*0x4830 74a8 */
+    uint32_t pm_wkst_usbhost;   /*0x4830 74b0 */
+    uint32_t pm_wkdep_usbhost;  /*0x4830 74c8 */
+    uint32_t pm_pwstctrl_usbhost;       /*0x4830 74e0 */
+    uint32_t pm_pwstst_usbhost; /*0x4830 74e4 */
+    uint32_t pm_prepwstst_usbhost;      /*0x4830 74e8 */
+
+};
+
+static void omap3_prm_int_update(struct omap3_prm_s *s)
+{
+    qemu_set_irq(s->mpu_irq, s->prm_irqstatus_mpu & s->prm_irqenable_mpu);
+    qemu_set_irq(s->iva_irq, s->prm_irqstatus_iva2 & s->prm_irqenable_iva2);
+}
+
+static void omap3_prm_reset(struct omap3_prm_s *s)
+{
+    s->rm_rstctrl_iva2 = 0x7;
+    s->rm_rstst_iva2 = 0x1;
+    s->pm_wkdep_iva2 = 0xb3;
+    s->pm_pwstctrl_iva2 = 0xff0f07;
+    s->pm_pwstst_iva2 = 0xff7;
+    s->pm_prepwstst_iva2 = 0x0;
+    s->prm_irqstatus_iva2 = 0x0;
+    s->prm_irqenable_iva2 = 0x0;
+
+    s->prm_revision = 0x10;
+    s->prm_sysconfig = 0x1;
+    s->prm_irqstatus_mpu = 0x0;
+    s->prm_irqenable_mpu = 0x0;
+
+    s->rm_rstst_mpu = 0x1;
+    s->pm_wkdep_mpu = 0xa5;
+    s->pm_evgenctrl_mpu = 0x12;
+    s->pm_evgenontim_mpu = 0x0;
+    s->pm_evgenofftim_mpu = 0x0;
+    s->pm_pwstctrl_mpu = 0x30107;
+    s->pm_pwstst_mpu = 0xc7;
+    s->pm_pwstst_mpu = 0x0;
+
+    s->rm_rstst_core = 0x1;
+    s->pm_wken1_core = 0xc33ffe18;
+    s->pm_mpugrpsel1_core = 0xc33ffe18;
+    s->pm_iva2grpsel1_core = 0xc33ffe18;
+    s->pm_wkst1_core = 0x0;
+    s->pm_wkst3_core = 0x0;
+    s->pm_pwstctrl_core = 0xf0307;
+    s->pm_pwstst_core = 0xf7;
+    s->pm_prepwstst_core = 0x0;
+    s->pm_wken3_core = 0x4;
+    s->pm_iva2grpsel3_core = 0x4;
+    s->pm_mpugrpsel3_core = 0x4;
+
+    s->rm_rstst_sgx = 0x1;
+    s->pm_wkdep_sgx = 0x16;
+    s->pm_pwstctrl_sgx = 0x30107;
+    s->pm_pwstst_sgx = 0x3;
+    s->pm_prepwstst_sgx = 0x0;
+
+    s->pm_wken_wkup = 0x3cb;
+    s->pm_mpugrpsel_wkup = 0x3cb;
+    s->pm_iva2grpsel_wkup = 0x0;
+    s->pm_wkst_wkup = 0x0;
+
+    s->prm_clksel = 0x4;
+    s->prm_clkout_ctrl = 0x80;
+
+    s->rm_rstst_dss = 0x1;
+    s->pm_wken_dss = 0x1;
+    s->pm_wkdep_dss = 0x16;
+    s->pm_pwstctrl_dss = 0x30107;
+    s->pm_pwstst_dss = 0x3;
+    s->pm_prepwstst_dss = 0x0;
+
+    s->rm_rstst_cam = 0x1;
+    s->pm_wkdep_cam = 0x16;
+    s->pm_pwstctrl_cam = 0x30107;
+    s->pm_pwstst_cam = 0x3;
+    s->pm_prepwstst_cam = 0x0;
+
+    s->rm_rstst_per = 0x1;
+    s->pm_wken_per = 0x3efff;
+    s->pm_mpugrpsel_per = 0x3efff;
+    s->pm_iva2grpsel_per = 0x3efff;
+    s->pm_wkst_per = 0x0;
+    s->pm_wkdep_per = 0x17;
+    s->pm_pwstctrl_per = 0x30107;
+    s->pm_pwstst_per = 0x7;
+    s->pm_perpwstst_per = 0x0;
+
+    s->rm_rstst_emu = 0x1;
+    s->pm_pwstst_emu = 0x13;
+
+    s->prm_vc_smps_sa = 0x0;
+    s->prm_vc_smps_vol_ra = 0x0;
+    s->prm_vc_smps_cmd_ra = 0x0;
+    s->prm_vc_cmd_val_0 = 0x0;
+    s->prm_vc_cmd_val_1 = 0x0;
+    s->prm_vc_hc_conf = 0x0;
+    s->prm_vc_i2c_cfg = 0x18;
+    s->prm_vc_bypass_val = 0x0;
+    s->prm_rstctrl = 0x0;
+    s->prm_rsttimer = 0x1006;
+    s->prm_rstst = 0x1;
+    s->prm_voltctrl = 0x0;
+    s->prm_sram_pcharge = 0x50;
+    s->prm_clksrc_ctrl = 0x43;
+    s->prm_obs = 0x0;
+    s->prm_voltsetup1 = 0x0;
+    s->prm_voltoffset = 0x0;
+    s->prm_clksetup = 0x0;
+    s->prm_polctrl = 0xa;
+    s->prm_voltsetup2 = 0x0;
+
+    s->rm_rstst_neon = 0x1;
+    s->pm_wkdep_neon = 0x2;
+    s->pm_pwstctrl_neon = 0x7;
+    s->pm_pwstst_neon = 0x3;
+    s->pm_prepwstst_neon = 0x0;
+
+    s->rm_rstst_usbhost = 0x1;
+    s->pm_wken_usbhost = 0x1;
+    s->pm_mpugrpsel_usbhost = 0x1;
+    s->pm_iva2grpsel_usbhost = 0x1;
+    s->pm_wkst_usbhost = 0x0;
+    s->pm_wkdep_usbhost = 0x17;
+    s->pm_pwstctrl_usbhost = 0x30107;
+    s->pm_pwstst_usbhost = 0x3;
+    s->pm_prepwstst_usbhost = 0x0;
+
+    omap3_prm_int_update(s);
+}
+
+static uint32_t omap3_prm_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap3_prm_s *s = (struct omap3_prm_s *)opaque;
+
+    TRACE("%04x", addr);
+    switch (addr) {
+        /* IVA2_PRM */
+        case 0x0050: return s->rm_rstctrl_iva2;
+        case 0x0058: return s->rm_rstst_iva2;
+        case 0x00c8: return s->pm_wkdep_iva2;
+        case 0x00e0: return s->pm_pwstctrl_iva2;
+        case 0x00e4: return s->pm_pwstst_iva2;
+        case 0x00e8: return s->pm_prepwstst_iva2;
+        case 0x00f8: return s->prm_irqstatus_iva2;
+        case 0x00fc: return s->prm_irqenable_iva2;
+        /* OCP_System_Reg_PRM */
+        case 0x0804: return s->prm_revision;
+        case 0x0814: return s->prm_sysconfig;
+        case 0x0818: return s->prm_irqstatus_mpu;
+        case 0x081c: return s->prm_irqenable_mpu;
+        /* MPU_PRM */
+        case 0x0958: return s->rm_rstst_mpu;
+        case 0x09c8: return s->pm_wkdep_mpu;
+        case 0x09d4: return s->pm_evgenctrl_mpu;
+        case 0x09d8: return s->pm_evgenontim_mpu;
+        case 0x09dc: return s->pm_evgenofftim_mpu;
+        case 0x09e0: return s->pm_pwstctrl_mpu;
+        case 0x09e4: return s->pm_pwstst_mpu;
+        case 0x09e8: return s->pm_perpwstst_mpu;
+        /* CORE_PRM */
+        case 0x0a58: return s->rm_rstst_core;
+        case 0x0aa0: return s->pm_wken1_core;
+        case 0x0aa4: return s->pm_mpugrpsel1_core;
+        case 0x0aa8: return s->pm_iva2grpsel1_core;
+        case 0x0ab0: return s->pm_wkst1_core;
+        case 0x0ab8: return s->pm_wkst3_core;
+        case 0x0ae0: return s->pm_pwstctrl_core;
+        case 0x0ae4: return s->pm_pwstst_core;
+        case 0x0ae8: return s->pm_prepwstst_core;
+        case 0x0af0: return s->pm_wken3_core;
+        case 0x0af4: return s->pm_iva2grpsel3_core;
+        case 0x0af8: return s->pm_mpugrpsel3_core;
+        /* SGX_PRM */
+        case 0x0b58: return s->rm_rstst_sgx;
+        case 0x0bc8: return s->pm_wkdep_sgx;
+        case 0x0be0: return s->pm_pwstctrl_sgx;
+        case 0x0be4: return s->pm_pwstst_sgx;
+        case 0x0be8: return s->pm_prepwstst_sgx;
+       /* WKUP_PRM */
+        case 0x0ca0: return s->pm_wken_wkup;
+        case 0x0ca4: return s->pm_mpugrpsel_wkup;
+        case 0x0ca8: return s->pm_iva2grpsel_wkup;
+        case 0x0cb0: return s->pm_wkst_wkup;
+        //case 0x0ce4: return 0x3; /* power on */
+       /* Clock_Control_Reg_PRM */
+        case 0x0d40: return s->prm_clksel;
+        case 0x0d70: return s->prm_clkout_ctrl;
+        //case 0x0de4: return 0x3; /* power on */
+        /* DSS_PRM */
+        case 0x0e58: return s->rm_rstst_dss;
+        case 0x0ea0: return s->pm_wken_dss;
+        case 0x0ec8: return s->pm_wkdep_dss;
+        case 0x0ee0: return s->pm_pwstctrl_dss;
+        case 0x0ee4: return s->pm_pwstst_dss;
+        case 0x0ee8: return s->pm_prepwstst_dss;
+        /* CAM_PRM */
+        case 0x0f58: return s->rm_rstst_cam;
+        case 0x0fc8: return s->pm_wkdep_cam;
+        case 0x0fe0: return s->pm_pwstctrl_cam;
+        case 0x0fe4: return s->pm_pwstst_cam;
+        case 0x0fe8: return s->pm_prepwstst_cam;
+        /* PER_PRM */
+        case 0x1058: return s->rm_rstst_per;
+        case 0x10a0: return s->pm_wken_per;
+        case 0x10a4: return s->pm_mpugrpsel_per;
+        case 0x10a8: return s->pm_iva2grpsel_per;
+        case 0x10b0: return s->pm_wkst_per;
+        case 0x10c8: return s->pm_wkdep_per;
+        case 0x10e0: return s->pm_pwstctrl_per;
+        case 0x10e4: return s->pm_pwstst_per;
+        case 0x10e8: return s->pm_perpwstst_per;
+        /* EMU_PRM */
+        case 0x1158: return s->rm_rstst_emu;
+        case 0x11e4: return s->pm_pwstst_emu;
+        /* Global_Reg_PRM */
+        case 0x1220: return s->prm_vc_smps_sa;
+        case 0x1224: return s->prm_vc_smps_vol_ra;
+        case 0x1228: return s->prm_vc_smps_cmd_ra;
+        case 0x122c: return s->prm_vc_cmd_val_0;
+        case 0x1230: return s->prm_vc_cmd_val_1;
+        case 0x1234: return s->prm_vc_hc_conf;
+        case 0x1238: return s->prm_vc_i2c_cfg;
+        case 0x123c: return s->prm_vc_bypass_val;
+        case 0x1250: return s->prm_rstctrl;
+        case 0x1254: return s->prm_rsttimer;
+        case 0x1258: return s->prm_rstst;
+        case 0x1260: return s->prm_voltctrl;
+        case 0x1264: return s->prm_sram_pcharge;       
+        case 0x1270: return s->prm_clksrc_ctrl;
+        case 0x1280: return s->prm_obs;
+        case 0x1290: return s->prm_voltsetup1;
+        case 0x1294: return s->prm_voltoffset;
+        case 0x1298: return s->prm_clksetup;
+        case 0x129c: return s->prm_polctrl;
+        case 0x12a0: return s->prm_voltsetup2;
+        /* NEON_PRM */
+        case 0x1358: return s->rm_rstst_neon;
+        case 0x13c8: return s->pm_wkdep_neon;
+        case 0x13e0: return s->pm_pwstctrl_neon;
+        case 0x13e4: return s->pm_pwstst_neon;
+        case 0x13e8: return s->pm_prepwstst_neon;
+        /* USBHOST_PRM */
+        case 0x1458: return s->rm_rstst_usbhost;
+        case 0x14a0: return s->pm_wken_usbhost;
+        case 0x14a4: return s->pm_mpugrpsel_usbhost;
+        case 0x14a8: return s->pm_iva2grpsel_usbhost;
+        case 0x14b0: return s->pm_wkst_usbhost;
+        case 0x14c8: return s->pm_wkdep_usbhost;
+        case 0x14e0: return s->pm_pwstctrl_usbhost;
+        case 0x14e4: return s->pm_pwstst_usbhost;
+        case 0x14e8: return s->pm_prepwstst_usbhost;
+        default:
+            OMAP_BAD_REG(addr);
+            return 0;
+    }
+}
+
+static inline void omap3_prm_clksrc_ctrl_update(struct omap3_prm_s *s,
+                                                uint32_t value)
+{
+    if ((value & 0xd0) == 0x40)
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_sys_clk"), 1, 1);
+    else if ((value & 0xd0) == 0x80)
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_sys_clk"), 2, 1);
+}
+
+static void omap3_prm_write(void *opaque, target_phys_addr_t addr,
+                            uint32_t value)
+{
+    struct omap3_prm_s *s = (struct omap3_prm_s *)opaque;
+
+    TRACE("%04x = %08x", addr, value);
+    switch (addr) {
+        /* IVA2_PRM */
+        case 0x0050: s->rm_rstctrl_iva2 = value & 0x7; break;
+        case 0x0058: s->rm_rstst_iva2 &= ~(value & 0x3f0f); break;
+        case 0x00c8: s->pm_wkdep_iva2 = value & 0xb3; break;
+        case 0x00e0: s->pm_pwstctrl_iva2 = 0xcff000 | (value & 0x300f0f); break;
+        case 0x00e4: OMAP_RO_REG(addr); break;
+        case 0x00e8: s->pm_prepwstst_iva2 = value & 0xff7;
+        case 0x00f8:
+            s->prm_irqstatus_iva2 &= ~(value & 0x7);
+            omap3_prm_int_update(s);
+            break;
+        case 0x00fc:
+            s->prm_irqenable_iva2 = value & 0x7;
+            omap3_prm_int_update(s);
+            break;
+        /* OCP_System_Reg_PRM */
+        case 0x0804: OMAP_RO_REG(addr); break;
+        case 0x0814: s->prm_sysconfig = value & 0x1; break;
+        case 0x0818:
+            s->prm_irqstatus_mpu &= ~(value & 0x03c003fd);
+            omap3_prm_int_update(s);
+            break;
+        case 0x081c:
+            s->prm_irqenable_mpu = value & 0x03c003fd;
+            omap3_prm_int_update(s);
+            break;
+        /* MPU_PRM */
+        case 0x0958: s->rm_rstst_mpu &= ~(value & 0x080f); break;
+        case 0x09c8: s->pm_wkdep_mpu = value & 0xa5; break;
+        case 0x09d4: s->pm_evgenctrl_mpu = value & 0x1f; break;
+        case 0x09d8: s->pm_evgenontim_mpu = value; break;
+        case 0x09dc: s->pm_evgenofftim_mpu = value; break;
+        case 0x09e0: s->pm_pwstctrl_mpu = value & 0x3010f; break;
+        case 0x09e4: OMAP_RO_REG(addr); break;
+        case 0x09e8: s->pm_perpwstst_mpu = value & 0xc7; break;
+        /* CORE_PRM */
+        case 0x0a58: s->rm_rstst_core &= ~(value & 0x7); break;
+        case 0x0aa0: s->pm_wken1_core = 0x80000008 | (value & 0x433ffe10); break;
+        case 0x0aa4: s->pm_mpugrpsel1_core = 0x80000008 | (value & 0x433ffe10); break;
+        case 0x0aa8: s->pm_iva2grpsel1_core = 0x80000008 | (value & 0x433ffe10); break;
+        case 0x0ab0: s->pm_wkst1_core = value & 0x433ffe10; break;
+        case 0x0ab8: s->pm_wkst3_core &= ~(value & 0x4); break;
+        case 0x0ae0: s->pm_pwstctrl_core = (value & 0x0f031f); break;
+        case 0x0ae4: OMAP_RO_REG(addr); break;
+        case 0x0ae8: s->pm_prepwstst_core = value & 0xf7; break;
+        case 0x0af0: s->pm_wken3_core = value & 0x4; break;
+        case 0x0af4: s->pm_iva2grpsel3_core = value & 0x4; break;
+        case 0x0af8: s->pm_mpugrpsel3_core = value & 0x4; break;
+        /* SGX_PRM */
+        case 0x0b58: s->rm_rstst_sgx &= ~(value & 0xf); break;
+        case 0x0bc8: s->pm_wkdep_sgx = value & 0x16; break;
+        case 0x0be0: s->pm_pwstctrl_sgx = 0x030104 | (value & 0x3); break;
+        case 0x0be4: OMAP_RO_REG(addr); break;
+        case 0x0be8: s->pm_prepwstst_sgx = value & 0x3; break;
+        /* WKUP_PRM */
+        case 0x0ca0: s->pm_wken_wkup = 0x2 | (value & 0x0103c9); break;
+        case 0x0ca4: s->pm_mpugrpsel_wkup = 0x0102 | (value & 0x02c9); break;
+        case 0x0ca8: s->pm_iva2grpsel_wkup = value & 0x03cb; break;
+        case 0x0cb0: s->pm_wkst_wkup &= ~(value & 0x0103cb); break;
+        /* Clock_Control_Reg_PRM */
+        case 0x0d40: 
+            s->prm_clksel = value & 0x7;
+            fprintf(stderr, "%s PRM_CLKSEL = 0x%x\n", __FUNCTION__,
+                    s->prm_clksel);
+            /* TODO: update clocks */
+            break;
+        case 0x0d70:
+            s->prm_clkout_ctrl = value & 0x80;
+            fprintf(stderr, "%s PRM_CLKOUT_CTRL = 0x%x\n", __FUNCTION__,
+                    s->prm_clkout_ctrl);
+            /* TODO: update clocks */
+            break;
+        /* DSS_PRM */
+        case 0x0e58: s->rm_rstst_dss &= ~(value & 0xf); break;
+        case 0x0ea0: s->pm_wken_dss = value & 1; break;
+        case 0x0ec8: s->pm_wkdep_dss = value & 0x16; break;
+        case 0x0ee0: s->pm_pwstctrl_dss = 0x030104 | (value & 3); break;
+        case 0x0ee4: OMAP_RO_REG(addr); break;
+        case 0x0ee8: s->pm_prepwstst_dss = value & 3; break;
+        /* CAM_PRM */
+        case 0x0f58: s->rm_rstst_cam &= (value & 0xf); break;
+        case 0x0fc8: s->pm_wkdep_cam = value & 0x16; break;
+        case 0x0fe0: s->pm_pwstctrl_cam = 0x030104 | (value & 3); break;
+        case 0x0fe4: OMAP_RO_REG(addr); break;
+        case 0x0fe8: s->pm_prepwstst_cam = value & 0x3; break;
+        /* PER_PRM */
+        case 0x1058: s->rm_rstst_per &= ~(value & 0xf); break;
+        case 0x10a0: s->pm_wken_per = value & 0x03efff; break;
+        case 0x10a4: s->pm_mpugrpsel_per = value & 0x03efff; break;
+        case 0x10a8: s->pm_iva2grpsel_per = value & 0x03efff; break;
+        case 0x10b0: s->pm_wkst_per &= ~(value & 0x03efff); break;
+        case 0x10c8: s->pm_wkdep_per = value & 0x17; break;
+        case 0x10e0: s->pm_pwstctrl_per = 0x030100 | (value & 7); break;
+        case 0x10e4: OMAP_RO_REG(addr); break;
+        case 0x10e8: s->pm_perpwstst_per = value & 0x7; break;
+        /* EMU_PRM */
+        case 0x1158: s->rm_rstst_emu &= ~(value & 7); break;
+        case 0x11e4: OMAP_RO_REG(addr); break;
+        /* Global_Reg_PRM */
+        case 0x1220: s->prm_vc_smps_sa = value & 0x7f007f; break;
+        case 0x1224: s->prm_vc_smps_vol_ra = value & 0xff00ff; break;
+        case 0x1228: s->prm_vc_smps_cmd_ra = value & 0xff00ff; break;
+        case 0x122c: s->prm_vc_cmd_val_0 = value; break;
+        case 0x1230: s->prm_vc_cmd_val_1 = value; break;
+        case 0x1234: s->prm_vc_hc_conf = value & 0x1f001f; break;
+        case 0x1238: s->prm_vc_i2c_cfg = value & 0x3f; break;
+        case 0x123c: s->prm_vc_bypass_val = value & 0x01ffff7f; break;
+        case 0x1250: s->prm_rstctrl = 0; break; /* TODO: resets */
+        case 0x1254: s->prm_rsttimer = value & 0x1fff; break;
+        case 0x1258: s->prm_rstst &= ~(value & 0x7fb); break;
+        case 0x1260: s->prm_voltctrl = value & 0x1f; break;
+        case 0x1264: s->prm_sram_pcharge = value & 0xff; break;
+        case 0x1270:
+            s->prm_clksrc_ctrl = value & (0xd8);
+            omap3_prm_clksrc_ctrl_update(s, s->prm_clksrc_ctrl);
+            /* TODO: update SYSCLKSEL bits */
+            break;
+        case 0x1280: OMAP_RO_REG(addr); break;
+        case 0x1290: s->prm_voltsetup1 = value; break;
+        case 0x1294: s->prm_voltoffset = value & 0xffff; break;
+        case 0x1298: s->prm_clksetup = value & 0xffff; break;
+        case 0x129c: s->prm_polctrl = value & 0xf; break;
+        case 0x12a0: s->prm_voltsetup2 = value & 0xffff; break;
+        /* NEON_PRM */
+        case 0x1358: s->rm_rstst_neon &= ~(value & 0xf); break;
+        case 0x13c8: s->pm_wkdep_neon = value & 0x2; break;
+        case 0x13e0: s->pm_pwstctrl_neon = 0x4 | (value & 3); break;
+        case 0x13e4: OMAP_RO_REG(addr); break;
+        case 0x13e8: s->pm_prepwstst_neon = value & 3; break;
+        /* USBHOST_PRM */
+        case 0x1458: s->rm_rstst_usbhost &= ~(value & 0xf); break;
+        case 0x14a0: s->pm_wken_usbhost = value & 1; break;
+        case 0x14a4: s->pm_mpugrpsel_usbhost = value & 1; break;
+        case 0x14a8: s->pm_iva2grpsel_usbhost = value & 1; break;
+        case 0x14b0: s->pm_wkst_usbhost &= ~(value & 1); break;
+        case 0x14c8: s->pm_wkdep_usbhost = value & 0x17; break;
+        case 0x14e0: s->pm_pwstctrl_usbhost = 0x030104 | (value & 0x13); break;
+        case 0x14e4: OMAP_RO_REG(addr); break;
+        case 0x14e8: s->pm_prepwstst_usbhost = value & 3; break;
+        default:
+            OMAP_BAD_REGV(addr, value);
+            break;
+    }
+}
+
+static CPUReadMemoryFunc *omap3_prm_readfn[] = {
+    omap_badwidth_read32,
+    omap_badwidth_read32,
+    omap3_prm_read,
+};
+
+static CPUWriteMemoryFunc *omap3_prm_writefn[] = {
+    omap_badwidth_write32,
+    omap_badwidth_write32,
+    omap3_prm_write,
+};
+
+struct omap3_prm_s *omap3_prm_init(struct omap_target_agent_s *ta,
+                                   qemu_irq mpu_int, qemu_irq iva_int,
+                                   struct omap_mpu_state_s *mpu)
+{
+    int iomemtype;
+    struct omap3_prm_s *s = (struct omap3_prm_s *) qemu_mallocz(sizeof(*s));
+
+    s->mpu_irq = mpu_int;
+    s->iva_irq = iva_int;
+    s->mpu = mpu;
+    omap3_prm_reset(s);
+
+    iomemtype = l4_register_io_memory(0, omap3_prm_readfn,
+                                      omap3_prm_writefn, s);
+    omap_l4_attach(ta, 0, iomemtype);
+    omap_l4_attach(ta, 1, iomemtype);
+
+    return s;
+}
+
+
+struct omap3_cm_s
+{
+    qemu_irq irq[3];
+    struct omap_mpu_state_s *mpu;
+
+    /*IVA2_CM Register */
+    uint32_t cm_fclken_iva2;    /*0x4800 4000 */
+    uint32_t cm_clken_pll_iva2; /*0x4800 4004 */
+    uint32_t cm_idlest_iva2;    /*0x4800 4020 */
+    uint32_t cm_idlest_pll_iva2;        /*0x4800 4024 */
+    uint32_t cm_autoidle_pll_iva2;      /*0x4800 4034 */
+    uint32_t cm_clksel1_pll_iva2;       /*0x4800 4040 */
+    uint32_t cm_clksel2_pll_iva2;       /*0x4800 4044 */
+    uint32_t cm_clkstctrl_iva2; /*0x4800 4048 */
+    uint32_t cm_clkstst_iva2;   /*0x4800 404c */
+
+    /*OCP_System_Reg_CM */
+    uint32_t cm_revision;       /*0x4800 4800 */
+    uint32_t cm_sysconfig;      /*0x4800 4810 */
+
+    /*MPU_CM Register */
+    uint32_t cm_clken_pll_mpu;  /*0x4800 4904 */
+    uint32_t cm_idlest_mpu;     /*0x4800 4920 */
+    uint32_t cm_idlest_pll_mpu; /*0x4800 4924 */
+    uint32_t cm_autoidle_pll_mpu;       /*0x4800 4934 */
+    uint32_t cm_clksel1_pll_mpu;        /*0x4800 4940 */
+    uint32_t cm_clksel2_pll_mpu;        /*0x4800 4944 */
+    uint32_t cm_clkstctrl_mpu;  /*0x4800 4948 */
+    uint32_t cm_clkstst_mpu;    /*0x4800 494c */
+
+    /*CORE_CM Register */
+    uint32_t cm_fclken1_core;   /*0x4800 4a00 */
+    uint32_t cm_fclken3_core;   /*0x4800 4a08 */
+    uint32_t cm_iclken1_core;   /*0x4800 4a10 */
+    uint32_t cm_iclken2_core;   /*0x4800 4a14 */
+    uint32_t cm_iclken3_core;   /*0x4800 4a18 */
+    uint32_t cm_idlest1_core;   /*0x4800 4a20 */
+    uint32_t cm_idlest2_core;   /*0x4800 4a24 */
+    uint32_t cm_idlest3_core;   /*0x4800 4a28 */
+    uint32_t cm_autoidle1_core; /*0x4800 4a30 */
+    uint32_t cm_autoidle2_core; /*0x4800 4a34 */
+    uint32_t cm_autoidle3_core; /*0x4800 4a38 */
+    uint32_t cm_clksel_core;    /*0x4800 4a40 */
+    uint32_t cm_clkstctrl_core; /*0x4800 4a48 */
+    uint32_t cm_clkstst_core;   /*0x4800 4a4c */
+
+    /*SGX_CM Register */
+    uint32_t cm_fclken_sgx;     /*0x4800 4b00 */
+    uint32_t cm_iclken_sgx;     /*0x4800 4b10 */
+    uint32_t cm_idlest_sgx;     /*0x4800 4b20 */
+    uint32_t cm_clksel_sgx;     /*0x4800 4b40 */
+    uint32_t cm_sleepdep_sgx;   /*0x4800 4b44 */
+    uint32_t cm_clkstctrl_sgx;  /*0x4800 4b48 */
+    uint32_t cm_clkstst_sgx;    /*0x4800 4b4c */
+
+    /*WKUP_CM Register */
+    uint32_t cm_fclken_wkup;    /*0x4800 4c00 */
+    uint32_t cm_iclken_wkup;    /*0x4800 4c10 */
+    uint32_t cm_idlest_wkup;    /*0x4800 4c20 */
+    uint32_t cm_autoidle_wkup;  /*0x4800 4c30 */
+    uint32_t cm_clksel_wkup;    /*0x4800 4c40 */
+    uint32_t cm_c48;                  /*0x4800 4c48 */
+
+    /*Clock_Control_Reg_CM Register */
+    uint32_t cm_clken_pll;      /*0x4800 4d00 */
+    uint32_t cm_clken2_pll;     /*0x4800 4d04 */
+    uint32_t cm_idlest_ckgen;   /*0x4800 4d20 */
+    uint32_t cm_idlest2_ckgen;  /*0x4800 4d24 */
+    uint32_t cm_autoidle_pll;   /*0x4800 4d30 */
+    uint32_t cm_autoidle2_pll;  /*0x4800 4d34 */
+    uint32_t cm_clksel1_pll;    /*0x4800 4d40 */
+    uint32_t cm_clksel2_pll;    /*0x4800 4d44 */
+    uint32_t cm_clksel3_pll;    /*0x4800 4d48 */
+    uint32_t cm_clksel4_pll;    /*0x4800 4d4c */
+    uint32_t cm_clksel5_pll;    /*0x4800 4d50 */
+    uint32_t cm_clkout_ctrl;    /*0x4800 4d70 */
+
+    /*DSS_CM Register */
+    uint32_t cm_fclken_dss;     /*0x4800 4e00 */
+    uint32_t cm_iclken_dss;     /*0x4800 4e10 */
+    uint32_t cm_idlest_dss;     /*0x4800 4e20 */
+    uint32_t cm_autoidle_dss;   /*0x4800 4e30 */
+    uint32_t cm_clksel_dss;     /*0x4800 4e40 */
+    uint32_t cm_sleepdep_dss;   /*0x4800 4e44 */
+    uint32_t cm_clkstctrl_dss;  /*0x4800 4e48 */
+    uint32_t cm_clkstst_dss;    /*0x4800 4e4c */
+
+
+    /*CAM_CM Register */
+    uint32_t cm_fclken_cam;     /*0x4800 4f00 */
+    uint32_t cm_iclken_cam;     /*0x4800 4f10 */
+    uint32_t cm_idlest_cam;     /*0x4800 4f20 */
+    uint32_t cm_autoidle_cam;   /*0x4800 4f30 */
+    uint32_t cm_clksel_cam;     /*0x4800 4f40 */
+    uint32_t cm_sleepdep_cam;   /*0x4800 4f44 */
+    uint32_t cm_clkstctrl_cam;  /*0x4800 4f48 */
+    uint32_t cm_clkstst_cam;    /*0x4800 4f4c */
+
+    /*PER_CM Register */
+    uint32_t cm_fclken_per;     /*0x4800 5000 */
+    uint32_t cm_iclken_per;     /*0x4800 5010 */
+    uint32_t cm_idlest_per;     /*0x4800 5020 */
+    uint32_t cm_autoidle_per;   /*0x4800 5030 */
+    uint32_t cm_clksel_per;     /*0x4800 5040 */
+    uint32_t cm_sleepdep_per;   /*0x4800 5044 */
+    uint32_t cm_clkstctrl_per;  /*0x4800 5048 */
+    uint32_t cm_clkstst_per;    /*0x4800 504c */
+
+    /*EMU_CM Register */
+    uint32_t cm_clksel1_emu;    /*0x4800 5140 */
+    uint32_t cm_clkstctrl_emu;  /*0x4800 5148 */
+    uint32_t cm_clkstst_emu;    /*0x4800 514c */
+    uint32_t cm_clksel2_emu;    /*0x4800 5150 */
+    uint32_t cm_clksel3_emu;    /*0x4800 5154 */
+
+    /*Global_Reg_CM Register */
+    uint32_t cm_polctrl;        /*0x4800 529c */
+
+    /*NEON_CM Register */
+    uint32_t cm_idlest_neon;    /*0x4800 5320 */
+    uint32_t cm_clkstctrl_neon; /*0x4800 5348 */
+
+    /*USBHOST_CM Register */
+    uint32_t cm_fclken_usbhost; /*0x4800 5400 */
+    uint32_t cm_iclken_usbhost; /*0x4800 5410 */
+    uint32_t cm_idlest_usbhost; /*0x4800 5420 */
+    uint32_t cm_autoidle_usbhost;       /*0x4800 5430 */
+    uint32_t cm_sleepdep_usbhost;       /*0x4800 5444 */
+    uint32_t cm_clkstctrl_usbhost;      /*0x4800 5448 */
+    uint32_t cm_clkstst_usbhost;        /*0x4800 544c */
+
+};
+
+/*
+static inline void omap3_cm_fclken_wkup_update(struct omap3_cm_s *s,
+                uint32_t value)
+{
+       
+       if (value & 0x28)
+       omap_clk_onoff(omap_findclk(s->mpu,"omap3_wkup_32k_fclk"), 1);
+    else
+       omap_clk_onoff(omap_findclk(s->mpu,"omap3_wkup_32k_fclk"), 0);
+
+    if (value &0x1)
+       omap_clk_onoff(omap_findclk(s->mpu,"omap3_gp1_fclk"), 1);
+    else
+       omap_clk_onoff(omap_findclk(s->mpu,"omap3_gp1_fclk"), 0);
+
+}
+static inline void omap3_cm_iclken_wkup_update(struct omap3_cm_s *s,
+                uint32_t value)
+{
+       
+       if (value & 0x3f)
+       omap_clk_onoff(omap_findclk(s->mpu,"omap3_wkup_l4_iclk"), 1);
+    else
+       omap_clk_onoff(omap_findclk(s->mpu,"omap3_wkup_l4_iclk"), 0);
+
+}
+*/
+static inline void omap3_cm_clksel_wkup_update(struct omap3_cm_s *s,
+                                               uint32_t value)
+{
+    omap_clk gp1_fclk = omap_findclk(s->mpu, "omap3_gp1_fclk");
+
+    if (value & 0x1)
+        omap_clk_reparent(gp1_fclk, omap_findclk(s->mpu, "omap3_sys_clk"));
+    else
+        omap_clk_reparent(gp1_fclk, omap_findclk(s->mpu, "omap3_32k_fclk"));
+    /*Tell GPTIMER to generate new clk rate */
+    omap_gp_timer_change_clk(s->mpu->gptimer[0]);
+
+    TRACE("omap3_gp1_fclk %lld",
+          omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp1_fclk")));
+
+    /*TODO:CM_USIM_CLK CLKSEL_RM */
+}
+
+static inline void omap3_cm_mpu_update(struct omap3_cm_s *s)
+{
+    uint32_t m, n, divide, m2, cm_clken_pll_mpu;
+    uint32_t bypass = 1;
+
+    cm_clken_pll_mpu = s->cm_clken_pll_mpu;
+    omap_clk mpu_clk = omap_findclk(s->mpu, "omap3_mpu_clk");
+
+    if ((cm_clken_pll_mpu & 0x7) == 0x5)
+    {
+        bypass = 1;
+    }
+    else if ((cm_clken_pll_mpu & 0x7) == 0x7)
+    {
+        m = (s->cm_clksel1_pll_mpu & 0x7ff00) >> 8;
+        if ((m == 0) || (m == 1))
+            bypass = 1;
+        else
+            bypass = 0;
+    }
+    if (bypass == 1)
+    {
+        /*BYPASS Model */
+        divide = (s->cm_clksel1_pll_mpu & 0x380000) >> 19;
+        //OMAP3_DEBUG(("divide %d\n",divide));
+        omap_clk_reparent(mpu_clk, omap_findclk(s->mpu, "omap3_core_clk"));
+        omap_clk_setrate(mpu_clk, divide, 1);
+
+    }
+    else
+    {
+        n = (s->cm_clksel1_pll_mpu & 0x7F);
+        m2 = (s->cm_clksel2_pll_mpu & 0x1F);
+        //OMAP3_DEBUG(("M  %d N %d M2 %d \n",m,n,m2 ));
+        omap_clk_reparent(mpu_clk, omap_findclk(s->mpu, "omap3_sys_clk"));
+        omap_clk_setrate(mpu_clk, (n + 1) * m2, m);
+        //OMAP3_DEBUG(("mpu %d \n",omap_clk_getrate(mpu_clk)));
+
+    }
+
+}
+static inline void omap3_cm_iva2_update(struct omap3_cm_s *s)
+{
+    uint32_t m, n, divide, m2, cm_clken_pll_iva2;
+    uint32_t bypass = 1;
+
+    cm_clken_pll_iva2 = s->cm_clken_pll_iva2;
+    omap_clk iva2_clk = omap_findclk(s->mpu, "omap3_iva2_clk");
+
+    if (((cm_clken_pll_iva2 & 0x7) == 0x5)
+        || ((cm_clken_pll_iva2 & 0x7) == 0x1))
+    {
+        bypass = 1;
+    }
+    else if ((cm_clken_pll_iva2 & 0x7) == 0x7)
+    {
+        m = (s->cm_clksel1_pll_iva2 & 0x7ff00) >> 8;
+        if ((m == 0) || (m == 1))
+            bypass = 1;
+        else
+            bypass = 0;
+    }
+    if (bypass == 1)
+    {
+        /*BYPASS Model */
+        divide = (s->cm_clksel1_pll_iva2 & 0x380000) >> 19;
+        //OMAP3_DEBUG(("divide %d\n",divide));
+        omap_clk_reparent(iva2_clk, omap_findclk(s->mpu, "omap3_core_clk"));
+        omap_clk_setrate(iva2_clk, divide, 1);
+
+    }
+    else
+    {
+        n = (s->cm_clksel1_pll_iva2 & 0x7F);
+        m2 = (s->cm_clksel2_pll_iva2 & 0x1F);
+        //OMAP3_DEBUG(("M  %d N %d M2 %d \n",m,n,m2 ));
+        omap_clk_reparent(iva2_clk, omap_findclk(s->mpu, "omap3_sys_clk"));
+        omap_clk_setrate(iva2_clk, (n + 1) * m2, m);
+        //OMAP3_DEBUG(("iva2_clk %d \n",omap_clk_getrate(iva2_clk)));
+
+    }
+
+}
+
+static inline void omap3_cm_dpll3_update(struct omap3_cm_s *s)
+{
+    uint32_t m, n, m2, m3, cm_clken_pll;
+    uint32_t bypass = 1;
+
+    cm_clken_pll = s->cm_clken_pll;
+
+    /*dpll3 bypass mode. parent clock is always omap3_sys_clk */
+    if (((cm_clken_pll & 0x7) == 0x5) || ((cm_clken_pll & 0x7) == 0x6))
+    {
+        bypass = 1;
+    }
+    else if ((cm_clken_pll & 0x7) == 0x7)
+    {
+        m = (s->cm_clksel1_pll & 0x7ff0000) >> 16;
+        if ((m == 0) || (m == 1))
+            bypass = 1;
+        else
+            bypass = 0;
+    }
+    if (bypass == 1)
+    {
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_core_clk"), 1, 1);
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_core2_clk"), 1, 1);
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_emu_core_alwon_clk"), 1,
+                         1);
+    }
+    else
+    {
+        n = (s->cm_clksel1_pll & 0x3f00) >> 8;
+        m2 = (s->cm_clksel1_pll & 0xf8000000) >> 27;
+        m3 = (s->cm_clksel1_emu & 0x1f0000) >> 16;
+
+        if (s->cm_clksel2_emu&0x80000)
+        {
+               /*override control of DPLL3*/
+               m = (s->cm_clksel2_emu&0x7ff)>>8;
+               n =  s->cm_clksel2_emu&0x7f;
+               TRACE("DPLL3 override, m 0x%x n 0x%x",m,n);
+        }
+
+        //OMAP3_DEBUG(("dpll3 cm_clksel1_pll %x m  %d n %d m2 %d  m3 %d\n",s->cm_clksel1_pll,m,n,m2,m3 ));
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_core_clk"), (n + 1) * m2,
+                         m);
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_core2_clk"), (n + 1) * m2,
+                         m * 2);
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_emu_core_alwon_clk"),
+                         (n + 1) * m3, m * 2);
+        TRACE("coreclk %lld",
+              omap_clk_getrate(omap_findclk(s->mpu, "omap3_core_clk")));
+    }
+
+
+}
+
+
+static inline void omap3_cm_dpll4_update(struct omap3_cm_s *s)
+{
+    uint32_t m, n, m2, m3, m4, m5, m6, cm_clken_pll;
+    cm_clken_pll = s->cm_clken_pll;
+    uint32_t bypass = 1;
+
+    /*dpll3 bypass mode. parent clock is always omap3_sys_clk */
+    /*DPLL4 */
+    if ((cm_clken_pll & 0x70000) == 0x10000)
+    {
+        bypass = 1;
+    }
+    else if ((cm_clken_pll & 0x70000) == 0x70000)
+    {
+        m = (s->cm_clksel2_pll & 0x7ff00) >> 8;
+        if ((m == 0) || (m == 1))
+            bypass = 1;
+        else
+            bypass = 0;
+    }
+    if (bypass == 1)
+    {
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_96m_fclk"), 1, 1);
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_54m_fclk"), 1, 1);
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_dss1_alwon_fclk"), 1, 1);
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_cam_mclk"), 1, 1);
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_per_alwon_clk"), 1, 1);
+    }
+    else
+    {
+        n = (s->cm_clksel2_pll & 0x7f);
+        m2 = s->cm_clksel3_pll & 0x1f;
+        m3 = (s->cm_clksel_dss & 0x1f00) >> 8;
+        m4 = s->cm_clksel_dss & 0x1f;
+        m5 = s->cm_clksel_cam & 0x1f;
+        m6 = (s->cm_clksel1_emu & 0x1f000000) >> 24;
+
+        if (s->cm_clksel3_emu&0x80000)
+        {
+               /*override control of DPLL4*/
+               m = (s->cm_clksel3_emu&0x7ff)>>8;
+               n =  s->cm_clksel3_emu&0x7f;
+               TRACE("DPLL4 override, m 0x%x n 0x%x",m,n);
+        }
+
+
+        //OMAP3_DEBUG(("dpll4 m  %d n %d m2 %d  m3 %d m4 %d m5 %d m6 %d \n",m,n,m2,m3,m4,m5,m6 ));
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_96m_fclk"), (n + 1) * m2,
+                         m * 2);
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_54m_fclk"), (n + 1) * m3,
+                         m * 2);
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_dss1_alwon_fclk"),
+                         (n + 1) * m4, m * 2);
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_cam_mclk"), (n + 1) * m5,
+                         m * 2);
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_per_alwon_clk"),
+                         (n + 1) * m6, m * 2);
+
+        TRACE("omap3_96m_fclk %lld",
+              omap_clk_getrate(omap_findclk(s->mpu, "omap3_96m_fclk")));
+        TRACE("omap3_54m_fclk %lld",
+              omap_clk_getrate(omap_findclk(s->mpu, "omap3_54m_fclk")));
+        TRACE("omap3_dss1_alwon_fclk %lld",
+              omap_clk_getrate(omap_findclk(s->mpu, "omap3_dss1_alwon_fclk")));
+        TRACE("omap3_cam_mclk %lld",
+              omap_clk_getrate(omap_findclk(s->mpu, "omap3_cam_mclk")));
+        TRACE("omap3_per_alwon_clk %lld",
+              omap_clk_getrate(omap_findclk(s->mpu, "omap3_per_alwon_clk")));
+        TRACE("omap3_48m_fclk %lld",
+              omap_clk_getrate(omap_findclk(s->mpu, "omap3_48m_fclk")));
+        TRACE("omap3_12m_fclk %lld",
+              omap_clk_getrate(omap_findclk(s->mpu, "omap3_12m_fclk")));
+    }
+}
+
+static inline void omap3_cm_dpll5_update(struct omap3_cm_s *s)
+{
+        uint32_t m, n, m2, cm_idlest2_ckgen;
+    uint32_t bypass = 1;
+
+    cm_idlest2_ckgen = s->cm_idlest2_ckgen;;
+
+    /*dpll5 bypass mode */
+    if ((cm_idlest2_ckgen & 0x1) == 0x0) 
+    {
+        bypass = 1;
+    }
+
+    if (bypass == 1)
+    {
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_120m_fclk"), 1, 1);
+    }
+    else
+    {
+        m = (s->cm_clksel4_pll & 0x7ff00)>>8;
+        n = s->cm_clksel4_pll & 0x3f00;
+        m2 = s->cm_clksel5_pll & 0x1f;
+
+        TRACE("dpll5 m %d n %d m2 %d",m,n,m2);
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_120m_fclk"), (n + 1) * m2,
+                         m);
+        TRACE("omap3_120m_fclk %lld",
+              omap_clk_getrate(omap_findclk(s->mpu, "omap3_120m_fclk")));
+    }
+
+
+}
+static inline void omap3_cm_48m_update(struct omap3_cm_s *s)
+{
+    if (s->cm_clksel1_pll & 0x8)
+    {
+        /*parent is sysaltclk */
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_48m_fclk"),
+                          omap_findclk(s->mpu, "omap3_sys_altclk"));
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_12m_fclk"),
+                          omap_findclk(s->mpu, "omap3_sys_altclk"));
+        /*TODO:need to set rate ? */
+
+    }
+    else
+    {
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_12m_fclk"),
+                          omap_findclk(s->mpu, "omap3_96m_fclk"));
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_48m_fclk"),
+                          omap_findclk(s->mpu, "omap3_96m_fclk"));
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_48m_fclk"), 2, 1);
+        omap_clk_setrate(omap_findclk(s->mpu, "omap3_12m_fclk"), 8, 1);
+
+    }
+
+}
+
+static inline void omap3_cm_gp10_update(struct omap3_cm_s *s)
+{
+    omap_clk gp10_fclk = omap_findclk(s->mpu, "omap3_gp10_fclk");
+
+    if (s->cm_clksel_core & 0x40)
+        omap_clk_reparent(gp10_fclk, omap_findclk(s->mpu, "omap3_sys_clk"));
+    else
+        omap_clk_reparent(gp10_fclk, omap_findclk(s->mpu, "omap3_32k_fclk"));
+
+    /*Tell GPTIMER10 to generate new clk rate */
+    omap_gp_timer_change_clk(s->mpu->gptimer[9]);
+    TRACE("omap3_gp10_fclk %lld",
+          omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp10_fclk")));
+}
+
+static inline void omap3_cm_gp11_update(struct omap3_cm_s *s)
+{
+    omap_clk gp11_fclk = omap_findclk(s->mpu, "omap3_gp11_fclk");
+
+    if (s->cm_clksel_core & 0x80)
+        omap_clk_reparent(gp11_fclk, omap_findclk(s->mpu, "omap3_sys_clk"));
+    else
+        omap_clk_reparent(gp11_fclk, omap_findclk(s->mpu, "omap3_32k_fclk"));
+    /*Tell GPTIMER11 to generate new clk rate */
+    omap_gp_timer_change_clk(s->mpu->gptimer[10]);
+    TRACE("omap3_gp11_fclk %lld",
+          omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp11_fclk")));
+}
+
+static inline void omap3_cm_l3clk_update(struct omap3_cm_s *s)
+{
+    omap_clk l3_iclk = omap_findclk(s->mpu, "omap3_l3_iclk");
+    if ((s->cm_clksel_core & 0x3) == 0x1)
+        omap_clk_setrate(l3_iclk, 1, 1);
+    else if ((s->cm_clksel_core & 0x3) == 0x2)
+        omap_clk_setrate(l3_iclk, 2, 1);
+}
+
+static inline void omap3_cm_l4clk_update(struct omap3_cm_s *s)
+{
+    omap_clk l4_iclk = omap_findclk(s->mpu, "omap3_l4_iclk");
+    if ((s->cm_clksel_core & 0xc) == 0x4)
+        omap_clk_setrate(l4_iclk, 1, 1);
+    else if ((s->cm_clksel_core & 0xc) == 0x8)
+        omap_clk_setrate(l4_iclk, 2, 1);
+}
+
+static inline void omap3_cm_per_gptimer_update(struct omap3_cm_s *s)
+{
+    uint32_t cm_clksel_per = s->cm_clksel_per;
+
+    if (cm_clksel_per & 0x1)
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp2_fclk"),
+                          omap_findclk(s->mpu, "omap3_sys_clk"));
+    else
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp2_fclk"),
+                          omap_findclk(s->mpu, "omap3_32k_fclk"));
+    omap_gp_timer_change_clk(s->mpu->gptimer[1]);
+
+    if (cm_clksel_per & 0x2)
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp3_fclk"),
+                          omap_findclk(s->mpu, "omap3_sys_clk"));
+    else
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp3_fclk"),
+                          omap_findclk(s->mpu, "omap3_32k_fclk"));
+    omap_gp_timer_change_clk(s->mpu->gptimer[2]);
+
+    if (cm_clksel_per & 0x4)
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp4_fclk"),
+                          omap_findclk(s->mpu, "omap3_sys_clk"));
+    else
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp4_fclk"),
+                          omap_findclk(s->mpu, "omap3_32k_fclk"));
+    omap_gp_timer_change_clk(s->mpu->gptimer[3]);
+
+    if (cm_clksel_per & 0x8)
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp5_fclk"),
+                          omap_findclk(s->mpu, "omap3_sys_clk"));
+    else
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp5_fclk"),
+                          omap_findclk(s->mpu, "omap3_32k_fclk"));
+    omap_gp_timer_change_clk(s->mpu->gptimer[4]);
+
+    if (cm_clksel_per & 0x10)
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp6_fclk"),
+                          omap_findclk(s->mpu, "omap3_sys_clk"));
+    else
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp6_fclk"),
+                          omap_findclk(s->mpu, "omap3_32k_fclk"));
+    omap_gp_timer_change_clk(s->mpu->gptimer[5]);
+    
+    if (cm_clksel_per & 0x20)
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp7_fclk"),
+                          omap_findclk(s->mpu, "omap3_sys_clk"));
+    else
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp7_fclk"),
+                          omap_findclk(s->mpu, "omap3_32k_fclk"));
+    omap_gp_timer_change_clk(s->mpu->gptimer[6]);
+
+
+    if (cm_clksel_per & 0x40)
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp8_fclk"),
+                          omap_findclk(s->mpu, "omap3_sys_clk"));
+    else
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp8_fclk"),
+                          omap_findclk(s->mpu, "omap3_32k_fclk"));
+    omap_gp_timer_change_clk(s->mpu->gptimer[7]);
+    
+    if (cm_clksel_per & 0x80)
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp9_fclk"),
+                          omap_findclk(s->mpu, "omap3_sys_clk"));
+    else
+        omap_clk_reparent(omap_findclk(s->mpu, "omap3_gp9_fclk"),
+                          omap_findclk(s->mpu, "omap3_32k_fclk"));
+    omap_gp_timer_change_clk(s->mpu->gptimer[8]);
+
+    /*TODO:Tell GPTIMER to generate new clk rate */
+    TRACE("omap3_gp2_fclk %lld",
+          omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp2_fclk")));
+    TRACE("omap3_gp3_fclk %lld",
+          omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp3_fclk")));
+       TRACE("omap3_gp4_fclk %lld",
+          omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp4_fclk")));
+    TRACE("omap3_gp5_fclk %lld",
+          omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp5_fclk")));
+    TRACE("omap3_gp6_fclk %lld",
+          omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp6_fclk")));
+    TRACE("omap3_gp7_fclk %lld",
+          omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp7_fclk")));
+    TRACE("omap3_gp8_fclk %lld",
+          omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp8_fclk")));
+    TRACE("omap3_gp9_fclk %lld",
+          omap_clk_getrate(omap_findclk(s->mpu, "omap3_gp9_fclk")));
+}
+
+static inline void omap3_cm_clkout2_update(struct omap3_cm_s *s)
+{
+       uint32 divor;
+       
+       if (!s->cm_clkout_ctrl&0x80)
+               return;
+
+       switch (s->cm_clkout_ctrl&0x3)
+       {
+               case 0x0:
+                       omap_clk_reparent(omap_findclk(s->mpu, "omap3_sys_clkout2"),
+                          omap_findclk(s->mpu, "omap3_core_clk"));
+                       break;
+               case 0x1:
+                       omap_clk_reparent(omap_findclk(s->mpu, "omap3_sys_clkout2"),
+                          omap_findclk(s->mpu, "omap3_sys_clk"));
+                       break;
+               case 0x2:
+                       omap_clk_reparent(omap_findclk(s->mpu, "omap3_sys_clkout2"),
+                          omap_findclk(s->mpu, "omap3_96m_fclk"));
+                       break;
+               case 0x3:
+                       omap_clk_reparent(omap_findclk(s->mpu, "omap3_sys_clkout2"),
+                          omap_findclk(s->mpu, "omap3_54m_fclk"));
+                       break;
+       }
+
+       divor = (s->cm_clkout_ctrl&0x31)>>3;
+       divor = 1<<divor;
+       omap_clk_setrate(omap_findclk(s->mpu, "omap3_sys_clkout2"), divor, 1);
+       
+}
+
+static void omap3_cm_reset(struct omap3_cm_s *s)
+{
+    s->cm_fclken_iva2 = 0x0;
+    s->cm_clken_pll_iva2 = 0x11;
+    s->cm_idlest_iva2 = 0x1;
+    s->cm_idlest_pll_iva2 = 0x0;
+    s->cm_autoidle_pll_iva2 = 0x0;
+    s->cm_clksel1_pll_iva2 = 0x80000;
+    s->cm_clksel2_pll_iva2 = 0x1;
+    s->cm_clkstctrl_iva2 = 0x0;
+    s->cm_clkstst_iva2 = 0x0;
+
+    s->cm_revision = 0x10;
+    s->cm_sysconfig = 0x1;
+
+    s->cm_clken_pll_mpu = 0x15;
+    s->cm_idlest_mpu = 0x1;
+    s->cm_idlest_pll_mpu = 0x0;
+    s->cm_autoidle_pll_mpu = 0x0;
+    s->cm_clksel1_pll_mpu = 0x80000;
+    s->cm_clksel2_pll_mpu = 0x1;
+    s->cm_clkstctrl_mpu = 0x0;
+    s->cm_clkstst_mpu = 0x0;
+
+    s->cm_fclken1_core = 0x0;
+    s->cm_fclken3_core = 0x0;
+    s->cm_iclken1_core = 0x42;
+    s->cm_iclken2_core = 0x0;
+    s->cm_iclken3_core = 0x0;
+    /*allow access to devices*/
+    s->cm_idlest1_core = 0x0;
+    s->cm_idlest2_core = 0x0;
+    /*ide status =0 */
+    s->cm_idlest3_core = 0xa; 
+    s->cm_autoidle1_core = 0x0;
+    s->cm_autoidle2_core = 0x0;
+    s->cm_autoidle3_core = 0x0;
+    s->cm_clksel_core = 0x105;
+    s->cm_clkstctrl_core = 0x0;
+    s->cm_clkstst_core = 0x0;
+
+    s->cm_fclken_sgx = 0x0;
+    s->cm_iclken_sgx = 0x0;
+    s->cm_idlest_sgx = 0x1;
+    s->cm_clksel_sgx = 0x0;
+    s->cm_sleepdep_sgx = 0x0;
+    s->cm_clkstctrl_sgx = 0x0;
+    s->cm_clkstst_sgx = 0x0;
+
+    s->cm_fclken_wkup = 0x0;
+    s->cm_iclken_wkup = 0x0;
+    /*assume all clock can be accessed*/
+    s->cm_idlest_wkup = 0x0;
+    s->cm_autoidle_wkup = 0x0;
+    s->cm_clksel_wkup = 0x12;
+
+    s->cm_clken_pll = 0x110015;
+    s->cm_clken2_pll = 0x11;
+    s->cm_idlest_ckgen = 0x0;
+    s->cm_idlest2_ckgen = 0x0;
+    s->cm_autoidle_pll = 0x0;
+    s->cm_autoidle2_pll = 0x0;
+    s->cm_clksel1_pll = 0x8000040;
+    s->cm_clksel2_pll = 0x0;
+    s->cm_clksel3_pll = 0x1;
+    s->cm_clksel4_pll = 0x0;
+    s->cm_clksel5_pll = 0x1;
+    s->cm_clkout_ctrl = 0x3;
+
+
+    s->cm_fclken_dss = 0x0;
+    s->cm_iclken_dss = 0x0;
+    /*dss can be accessed*/
+    s->cm_idlest_dss = 0x0;
+    s->cm_autoidle_dss = 0x0;
+    s->cm_clksel_dss = 0x1010;
+    s->cm_sleepdep_dss = 0x0;
+    s->cm_clkstctrl_dss = 0x0;
+    s->cm_clkstst_dss = 0x0;
+
+    s->cm_fclken_cam = 0x0;
+    s->cm_iclken_cam = 0x0;
+    s->cm_idlest_cam = 0x1;
+    s->cm_autoidle_cam = 0x0;
+    s->cm_clksel_cam = 0x10;
+    s->cm_sleepdep_cam = 0x0;
+    s->cm_clkstctrl_cam = 0x0;
+    s->cm_clkstst_cam = 0x0;
+
+    s->cm_fclken_per = 0x0;
+    s->cm_iclken_per = 0x0;
+    //s->cm_idlest_per = 0x3ffff;
+    s->cm_idlest_per = 0x0; //enable GPIO access
+    s->cm_autoidle_per = 0x0;
+    s->cm_clksel_per = 0x0;
+    s->cm_sleepdep_per = 0x0;
+    s->cm_clkstctrl_per = 0x0;
+    s->cm_clkstst_per = 0x0;
+
+    s->cm_clksel1_emu = 0x10100a50;
+    s->cm_clkstctrl_emu = 0x2;
+    s->cm_clkstst_emu = 0x0;
+    s->cm_clksel2_emu = 0x0;
+    s->cm_clksel3_emu = 0x0;
+
+    s->cm_polctrl = 0x0;
+
+    s->cm_idlest_neon = 0x1;
+    s->cm_clkstctrl_neon = 0x0;
+
+    s->cm_fclken_usbhost = 0x0;
+    s->cm_iclken_usbhost = 0x0;
+    s->cm_idlest_usbhost = 0x3;
+    s->cm_autoidle_usbhost = 0x0;
+    s->cm_sleepdep_usbhost = 0x0;
+    s->cm_clkstctrl_usbhost = 0x0;
+    s->cm_clkstst_usbhost = 0x0;
+}
+
+static uint32_t omap3_cm_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap3_cm_s *s = (struct omap3_cm_s *) opaque;
+    uint32_t ret;
+    uint32_t bypass = 0, m;
+
+    TRACE("%04x", addr);
+    switch (addr)
+    {
+    case 0x0:
+       return s->cm_fclken_iva2;
+    case 0x04:
+        return s->cm_clken_pll_iva2;
+    case 0x20:
+       return s->cm_idlest_iva2;
+    case 0x24:
+        if (((s->cm_clken_pll_iva2 & 0x7) == 0x5)
+            || ((s->cm_clken_pll_iva2 & 0x7) == 0x1))
+        {
+            bypass = 1;
+        }
+        else if ((s->cm_clken_pll_iva2 & 0x7) == 0x7)
+        {
+            m = (s->cm_clksel1_pll_iva2 & 0x7ff00) >> 8;
+            if ((m == 0) || (m == 1))
+                bypass = 1;
+            else
+                bypass = 0;
+        }
+        if (bypass)
+            return 0;
+        else
+            return 1;
+    case 0x34:
+       return s->cm_autoidle_pll_iva2;
+    case 0x40:
+        return s->cm_clksel1_pll_iva2;
+    case 0x44:
+        return s->cm_clksel2_pll_iva2;
+    case 0x48:
+       return s->cm_clkstctrl_iva2;
+    case 0x4c:
+       return s->cm_clkstst_iva2;
+
+   case 0x800:
+               return s->cm_revision;
+       case 0x810:
+               return s->cm_sysconfig;
+
+       
+    case 0x904:                /*CM_CLKEN_PLL_MPU */
+        return s->cm_clken_pll_mpu;
+   case 0x920:
+               return s->cm_idlest_mpu & 0x0;  /*MPU is active*/
+    case 0x924:
+        if ((s->cm_clken_pll_mpu & 0x7) == 0x5)
+        {
+            bypass = 1;
+        }
+        else if ((s->cm_clken_pll_mpu & 0x7) == 0x7)
+        {
+            m = (s->cm_clksel1_pll_mpu & 0x7ff00) >> 8;
+            if ((m == 0) || (m == 1))
+                bypass = 1;
+            else
+                bypass = 0;
+        }
+        if (bypass)
+            return 0;
+        else
+            return 1;
+    case 0x934:
+       return s->cm_autoidle_pll_mpu;
+    case 0x940:
+        return s->cm_clksel1_pll_mpu;
+    case 0x944:
+        return s->cm_clksel2_pll_mpu;
+     case 0x948:
+       return s->cm_clkstctrl_mpu;
+     case 0x94c:
+       return s->cm_clkstst_mpu;
+
+
+       
+    case 0xa00:
+        return s->cm_fclken1_core;
+    case 0xa08:
+       return s->cm_fclken3_core;
+    case 0xa10:
+        return s->cm_iclken1_core;
+    case 0xa14:
+        return s->cm_iclken2_core;
+    case 0xa20:
+       return s->cm_idlest1_core;
+    case 0xa24:
+       return s->cm_idlest2_core;
+    case 0xa28:
+       return s->cm_idlest3_core;
+    case 0xa30:
+       return s->cm_autoidle1_core;
+    case 0xa34:
+       return s->cm_autoidle2_core;
+    case 0xa38:
+       return s->cm_autoidle3_core;
+    case 0xa40:                /*CM_CLKSEL_CORE */
+        return s->cm_clksel_core;
+    case 0xa48:
+        return s->cm_clkstctrl_core;
+     case 0xa4c:
+       return s->cm_clkstst_core;
+
+   case 0xb00:
+               return s->cm_fclken_sgx;
+       case 0xb10:
+               return s->cm_iclken_sgx;
+       case 0xb20:
+               return s->cm_idlest_sgx&0x0;
+   case 0xb40:                /*CM_CLKSEL_SGX */
+        return s->cm_clksel_sgx;
+   case 0xb48:
+               return s->cm_clkstctrl_sgx;
+       case 0xb4c:
+               return s->cm_clkstst_sgx;
+
+               
+    case 0xc00:                /*CM_FCLKEN_WKUP */
+        return s->cm_fclken_wkup;
+    case 0xc10:                /*CM_ICLKEN_WKUP */
+        return s->cm_iclken_wkup;
+    case 0xc20:                /*CM_IDLEST_WKUP */
+        /*TODO: Check whether the timer can be accessed. */
+        return 0x0;
+    case 0xc30:
+       return s->cm_idlest_wkup;
+    case 0xc40:
+        return s->cm_clksel_wkup;
+    case 0xc48:
+       return s->cm_c48;
+
+       
+    case 0xd00:                /*CM_CLKEN_PLL */
+        return s->cm_clken_pll;
+    case 0xd04:
+       return s->cm_clken2_pll;
+    case 0xd20:
+        /*FIXME: all clock is active. we do not care it. */
+        ret = 0x3ffff;
+
+       /*DPLL3*/
+       bypass = 0;
+       if (((s->cm_clken_pll & 0x7) == 0x5) || ((s->cm_clken_pll & 0x7) == 0x6))
+               bypass = 1;
+        else if ((s->cm_clken_pll & 0x7) == 0x7) {
+            m = (s->cm_clksel1_pll & 0x7ff0000) >> 16;
+            if ((m == 0) || (m == 1))
+                bypass = 1;
+            else
+                bypass = 0;
+        }
+        if (bypass)
+            ret &= 0xfffe;
+        
+        /*DPLL4*/
+           bypass = 0;
+           if ((s->cm_clken_pll & 0x70000) == 0x10000)
+            bypass = 1;
+        else if ((s->cm_clken_pll & 0x70000) == 0x70000) {
+            m = (s->cm_clksel2_pll & 0x7ff00) >> 8;
+            if ((m == 0) || (m == 1))
+                bypass = 1;
+            else
+                bypass = 0;
+        }
+        if (bypass)
+            ret &= 0xfffd;
+       return ret;
+       
+    case 0xd24:
+       return s->cm_idlest2_ckgen;
+    case 0xd30:
+       return s->cm_autoidle_pll;
+    case 0xd34:
+       return s->cm_autoidle2_pll;
+    case 0xd40:                /*CM_CLKSEL1_PLL */
+        return s->cm_clksel1_pll;
+    case 0xd44:
+        return s->cm_clksel2_pll;
+    case 0xd48:                /*CM_CLKSEL3_PLL */
+        return s->cm_clksel3_pll;
+    case 0xd4c:
+        return s->cm_clksel4_pll;
+    case 0xd50:                /*CM_CLKSEL5_PLL */
+        return s->cm_clksel5_pll;
+    case 0xd70:
+        return s->cm_clkout_ctrl;
+
+        
+    case 0xe00:
+       return s->cm_fclken_dss;
+       case 0xe10:
+       return s->cm_iclken_dss;
+    case 0xe20:
+       return s->cm_idlest_dss;
+    case 0xe30:
+       return s->cm_autoidle_dss;
+    case 0xe40:
+        return s->cm_clksel_dss;
+    case 0xe44:
+        return s->cm_sleepdep_dss;
+    case 0xe48:
+        return s->cm_clkstctrl_dss;
+    case 0xe4c:
+        return s->cm_clkstst_dss;
+
+        
+    case 0xf00:
+       return s->cm_fclken_cam;
+    case 0xf10:
+       return s->cm_iclken_cam;
+    case 0xf20:
+       return s->cm_idlest_cam&0x0;
+    case 0xf30:
+       return s->cm_autoidle_cam;
+    case 0xf40:
+        return s->cm_clksel_cam;
+    case 0xf44:
+       return s->cm_sleepdep_cam;
+    case 0xf48:
+       return s->cm_clkstctrl_cam;
+    case 0xf4c:
+       return s->cm_clkstst_cam;
+
+       
+    case 0x1000:
+        return s->cm_fclken_per;
+    case 0x1010:
+        return s->cm_iclken_per;
+    case 0x1020:
+       return s->cm_idlest_per ;
+    case 0x1030:
+       return s->cm_autoidle_per;
+    case 0x1040:
+        return s->cm_clksel_per;
+    case 0x1044:
+       return s->cm_sleepdep_per;
+    case 0x1048:
+       return s->cm_clkstctrl_per;
+    case 0x104c:
+               return s->cm_clkstst_per;
+
+       
+    case 0x1140:               /*CM_CLKSEL1_EMU */
+        return s->cm_clksel1_emu;
+    case 0x1148:
+        return s->cm_clkstctrl_emu;
+    case 0x114c:
+       return s->cm_clkstst_emu&0x0;
+    case 0x1150:
+       return s->cm_clksel2_emu;
+    case 0x1154:
+       return s->cm_clksel3_emu;
+
+   case 0x129c:
+               return s->cm_polctrl;
+
+       case 0x1320:
+               return s->cm_idlest_neon&0x0;
+       case 0x1348:
+               return s->cm_clkstctrl_neon;
+
+       case 0x1400:
+               return s->cm_fclken_usbhost;
+       case 0x1410:
+               return s->cm_iclken_usbhost;
+       case 0x1420:
+               return s->cm_idlest_usbhost&0x0;
+    case 0x1430:
+       return s->cm_autoidle_usbhost;
+    case 0x1444:
+       return s->cm_sleepdep_usbhost;
+    case 0x1448:
+       return s->cm_clkstctrl_usbhost;
+    case 0x144c:
+       return s->cm_clkstst_usbhost;
+
+    default:
+        printf("omap3_cm_read addr %x pc %x \n", addr, cpu_single_env->regs[15] );
+        exit(-1);
+    }
+}
+
+
+static void omap3_cm_write(void *opaque, target_phys_addr_t addr,
+                           uint32_t value)
+{
+    struct omap3_cm_s *s = (struct omap3_cm_s *) opaque;
+
+    TRACE("%04x = %08x", addr, value);
+    switch (addr)
+    {
+    case 0x20:
+    case 0x24:
+    case 0x4c:
+    case 0x800:
+    case 0x920:
+    case 0x924:
+    case 0x94c:
+    case 0xa20:
+    case 0xa24:
+    case 0xa28:
+    case 0xa4c:
+    case 0xb20:
+    case 0xb4c:
+    case 0xc20:                /*CM_IDLEST_WKUP */
+    case 0xd20:
+    case 0xd24:
+    case 0xe20:
+    case 0xe4c:
+    case 0xf20:
+    case 0xf4c:
+    case 0x1020:
+    case 0x104c:
+    case 0x114c:
+    case 0x1320:
+    case 0x1420:
+    case 0x144c:
+        OMAP_RO_REG(addr);
+        exit(-1);
+        break;
+        
+    case 0x0:
+       s->cm_fclken_iva2 = value & 0x1;
+       break;
+    case 0x4:                  /*CM_CLKEN_PLL_IVA2 */
+        s->cm_clken_pll_iva2 = value & 0x7ff;
+        omap3_cm_iva2_update(s);
+        break;
+    case 0x34:
+       s->cm_autoidle_pll_iva2 = value & 0x7;
+       break;
+    case 0x40:
+        s->cm_clksel1_pll_iva2 = value & 0x3fff7f;
+        //printf("value %x s->cm_clksel1_pll_iva2 %x \n",value,s->cm_clksel1_pll_iva2);
+        omap3_cm_iva2_update(s);
+        break;
+    case 0x44:
+        s->cm_clksel2_pll_iva2 = value & 0x1f;
+        omap3_cm_iva2_update(s);
+        break;
+    case 0x48:
+       s->cm_clkstctrl_iva2 = value& 0x3;
+       break;
+
+    case 0x810:
+       s->cm_sysconfig = value & 0x1;
+       break;
+
+        
+    case 0x904:                /*CM_CLKEN_PLL_MPU */
+        s->cm_clken_pll_mpu = value & 0x7ff;
+        omap3_cm_mpu_update(s);
+        break;
+    case 0x934:
+       s->cm_autoidle_pll_mpu = value & 0x7;
+       break;
+    case 0x940:
+        //printf("s->cm_clksel1_pll_mpu  %x\n",s->cm_clksel1_pll_mpu );
+        s->cm_clksel1_pll_mpu = value & 0x3fff7f;
+        omap3_cm_mpu_update(s);
+        break;
+    case 0x944:
+        s->cm_clksel2_pll_mpu = value & 0x1f;
+        omap3_cm_mpu_update(s);
+        break;
+    case 0x948:
+       s->cm_clkstctrl_mpu = value & 0x3;
+       break;
+
+       
+    case 0xa00:
+        s->cm_fclken1_core = value & 0x43fffe00;
+         break;
+    case 0xa08:
+        s->cm_fclken3_core = value & 0x7;
+        break;
+    case 0xa10:
+        s->cm_iclken1_core = value & 0x637ffed2;
+        s->cm_idlest1_core = ~s->cm_iclken1_core;
+        /* TODO: replace code below with real implementation */
+        s->cm_idlest1_core &= ~0x20; /* HS OTG USB idle */
+        s->cm_idlest1_core |= 4; /* SDMA in standby */
+        break;
+    case 0xa14:
+        s->cm_iclken2_core = value & 0x1f;
+        break;
+    case 0xa18:
+       s->cm_iclken3_core = value & 0x4;
+        s->cm_idlest3_core = 0xd & ~(s->cm_iclken3_core & 4);
+       break;
+    case 0xa30:
+       s->cm_autoidle1_core = value & 0x7ffffed0;
+       break;
+    case 0xa34:
+       s->cm_autoidle2_core = value & 0x1f;
+       break;
+    case 0xa38:
+       s->cm_autoidle3_core = value & 0x2;
+       break;
+    case 0xa40:                /*CM_CLKSEL_CORE */
+        s->cm_clksel_core = (value & 0xff);
+        s->cm_clksel_core |= 0x100;
+        omap3_cm_gp10_update(s);
+        omap3_cm_gp11_update(s);
+        omap3_cm_l3clk_update(s);
+        omap3_cm_l4clk_update(s);
+        break;
+    case 0xa48:
+       s->cm_clkstctrl_core = value & 0xf;
+       break;
+
+    case 0xb00:
+       s->cm_fclken_sgx = value &0x2;
+       break;
+    case 0xb10:
+       s->cm_iclken_sgx = value & 0x1;
+       break;
+    case 0xb40:                /*CM_CLKSEL_SGX */
+        /*TODO: SGX Clock!! */
+        s->cm_clksel_sgx = value;
+        break;
+    case 0xb44:
+       s->cm_sleepdep_sgx = value &0x2;
+       break;
+    case 0xb48:
+       s->cm_clkstctrl_sgx = value & 0x3;
+       break;
+
+    
+    case 0xc00:                /*CM_FCLKEN_WKUP */
+        s->cm_fclken_wkup = value & 0x2e9;
+        break;
+    case 0xc10:                /*CM_ICLKEN_WKUP */
+        s->cm_iclken_wkup = value & 0x2ff;
+        break;
+    case 0xc30:
+       s->cm_autoidle_wkup = value & 0x23f;
+       break;
+    case 0xc40:                /*CM_CLKSEL_WKUP */
+        s->cm_clksel_wkup = value & 0x7f;
+        omap3_cm_clksel_wkup_update(s, s->cm_clksel_wkup);
+        break;
+
+        
+    case 0xd00:                /*CM_CLKEN_PLL */
+        s->cm_clken_pll = value & 0xffff17ff;
+        omap3_cm_dpll3_update(s);
+        omap3_cm_dpll4_update(s);
+        break;
+    case 0xd04:
+       s->cm_clken2_pll = value & 0x7ff;
+       break;
+    case 0xd30:
+       s->cm_autoidle_pll = value & 0x3f;
+       break;
+    case 0xd34:
+       s->cm_autoidle2_pll = value & 0x7;
+       break;
+    case 0xd40:                /*CM_CLKSEL1_PLL */
+        //OMAP3_DEBUG(("WD40 value %x \n",value));
+        s->cm_clksel1_pll = value & 0xffffbffc;
+        //OMAP3_DEBUG(("WD40 value %x \n",value));
+        omap3_cm_dpll3_update(s);
+        omap3_cm_48m_update(s);
+        break;
+    case 0xd44:
+        s->cm_clksel2_pll = value & 0x7ff7f;
+        omap3_cm_dpll4_update(s);
+        break;
+    case 0xd48:                /*CM_CLKSEL3_PLL */
+        s->cm_clksel3_pll = value & 0x1f;
+        omap3_cm_dpll4_update(s);
+        break;
+    case 0xd4c:                /*CM_CLKSEL4_PLL */  
+       s->cm_clksel4_pll = value & 0x7ff7f;
+        omap3_cm_dpll5_update(s);
+        break;
+     case 0xd50:                /*CM_CLKSEL5_PLL */
+        s->cm_clksel5_pll = value & 0x1f;
+        omap3_cm_dpll5_update(s);
+        break;
+    case 0xd70:
+       s->cm_clkout_ctrl = value & 0xbb;
+       omap3_cm_clkout2_update(s);
+       break;
+        
+    case 0xe00:
+       s->cm_fclken_dss = value & 0x7;
+       break;
+       case 0xe10:
+       s->cm_iclken_dss = value & 0x1;
+       break;
+    case 0xe30:
+       s->cm_autoidle_dss = value & 0x1;
+       break;
+    case 0xe40:
+        s->cm_clksel_dss = value & 0x1f1f;
+        omap3_cm_dpll4_update(s);
+        break;
+   case 0xe44:
+               s->cm_sleepdep_dss = value & 0x7;
+       break;
+   case 0xe48:
+               s->cm_clkstctrl_dss = value & 0x3;
+       break;
+        
+    case 0xf00:
+       s->cm_fclken_cam = value & 0x3;
+       break;
+    case 0xf10:
+       s->cm_iclken_cam = value & 0x1;
+       break;
+    case 0xf30:
+       s->cm_autoidle_cam = value & 0x1;
+       break;
+    case 0xf40:
+        s->cm_clksel_cam = value & 0x1f;
+        omap3_cm_dpll4_update(s);
+        break;
+    case 0xf44:
+       s->cm_sleepdep_cam = value & 0x2;
+       break;
+    case 0xf48:
+       s->cm_clkstctrl_cam = value & 0x3;
+       break;
+   
+    case 0x1000:
+        s->cm_fclken_per = value & 0x3ffff;
+        break;
+    case 0x1010:
+        s->cm_iclken_per = value & 0x3ffff;
+        break;
+    
+    case 0x1030:
+       s->cm_autoidle_per = value &0x3ffff;
+       break;
+    case 0x1040:
+        s->cm_clksel_per = value & 0xff;
+        omap3_cm_per_gptimer_update(s);
+        break;
+    case 0x1044:
+       s->cm_sleepdep_per = value & 0x6;
+       break;
+    case 0x1048:
+        s->cm_clkstctrl_per = value &0x7;
+        break;
+        
+    case 0x1140:               /*CM_CLKSEL1_EMU */
+        s->cm_clksel1_emu = value & 0x1f1f3fff;
+        //printf("cm_clksel1_emu %x\n",s->cm_clksel1_emu);
+        omap3_cm_dpll3_update(s);
+        omap3_cm_dpll4_update(s);
+        break;
+    case 0x1148:
+       s->cm_clkstctrl_emu = value & 0x3;
+       break;
+        case 0x1150:
+                s->cm_clksel2_emu = value & 0xfff7f;
+                omap3_cm_dpll3_update(s);
+        break;
+    case 0x1154:
+        s->cm_clksel3_emu = value & 0xfff7f;
+                omap3_cm_dpll4_update(s);
+        break;
+
+    case 0x129c:
+        s->cm_polctrl = value & 0x1;
+        break;
+
+   case 0x1348:
+               s->cm_clkstctrl_neon = value & 0x3;
+               break;
+
+       case 0x1400:
+               s->cm_fclken_usbhost = value & 0x3;
+               break;
+       case 0x1410:
+               s->cm_iclken_usbhost = value & 0x1;
+               break;
+    case 0x1430:
+       s->cm_autoidle_usbhost = value & 0x1;
+       break;
+    case 0x1444:
+       s->cm_sleepdep_usbhost = value & 0x6;
+       break;
+    case 0x1448:
+       s->cm_clkstctrl_usbhost = value & 0x3;
+       break;
+   
+    default:
+        printf("omap3_cm_write addr %x value %x pc %x\n", addr, value,cpu_single_env->regs[15] );
+        exit(-1);
+    }
+}
+
+
+
+static CPUReadMemoryFunc *omap3_cm_readfn[] = {
+    omap_badwidth_read32,
+    omap_badwidth_read32,
+    omap3_cm_read,
+};
+
+static CPUWriteMemoryFunc *omap3_cm_writefn[] = {
+    omap_badwidth_write32,
+    omap_badwidth_write32,
+    omap3_cm_write,
+};
+
+struct omap3_cm_s *omap3_cm_init(struct omap_target_agent_s *ta,
+                                 qemu_irq mpu_int, qemu_irq dsp_int,
+                                 qemu_irq iva_int, struct omap_mpu_state_s *mpu)
+{
+    int iomemtype;
+    struct omap3_cm_s *s = (struct omap3_cm_s *) qemu_mallocz(sizeof(*s));
+
+    s->irq[0] = mpu_int;
+    s->irq[1] = dsp_int;
+    s->irq[2] = iva_int;
+    s->mpu = mpu;
+    omap3_cm_reset(s);
+
+    iomemtype = l4_register_io_memory(0, omap3_cm_readfn, omap3_cm_writefn, s);
+    omap_l4_attach(ta, 0, iomemtype);
+    omap_l4_attach(ta, 1, iomemtype);
+
+    return s;
+}
+
+#define OMAP3_SEC_WDT          1
+#define OMAP3_MPU_WDT         2
+#define OMAP3_IVA2_WDT        3
+/*omap3 watchdog timer*/
+struct omap3_wdt_s
+{
+    qemu_irq irq;               /*IVA2 IRQ */
+    struct omap_mpu_state_s *mpu;
+    omap_clk clk;
+    QEMUTimer *timer;
+
+    int active;
+    int64_t rate;
+    int64_t time;
+    //int64_t ticks_per_sec;
+
+    uint32_t wd_sysconfig;
+    uint32_t wd_sysstatus;
+    uint32_t wisr;
+    uint32_t wier;
+    uint32_t wclr;
+    uint32_t wcrr;
+    uint32_t wldr;
+    uint32_t wtgr;
+    uint32_t wwps;
+    uint32_t wspr;
+
+    /*pre and ptv in wclr */
+    uint32_t pre;
+    uint32_t ptv;
+    //uint32_t val;
+
+    uint16_t writeh;            /* LSB */
+    uint16_t readh;             /* MSB */
+
+};
+
+
+
+
+
+static inline void omap3_wdt_timer_update(struct omap3_wdt_s *wdt_timer)
+{
+    int64_t expires;
+    if (wdt_timer->active)
+    {
+        expires = muldiv64(0xffffffffll - wdt_timer->wcrr,
+                           ticks_per_sec, wdt_timer->rate);
+        qemu_mod_timer(wdt_timer->timer, wdt_timer->time + expires);
+    }
+    else
+        qemu_del_timer(wdt_timer->timer);
+}
+static void omap3_wdt_clk_setup(struct omap3_wdt_s *timer)
+{
+    /*TODO: Add irq as user to clk */
+}
+
+static inline uint32_t omap3_wdt_timer_read(struct omap3_wdt_s *timer)
+{
+    uint64_t distance;
+
+    if (timer->active)
+    {
+        distance = qemu_get_clock(vm_clock) - timer->time;
+        distance = muldiv64(distance, timer->rate, ticks_per_sec);
+
+        if (distance >= 0xffffffff - timer->wcrr)
+            return 0xffffffff;
+        else
+            return timer->wcrr + distance;
+    }
+    else
+        return timer->wcrr;
+}
+
+/*
+static inline void omap3_wdt_timer_sync(struct omap3_wdt_s *timer)
+{
+    if (timer->active) {
+        timer->val = omap3_wdt_timer_read(timer);
+        timer->time = qemu_get_clock(vm_clock);
+    }
+}*/
+
+static void omap3_wdt_reset(struct omap3_wdt_s *s, int wdt_index)
+{
+    s->wd_sysconfig = 0x0;
+    s->wd_sysstatus = 0x0;
+    s->wisr = 0x0;
+    s->wier = 0x0;
+    s->wclr = 0x20;
+    s->wcrr = 0x0;
+    switch (wdt_index)
+    {
+    case OMAP3_MPU_WDT:
+    case OMAP3_IVA2_WDT:
+        s->wldr = 0xfffb0000;
+        break;
+    case OMAP3_SEC_WDT:
+        s->wldr = 0xffa60000;
+        break;
+    }
+    s->wtgr = 0x0;
+    s->wwps = 0x0;
+    s->wspr = 0x0;
+
+    switch (wdt_index)
+    {
+    case OMAP3_SEC_WDT:
+    case OMAP3_MPU_WDT:
+        s->active = 1;
+        break;
+    case OMAP3_IVA2_WDT:
+        s->active = 0;
+        break;
+    }
+    s->pre = s->wclr & (1 << 5);
+    s->ptv = (s->wclr & 0x1c) >> 2;
+    s->rate = omap_clk_getrate(s->clk) >> (s->pre ? s->ptv : 0);
+
+    s->active = 1;
+    s->time = qemu_get_clock(vm_clock);
+    omap3_wdt_timer_update(s);
+}
+
+static uint32_t omap3_wdt_read32(void *opaque, target_phys_addr_t addr,
+                                 int wdt_index)
+{
+    struct omap3_wdt_s *s = (struct omap3_wdt_s *) opaque;
+
+    //uint32_t ret;
+    //printf("omap3_wdt_read32 addr %x \n",addr);
+    switch (addr)
+    {
+    case 0x10:                 /*WD_SYSCONFIG */
+        return s->wd_sysconfig;
+    case 0x14:                 /*WD_SYSSTATUS */
+        return s->wd_sysstatus;
+    case 0x18:
+         /*WISR*/ return s->wisr & 0x1;
+    case 0x1c:
+         /*WIER*/ return s->wier & 0x1;
+    case 0x24:
+         /*WCLR*/ return s->wclr & 0x3c;
+    case 0x28:
+         /*WCRR*/ s->wcrr = omap3_wdt_timer_read(s);
+        s->time = qemu_get_clock(vm_clock);
+        return s->wcrr;
+    case 0x2c:
+         /*WLDR*/ return s->wldr;
+    case 0x30:
+         /*WTGR*/ return s->wtgr;
+    case 0x34:
+         /*WWPS*/ return s->wwps;
+    case 0x48:
+         /*WSPR*/ return s->wspr;
+    default:
+        printf("omap3_wdt_read32 addr %x \n", addr);
+        exit(-1);
+    }
+}
+static uint32_t omap3_mpu_wdt_read16(void *opaque, target_phys_addr_t addr)
+{
+    struct omap3_wdt_s *s = (struct omap3_wdt_s *) opaque;
+    uint32_t ret;
+
+    if (addr & 2)
+        return s->readh;
+    else
+    {
+        ret = omap3_wdt_read32(opaque, addr, OMAP3_MPU_WDT);
+        s->readh = ret >> 16;
+        return ret & 0xffff;
+    }
+}
+static uint32_t omap3_mpu_wdt_read32(void *opaque, target_phys_addr_t addr)
+{
+    return omap3_wdt_read32(opaque, addr, OMAP3_MPU_WDT);
+}
+
+static void omap3_wdt_write32(void *opaque, target_phys_addr_t addr,
+                              uint32_t value, int wdt_index)
+{
+    struct omap3_wdt_s *s = (struct omap3_wdt_s *) opaque;
+
+    //printf("omap3_wdt_write32 addr %x value %x \n",addr,value);
+    switch (addr)
+    {
+    case 0x14:                 /*WD_SYSSTATUS */
+    case 0x34:
+         /*WWPS*/ OMAP_RO_REG(addr);
+        exit(-1);
+        break;
+    case 0x10:                 /*WD_SYSCONFIG */
+        s->wd_sysconfig = value & 0x33f;
+        break;
+    case 0x18:
+         /*WISR*/ s->wisr = value & 0x1;
+        break;
+    case 0x1c:
+         /*WIER*/ s->wier = value & 0x1;
+        break;
+    case 0x24:
+         /*WCLR*/ s->wclr = value & 0x3c;
+        break;
+    case 0x28:
+         /*WCRR*/ s->wcrr = value;
+        s->time = qemu_get_clock(vm_clock);
+        omap3_wdt_timer_update(s);
+        break;
+    case 0x2c:
+         /*WLDR*/ s->wldr = value;      /*It will take effect after next overflow */
+        break;
+    case 0x30:
+         /*WTGR*/ if (value != s->wtgr)
+        {
+            s->wcrr = s->wldr;
+            s->pre = s->wclr & (1 << 5);
+            s->ptv = (s->wclr & 0x1c) >> 2;
+            s->rate = omap_clk_getrate(s->clk) >> (s->pre ? s->ptv : 0);
+            s->time = qemu_get_clock(vm_clock);
+            omap3_wdt_timer_update(s);
+        }
+        s->wtgr = value;
+        break;
+    case 0x48:
+         /*WSPR*/
+            if (((value & 0xffff) == 0x5555) && ((s->wspr & 0xffff) == 0xaaaa))
+        {
+            s->active = 0;
+            s->wcrr = omap3_wdt_timer_read(s);
+            omap3_wdt_timer_update(s);
+        }
+        if (((value & 0xffff) == 0x4444) && ((s->wspr & 0xffff) == 0xbbbb))
+        {
+            s->active = 1;
+            s->time = qemu_get_clock(vm_clock);
+            omap3_wdt_timer_update(s);
+        }
+        s->wspr = value;
+        break;
+    default:
+        printf("omap3_wdt_write32 addr %x \n", addr);
+        exit(-1);
+    }
+}
+
+static void omap3_mpu_wdt_write16(void *opaque, target_phys_addr_t addr,
+                                  uint32_t value)
+{
+    struct omap3_wdt_s *s = (struct omap3_wdt_s *) opaque;
+
+    if (addr & 2)
+        return omap3_wdt_write32(opaque, addr, (value << 16) | s->writeh,
+                                 OMAP3_MPU_WDT);
+    else
+        s->writeh = (uint16_t) value;
+}
+static void omap3_mpu_wdt_write32(void *opaque, target_phys_addr_t addr,
+                                  uint32_t value)
+{
+    omap3_wdt_write32(opaque, addr, value, OMAP3_MPU_WDT);
+}
+
+
+static CPUReadMemoryFunc *omap3_mpu_wdt_readfn[] = {
+    omap_badwidth_read32,
+    omap3_mpu_wdt_read16,
+    omap3_mpu_wdt_read32,
+};
+
+static CPUWriteMemoryFunc *omap3_mpu_wdt_writefn[] = {
+    omap_badwidth_write32,
+    omap3_mpu_wdt_write16,
+    omap3_mpu_wdt_write32,
+};
+
+
+
+static void omap3_mpu_wdt_timer_tick(void *opaque)
+{
+    struct omap3_wdt_s *wdt_timer = (struct omap3_wdt_s *) opaque;
+
+    /*TODO:Sent reset pulse to PRCM */
+    wdt_timer->wcrr = wdt_timer->wldr;
+
+    /*after overflow, generate the new wdt_timer->rate */
+    wdt_timer->pre = wdt_timer->wclr & (1 << 5);
+    wdt_timer->ptv = (wdt_timer->wclr & 0x1c) >> 2;
+    wdt_timer->rate =
+        omap_clk_getrate(wdt_timer->clk) >> (wdt_timer->pre ? wdt_timer->
+                                             ptv : 0);
+
+    wdt_timer->time = qemu_get_clock(vm_clock);
+    omap3_wdt_timer_update(wdt_timer);
+}
+
+static struct omap3_wdt_s *omap3_mpu_wdt_init(struct omap_target_agent_s *ta,
+                                              qemu_irq irq, omap_clk fclk,
+                                              omap_clk iclk,
+                                              struct omap_mpu_state_s *mpu)
+{
+    int iomemtype;
+    struct omap3_wdt_s *s = (struct omap3_wdt_s *) qemu_mallocz(sizeof(*s));
+
+    s->irq = irq;
+    s->clk = fclk;
+    s->timer = qemu_new_timer(vm_clock, omap3_mpu_wdt_timer_tick, s);
+
+    omap3_wdt_reset(s, OMAP3_MPU_WDT);
+    if (irq != NULL)
+        omap3_wdt_clk_setup(s);
+
+    iomemtype = l4_register_io_memory(0, omap3_mpu_wdt_readfn,
+                                      omap3_mpu_wdt_writefn, s);
+    omap_l4_attach(ta, 0, iomemtype);
+
+    return s;
+
+}
+
+
+/*dummy system control module*/
+struct omap3_scm_s
+{
+    struct omap_mpu_state_s *mpu;
+
+       uint8 interface[48];           /*0x4800 2000*/
+       uint8 padconfs[576];         /*0x4800 2030*/
+       uint32 general[228];            /*0x4800 2270*/
+       uint8 mem_wkup[1024];     /*0x4800 2600*/
+       uint8 padconfs_wkup[84]; /*0x4800 2a00*/
+       uint32 general_wkup[8];    /*0x4800 2a60*/
+};
+
+#define PADCONFS_VALUE(wakeup0,wakeup1,offmode0,offmode1, \
+                                               inputenable0,inputenable1,pupd0,pupd1,muxmode0,muxmode1,offset) \
+       do { \
+                *(padconfs+offset/4) = (wakeup0 <<14)|(offmode0<<9)|(inputenable0<<8)|(pupd0<<3)|(muxmode0); \
+                *(padconfs+offset/4) |= (wakeup1 <<30)|(offmode1<<25)|(inputenable1<<24)|(pupd1<<19)|(muxmode1<<16); \
+} while (0)
+
+
+static void omap3_scm_reset(struct omap3_scm_s *s)
+{
+        uint32 * padconfs;
+    padconfs = (uint32 *)(s->padconfs);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x0);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x4);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x8);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0xc);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x10);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x14);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x18);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x1c);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x20);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x24);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x28);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x2c);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x30);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x34);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x38);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x3c);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x40);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x44);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,1,0,7,0x48);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x4c);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x50);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x54);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x58);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,0,0x5c);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x60);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x64);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x68);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x6c);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x70);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x74);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x78);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x7c);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,3,0,7,0x80);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x84);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x88);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,0,7,0,0x8c);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x90);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x94);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,0,7,0,0x98);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,7,0x9c);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0xa0);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0xa4);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0xa8);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xac);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xb0);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xb4);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xb8);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xbc);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xc0);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xc4);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xc8);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xcc);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xd0);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xd4);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xd8);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xdc);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xe0);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xe4);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xe8);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xec);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xf0);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xf4);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xf8);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0xfc);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x100);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x104);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x108);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x10c);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x110);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x114);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x118);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x11c);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x120);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x124);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x128);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x12c);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x130);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x134);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x138);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x13c);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x140);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x144);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x148);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x14c);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x150);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x154);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x158);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x15c);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x160);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x164);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x168);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x16c);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x170);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x174);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x178);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x17c);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x180);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x184);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x188);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x18c);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x190);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x194);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x198);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,3,7,7,0x19c);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x1a0);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x1a4);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x1a8);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x1ac);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,1,7,7,0x1b0);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1b4);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1b8);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1bc);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c0);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c4);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c8);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1cc);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1d0);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1d4);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1d8);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1dc);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1e0);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1e4);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1e8);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1ec);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1f0);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1f4);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1f8);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1fc);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x200);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x204);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x208);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x20c);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x210);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x214);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x218);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x21c);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x220);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,1,0,0,0x224);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,1,0,0,0x228);
+    PADCONFS_VALUE(0,0,0,0,1,1,0,1,0,0,0x22c);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x230);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,7,7,0x234);
+
+
+       padconfs = (uint32 *)(s->general);
+       s->general[1] = 0x4000000;  /*0x4800 2274*/
+       s->general[0x1c] = 0x1;  /*0x4800 22e0*/
+       s->general[0x75] = 0x7fc0;  /*0x4800 2444*/
+       s->general[0x76] = 0xaa;  /*0x4800 2448*/
+       s->general[0x7c] = 0x2700;  /*0x4800 2460*/
+       s->general[0x7d] = 0x300000;  /*0x4800 2464*/
+       s->general[0x7e] = 0x300000;  /*0x4800 2468*/
+       s->general[0x81] = 0xffff;  /*0x4800 2474*/
+       s->general[0x82] = 0xffff;  /*0x4800 2478*/
+       s->general[0x83] = 0xffff;  /*0x4800 247c*/
+       s->general[0x84] = 0x6;  /*0x4800 2480*/
+       s->general[0x85] = 0xffffffff;  /*0x4800 2484*/
+       s->general[0x86] = 0xffff;  /*0x4800 2488*/
+       s->general[0x87] = 0xffff;  /*0x4800 248c*/
+       s->general[0x88] = 0x1;  /*0x4800 2490*/
+       s->general[0x8b] = 0xffffffff;  /*0x4800 249c*/
+       s->general[0x8c] = 0xffff;  /*0x4800 24a0*/
+       s->general[0x8e] = 0xffff;  /*0x4800 24a8*/
+       s->general[0x8f] = 0xffff;  /*0x4800 24ac*/
+       s->general[0x91] = 0xffff;  /*0x4800 24b4*/
+       s->general[0x92] = 0xffff;  /*0x4800 24b8*/
+       s->general[0xac] = 0x109;  /*0x4800 2520*/
+       s->general[0xb2] = 0xffff;  /*0x4800 2538*/
+       s->general[0xb3] = 0xffff;  /*0x4800 253c*/
+       s->general[0xb4] = 0xffff;  /*0x4800 2540*/
+       PADCONFS_VALUE(0,0,0,0,1,1,3,3,4,4,0x368);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,4,4,0x36c);
+    PADCONFS_VALUE(0,0,0,0,1,1,3,3,4,4,0x370);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x374);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x378);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x37c);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x380);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x384);
+    PADCONFS_VALUE(0,0,0,0,1,1,1,1,4,4,0x388);
+
+    
+
+       padconfs = (uint32 *)(s->padconfs_wkup);
+       PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x0);
+       PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x4);
+       PADCONFS_VALUE(0,0,0,0,1,1,3,0,0,0,0x8);
+       PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0xc);
+       PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x10);
+       PADCONFS_VALUE(0,0,0,0,1,1,0,0,0,0,0x14);
+       PADCONFS_VALUE(0,0,0,0,1,1,1,1,7,7,0x18);
+       PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x1c);
+       PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x20);
+       PADCONFS_VALUE(0,0,0,0,1,1,3,3,0,0,0x24);
+       PADCONFS_VALUE(0,0,0,0,1,1,1,1,0,0,0x2c);
+
+
+       s->general_wkup[0] = 0x66ff; /*0x4800 2A60*/
+           
+}
+
+static uint32_t omap3_scm_read8(void *opaque, target_phys_addr_t addr)
+{
+    struct omap3_scm_s *s = (struct omap3_scm_s *) opaque;
+    uint8_t* temp;
+       
+    switch (addr) {
+    case 0x00 ... 0x2f:
+        return s->interface[addr];
+    case 0x30 ... 0x26f:
+        return s->padconfs[addr-0x30];
+    case 0x270 ... 0x5ff:
+        temp = (uint8_t *)s->general;
+        return temp[addr-0x270];
+    case 0x600 ... 0x9ff:
+        return s->mem_wkup[addr-0x600];
+    case 0xa00 ... 0xa5f:
+        return s->padconfs_wkup[addr-0xa00];
+    case 0xa60 ... 0xa7f:
+        temp = (uint8_t *)s->general_wkup;
+        return temp[addr-0xa60];
+    /* case 0x2f0:
+        return s->control_status & 0xff;
+    case 0x2f1:
+        return (s->control_status & 0xff00) >> 8;
+    case 0x2f2:
+        return (s->control_status & 0xff0000) >> 16;
+    case 0x2f3:
+        return (s->control_status & 0xff000000) >> 24;    */
+       
+    default:
+        break;
+    }
+    printf("omap3_scm_read8 addr %x pc %x  \n", addr,cpu_single_env->regs[15] );
+    return 0;
+}
+
+static uint32_t omap3_scm_read16(void *opaque, target_phys_addr_t addr)
+{
+    uint32_t v;
+    v = omap3_scm_read8(opaque, addr);
+    v |= omap3_scm_read8(opaque, addr + 1) << 8;
+    return v;
+}
+
+static uint32_t omap3_scm_read32(void *opaque, target_phys_addr_t addr)
+{
+    uint32_t v;
+    v = omap3_scm_read8(opaque, addr);
+    v |= omap3_scm_read8(opaque, addr + 1) << 8;
+    v |= omap3_scm_read8(opaque, addr + 2) << 16;
+    v |= omap3_scm_read8(opaque, addr + 3) << 24;
+    return v;
+}
+
+static void omap3_scm_write8(void *opaque, target_phys_addr_t addr,
+                             uint32_t value)
+{
+    struct omap3_scm_s *s = (struct omap3_scm_s *) opaque;
+    uint8_t* temp;
+
+    switch (addr)
+    {
+    case 0x00 ... 0x2f:
+        s->interface[addr] = value;
+        break;
+    case 0x30 ... 0x26f:
+        s->padconfs[addr-0x30] = value;
+        break;
+    case 0x270 ... 0x5ff:
+        temp = (uint8_t *)s->general;
+        temp[addr-0x270] = value;
+        break;
+    case 0x600 ... 0x9ff:
+        s->mem_wkup[addr-0x600] = value;
+        break;
+    case 0xa00 ... 0xa5f:
+        s->padconfs_wkup[addr-0xa00] = value;
+        break;
+    case 0xa60 ... 0xa7f:
+        temp = (uint8_t *)s->general_wkup;
+        temp[addr-0xa60] = value;
+        break;
+    default:
+        /*we do not care scm write*/
+        printf("omap3_scm_write8 addr %x pc %x \n \n", addr,
+               cpu_single_env->regs[15] - 0x80008000 + 0x80e80000);
+        exit(1);
+        //break;
+    }
+}
+
+static void omap3_scm_write16(void *opaque, target_phys_addr_t addr,
+                              uint32_t value)
+{
+    omap3_scm_write8(opaque, addr + 0, (value) & 0xff);
+    omap3_scm_write8(opaque, addr + 1, (value >> 8) & 0xff);
+}
+
+static void omap3_scm_write32(void *opaque, target_phys_addr_t addr,
+                              uint32_t value)
+{
+    omap3_scm_write8(opaque, addr + 0, (value) & 0xff);
+    omap3_scm_write8(opaque, addr + 1, (value >> 8) & 0xff);
+    omap3_scm_write8(opaque, addr + 2, (value >> 16) & 0xff);
+    omap3_scm_write8(opaque, addr + 3, (value >> 24) & 0xff);
+}
+
+static CPUReadMemoryFunc *omap3_scm_readfn[] = {
+    omap3_scm_read8,
+    omap3_scm_read16,
+    omap3_scm_read32,
+};
+
+static CPUWriteMemoryFunc *omap3_scm_writefn[] = {
+    omap3_scm_write8,
+    omap3_scm_write16,
+    omap3_scm_write32,
+};
+
+static struct omap3_scm_s *omap3_scm_init(struct omap_target_agent_s *ta,
+                                          struct omap_mpu_state_s *mpu)
+{
+    int iomemtype;
+    struct omap3_scm_s *s = (struct omap3_scm_s *) qemu_mallocz(sizeof(*s));
+
+    s->mpu = mpu;
+
+    omap3_scm_reset(s);
+
+    iomemtype = l4_register_io_memory(0, omap3_scm_readfn,
+                                      omap3_scm_writefn, s);
+    omap_l4_attach(ta, 0, iomemtype);
+    
+    return s;
+}
+
+
+/*dummy port protection*/
+struct omap3_pm_s
+{
+    struct omap_mpu_state_s *mpu;
+
+    uint32_t l3_pm_rt_error_log;        /*0x6801 0020 */
+    uint32_t l3_pm_rt_control;  /*0x6801 0028 */
+    uint32_t l3_pm_rt_error_clear_single;       /*0x6801 0030 */
+    uint32_t l3_pm_rt_error_clear_multi;        /*0x6801 0038 */
+    uint32_t l3_pm_rt_req_info_permission[2];   /*0x6801 0048 + (0x20*i) */
+    uint32_t l3_pm_rt_read_permission[2];       /*0x6801 0050 + (0x20*i) */
+    uint32_t l3_pm_rt_write_permission[2];      /*0x6801 0058 + (0x20*i) */
+    uint32_t l3_pm_rt_addr_match[1];    /*0x6801 0060 + (0x20*k) */
+
+    uint32_t l3_pm_gpmc_error_log;      /*0x6801 2420 */
+    uint32_t l3_pm_gpmc_control;        /*0x6801 2428 */
+    uint32_t l3_pm_gpmc_error_clear_single;     /*0x6801 2430 */
+    uint32_t l3_pm_gpmc_error_clear_multi;      /*0x6801 2438 */
+    uint32_t l3_pm_gpmc_req_info_permission[8]; /*0x6801 2448 + (0x20*i) */
+    uint32_t l3_pm_gpmc_read_permission[8];     /*0x6801 2450 + (0x20*i) */
+    uint32_t l3_pm_gpmc_write_permission[8];    /*0x6801 2458 + (0x20*i) */
+    uint32_t l3_pm_gpmc_addr_match[7];  /*0x6801 2460 + (0x20*k) */
+
+    uint32_t l3_pm_ocmram_error_log;    /*0x6801 2820 */
+    uint32_t l3_pm_ocmram_control;      /*0x6801 2828 */
+    uint32_t l3_pm_ocmram_error_clear_single;   /*0x6801 2830 */
+    uint32_t l3_pm_ocmram_error_clear_multi;    /*0x6801 2838 */
+    uint32_t l3_pm_ocmram_req_info_permission[8];       /*0x6801 2848 + (0x20*i) */
+    uint32_t l3_pm_ocmram_read_permission[8];   /*0x6801 2850 + (0x20*i) */
+    uint32_t l3_pm_ocmram_write_permission[8];  /*0x6801 2858 + (0x20*i) */
+    uint32_t l3_pm_ocmram_addr_match[7];        /*0x6801 2860 + (0x20*k) */
+
+    uint32_t l3_pm_ocmrom_error_log;    /*0x6801 2c20 */
+    uint32_t l3_pm_ocmrom_control;      /*0x6801 2c28 */
+    uint32_t l3_pm_ocmrom_error_clear_single;   /*0x6801 2c30 */
+    uint32_t l3_pm_ocmrom_error_clear_multi;    /*0x6801 2c38 */
+    uint32_t l3_pm_ocmrom_req_info_permission[2];       /*0x6801 2c48 + (0x20*i) */
+    uint32_t l3_pm_ocmrom_read_permission[2];   /*0x6801 2c50 + (0x20*i) */
+    uint32_t l3_pm_ocmrom_write_permission[2];  /*0x6801 2c58 + (0x20*i) */
+    uint32_t l3_pm_ocmrom_addr_match[1];        /*0x6801 2c60 + (0x20*k) */
+
+    uint32_t l3_pm_mad2d_error_log;     /*0x6801 3020 */
+    uint32_t l3_pm_mad2d_control;       /*0x6801 3028 */
+    uint32_t l3_pm_mad2d_error_clear_single;    /*0x6801 3030 */
+    uint32_t l3_pm_mad2d_error_clear_multi;     /*0x6801 3038 */
+    uint32_t l3_pm_mad2d_req_info_permission[8];        /*0x6801 3048 + (0x20*i) */
+    uint32_t l3_pm_mad2d_read_permission[8];    /*0x6801 3050 + (0x20*i) */
+    uint32_t l3_pm_mad2d_write_permission[8];   /*0x6801 3058 + (0x20*i) */
+    uint32_t l3_pm_mad2d_addr_match[7]; /*0x6801 3060 + (0x20*k) */
+
+    uint32_t l3_pm_iva_error_log;       /*0x6801 4020 */
+    uint32_t l3_pm_iva_control; /*0x6801 4028 */
+    uint32_t l3_pm_iva_error_clear_single;      /*0x6801 4030 */
+    uint32_t l3_pm_iva_error_clear_multi;       /*0x6801 4038 */
+    uint32_t l3_pm_iva_req_info_permission[4];  /*0x6801 4048 + (0x20*i) */
+    uint32_t l3_pm_iva_read_permission[4];      /*0x6801 4050 + (0x20*i) */
+    uint32_t l3_pm_iva_write_permission[4];     /*0x6801 4058 + (0x20*i) */
+    uint32_t l3_pm_iva_addr_match[3];   /*0x6801 4060 + (0x20*k) */
+};
+
+static void omap3_pm_reset(struct omap3_pm_s *s)
+{
+    int i;
+
+    s->l3_pm_rt_control = 0x3000000;
+    s->l3_pm_gpmc_control = 0x3000000;
+    s->l3_pm_ocmram_control = 0x3000000;
+    s->l3_pm_ocmrom_control = 0x3000000;
+    s->l3_pm_mad2d_control = 0x3000000;
+    s->l3_pm_iva_control = 0x3000000;
+
+    s->l3_pm_rt_req_info_permission[0] = 0xffff;
+    s->l3_pm_rt_req_info_permission[1] = 0x0;
+    for (i = 3; i < 8; i++)
+        s->l3_pm_gpmc_req_info_permission[i] = 0xffff;
+    for (i = 1; i < 8; i++)
+        s->l3_pm_ocmram_req_info_permission[i] = 0xffff;
+    s->l3_pm_ocmrom_req_info_permission[1] = 0xffff;
+    for (i = 1; i < 8; i++)
+        s->l3_pm_mad2d_req_info_permission[i] = 0xffff;
+    for (i = 1; i < 4; i++)
+        s->l3_pm_iva_req_info_permission[i] = 0xffff;
+
+    s->l3_pm_rt_read_permission[0] = 0x1406;
+    s->l3_pm_rt_read_permission[1] = 0x1406;
+    s->l3_pm_rt_write_permission[0] = 0x1406;
+    s->l3_pm_rt_write_permission[1] = 0x1406;
+    for (i = 0; i < 8; i++)
+    {
+        s->l3_pm_gpmc_read_permission[i] = 0x563e;
+        s->l3_pm_gpmc_write_permission[i] = 0x563e;
+    }
+    for (i = 0; i < 8; i++)
+    {
+        s->l3_pm_ocmram_read_permission[i] = 0x5f3e;
+        s->l3_pm_ocmram_write_permission[i] = 0x5f3e;
+    }
+    for (i = 0; i < 2; i++)
+    {
+        s->l3_pm_ocmrom_read_permission[i] = 0x1002;
+        s->l3_pm_ocmrom_write_permission[i] = 0x1002;
+    }
+
+    for (i = 0; i < 8; i++)
+    {
+        s->l3_pm_mad2d_read_permission[i] = 0x5f1e;
+        s->l3_pm_mad2d_write_permission[i] = 0x5f1e;
+    }
+
+    for (i = 0; i < 4; i++)
+    {
+        s->l3_pm_iva_read_permission[i] = 0x140e;
+        s->l3_pm_iva_write_permission[i] = 0x140e;
+    }
+
+
+    s->l3_pm_rt_addr_match[0] = 0x10230;
+
+    s->l3_pm_gpmc_addr_match[0] = 0x10230;
+}
+
+static uint32_t omap3_pm_read8(void *opaque, target_phys_addr_t addr)
+{
+    //struct omap3_pm_s *s = (struct omap3_pm_s *) opaque;
+
+    switch (addr)
+    {
+    default:
+        printf("omap3_pm_read8 addr %x \n", addr);
+        exit(-1);
+    }
+}
+
+static uint32_t omap3_pm_read16(void *opaque, target_phys_addr_t addr)
+{
+    uint32_t v;
+    v = omap3_pm_read8(opaque, addr);
+    v |= omap3_pm_read8(opaque, addr + 1) << 8;
+    return v;
+}
+
+static uint32_t omap3_pm_read32(void *opaque, target_phys_addr_t addr)
+{
+    uint32_t v;
+    v = omap3_pm_read8(opaque, addr);
+    v |= omap3_pm_read8(opaque, addr + 1) << 8;
+    v |= omap3_pm_read8(opaque, addr + 2) << 16;
+    v |= omap3_pm_read8(opaque, addr + 3) << 24;
+    return v;
+}
+
+static void omap3_pm_write8(void *opaque, target_phys_addr_t addr,
+                            uint32_t value)
+{
+    struct omap3_pm_s *s = (struct omap3_pm_s *) opaque;
+    int i;
+
+    switch (addr)
+    {
+    case 0x48 ... 0x4b:
+    case 0x68 ... 0x6b:
+        i = (addr - 0x48) / 0x20;
+        s->l3_pm_rt_req_info_permission[i] &=
+            (~(0xff << ((addr - 0x48 - i * 0x20) * 8)));
+        s->l3_pm_rt_req_info_permission[i] |=
+            (value << (addr - 0x48 - i * 0x20) * 8);
+        break;
+    case 0x50 ... 0x53:
+    case 0x70 ... 0x73:
+        i = (addr - 0x50) / 0x20;
+        s->l3_pm_rt_read_permission[i] &=
+            (~(0xff << ((addr - 0x50 - i * 0x20) * 8)));
+        s->l3_pm_rt_read_permission[i] |=
+            (value << (addr - 0x50 - i * 0x20) * 8);
+        break;
+    case 0x58 ... 0x5b:
+    case 0x78 ... 0x7b:
+        i = (addr - 0x58) / 0x20;
+        s->l3_pm_rt_write_permission[i] &=
+            (~(0xff << ((addr - 0x58 - i * 0x20) * 8)));
+        s->l3_pm_rt_write_permission[i] |=
+            (value << (addr - 0x58 - i * 0x20) * 8);
+        break;
+    case 0x60 ... 0x63:
+        s->l3_pm_rt_addr_match[0] &= (~(0xff << ((addr - 0x60) * 8)));
+        s->l3_pm_rt_addr_match[0] |= (value << (addr - 0x60) * 8);
+        break;
+    case 0x2448 ... 0x244b:
+    case 0x2468 ... 0x246b:
+    case 0x2488 ... 0x248b:
+    case 0x24a8 ... 0x24ab:
+    case 0x24c8 ... 0x24cb:
+    case 0x24e8 ... 0x24eb:
+    case 0x2508 ... 0x250b:
+    case 0x2528 ... 0x252b:
+        i = (addr - 0x2448) / 0x20;
+        s->l3_pm_gpmc_req_info_permission[i] &=
+            (~(0xff << ((addr - 0x2448 - i * 0x20) * 8)));
+        s->l3_pm_gpmc_req_info_permission[i] |=
+            (value << (addr - 0x2448 - i * 0x20) * 8);
+        break;
+    case 0x2450 ... 0x2453:
+    case 0x2470 ... 0x2473:
+    case 0x2490 ... 0x2493:
+    case 0x24b0 ... 0x24b3:
+    case 0x24d0 ... 0x24d3:
+    case 0x24f0 ... 0x24f3:
+    case 0x2510 ... 0x2513:
+    case 0x2530 ... 0x2533:
+        i = (addr - 0x2450) / 0x20;
+        s->l3_pm_gpmc_read_permission[i] &=
+            (~(0xff << ((addr - 0x2450 - i * 0x20) * 8)));
+        s->l3_pm_gpmc_read_permission[i] |=
+            (value << (addr - 0x2450 - i * 0x20) * 8);
+        break;
+    case 0x2458 ... 0x245b:
+    case 0x2478 ... 0x247b:
+    case 0x2498 ... 0x249b:
+    case 0x24b8 ... 0x24bb:
+    case 0x24d8 ... 0x24db:
+    case 0x24f8 ... 0x24fb:
+    case 0x2518 ... 0x251b:
+    case 0x2538 ... 0x253b:
+        i = (addr - 0x2458) / 0x20;
+        s->l3_pm_gpmc_write_permission[i] &=
+            (~(0xff << ((addr - 0x2458 - i * 0x20) * 8)));
+        s->l3_pm_gpmc_write_permission[i] |=
+            (value << (addr - 0x2458 - i * 0x20) * 8);
+        break;
+    case 0x2848 ... 0x284b:
+    case 0x2868 ... 0x286b:
+    case 0x2888 ... 0x288b:
+    case 0x28a8 ... 0x28ab:
+    case 0x28c8 ... 0x28cb:
+    case 0x28e8 ... 0x28eb:
+    case 0x2908 ... 0x290b:
+    case 0x2928 ... 0x292b:
+        i = (addr - 0x2848) / 0x20;
+        s->l3_pm_ocmram_req_info_permission[i] &=
+            (~(0xff << ((addr - 0x2848 - i * 0x20) * 8)));
+        s->l3_pm_ocmram_req_info_permission[i] |=
+            (value << (addr - 0x2848 - i * 0x20) * 8);
+        break;
+    case 0x2850 ... 0x2853:
+    case 0x2870 ... 0x2873:
+    case 0x2890 ... 0x2893:
+    case 0x28b0 ... 0x28b3:
+    case 0x28d0 ... 0x28d3:
+    case 0x28f0 ... 0x28f3:
+    case 0x2910 ... 0x2913:
+    case 0x2930 ... 0x2933:
+        i = (addr - 0x2850) / 0x20;
+        s->l3_pm_ocmram_read_permission[i] &=
+            (~(0xff << ((addr - 0x2850 - i * 0x20) * 8)));
+        s->l3_pm_ocmram_read_permission[i] |=
+            (value << (addr - 0x2850 - i * 0x20) * 8);
+        break;
+    case 0x2858 ... 0x285b:
+    case 0x2878 ... 0x287b:
+    case 0x2898 ... 0x289b:
+    case 0x28b8 ... 0x28bb:
+    case 0x28d8 ... 0x28db:
+    case 0x28f8 ... 0x28fb:
+    case 0x2918 ... 0x291b:
+    case 0x2938 ... 0x293b:
+        i = (addr - 0x2858) / 0x20;
+        s->l3_pm_ocmram_write_permission[i] &=
+            (~(0xff << ((addr - 0x2858 - i * 0x20) * 8)));
+        s->l3_pm_ocmram_write_permission[i] |=
+            (value << (addr - 0x2858 - i * 0x20) * 8);
+        break;
+
+    case 0x2860 ... 0x2863:
+    case 0x2880 ... 0x2883:
+    case 0x28a0 ... 0x28a3:
+    case 0x28c0 ... 0x28c3:
+    case 0x28e0 ... 0x28e3:
+    case 0x2900 ... 0x2903:
+    case 0x2920 ... 0x2923:
+        i = (addr - 0x2860) / 0x20;
+        s->l3_pm_ocmram_addr_match[i] &=
+            (~(0xff << ((addr - 0x2860 - i * 0x20) * 8)));
+        s->l3_pm_ocmram_addr_match[i] |=
+            (value << (addr - 0x2860 - i * 0x20) * 8);
+        break;
+
+    case 0x4048 ... 0x404b:
+    case 0x4068 ... 0x406b:
+    case 0x4088 ... 0x408b:
+    case 0x40a8 ... 0x40ab:
+        i = (addr - 0x4048) / 0x20;
+        s->l3_pm_iva_req_info_permission[i] &=
+            (~(0xff << ((addr - 0x4048 - i * 0x20) * 8)));
+        s->l3_pm_iva_req_info_permission[i] |=
+            (value << (addr - 0x4048 - i * 0x20) * 8);
+        break;
+    case 0x4050 ... 0x4053:
+    case 0x4070 ... 0x4073:
+    case 0x4090 ... 0x4093:
+    case 0x40b0 ... 0x40b3:
+        i = (addr - 0x4050) / 0x20;
+        s->l3_pm_iva_read_permission[i] &=
+            (~(0xff << ((addr - 0x4050 - i * 0x20) * 8)));
+        s->l3_pm_iva_read_permission[i] |=
+            (value << (addr - 0x4050 - i * 0x20) * 8);
+        break;
+    case 0x4058 ... 0x405b:
+    case 0x4078 ... 0x407b:
+    case 0x4098 ... 0x409b:
+    case 0x40b8 ... 0x40bb:
+        i = (addr - 0x4058) / 0x20;
+        s->l3_pm_iva_write_permission[i] &=
+            (~(0xff << ((addr - 0x4058 - i * 0x20) * 8)));
+        s->l3_pm_iva_write_permission[i] |=
+            (value << (addr - 0x4058 - i * 0x20) * 8);
+        break;
+    default:
+        printf("omap3_pm_write8 addr %x \n", addr);
+        exit(-1);
+    }
+}
+
+static void omap3_pm_write16(void *opaque, target_phys_addr_t addr,
+                             uint32_t value)
+{
+    omap3_pm_write8(opaque, addr + 0, (value) & 0xff);
+    omap3_pm_write8(opaque, addr + 1, (value >> 8) & 0xff);
+}
+
+static void omap3_pm_write32(void *opaque, target_phys_addr_t addr,
+                             uint32_t value)
+{
+    omap3_pm_write8(opaque, addr + 0, (value) & 0xff);
+    omap3_pm_write8(opaque, addr + 1, (value >> 8) & 0xff);
+    omap3_pm_write8(opaque, addr + 2, (value >> 16) & 0xff);
+    omap3_pm_write8(opaque, addr + 3, (value >> 24) & 0xff);
+}
+
+static CPUReadMemoryFunc *omap3_pm_readfn[] = {
+    omap3_pm_read8,
+    omap3_pm_read16,
+    omap3_pm_read32,
+};
+
+static CPUWriteMemoryFunc *omap3_pm_writefn[] = {
+    omap3_pm_write8,
+    omap3_pm_write16,
+    omap3_pm_write32,
+};
+
+static struct omap3_pm_s *omap3_pm_init(struct omap_mpu_state_s *mpu)
+{
+    int iomemtype;
+    struct omap3_pm_s *s = (struct omap3_pm_s *) qemu_mallocz(sizeof(*s));
+
+    s->mpu = mpu;
+    //s->base = 0x68010000;
+    //s->size = 0x4400;
+
+    omap3_pm_reset(s);
+
+    iomemtype = cpu_register_io_memory(0, omap3_pm_readfn, omap3_pm_writefn, s);
+    cpu_register_physical_memory(0x68010000, 0x4400, iomemtype);
+
+    return s;
+}
+
+/*dummy SDRAM Memory Scheduler emulation*/
+struct omap3_sms_s
+{
+    struct omap_mpu_state_s *mpu;
+
+    uint32 sms_sysconfig;
+    uint32 sms_sysstatus;
+    uint32 sms_rg_att[8];
+    uint32 sms_rg_rdperm[8];
+    uint32 sms_rg_wrperm[8];
+    uint32 sms_rg_start[7];
+    uint32 sms_rg_end[7];
+    uint32 sms_security_control;
+    uint32 sms_class_arbiter0;
+    uint32 sms_class_arbiter1;
+    uint32 sms_class_arbiter2;
+    uint32 sms_interclass_arbiter;
+    uint32 sms_class_rotation[3];
+    uint32 sms_err_addr;
+    uint32 sms_err_type;
+    uint32 sms_pow_ctrl;
+    uint32 sms_rot_control[12];
+    uint32 sms_rot_size[12];
+    uint32 sms_rot_physical_ba[12];
+
+
+};
+
+static uint32_t omap3_sms_read32(void *opaque, target_phys_addr_t addr)
+{
+    struct omap3_sms_s *s = (struct omap3_sms_s *) opaque;
+
+    switch (addr)
+    {
+    case 0x10:
+       return s->sms_sysconfig;
+    case 0x14:
+       return s->sms_sysstatus;
+    case 0x48:
+    case 0x68:
+    case 0x88:
+    case 0xa8:
+    case 0xc8:
+    case 0xe8:
+    case 0x108:
+    case 0x128:
+       return s->sms_rg_att[(addr-0x48)/0x20];
+    case 0x50:
+    case 0x70:
+    case 0x90:
+    case 0xb0:
+    case 0xd0:
+    case 0xf0:
+    case 0x110:
+    case 0x130:
+       return s->sms_rg_rdperm[(addr-0x50)/0x20];
+    case 0x58:
+    case 0x78:
+    case 0x98:
+    case 0xb8:
+    case 0xd8:
+    case 0xf8:
+    case 0x118:
+       return s->sms_rg_wrperm[(addr-0x58)/0x20];
+    case 0x60:
+    case 0x80:
+    case 0xa0:
+    case 0xc0:
+    case 0xe0:
+    case 0x100:
+    case 0x120:
+       return s->sms_rg_start[(addr-0x60)/0x20];
+
+    case 0x64:
+    case 0x84:
+    case 0xa4:
+    case 0xc4:
+    case 0xe4:
+    case 0x104:
+    case 0x124:
+       return s->sms_rg_end[(addr-0x64)/0x20];
+    case 0x140:
+       return s->sms_security_control;
+    case 0x150:
+       return s->sms_class_arbiter0;
+       case 0x154:
+               return s->sms_class_arbiter1;
+       case 0x158:
+               return s->sms_class_arbiter2;
+       case 0x160:
+               return s->sms_interclass_arbiter;
+       case 0x164:
+       case 0x168:
+       case 0x16c:
+               return s->sms_class_rotation[(addr-0x164)/4];
+       case 0x170:
+               return s->sms_err_addr;
+       case 0x174:
+               return s->sms_err_type;
+       case 0x178:
+               return s->sms_pow_ctrl;
+       case 0x180:
+       case 0x190:
+       case 0x1a0:
+       case 0x1b0:
+       case 0x1c0:
+       case 0x1d0:
+       case 0x1e0:
+       case 0x1f0:
+       case 0x200:
+       case 0x210:
+       case 0x220:
+       case 0x230:
+               return s->sms_rot_control[(addr-0x180)/0x10];
+       case 0x184:
+       case 0x194:
+       case 0x1a4:
+       case 0x1b4:
+       case 0x1c4:
+       case 0x1d4:
+       case 0x1e4:
+       case 0x1f4:
+       case 0x204:
+       case 0x214:
+       case 0x224:
+       case 0x234:
+               return s->sms_rot_size[(addr-0x184)/0x10];
+
+       case 0x188:
+       case 0x198:
+       case 0x1a8:
+       case 0x1b8:
+       case 0x1c8:
+       case 0x1d8:
+       case 0x1e8:
+       case 0x1f8:
+       case 0x208:
+       case 0x218:
+       case 0x228:
+       case 0x238:
+               return s->sms_rot_size[(addr-0x188)/0x10];
+
+    default:
+        printf("omap3_sms_read32 addr %x \n", addr);
+        exit(-1);
+    }
+}
+
+static void omap3_sms_write32(void *opaque, target_phys_addr_t addr,
+                              uint32_t value)
+{
+    struct omap3_sms_s *s = (struct omap3_sms_s *) opaque;
+    //int i;
+
+    switch (addr)
+    {
+    case 0x14:
+       OMAP_RO_REG(addr);
+        return;
+    case 0x10:
+       s->sms_sysconfig = value & 0x1f;
+       break;
+    
+    case 0x48:
+    case 0x68:
+    case 0x88:
+    case 0xa8:
+    case 0xc8:
+    case 0xe8:
+    case 0x108:
+    case 0x128:
+       s->sms_rg_att[(addr-0x48)/0x20] = value;
+       break;
+    case 0x50:
+    case 0x70:
+    case 0x90:
+    case 0xb0:
+    case 0xd0:
+    case 0xf0:
+    case 0x110:
+    case 0x130:
+       s->sms_rg_rdperm[(addr-0x50)/0x20] = value&0xffff;
+       break;
+    case 0x58:
+    case 0x78:
+    case 0x98:
+    case 0xb8:
+    case 0xd8:
+    case 0xf8:
+    case 0x118:
+       s->sms_rg_wrperm[(addr-0x58)/0x20] = value&0xffff;
+       break;          
+    case 0x60:
+    case 0x80:
+    case 0xa0:
+    case 0xc0:
+    case 0xe0:
+    case 0x100:
+    case 0x120:
+       s->sms_rg_start[(addr-0x60)/0x20] = value;
+       break;
+    case 0x64:
+    case 0x84:
+    case 0xa4:
+    case 0xc4:
+    case 0xe4:
+    case 0x104:
+    case 0x124:
+       s->sms_rg_end[(addr-0x64)/0x20] = value;
+       break;
+    case 0x140:
+       s->sms_security_control = value &0xfffffff;
+       break;
+    case 0x150:
+       s->sms_class_arbiter0 = value;
+       break;
+       case 0x154:
+               s->sms_class_arbiter1 = value;
+               break;
+       case 0x158:
+               s->sms_class_arbiter2 = value;
+               break;
+       case 0x160:
+               s->sms_interclass_arbiter = value;
+               break;
+       case 0x164:
+       case 0x168:
+       case 0x16c:
+               s->sms_class_rotation[(addr-0x164)/4] = value;
+               break;
+       case 0x170:
+               s->sms_err_addr = value;
+               break;
+       case 0x174:
+               s->sms_err_type = value;
+               break;
+       case 0x178:
+               s->sms_pow_ctrl = value;
+               break;
+       case 0x180:
+       case 0x190:
+       case 0x1a0:
+       case 0x1b0:
+       case 0x1c0:
+       case 0x1d0:
+       case 0x1e0:
+       case 0x1f0:
+       case 0x200:
+       case 0x210:
+       case 0x220:
+       case 0x230:
+               s->sms_rot_control[(addr-0x180)/0x10] = value;
+               break;
+       case 0x184:
+       case 0x194:
+       case 0x1a4:
+       case 0x1b4:
+       case 0x1c4:
+       case 0x1d4:
+       case 0x1e4:
+       case 0x1f4:
+       case 0x204:
+       case 0x214:
+       case 0x224:
+       case 0x234:
+               s->sms_rot_size[(addr-0x184)/0x10] = value;
+               break;
+
+       case 0x188:
+       case 0x198:
+       case 0x1a8:
+       case 0x1b8:
+       case 0x1c8:
+       case 0x1d8:
+       case 0x1e8:
+       case 0x1f8:
+       case 0x208:
+       case 0x218:
+       case 0x228:
+       case 0x238:
+               s->sms_rot_size[(addr-0x188)/0x10] = value;   
+               break;
+       default:
+        printf("omap3_sms_write32 addr %x\n", addr);
+        exit(-1);
+    }
+}
+
+static CPUReadMemoryFunc *omap3_sms_readfn[] = {
+    omap_badwidth_read32,
+    omap_badwidth_read32,
+    omap3_sms_read32,
+};
+
+static CPUWriteMemoryFunc *omap3_sms_writefn[] = {
+    omap_badwidth_write32,
+    omap_badwidth_write32,
+    omap3_sms_write32,
+};
+
+static void omap3_sms_reset(struct omap3_sms_s *s)
+{
+       s->sms_sysconfig = 0x1;
+       s->sms_class_arbiter0 = 0x500000;
+       s->sms_class_arbiter1 = 0x500;
+       s->sms_class_arbiter2 = 0x55000;
+       s->sms_interclass_arbiter = 0x400040;
+       s->sms_class_rotation[0] = 0x1;
+       s->sms_class_rotation[1] = 0x1;
+       s->sms_class_rotation[2] = 0x1;
+       s->sms_pow_ctrl = 0x80;
+}
+
+static struct omap3_sms_s *omap3_sms_init(struct omap_mpu_state_s *mpu)
+{
+    int iomemtype;
+    struct omap3_sms_s *s = (struct omap3_sms_s *) qemu_mallocz(sizeof(*s));
+
+    s->mpu = mpu;
+
+    omap3_sms_reset(s);
+    
+    iomemtype = cpu_register_io_memory(0, omap3_sms_readfn,
+                                       omap3_sms_writefn, s);
+    cpu_register_physical_memory(0x6c000000, 0x10000, iomemtype);
+
+    return s;
+}
+
+static const struct dma_irq_map omap3_dma_irq_map[] = {
+    {0, OMAP_INT_35XX_SDMA_IRQ0},
+    {0, OMAP_INT_35XX_SDMA_IRQ1},
+    {0, OMAP_INT_35XX_SDMA_IRQ2},
+    {0, OMAP_INT_35XX_SDMA_IRQ3},
+};
+
+static int omap3_validate_addr(struct omap_mpu_state_s *s,
+                               target_phys_addr_t addr)
+{
+    return 1;
+}
+
+/*
+  set the kind of memory connected to GPMC that we are trying to boot form.
+  Uses SYS BOOT settings.
+*/
+void omap3_set_mem_type(struct omap_mpu_state_s *s,int bootfrom)
+{
+       switch (bootfrom)
+       {
+               case 0x0: /*GPMC_NOR*/
+                       s->omap3_scm->general[32] |= 7;
+                       break;
+               case 0x1: /*GPMC_NAND*/
+                       s->omap3_scm->general[32] |= 1;
+                       break;
+               case 0x2:
+                       s->omap3_scm->general[32] |= 8;
+                       break;
+               case 0x3:
+                       s->omap3_scm->general[32] |= 0;
+                       break;
+               case 0x4:
+                       s->omap3_scm->general[32] |= 17;
+                       break;
+               case 0x5:
+                       s->omap3_scm->general[32] |= 3;
+                       break;
+       }
+}
+
+void omap3_set_device_type(struct omap_mpu_state_s *s,int device_type)
+{
+       s->omap3_scm->general[32] |= (device_type & 0x7) << 8;
+}
+
+struct omap_mpu_state_s *omap3530_mpu_init(unsigned long sdram_size,
+                                           const char *core)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
+        qemu_mallocz(sizeof(struct omap_mpu_state_s));
+    ram_addr_t sram_base, q2_base;
+    qemu_irq *cpu_irq;
+    qemu_irq dma_irqs[4];
+    int i;
+    int sdindex;
+    //omap_clk gpio_clks[4];
+
+
+    s->mpu_model = omap3530;
+    s->env = cpu_init("cortex-a8-r2");
+    if (!s->env)
+    {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    s->sdram_size = sdram_size;
+    s->sram_size = OMAP3530_SRAM_SIZE;
+
+    sdindex = drive_get_index(IF_SD, 0, 0);
+    if (sdindex == -1) {
+        fprintf(stderr, "qemu: missing SecureDigital device\n");
+        exit(1);
+    }
+
+    /* Clocks */
+    omap_clk_init(s);
+
+    /* Memory-mapped stuff */
+
+    q2_base = qemu_ram_alloc(s->sdram_size);
+    cpu_register_physical_memory(OMAP3_Q2_BASE, s->sdram_size,
+                                 (q2_base | IO_MEM_RAM));
+    sram_base = qemu_ram_alloc(s->sram_size);
+    cpu_register_physical_memory(OMAP3_SRAM_BASE, s->sram_size,
+                                 (sram_base | IO_MEM_RAM));
+
+    s->l4 = omap_l4_init(OMAP3_L4_BASE, 
+                         sizeof(omap3_l4_agent_info) 
+                         / sizeof(struct omap_l4_agent_info_s));
+
+    cpu_irq = arm_pic_init_cpu(s->env);
+    s->ih[0] = omap2_inth_init(s, 0x48200000, 0x1000, 3, &s->irq[0],
+                               cpu_irq[ARM_PIC_CPU_IRQ],
+                               cpu_irq[ARM_PIC_CPU_FIQ], 
+                               omap_findclk(s, "omap3_mpu_intc_fclk"),
+                               omap_findclk(s, "omap3_mpu_intc_iclk"));
+
+    for (i = 0; i < 4; i++)
+        dma_irqs[i] =
+            s->irq[omap3_dma_irq_map[i].ih][omap3_dma_irq_map[i].intr];
+    s->dma = omap_dma4_init(0x48056000, dma_irqs, s, 256, 32,
+                            omap_findclk(s, "omap3_sdma_fclk"),
+                            omap_findclk(s, "omap3_sdma_iclk"));
+    s->port->addr_valid = omap3_validate_addr;
+
+
+    /* Register SDRAM and SRAM ports for fast DMA transfers.  */
+    soc_dma_port_add_mem_ram(s->dma, q2_base, OMAP2_Q2_BASE, s->sdram_size);
+    soc_dma_port_add_mem_ram(s->dma, sram_base, OMAP2_SRAM_BASE, s->sram_size);
+
+
+    s->omap3_cm = omap3_cm_init(omap3_l4ta_get(s->l4, L4A_CM), NULL, NULL, NULL, s);
+
+    s->omap3_prm = omap3_prm_init(omap3_l4ta_get(s->l4, L4A_PRM),
+                                  s->irq[0][OMAP_INT_35XX_PRCM_MPU_IRQ],
+                                  NULL, s);
+
+    s->omap3_mpu_wdt = omap3_mpu_wdt_init(omap3_l4ta_get(s->l4, L4A_WDTIMER2),
+                                          NULL,
+                                          omap_findclk(s, "omap3_wkup_32k_fclk"),
+                                          omap_findclk(s, "omap3_wkup_l4_iclk"),
+                                          s);
+
+    s->omap3_scm = omap3_scm_init(omap3_l4ta_get(s->l4, L4A_SCM), s);
+
+    s->omap3_pm = omap3_pm_init(s);
+    s->omap3_sms = omap3_sms_init(s);
+
+    s->gptimer[0] = omap_gp_timer_init(omap3_l4ta_get(s->l4, L4A_GPTIMER1),
+                                       s->irq[0][OMAP_INT_35XX_GPTIMER1],
+                                       omap_findclk(s, "omap3_gp1_fclk"),
+                                       omap_findclk(s, "omap3_wkup_l4_iclk"));
+    s->gptimer[1] = omap_gp_timer_init(omap3_l4ta_get(s->l4, L4A_GPTIMER2),
+                                       s->irq[0][OMAP_INT_35XX_GPTIMER2],
+                                       omap_findclk(s, "omap3_gp2_fclk"),
+                                       omap_findclk(s, "omap3_per_l4_iclk"));
+    s->gptimer[2] = omap_gp_timer_init(omap3_l4ta_get(s->l4, L4A_GPTIMER3),
+                                       s->irq[0][OMAP_INT_35XX_GPTIMER3],
+                                       omap_findclk(s, "omap3_gp3_fclk"),
+                                       omap_findclk(s, "omap3_per_l4_iclk"));
+    s->gptimer[3] = omap_gp_timer_init(omap3_l4ta_get(s->l4, L4A_GPTIMER4),
+                                       s->irq[0][OMAP_INT_35XX_GPTIMER4],
+                                       omap_findclk(s, "omap3_gp4_fclk"),
+                                       omap_findclk(s, "omap3_per_l4_iclk"));
+    s->gptimer[4] = omap_gp_timer_init(omap3_l4ta_get(s->l4, L4A_GPTIMER5),
+                                       s->irq[0][OMAP_INT_35XX_GPTIMER5],
+                                       omap_findclk(s, "omap3_gp5_fclk"),
+                                       omap_findclk(s, "omap3_per_l4_iclk"));
+    s->gptimer[5] = omap_gp_timer_init(omap3_l4ta_get(s->l4, L4A_GPTIMER6),
+                                       s->irq[0][OMAP_INT_35XX_GPTIMER6],
+                                       omap_findclk(s, "omap3_gp6_fclk"),
+                                       omap_findclk(s, "omap3_per_l4_iclk"));
+    s->gptimer[6] = omap_gp_timer_init(omap3_l4ta_get(s->l4, L4A_GPTIMER7),
+                                       s->irq[0][OMAP_INT_35XX_GPTIMER7],
+                                       omap_findclk(s, "omap3_gp7_fclk"),
+                                       omap_findclk(s, "omap3_per_l4_iclk"));
+    s->gptimer[7] = omap_gp_timer_init(omap3_l4ta_get(s->l4, L4A_GPTIMER8),
+                                       s->irq[0][OMAP_INT_35XX_GPTIMER8],
+                                       omap_findclk(s, "omap3_gp8_fclk"),
+                                       omap_findclk(s, "omap3_per_l4_iclk"));
+    s->gptimer[8] = omap_gp_timer_init(omap3_l4ta_get(s->l4, L4A_GPTIMER9),
+                                       s->irq[0][OMAP_INT_35XX_GPTIMER9],
+                                       omap_findclk(s, "omap3_gp9_fclk"),
+                                       omap_findclk(s, "omap3_per_l4_iclk"));
+    s->gptimer[9] = omap_gp_timer_init(omap3_l4ta_get(s->l4, L4A_GPTIMER10),
+                                       s->irq[0][OMAP_INT_35XX_GPTIMER10],
+                                       omap_findclk(s, "omap3_gp10_fclk"),
+                                       omap_findclk(s, "omap3_core_l4_iclk"));
+    s->gptimer[10] = omap_gp_timer_init(omap3_l4ta_get(s->l4, L4A_GPTIMER11),
+                                       s->irq[0][OMAP_INT_35XX_GPTIMER11],
+                                       omap_findclk(s, "omap3_gp12_fclk"),
+                                       omap_findclk(s, "omap3_core_l4_iclk"));
+    s->gptimer[11] = omap_gp_timer_init(omap3_l4ta_get(s->l4, L4A_GPTIMER12),
+                                        s->irq[0][OMAP_INT_35XX_GPTIMER12],
+                                        omap_findclk(s, "omap3_gp12_fclk"),
+                                        omap_findclk(s, "omap3_wkup_l4_iclk"));
+    
+       
+    omap_synctimer_init(omap3_l4ta_get(s->l4, L4A_32KTIMER), s,
+                        omap_findclk(s, "omap3_sys_32k"), NULL);
+
+    s->sdrc = omap_sdrc_init(0x6d000000);
+    
+    s->gpmc = omap_gpmc_init(s, 0x6e000000, s->irq[0][OMAP_INT_35XX_GPMC_IRQ]);
+    
+
+    s->uart[0] = omap2_uart_init(omap3_l4ta_get(s->l4, L4A_UART1),
+                                 s->irq[0][OMAP_INT_35XX_UART1_IRQ],
+                                 omap_findclk(s, "omap3_uart1_fclk"),
+                                 omap_findclk(s, "omap3_uart1_iclk"),
+                                 s->drq[OMAP35XX_DMA_UART1_TX],
+                                 s->drq[OMAP35XX_DMA_UART1_RX], serial_hds[0]);
+    s->uart[1] = omap2_uart_init(omap3_l4ta_get(s->l4, L4A_UART2),
+                                 s->irq[0][OMAP_INT_35XX_UART2_IRQ],
+                                 omap_findclk(s, "omap3_uart2_fclk"),
+                                 omap_findclk(s, "omap3_uart2_iclk"),
+                                 s->drq[OMAP35XX_DMA_UART2_TX],
+                                 s->drq[OMAP35XX_DMA_UART2_RX],
+                                 serial_hds[0] ? serial_hds[1] : 0);
+    s->uart[2] = omap2_uart_init(omap3_l4ta_get(s->l4, L4A_UART3),
+                                 s->irq[0][OMAP_INT_35XX_UART3_IRQ],
+                                 omap_findclk(s, "omap3_uart2_fclk"),
+                                 omap_findclk(s, "omap3_uart3_iclk"),
+                                 s->drq[OMAP35XX_DMA_UART3_TX],
+                                 s->drq[OMAP35XX_DMA_UART3_RX],
+                                 serial_hds[0]
+                                 && serial_hds[1] ? serial_hds[2] : 0);
+    
+    /*attach serial[0] to uart 2 for beagle board */
+    omap_uart_attach(s->uart[2], serial_hds[0]);
+
+    s->dss = omap_dss_init(omap3_l4ta_get(s->l4, L4A_DSS), 0x68005400, 
+                    s->irq[0][OMAP_INT_35XX_DSS_IRQ], s->drq[OMAP24XX_DMA_DSS],
+                   NULL,NULL,NULL,NULL,NULL,1);
+
+    //gpio_clks[0] = NULL;
+    //gpio_clks[1] = NULL;
+    //gpio_clks[2] = NULL;
+    //gpio_clks[3] = NULL;
+
+    s->gpif = omap3_gpif_init();
+    omap3_gpio_init(s, s->gpif ,omap3_l4ta_get(s->l4, L4A_GPIO1),
+                    &s->irq[0][OMAP_INT_35XX_GPIO_BANK1], 
+                    NULL,NULL,0);
+    omap3_gpio_init(s, s->gpif ,omap3_l4ta_get(s->l4, L4A_GPIO2),
+                    &s->irq[0][OMAP_INT_35XX_GPIO_BANK2], 
+                    NULL,NULL,1);
+    omap3_gpio_init(s, s->gpif ,omap3_l4ta_get(s->l4, L4A_GPIO3),
+                    &s->irq[0][OMAP_INT_35XX_GPIO_BANK3], 
+                    NULL,NULL,2);
+    omap3_gpio_init(s, s->gpif ,omap3_l4ta_get(s->l4, L4A_GPIO4),
+                    &s->irq[0][OMAP_INT_35XX_GPIO_BANK4], 
+                    NULL,NULL,3);
+    omap3_gpio_init(s, s->gpif ,omap3_l4ta_get(s->l4, L4A_GPIO5),
+                    &s->irq[0][OMAP_INT_35XX_GPIO_BANK5], 
+                    NULL,NULL,4);
+    omap3_gpio_init(s, s->gpif ,omap3_l4ta_get(s->l4, L4A_GPIO6),
+                    &s->irq[0][OMAP_INT_35XX_GPIO_BANK6], 
+                    NULL,NULL,5);
+
+    omap_tap_init(omap3_l4ta_get(s->l4, L4A_TAP), s);
+
+    s->omap3_mmc[0] = omap3_mmc_init(omap3_l4ta_get(s->l4, L4A_MMC1),
+                                     drives_table[sdindex].bdrv,
+                                     s->irq[0][OMAP_INT_35XX_MMC1_IRQ],
+                                     &s->drq[OMAP35XX_DMA_MMC1_TX],
+                                     omap_findclk(s, "omap3_mmc1_fclk"),
+                                     omap_findclk(s, "omap3_mmc1_iclk"));
+
+    s->omap3_mmc[1] = omap3_mmc_init(omap3_l4ta_get(s->l4, L4A_MMC2),
+                                     NULL,
+                                     s->irq[0][OMAP_INT_35XX_MMC2_IRQ],
+                                     &s->drq[OMAP35XX_DMA_MMC2_TX],
+                                     omap_findclk(s, "omap3_mmc2_fclk"),
+                                     omap_findclk(s, "omap3_mmc2_iclk"));
+
+    s->omap3_mmc[2] = omap3_mmc_init(omap3_l4ta_get(s->l4, L4A_MMC3),
+                                     NULL,
+                                     s->irq[0][OMAP_INT_35XX_MMC3_IRQ],
+                                     &s->drq[OMAP35XX_DMA_MMC3_TX],
+                                     omap_findclk(s, "omap3_mmc3_fclk"),
+                                     omap_findclk(s, "omap3_mmc3_iclk"));
+
+    s->i2c[0] = omap3_i2c_init(omap3_l4ta_get(s->l4, L4A_I2C1),
+                               s->irq[0][OMAP_INT_35XX_I2C1_IRQ],
+                               &s->drq[OMAP35XX_DMA_I2C1_TX],
+                               omap_findclk(s, "omap3_i2c1_fclk"),
+                               omap_findclk(s, "omap3_i2c1_iclk"),
+                               8);
+    s->i2c[1] = omap3_i2c_init(omap3_l4ta_get(s->l4, L4A_I2C2),
+                               s->irq[0][OMAP_INT_35XX_I2C2_IRQ],
+                               &s->drq[OMAP35XX_DMA_I2C2_TX],
+                               omap_findclk(s, "omap3_i2c2_fclk"),
+                               omap_findclk(s, "omap3_i2c2_iclk"),
+                               8);
+    s->i2c[2] = omap3_i2c_init(omap3_l4ta_get(s->l4, L4A_I2C3),
+                               s->irq[0][OMAP_INT_35XX_I2C3_IRQ],
+                               &s->drq[OMAP35XX_DMA_I2C3_TX],
+                               omap_findclk(s, "omap3_i2c3_fclk"),
+                               omap_findclk(s, "omap3_i2c3_iclk"),
+                               64);
+
+    return s;
+}
+
+
+static uint32_t omap3_get_le32(void *p)
+{
+    uint8_t *q = (uint8_t *)p;
+    uint32_t v;
+    v = q[3]; v <<= 8;
+    v |= q[2]; v <<= 8;
+    v |= q[1]; v <<= 8;
+    v |= q[0];
+    return v;
+}
+
+static uint32_t omap3_get_le16(void *p)
+{
+    uint8_t *q = (uint8_t *)p;
+    uint32_t v;
+    v = q[1]; v <<= 8;
+    v |= q[0];
+    return v;
+}
+
+/* returns ptr to matching dir entry / zero entry or 0 if unsuccessful */
+static uint8_t *omap3_scan_fat_dir_sector(uint8_t *s)
+{
+    int i;
+    
+    /* there are 0x10 items with 0x20 bytes per item */
+    for (i = 0x10; i--; s += 0x20) {
+        if (*s == 0xe5 || (s[0x0b] & 0x0f) == 0x0f) continue; /* erased/LFN */
+        if (!*s || !strncasecmp((void *)s, "mlo        ", 8+3)) return s;
+    }
+    return 0;
+}
+
+struct omap3_fat_drv_s {
+    BlockDriverState *bs;
+    uint8_t ptype; // 12, 16, 32
+    uint64_t c0;   // physical byte offset for data cluster 0
+    uint64_t fat;  // physical byte offset for used FAT sector 0
+    uint32_t spc;  // sectors per cluster
+};
+
+/* returns cluster data in the buffer and next cluster chain number
+   or 0 if unsuccessful */
+static uint32_t omap3_read_fat_cluster(uint8_t *data,
+                                       struct omap3_fat_drv_s *drv,
+                                       uint32_t cl)
+{
+    uint8_t buf[ 4 ];
+    uint32_t len = drv->spc * 0x200; // number of bytes to read
+    
+    switch (drv->ptype) { /* check for EOF */
+        case 12: if (cl > 0xff0) return 0; break;
+        case 16: if (cl > 0xfff0) return 0; break;
+        case 32: if (cl > 0x0ffffff0) return 0; break;
+        default: return 0;
+    }
+    
+    if (bdrv_pread(drv->bs, 
+                   drv->c0 + ((drv->ptype == 32 ? cl - 2 : cl) * len),
+                   data, len) != len)
+        return 0;
+    
+    switch (drv->ptype) { /* determine next cluster # */
+        case 12:
+            fprintf(stderr, "%s: FAT12 parsing not implemented!\n",
+                    __FUNCTION__);
+            break;
+        case 16:
+            return (bdrv_pread(drv->bs, drv->fat + cl * 2, buf, 2) != 2)
+            ? 0 : omap3_get_le16(buf);
+        case 32:
+            return (bdrv_pread(drv->bs, drv->fat + cl * 4, buf, 4) != 4)
+            ? 0 : omap3_get_le32(buf) & 0x0fffffff;
+        default:
+            break;
+    }
+    return 0;
+}
+
+static int omap3_mmc_fat_boot(BlockDriverState *bs,
+                              uint8_t *sector,
+                              uint32_t pstart,
+                              struct omap_mpu_state_s *mpu)
+{
+    struct omap3_fat_drv_s drv;
+    uint32_t i, j, k, cluster0, fatsize, bootsize, rootsize;
+    uint32_t img_size, img_addr;
+    uint8_t *p, *q;
+    int result = 0;
+    
+    /* determine FAT type */
+    
+    drv.bs = bs;
+    fatsize = omap3_get_le16(sector + 0x16);
+    if (!fatsize) 
+        fatsize = omap3_get_le32(sector + 0x24);
+    bootsize = omap3_get_le16(sector + 0x0e);
+    cluster0 = bootsize + fatsize * sector[0x10];
+    rootsize = omap3_get_le16(sector + 0x11);
+    if (rootsize & 0x0f)
+        rootsize += 0x10;
+    rootsize >>= 4;
+    drv.spc = sector[0x0d];
+    i = omap3_get_le16(sector + 0x13);
+    if (!i)
+        i = omap3_get_le32(sector + 0x20);
+    i = (i - (cluster0 + rootsize)) / drv.spc;
+    drv.ptype = (i < 4085) ? 12 : (i < 65525) ? 16 : 32;
+    
+    /* search for boot loader file */
+    
+    drv.fat = (bootsize + pstart) * 0x200;
+    drv.c0 = (cluster0 + pstart) * 0x200;
+    if (drv.ptype == 32) {
+        i = omap3_get_le32(sector + 0x2c); /* first root cluster # */
+        j = omap3_get_le16(sector + 0x28);
+        if (j & 0x80)
+            drv.fat += (j & 0x0f) * fatsize * 0x200;
+        uint8_t *cluster = qemu_mallocz(drv.spc * 0x200);
+        for (p = 0; !p && (i = omap3_read_fat_cluster(cluster, &drv, i)); ) {
+            for (j = drv.spc, q=cluster; j-- & !p; q += 0x200)
+                p = omap3_scan_fat_dir_sector(q);
+            if (p) 
+                memcpy(sector, q - 0x200, 0x200); // save the sector
+        }
+        free(cluster);
+    } else { /* FAT12/16 */
+        for (i = rootsize, j = 0, p = 0; i-- && !p; j++) {
+            if (bdrv_pread(drv.bs, drv.c0 + j * 0x200, sector, 0x200) != 0x200)
+                break;
+            p = omap3_scan_fat_dir_sector(sector);
+        }
+    }
+    
+    if (p && *p) { // did we indeed find the file?
+        i = omap3_get_le16(p + 0x14);
+        i <<= 16;
+        i |= omap3_get_le16(p + 0x1a);
+        j = drv.spc * 0x200;
+        uint8 *data = qemu_mallocz(j);
+        if ((i = omap3_read_fat_cluster(data, &drv, i))) {
+            /* TODO: support HS device boot
+               for now only GP device is supported */
+            img_size = omap3_get_le32(data);
+            img_addr = omap3_get_le32(data + 4);
+            mpu->env->regs[15] = img_addr;
+            cpu_physical_memory_write(img_addr, data + 8, 
+                                      (k = (j - 8 >= img_size) ? img_size : j - 8));
+            for (img_addr += k, img_size -= k;
+                 img_size && (i = omap3_read_fat_cluster(data, &drv, i));
+                 img_addr += k, img_size -= k) {
+                cpu_physical_memory_write(img_addr, data, 
+                                          (k = (j >= img_size) ? img_size : j));
+            }
+            result = 1;
+        } else
+            fprintf(stderr, "%s: unable to read MLO file contents from SD card\n",
+                    __FUNCTION__);
+        free(data);
+    } else
+        fprintf(stderr, "%s: MLO file not found in the root directory\n",
+                __FUNCTION__);
+
+    return result;
+}
+
+static int omap3_mmc_raw_boot(BlockDriverState *bs,
+                              uint8_t *sector,
+                              struct omap_mpu_state_s *mpu)
+{
+    return 0;
+}
+
+/* returns non-zero if successful, zero if unsuccessful */
+int omap3_mmc_boot(struct omap_mpu_state_s *s)
+{
+    BlockDriverState *bs;
+    int sdindex = drive_get_index(IF_SD, 0, 0);
+    uint8_t sector[0x200], *p;
+    uint32_t pstart, i;
+    
+    /* very simple implementation, supports only two modes:
+       1. MBR partition table with an active FAT partition
+          and boot loader file (MLO) in its root directory, or
+       2. boot loader located on first sector */
+    if (sdindex >= 0) {
+        bs = drives_table[sdindex].bdrv;
+        if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
+            for (i = 0, p = sector + 0x1be; i < 4; i++, p += 0x10) 
+                if (p[0] == 0x80) break;
+            if (sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa /* signature */
+                && i < 4 /* active partition exists */
+                && (p[4] == 1 || p[4] == 4 || p[4] == 6 || p[4] == 11
+                    || p[4] == 12 || p[4] == 14 || p[4] == 15) /* FAT */
+                && bdrv_pread(bs, (pstart = omap3_get_le32(p + 8)) * 0x200,
+                              sector, 0x200) == 0x200
+                && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa)
+                return omap3_mmc_fat_boot(bs, sector, pstart, s);
+            else
+                return omap3_mmc_raw_boot(bs, sector, s);
+        }
+    }
+    return 0;
+}
+
diff --git a/hw/omap3_lcd_panel_template.h b/hw/omap3_lcd_panel_template.h
new file mode 100644 (file)
index 0000000..65fb70d
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * QEMU Epson S1D13744/S1D13745 templates
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * QEMU OMAP3 LCD Panel Emulation templates
+ *
+ * Copyright (c) 2008 yajin  <yajin@vm-kernel.org>
+ *
+ * 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 or
+ * (at your option) version 3 of the License.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+
+#define SKIP_PIXEL(to)         to += deststep
+#if DEPTH == 8
+# define PIXEL_TYPE            uint8_t
+# define COPY_PIXEL(to, from)  *to = from; SKIP_PIXEL(to)
+# define COPY_PIXEL1(to, from) *to ++ = from
+#elif DEPTH == 15 || DEPTH == 16
+# define PIXEL_TYPE            uint16_t
+# define COPY_PIXEL(to, from)  *to = from; SKIP_PIXEL(to)
+# define COPY_PIXEL1(to, from) *to ++ = from
+#elif DEPTH == 24
+# define PIXEL_TYPE            uint8_t
+# define COPY_PIXEL(to, from)  \
+    to[0] = from; to[1] = (from) >> 8; to[2] = (from) >> 16; SKIP_PIXEL(to)
+# define COPY_PIXEL1(to, from) \
+    *to ++ = from; *to ++ = (from) >> 8; *to ++ = (from) >> 16
+#elif DEPTH == 32
+# define PIXEL_TYPE            uint32_t
+# define COPY_PIXEL(to, from)  *to = from; SKIP_PIXEL(to)
+# define COPY_PIXEL1(to, from) *to ++ = from
+#else
+# error unknown bit depth
+#endif
+
+#ifdef WORDS_BIGENDIAN
+# define SWAP_WORDS    1
+#endif
+
+
+static void glue(omap3_lcd_panel_draw_line16_, DEPTH)(PIXEL_TYPE *dest,
+                const uint16_t *src, unsigned int width)
+{
+#if !defined(SWAP_WORDS) && DEPTH == 16
+    memcpy(dest, src, width);
+#else
+    uint16_t data;
+    unsigned int r, g, b;
+    const uint16_t *end = (const void *) src + width;
+    while (src < end) {
+        data = lduw_raw(src ++);
+        b = (data & 0x1f) << 3;
+        data >>= 5;
+        g = (data & 0x3f) << 2;
+        data >>= 6;
+        r = (data & 0x1f) << 3;
+        data >>= 5;
+        COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b));
+    }
+#endif
+}
+
+static void glue(omap3_lcd_panel_draw_line16_bgr_, DEPTH)(PIXEL_TYPE *dest,
+                                                      const uint16_t *src, unsigned int width)
+{
+#if !defined(SWAP_WORDS) && DEPTH == 16
+    memcpy(dest, src, width);
+#else
+    uint16_t data;
+    unsigned int r, g, b;
+    const uint16_t *end = (const void *) src + width;
+    while (src < end) {
+        data = lduw_raw(src ++);
+        r = (data & 0x1f) << 3;
+        data >>= 5;
+        g = (data & 0x3f) << 2;
+        data >>= 6;
+        b = (data & 0x1f) << 3;
+        data >>= 5;
+        COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b));
+    }
+#endif
+}
+
+
+/*
+LCD: 0x4: RGB 12      
+        0x5: ARGB16
+        0x6: RGB 16
+        0x8: RGB 24 (un-packed in 32-bit container)
+        0x9: RGB 24 (packed in 24-bit container)
+        0xc: ARGB32
+        0xd: RGBA32
+        0xe: RGBx 32 (24-bit RGB aligned on MSB of the 32-bit container)
+
+SDL:  8/16/24/32
+
+*/
+
+/* No rotation */
+static omap3_lcd_panel_fn_t glue(omap3_lcd_panel_draw_fn_, DEPTH)[0x10] = {
+    NULL,   /*0x0*/
+    NULL,   /*0x1*/
+    NULL,   /*0x2*/
+    NULL,   /*0x3*/
+    NULL,  /*0x4:RGB 12 */
+    NULL,  /*0x5: ARGB16 */
+    (omap3_lcd_panel_fn_t)glue(omap3_lcd_panel_draw_line16_, DEPTH),  /*0x6: RGB 16 */
+    NULL,  /*0x7*/
+    NULL,  /*0x8: RGB 24 (un-packed in 32-bit container) */
+    NULL,  /*0x9: RGB 24 (packed in 24-bit container) */
+    NULL,  /*0xa */
+    NULL,  /*0xb */
+    NULL,  /*0xc: ARGB32 */
+    NULL,  /*0xd: RGBA32 */
+    NULL,  /*0xe: RGBx 32 (24-bit RGB aligned on MSB of the 32-bit container) */
+    NULL,  /*0xf */
+};
+static omap3_lcd_panel_fn_t glue(omap3_lcd_panel_draw_fn_bgr_, DEPTH)[0x10] = {
+    NULL,   /*0x0*/
+    NULL,   /*0x1*/
+    NULL,   /*0x2*/
+    NULL,   /*0x3*/
+    NULL,  /*0x4:RGB 12 */
+    NULL,  /*0x5: ARGB16 */
+    (omap3_lcd_panel_fn_t)glue(omap3_lcd_panel_draw_line16_bgr_, DEPTH),  /*0x6: RGB 16 */
+    NULL,  /*0x7*/
+    NULL,  /*0x8: RGB 24 (un-packed in 32-bit container) */
+    NULL,  /*0x9: RGB 24 (packed in 24-bit container) */
+    NULL,  /*0xa */
+    NULL,  /*0xb */
+    NULL,  /*0xc: ARGB32 */
+    NULL,  /*0xd: RGBA32 */
+    NULL,  /*0xe: RGBx 32 (24-bit RGB aligned on MSB of the 32-bit container) */
+    NULL,  /*0xf */
+};
+
+/* 90deg, 180deg and 270deg rotation */
+static omap3_lcd_panel_fn_t glue(omap3_lcd_panel_draw_fn_r_, DEPTH)[0x10] = {
+    /* TODO */
+    [0 ... 0xf] = NULL,
+};
+static omap3_lcd_panel_fn_t glue(omap3_lcd_panel_draw_fn_r_bgr_, DEPTH)[0x10] = {
+    /* TODO */
+    [0 ... 0xf] = NULL,
+};
+
+#undef DEPTH
+#undef SKIP_PIXEL
+#undef COPY_PIXEL
+#undef COPY_PIXEL1
+#undef PIXEL_TYPE
+
+#undef SWAP_WORDS
+
diff --git a/hw/omap3_mmc.c b/hw/omap3_mmc.c
new file mode 100644 (file)
index 0000000..632e8d7
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+ * OMAP3 Multimedia Card/Secure Digital/Secure Digital I/O (MMC/SD/SDIO) Card Interface emulation
+ *
+ * Copyright (C) 2008 yajin  <yajin@vm-kernel.org>
+ *
+ * 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 or
+ * (at your option) version 3 of the License.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*The MMCHS of OMAP3530/3430 is different from OMAP1 and OAMP2420.*/
+
+
+#include "hw.h"
+#include "omap.h"
+#include "sd.h"
+
+
+#define MMC_DEBUG_LEVEL 0
+
+#if MMC_DEBUG_LEVEL>0
+#define TRACE(fmt,...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
+#if MMC_DEBUG_LEVEL>1
+#define TRACE2(...) TRACE(__VA_ARGS__)
+#else
+#define TRACE2(...)
+#endif
+#else
+#define TRACE(...)
+#define TRACE2(...)
+#endif
+
+struct omap3_mmc_s
+{
+    qemu_irq irq;
+    qemu_irq *dma;
+    qemu_irq coverswitch;
+    omap_clk clk;
+    SDState *card;
+
+    uint32_t sysconfig;         /*0x10 */
+    uint32_t sysstatus;         /*0x14 */
+    uint32_t csre;              /*0x24 */
+    uint32_t systest;           /*0x28 */
+    uint32_t con;               /*0x2c */
+    uint32_t pwcnt;             /*0x30 */
+    uint32_t blk;               /*0x104 */
+    uint32_t arg;               /*0x108 */
+    uint32_t cmd;               /*0x10c */
+    uint32_t rsp10;             /*0x110 */
+    uint32_t rsp32;             /*0x114 */
+    uint32_t rsp54;             /*0x118 */
+    uint32_t rsp76;             /*0x11c */
+    uint32_t data;              /*0x120 */
+    uint32_t pstate;            /*0x124 */
+    uint32_t hctl;              /*0x128 */
+    uint32_t sysctl;            /*0x12c */
+    uint32_t stat;              /*0x130 */
+    uint32_t ie;                /*0x134 */
+    uint32_t ise;               /*0x138 */
+    uint32_t ac12;              /*0x13c */
+    uint32_t capa;              /*0x140 */
+    uint32_t cur_capa;          /*0x148 */
+    uint32_t rev;               /*0x1fc */
+
+    /*for quick reference */
+    uint16_t blen_counter;
+    uint16_t nblk_counter;
+
+    uint32_t fifo[256];
+    int fifo_start;
+    int fifo_len;
+
+    int ddir;
+    int transfer;
+    
+    uint32_t stat_pending;
+};
+
+
+typedef enum
+{
+    sd_nore = 0,     /* no response */
+    sd_136_bits = 1, /* response length 136 bits */
+    sd_48_bits = 2,  /* response length 48 bits */
+    sd_48b_bits = 3, /* response length 48 bits with busy after response */
+} omap3_sd_rsp_type_t;
+
+int test=1;
+static void omap3_mmc_interrupts_update(struct omap3_mmc_s *s)
+{
+    qemu_set_irq(s->irq, !!((s->stat | s->stat_pending) & s->ie & s->ise));
+}
+
+static void omap3_mmc_fifolevel_update(struct omap3_mmc_s *host)
+{
+    TRACE2("ddir=%d, dma=%d, fifo_len=%d", host->ddir, host->cmd & 1, host->fifo_len);
+
+    if (host->cmd & 1) {             /* DE */
+        host->pstate &= ~0x0c00;     /* BRE | BWE */
+        host->stat_pending &= ~0x30; /* BRR | BWR */
+        host->stat &= ~0x30;         /* BRR | BWR */
+    }
+    
+    if (host->ddir && host->fifo_len) {
+        if (host->cmd & 1)               /* DE */
+            qemu_irq_raise(host->dma[1]);
+        else {
+            host->pstate |= 0x0800;      /* BRE */
+            host->stat_pending |= 0x20;  /* BRR */
+        }
+    } else {
+        host->pstate &= ~0x0800;         /* BRE */
+        host->stat_pending &= ~0x20;     /* BRR */
+        host->stat &= ~0x20;             /* BRR */
+        qemu_irq_lower(host->dma[1]);
+    }
+    
+    if (!host->ddir && !host->fifo_len) {
+        if (host->cmd & 1)               /* DE */
+            qemu_irq_raise(host->dma[0]);
+        else {
+            host->pstate |= 0x0400;      /* BWE */
+            host->stat_pending |= 0x10;  /* BWR */
+        }
+    } else {
+        host->pstate &= ~0x0400;     /* BWE */
+        host->stat_pending &= ~0x10; /* BWR */
+        host->stat &= ~0x10;         /* BWR */
+        qemu_irq_lower(host->dma[0]);
+    }
+}
+
+static void omap3_mmc_transfer(struct omap3_mmc_s *host)
+{
+    int i;
+
+    if (!host->transfer)
+        return;
+    
+    TRACE2("begin, %d bytes left to %s, %d bytes in FIFO", 
+           host->blen_counter,
+           host->ddir ? "receive" : "send",
+           host->fifo_len);
+    while (1) {
+        if (host->ddir) {
+            for (i = 0; i < 32 && host->blen_counter; i += 8, host->blen_counter--)
+                host->fifo[(host->fifo_start + host->fifo_len) & 0xff] |=
+                    sd_read_data(host->card) << i;
+            host->fifo_len++;
+        } else {
+            if (!host->fifo_len)
+                break;
+            for (i = 0; i < 32 && host->blen_counter; i += 8, host->blen_counter--)
+                sd_write_data(host->card, (host->fifo[host->fifo_start] >> i) & 0xff);
+            host->fifo_start++;
+            host->fifo_len--;
+            host->fifo_start &= 0xff;
+        }
+        if (!host->blen_counter) {
+            if (host->cmd & 2) /* BCE */
+                host->nblk_counter--;
+            TRACE2("block done, %d blocks left",
+                   (host->cmd & (1 << 5)) ? host->nblk_counter : 0);
+            host->blen_counter = host->blk & 0x7ff;
+            if (!(host->cmd & (1 << 5)) /* MSBS */
+                || !host->nblk_counter) {
+                host->nblk_counter = (host->blk >> 16) & 0xffff;
+                host->transfer = 0;
+                host->stat_pending |= 0x2; /* TC */
+                if (host->cmd & 4) { /* ACEN */
+                    fprintf(stderr, "%s: Auto CMD12 not implemented yet!\n", __FUNCTION__);
+                    /* TODO: issue CMD12 to SD controller */
+                }
+                break;
+            }
+        }
+    }
+    TRACE2("end, %d bytes in FIFO", host->fifo_len * 4);
+}
+
+static void omap3_mmc_command(struct omap3_mmc_s *host)
+{
+    uint32_t rspstatus, mask;
+    int rsplen, timeout;
+    struct sd_request_s request;
+    uint8_t response[16];
+    int cmd = (host->cmd >> 24) & 0x3f; /* INDX */
+
+    TRACE("%d type=%d arg=0x%08x", cmd, (host->cmd >> 22) & 3, host->arg);
+    
+    if ((host->con & 2) && !cmd) { /* INIT and CMD0 */
+        host->stat_pending |= 0x1;
+        host->pstate &= 0xfffffffe;
+        return;
+    }
+
+    if (host->cmd & (1 << 21)) { /* DP */
+        host->fifo_start = 0;
+        host->fifo_len = 0;
+        host->transfer = 1;
+        host->ddir = (host->cmd >> 4) & 1;
+    } else
+        host->transfer = 0;
+
+    timeout = 0;
+    mask = 0;
+    rspstatus = 0;
+
+    request.cmd = cmd;
+    request.arg = host->arg;
+    request.crc = 0; /* FIXME */
+
+    rsplen = sd_do_command(host->card, &request, response);
+
+    switch ((host->cmd >> 16) & 3) { /* RSP_TYPE */
+        case sd_nore:
+            rsplen = 0;
+            break;
+        case sd_136_bits:
+            if (rsplen < 16) {
+                timeout = 1;
+                break;
+            }
+            rsplen = 16;
+            host->rsp76 = (response[0] << 24) | (response[1] << 16) |
+                (response[2] << 8) | (response[3] << 0);
+            host->rsp54 = (response[4] << 24) | (response[5] << 16) |
+                (response[6] << 8) | (response[7] << 0);
+            host->rsp32 = (response[8] << 24) | (response[9] << 16) |
+                (response[10] << 8) | (response[11] << 0);
+            host->rsp10 = (response[12] << 24) | (response[13] << 16) |
+                (response[14] << 8) | (response[15] << 0);
+            break;
+        case sd_48_bits:
+        case sd_48b_bits:
+            if (rsplen < 4) {
+                timeout = 1;
+                break;
+            }
+            rsplen = 4;
+            host->rsp10 = (response[0] << 24) | (response[1] << 16) |
+                (response[2] << 8) | (response[3] << 0);
+            switch (cmd) {
+                case 41: /* r3 */
+                case 8:  /* r7 */
+                    break;
+                case 3:  /* r6 */
+                    mask = 0xe00;
+                    rspstatus = (response[2] << 8) | response[3];
+                    break;
+                default:
+                    mask = OUT_OF_RANGE | ADDRESS_ERROR | BLOCK_LEN_ERROR |
+                        ERASE_SEQ_ERROR | ERASE_PARAM | WP_VIOLATION |
+                        LOCK_UNLOCK_FAILED | COM_CRC_ERROR | ILLEGAL_COMMAND |
+                        CARD_ECC_FAILED | CC_ERROR | SD_ERROR |
+                        CID_CSD_OVERWRITE | WP_ERASE_SKIP;
+                    rspstatus = (response[0] << 24) | (response[1] << 16) |
+                        (response[2] << 8) | (response[3] << 0);
+                    break;
+            }
+        default:
+            break;
+    }
+
+    switch ((host->cmd >> 22) & 3) { /* CMD_TYPE */
+        case 0: /* normal commands */
+            break;
+        case 1: /* with CMD52, "bus suspend" operation */
+            if (cmd == 52) {
+                fprintf(stderr, "%s: bus suspend operation not supported yet!\n", __FUNCTION__);
+            }
+            break;
+        case 2: /* with CMD52, "function select" operation */
+            if (cmd == 52) {
+                fprintf(stderr, "%s: function select operation not supported yet!\n", __FUNCTION__);
+            }
+            break;
+        case 3: /* with CMD12 or CMD52, "I/O Abort" command */
+            if (cmd == 12 || cmd == 52) {
+                fprintf(stderr, "%s: i/o abort command received\n", __FUNCTION__);
+                //host->fifo_start = 0;
+                //host->fifo_len = 0;
+                //host->transfer = 0;
+                host->pstate &= ~0x0c00;     /* BRE | BWE */
+                host->stat_pending &= ~0x30; /* BRR | BWR */
+                host->stat &= ~0x30;         /* BRR | BWR */
+                qemu_irq_lower(host->dma[0]);
+                qemu_irq_lower(host->dma[1]);
+                host->stat_pending |= 2;
+            }
+            break;
+        default:
+            break;
+    }
+    
+    if (rspstatus & mask & host->csre)
+        host->stat_pending |= 1 << 28;    /* CERR */
+    else {
+        host->stat &= ~(1 << 28);         /* CERR */
+        host->stat_pending &= ~(1 << 28); /* CERR */
+    }
+    host->stat_pending |= timeout ? (1 << 16) : 0x1; /* CTO : CC */
+    host->stat_pending &= host->ie; /* use only enabled signals */
+}
+
+static void omap3_mmc_reset(struct omap3_mmc_s *s)
+{
+    s->sysconfig = 0x00000015;
+    s->con       = 0x00000500;
+    s->pstate    = 0x00040000;
+    s->capa      = 0x00e10080;
+    s->rev       = 0x26000000;
+
+    s->fifo_start =0;
+    s->fifo_len =0;
+}
+
+static uint32_t omap3_mmc_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap3_mmc_s *s = (struct omap3_mmc_s *) opaque;
+    uint32_t i ;
+
+    switch (addr) {
+        case 0x10:
+            TRACE2("SYSCONFIG = %08x", s->sysconfig);
+            return s->sysconfig;
+        case 0x14:
+            TRACE2("SYSSTATUS = %08x", s->sysstatus | 0x1);
+            return s->sysstatus | 0x1; /*reset completed */
+        case 0x24:
+            TRACE2("CSRE = %08x", s->csre);
+            return s->csre;
+        case 0x28:
+            TRACE2("SYSTEST = %08x", s->systest);
+            return s->systest;
+        case 0x2c: /* MMCHS_CON */
+            TRACE2("CON = %08x", s->con);
+            return s->con;
+        case 0x30:
+            TRACE2("PWCNT = %08x", s->pwcnt);
+            return s->pwcnt;
+        case 0x104: /* MMCHS_BLK */
+            TRACE2("BLK = %08x", s->blk);
+            return s->blk;
+        case 0x108: /* MMCHS_ARG */
+            TRACE2("ARG = %08x", s->arg);
+            return s->arg;
+        case 0x10c:
+            TRACE2("CMD = %08x", s->cmd);
+            return s->cmd;
+        case 0x110:
+            TRACE2("RSP10 = %08x", s->rsp10);
+            return s->rsp10;
+        case 0x114:
+            TRACE2("RSP32 = %08x", s->rsp32);
+            return s->rsp32;
+        case 0x118:
+            TRACE2("RSP54 = %08x", s->rsp54);
+            return s->rsp54;
+        case 0x11c:
+            TRACE2("RSP76 = %08x", s->rsp76);
+            return s->rsp76;
+        case 0x120:
+            /*Read Data */
+#if MMC_DEBUG_LEVEL>0
+            if(s->cmd&1) TRACE("DMA read data, fifo_len=%d", s->fifo_len);
+#endif
+            i = s->fifo[s->fifo_start];
+            s->fifo[s->fifo_start] = 0;
+            if (s->fifo_len == 0) {
+                fprintf(stderr, "MMC: FIFO underrun\n");
+                return i;
+            }
+            s->fifo_start++;
+            s->fifo_len--;
+            s->fifo_start &= 255;
+            omap3_mmc_transfer(s);
+            omap3_mmc_fifolevel_update(s);
+            omap3_mmc_interrupts_update(s);
+            return i;
+        case 0x124: /* MMCHS_PSTATE */
+            TRACE2("PSTATE = %08x", s->pstate);
+            return s->pstate;
+        case 0x128:
+            TRACE2("HCTL = %08x", s->hctl);
+            return s->hctl;
+        case 0x12c: /* MMCHS_SYSCTL */
+            TRACE2("SYSCTL = %08x", s->sysctl);
+            return s->sysctl;
+        case 0x130: /* MMCHS_STAT */
+            s->stat |= s->stat_pending;
+            if (s->stat & 0xffff0000)
+                   s->stat |= 1 << 15;    /* ERRI */
+            else
+                   s->stat &= ~(1 << 15); /* ERRI */
+            s->stat_pending = 0;
+            TRACE2("STAT = %08x", s->stat);
+            return s->stat;
+        case 0x134:
+            TRACE2("IE = %08x", s->ie);
+            return s->ie;
+        case 0x138:
+            TRACE2("ISE = %08x", s->ise);
+            return s->ise;
+        case 0x13c:
+            TRACE2("AC12 = %08x", s->ac12);
+            return s->ac12;
+        case 0x140: /* MMCHS_CAPA */
+            TRACE2("CAPA = %08x", s->capa);
+            return s->capa;
+        case 0x148:
+            TRACE2("CUR_CAPA = %08x", s->cur_capa);
+            return s->cur_capa;
+        case 0x1fc:
+            TRACE2("REV = %08x", s->rev);
+            return s->rev;
+        default:
+            OMAP_BAD_REG(addr);
+            exit(-1);
+            return 0;
+    }
+}
+
+static void omap3_mmc_write(void *opaque, target_phys_addr_t addr,
+                            uint32_t value)
+{
+    struct omap3_mmc_s *s = (struct omap3_mmc_s *) opaque;
+    
+    switch (addr) {
+        case 0x014:
+        case 0x110:
+        case 0x114:
+        case 0x118:
+        case 0x11c:
+        case 0x124:
+        case 0x13c:
+        case 0x1fc:
+            OMAP_RO_REG(addr);
+            break;
+        case 0x010:
+            TRACE2("SYSCONFIG = %08x", value);
+            if (value & 2)
+                omap3_mmc_reset(s);
+            s->sysconfig = value & 0x31d;
+            break;
+        case 0x024:
+            TRACE2("CSRE = %08x", value);
+            s->csre = value;
+            break;
+        case 0x028:
+            TRACE2("SYSTEST = %08x", value);
+            s->systest = value;
+            break;
+        case 0x02c: /* MMCHS_CON */
+            TRACE2("CON = %08x", value);
+            if (value & 0x10) {
+                fprintf(stderr, "%s: SYSTEST mode is not supported\n", __FUNCTION__);
+                exit(-1);
+            }
+            if (value & 0x20) {
+                fprintf(stderr, "%s: 8-bit data width is not supported\n", __FUNCTION__);
+                exit(-1);
+            }
+            s->con = value & 0x1ffff;
+            break;
+        case 0x030:
+            TRACE2("PWCNT = %08x", value);
+            s->pwcnt = value;
+            break;
+        case 0x104: /* MMCHS_BLK */
+            TRACE2("BLK = %08x", value);
+            s->blk = value & 0xffff07ff;
+            s->blen_counter = value & 0x7ff;
+            s->nblk_counter = (value >> 16) & 0xffff;
+            break;
+        case 0x108: /* MMCHS_ARG */
+            TRACE2("ARG = %08x", value);
+            s->arg = value;
+            break;
+        case 0x10c: /* MMCHS_CMD */
+            TRACE2("CMD = %08x", value);
+            s->cmd = value & 0x3ffb0037;
+            omap3_mmc_command(s);
+            omap3_mmc_transfer(s);
+            omap3_mmc_fifolevel_update(s);
+            omap3_mmc_interrupts_update(s);
+            break;
+        case 0x120:
+            /*data */
+            if (s->fifo_len == 256) {
+                fprintf(stderr, "%s: FIFO overrun\n", __FUNCTION__);
+                break;
+            }
+            s->fifo[(s->fifo_start + s->fifo_len) & 255] = value;
+            s->fifo_len++;
+            omap3_mmc_transfer(s);
+            omap3_mmc_fifolevel_update(s);
+            omap3_mmc_interrupts_update(s);
+            break;
+        case 0x128: /* MMCHS_HCTL */
+            TRACE2("HCTL = %08x", value);
+            s->hctl = value & 0xf0f0f02;
+            break;
+        case 0x12c: /* MMCHS_SYSCTL */
+            TRACE2("SYSCTL = %08x", value);
+            if (value & 0x04000000) { /* SRD */
+                s->data    = 0;
+                s->pstate &= ~0x00000f06; /* BRE, BWE, RTA, WTA, DLA, DATI */
+                s->hctl   &= ~0x00030000; /* SGBR, CR */
+                s->stat   &= ~0x00000034; /* BRR, BWR, BGE */
+                s->stat_pending &= ~0x00000034;
+                s->fifo_start = 0;
+                s->fifo_len = 0;
+            }
+            if (value & 0x02000000) { /* SRC */
+                s->pstate &= ~0x00000001; /* CMDI */
+            }
+            if (value & 0x01000000) { /* SRA */
+                uint32_t capa = s->capa;
+                uint32_t cur_capa = s->cur_capa;
+                omap3_mmc_reset(s);
+                s->capa = capa;
+                s->cur_capa = cur_capa;
+            }
+            value = (value & ~2) | ((value & 1) << 1); /* copy ICE directly to ICS */
+            s->sysctl = value & 0x000fffc7;
+            break;
+        case 0x130:
+            TRACE2("STAT = %08x", value);
+            value = value & 0x317f0237;
+            s->stat &= ~value;
+            /* stat_pending is NOT cleared */
+            omap3_mmc_interrupts_update(s);
+            break;
+        case 0x134: /* MMCHS_IE */
+            TRACE2("IE = %08x", value);
+            if (!(s->con & 0x4000)) /* if CON:OBIE is clear, ignore write to OBI_ENABLE */
+                value = (value & ~0x200) | (s->ie & 0x200);
+            s->ie = value & 0x317f0337;
+            if (!(s->ie & 0x100)) {
+                s->stat &= ~0x100;
+                s->stat_pending &= ~0x100;
+            }
+            omap3_mmc_interrupts_update(s);
+            break;
+        case 0x138:
+            TRACE2("ISE = %08x", value);
+            s->ise = value & 0x317f0337;
+            omap3_mmc_interrupts_update(s);
+            break;
+        case 0x140: /* MMCHS_CAPA */
+            TRACE2("CAPA = %08x", value);
+            s->capa &= ~0x07000000;
+            s->capa |= value & 0x07000000;
+            break;
+        case 0x148:
+            TRACE2("CUR_CAPA = %08x", value);
+            s->cur_capa = value & 0xffffff;
+            break;
+        default:
+            OMAP_BAD_REG(addr);
+            exit(-1);
+    }
+}
+
+static CPUReadMemoryFunc *omap3_mmc_readfn[] = {
+    omap_badwidth_read32,
+    omap_badwidth_read32,
+    omap3_mmc_read,
+};
+
+static CPUWriteMemoryFunc *omap3_mmc_writefn[] = {
+    omap_badwidth_write32,
+    omap_badwidth_write32,
+    omap3_mmc_write,
+};
+
+static void omap3_mmc_enable(struct omap3_mmc_s *s, int enable)
+{
+    sd_enable(s->card, enable);
+}
+
+struct omap3_mmc_s *omap3_mmc_init(struct omap_target_agent_s *ta,
+                                   BlockDriverState * bd, qemu_irq irq,
+                                   qemu_irq dma[], omap_clk fclk, omap_clk iclk)
+{
+    int iomemtype;
+    struct omap3_mmc_s *s = (struct omap3_mmc_s *)
+        qemu_mallocz(sizeof(struct omap3_mmc_s));
+
+    s->irq = irq;
+    s->dma = dma;
+    s->clk = fclk;
+
+    omap3_mmc_reset(s);
+
+    iomemtype = l4_register_io_memory(0, omap3_mmc_readfn,
+                                      omap3_mmc_writefn, s);
+    omap_l4_attach(ta, 0, iomemtype);
+
+    /* Instantiate the storage */
+    if (bd!=NULL) {
+       s->card = sd_init(bd, 0);
+           omap3_mmc_enable(s,1);
+    }
+
+    return s;
+}
index 38b098e..82fa414 100644 (file)
@@ -36,6 +36,7 @@ struct clk {
 #define CLOCK_IN_OMAP242X      (1 << 14)
 #define CLOCK_IN_OMAP243X      (1 << 15)
 #define CLOCK_IN_OMAP343X      (1 << 16)
+#define CLOCK_IN_OMAP353X   (1 << 17)
     uint32_t flags;
     int id;
 
@@ -944,6 +945,506 @@ static struct clk omapctrl_clk = {
     .parent    = &core_l4_iclk,
 };
 
+/*OMAP3 Clocks*/
+
+static struct clk omap3_sys_32k = {
+    .name      = "omap3_sys_32k",
+    .rate      = 32768,
+    .flags     = CLOCK_IN_OMAP353X  | ALWAYS_ENABLED,
+};
+
+static struct clk omap3_sys_xtalin = {
+    .name      = "omap3_sys_xtalin",
+    .rate      = 26000000,
+    .flags     = CLOCK_IN_OMAP353X  | ALWAYS_ENABLED,
+};
+
+/*Is the altclk is enabled in beagle board?*/
+static struct clk omap3_sys_altclk = {
+    .name      = "omap3_sys_altclk",
+    .rate      = 13000000,
+    .flags     = CLOCK_IN_OMAP353X  ,
+};
+
+/*PRM*/
+static struct clk omap3_sys_clk = {
+    .name      = "omap3_sys_clk",
+    .flags     = CLOCK_IN_OMAP353X  | ALWAYS_ENABLED,
+    .parent = &omap3_sys_xtalin,
+};
+
+static struct clk omap3_32k_fclk = {
+    .name      = "omap3_32k_fclk",
+    .rate      = 32768,
+    .flags     = CLOCK_IN_OMAP353X  | ALWAYS_ENABLED,
+    .parent = &omap3_sys_32k,
+};
+
+/*DPLL3:
+ *     Input: SYS_CLK
+ *   Output:
+ *           DPLL3_M2_CLK  (CORE_CLK)
+ *           DPLL3_M2*2_CLK   (CORE*2_CLK)
+ *           EMULE_CORE_ALWON_CLK
+ */
+static struct clk omap3_core_clk = {
+    .name      = "omap3_core_clk",
+    .flags     = CLOCK_IN_OMAP353X | ALWAYS_ENABLED,
+    .parent    = &omap3_sys_clk,       
+};
+
+static struct clk omap3_core2_clk = {
+    .name      = "omap3_core2_clk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_sys_clk,       
+};
+
+static struct clk omap3_emu_core_alwon_clk = {
+    .name      = "omap3_emu_core_alwon_clk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_sys_clk,       
+};
+
+/*DPLL1 : it is for MPU
+ *    Input:
+ *           reference clock: SYS_CLK
+ *           bypass clock : CORE_CLK from dpll3
+ *    Output:
+ *           MPU_CLK (DPLL_CLK_M2)
+ */
+static struct clk omap3_mpu_clk = {
+    .name      = "omap3_mpu_clk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_core_clk,         /*between sys_clk and core_clk*/
+};
+
+/*DPLL2: it is for iva2*/
+static struct clk omap3_iva2_clk = {
+    .name      = "omap3_iva2_clk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_core_clk,         /*between sys_clk and core_clk*/
+};
+
+/* DPLL4:
+ *      INPUT: SYS_CLK
+ *      OUTPUT:
+ *              M2: 96M_FCLK
+ *              M3: TO TV(54M_FCLK)
+ *              M4: DSS1_ALWON_CLK
+ *              M5: CAM_CLK
+ *              M6: EMUL_PER_ALWON_CLK
+ */
+static struct clk omap3_96m_fclk = {
+    .name      = "omap3_96m_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_sys_clk,                  
+};
+
+static struct clk omap3_54m_fclk = {
+    .name      = "omap3_54m_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_sys_clk,           
+};
+
+static struct clk omap3_dss1_alwon_fclk = {
+    .name      = "omap3_dss1_alwon_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_sys_clk,           
+};
+
+static struct clk omap3_cam_mclk = {
+    .name      = "omap3_cam_mclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_sys_clk,           
+};
+static struct clk omap3_per_alwon_clk = {
+    .name      = "omap3_per_alwon_clk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_sys_clk,           
+};
+
+/* DPLL5:
+ *      INPUT: SYS_CLK
+ *      OUTPUT:
+ *              M2: 120M_FCLK
+ */
+static struct clk omap3_120m_fclk = {
+    .name      = "omap3_120m_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_sys_clk,        
+};
+
+/*CM*/
+static struct clk omap3_48m_fclk = {
+    .name      = "omap3_48m_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_96m_fclk,          /*omap3_96m_fclk and omap3_sys_altclk*/
+};
+
+static struct clk omap3_12m_fclk = {
+    .name      = "omap3_12m_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_48m_fclk,          /*omap3_48m_fclk and omap3_sys_altclk*/
+};
+
+/*Common interface clock*/
+/*   Input: core_clk
+ *   Output:
+ *           l3x2_iclk
+ *           l3_iclk
+ *           l4_iclk
+ *           rm_iclk
+ */
+static struct clk omap3_l3x2_iclk = {
+    .name      = "omap3_l3x2_iclk",
+    .flags     = CLOCK_IN_OMAP353X | ALWAYS_ENABLED,
+    .parent    = &omap3_core_clk,
+};
+
+static struct clk omap3_l3_iclk = {
+    .name      = "omap3_l3_iclk",
+    .flags     = CLOCK_IN_OMAP353X | ALWAYS_ENABLED,
+    .parent    = &omap3_core_clk,
+};
+
+static struct clk omap3_l4_iclk = {
+    .name      = "omap3_l4_iclk",
+    .flags     = CLOCK_IN_OMAP353X | ALWAYS_ENABLED,
+    .parent    = &omap3_l3_iclk,
+};
+static struct clk omap3_rm_iclk = {
+    .name      = "omap3_rm_iclk",
+    .flags     = CLOCK_IN_OMAP353X | ALWAYS_ENABLED,
+    .parent    = &omap3_l4_iclk,
+};
+
+/*Core power domain clock*/
+/*   Input: cm_sys_clk
+ *            cm_32k_clk
+ *            120m_fclk
+ *            96m_fclk
+ *            48m_fclk
+ *            12m_fclk
+ *            l3_iclk
+ *            l4_iclk
+ *   Output:
+ *           gp10_fclk
+ *           gp11_fclk
+ *           core_32k_fclk
+ *           cpefuse_fclk
+ *           core_120M_fclk
+ *           usbttl_sap_fclk
+ *           core_96m_fclk
+ *           core_48m_flck
+ *           core_12m_fclk
+ *           core_l3_iclk
+ *           security_l3_iclk
+ *           core_l4_iclk
+ *           security_l4_iclk2
+ */
+static struct clk omap3_gp10_fclk = {
+    .name      = "omap3_gp10_fclk",
+    .flags     = CLOCK_IN_OMAP353X,
+    .parent    = &omap3_32k_fclk,   /*omap3_32k_fclk and omap3_sys_clk*/
+};
+
+static struct clk omap3_gp11_fclk = {
+    .name      = "omap3_gp11_fclk",
+    .flags     = CLOCK_IN_OMAP353X,
+    .parent    = &omap3_32k_fclk,   /*omap3_32k_fclk and omap3_sys_clk*/
+};
+
+static struct clk omap3_core_32k_fclk = {
+    .name      = "omap3_core_32k_fclk",
+    .flags     = CLOCK_IN_OMAP353X,
+    .parent    = &omap3_32k_fclk, 
+};
+
+static struct clk omap3_cpefuse_fclk = {
+    .name      = "omap3_cpefuse_fclk",
+    .flags     = CLOCK_IN_OMAP353X,
+    .parent    = &omap3_sys_clk, 
+};
+
+static struct clk omap3_core_120m_fclk = {
+    .name      = "omap3_core_120m_fclk",
+    .flags     = CLOCK_IN_OMAP353X,
+    .parent    = &omap3_120m_fclk, 
+};
+
+static struct clk omap3_core_96m_fclk = {
+    .name      = "omap3_core_96m_fclk",
+    .flags     = CLOCK_IN_OMAP353X,
+    .parent    = &omap3_96m_fclk, 
+};
+
+static struct clk omap3_core_48m_fclk = {
+    .name      = "omap3_core_48m_fclk",
+    .flags     = CLOCK_IN_OMAP353X,
+    .parent    = &omap3_48m_fclk, 
+};
+
+static struct clk omap3_core_12m_fclk = {
+    .name      = "omap3_core_12m_fclk",
+    .flags     = CLOCK_IN_OMAP353X,
+    .parent    = &omap3_12m_fclk, 
+};
+
+static struct clk omap3_core_l3_iclk = {
+    .name      = "omap3_core_l3_iclk",
+    .flags     = CLOCK_IN_OMAP353X | ALWAYS_ENABLED,
+    .parent    = &omap3_l3_iclk, 
+};
+
+
+static struct clk omap3_core_l4_iclk = {
+    .name      = "omap3_core_l4_iclk",
+    .flags     = CLOCK_IN_OMAP353X | ALWAYS_ENABLED,
+    .parent    = &omap3_l4_iclk, 
+};
+
+/*WKUP Power Domain*/
+static struct clk omap3_wkup_32k_fclk = {
+    .name      = "omap3_wkup_32k_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_32k_fclk, 
+};
+
+static struct clk omap3_wkup_l4_iclk = {
+    .name      = "omap3_wkup_l4_iclk",
+    .flags     = CLOCK_IN_OMAP353X,
+    .enabled = 1,
+    .parent    = &omap3_sys_clk, 
+};
+
+static struct clk omap3_gp1_fclk = {
+    .name      = "omap3_gp1_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_32k_fclk,        /*omap3_32k_fclk and omap3_sys_clk*/
+};
+
+static struct clk omap3_gp12_fclk = {
+    .name      = "omap3_gp12_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_32k_fclk,        /*SECURE_32K_FCLK -> 32-kHz oscillator */
+};
+
+/*PER Power Domain clock*/
+/*gp2-gp9 timer*/
+static struct clk omap3_gp2_fclk = {
+    .name      = "omap3_gp2_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_32k_fclk,        /*omap3_32k_fclk and omap3_sys_clk*/
+};
+
+static struct clk omap3_gp3_fclk = {
+    .name      = "omap3_gp3_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_32k_fclk,        /*omap3_32k_fclk and omap3_sys_clk*/
+};
+
+static struct clk omap3_gp4_fclk = {
+    .name      = "omap3_gp4_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_32k_fclk,        /*omap3_32k_fclk and omap3_sys_clk*/
+};
+
+static struct clk omap3_gp5_fclk = {
+    .name      = "omap3_gp5_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_32k_fclk,        /*omap3_32k_fclk and omap3_sys_clk*/
+};
+
+static struct clk omap3_gp6_fclk = {
+    .name      = "omap3_gp6_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_32k_fclk,        /*omap3_32k_fclk and omap3_sys_clk*/
+};
+
+static struct clk omap3_gp7_fclk = {
+    .name      = "omap3_gp7_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_32k_fclk,        /*omap3_32k_fclk and omap3_sys_clk*/
+};
+
+static struct clk omap3_gp8_fclk = {
+    .name      = "omap3_gp8_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_32k_fclk,        /*omap3_32k_fclk and omap3_sys_clk*/
+};
+
+static struct clk omap3_gp9_fclk = {
+    .name      = "omap3_gp9_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_32k_fclk,        /*omap3_32k_fclk and omap3_sys_clk*/
+};
+
+static struct clk omap3_per_96m_fclk = {
+    .name      = "omap3_per_96m_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_96m_fclk,        
+};
+
+static struct clk omap3_per_48m_fclk = {
+    .name      = "omap3_per_48m_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_48m_fclk,        
+};
+
+static struct clk omap3_per_l4_iclk = {
+    .name      = "omap3_per_l4_iclk",
+    .flags     = CLOCK_IN_OMAP353X,
+    .enabled = 1,
+    .parent    = &omap3_l4_iclk, 
+};
+
+/*UART Clocks*/
+static struct clk omap3_uart1_fclk = {
+    .name      = "omap3_uart1_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_core_48m_fclk,        
+};
+
+static struct clk omap3_uart1_iclk = {
+    .name      = "omap3_uart1_iclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_core_l4_iclk,        
+};
+
+static struct clk omap3_uart2_fclk = {
+    .name      = "omap3_uart2_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_core_48m_fclk,        
+};
+
+static struct clk omap3_uart2_iclk = {
+    .name      = "omap3_uart2_iclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_core_l4_iclk,        
+};
+
+static struct clk omap3_uart3_fclk = {
+    .name      = "omap3_uart3_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_per_48m_fclk,        
+};
+
+static struct clk omap3_uart3_iclk = {
+    .name      = "omap3_uart3_iclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_core_l4_iclk,        
+};
+
+/*INTC Clock*/
+static struct clk omap3_mpu_intc_fclk = {
+    .name      = "omap3_mpu_intc_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .divisor = 2,
+    .parent    = &omap3_mpu_clk,        
+};
+
+static struct clk omap3_mpu_intc_iclk = {
+    .name      = "omap3_mpu_intc_iclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .divisor = 2,
+    .parent    = &omap3_mpu_clk,        
+};
+
+/*SDMA clock*/
+static struct clk omap3_sdma_fclk = {
+    .name      = "omap3_sdma_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_core_l3_iclk,        
+};
+
+static struct clk omap3_sdma_iclk = {
+    .name      = "omap3_sdma_iclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_core_l4_iclk,        
+};
+
+/*CLKOUT*/
+static struct clk omap3_sys_clkout2 = {
+    .name      = "omap3_sys_clkout2",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_core_clk,        /*CORE_CLK CM_SYS_CLK CM_96M_FCLK 54 MHz clock*/
+};
+
+/*MMC Clock*/
+static struct clk omap3_mmc1_fclk = {
+    .name      = "omap3_mmc1_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_per_96m_fclk,       
+};
+
+static struct clk omap3_mmc1_iclk = {
+    .name      = "omap3_mmc1_iclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_per_l4_iclk,       
+};
+
+static struct clk omap3_mmc2_fclk = {
+    .name      = "omap3_mmc2_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_per_96m_fclk,       
+};
+
+static struct clk omap3_mmc2_iclk = {
+    .name      = "omap3_mmc2_iclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_per_l4_iclk,       
+};
+
+static struct clk omap3_mmc3_fclk = {
+    .name      = "omap3_mmc3_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_per_96m_fclk,       
+};
+
+static struct clk omap3_mmc3_iclk = {
+    .name      = "omap3_mmc3_iclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_per_l4_iclk,       
+};
+
+/*I2C Clocls*/
+static struct clk omap3_i2c1_fclk = {
+    .name      = "omap3_i2c1_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_per_96m_fclk,       
+};
+
+static struct clk omap3_i2c1_iclk = {
+    .name      = "omap3_i2c1_iclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_core_l4_iclk,       
+};
+
+static struct clk omap3_i2c2_fclk = {
+    .name      = "omap3_i2c2_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_per_96m_fclk,       
+};
+
+static struct clk omap3_i2c2_iclk = {
+    .name      = "omap3_i2c2_iclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_core_l4_iclk,       
+};
+
+static struct clk omap3_i2c3_fclk = {
+    .name      = "omap3_i2c3_fclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_per_96m_fclk,       
+};
+
+static struct clk omap3_i2c3_iclk = {
+    .name      = "omap3_i2c3_iclk",
+    .flags     = CLOCK_IN_OMAP353X ,
+    .parent    = &omap3_core_l4_iclk,       
+};
+
+
 static struct clk *onchip_clks[] = {
     /* OMAP 1 */
 
@@ -1087,6 +1588,79 @@ static struct clk *onchip_clks[] = {
     &dss_l4_iclk,
     &omapctrl_clk,
 
+    /* OMAP 3*/
+
+    &omap3_sys_32k,
+    &omap3_sys_xtalin,
+    &omap3_sys_altclk,
+    &omap3_sys_clk,
+    &omap3_32k_fclk,
+    &omap3_core_clk,
+    &omap3_core2_clk,
+    &omap3_emu_core_alwon_clk,
+    &omap3_mpu_clk,
+    &omap3_iva2_clk,
+    &omap3_96m_fclk,
+    &omap3_54m_fclk,
+    &omap3_dss1_alwon_fclk,
+    &omap3_cam_mclk,
+    &omap3_per_alwon_clk,
+    &omap3_120m_fclk,
+    &omap3_48m_fclk,
+    &omap3_12m_fclk,
+    &omap3_l3x2_iclk,
+    &omap3_l3_iclk,
+    &omap3_l4_iclk,
+    &omap3_rm_iclk,
+    &omap3_gp10_fclk,
+    &omap3_gp11_fclk,
+    &omap3_core_32k_fclk,
+    &omap3_cpefuse_fclk,
+    &omap3_core_120m_fclk,
+    &omap3_core_96m_fclk,
+    &omap3_core_48m_fclk,
+    &omap3_core_12m_fclk,
+    &omap3_core_l3_iclk,
+    &omap3_core_l4_iclk,
+    &omap3_wkup_32k_fclk,
+    &omap3_wkup_l4_iclk,
+    &omap3_gp1_fclk,
+    &omap3_gp12_fclk,
+    &omap3_gp2_fclk,
+    &omap3_gp3_fclk,
+    &omap3_gp4_fclk,
+    &omap3_gp5_fclk,
+    &omap3_gp6_fclk,
+    &omap3_gp7_fclk,
+    &omap3_gp8_fclk,
+    &omap3_gp9_fclk,
+    &omap3_per_96m_fclk,
+    &omap3_per_48m_fclk,
+    &omap3_per_l4_iclk,
+    &omap3_uart1_fclk,
+    &omap3_uart1_iclk,
+    &omap3_uart2_fclk,
+    &omap3_uart2_iclk,
+    &omap3_uart3_fclk,
+    &omap3_uart3_iclk,
+    &omap3_mpu_intc_fclk,
+    &omap3_mpu_intc_iclk,
+    &omap3_sdma_fclk,
+    &omap3_sdma_iclk,
+    &omap3_sys_clkout2,
+    &omap3_mmc1_fclk,
+    &omap3_mmc1_iclk,
+    &omap3_mmc2_fclk,
+    &omap3_mmc2_iclk,
+    &omap3_mmc3_fclk,
+    &omap3_mmc3_iclk,
+    &omap3_i2c1_fclk,
+    &omap3_i2c1_iclk,
+    &omap3_i2c2_fclk,
+    &omap3_i2c2_iclk,
+    &omap3_i2c3_fclk,
+    &omap3_i2c3_iclk,
+
     0
 };
 
@@ -1248,6 +1822,8 @@ void omap_clk_init(struct omap_mpu_state_s *mpu)
         flag = CLOCK_IN_OMAP243X;
     else if (cpu_is_omap3430(mpu))
         flag = CLOCK_IN_OMAP243X;
+    else if (cpu_is_omap3530(mpu))
+        flag = CLOCK_IN_OMAP353X;
     else
         return;
 
index 6df3800..9937a68 100644 (file)
@@ -1825,7 +1825,7 @@ static uint32_t omap_dma4_read(void *opaque, target_phys_addr_t addr)
         return ch->color;
 
     default:
-        OMAP_BAD_REG(addr);
+        OMAP_BAD_REG(0x80 + chnum * 0x60 + addr);
         return 0;
     }
 }
@@ -1931,7 +1931,10 @@ static void omap_dma4_write(void *opaque, target_phys_addr_t addr,
         break;
 
     case 0x08: /* DMA4_CICR */
-        ch->interrupts = value & 0x09be;
+        if (cpu_class_omap3(s->mpu))
+            ch->interrupts = value & 0x1dbe;
+        else
+            ch->interrupts = value & 0x09be;
         break;
 
     case 0x0c: /* DMA4_CSR */
@@ -2010,11 +2013,11 @@ static void omap_dma4_write(void *opaque, target_phys_addr_t addr,
     case 0x38: /* DMA4_CDAC */
     case 0x3c: /* DMA4_CCEN */
     case 0x40: /* DMA4_CCFN */
-        OMAP_RO_REG(addr);
+        OMAP_RO_REG(0x80 + chnum * 0x60 + addr);
         break;
 
     default:
-        OMAP_BAD_REG(addr);
+        OMAP_BAD_REG(0x80 + chnum * 0x60 + addr);
     }
 }
 
index 67b2b02..f1ca109 100644 (file)
 #include "hw.h"
 #include "console.h"
 #include "omap.h"
+#include "qemu-common.h"
+#include "sysemu.h"
+#include "devices.h"
+#include "vga_int.h"
+#include "pixel_ops.h"
 
 struct omap_dss_s {
     qemu_irq irq;
@@ -29,16 +34,19 @@ struct omap_dss_s {
 
     int autoidle;
     int control;
+    uint32_t sdi_control;
     int enable;
 
     struct omap_dss_panel_s {
         int enable;
+        int active;
         int nx;
         int ny;
 
         int x;
         int y;
     } dig, lcd;
+    struct omap3_lcd_panel_s *omap_lcd_panel[2];
 
     struct {
         uint32_t idlemode;
@@ -60,6 +68,10 @@ struct omap_dss_s {
             int nx;
             int ny;
 
+            int rotation_flag;
+            int gfx_format;
+            int gfx_channel;
+            
             target_phys_addr_t addr[3];
 
             uint32_t attr;
@@ -88,6 +100,10 @@ struct omap_dss_s {
         uint16_t hsync;
         struct rfbi_chip_s *chip[2];
     } rfbi;
+    
+    struct {
+        uint32_t irqst;
+    } dsi;
 };
 
 static void omap_dispc_interrupt_update(struct omap_dss_s *s)
@@ -123,6 +139,7 @@ void omap_dss_reset(struct omap_dss_s *s)
 {
     s->autoidle = 0;
     s->control = 0;
+    s->sdi_control = 0;
     s->enable = 0;
 
     s->dig.enable = 0;
@@ -164,6 +181,8 @@ void omap_dss_reset(struct omap_dss_s *s)
     s->dispc.l[0].colinc = 1;
     s->dispc.l[0].wininc = 0;
 
+    s->dsi.irqst = 0;
+    
     omap_rfbi_reset(s);
     omap_dispc_interrupt_update(s);
 }
@@ -181,10 +200,17 @@ static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr)
 
     case 0x14: /* DSS_SYSSTATUS */
         return 1;                                              /* RESETDONE */
+            
+    case 0x18:  /* DSS_IRQSTATUS */
+        return ((s->dispc.irqst & s->dispc.irqen) ? 0x1 : 0x0)
+            | ((s->dsi.irqst) ? 0x2 : 0x0);
 
     case 0x40: /* DSS_CONTROL */
         return s->control;
 
+    case 0x44:  /* DSS_SDI_CONTROL */
+        return s->sdi_control;
+
     case 0x50: /* DSS_PSA_LCD_REG_1 */
     case 0x54: /* DSS_PSA_LCD_REG_2 */
     case 0x58: /* DSS_PSA_VIDEO_REG */
@@ -213,7 +239,7 @@ static void omap_diss_write(void *opaque, target_phys_addr_t addr,
     case 0x54: /* DSS_PSA_LCD_REG_2 */
     case 0x58: /* DSS_PSA_VIDEO_REG */
     case 0x5c: /* DSS_STATUS */
-        OMAP_RO_REG(addr);
+        OMAP_RO_REGV(addr, value);
         break;
 
     case 0x10: /* DSS_SYSCONFIG */
@@ -226,8 +252,13 @@ static void omap_diss_write(void *opaque, target_phys_addr_t addr,
         s->control = value & 0x3dd;
         break;
 
+    case 0x44: /* DSS_SDI_CONTROL */
+        s->sdi_control = value & 0x000ff80f;
+        break;
+    
     default:
-        OMAP_BAD_REG(addr);
+        OMAP_BAD_REGV(addr, value);
+        break;
     }
 }
 
@@ -249,7 +280,7 @@ static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr)
 
     switch (addr) {
     case 0x000:        /* DISPC_REVISION */
-        return 0x20;
+        return 0x20; // 0x30 in OMAP3
 
     case 0x010:        /* DISPC_SYSCONFIG */
         return s->dispc.idlemode;
@@ -369,6 +400,13 @@ static void omap_disc_write(void *opaque, target_phys_addr_t addr,
     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
 
     switch (addr) {
+    case 0x000: /* DISPC_REVISION */
+    case 0x014: /* DISPC_SYSSTATUS */
+    case 0x05c: /* DISPC_LINE_STATUS */
+    case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */
+        OMAP_RO_REGV(addr, value);
+        break;
+            
     case 0x010:        /* DISPC_SYSCONFIG */
         if (value & 2)                                         /* SOFTRESET */
             omap_dss_reset(s);
@@ -389,6 +427,7 @@ static void omap_disc_write(void *opaque, target_phys_addr_t addr,
         s->dispc.control = value & 0x07ff9fff;
         s->dig.enable = (value >> 1) & 1;
         s->lcd.enable = (value >> 0) & 1;
+        s->lcd.active = (value >> 5) & 1;
         if (value & (1 << 12))                 /* OVERLAY_OPTIMIZATION */
             if (~((s->dispc.l[1].attr | s->dispc.l[2].attr) & 1))
                  fprintf(stderr, "%s: Overlay Optimization when no overlay "
@@ -507,12 +546,15 @@ static void omap_disc_write(void *opaque, target_phys_addr_t addr,
         s->dispc.invalidate = 1;
         break;
     case 0x0a0:        /* DISPC_GFX_ATTRIBUTES */
-        s->dispc.l[0].attr = value & 0x7ff;
+        s->dispc.l[0].attr = value & 0xffff;
         if (value & (3 << 9))
             fprintf(stderr, "%s: Big-endian pixel format not supported\n",
                             __FUNCTION__);
         s->dispc.l[0].enable = value & 1;
         s->dispc.l[0].bpp = (value >> 1) & 0xf;
+        s->dispc.l[0].rotation_flag = (value >> 12) & 0x3;
+        s->dispc.l[0].gfx_format = (value >> 1) & 0xf;
+        s->dispc.l[0].gfx_channel = (value >> 8) & 0x1;
         s->dispc.invalidate = 1;
         break;
     case 0x0a4:        /* DISPC_GFX_FIFO_TRESHOLD */
@@ -566,7 +608,8 @@ static void omap_disc_write(void *opaque, target_phys_addr_t addr,
         break;
 
     default:
-        OMAP_BAD_REG(addr);
+        OMAP_BAD_REGV(addr, value);
+        break;
     }
 }
 
@@ -836,7 +879,8 @@ static void omap_rfbi_write(void *opaque, target_phys_addr_t addr,
         break;
 
     default:
-        OMAP_BAD_REG(addr);
+        OMAP_BAD_REGV(addr, value);
+        break;
     }
 }
 
@@ -955,7 +999,8 @@ static void omap_venc_write(void *opaque, target_phys_addr_t addr,
         break;
 
     default:
-        OMAP_BAD_REG(addr);
+        OMAP_BAD_REGV(addr, value);
+        break;
     }
 }
 
@@ -1005,7 +1050,8 @@ static void omap_im3_write(void *opaque, target_phys_addr_t addr,
         break;
 
     default:
-        OMAP_BAD_REG(addr);
+        OMAP_BAD_REGV(addr, value);
+        break;
     }
 }
 
@@ -1022,12 +1068,12 @@ static CPUWriteMemoryFunc *omap_im3_writefn[] = {
 };
 
 struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
-                target_phys_addr_t l3_base,
-                qemu_irq irq, qemu_irq drq,
-                omap_clk fck1, omap_clk fck2, omap_clk ck54m,
-                omap_clk ick1, omap_clk ick2)
+                                 target_phys_addr_t l3_base,
+                                 qemu_irq irq, qemu_irq drq,
+                                 omap_clk fck1, omap_clk fck2, omap_clk ck54m,
+                                 omap_clk ick1, omap_clk ick2, int region_base)
 {
-    int iomemtype[5];
+    int iomemtype[6];
     struct omap_dss_s *s = (struct omap_dss_s *)
             qemu_mallocz(sizeof(struct omap_dss_s));
 
@@ -1036,19 +1082,20 @@ struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
     omap_dss_reset(s);
 
     iomemtype[0] = l4_register_io_memory(0, omap_diss1_readfn,
-                    omap_diss1_writefn, s);
+                                         omap_diss1_writefn, s);
     iomemtype[1] = l4_register_io_memory(0, omap_disc1_readfn,
-                    omap_disc1_writefn, s);
+                                         omap_disc1_writefn, s);
     iomemtype[2] = l4_register_io_memory(0, omap_rfbi1_readfn,
-                    omap_rfbi1_writefn, s);
+                                         omap_rfbi1_writefn, s);
     iomemtype[3] = l4_register_io_memory(0, omap_venc1_readfn,
-                    omap_venc1_writefn, s);
+                                         omap_venc1_writefn, s);
     iomemtype[4] = cpu_register_io_memory(0, omap_im3_readfn,
-                    omap_im3_writefn, s);
-    omap_l4_attach(ta, 0, iomemtype[0]);
-    omap_l4_attach(ta, 1, iomemtype[1]);
-    omap_l4_attach(ta, 2, iomemtype[2]);
-    omap_l4_attach(ta, 3, iomemtype[3]);
+                                          omap_im3_writefn, s);
+    /* TODO: DSI */
+    omap_l4_attach(ta, region_base+0, iomemtype[0]);
+    omap_l4_attach(ta, region_base+1, iomemtype[1]);
+    omap_l4_attach(ta, region_base+2, iomemtype[2]);
+    omap_l4_attach(ta, region_base+3, iomemtype[3]);
     cpu_register_physical_memory(l3_base, 0x1000, iomemtype[4]);
 
 #if 0
@@ -1065,3 +1112,182 @@ void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip)
         cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
     s->rfbi.chip[cs] = chip;
 }
+
+void omap3_lcd_panel_attach(struct omap_dss_s *s, int cs, struct omap3_lcd_panel_s *lcd_panel)
+{
+    if (cs < 0 || cs > 1)
+        cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
+    s->omap_lcd_panel[cs] = lcd_panel;
+}
+
+/*omap3 lcd panel stuff*/
+
+/* Bytes(!) per pixel */
+static const int omap3_lcd_panel_bpp[0x10] = {
+    0,   /*0x0*/
+    0,   /*0x1*/
+    0,   /*0x2*/
+    0,   /*0x3*/
+    2,  /*0x4:RGB 12 */
+    2,  /*0x5: ARGB16 */
+    2,  /*0x6: RGB 16 */
+    0,  /*0x7*/
+    4,  /*0x8: RGB 24 (un-packed in 32-bit container) */
+    3,  /*0x9: RGB 24 (packed in 24-bit container) */
+    0,  /*0xa */
+    0,  /*0xb */
+    4,  /*0xc: ARGB32 */
+    4,  /*0xd: RGBA32 */
+    4,  /*0xe: RGBx 32 (24-bit RGB aligned on MSB of the 32-bit container) */
+    0,  /*0xf */
+};
+
+static inline void omap3_lcd_panel_invalidate_display(void *opaque) 
+{
+    struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *)opaque;
+    s->invalidate = 1;
+}
+
+static void omap3_lcd_panel_update_display(void *opaque)
+{
+    struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *)opaque;
+    struct omap_dss_s *dss = s->dss;
+    uint32_t lcd_width,lcd_height;
+    uint32_t graphic_width,graphic_height;
+    uint32_t start_x,start_y;
+    uint32_t lcd_Bpp,dss_Bpp;
+    uint32_t linesize,y;
+    uint32_t copy_width,copy_height;
+    uint8_t *src, *dest;
+
+    //printf("dss->lcd.active  %d dss->lcd.enable %d \n",dss->lcd.active,dss->lcd.enable);
+    if (!dss->lcd.active)
+        return;
+
+    /*check whether LCD is enabled*/
+    if (!dss->lcd.enable)
+        return;
+
+    if ((dss->dispc.control & (1 << 11)))                      /* RFBIMODE */
+        return;
+
+    if (dss->dispc.l[0].gfx_channel)                   /* 24 bit digital out */
+        return;
+
+    if (!(dss->dispc.l[0].rotation_flag)) {      /* rotation*/
+        s->line_fn = s->line_fn_tab[0][dss->dispc.l[0].gfx_format];
+    } else {
+        fprintf(stderr, "%s: rotation is not supported \n", __FUNCTION__);
+        exit(1);
+    }
+    if (!s->line_fn) {
+        fprintf(stderr, "%s:s->line_fn is NULL. Not supported gfx_format \n", __FUNCTION__);
+        exit(1);
+    }
+
+    /* Resolution */
+    lcd_width = dss->lcd.nx;
+    lcd_height = dss->lcd.ny;
+    graphic_width = dss->dispc.l[0].nx;
+    graphic_height = dss->dispc.l[0].ny;
+    start_x = dss->dispc.l[0].posx;
+    start_y = dss->dispc.l[0].posy;
+    //printf("lcd_width %d lcd_height %d \n",lcd_width,lcd_height);
+    //printf("graphic_width %d graphic_height %d \n",graphic_width,graphic_height);
+    //printf("start_x %d start_y %d \n",start_x,start_y);
+
+    if (lcd_width != ds_get_width(s->state) 
+        || lcd_height != ds_get_height(s->state)) {
+        qemu_console_resize(s->state, lcd_width, lcd_height);
+        dss->dispc.invalidate = 1;
+    }
+
+    /*if ((start_x+graphic_width)>lcd_width) {
+        fprintf(stderr, "%s: graphic window width(0x%x) > lcd width(0x%x) \n",__FUNCTION__,start_x+graphic_width,lcd_width );
+         exit(1);
+    }
+    if ((start_y+graphic_height)>lcd_height) {
+        fprintf(stderr, "%s: graphic window height(0x%x) > lcd height(0x%x) \n",__FUNCTION__,start_y+graphic_height,lcd_height);
+        exit(1);
+    }*/
+
+    /*use the rfbi function*/
+    src = (uint8_t *)omap_rfbi_get_buffer(dss);
+    dest = ds_get_data(s->state);
+    linesize = ds_get_linesize(s->state);
+
+    lcd_Bpp = omap3_lcd_panel_bpp[dss->dispc.l[0].gfx_format];
+    dss_Bpp = linesize/ds_get_width(s->state);
+
+    //printf("LCD BPP %d dss_bpp %d \n",lcd_Bpp,dss_Bpp);
+
+    dest += linesize*start_y;
+    dest += start_x*dss_Bpp;
+
+    if ((start_x+graphic_width)>lcd_width)
+        copy_width = lcd_width - start_x;
+    else
+       copy_width = graphic_width;
+    copy_height = lcd_height>graphic_height ? graphic_height:lcd_height;
+
+    for (y=start_y;y<copy_height;y++) {
+        s->line_fn(dest,src,copy_width*lcd_Bpp);
+        src += graphic_width*lcd_Bpp;
+        dest += linesize;
+    }
+
+    dpy_update(s->state, start_x, start_y, graphic_width, graphic_height);
+}
+
+/*omap lcd stuff*/
+#define DEPTH 8
+#include "omap3_lcd_panel_template.h"
+#define DEPTH 15
+#include "omap3_lcd_panel_template.h"
+#define DEPTH 16
+#include "omap3_lcd_panel_template.h"
+#define DEPTH 24
+#include "omap3_lcd_panel_template.h"
+#define DEPTH 32
+#include "omap3_lcd_panel_template.h"
+
+void *omap3_lcd_panel_init()
+{
+    struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *) qemu_mallocz(sizeof(*s));
+
+    s->state = graphic_console_init(omap3_lcd_panel_update_display,
+                                      omap3_lcd_panel_invalidate_display,
+                                      NULL, NULL, s);
+
+    switch (ds_get_bits_per_pixel(s->state)) {
+    case 0:
+        s->line_fn_tab[0] = s->line_fn_tab[1] =
+            qemu_mallocz(sizeof(omap3_lcd_panel_fn_t) * 0x10);
+        break;
+    case 8:
+        s->line_fn_tab[0] =  omap3_lcd_panel_draw_fn_8;
+        s->line_fn_tab[1] =  omap3_lcd_panel_draw_fn_r_8;
+        break;
+    case 15:
+        s->line_fn_tab[0] =  omap3_lcd_panel_draw_fn_15;
+        s->line_fn_tab[1] =  omap3_lcd_panel_draw_fn_r_15;
+        break;
+    case 16:
+        s->line_fn_tab[0] =  omap3_lcd_panel_draw_fn_16;
+        s->line_fn_tab[1] =  omap3_lcd_panel_draw_fn_r_16;
+        break;
+    case 24:
+        s->line_fn_tab[0] =  omap3_lcd_panel_draw_fn_24;
+        s->line_fn_tab[1] =  omap3_lcd_panel_draw_fn_r_24;
+        break;
+    case 32:
+        s->line_fn_tab[0] =  omap3_lcd_panel_draw_fn_32;
+        s->line_fn_tab[1] =  omap3_lcd_panel_draw_fn_r_32;
+        break;
+    default:
+        fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
+        exit(1);
+    }
+
+    return s;
+}
index 258730b..47660e0 100644 (file)
 struct omap_i2c_s {
     qemu_irq irq;
     qemu_irq drq[2];
-    i2c_slave slave;
+    i2c_slave slave[4];
     i2c_bus *bus;
 
     uint8_t revision;
-    uint8_t mask;
+    uint16_t mask;
     uint16_t stat;
+    uint16_t we;
     uint16_t dma;
     uint16_t count;
     int count_cur;
-    uint32_t fifo;
-    int rxlen;
-    int txlen;
+    uint16_t sysc;
     uint16_t control;
-    uint16_t addr[2];
+    uint16_t own_addr[4];
+    uint16_t slave_addr;
+    uint8_t sblock;
     uint8_t divider;
-    uint8_t times[2];
+    uint16_t times[2];
     uint16_t test;
+    int rxlen;
+    int txlen;
+    int fifosize;
+    uint8_t fifo[64];
 };
 
 #define OMAP2_INTR_REV 0x34
 #define OMAP2_GC_REV   0x34
+#define OMAP3_INTR_REV  0x3c
+
+//#define I2C_DEBUG
+#ifdef I2C_DEBUG
+#define TRACE(fmt, ...) fprintf(stderr, "%s " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
+#else
+#define TRACE(...)
+#endif
 
 static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
 {
+    TRACE("IRQ=%04x,RDRQ=%d,XDRQ=%d", 
+          s->stat & s->mask,
+          ((s->dma >> 15 ) & 1) & ((s->stat >> 3) & 1),
+          ((s->dma >> 7 ) & 1 )& ((s->stat >> 4 ) & 1));
     qemu_set_irq(s->irq, s->stat & s->mask);
-    if ((s->dma >> 15) & 1)                                    /* RDMA_EN */
-        qemu_set_irq(s->drq[0], (s->stat >> 3) & 1);           /* RRDY */
-    if ((s->dma >> 7) & 1)                                     /* XDMA_EN */
-        qemu_set_irq(s->drq[1], (s->stat >> 4) & 1);           /* XRDY */
+    if ((s->dma >> 15) & 1)                          /* RDMA_EN */
+        qemu_set_irq(s->drq[0], (s->stat >> 3) & 1); /* RRDY */
+    if ((s->dma >> 7) & 1)                           /* XDMA_EN */
+        qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */
 }
 
 /* These are only stubs now.  */
 static void omap_i2c_event(i2c_slave *i2c, enum i2c_event event)
 {
-    struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
-
-    if ((~s->control >> 15) & 1)                               /* I2C_EN */
-        return;
-
-    switch (event) {
-    case I2C_START_SEND:
-    case I2C_START_RECV:
-        s->stat |= 1 << 9;                                     /* AAS */
-        break;
-    case I2C_FINISH:
-        s->stat |= 1 << 2;                                     /* ARDY */
-        break;
-    case I2C_NACK:
-        s->stat |= 1 << 1;                                     /* NACK */
-        break;
-    }
-
-    omap_i2c_interrupts_update(s);
+    fprintf(stderr, "%s: I^2C slave mode not supported\n", __FUNCTION__);
+    
+    /* code below is broken, i2c_slave CANNOT be cast to omap_i2c_s! */
+     
+    //struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
+    // 
+    //if ((~s->control >> 15) & 1)                             /* I2C_EN */
+    //    return;
+    //
+    //switch (event) {
+    //    case I2C_START_SEND:
+    //    case I2C_START_RECV:
+    //        s->stat |= 1 << 9;                                       /* AAS */
+    //        break;
+    //    case I2C_FINISH:
+    //        s->stat |= 1 << 2;                                       /* ARDY */
+    //        break;
+    //    case I2C_NACK:
+    //        s->stat |= 1 << 1;                                       /* NACK */
+    //        break;
+    //    default:
+    //        break;
+    //}
+    //
+    //omap_i2c_interrupts_update(s);
 }
 
 static int omap_i2c_rx(i2c_slave *i2c)
 {
-    struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
-    uint8_t ret = 0;
-
-    if ((~s->control >> 15) & 1)                               /* I2C_EN */
-        return -1;
-
-    if (s->txlen)
-        ret = s->fifo >> ((-- s->txlen) << 3) & 0xff;
-    else
-        s->stat |= 1 << 10;                                    /* XUDF */
-    s->stat |= 1 << 4;                                         /* XRDY */
-
-    omap_i2c_interrupts_update(s);
-    return ret;
+    fprintf(stderr, "%s: I^2C slave mode not supported\n", __FUNCTION__);
+    return 0;
+    
+    /* code below is broken, i2c_slave CANNOT be cast to omap_i2c_s! */
+    
+    //struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
+    //uint8_t ret = 0;
+    //
+    //if ((~s->control >> 15) & 1)                             /* I2C_EN */
+    //    return -1;
+    //
+    //if (s->rxlen < s->txlen)
+    //    ret = s->fifo[s->rxlen++];
+    //else
+    //    s->stat |= 1 << 10;                                  /* XUDF */
+    //s->stat |= 1 << 4;                                               /* XRDY */
+    //
+    //omap_i2c_interrupts_update(s);
+    //return ret;
 }
 
 static int omap_i2c_tx(i2c_slave *i2c, uint8_t data)
 {
-    struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
-
-    if ((~s->control >> 15) & 1)                               /* I2C_EN */
-        return 1;
-
-    if (s->rxlen < 4)
-        s->fifo |= data << ((s->rxlen ++) << 3);
-    else
-        s->stat |= 1 << 11;                                    /* ROVR */
-    s->stat |= 1 << 3;                                         /* RRDY */
-
-    omap_i2c_interrupts_update(s);
+    fprintf(stderr, "%s: I^2C slave mode not supported\n", __FUNCTION__);
     return 1;
+    
+    /* code below is broken, i2c_slave CANNOT be cast to omap_i2c_s! */
+    
+    //struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
+    //
+    //if ((~s->control >> 15) & 1)                             /* I2C_EN */
+    //    return 1;
+    //
+    //if (s->txlen < s->fifosize)
+    //    s->fifo[s->txlen++] = data;
+    //else
+    //    s->stat |= 1 << 11;                                  /* ROVR */
+    //s->stat |= 1 << 3;                                               /* RRDY */
+    //
+    //omap_i2c_interrupts_update(s);
+    //return 1;
 }
 
 static void omap_i2c_fifo_run(struct omap_i2c_s *s)
 {
-    int ack = 1;
+    int ack = 1, i;
 
     if (!i2c_bus_busy(s->bus))
         return;
@@ -128,58 +161,78 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s)
             s->count_cur = s->count;
             s->txlen = 0;
         } else if ((s->control >> 9) & 1) {                    /* TRX */
-            while (ack && s->txlen)
-                ack = (i2c_send(s->bus,
-                                        (s->fifo >> ((-- s->txlen) << 3)) &
-                                        0xff) >= 0);
+            for (i = 0; ack && i < s->txlen; i++)
+                ack = (i2c_send(s->bus, s->fifo[i]) >= 0);
+            s->txlen = 0;
             s->stat |= 1 << 4;                                 /* XRDY */
         } else {
-            while (s->rxlen < 4)
-                s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
+            for (i = 0; i < 4; i++)
+                s->fifo[i] = i2c_recv(s->bus);
+            s->rxlen = 4;
             s->stat |= 1 << 3;                                 /* RRDY */
         }
     } else {
-        if ((s->control >> 9) & 1) {                           /* TRX */
-            while (ack && s->count_cur && s->txlen) {
-                ack = (i2c_send(s->bus,
-                                        (s->fifo >> ((-- s->txlen) << 3)) &
-                                        0xff) >= 0);
-                s->count_cur --;
-            }
-            if (ack && s->count_cur)
-                s->stat |= 1 << 4;                             /* XRDY */
-            else
-                s->stat &= ~(1 << 4);                          /* XRDY */
-            if (!s->count_cur) {
-                s->stat |= 1 << 2;                             /* ARDY */
-                s->control &= ~(1 << 10);                      /* MST */
+        if ((s->control >> 9) & 1) {                /* TRX */
+            TRACE("master transmit, count_cur=%d, txlen=%d", s->count_cur, s->txlen);
+            /* this implementation actually always transfers everything
+               in the FIFO if acknowledged by the slave; thus a situation
+               where we would set XDR status never really happens */
+            for (i = 0; ack && s->count_cur && i < s->txlen; i++, s->count_cur--)
+                ack = (i2c_send(s->bus, s->fifo[i]) >= 0);
+            s->txlen -= i;
+            if (s->txlen) /* happens only when NACK has been received */
+                memmove(s->fifo, s->fifo + i, s->txlen);
+            s->stat &= ~0x4410;                     /* XDR | XUDF | XRDY */
+            if (ack && s->count_cur) {              /* send more? */
+                /* we know that FIFO is empty */
+                s->stat |= 1 << 10;                 /* XUDF */
+                if (s->revision < OMAP3_INTR_REV)
+                    s->stat |= 1 << 4;              /* XRDY */
+                else {
+                    if (s->count_cur > (s->dma & 0x3f)) /* XTRSH */
+                        s->stat |= 1 << 4;          /* XRDY */
+                    else
+                        s->stat |= 1 << 14;         /* XDR */
+                }
             }
-        } else {
-            while (s->count_cur && s->rxlen < 4) {
-                s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
-                s->count_cur --;
+            if (!s->count_cur)                      /* everything sent? */
+                s->stat |= 1 << 2;                  /* ARDY */
+        } else {                                           /* !TRX */
+            TRACE("master receive");
+            for (; s->count_cur && s->rxlen < s->fifosize; s->count_cur--) {
+                i = i2c_recv(s->bus);
+                if (i < 0) break; /* stop receiving if nothing to receive */
+                s->fifo[s->rxlen++] = (uint8_t)(i & 0xff);
+                TRACE("received fifo[%02x] = %02x", s->rxlen - 1, s->fifo[s->rxlen - 1]);
             }
-            if (s->rxlen)
-                s->stat |= 1 << 3;                             /* RRDY */
-            else
-                s->stat &= ~(1 << 3);                          /* RRDY */
+            s->stat &= ~((1 << 3) | (1 << 13));            /* RRDY | RDR */
+            if (s->rxlen) {
+                if (s->revision < OMAP3_INTR_REV)
+                    s->stat |= 1 << 3;                     /* RRDY */
+                else {
+                    if (s->rxlen > ((s->dma >> 8) & 0x3f)) /* RTRSH */
+                        s->stat |= 1 << 3;                 /* RRDY */
+                    else
+                        s->stat |= 1 << 13;                /* RDR */
+                }
+            } else if (!s->count_cur && (s->control & 2))  /* STP */
+                s->stat |= 1 << 2;                         /* ARDY */
         }
         if (!s->count_cur) {
-            if ((s->control >> 1) & 1) {                       /* STP */
+            TRACE("no more data to transmit/receive");
+            if ((s->control >> 1) & 1) {   /* STP */
                 i2c_end_transfer(s->bus);
-                s->control &= ~(1 << 1);                       /* STP */
+                s->control &= ~0x0602;     /* MST | TRX | STP */
                 s->count_cur = s->count;
                 s->txlen = 0;
-            } else {
-                s->stat |= 1 << 2;                             /* ARDY */
-                s->control &= ~(1 << 10);                      /* MST */
-            }
+            } 
         }
     }
 
-    s->stat |= (!ack) << 1;                                    /* NACK */
+    s->stat |= (!ack) << 1;                  /* NACK */
     if (!ack)
-        s->control &= ~(1 << 1);                               /* STP */
+        s->control &= ~(1 << 1);          /* STP */
+    TRACE("finished, STAT = %04x, CNT = %d", s->stat, s->count_cur);
 }
 
 void omap_i2c_reset(struct omap_i2c_s *s)
@@ -189,12 +242,17 @@ void omap_i2c_reset(struct omap_i2c_s *s)
     s->dma = 0;
     s->count = 0;
     s->count_cur = 0;
-    s->fifo = 0;
+    s->we = 0;
+    s->sysc = 0;
     s->rxlen = 0;
     s->txlen = 0;
     s->control = 0;
-    s->addr[0] = 0;
-    s->addr[1] = 0;
+    s->own_addr[0] = 0;
+    s->own_addr[1] = 0;
+    s->own_addr[2] = 0;
+    s->own_addr[3] = 0;
+    s->slave_addr = 0;
+    s->sblock = 0;
     s->divider = 0;
     s->times[0] = 0;
     s->times[1] = 0;
@@ -208,91 +266,127 @@ static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr)
     uint16_t ret;
 
     switch (offset) {
-    case 0x00: /* I2C_REV */
-        return s->revision;                                    /* REV */
-
-    case 0x04: /* I2C_IE */
-        return s->mask;
-
-    case 0x08: /* I2C_STAT */
-        return s->stat | (i2c_bus_busy(s->bus) << 12);
-
-    case 0x0c: /* I2C_IV */
-        if (s->revision >= OMAP2_INTR_REV)
-            break;
-        ret = ffs(s->stat & s->mask);
-        if (ret)
-            s->stat ^= 1 << (ret - 1);
-        omap_i2c_interrupts_update(s);
-        return ret;
-
-    case 0x10: /* I2C_SYSS */
-        return (s->control >> 15) & 1;                         /* I2C_EN */
-
-    case 0x14: /* I2C_BUF */
-        return s->dma;
-
-    case 0x18: /* I2C_CNT */
-        return s->count_cur;                                   /* DCOUNT */
-
-    case 0x1c: /* I2C_DATA */
-        ret = 0;
-        if (s->control & (1 << 14)) {                          /* BE */
-            ret |= ((s->fifo >> 0) & 0xff) << 8;
-            ret |= ((s->fifo >> 8) & 0xff) << 0;
-        } else {
-            ret |= ((s->fifo >> 8) & 0xff) << 8;
-            ret |= ((s->fifo >> 0) & 0xff) << 0;
-        }
-        if (s->rxlen == 1) {
-            s->stat |= 1 << 15;                                        /* SBD */
-            s->rxlen = 0;
-        } else if (s->rxlen > 1) {
-            if (s->rxlen > 2)
-                s->fifo >>= 16;
-            s->rxlen -= 2;
-        } else
-            /* XXX: remote access (qualifier) error - what's that?  */;
-        if (!s->rxlen) {
-            s->stat &= ~(1 << 3);                              /* RRDY */
-            if (((s->control >> 10) & 1) &&                    /* MST */
-                            ((~s->control >> 9) & 1)) {                /* TRX */
-                s->stat |= 1 << 2;                             /* ARDY */
-                s->control &= ~(1 << 10);                      /* MST */
+        case 0x00: /* I2C_REV */
+            TRACE("REV returns %04x", s->revision);
+            return s->revision;
+        case 0x04: /* I2C_IE */
+            TRACE("IE returns %04x", s->mask);
+            return s->mask;
+        case 0x08: /* I2C_STAT */
+            TRACE("STAT returns %04x", s->stat | (i2c_bus_busy(s->bus) << 12));
+            return s->stat | (i2c_bus_busy(s->bus) << 12);
+        case 0x0c: /* I2C_IV / I2C_WE */
+            if (s->revision >= OMAP3_INTR_REV)
+                return s->we;
+            if (s->revision >= OMAP2_INTR_REV)
+                break;
+            ret = ffs(s->stat & s->mask);
+            if (ret)
+                s->stat ^= 1 << (ret - 1);
+            omap_i2c_interrupts_update(s);
+            return ret;
+        case 0x10: /* I2C_SYSS */
+            return (s->control >> 15) & 1; /* reset completed == I2C_EN */
+        case 0x14: /* I2C_BUF */
+            TRACE("BUF returns %04x", s->dma);
+            return s->dma;
+        case 0x18: /* I2C_CNT */
+            TRACE("CNT returns %04x", s->count_cur);
+            return s->count_cur; /* DCOUNT */
+        case 0x1c: /* I2C_DATA */
+            ret = 0;
+            if (s->rxlen) {
+                if (s->revision < OMAP3_INTR_REV) {
+                    if (s->control & (1 << 14)) /* BE */
+                        ret = (((uint16_t)s->fifo[0]) << 8) | s->fifo[1];
+                    else
+                        ret = (((uint16_t)s->fifo[1]) << 8) | s->fifo[0];
+                    if (s->rxlen == 1) {
+                        s->stat |= 1 << 15; /* SBD */
+                        s->rxlen = 0;
+                    } else {
+                        s->rxlen -= 2;
+                        if (s->rxlen)
+                            memmove(s->fifo, s->fifo + 2, s->rxlen);
+                    }
+                    if (!s->rxlen) {
+                        s->stat &= ~(1 << 3); /* RRDY */
+                        s->stat |= 1 << 2;    /* ARDY */
+                    }
+                } else {
+                    s->stat &= ~(1 << 7); /* AERR */
+                    ret = s->fifo[0];
+                    if (--s->rxlen) {
+                        memmove(s->fifo, s->fifo + 1, s->rxlen);
+                        if (s->rxlen < ((s->dma & 0x3f) >> 8)) {
+                            s->stat &= ~(1 << 3); /* RRDY */
+                            s->stat |= 1 << 13;   /* RDR */
+                        }
+                    } else {
+                        s->stat &= ~((1 << 3) | (1 << 13)); /* RRDY | RDR */
+                        s->stat |= 1 << 2;                  /* ARDY */
+                    }
+                }
+                s->stat &= ~(1 << 11); /* ROVR */
+            } else if (s->revision >= OMAP3_INTR_REV)
+                s->stat |= (1 << 7); /* AERR */
+            TRACE("DATA returns %04x", ret);
+            omap_i2c_fifo_run(s);
+            omap_i2c_interrupts_update(s);
+            return ret;
+        case 0x20: /* I2C_SYSC */
+            TRACE("SYSC returns %04x", s->sysc);
+            return s->sysc;
+        case 0x24: /* I2C_CON */
+            TRACE("CON returns %04x", s->control);
+            return s->control;
+        case 0x28: /* I2C_OA / I2C_OA0 */
+            return s->own_addr[0];
+        case 0x2c: /* I2C_SA */
+            return s->slave_addr;
+        case 0x30: /* I2C_PSC */
+            return s->divider;
+        case 0x34: /* I2C_SCLL */
+            return s->times[0];
+        case 0x38: /* I2C_SCLH */
+            return s->times[1];
+        case 0x3c: /* I2C_SYSTEST */
+            if (s->test & (1 << 15)) { /* ST_EN */
+                s->test ^= 0xa;
+                return s->test;
             }
-        }
-        s->stat &= ~(1 << 11);                                 /* ROVR */
-        omap_i2c_fifo_run(s);
-        omap_i2c_interrupts_update(s);
-        return ret;
-
-    case 0x20: /* I2C_SYSC */
-        return 0;
-
-    case 0x24: /* I2C_CON */
-        return s->control;
-
-    case 0x28: /* I2C_OA */
-        return s->addr[0];
-
-    case 0x2c: /* I2C_SA */
-        return s->addr[1];
-
-    case 0x30: /* I2C_PSC */
-        return s->divider;
-
-    case 0x34: /* I2C_SCLL */
-        return s->times[0];
-
-    case 0x38: /* I2C_SCLH */
-        return s->times[1];
-
-    case 0x3c: /* I2C_SYSTEST */
-        if (s->test & (1 << 15)) {                             /* ST_EN */
-            s->test ^= 0xa;
-            return s->test;
-        } else
             return s->test & ~0x300f;
+        case 0x40: /* I2C_BUFSTAT */
+            if (s->revision >= OMAP3_INTR_REV) {
+                switch (s->fifosize) {
+                    case 8:  ret = 0x0000; break;
+                    case 16: ret = 0x4000; break;
+                    case 32: ret = 0x8000; break;
+                    case 64: ret = 0xc000; break;
+                    default: ret = 0x0000; break;
+                }
+                ret |= ((s->rxlen) & 0x3f) << 8;  /* RXSTAT */
+                ret |= (s->count_cur) & 0x3f;     /* TXSTAT */
+                TRACE("BUFSTAT returns %04x", ret);
+                return ret;
+            }
+            break;
+        case 0x44: /* I2C_OA1 */
+        case 0x48: /* I2C_OA2 */
+        case 0x4c: /* I2C_OA3 */
+            if (s->revision >= OMAP3_INTR_REV)
+                return s->own_addr[(addr >> 2) & 3];
+            break;
+        case 0x50: /* I2C_ACTOA */
+            if (s->revision >= OMAP3_INTR_REV)
+                return 0; /* TODO: determine accessed slave own address */
+            break;
+        case 0x54: /* I2C_SBLOCK */
+            if (s->revision >= OMAP3_INTR_REV)
+                return s->sblock;
+            break;
+        default:
+            break;
     }
 
     OMAP_BAD_REG(addr);
@@ -307,138 +401,193 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
     int nack;
 
     switch (offset) {
-    case 0x00: /* I2C_REV */
-    case 0x0c: /* I2C_IV */
-    case 0x10: /* I2C_SYSS */
-        OMAP_RO_REG(addr);
-        return;
-
-    case 0x04: /* I2C_IE */
-        s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
-        break;
-
-    case 0x08: /* I2C_STAT */
-        if (s->revision < OMAP2_INTR_REV) {
+        case 0x00: /* I2C_REV */
+        case 0x10: /* I2C_SYSS */
+        case 0x40: /* I2C_BUFSTAT */
+        case 0x50: /* I2C_ACTOA */
             OMAP_RO_REG(addr);
-            return;
-        }
-
-        /* RRDY and XRDY are reset by hardware. (in all versions???) */
-        s->stat &= ~(value & 0x27);
-        omap_i2c_interrupts_update(s);
-        break;
-
-    case 0x14: /* I2C_BUF */
-        s->dma = value & 0x8080;
-        if (value & (1 << 15))                                 /* RDMA_EN */
-            s->mask &= ~(1 << 3);                              /* RRDY_IE */
-        if (value & (1 << 7))                                  /* XDMA_EN */
-            s->mask &= ~(1 << 4);                              /* XRDY_IE */
-        break;
-
-    case 0x18: /* I2C_CNT */
-        s->count = value;                                      /* DCOUNT */
-        break;
-
-    case 0x1c: /* I2C_DATA */
-        if (s->txlen > 2) {
-            /* XXX: remote access (qualifier) error - what's that?  */
             break;
-        }
-        s->fifo <<= 16;
-        s->txlen += 2;
-        if (s->control & (1 << 14)) {                          /* BE */
-            s->fifo |= ((value >> 8) & 0xff) << 8;
-            s->fifo |= ((value >> 0) & 0xff) << 0;
-        } else {
-            s->fifo |= ((value >> 0) & 0xff) << 8;
-            s->fifo |= ((value >> 8) & 0xff) << 0;
-        }
-        s->stat &= ~(1 << 10);                                 /* XUDF */
-        if (s->txlen > 2)
-            s->stat &= ~(1 << 4);                              /* XRDY */
-        omap_i2c_fifo_run(s);
-        omap_i2c_interrupts_update(s);
-        break;
-
-    case 0x20: /* I2C_SYSC */
-        if (s->revision < OMAP2_INTR_REV) {
-            OMAP_BAD_REG(addr);
-            return;
-        }
-
-        if (value & 2)
-            omap_i2c_reset(s);
-        break;
-
-    case 0x24: /* I2C_CON */
-        s->control = value & 0xcf87;
-        if (~value & (1 << 15)) {                              /* I2C_EN */
+        case 0x04: /* I2C_IE */
+            TRACE("IE = %04x", value);
+            if (s->revision >= OMAP3_INTR_REV)
+                s->mask = value & 0x63ff;
+            else
+                s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
+            omap_i2c_interrupts_update(s);
+            break;
+        case 0x08: /* I2C_STAT */
             if (s->revision < OMAP2_INTR_REV)
+                OMAP_RO_REG(addr);
+            else {
+                TRACE("STAT = %04x", value);
+                /* RRDY and XRDY are reset by hardware. (in all versions???) */
+                s->stat &= ~(value & (s->revision < OMAP3_INTR_REV ? 0x27 : 0x63e7));
+                omap_i2c_interrupts_update(s);
+            }
+            break;
+        case 0x0c: /* I2C_IV / I2C_WE */
+            if (s->revision < OMAP3_INTR_REV)
+                OMAP_RO_REG(addr);
+            else
+                s->we = value & 0x636f;
+            break;
+        case 0x14: /* I2C_BUF */
+            TRACE("BUF = %04x", value);
+            if (s->revision < OMAP3_INTR_REV)
+                s->dma = value & 0x8080;
+            else {
+                s->dma = value & 0xbfbf;
+                if (value & (1 << 14)) /* RXFIFO_CLR */
+                    s->rxlen = 0;
+                if (value & (1 << 6))  /* TXFIFO_CLR */
+                    s->txlen = 0;
+            }
+            if (value & (1 << 15))     /* RDMA_EN */
+                s->mask &= ~(1 << 3);  /* RRDY_IE */
+            if (value & (1 << 7))      /* XDMA_EN */
+                s->mask &= ~(1 << 4);  /* XRDY_IE */
+            break;
+        case 0x18: /* I2C_CNT */
+            TRACE("CNT = %04x", value);
+            s->count = value; /* DCOUNT */
+            break;
+        case 0x1c: /* I2C_DATA */
+            TRACE("DATA = %04x", value);
+            if (s->revision < OMAP3_INTR_REV) {
+                if (s->txlen > 2) {
+                    /* XXX: remote access (qualifier) error - what's that? */
+                    break;
+                }
+                if (s->control & (1 << 14)) { /* BE */
+                    s->fifo[s->txlen++] = (uint8_t)((value >> 8) & 0xff);
+                    s->fifo[s->txlen++] = (uint8_t)(value & 0xff);
+                } else {
+                    s->fifo[s->txlen++] = (uint8_t)(value & 0xff);
+                    s->fifo[s->txlen++] = (uint8_t)((value >> 8) & 0xff);
+                }
+            } else {
+                if (s->txlen < s->fifosize) {
+                    s->stat &= ~(1 << 7); /* AERR */
+                    s->fifo[s->txlen++] = (uint8_t)(value & 0xff);
+                } else
+                    s->stat |= (1 << 7); /* AERR */
+            }
+            s->stat &= ~(1 << 10); /* XUDF */
+            omap_i2c_fifo_run(s);
+            omap_i2c_interrupts_update(s);
+            break;
+        case 0x20: /* I2C_SYSC */
+            if (s->revision < OMAP2_INTR_REV) {
+                OMAP_BAD_REG(addr);
+                break;
+            }
+            TRACE("SYSC = %04x", value);
+            if (value & 2)
                 omap_i2c_reset(s);
+            else if (s->revision >= OMAP3_INTR_REV)
+                s->sysc = value & 0x031d;
             break;
-        }
-        if ((value & (1 << 15)) && !(value & (1 << 10))) {     /* MST */
-            fprintf(stderr, "%s: I^2C slave mode not supported\n",
-                            __FUNCTION__);
+        case 0x24: /* I2C_CON */
+            TRACE("CON = %04x", value);
+            s->control = value & (s->revision < OMAP3_INTR_REV ? 0xcf87 : 0xbff3);
+            if (~value & (1 << 15)) { /* I2C_EN */
+                if (s->revision < OMAP2_INTR_REV)
+                    omap_i2c_reset(s);
+                break;
+            }
+            if (s->revision >= OMAP3_INTR_REV && ((value >> 12) & 3) > 1) { /* OPMODE */
+                fprintf(stderr,
+                        "%s: only FS and HS modes are supported\n",
+                        __FUNCTION__);
+                break;
+            }
+            if ((value & (1 << 10))) { /* MST */
+                if (value & 1) { /* STT */
+                    nack = !!i2c_start_transfer(s->bus, s->slave_addr, /*SA*/
+                                                (~value >> 9) & 1);    /*TRX*/
+                    s->stat |= nack << 1;        /* NACK */
+                    s->control &= ~(1 << 0);     /* STT */
+                    s->txlen = 0;
+                    s->rxlen = 0;
+                    if (nack)
+                        s->control &= ~(1 << 1); /* STP */
+                    else {
+                        s->count_cur = s->count;
+                        omap_i2c_fifo_run(s);
+                    }
+                    omap_i2c_interrupts_update(s);
+                } else if (value & 2) { /* STP, but not STT */
+                    i2c_end_transfer(s->bus);
+                    s->control &= ~0x0602;     /* MST | TRX | STP */
+                    s->count_cur = s->count;
+                    s->txlen = 0;
+                }
+            }
             break;
-        }
-        if ((value & (1 << 15)) && value & (1 << 8)) {         /* XA */
-            fprintf(stderr, "%s: 10-bit addressing mode not supported\n",
-                            __FUNCTION__);
+        case 0x28: /* I2C_OA / I2C_OA0 */
+            TRACE("OA0 = %04x", value);
+            s->own_addr[0] = value & (s->revision < OMAP3_INTR_REV 
+                                      ? 0x3ff : 0xe3ff);
+            i2c_set_slave_address(&s->slave[0], 
+                                  value & (s->revision >= OMAP3_INTR_REV 
+                                           && (s->control & 0x80) 
+                                           ? 0x3ff: 0x7f));
             break;
-        }
-        if ((value & (1 << 15)) && value & (1 << 0)) {         /* STT */
-            nack = !!i2c_start_transfer(s->bus, s->addr[1],    /* SA */
-                            (~value >> 9) & 1);                        /* TRX */
-            s->stat |= nack << 1;                              /* NACK */
-            s->control &= ~(1 << 0);                           /* STT */
-            s->fifo = 0;
-            if (nack)
-                s->control &= ~(1 << 1);                       /* STP */
+        case 0x2c: /* I2C_SA */
+            TRACE("SA = %04x", value);
+            s->slave_addr = value & 0x3ff;
+            break;
+        case 0x30: /* I2C_PSC */
+            s->divider = value;
+            break;
+        case 0x34: /* I2C_SCLL */
+            s->times[0] = value & (s->revision < OMAP3_INTR_REV 
+                                   ? 0xff : 0xffff);
+            break;
+        case 0x38: /* I2C_SCLH */
+            s->times[1] = value & (s->revision < OMAP3_INTR_REV
+                                   ? 0xff : 0xffff);
+            break;
+        case 0x3c: /* I2C_SYSTEST */
+            value &= s->revision < OMAP3_INTR_REV ? 0xf805 : 0xf815;
+            if ((value & (1 << 15))) { /* ST_EN */
+                fprintf(stderr, "%s: System Test not supported\n",
+                        __FUNCTION__);
+                s->test = (s->test & 0x0a) | value;
+            } else
+                s->test = (s->test & 0x1f) | (value & 0xf800);
+            if (value & (1 << 11)) /* SBB */
+                if (s->revision >= OMAP2_INTR_REV) {
+                    s->stat |= 0x3f;
+                    if (s->revision >= OMAP3_INTR_REV)
+                        s->stat |= 0x600;
+                    omap_i2c_interrupts_update(s);
+                }
+            break;
+        case 0x44: /* I2C_OA1 */
+        case 0x48: /* I2C_OA2 */
+        case 0x4c: /* I2C_OA3 */
+            if (s->revision < OMAP3_INTR_REV)
+                OMAP_BAD_REG(addr);
             else {
-                s->count_cur = s->count;
-                omap_i2c_fifo_run(s);
+                addr = (addr >> 2) & 3;
+                TRACE("OA%d = %04x", addr, value);
+                s->own_addr[addr] = value & 0x3ff;
+                i2c_set_slave_address(&s->slave[addr], 
+                                      value & ((s->control & (0x80 >> addr)) 
+                                               ? 0x3ff: 0x7f));
             }
-            omap_i2c_interrupts_update(s);
-        }
-        break;
-
-    case 0x28: /* I2C_OA */
-        s->addr[0] = value & 0x3ff;
-        i2c_set_slave_address(&s->slave, value & 0x7f);
-        break;
-
-    case 0x2c: /* I2C_SA */
-        s->addr[1] = value & 0x3ff;
-        break;
-
-    case 0x30: /* I2C_PSC */
-        s->divider = value;
-        break;
-
-    case 0x34: /* I2C_SCLL */
-        s->times[0] = value;
-        break;
-
-    case 0x38: /* I2C_SCLH */
-        s->times[1] = value;
-        break;
-
-    case 0x3c: /* I2C_SYSTEST */
-        s->test = value & 0xf80f;
-        if (value & (1 << 11))                                 /* SBB */
-            if (s->revision >= OMAP2_INTR_REV) {
-                s->stat |= 0x3f;
-                omap_i2c_interrupts_update(s);
+            break;
+        case 0x54: /* I2C_SBLOCK */
+            if (s->revision < OMAP3_INTR_REV)
+                OMAP_BAD_REG(addr);
+            else {
+                s->sblock = value & 0x0f;
             }
-        if (value & (1 << 15))                                 /* ST_EN */
-            fprintf(stderr, "%s: System Test not supported\n", __FUNCTION__);
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
+            break;
+        default:
+            OMAP_BAD_REG(addr);
+            break;
     }
 }
 
@@ -449,24 +598,25 @@ static void omap_i2c_writeb(void *opaque, target_phys_addr_t addr,
     int offset = addr & OMAP_MPUI_REG_MASK;
 
     switch (offset) {
-    case 0x1c: /* I2C_DATA */
-        if (s->txlen > 2) {
-            /* XXX: remote access (qualifier) error - what's that?  */
+        case 0x1c: /* I2C_DATA */
+            TRACE("DATA = %02x", value);
+            if (s->revision < OMAP3_INTR_REV && s->txlen > 2) {
+                /* XXX: remote access (qualifier) error - what's that? */
+                break;
+            }
+            if (s->txlen < s->fifosize) {
+                s->fifo[s->txlen++] = (uint8_t)(value & 0xff);
+                if (s->revision >= OMAP3_INTR_REV)
+                    s->stat &= ~(1 << 7); /* AERR */
+                s->stat &= ~(1 << 10);    /* XUDF */
+                omap_i2c_fifo_run(s);
+            } else if (s->revision >= OMAP3_INTR_REV)
+                s->stat |= (1 << 7);      /* AERR */
+            omap_i2c_interrupts_update(s);
+            break;
+        default:
+            OMAP_BAD_REG(addr);
             break;
-        }
-        s->fifo <<= 8;
-        s->txlen += 1;
-        s->fifo |= value & 0xff;
-        s->stat &= ~(1 << 10);                                 /* XUDF */
-        if (s->txlen > 2)
-            s->stat &= ~(1 << 4);                              /* XRDY */
-        omap_i2c_fifo_run(s);
-        omap_i2c_interrupts_update(s);
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
     }
 }
 
@@ -494,10 +644,11 @@ struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
     s->irq = irq;
     s->drq[0] = dma[0];
     s->drq[1] = dma[1];
-    s->slave.event = omap_i2c_event;
-    s->slave.recv = omap_i2c_rx;
-    s->slave.send = omap_i2c_tx;
+    s->slave[0].event = omap_i2c_event;
+    s->slave[0].recv = omap_i2c_rx;
+    s->slave[0].send = omap_i2c_tx;
     s->bus = i2c_init_bus();
+    s->fifosize = 4;
     omap_i2c_reset(s);
 
     iomemtype = cpu_register_io_memory(0, omap_i2c_readfn,
@@ -518,10 +669,11 @@ struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
     s->irq = irq;
     s->drq[0] = dma[0];
     s->drq[1] = dma[1];
-    s->slave.event = omap_i2c_event;
-    s->slave.recv = omap_i2c_rx;
-    s->slave.send = omap_i2c_tx;
+    s->slave[0].event = omap_i2c_event;
+    s->slave[0].recv = omap_i2c_rx;
+    s->slave[0].send = omap_i2c_tx;
     s->bus = i2c_init_bus();
+    s->fifosize = 4;
     omap_i2c_reset(s);
 
     iomemtype = l4_register_io_memory(0, omap_i2c_readfn,
@@ -531,6 +683,38 @@ struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
     return s;
 }
 
+struct omap_i2c_s *omap3_i2c_init(struct omap_target_agent_s *ta,
+                                  qemu_irq irq, qemu_irq *dma,
+                                  omap_clk fclk, omap_clk iclk,
+                                  int fifosize)
+{
+    int iomemtype;
+    struct omap_i2c_s *s = (struct omap_i2c_s *)qemu_mallocz(sizeof(struct omap_i2c_s));
+    
+    if (fifosize != 8 && fifosize != 16 && fifosize != 32 && fifosize != 64)
+        fprintf(stderr, "%s: unsupported FIFO depth specified (%d)\n",
+                __FUNCTION__, fifosize);
+    s->revision = OMAP3_INTR_REV;
+    s->irq = irq;
+    s->drq[0] = dma[0];
+    s->drq[1] = dma[1];
+    s->slave[0].event = s->slave[1].event = s->slave[2].event =
+        s->slave[3].event = omap_i2c_event;
+    s->slave[0].recv = s->slave[1].recv = s->slave[2].recv =
+        s->slave[3].recv = omap_i2c_rx;
+    s->slave[0].send = s->slave[1].send = s->slave[2].send =
+        s->slave[3].send = omap_i2c_tx;
+    s->bus = i2c_init_bus();
+    s->fifosize = fifosize;
+    omap_i2c_reset(s);
+    
+    iomemtype = l4_register_io_memory(0, omap_i2c_readfn,
+                                      omap_i2c_writefn, s);
+    omap_l4_attach(ta, 0, iomemtype);
+    
+    return s;
+}
+
 i2c_bus *omap_i2c_bus(struct omap_i2c_s *s)
 {
     return s->bus;
diff --git a/hw/sd.c b/hw/sd.c
index 0c770bc..9774361 100644 (file)
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -37,7 +37,7 @@
 
 #ifdef DEBUG_SD
 #define DPRINTF(fmt, args...) \
-do { fprintf(stderr, "SD: " fmt , ##args); } while (0)
+do { fprintf(stderr, "%s: " fmt , __FUNCTION__, ##args); } while (0)
 #else
 #define DPRINTF(fmt, args...) do {} while(0)
 #endif
@@ -195,13 +195,13 @@ static uint16_t sd_crc16(void *message, size_t width)
 static void sd_set_ocr(SDState *sd)
 {
     /* All voltages OK, card power-up OK, Standard Capacity SD Memory Card */
-    sd->ocr = 0x80ffff80;
+    sd->ocr = 0x80ffff00;
 }
 
 static void sd_set_scr(SDState *sd)
 {
-    sd->scr[0] = 0x00;         /* SCR Structure */
-    sd->scr[1] = 0x2f;         /* SD Security Support */
+    sd->scr[0] = 0x00; /* SCR v1.0, SD spec v1.0/1.01 */
+    sd->scr[1] = 0x25; /* erase=0, SD security v1.01, 1bit/4bit bus width */
     sd->scr[2] = 0x00;
     sd->scr[3] = 0x00;
     sd->scr[4] = 0x00;
@@ -1308,8 +1308,8 @@ int sd_do_command(SDState *sd, struct sd_request_s *req,
         int i;
         DPRINTF("Response:");
         for (i = 0; i < rsplen; i++)
-            printf(" %02x", response[i]);
-        printf(" state %d\n", sd->state);
+            fprintf(stderr, " %02x", response[i]);
+        fprintf(stderr, " state %d\n", sd->state);
     } else {
         DPRINTF("No response %d\n", sd->state);
     }
@@ -1506,7 +1506,7 @@ uint8_t sd_read_data(SDState *sd)
         return 0x00;
 
     if (sd->state != sd_sendingdata_state) {
-        fprintf(stderr, "sd_read_data: not in Sending-Data state\n");
+        fprintf(stderr, "sd_read_data: not in Sending-Data state (state=%d)\n", sd->state);
         return 0x00;
     }
 
index e8d4a85..68b18c4 100644 (file)
@@ -229,25 +229,6 @@ static void tsc2005_write(struct tsc2005_state_s *s, int reg, uint16_t data)
 static void tsc2005_pin_update(struct tsc2005_state_s *s)
 {
     int64_t expires;
-    int pin_state;
-
-    switch (s->pin_func) {
-    case 0:
-        pin_state = !s->pressure && !!s->dav;
-        break;
-    case 1:
-    case 3:
-    default:
-        pin_state = !s->dav;
-        break;
-    case 2:
-        pin_state = !s->pressure;
-    }
-
-    if (pin_state != s->irq) {
-        s->irq = pin_state;
-        qemu_set_irq(s->pint, s->irq);
-    }
 
     switch (s->nextfunction) {
     case TSC_MODE_XYZ_SCAN:
@@ -400,16 +381,35 @@ uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len)
 static void tsc2005_timer_tick(void *opaque)
 {
     struct tsc2005_state_s *s = opaque;
+       int pin_state;
 
     /* Timer ticked -- a set of conversions has been finished.  */
 
     if (!s->busy)
         return;
 
-    s->busy = 0;
-    s->dav |= mode_regs[s->function];
-    s->function = -1;
-    tsc2005_pin_update(s);
+       switch (s->pin_func) {
+               case 0:
+                       pin_state = !s->pressure && !!s->dav;
+                       break;
+               case 1:
+               case 3:
+               default:
+                       pin_state = !s->dav;
+                       break;
+               case 2:
+                       pin_state = !s->pressure;
+    }
+       
+       s->busy = 0;
+       if (pin_state && !s->irq) s->dav |= mode_regs[s->function];
+       s->function = -1;
+       tsc2005_pin_update(s);
+
+    if (pin_state != s->irq) {
+        s->irq = pin_state;
+        qemu_set_irq(s->pint, s->irq);
+    }
 }
 
 static void tsc2005_touchscreen_event(void *opaque,
diff --git a/hw/twl4030.c b/hw/twl4030.c
new file mode 100644 (file)
index 0000000..bb867ce
--- /dev/null
@@ -0,0 +1,894 @@
+/*
+ * TI TWL4030 for beagle board
+ * register implementation based on TPS65950 ES1.0 specification
+ *
+ * Copyright (C) 2008 yajin<yajin@vm-kernel.org>
+ *
+ * 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 or
+ * (at your option) version 3 of the License.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include "hw.h"
+#include "qemu-timer.h"
+#include "i2c.h"
+#include "sysemu.h"
+#include "console.h"
+#include "cpu-all.h"
+
+#define VERBOSE 1
+#define TRACEW(regname, value) fprintf(stderr, "%s: %s = 0x%02x\n", __FUNCTION__, regname, value);
+
+//extern CPUState *cpu_single_env;
+
+struct twl4030_i2c_s {
+    i2c_slave i2c;
+    int firstbyte;
+    uint8_t reg;
+    qemu_irq irq;
+    uint8 reg_data[256];
+    struct twl4030_s *twl4030;
+};
+
+struct twl4030_s {
+    struct twl4030_i2c_s *i2c[5];
+    
+    int key_cfg;
+    int key_tst;
+    
+    uint8_t seq_mem[64][4]; /* power-management sequencing memory */
+};
+
+static const uint8_t addr_48_reset_values[256] = {
+    0x51, 0x04, 0x02, 0xc0, 0x41, 0x41, 0x41, 0x10, /* 0x00...0x07 */
+    0x10, 0x10, 0x06, 0x06, 0x06, 0x1f, 0x1f, 0x1f, /* 0x08...0x0f */
+    0x1f, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10...0x17 */
+    0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, /* 0x18...0x1f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0a, 0x03, /* 0x20...0x27 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28...0x2f */
+    0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, /* 0x30...0x37 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38...0x3f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40...0x47 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48...0x4f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50...0x57 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60...0x67 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70...0x77 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78...0x7f */
+    0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, /* 0x80...0x87 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88...0x8f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90...0x97 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98...0x9f */
+    0x00, 0x10, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 0xa0...0xa7 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8...0xaf */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0...0xb7 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8...0xb8 */
+    0xa0, 0xa0, 0x64, 0x7f, 0x6c, 0x75, 0x64, 0x20, /* 0xc0...0xc7 */
+    0x01, 0x17, 0x01, 0x02, 0x00, 0x36, 0x44, 0x07, /* 0xc8...0xcf */
+    0x3b, 0x17, 0x6b, 0x04, 0x00, 0x00, 0x00, 0x00, /* 0xd0...0xd7 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8...0xdf */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0...0xe7 */
+    0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 0xe8...0xef */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00  /* 0xf8...0xff */
+};
+
+static const uint8_t addr_49_reset_values[256] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00...0x07 */
+    0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, /* 0x08...0x0f */
+    0x3f, 0x3f, 0x3f, 0x3f, 0x25, 0x00, 0x00, 0x00, /* 0x10...0x17 */
+    0x00, 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x55, /* 0x18...0x1f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20...0x27 */
+    0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, /* 0x28...0x2f */
+    0x13, 0x00, 0x00, 0x00, 0x00, 0x79, 0x11, 0x00, /* 0x30...0x37 */
+    0x00, 0x00, 0x06, 0x00, 0x44, 0x69, 0x00, 0x00, /* 0x38...0x3f */
+    0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, /* 0x40...0x47 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48...0x4f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50...0x57 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60...0x67 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70...0x77 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78...0x7f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80...0x87 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88...0x8f */
+    0x00, 0x90, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, /* 0x90...0x97 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98...0x9f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0...0xa7 */
+    0x00, 0x00, 0x04, 0x00, 0x55, 0x01, 0x55, 0x05, /* 0xa8...0xaf */
+    0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, /* 0xb0...0xb7 */
+    0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, /* 0xb8...0xbf */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, /* 0xc0...0xc7 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8...0xcf */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0...0xd7 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8...0xdf */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0...0xe7 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8...0xef */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8...0xff */
+};
+
+static const uint8_t addr_4a_reset_values[256] = {
+    0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00...0x07 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08...0x0f */
+    0xc0, 0x8c, 0xde, 0xde, 0x00, 0x00, 0x00, 0x00, /* 0x10...0x17 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18...0x1f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20...0x27 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28...0x2f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30...0x37 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38...0x3f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40...0x47 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48...0x4f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50...0x57 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
+    0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x07, /* 0x60...0x67 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70...0x77 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78...0x7f */
+    0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, /* 0x80...0x87 */
+    0x00, 0x68, 0x9b, 0x86, 0x48, 0x2a, 0x07, 0x28, /* 0x88...0x8f */
+    0x09, 0x69, 0x90, 0x00, 0x2a, 0x00, 0x02, 0x00, /* 0x90...0x97 */
+    0x10, 0xcd, 0x02, 0x68, 0x03, 0x00, 0x00, 0x00, /* 0x98...0x9f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0...0xa7 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8...0xaf */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0...0xb7 */
+    0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, /* 0xb8...0xbf */
+    0x0f, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x01, 0x00, /* 0xc0...0xc7 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8...0xcf */
+    0x00, 0x00, 0x03, 0x00, 0x00, 0xe0, 0x00, 0x00, /* 0xd0...0xd7 */
+    0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8...0xdf */
+    0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, /* 0xe0...0xe7 */
+    0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8...0xef */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* 0xf8...0xff */
+};
+
+static const uint8_t addr_4b_reset_values[256] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00...0x07 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08...0x0f */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10...0x17 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x18...0x1f */
+    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, /* 0x20...0x27 */
+    0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28...0x2f */
+    0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0xbf, 0xbf, /* 0x30...0x37 */
+    0xbf, 0xab, 0x00, 0x08, 0x3f, 0x15, 0x40, 0x0e, /* 0x38...0x3f */
+    0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40...0x47 */
+    0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, /* 0x48...0x4f */
+    0x00, 0x02, 0x00, 0x04, 0x0d, 0x00, 0x00, 0x00, /* 0x50...0x57 */
+    0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
+    0x00, 0x00, 0x2f, 0x18, 0x0f, 0x08, 0x0f, 0x08, /* 0x60...0x67 */
+    0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
+    0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x80, 0x03, /* 0x70...0x77 */
+    0x08, 0x09, 0x00, 0x00, 0x08, 0x03, 0x80, 0x03, /* 0x78...0x7f */
+    0x08, 0x02, 0x00, 0x00, 0x08, 0x00, 0x80, 0x03, /* 0x80...0x87 */
+    0x08, 0x08, 0x20, 0x00, 0x00, 0x02, 0x80, 0x04, /* 0x88...0x8f */
+    0x08, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, /* 0x90...0x97 */
+    0x08, 0x02, 0xe0, 0x01, 0x08, 0x00, 0xe0, 0x00, /* 0x98...0x9f */
+    0x08, 0x01, 0xe0, 0x01, 0x08, 0x04, 0xe0, 0x03, /* 0xa0...0xa7 */
+    0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8...0xaf */
+    0x20, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0...0xb7 */
+    0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, /* 0xb8...0xbf */
+    0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, /* 0xc0...0xc7 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, /* 0xc8...0xcf */
+    0x00, 0x08, 0xe0, 0x00, 0x08, 0x00, 0x00, 0x00, /* 0xd0...0xd7 */
+    0x14, 0x08, 0xe0, 0x02, 0x08, 0xe0, 0x00, 0x08, /* 0xd8...0xdf */
+    0xe0, 0x05, 0x08, 0xe0, 0x06, 0x08, 0xe0, 0x00, /* 0xe0...0xe7 */
+    0x08, 0xe0, 0x00, 0x08, 0xe0, 0x06, 0x06, 0xe0, /* 0xe8...0xef */
+    0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* 0xf8...0xff */
+};
+
+static uint8_t twl4030_48_read(void *opaque, uint8_t addr)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
+       
+    switch (addr) {
+        case 0x00: /* VENDOR_ID_LO */
+        case 0x01: /* VENDOR_ID_HI */
+        case 0x02: /* PRODUCT_ID_LO */
+        case 0x03: /* PRODUCT_ID_HI */
+            return s->reg_data[addr];
+        case 0x04: /* FUNC_CTRL */
+        case 0x05: /* FUNC_CRTL_SET */
+        case 0x06: /* FUNC_CRTL_CLR */
+            return s->reg_data[0x04];
+        case 0x07: /* IFC_CTRL */
+        case 0x08: /* IFC_CRTL_SET */
+        case 0x09: /* IFC_CRTL_CLR */
+            return s->reg_data[0x07];
+        case 0xac: /* POWER_CTRL */
+        case 0xad: /* POWER_SET */
+        case 0xae: /* POWER_CLR */
+            return s->reg_data[0xac];
+        case 0xfd: /* PHY_PWR_CTRL */
+        case 0xfe: /* PHY_CLK_CTRL */
+            return s->reg_data[addr];
+        case 0xff: /* PHY_CLK_CTRL */
+            return s->reg_data[0xfe] & 0x1;
+        default:
+#ifdef VERBOSE
+            printf("%s: unknown register %02x pc %x \n", __FUNCTION__, addr,cpu_single_env->regs[15] );
+               //printf("%s: unknown register %02x \n", __FUNCTION__, addr);
+#endif
+            exit(-1);
+            break;
+    }
+}
+
+static void twl4030_48_write(void *opaque, uint8_t addr, uint8_t value)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
+       
+    switch (addr) {
+        case 0x04: /* IFC_CTRL */
+            s->reg_data[0x04] = value & 0x80;
+            break;
+        case 0x05: /* IFC_CRTL_SET */
+            s->reg_data[0x04] =  (s->reg_data[0x04] | value) & 0x80;
+            break;
+        case 0x06: /* IFC_CRTL_CLEAR */
+            s->reg_data[0x04] =  (s->reg_data[0x04] & ~value) & 0x80;
+            break;
+        case 0x07: /* IFC_CTRL */
+            s->reg_data[0x07] = value & 0x61;
+            break;
+        case 0x08: /* IFC_CRTL_SET */
+            s->reg_data[0x07] =  (s->reg_data[0x07] | value) & 0x61;
+            break;
+        case 0x09: /* IFC_CRTL_CLEAR */
+            s->reg_data[0x07] =  (s->reg_data[0x07] & ~value) & 0x61;
+            break;
+        case 0xac: /* POWER_CTRL */
+            s->reg_data[0xac] = value & 0x20;
+            break;
+        case 0xad: /* POWER_SET */
+            s->reg_data[0xac] =  (s->reg_data[0xac] | value) & 0x20;
+            break;
+        case 0xae: /* POWER_CLEAR */
+            s->reg_data[0xac] =  (s->reg_data[0xac] & ~value) & 0x20;
+            break;
+        case 0xfd: /* PHY_PWR_CTRL */
+            s->reg_data[addr] = value & 0x1;
+            break;
+        case 0xfe: /* PHY_CLK_CTRL */
+            s->reg_data[addr] = value & 0x7;
+            break;
+        default:
+#ifdef VERBOSE
+            printf("%s: unknown register %02x pc %x \n", __FUNCTION__, addr,cpu_single_env->regs[15] );
+            //printf("%s: unknown register %02x \n", __FUNCTION__, addr);
+#endif
+                       exit(-1);
+                       break;
+    }
+}
+
+static int twl4030_48_tx(i2c_slave *i2c, uint8_t data)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+    /* Interpret register address byte */
+    if (s->firstbyte) {
+        s->reg = data;
+        s->firstbyte = 0;
+    } else
+        twl4030_48_write(s, s->reg++, data);
+       
+    return 0;
+}
+
+static int twl4030_48_rx(i2c_slave *i2c)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+       
+    return twl4030_48_read(s, s->reg++);
+}
+
+static void twl4030_48_reset(i2c_slave *i2c)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+    s->reg = 0x00;
+    memcpy(s->reg_data, addr_48_reset_values, 256);
+}
+
+static void twl4030_48_event(i2c_slave *i2c, enum i2c_event event)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+    
+    if (event == I2C_START_SEND)
+        s->firstbyte = 1;
+}
+
+static uint8_t twl4030_49_read(void *opaque, uint8_t addr)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
+
+    switch (addr) {
+        case 0x98: /* GPIO_DATAIN1 */
+        case 0x99: /* GPIO_DATAIN2 */
+        case 0x9a: /* GPIO_DATAIN3 */
+        case 0x9b: /* GPIO_DATADIR1 */
+        case 0x9c: /* GPIO_DATADIR2 */
+        case 0x9d: /* GPIO_DATADIR3 */
+        case 0xb1: /* GPIO_ISR1A */
+        case 0xb2: /* GPIO_ISR2A */
+        case 0xb3: /* GPIO_ISR3A */
+        case 0xc0: /* GPIO_EDR1 */
+        case 0xc1: /* GPIO_EDR2 */
+        case 0xc2: /* GPIO_EDR3 */
+        case 0xc3: /* GPIO_EDR4 */
+        case 0xc4: /* GPIO_EDR5 */
+            return s->reg_data[addr];
+        default:
+#ifdef VERBOSE
+            fprintf(stderr, "%s: unknown register %02x pc %x\n",
+                    __FUNCTION__, addr,cpu_single_env->regs[15]);
+#endif
+                       exit(-1);
+    }
+}
+
+static void twl4030_49_write(void *opaque, uint8_t addr, uint8_t value)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
+       
+    switch (addr) {
+        case 0x9b: /* GPIODATADIR1 */
+        case 0x9c: /* GPIODATADIR2 */
+        case 0x9d: /* GPIODATADIR3 */
+        case 0x9e: /* GPIODATAOUT1 */
+        case 0x9f: /* GPIODATAOUT2 */
+        case 0xa0: /* GPIODATAOUT3 */
+        case 0xa1: /* CLEARGPIODATAOUT1 */
+        case 0xa2: /* CLEARGPIODATAOUT2 */
+        case 0xa3: /* CLEARGPIODATAOUT3 */
+        case 0xa4: /* SETGPIODATAOUT1 */
+        case 0xa5: /* SETGPIODATAOUT2 */
+        case 0xa6: /* SETGPIODATAOUT3 */
+        case 0xa7: /* GPIO_DEBEN1 */
+        case 0xa8: /* GPIO_DEBEN2 */
+        case 0xa9: /* GPIO_DEBEN3 */
+        case 0xaa: /* GPIO_CTRL */
+        case 0xab: /* GPIOPUPDCTR1 */
+        case 0xac: /* GPIOPUPDCTR2 */
+        case 0xad: /* GPIOPUPDCTR3 */
+        case 0xae: /* GPIOPUPDCTR4 */
+            s->reg_data[addr] = value;
+            break;
+        case 0xaf: /* GPIOPUPDCTR5 */
+            s->reg_data[addr] = value & 0x0f;
+            break;
+           case 0xb4: /* GPIO_IMR1A */
+           case 0xb5: /* GPIO_IMR2A */
+            s->reg_data[addr] = value;
+            break;
+           case 0xb6: /* GPIO_IMR3A */
+            s->reg_data[addr] = value & 0x03;
+            break;
+           case 0xc0: /* GPIO_EDR1 */
+           case 0xc1: /* GPIO_EDR2 */
+           case 0xc2: /* GPIO_EDR3 */
+           case 0xc3: /* GPIO_EDR4 */
+           case 0xc4: /* GPIO_EDR5 */
+            s->reg_data[addr] = value;
+            break;
+           case 0xc5: /* GPIO_SIH_CTRL */
+            s->reg_data[addr] = value & 0x07;
+            break;
+        default:
+#ifdef VERBOSE
+            printf("%s: unknown register %02x pc %x \n", __FUNCTION__, addr,
+                   cpu_single_env->regs[15]);
+            //printf("%s: unknown register %02x \n", __FUNCTION__, addr);
+#endif
+            exit(-1);
+            break;
+    }
+}
+
+
+static int twl4030_49_tx(i2c_slave *i2c, uint8_t data)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+    /* Interpret register address byte */
+    if (s->firstbyte) {
+        s->reg = data;
+        s->firstbyte = 0;
+    } else
+        twl4030_49_write(s, s->reg++, data);
+       
+    return 0;
+}
+
+static int twl4030_49_rx(i2c_slave *i2c)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+       
+    return twl4030_49_read(s, s->reg++);
+}
+
+static void twl4030_49_reset(i2c_slave *i2c)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+    s->reg = 0x00;
+    memcpy(s->reg_data, addr_49_reset_values, 256);
+}
+
+static void twl4030_49_event(i2c_slave *i2c, enum i2c_event event)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+       
+    if (event == I2C_START_SEND)
+        s->firstbyte = 1;
+}
+
+static uint8_t twl4030_4a_read(void *opaque, uint8_t addr)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
+       
+    switch (addr) {
+        case 0x61: /* MADC_ISR1 */
+        case 0xb9: /* BCIISR1A */
+        case 0xba: /* BCIISR2A */
+        case 0xe3: /* KEYP_ISR1 */
+        case 0xee: /* LEDEN */
+            return s->reg_data[addr];
+        default:
+#ifdef VERBOSE
+               printf("%s: unknown register %02x pc %x \n", __FUNCTION__, addr,cpu_single_env->regs[15] );
+#endif
+            exit(-1);
+            break;
+    }
+}
+
+static void twl4030_4a_write(void *opaque, uint8_t addr, uint8_t value)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
+       
+    switch (addr) {
+        case 0x61: /* MADC_ISR1 */
+            s->reg_data[value] &= ~(value & 0x0f);
+            break;
+        case 0x62: /* MADC_IMR1 */
+            s->reg_data[value] = value & 0x0f;
+            break;
+        case 0xb9: /* BCIISR1A */
+            s->reg_data[value] &= ~value;
+            break;
+        case 0xba: /* BCIISR2A */
+            s->reg_data[value] &= ~(value & 0x0f);
+            break;
+        case 0xbb: /* BCIIMR1A */
+            s->reg_data[addr] = value;
+            break;
+        case 0xbc: /* BCIIMR2A */
+            s->reg_data[addr] = value & 0x0f;
+            break;
+        case 0xe4: /* KEYP_IMR1 */
+            s->reg_data[addr] = value & 0x0f;
+            break;
+        case 0xe9: /* KEYP_SIH_CTRL */
+            s->reg_data[addr] = value & 0x07;
+            break;
+        case 0xee: /* LEDEN */
+            s->reg_data[addr] = value;
+#ifdef VERBOSE
+            fprintf(stderr, "%s: LEDA power=%s/enable=%s, LEDB power=%s/enable=%s\n", __FUNCTION__,
+                    value & 0x10 ? "on" : "off", value & 0x01 ? "yes" : "no",
+                    value & 0x20 ? "on" : "off", value & 0x02 ? "yes" : "no");
+#endif      
+            break;
+        case 0xef: /* PWMAON */
+            s->reg_data[addr] = value;
+            break;
+        case 0xf0: /* PWMAOFF */
+            s->reg_data[addr] = value & 0x7f;
+            break;
+        default:
+#ifdef VERBOSE
+               printf("%s: unknown register %02x pc %x \n", __FUNCTION__, addr,cpu_single_env->regs[15] );
+#endif
+            exit(-1);
+            break;
+    }
+}
+
+static int twl4030_4a_tx(i2c_slave *i2c, uint8_t data)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+    /* Interpret register address byte */
+    if (s->firstbyte) {
+        s->reg = data;
+        s->firstbyte = 0;
+    } else
+        twl4030_4a_write(s, s->reg++, data);
+       
+    return 0;
+}
+
+static int twl4030_4a_rx(i2c_slave *i2c)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+       
+    return twl4030_4a_read(s, s->reg++);
+}
+
+static void twl4030_4a_reset(i2c_slave *i2c)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+    s->reg = 0x00;
+    memcpy(s->reg_data, addr_4a_reset_values, 256);
+}
+
+static void twl4030_4a_event(i2c_slave *i2c, enum i2c_event event)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+       
+    if (event == I2C_START_SEND)
+        s->firstbyte = 1;
+}
+
+static uint8_t twl4030_4b_read(void *opaque, uint8_t addr)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
+       
+    switch (addr) {
+        case 0x1c: /* RTC */
+        case 0x1d:
+        case 0x1e:
+        case 0x1f:
+        case 0x20:
+        case 0x21:
+        case 0x22:
+        case 0x23:
+        case 0x24:
+        case 0x25:
+        case 0x26:
+        case 0x27:
+        case 0x28:
+        case 0x29:
+        case 0x2a:
+        case 0x2b:
+        case 0x2c:
+        case 0x2d: /*RTC end */
+        case 0x2e: /* PWR_ISR1 */
+        case 0x33: /* PWR_EDR1 */
+        case 0x34: /* PWR_EDR2 */
+        case 0x45: /* STS_HW_CONDITIONS */
+            return s->reg_data[addr];
+        default:
+#ifdef VERBOSE
+               printf("%s: unknown register %02x pc %x \n", __FUNCTION__, addr,cpu_single_env->regs[15] );
+               //printf("%s: unknown register %02x \n", __FUNCTION__, addr);
+#endif
+            exit(-1);
+            break;
+    }
+}
+
+
+static void twl4030_4b_write(void *opaque, uint8_t addr, uint8_t value)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
+    uint8_t seq_addr, seq_sub;
+       
+    switch (addr) {
+        case 0x29: /* RTC_CTRL_REG */
+        case 0x2a: /* RTC_STATUS_REG */
+        case 0x2b: /* RTC_INTERRUPTS_REG */
+        case 0x33: /* PWR_EDR1 */
+        case 0x34: /* PWR_EDR2 */
+            s->reg_data[addr] = value;
+            break;
+        case 0x46: /* P1_SW_EVENTS */
+        case 0x47: /* P2_SW_EVENTS */
+        case 0x48: /* P3_SW_EVENTS */
+            s->reg_data[addr] = value & 0x78;
+            break;
+        case 0x52: /* SEQ_ADD_W2P */
+        case 0x53: /* SEQ_ADD_P2A */
+        case 0x54: /* SEQ_ADD_A2W */
+        case 0x55: /* SEQ_ADD_A2S */
+        case 0x56: /* SEQ_ADD_S2A12 */
+        case 0x57: /* SEQ_ADD_S2A3 */
+        case 0x58: /* SEQ_ADD_WARM */
+            if (s->twl4030->key_cfg)
+                s->reg_data[addr] = value & 0x3f;
+            break;
+        case 0x59: /* MEMORY_ADDRESS */
+            if (s->twl4030->key_cfg)
+                s->reg_data[addr] = value;
+            break;
+        case 0x5a: /* MEMORY_DATA */
+            if (s->twl4030->key_cfg) {
+                s->reg_data[addr] = value;
+                seq_addr = s->reg_data[0x59];
+                seq_sub = seq_addr & 3;
+                seq_addr >>= 2;
+                if ((seq_addr >= 0x2b && seq_addr <= 0x3e) || (seq_addr <= 0x0e && seq_sub == 3))
+                    s->twl4030->seq_mem[seq_addr][seq_sub] = value;
+            }
+            s->reg_data[0x59]++; /* TODO: check if autoincrement is write-protected as well */
+            break;
+        case 0x7a: /* VAUX3_DEV_GRP */
+        case 0x82: /* VMMC1_DEV_GRP */
+        case 0x8e: /* VPLL2_DEV_GRP */
+        case 0x96: /* VDAC_DEV_GRP */
+        case 0xcc: /* VUSB1V5_DEV_GRP */
+        case 0xcf: /* VUSB1V8_DEV_GRP */
+        case 0xd2: /* VUSB3V1_DEV_GRP */
+        case 0xe6: /* HFCLKOUT_DEV_GRP */
+            s->reg_data[addr] = (s->reg_data[addr] & 0x0f) | (value & 0xf0); 
+            break;
+        case 0x2f: /* PWR_IMR1 */
+            s->reg_data[addr] = value;
+            break;
+        case 0x35: /* PWR_SIH_CTRL */
+            s->reg_data[addr] = value & 0x07;
+            break;
+        case 0x3b: /* CFG_BOOT */
+            if (s->twl4030->key_cfg)
+                s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x8f);
+            break;
+        case 0x44: /* PROTECT_KEY */
+            s->twl4030->key_cfg = 0;
+            s->twl4030->key_tst = 0;
+            switch (value) {
+                case 0x0C: 
+                    if (s->reg_data[addr] == 0xC0)
+                        s->twl4030->key_cfg = 1;
+                    break;
+                case 0xE0:
+                    if (s->reg_data[addr] == 0x0E)
+                        s->twl4030->key_tst = 1;
+                    break;
+                case 0xEC:
+                    if (s->reg_data[addr] == 0xCE) {
+                        s->twl4030->key_cfg = 1;
+                        s->twl4030->key_tst = 1;
+                    }
+                    break;
+                default:
+                    break;
+            }
+            s->reg_data[addr] = value;
+            break;
+        case 0x7d: /* VAUX3_DEDICATED */
+            if (s->twl4030->key_tst)
+                s->reg_data[addr] = value & 0x77;
+            else
+                s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x07);
+            break;
+        case 0x85: /* VMMC1_DEDICATED */
+        case 0x99: /* VDAC_DEDICATED */
+            if (s->twl4030->key_tst) 
+                s->reg_data[addr] = value & 0x73;
+            else
+                s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x03);
+            break;
+        case 0x91: /* VPLL2_DEDICATED */
+            if (s->twl4030->key_tst)
+                s->reg_data[addr] = value & 0x7f;
+            else
+                s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x0f);
+            break;
+        case 0xcd: /* VUSB1V5_TYPE */
+        case 0xd0: /* VUSB1V8_TYPE */
+        case 0xd3: /* VUSB3V1_TYPE */
+            s->reg_data[addr] = value & 0x1f;
+            break;
+        case 0xd8: /* VUSB_DEDICATED1 */
+            s->reg_data[addr] = value & 0x1f;
+            break;
+        case 0xd9: /* VUSB_DEDICATED2 */
+            s->reg_data[addr] = value & 0x08;
+            break;
+            
+        default:
+#ifdef VERBOSE
+               fprintf(stderr, "%s: unknown register %02x value %0x pc %x \n", __FUNCTION__, 
+                    addr, value, cpu_single_env->regs[15]);
+#endif
+            exit(-1);
+            break;
+    }
+}
+
+static int twl4030_4b_tx(i2c_slave *i2c, uint8_t data)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+    /* Interpret register address byte */
+    if (s->firstbyte) {
+        s->reg = data;
+        s->firstbyte = 0;
+    } else
+        twl4030_4b_write(s, s->reg++, data);
+       
+    return 1;
+}
+
+static int twl4030_4b_rx(i2c_slave *i2c)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+       
+    return twl4030_4b_read(s, s->reg++);
+}
+
+static void twl4030_4b_reset(i2c_slave *i2c)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+    s->reg = 0x00;
+    memcpy(s->reg_data, addr_4b_reset_values, 256);
+    s->twl4030->key_cfg = 0;
+    s->twl4030->key_tst = 0;
+}
+
+static void twl4030_4b_event(i2c_slave *i2c, enum i2c_event event)
+{
+    struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
+       
+    if (event == I2C_START_SEND)
+        s->firstbyte = 1;
+}
+
+struct twl4030_s *twl4030_init(i2c_bus *bus, qemu_irq irq)
+{
+    int i;
+       
+    struct twl4030_s *s = (struct twl4030_s *) qemu_mallocz(sizeof(*s));
+       
+    if (!s)
+    {
+        fprintf(stderr,"can not alloc memory space for twl4030_s \n");
+        exit(-1);
+    }
+    for (i=0;i<5;i++)
+    {
+        s->i2c[i]=(struct twl4030_i2c_s *)i2c_slave_init(bus, 0, sizeof(struct twl4030_i2c_s));
+        s->i2c[i]->irq = irq;
+        s->i2c[i]->twl4030 = s;
+    }
+    s->i2c[0]->i2c.event = twl4030_48_event;
+    s->i2c[0]->i2c.recv = twl4030_48_rx;
+    s->i2c[0]->i2c.send = twl4030_48_tx;
+    twl4030_48_reset(&s->i2c[0]->i2c);
+    i2c_set_slave_address((i2c_slave *)&s->i2c[0]->i2c,0x48);
+       
+    s->i2c[1]->i2c.event = twl4030_49_event;
+    s->i2c[1]->i2c.recv = twl4030_49_rx;
+    s->i2c[1]->i2c.send = twl4030_49_tx;
+    twl4030_49_reset(&s->i2c[1]->i2c);
+    i2c_set_slave_address((i2c_slave *)&s->i2c[1]->i2c,0x49);
+       
+    s->i2c[2]->i2c.event = twl4030_4a_event;
+    s->i2c[2]->i2c.recv = twl4030_4a_rx;
+    s->i2c[2]->i2c.send = twl4030_4a_tx;
+    twl4030_4a_reset(&s->i2c[2]->i2c);
+    i2c_set_slave_address((i2c_slave *)&s->i2c[2]->i2c,0x4a);
+       
+    s->i2c[3]->i2c.event = twl4030_4b_event;
+    s->i2c[3]->i2c.recv = twl4030_4b_rx;
+    s->i2c[3]->i2c.send = twl4030_4b_tx;
+    twl4030_4b_reset(&s->i2c[3]->i2c);
+    i2c_set_slave_address((i2c_slave *)&s->i2c[3]->i2c,0x4b);
+    /*TODO:other group*/
+       
+       
+    //register_savevm("menelaus", -1, 0, menelaus_save, menelaus_load, s);
+    return s;
+}
+
+#if 0
+static uint8_t twl4030_read(void *opaque, uint8_t addr)
+{
+//    struct twl4030_s *s = (struct twl4030_s *) opaque;
+//    int reg = 0;
+
+    printf("twl4030_read addr %x\n",addr);
+
+    switch (addr)
+    {
+       default:
+#ifdef VERBOSE
+        printf("%s: unknown register %02x\n", __FUNCTION__, addr);
+#endif
+                       //exit(-1);
+                       break;
+    }
+    return 0x00;
+}
+
+static void twl4030_write(void *opaque, uint8_t addr, uint8_t value)
+{
+//    struct twl4030_s *s = (struct twl4030_s *) opaque;
+//    int line;
+//    int reg = 0;
+//    struct tm tm;
+
+    printf("twl4030_write addr %x value %x \n",addr,value);
+
+     switch (addr) 
+     {
+        case 0x82:
+        case 0x85:
+               /*mmc*/
+               break;
+        default:
+#ifdef VERBOSE
+        printf("%s: unknown register %02x\n", __FUNCTION__, addr);
+#endif
+                       //exit(-1);
+                       break;
+       }
+}
+
+
+static int twl4030_tx(i2c_slave *i2c, uint8_t data)
+{
+    struct twl4030_s *s = (struct twl4030_s *) i2c;
+    /* Interpret register address byte */
+    if (s->firstbyte) {
+        s->reg = data;
+        s->firstbyte = 0;
+    } else
+        twl4030_write(s, s->reg ++, data);
+
+    return 0;
+}
+
+static int twl4030_rx(i2c_slave *i2c)
+{
+    struct twl4030_s *s = (struct twl4030_s *) i2c;
+
+    return twl4030_read(s, s->reg ++);
+}
+
+static void twl4030_reset(i2c_slave *i2c)
+{
+    struct twl4030_s *s = (struct twl4030_s *) i2c;
+    s->reg = 0x00;
+}
+
+static void twl4030_event(i2c_slave *i2c, enum i2c_event event)
+{
+    struct twl4030_s *s = (struct twl4030_s *) i2c;
+
+    if (event == I2C_START_SEND)
+        s->firstbyte = 1;
+}
+
+i2c_slave *twl4030_init(i2c_bus *bus, qemu_irq irq)
+{
+    struct twl4030_s *s = (struct twl4030_s *)
+            i2c_slave_init(bus, 0, sizeof(struct twl4030_s));
+
+    s->i2c.event = twl4030_event;
+    s->i2c.recv = twl4030_rx;
+    s->i2c.send = twl4030_tx;
+
+    s->irq = irq;
+    //s->rtc.hz_tm = qemu_new_timer(rt_clock, menelaus_rtc_hz, s);
+    //s->in = qemu_allocate_irqs(menelaus_gpio_set, s, 3);
+    //s->pwrbtn = qemu_allocate_irqs(menelaus_pwrbtn_set, s, 1)[0];
+
+    twl4030_reset(&s->i2c);
+
+    //register_savevm("menelaus", -1, 0, menelaus_save, menelaus_load, s);
+
+    return &s->i2c;
+}
+#endif
+
index 6e2984c..724387a 100644 (file)
@@ -1004,7 +1004,7 @@ void cpu_loop (CPUSPARCState *env)
         default:
             printf ("Unhandled trap: 0x%x\n", trapnr);
             cpu_dump_state(env, stderr, fprintf, 0);
-            exit (1);
+            _exit (1);
         }
         process_pending_signals (env);
     }
@@ -1933,7 +1933,7 @@ void cpu_loop (CPUState *env)
         default:
             printf ("Unhandled trap: 0x%x\n", trapnr);
             cpu_dump_state(env, stderr, fprintf, 0);
-            exit (1);
+            _exit (1);
         }
         process_pending_signals (env);
     }
@@ -2193,6 +2193,7 @@ static void usage(void)
            "-drop-ld-preload  drop LD_PRELOAD for target process\n"
            "-E var=value      sets/modifies targets environment variable(s)\n"
            "-U var            unsets targets environment variable(s)\n"
+           "-0 argv0          forces target process argv[0] to be argv0\n"
            "\n"
            "Debug options:\n"
            "-d options   activate log (logfile=%s)\n"
@@ -2233,7 +2234,7 @@ void init_task_state(TaskState *ts)
  
 int main(int argc, char **argv, char **envp)
 {
-    const char *filename;
+    char *filename = NULL;
     const char *cpu_model;
     struct target_pt_regs regs1, *regs = &regs1;
     struct image_info info1, *info = &info1;
@@ -2243,7 +2244,12 @@ int main(int argc, char **argv, char **envp)
     const char *r;
     int gdbstub_port = 0;
     char **target_environ, **wrk;
+    char **target_argv;
+    int target_argc;
+    int drop_ld_preload = 0;
     envlist_t *envlist = NULL;
+    const char *argv0 = NULL;
+    int i;
 
     if (argc <= 1)
         usage();
@@ -2289,7 +2295,7 @@ int main(int argc, char **argv, char **envp)
                 for(item = cpu_log_items; item->mask != 0; item++) {
                     printf("%-10s %s\n", item->name, item->help);
                 }
-                exit(1);
+                _exit(1);
             }
             cpu_set_log(mask);
         } else if (!strcmp(r, "E")) {
@@ -2300,6 +2306,13 @@ int main(int argc, char **argv, char **envp)
             r = argv[optind++];
             if (envlist_unsetenv(envlist, r) != 0)
                 usage();
+        } else if (!strcmp(r, "0")) {
+            r = argv[optind++];
+            argv0 = r;
+        } else if (!strcmp(r,"-sbox-call")) {
+           r = argv[optind++];
+           filename = r;
+           exec_path = r;
         } else if (!strcmp(r, "s")) {
             if (optind >= argc)
                 break;
@@ -2320,7 +2333,7 @@ int main(int argc, char **argv, char **envp)
             if (qemu_host_page_size == 0 ||
                 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
                 fprintf(stderr, "page size must be a power of two\n");
-                exit(1);
+                _exit(1);
             }
         } else if (!strcmp(r, "g")) {
             if (optind >= argc)
@@ -2338,7 +2351,9 @@ int main(int argc, char **argv, char **envp)
                 exit(1);
             }
         } else if (!strcmp(r, "drop-ld-preload")) {
-            (void) envlist_unsetenv(envlist, "LD_PRELOAD");
+            drop_ld_preload = 1;
+        } else if (!strcmp(r, "keep-ld-preload")) {
+            drop_ld_preload = 0;
         } else if (!strcmp(r, "strace")) {
             do_strace = 1;
         } else
@@ -2348,8 +2363,15 @@ int main(int argc, char **argv, char **envp)
     }
     if (optind >= argc)
         usage();
-    filename = argv[optind];
-    exec_path = argv[optind];
+    if (filename == NULL) {
+        filename = argv[optind];
+        exec_path = argv[optind];
+    } else {
+        argv0 = argv[optind];
+    }
+    if (drop_ld_preload) {
+        (void) envlist_unsetenv(envlist, "LD_PRELOAD");
+    }
 
     /* Zero out regs */
     memset(regs, 0, sizeof(struct target_pt_regs));
@@ -2368,7 +2390,7 @@ int main(int argc, char **argv, char **envp)
         cpu_model = "qemu32";
 #endif
 #elif defined(TARGET_ARM)
-        cpu_model = "arm926";
+        cpu_model = "any";
 #elif defined(TARGET_M68K)
         cpu_model = "any";
 #elif defined(TARGET_SPARC)
@@ -2410,11 +2432,39 @@ int main(int argc, char **argv, char **envp)
     target_environ = envlist_to_environ(envlist, NULL);
     envlist_free(envlist);
 
-    if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) {
+    /*
+     * Prepare copy of argv vector for target.
+     */
+    target_argc = argc - optind;
+    target_argv = calloc(target_argc + 1, sizeof (char *));
+    if (target_argv == NULL) {
+       (void) fprintf(stderr, "Unable to allocate memory for target_argv\n");
+       exit(1);
+    }
+
+    /*
+     * If argv0 is specified (using '-0' switch) we replace
+     * argv[0] pointer with the given one.
+     */
+    i = 0;
+    if (argv0 != NULL) {
+        target_argv[i++] = strdup(argv0);
+    }
+    for (; i < target_argc; i++) {
+        target_argv[i] = strdup(argv[optind + i]);
+    }
+    target_argv[target_argc] = NULL;
+
+    if (loader_exec(filename, target_argv, target_environ, regs, info) != 0) {
         printf("Error loading %s\n", filename);
         _exit(1);
     }
 
+    for (i = 0; i < target_argc; i++) {
+        free(target_argv[i]);
+    }
+    free(target_argv);
+
     for (wrk = target_environ; *wrk; wrk++) {
         free(*wrk);
     }
index 6f300a0..8cec230 100644 (file)
@@ -275,52 +275,59 @@ static abi_ulong mmap_next_start = 0x40000000;
 
 unsigned long last_brk;
 
-/* find a free memory area of size 'size'. The search starts at
-   'start'. If 'start' == 0, then a default start address is used.
-   Return -1 if error.
-*/
-/* page_init() marks pages used by the host as reserved to be sure not
-   to use them. */
-static abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
+/*
+ * Find and reserve a free memory area of size 'size'. The search
+ * starts at 'start'.
+ * It must be called with mmap_lock() held.
+ * Return -1 if error.
+ */
+abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
 {
-    abi_ulong addr, addr1, addr_start;
-    int prot;
-    unsigned long new_brk;
-
-    new_brk = (unsigned long)sbrk(0);
-    if (last_brk && last_brk < new_brk && last_brk == (target_ulong)last_brk) {
-        /* This is a hack to catch the host allocating memory with brk().
-           If it uses mmap then we loose.
-           FIXME: We really want to avoid the host allocating memory in
-           the first place, and maybe leave some slack to avoid switching
-           to mmap.  */
-        page_set_flags(last_brk & TARGET_PAGE_MASK,
-                       TARGET_PAGE_ALIGN(new_brk),
-                       PAGE_RESERVED); 
-    }
-    last_brk = new_brk;
+    void *ptr;
+    abi_ulong addr;
 
     size = HOST_PAGE_ALIGN(size);
-    start = start & qemu_host_page_mask;
+    start &= qemu_host_page_mask;
+
+    /* If 'start' == 0, then a default start address is used. */
+    if (start == 0)
+        start = mmap_next_start;
+
     addr = start;
-    if (addr == 0)
-        addr = mmap_next_start;
-    addr_start = addr;
+
     for(;;) {
-        prot = 0;
-        for(addr1 = addr; addr1 < (addr + size); addr1 += TARGET_PAGE_SIZE) {
-            prot |= page_get_flags(addr1);
-        }
-        if (prot == 0)
+        /*
+         * Reserve needed memory area to avoid a race.
+         * It should be discarded using:
+         *  - mmap() with MAP_FIXED flag
+         *  - mremap() with MREMAP_FIXED flag
+         *  - shmat() with SHM_REMAP flag
+         */
+        ptr = mmap((void *)(unsigned long)addr, size, PROT_NONE,
+                   MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
+
+        /* ENOMEM, if host address space has no memory */
+        if (ptr == MAP_FAILED)
+            return (abi_ulong)-1;
+
+        /* If address fits target address space we've found what we need */
+        if ((unsigned long)ptr + size - 1 <= (abi_ulong)-1)
             break;
+
+        /* Unmap and try again with new page */
+        munmap(ptr, size);
         addr += qemu_host_page_size;
-        /* we found nothing */
-        if (addr == addr_start)
+
+        /* ENOMEM if we check whole of target address space */
+        if (addr == start)
             return (abi_ulong)-1;
     }
-    if (start == 0)
-        mmap_next_start = addr + size;
-    return addr;
+
+    /* Update default start address */
+    if (start == mmap_next_start)
+        mmap_next_start = (unsigned long)ptr + size;
+
+    return h2g(ptr);
 }
 
 /* NOTE: all the constants are the HOST ones */
index 06b1f5f..b991af0 100644 (file)
@@ -4,6 +4,7 @@
    The assumption is that this area does not change.
 */
 #include <sys/types.h>
+#include <assert.h>
 #include <dirent.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -52,6 +53,38 @@ static struct pathelem *new_entry(const char *root,
 
 #define streq(a,b) (strcmp((a), (b)) == 0)
 
+/*
+ * Checks whether directory entry (dent) is valid.  This
+ * means that symlinks pointing to '.' and '..' should
+ * be skipped by main recursion code.  Returns 1 when
+ * entry is valid.
+ */
+static int
+is_dentry_valid(const char *path, const struct dirent *dent)
+{
+    char fullpath[PATH_MAX];
+    char linkbuf[PATH_MAX];
+    ssize_t len;
+
+    assert(path != NULL);
+    assert(dent != NULL);
+
+    if (dent->d_type != DT_LNK)
+        return (1);
+
+    (void) snprintf(fullpath, sizeof (fullpath), "%s/%s",
+       path, dent->d_name);
+
+    if ((len = readlink(fullpath, linkbuf, sizeof (linkbuf) - 1)) != -1) {
+        linkbuf[len] = '\0';
+        if (streq(linkbuf, ".") || streq(linkbuf, ".."))
+            return (0);
+    }
+
+    return (1);
+}
+
+/* TODO: add recursion count check */
 static struct pathelem *add_dir_maybe(struct pathelem *path)
 {
     DIR *dir;
@@ -61,7 +94,9 @@ static struct pathelem *add_dir_maybe(struct pathelem *path)
 
        while ((dirent = readdir(dir)) != NULL) {
            if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){
-               path = add_entry(path, dirent->d_name);
+               if (is_dentry_valid(path->pathname, dirent)) {
+                   path = add_entry(path, dirent->d_name);
+               }
            }
        }
         closedir(dir);
index 4f3741e..cb07b2e 100644 (file)
@@ -25,6 +25,7 @@
 #include <unistd.h>
 #include <signal.h>
 #include <errno.h>
+#include <assert.h>
 #include <sys/ucontext.h>
 
 #include "qemu.h"
@@ -352,22 +353,34 @@ static inline void free_sigqueue(CPUState *env, struct sigqueue *q)
 static void QEMU_NORETURN force_sig(int sig)
 {
     int host_sig;
+    struct sigaction act;
     host_sig = target_to_host_signal(sig);
     fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",
             sig, strsignal(host_sig));
-#if 1
     gdb_signalled(thread_env, sig);
-    _exit(-host_sig);
-#else
-    {
-        struct sigaction act;
-        sigemptyset(&act.sa_mask);
-        act.sa_flags = SA_SIGINFO;
-        act.sa_sigaction = SIG_DFL;
-        sigaction(SIGABRT, &act, NULL);
-        abort();
-    }
-#endif
+
+    /* The proper exit code for dieing from an uncaught signal is
+     * -<signal>.  The kernel doesn't allow exit() or _exit() to pass
+     * a negative value.  To get the proper exit code we need to
+     * actually die from an uncaught signal.  Here the default signal
+     * handler is installed, we send ourself a signal and we wait for
+     * it to arrive. */
+    sigfillset(&act.sa_mask);
+    act.sa_handler = SIG_DFL;
+    sigaction(host_sig, &act, NULL);
+
+    /* For some reason raise(host_sig) doesn't send the signal when
+     * statically linked on x86-64. */
+    kill(getpid(), host_sig);
+
+    /* Make sure the signal isn't masked (just reuse the mask inside
+    of act) */
+    sigdelset(&act.sa_mask, host_sig);
+    sigsuspend(&act.sa_mask);
+
+    /* unreachable */
+    assert(0);
+
 }
 
 /* queue a signal so that it will be send to the virtual CPU as soon
index 09a801f..3f688db 100644 (file)
 { TARGET_NR_mpx, "mpx" , NULL, NULL, NULL },
 #endif
 #ifdef TARGET_NR_mq_getsetattr
-{ TARGET_NR_mq_getsetattr, "mq_getsetattr" , NULL, NULL, NULL },
+{ TARGET_NR_mq_getsetattr, "mq_getsetattr" , "%s(%d,%p,%p)", NULL, NULL },
 #endif
 #ifdef TARGET_NR_mq_notify
-{ TARGET_NR_mq_notify, "mq_notify" , NULL, NULL, NULL },
+{ TARGET_NR_mq_notify, "mq_notify" , "%s(%d,%p)", NULL, NULL },
 #endif
 #ifdef TARGET_NR_mq_open
-{ TARGET_NR_mq_open, "mq_open" , NULL, NULL, NULL },
+{ TARGET_NR_mq_open, "mq_open" , "%s(\"/%s\",%#x,%#o,%p)", NULL, NULL },
 #endif
 #ifdef TARGET_NR_mq_timedreceive
-{ TARGET_NR_mq_timedreceive, "mq_timedreceive" , NULL, NULL, NULL },
+{ TARGET_NR_mq_timedreceive, "mq_timedreceive" , "%s(%d,%p,%d,%u,%p)", NULL, NULL },
 #endif
 #ifdef TARGET_NR_mq_timedsend
-{ TARGET_NR_mq_timedsend, "mq_timedsend" , NULL, NULL, NULL },
+{ TARGET_NR_mq_timedsend, "mq_timedsend" , "%s(%d,%p,%d,%u,%p)", NULL, NULL },
 #endif
 #ifdef TARGET_NR_mq_unlink
-{ TARGET_NR_mq_unlink, "mq_unlink" , NULL, NULL, NULL },
+{ TARGET_NR_mq_unlink, "mq_unlink" , "%s(%s)", NULL, NULL },
 #endif
 #ifdef TARGET_NR_mremap
 { TARGET_NR_mremap, "mremap" , NULL, NULL, NULL },
index 40eab4e..b5d2406 100644 (file)
@@ -29,6 +29,7 @@
 #include <fcntl.h>
 #include <time.h>
 #include <limits.h>
+#include <mqueue.h>
 #include <sys/types.h>
 #include <sys/ipc.h>
 #include <sys/msg.h>
@@ -43,6 +44,7 @@
 #include <signal.h>
 #include <sched.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 #include <sys/uio.h>
 #include <sys/poll.h>
 #include <sys/times.h>
@@ -51,6 +53,7 @@
 #include <sys/statfs.h>
 #include <utime.h>
 #include <sys/sysinfo.h>
+#include <sys/utsname.h>
 //#include <sys/user.h>
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
@@ -170,6 +173,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,   \
 #define __NR_sys_linkat __NR_linkat
 #define __NR_sys_mkdirat __NR_mkdirat
 #define __NR_sys_mknodat __NR_mknodat
+#define __NR_sys_newfstatat __NR_newfstatat
 #define __NR_sys_openat __NR_openat
 #define __NR_sys_readlinkat __NR_readlinkat
 #define __NR_sys_renameat __NR_renameat
@@ -199,19 +203,8 @@ static int gettid(void) {
 }
 #endif
 _syscall1(int,sys_exit,int,status)
-_syscall1(int,sys_uname,struct new_utsname *,buf)
-#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
-_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
-#endif
-#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
-_syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
-          mode_t,mode,int,flags)
-#endif
-#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
-_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
-          uid_t,owner,gid_t,group,int,flags)
-#endif
-#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64)
+#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
+        defined(__NR_fstatat64)
 _syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
           struct stat *,buf,int,flags)
 #endif
@@ -219,7 +212,6 @@ _syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
 _syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
          const struct timeval *,times)
 #endif
-_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
 #if TARGET_ABI_BITS == 32
 _syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
 #endif
@@ -231,33 +223,12 @@ _syscall2(int, sys_getpriority, int, which, int, who);
 _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
           loff_t *, res, uint, wh);
 #endif
-#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
-_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
-         int,newdirfd,const char *,newpath,int,flags)
-#endif
-#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
-_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
-#endif
-#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
-_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
-          mode_t,mode,dev_t,dev)
-#endif
-#if defined(TARGET_NR_openat) && defined(__NR_openat)
-_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
-#endif
-#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
-_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
-          char *,buf,size_t,bufsize)
-#endif
-#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
-_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
-          int,newdirfd,const char *,newpath)
+#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
+        defined(__NR_newfstatat)
+_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
+          struct stat *,buf,int,flags)
 #endif
 _syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
-#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
-_syscall3(int,sys_symlinkat,const char *,oldpath,
-          int,newdirfd,const char *,newpath)
-#endif
 _syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
 #if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
 _syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
@@ -271,13 +242,6 @@ _syscall1(int,exit_group,int,error_code)
 #if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
 _syscall1(int,set_tid_address,int *,tidptr)
 #endif
-#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
-_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
-#endif
-#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
-_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
-          const struct timespec *,tsp,int,flags)
-#endif
 #if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
 _syscall0(int,sys_inotify_init)
 #endif
@@ -294,6 +258,230 @@ _syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
 #endif
 #endif
 
+static bitmask_transtbl fcntl_flags_tbl[] = {
+  { TARGET_O_ACCMODE,   TARGET_O_WRONLY,    O_ACCMODE,   O_WRONLY,    },
+  { TARGET_O_ACCMODE,   TARGET_O_RDWR,      O_ACCMODE,   O_RDWR,      },
+  { TARGET_O_CREAT,     TARGET_O_CREAT,     O_CREAT,     O_CREAT,     },
+  { TARGET_O_EXCL,      TARGET_O_EXCL,      O_EXCL,      O_EXCL,      },
+  { TARGET_O_NOCTTY,    TARGET_O_NOCTTY,    O_NOCTTY,    O_NOCTTY,    },
+  { TARGET_O_TRUNC,     TARGET_O_TRUNC,     O_TRUNC,     O_TRUNC,     },
+  { TARGET_O_APPEND,    TARGET_O_APPEND,    O_APPEND,    O_APPEND,    },
+  { TARGET_O_NONBLOCK,  TARGET_O_NONBLOCK,  O_NONBLOCK,  O_NONBLOCK,  },
+  { TARGET_O_SYNC,      TARGET_O_SYNC,      O_SYNC,      O_SYNC,      },
+  { TARGET_FASYNC,      TARGET_FASYNC,      FASYNC,      FASYNC,      },
+  { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
+  { TARGET_O_NOFOLLOW,  TARGET_O_NOFOLLOW,  O_NOFOLLOW,  O_NOFOLLOW,  },
+  { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
+#if defined(O_DIRECT)
+  { TARGET_O_DIRECT,    TARGET_O_DIRECT,    O_DIRECT,    O_DIRECT,    },
+#endif
+  { 0, 0, 0, 0 }
+};
+
+static int
+sys_uname(struct new_utsname *buf)
+{
+  struct utsname uts_buf;
+
+  if (uname(&uts_buf) < 0)
+      return (-1);
+
+  /*
+   * Just in case these have some differences, we
+   * translate utsname to new_utsname (which is the
+   * struct linux kernel uses).
+   */
+
+#define COPY_UTSNAME_FIELD(dest, src) \
+  do { \
+      /* __NEW_UTS_LEN doesn't include terminating null */ \
+      (void) strncpy((dest), (src), __NEW_UTS_LEN); \
+      (dest)[__NEW_UTS_LEN] = '\0'; \
+  } while (0)
+
+  bzero(buf, sizeof (*buf));
+  COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
+  COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
+  COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
+  COPY_UTSNAME_FIELD(buf->version, uts_buf.version);
+  COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine);
+#ifdef _GNU_SOURCE
+  COPY_UTSNAME_FIELD(buf->domainname, uts_buf.domainname);
+#endif
+  return (0);
+
+#undef COPY_UTSNAME_FIELD
+}
+
+static int
+sys_getcwd1(char *buf, size_t size)
+{
+  if (getcwd(buf, size) == NULL) {
+      /* getcwd() sets errno */
+      return (-1);
+  }
+  return (0);
+}
+
+#ifdef CONFIG_ATFILE
+
+/*
+ * Host system seems to have atfile syscall stubs available.  We
+ * now enable them one by one as specified by target syscall_nr.h.
+ */
+
+#ifdef TARGET_NR_openat
+static int
+sys_openat(int dirfd, const char *pathname, int flags, ...)
+{
+  /*
+   * open(2) has extra parameter 'mode' when called with
+   * flag O_CREAT.
+   */
+  if ((flags & O_CREAT) != 0) {
+      va_list ap;
+      mode_t mode;
+
+      /*
+       * Get the 'mode' parameter and translate it to
+       * host bits.
+       */
+      va_start(ap, flags);
+      mode = va_arg(ap, mode_t);
+      mode = target_to_host_bitmask(mode, fcntl_flags_tbl);
+      va_end(ap);
+
+      return (openat(dirfd, pathname, flags, mode));
+  }
+  return (openat(dirfd, pathname, flags));
+}
+#endif
+
+#ifdef TARGET_NR_mkdirat
+static int
+sys_mkdirat(int dirfd, const char *pathname, mode_t mode)
+{
+  return (mkdirat(dirfd, pathname, mode));
+}
+#endif
+
+#ifdef TARGET_NR_mknodat
+static int
+sys_mknodat(int dirfd, const char *pathname, mode_t mode, dev_t dev)
+{
+  return (mknodat(dirfd, pathname, mode, dev));
+}
+#endif
+
+#ifdef TARGET_NR_fchownat
+static int
+sys_fchownat(int dirfd, const char *pathname, uid_t owner,
+    gid_t group, int flags)
+{
+  return (fchownat(dirfd, pathname, owner, group, flags));
+}
+#endif
+
+#ifdef TARGET_NR_fstatat
+static int
+sys_fstatat64(int dirfd, const char *pathname, struct stat *buf,
+    int flags)
+{
+  return (fstatat64(dirfd, pathname, buf, flags));
+}
+#endif
+
+#ifdef TARGET_NR_unlinkat
+static int
+sys_unlinkat(int dirfd, const char *pathname, int flags)
+{
+  return (unlinkat(dirfd, pathname, flags));
+}
+#endif
+
+#ifdef TARGET_NR_renameat
+static int
+sys_renameat(int olddirfd, const char *oldpath,
+    int newdirfd, const char *newpath)
+{
+  return (renameat(olddirfd, oldpath, newdirfd, newpath));
+}
+#endif
+
+#ifdef TARGET_NR_linkat
+static int
+sys_linkat(int olddirfd, const char *oldpath,
+    int newdirfd, const char *newpath, int flags)
+{
+  return (linkat(olddirfd, oldpath, newdirfd, newpath, flags));
+}
+#endif
+
+#ifdef TARGET_NR_symlinkat
+static int
+sys_symlinkat(const char *oldpath, int newdirfd, const char *newpath)
+{
+  return (symlinkat(oldpath, newdirfd, newpath));
+}
+#endif
+
+#ifdef TARGET_NR_readlinkat
+static int
+sys_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
+{
+  return (readlinkat(dirfd, pathname, buf, bufsiz));
+}
+#endif
+
+#ifdef TARGET_NR_fchmodat
+static int
+sys_fchmodat(int dirfd, const char *pathname, mode_t mode, int flags)
+{
+  return (fchmodat(dirfd, pathname, mode, flags));
+}
+#endif
+
+#ifdef TARGET_NR_faccessat
+static int
+sys_faccessat(int dirfd, const char *pathname, int mode, int flags)
+{
+  return (faccessat(dirfd, pathname, mode, flags));
+}
+#endif
+
+#ifdef TARGET_NR_utimensat
+static int
+sys_utimensat(int dirfd, const char *pathname,
+    const struct timespec times[2], int flags)
+{
+  return (utimensat(dirfd, pathname, times, flags));
+}
+#endif
+
+#else /* !CONFIG_ATFILE */
+
+/*
+ * Host system doesn't have these available so we don't try
+ * to implement them.
+ */
+
+#undef TARGET_NR_openat
+#undef TARGET_NR_mkdirat
+#undef TARGET_NR_mknodat
+#undef TARGET_NR_fchownat
+#undef TARGET_NR_fstatat
+#undef TARGET_NR_unlinkat
+#undef TARGET_NR_renameat
+#undef TARGET_NR_linkat
+#undef TARGET_NR_symlinkat
+#undef TARGET_NR_readlinkat
+#undef TARGET_NR_fchmodat
+#undef TARGET_NR_faccessat
+#undef TARGET_NR_utimensat
+
+#endif /* CONFIG_ATFILE */
+
+
 extern int personality(int);
 extern int flock(int, int);
 extern int setfsuid(int);
@@ -630,6 +818,43 @@ static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
     return 0;
 }
 
+static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
+                                              abi_ulong target_mq_attr_addr)
+{
+    struct target_mq_attr *target_mq_attr;
+
+    if (!lock_user_struct(VERIFY_READ, target_mq_attr,
+                          target_mq_attr_addr, 1))
+        return -TARGET_EFAULT;
+
+    __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
+    __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
+    __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
+    __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
+
+    unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
+
+    return 0;
+}
+
+static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
+                                            const struct mq_attr *attr)
+{
+    struct target_mq_attr *target_mq_attr;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
+                          target_mq_attr_addr, 0))
+        return -TARGET_EFAULT;
+
+    __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
+    __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
+    __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
+    __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
+
+    unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
+
+    return 0;
+}
 
 /* do_select() must return target values and target errnos. */
 static abi_long do_select(int n,
@@ -692,13 +917,37 @@ static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
                                                abi_ulong target_addr,
                                                socklen_t len)
 {
+    const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
+    sa_family_t sa_family;
     struct target_sockaddr *target_saddr;
 
     target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
     if (!target_saddr)
         return -TARGET_EFAULT;
+
+    sa_family = tswap16(target_saddr->sa_family);
+
+    /* Oops. The caller might send a incomplete sun_path; sun_path
+     * must be terminated by \0 (see the manual page), but
+     * unfortunately it is quite common to specify sockaddr_un
+     * length as "strlen(x->sun_path)" while it should be
+     * "strlen(...) + 1". We'll fix that here if needed.
+     * Linux kernel has a similar feature.
+     */
+
+    if (sa_family == AF_UNIX) {
+        if (len < unix_maxlen) {
+            char *cp = (char*)target_saddr;
+
+            if ( cp[len-1] && !cp[len] )
+                len++;
+        }
+        if (len > unix_maxlen)
+            len = unix_maxlen;
+    }
+
     memcpy(addr, target_saddr, len);
-    addr->sa_family = tswap16(target_saddr->sa_family);
+    addr->sa_family = sa_family;
     unlock_user(target_saddr, target_addr, 0);
 
     return 0;
@@ -1152,7 +1401,7 @@ static abi_long do_bind(int sockfd, abi_ulong target_addr,
     if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
         return -TARGET_EINVAL;
 
-    addr = alloca(addrlen);
+    addr = alloca(addrlen+1);
 
     target_to_host_sockaddr(addr, target_addr, addrlen);
     return get_errno(bind(sockfd, addr, addrlen));
@@ -1236,6 +1485,9 @@ static abi_long do_accept(int fd, abi_ulong target_addr,
     void *addr;
     abi_long ret;
 
+    if (target_addr == 0)
+       return get_errno(accept(fd, NULL, NULL));
+
     if (get_user_u32(addrlen, target_addrlen_addr))
         return -TARGET_EFAULT;
 
@@ -1647,14 +1899,12 @@ static abi_long do_socketcall(int num, abi_ulong vptr)
 }
 #endif
 
-#ifdef TARGET_NR_ipc
 #define N_SHM_REGIONS  32
 
 static struct shm_region {
     abi_ulong  start;
     abi_ulong  size;
 } shm_regions[N_SHM_REGIONS];
-#endif
 
 struct target_ipc_perm
 {
@@ -1673,14 +1923,14 @@ struct target_ipc_perm
 
 struct target_semid_ds
 {
-  struct target_ipc_perm sem_perm;
-  abi_ulong sem_otime;
-  abi_ulong __unused1;
-  abi_ulong sem_ctime;
-  abi_ulong __unused2;
-  abi_ulong sem_nsems;
-  abi_ulong __unused3;
-  abi_ulong __unused4;
+    struct target_ipc_perm sem_perm;
+    abi_ulong sem_otime;
+    abi_ulong __unused1;
+    abi_ulong sem_ctime;
+    abi_ulong __unused2;
+    abi_ulong sem_nsems;
+    abi_ulong __unused3;
+    abi_ulong __unused4;
 };
 
 static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
@@ -1728,7 +1978,8 @@ static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
 
     if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
         return -TARGET_EFAULT;
-    target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
+    if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
+        return -TARGET_EFAULT;
     host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
     host_sd->sem_otime = tswapl(target_sd->sem_otime);
     host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
@@ -1743,7 +1994,8 @@ static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
 
     if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
         return -TARGET_EFAULT;
-    host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
+    if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
+        return -TARGET_EFAULT;;
     target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
     target_sd->sem_otime = tswapl(host_sd->sem_otime);
     target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
@@ -1751,135 +2003,215 @@ static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
     return 0;
 }
 
+struct target_seminfo {
+    int semmap;
+    int semmni;
+    int semmns;
+    int semmnu;
+    int semmsl;
+    int semopm;
+    int semume;
+    int semusz;
+    int semvmx;
+    int semaem;
+};
+
+static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
+                                              struct seminfo *host_seminfo)
+{
+    struct target_seminfo *target_seminfo;
+    if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
+        return -TARGET_EFAULT;
+    __put_user(host_seminfo->semmap, &target_seminfo->semmap);
+    __put_user(host_seminfo->semmni, &target_seminfo->semmni);
+    __put_user(host_seminfo->semmns, &target_seminfo->semmns);
+    __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
+    __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
+    __put_user(host_seminfo->semopm, &target_seminfo->semopm);
+    __put_user(host_seminfo->semume, &target_seminfo->semume);
+    __put_user(host_seminfo->semusz, &target_seminfo->semusz);
+    __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
+    __put_user(host_seminfo->semaem, &target_seminfo->semaem);
+    unlock_user_struct(target_seminfo, target_addr, 1);
+    return 0;
+}
+
 union semun {
-       int val;
-       struct semid_ds *buf;
-       unsigned short *array;
+    int val;
+    struct semid_ds *buf;
+    unsigned short *array;
+    struct seminfo *__buf;
 };
 
 union target_semun {
-       int val;
-       abi_long buf;
-       unsigned short int *array;
+    int val;
+    abi_ulong buf;
+    abi_ulong array;
+    abi_ulong __buf;
 };
 
-static inline abi_long target_to_host_semun(int cmd,
-                                            union semun *host_su,
-                                            abi_ulong target_addr,
-                                            struct semid_ds *ds)
+static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
+                                               abi_ulong target_addr)
 {
-    union target_semun *target_su;
-
-    switch( cmd ) {
-       case IPC_STAT:
-       case IPC_SET:
-           if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
-               return -TARGET_EFAULT;
-          target_to_host_semid_ds(ds,target_su->buf);
-          host_su->buf = ds;
-           unlock_user_struct(target_su, target_addr, 0);
-          break;
-       case GETVAL:
-       case SETVAL:
-           if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
-               return -TARGET_EFAULT;
-          host_su->val = tswapl(target_su->val);
-           unlock_user_struct(target_su, target_addr, 0);
-          break;
-       case GETALL:
-       case SETALL:
-           if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
-               return -TARGET_EFAULT;
-          *host_su->array = tswap16(*target_su->array);
-           unlock_user_struct(target_su, target_addr, 0);
-          break;
-       default:
-           gemu_log("semun operation not fully supported: %d\n", (int)cmd);
+    int nsems;
+    unsigned short *array;
+    union semun semun;
+    struct semid_ds semid_ds;
+    int i, ret;
+
+    semun.buf = &semid_ds;
+
+    ret = semctl(semid, 0, IPC_STAT, semun);
+    if (ret == -1)
+        return get_errno(ret);
+
+    nsems = semid_ds.sem_nsems;
+
+    *host_array = malloc(nsems*sizeof(unsigned short));
+    array = lock_user(VERIFY_READ, target_addr,
+                      nsems*sizeof(unsigned short), 1);
+    if (!array)
+        return -TARGET_EFAULT;
+
+    for(i=0; i<nsems; i++) {
+        __get_user((*host_array)[i], &array[i]);
     }
+    unlock_user(array, target_addr, 0);
+
     return 0;
 }
 
-static inline abi_long host_to_target_semun(int cmd,
-                                            abi_ulong target_addr,
-                                            union semun *host_su,
-                                            struct semid_ds *ds)
+static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
+                                               unsigned short **host_array)
 {
-    union target_semun *target_su;
-
-    switch( cmd ) {
-       case IPC_STAT:
-       case IPC_SET:
-           if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
-               return -TARGET_EFAULT;
-          host_to_target_semid_ds(target_su->buf,ds);
-           unlock_user_struct(target_su, target_addr, 1);
-          break;
-       case GETVAL:
-       case SETVAL:
-           if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
-               return -TARGET_EFAULT;
-          target_su->val = tswapl(host_su->val);
-           unlock_user_struct(target_su, target_addr, 1);
-          break;
-       case GETALL:
-       case SETALL:
-           if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
-               return -TARGET_EFAULT;
-          *target_su->array = tswap16(*host_su->array);
-           unlock_user_struct(target_su, target_addr, 1);
-          break;
-        default:
-           gemu_log("semun operation not fully supported: %d\n", (int)cmd);
+    int nsems;
+    unsigned short *array;
+    union semun semun;
+    struct semid_ds semid_ds;
+    int i, ret;
+
+    semun.buf = &semid_ds;
+
+    ret = semctl(semid, 0, IPC_STAT, semun);
+    if (ret == -1)
+        return get_errno(ret);
+
+    nsems = semid_ds.sem_nsems;
+
+    array = lock_user(VERIFY_WRITE, target_addr,
+                      nsems*sizeof(unsigned short), 0);
+    if (!array)
+        return -TARGET_EFAULT;
+
+    for(i=0; i<nsems; i++) {
+        __put_user((*host_array)[i], &array[i]);
     }
+    free(*host_array);
+    unlock_user(array, target_addr, 1);
+
     return 0;
 }
 
-static inline abi_long do_semctl(int first, int second, int third,
-                                 abi_long ptr)
+static inline abi_long do_semctl(int semid, int semnum, int cmd,
+                                 union target_semun target_su)
 {
     union semun arg;
     struct semid_ds dsarg;
-    int cmd = third&0xff;
-    abi_long ret = 0;
+    unsigned short *array;
+    struct seminfo seminfo;
+    abi_long ret = -TARGET_EINVAL;
+    abi_long err;
 
-    switch( cmd ) {
-       case GETVAL:
-            target_to_host_semun(cmd,&arg,ptr,&dsarg);
-            ret = get_errno(semctl(first, second, cmd, arg));
-            host_to_target_semun(cmd,ptr,&arg,&dsarg);
-            break;
-       case SETVAL:
-            target_to_host_semun(cmd,&arg,ptr,&dsarg);
-            ret = get_errno(semctl(first, second, cmd, arg));
-            host_to_target_semun(cmd,ptr,&arg,&dsarg);
-            break;
-       case GETALL:
-            target_to_host_semun(cmd,&arg,ptr,&dsarg);
-            ret = get_errno(semctl(first, second, cmd, arg));
-            host_to_target_semun(cmd,ptr,&arg,&dsarg);
-            break;
-       case SETALL:
-            target_to_host_semun(cmd,&arg,ptr,&dsarg);
-            ret = get_errno(semctl(first, second, cmd, arg));
-            host_to_target_semun(cmd,ptr,&arg,&dsarg);
-            break;
-       case IPC_STAT:
-            target_to_host_semun(cmd,&arg,ptr,&dsarg);
-            ret = get_errno(semctl(first, second, cmd, arg));
-            host_to_target_semun(cmd,ptr,&arg,&dsarg);
-            break;
-       case IPC_SET:
-            target_to_host_semun(cmd,&arg,ptr,&dsarg);
-            ret = get_errno(semctl(first, second, cmd, arg));
-            host_to_target_semun(cmd,ptr,&arg,&dsarg);
-            break;
-    default:
-            ret = get_errno(semctl(first, second, cmd, arg));
+    cmd &= 0xff;
+
+    switch (cmd) {
+    case IPC_STAT:
+    case IPC_SET:
+    case SEM_STAT:
+        err = target_to_host_semid_ds(&dsarg, target_su.buf);
+        if (err)
+            return err;
+        arg.buf = &dsarg;
+        ret = get_errno(semctl(semid, semnum, cmd, arg));
+        err = host_to_target_semid_ds(target_su.buf, &dsarg);
+        if (err)
+            return err;
+        break;
+    case GETVAL:
+    case SETVAL:
+        arg.val = tswapl(target_su.val);
+        ret = get_errno(semctl(semid, semnum, cmd, arg));
+        target_su.val = tswapl(arg.val);
+        break;
+    case GETALL:
+    case SETALL:
+        err = target_to_host_semarray(semid, &array, target_su.array);
+        if (err)
+            return err;
+        arg.array = array;
+        ret = get_errno(semctl(semid, semnum, cmd, arg));
+        err = host_to_target_semarray(semid, target_su.array, &array);
+        if (err)
+            return err;
+        break;
+    case IPC_INFO:
+    case SEM_INFO:
+        arg.__buf = &seminfo;
+        ret = get_errno(semctl(semid, semnum, cmd, arg));
+        err = host_to_target_seminfo(target_su.__buf, &seminfo);
+        if (err)
+            return err;
+        break;
+    case IPC_RMID:
+    case GETPID:
+    case GETNCNT:
+    case GETZCNT:
+        ret = get_errno(semctl(semid, semnum, cmd, NULL));
+        break;
     }
 
     return ret;
 }
 
+struct target_sembuf {
+    unsigned short sem_num;
+    short sem_op;
+    short sem_flg;
+};
+
+static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
+                                             abi_ulong target_addr,
+                                             unsigned nsops)
+{
+    struct target_sembuf *target_sembuf;
+    int i;
+
+    target_sembuf = lock_user(VERIFY_READ, target_addr,
+                              nsops*sizeof(struct target_sembuf), 1);
+    if (!target_sembuf)
+        return -TARGET_EFAULT;
+
+    for(i=0; i<nsops; i++) {
+        __put_user(target_sembuf[i].sem_num, &host_sembuf[i].sem_num);
+        __put_user(target_sembuf[i].sem_op, &host_sembuf[i].sem_op);
+        __put_user(target_sembuf[i].sem_flg, &host_sembuf[i].sem_flg);
+    }
+
+    unlock_user(target_sembuf, target_addr, 0);
+
+    return 0;
+}
+
+static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
+{
+    struct sembuf sops[nsops];
+
+    if (target_to_host_sembuf(sops, ptr, nsops))
+        return -TARGET_EFAULT;
+
+    return semop(semid, sops, nsops);
+}
+
 struct target_msqid_ds
 {
     struct target_ipc_perm msg_perm;
@@ -2066,6 +2398,224 @@ end:
     return ret;
 }
 
+struct target_shmid_ds
+{
+    struct target_ipc_perm shm_perm;
+    abi_ulong shm_segsz;
+    abi_ulong shm_atime;
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused1;
+#endif
+    abi_ulong shm_dtime;
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused2;
+#endif
+    abi_ulong shm_ctime;
+#if TARGET_ABI_BITS == 32
+    abi_ulong __unused3;
+#endif
+    int shm_cpid;
+    int shm_lpid;
+    abi_ulong shm_nattch;
+    unsigned long int __unused4;
+    unsigned long int __unused5;
+};
+
+static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
+                                               abi_ulong target_addr)
+{
+    struct target_shmid_ds *target_sd;
+
+    if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
+        return -TARGET_EFAULT;
+    if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
+        return -TARGET_EFAULT;
+    __put_user(target_sd->shm_segsz, &host_sd->shm_segsz);
+    __put_user(target_sd->shm_atime, &host_sd->shm_atime);
+    __put_user(target_sd->shm_dtime, &host_sd->shm_dtime);
+    __put_user(target_sd->shm_ctime, &host_sd->shm_ctime);
+    __put_user(target_sd->shm_cpid, &host_sd->shm_cpid);
+    __put_user(target_sd->shm_lpid, &host_sd->shm_lpid);
+    __put_user(target_sd->shm_nattch, &host_sd->shm_nattch);
+    unlock_user_struct(target_sd, target_addr, 0);
+    return 0;
+}
+
+static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
+                                               struct shmid_ds *host_sd)
+{
+    struct target_shmid_ds *target_sd;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
+        return -TARGET_EFAULT;
+    if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
+        return -TARGET_EFAULT;
+    __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
+    __put_user(host_sd->shm_atime, &target_sd->shm_atime);
+    __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
+    __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
+    __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
+    __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
+    __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
+    unlock_user_struct(target_sd, target_addr, 1);
+    return 0;
+}
+
+struct  target_shminfo {
+    abi_ulong shmmax;
+    abi_ulong shmmin;
+    abi_ulong shmmni;
+    abi_ulong shmseg;
+    abi_ulong shmall;
+};
+
+static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
+                                              struct shminfo *host_shminfo)
+{
+    struct target_shminfo *target_shminfo;
+    if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
+        return -TARGET_EFAULT;
+    __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
+    __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
+    __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
+    __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
+    __put_user(host_shminfo->shmall, &target_shminfo->shmall);
+    unlock_user_struct(target_shminfo, target_addr, 1);
+    return 0;
+}
+
+struct target_shm_info {
+    int used_ids;
+    abi_ulong shm_tot;
+    abi_ulong shm_rss;
+    abi_ulong shm_swp;
+    abi_ulong swap_attempts;
+    abi_ulong swap_successes;
+};
+
+static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
+                                               struct shm_info *host_shm_info)
+{
+    struct target_shm_info *target_shm_info;
+    if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
+        return -TARGET_EFAULT;
+    __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
+    __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
+    __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
+    __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
+    __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
+    __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
+    unlock_user_struct(target_shm_info, target_addr, 1);
+    return 0;
+}
+
+static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
+{
+    struct shmid_ds dsarg;
+    struct shminfo shminfo;
+    struct shm_info shm_info;
+    abi_long ret = -TARGET_EINVAL;
+
+    cmd &= 0xff;
+
+    switch(cmd) {
+    case IPC_STAT:
+    case IPC_SET:
+    case SHM_STAT:
+        if (target_to_host_shmid_ds(&dsarg, buf))
+            return -TARGET_EFAULT;
+        ret = get_errno(shmctl(shmid, cmd, &dsarg));
+        if (host_to_target_shmid_ds(buf, &dsarg))
+            return -TARGET_EFAULT;
+        break;
+    case IPC_INFO:
+        ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
+        if (host_to_target_shminfo(buf, &shminfo))
+            return -TARGET_EFAULT;
+        break;
+    case SHM_INFO:
+        ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
+        if (host_to_target_shm_info(buf, &shm_info))
+            return -TARGET_EFAULT;
+        break;
+    case IPC_RMID:
+    case SHM_LOCK:
+    case SHM_UNLOCK:
+        ret = get_errno(shmctl(shmid, cmd, NULL));
+        break;
+    }
+
+    return ret;
+}
+
+static inline abi_long do_shmat(int shmid, abi_ulong shmaddr, int shmflg,
+                                unsigned long *raddr)
+{
+    abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size);
+    abi_long ret;
+    struct shmid_ds shm_info;
+    int i;
+
+    /* find out the length of the shared memory segment */
+    ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
+    if (is_error(ret)) {
+        /* can't get length, bail out */
+        return get_errno(ret);
+    }
+
+    mmap_lock();
+
+    if (shmaddr)
+        *raddr = (unsigned long) shmat(shmid, g2h(shmaddr), shmflg);
+    else {
+        abi_ulong mmap_start;
+
+        mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
+
+        if (mmap_start == -1) {
+            errno = ENOMEM;
+            *raddr = -1;
+        } else
+            *raddr = (unsigned long) shmat(shmid, g2h(mmap_start),
+                                           shmflg | SHM_REMAP);
+    }
+
+    if (*raddr == -1) {
+        mmap_unlock();
+        return get_errno(*raddr);
+    }
+
+    page_set_flags(h2g(*raddr), h2g(*raddr) + shm_info.shm_segsz,
+                   PAGE_VALID | PAGE_READ |
+                   ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
+
+    for (i = 0; i < N_SHM_REGIONS; i++) {
+        if (shm_regions[i].start == 0) {
+            shm_regions[i].start = h2g(*raddr);
+            shm_regions[i].size = shm_info.shm_segsz;
+            break;
+        }
+    }
+
+    mmap_unlock();
+    return 0;
+}
+
+static inline abi_long do_shmdt(abi_ulong shmaddr)
+{
+    int i;
+
+    for (i = 0; i < N_SHM_REGIONS; ++i) {
+        if (shm_regions[i].start == shmaddr) {
+            shm_regions[i].start = 0;
+            page_set_flags(shmaddr, shm_regions[i].size, 0);
+            break;
+        }
+    }
+
+    return get_errno(shmdt(g2h(shmaddr)));
+}
+
 #ifdef TARGET_NR_ipc
 /* ??? This only works with linear mappings.  */
 /* do_ipc() must return target values and target errnos. */
@@ -2075,15 +2625,13 @@ static abi_long do_ipc(unsigned int call, int first,
 {
     int version;
     abi_long ret = 0;
-    struct shmid_ds shm_info;
-    int i;
 
     version = call >> 16;
     call &= 0xffff;
 
     switch (call) {
     case IPCOP_semop:
-        ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
+        ret = do_semop(first, ptr, second);
         break;
 
     case IPCOP_semget:
@@ -2091,12 +2639,7 @@ static abi_long do_ipc(unsigned int call, int first,
         break;
 
     case IPCOP_semctl:
-        ret = do_semctl(first, second, third, ptr);
-        break;
-
-    case IPCOP_semtimedop:
-        gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
-        ret = -TARGET_ENOSYS;
+        ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr);
         break;
 
     case IPCOP_msgget:
@@ -2136,72 +2679,40 @@ static abi_long do_ipc(unsigned int call, int first,
         break;
 
     case IPCOP_shmat:
-        {
-            abi_ulong raddr;
-            void *host_addr;
-            /* SHM_* flags are the same on all linux platforms */
-            host_addr = shmat(first, (void *)g2h(ptr), second);
-            if (host_addr == (void *)-1) {
-                ret = get_errno((long)host_addr);
-                break;
-            }
-            raddr = h2g((unsigned long)host_addr);
-            /* find out the length of the shared memory segment */
-            
-            ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
-            if (is_error(ret)) {
-                /* can't get length, bail out */
-                shmdt(host_addr);
-                break;
-            }
-            page_set_flags(raddr, raddr + shm_info.shm_segsz,
-                           PAGE_VALID | PAGE_READ |
-                           ((second & SHM_RDONLY)? 0: PAGE_WRITE));
-            for (i = 0; i < N_SHM_REGIONS; ++i) {
-                if (shm_regions[i].start == 0) {
-                    shm_regions[i].start = raddr;
-                    shm_regions[i].size = shm_info.shm_segsz;
+        switch (version) {
+        default:
+            {
+                unsigned long raddr;
+
+                ret = do_shmat(first, ptr, second, &raddr);
+                if (ret)
                     break;
-                }
+
+                ret = put_user_ual(raddr, third);
+                break;
             }
-            if (put_user_ual(raddr, third))
-                return -TARGET_EFAULT;
-            ret = 0;
+        case 1:
+            ret = -TARGET_EINVAL;
+            break;
         }
-       break;
+        break;
+
     case IPCOP_shmdt:
-       for (i = 0; i < N_SHM_REGIONS; ++i) {
-           if (shm_regions[i].start == ptr) {
-               shm_regions[i].start = 0;
-               page_set_flags(ptr, shm_regions[i].size, 0);
-               break;
-           }
-       }
-       ret = get_errno(shmdt((void *)g2h(ptr)));
-       break;
+        ret = do_shmdt(ptr);
+        break;
 
     case IPCOP_shmget:
-       /* IPC_* flag values are the same on all linux platforms */
-       ret = get_errno(shmget(first, second, third));
-       break;
+        ret = get_errno(shmget(first, second, third));
+        break;
 
-       /* IPC_* and SHM_* command values are the same on all linux platforms */
     case IPCOP_shmctl:
-        switch(second) {
-        case IPC_RMID:
-        case SHM_LOCK:
-        case SHM_UNLOCK:
-            ret = get_errno(shmctl(first, second, NULL));
-            break;
-        default:
-            goto unimplemented;
-        }
+        ret = do_shmctl(first, second, third);
         break;
+
     default:
-    unimplemented:
-       gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
-       ret = -TARGET_ENOSYS;
-       break;
+        gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
+        ret = -TARGET_ENOSYS;
+        break;
     }
     return ret;
 }
@@ -2515,26 +3026,6 @@ static bitmask_transtbl mmap_flags_tbl[] = {
        { 0, 0, 0, 0 }
 };
 
-static bitmask_transtbl fcntl_flags_tbl[] = {
-       { TARGET_O_ACCMODE,   TARGET_O_WRONLY,    O_ACCMODE,   O_WRONLY,    },
-       { TARGET_O_ACCMODE,   TARGET_O_RDWR,      O_ACCMODE,   O_RDWR,      },
-       { TARGET_O_CREAT,     TARGET_O_CREAT,     O_CREAT,     O_CREAT,     },
-       { TARGET_O_EXCL,      TARGET_O_EXCL,      O_EXCL,      O_EXCL,      },
-       { TARGET_O_NOCTTY,    TARGET_O_NOCTTY,    O_NOCTTY,    O_NOCTTY,    },
-       { TARGET_O_TRUNC,     TARGET_O_TRUNC,     O_TRUNC,     O_TRUNC,     },
-       { TARGET_O_APPEND,    TARGET_O_APPEND,    O_APPEND,    O_APPEND,    },
-       { TARGET_O_NONBLOCK,  TARGET_O_NONBLOCK,  O_NONBLOCK,  O_NONBLOCK,  },
-       { TARGET_O_SYNC,      TARGET_O_SYNC,      O_SYNC,      O_SYNC,      },
-       { TARGET_FASYNC,      TARGET_FASYNC,      FASYNC,      FASYNC,      },
-       { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
-       { TARGET_O_NOFOLLOW,  TARGET_O_NOFOLLOW,  O_NOFOLLOW,  O_NOFOLLOW,  },
-       { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
-#if defined(O_DIRECT)
-       { TARGET_O_DIRECT,    TARGET_O_DIRECT,    O_DIRECT,    O_DIRECT,    },
-#endif
-       { 0, 0, 0, 0 }
-};
-
 #if defined(TARGET_I386)
 
 /* NOTE: there is really one LDT for all the threads */
@@ -2856,6 +3347,7 @@ typedef struct {
     pthread_cond_t cond;
     pthread_t thread;
     uint32_t tid;
+    unsigned int flags;
     abi_ulong child_tidptr;
     abi_ulong parent_tidptr;
     sigset_t sigmask;
@@ -2869,9 +3361,11 @@ static void *clone_func(void *arg)
     env = info->env;
     thread_env = env;
     info->tid = gettid();
-    if (info->child_tidptr)
+    if (info->flags & CLONE_CHILD_SETTID)
         put_user_u32(info->tid, info->child_tidptr);
-    if (info->parent_tidptr)
+    if (info->flags & CLONE_CHILD_CLEARTID)
+        set_tid_address(g2h(info->child_tidptr));
+    if (info->flags & CLONE_PARENT_SETTID)
         put_user_u32(info->tid, info->parent_tidptr);
     /* Enable signals.  */
     sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
@@ -2936,7 +3430,6 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
         nptl_flags = flags;
         flags &= ~CLONE_NPTL_FLAGS2;
 
-        /* TODO: Implement CLONE_CHILD_CLEARTID.  */
         if (nptl_flags & CLONE_SETTLS)
             cpu_set_tls (new_env, newtls);
 
@@ -2948,7 +3441,9 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
         pthread_mutex_lock(&info.mutex);
         pthread_cond_init(&info.cond, NULL);
         info.env = new_env;
-        if (nptl_flags & CLONE_CHILD_SETTID)
+        info.flags = nptl_flags;
+        if (nptl_flags & CLONE_CHILD_SETTID ||
+            nptl_flags & CLONE_CHILD_CLEARTID)
             info.child_tidptr = child_tidptr;
         if (nptl_flags & CLONE_PARENT_SETTID)
             info.parent_tidptr = parent_tidptr;
@@ -3011,7 +3506,8 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
             ts = (TaskState *)env->opaque;
             if (flags & CLONE_SETTLS)
                 cpu_set_tls (env, newtls);
-            /* TODO: Implement CLONE_CHILD_CLEARTID.  */
+            if (flags & CLONE_CHILD_CLEARTID)
+                set_tid_address(g2h(child_tidptr));
 #endif
         } else {
             fork_end(0);
@@ -3277,7 +3773,7 @@ static inline abi_long host_to_target_timespec(abi_ulong target_addr,
     return 0;
 }
 
-#ifdef TARGET_NR_stat64
+#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
 static inline abi_long host_to_target_stat64(void *cpu_env,
                                              abi_ulong target_addr,
                                              struct stat *host_st)
@@ -3309,11 +3805,15 @@ static inline abi_long host_to_target_stat64(void *cpu_env,
     } else
 #endif
     {
+#if TARGET_LONG_BITS == 64
+        struct target_stat *target_st;
+#else
         struct target_stat64 *target_st;
+#endif
 
         if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
             return -TARGET_EFAULT;
-        memset(target_st, 0, sizeof(struct target_stat64));
+        memset(target_st, 0, sizeof(*target_st));
         __put_user(host_st->st_dev, &target_st->st_dev);
         __put_user(host_st->st_ino, &target_st->st_ino);
 #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
@@ -4884,7 +5384,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
        ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
        break;
 #endif
-
+#ifdef TARGET_NR_semget
+    case TARGET_NR_semget:
+        ret = get_errno(semget(arg1, arg2, arg3));
+        break;
+#endif
+#ifdef TARGET_NR_semop
+    case TARGET_NR_semop:
+        ret = get_errno(do_semop(arg1, arg2, arg3));
+        break;
+#endif
+#ifdef TARGET_NR_semctl
+    case TARGET_NR_semctl:
+        ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
+        break;
+#endif
 #ifdef TARGET_NR_msgctl
     case TARGET_NR_msgctl:
         ret = do_msgctl(arg1, arg2, arg3);
@@ -4905,6 +5419,32 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         ret = do_msgsnd(arg1, arg2, arg3, arg4);
         break;
 #endif
+#ifdef TARGET_NR_shmget
+    case TARGET_NR_shmget:
+        ret = get_errno(shmget(arg1, arg2, arg3));
+        break;
+#endif
+#ifdef TARGET_NR_shmctl
+    case TARGET_NR_shmctl:
+        ret = do_shmctl(arg1, arg2, arg3);
+        break;
+#endif
+#ifdef TARGET_NR_shmat
+    case TARGET_NR_shmat:
+        {
+            abi_long err;
+            unsigned long _ret;
+
+            err = do_shmat(arg1, arg2, arg3, &_ret);
+            ret = err ? err : _ret;
+        }
+        break;
+#endif
+#ifdef TARGET_NR_shmdt
+    case TARGET_NR_shmdt:
+        ret = do_shmdt(arg1);
+        break;
+#endif
     case TARGET_NR_fsync:
         ret = get_errno(fsync(arg1));
         break;
@@ -5422,11 +5962,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             ret = host_to_target_stat64(cpu_env, arg2, &st);
         break;
 #endif
-#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64)
+#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
+        (defined(__NR_fstatat64) || defined(__NR_newfstatat))
+#ifdef TARGET_NR_fstatat64
     case TARGET_NR_fstatat64:
+#endif
+#ifdef TARGET_NR_newfstatat
+    case TARGET_NR_newfstatat:
+#endif
         if (!(p = lock_user_string(arg2)))
             goto efault;
+#ifdef __NR_fstatat64
         ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
+#else
+        ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4));
+#endif
         if (!is_error(ret))
             ret = host_to_target_stat64(cpu_env, arg3, &st);
         break;
@@ -6090,6 +6640,81 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #endif
 
+#ifdef TARGET_NR_mq_open
+    case TARGET_NR_mq_open:
+    {
+        struct mq_attr posix_mq_attr;
+
+        p = lock_user_string(arg1 - 1);
+        if (arg4 != 0)
+            copy_from_user_mq_attr (&posix_mq_attr, arg4);
+        ret = get_errno(mq_open(p, arg2, arg3, &posix_mq_attr));
+        unlock_user (p, arg1, 0);
+        break;
+    }
+
+    case TARGET_NR_mq_unlink:
+        p = lock_user_string(arg1 - 1);
+        ret = get_errno(mq_unlink(p));
+        unlock_user (p, arg1, 0);
+        break;
+
+    case TARGET_NR_mq_timedsend:
+    {
+        struct timespec ts;
+
+        p = lock_user (VERIFY_READ, arg2, arg3, 1);
+        if (arg5 != 0) {
+            target_to_host_timespec(&ts, arg5);
+            ret = get_errno(mq_timedsend(arg1, p, arg3, arg4, &ts));
+            host_to_target_timespec(arg5, &ts);
+        }
+        else
+            ret = get_errno(mq_send(arg1, p, arg3, arg4));
+        unlock_user (p, arg2, arg3);
+        break;
+    }
+
+    case TARGET_NR_mq_timedreceive:
+    {
+        struct timespec ts;
+        unsigned int prio;
+
+        p = lock_user (VERIFY_READ, arg2, arg3, 1);
+        if (arg5 != 0) {
+            target_to_host_timespec(&ts, arg5);
+            ret = get_errno(mq_timedreceive(arg1, p, arg3, &prio, &ts));
+            host_to_target_timespec(arg5, &ts);
+        }
+        else
+            ret = get_errno(mq_receive(arg1, p, arg3, &prio));
+        unlock_user (p, arg2, arg3);
+        if (arg4 != 0)
+            put_user_u32(prio, arg4);
+        break;
+    }
+
+    /* Not implemented for now... */
+/*     case TARGET_NR_mq_notify: */
+/*         break; */
+
+    case TARGET_NR_mq_getsetattr:
+    {
+        struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
+        ret = 0;
+        if (arg3 != 0) {
+            ret = mq_getattr(arg1, &posix_mq_attr_out);
+            copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
+        }
+        if (arg2 != 0) {
+            copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
+            ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out);
+        }
+
+        break;
+    }
+#endif
+
     default:
     unimplemented:
         gemu_log("qemu: Unsupported syscall: %d\n", num);
index 7db7a8c..a373690 100644 (file)
@@ -1998,6 +1998,13 @@ struct linux_dirent64 {
     char            d_name[256];
 };
 
+struct target_mq_attr {
+    abi_long mq_flags;
+    abi_long mq_maxmsg;
+    abi_long mq_msgsize;
+    abi_long mq_curmsgs;
+};
+
 #include "socket.h"
 
 #include "errno_defs.h"
index cab80cd..7d0ee08 100644 (file)
@@ -108,6 +108,9 @@ typedef struct CPUARMState {
         uint32_t c1_sys; /* System control register.  */
         uint32_t c1_coproc; /* Coprocessor access register.  */
         uint32_t c1_xscaleauxcr; /* XScale auxiliary control register.  */
+        uint32_t c1_secfg; /* Secure configuration register. */
+        uint32_t c1_sedbg; /* Secure debug enable register. */
+        uint32_t c1_nseac; /* Non-secure access control register. */
         uint32_t c2_base0; /* MMU translation table base 0.  */
         uint32_t c2_base1; /* MMU translation table base 1.  */
         uint32_t c2_control; /* MMU translation table base control.  */
@@ -339,7 +342,8 @@ enum arm_features {
     ARM_FEATURE_DIV,
     ARM_FEATURE_M, /* Microcontroller profile.  */
     ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling.  */
-    ARM_FEATURE_THUMB2EE
+    ARM_FEATURE_THUMB2EE,
+       ARM_FEATURE_TRUSTZONE /* TrustZone Security Extensions. */
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
@@ -365,29 +369,30 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define IS_M(env) arm_feature(env, ARM_FEATURE_M)
 #define ARM_CPUID(env) (env->cp15.c0_cpuid)
 
-#define ARM_CPUID_ARM1026     0x4106a262
-#define ARM_CPUID_ARM926      0x41069265
-#define ARM_CPUID_ARM946      0x41059461
-#define ARM_CPUID_TI915T      0x54029152
-#define ARM_CPUID_TI925T      0x54029252
-#define ARM_CPUID_PXA250      0x69052100
-#define ARM_CPUID_PXA255      0x69052d00
-#define ARM_CPUID_PXA260      0x69052903
-#define ARM_CPUID_PXA261      0x69052d05
-#define ARM_CPUID_PXA262      0x69052d06
-#define ARM_CPUID_PXA270      0x69054110
-#define ARM_CPUID_PXA270_A0   0x69054110
-#define ARM_CPUID_PXA270_A1   0x69054111
-#define ARM_CPUID_PXA270_B0   0x69054112
-#define ARM_CPUID_PXA270_B1   0x69054113
-#define ARM_CPUID_PXA270_C0   0x69054114
-#define ARM_CPUID_PXA270_C5   0x69054117
-#define ARM_CPUID_ARM1136     0x4117b363
-#define ARM_CPUID_ARM1136_R2  0x4107b362
-#define ARM_CPUID_ARM11MPCORE 0x410fb022
-#define ARM_CPUID_CORTEXA8    0x410fc080
-#define ARM_CPUID_CORTEXM3    0x410fc231
-#define ARM_CPUID_ANY         0xffffffff
+#define ARM_CPUID_ARM1026       0x4106a262
+#define ARM_CPUID_ARM926        0x41069265
+#define ARM_CPUID_ARM946        0x41059461
+#define ARM_CPUID_TI915T        0x54029152
+#define ARM_CPUID_TI925T        0x54029252
+#define ARM_CPUID_PXA250        0x69052100
+#define ARM_CPUID_PXA255        0x69052d00
+#define ARM_CPUID_PXA260        0x69052903
+#define ARM_CPUID_PXA261        0x69052d05
+#define ARM_CPUID_PXA262        0x69052d06
+#define ARM_CPUID_PXA270        0x69054110
+#define ARM_CPUID_PXA270_A0     0x69054110
+#define ARM_CPUID_PXA270_A1     0x69054111
+#define ARM_CPUID_PXA270_B0     0x69054112
+#define ARM_CPUID_PXA270_B1     0x69054113
+#define ARM_CPUID_PXA270_C0     0x69054114
+#define ARM_CPUID_PXA270_C5     0x69054117
+#define ARM_CPUID_ARM1136       0x4117b363
+#define ARM_CPUID_ARM1136_R2    0x4107b362
+#define ARM_CPUID_ARM11MPCORE   0x410fb022
+#define ARM_CPUID_CORTEXA8      0x411fc081
+#define ARM_CPUID_CORTEXA8_R2   0x412fc083
+#define ARM_CPUID_CORTEXM3      0x410fc231
+#define ARM_CPUID_ANY           0xffffffff
 
 #if defined(CONFIG_USER_ONLY)
 #define TARGET_PAGE_BITS 12
index 3250fb8..8a91602 100644 (file)
@@ -14,6 +14,9 @@ static uint32_t cortexa8_cp15_c0_c1[8] =
 static uint32_t cortexa8_cp15_c0_c2[8] =
 { 0x00101111, 0x12112111, 0x21232031, 0x11112131, 0x00111142, 0, 0, 0 };
 
+static uint32_t cortexa8r2_cp16_c0_c2[8] =
+{ 0x00101111, 0x12112111, 0x21232031, 0x11112131, 0x00011142, 0, 0, 0 };
+
 static uint32_t mpcore_cp15_c0_c1[8] =
 { 0x111, 0x1, 0, 0x2, 0x01100103, 0x10020302, 0x01222000, 0 };
 
@@ -89,6 +92,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         set_feature(env, ARM_FEATURE_VFP3);
         set_feature(env, ARM_FEATURE_NEON);
         set_feature(env, ARM_FEATURE_THUMB2EE);
+        set_feature(env, ARM_FEATURE_TRUSTZONE);
         env->vfp.xregs[ARM_VFP_FPSID] = 0x410330c0;
         env->vfp.xregs[ARM_VFP_MVFR0] = 0x11110222;
         env->vfp.xregs[ARM_VFP_MVFR1] = 0x00011100;
@@ -100,6 +104,28 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c0_ccsid[1] = 0x2007e01a; /* 16k L1 icache. */
         env->cp15.c0_ccsid[2] = 0xf0000000; /* No L2 icache. */
         break;
+    case ARM_CPUID_CORTEXA8_R2:
+        set_feature(env, ARM_FEATURE_V6);
+        set_feature(env, ARM_FEATURE_V6K);
+        set_feature(env, ARM_FEATURE_V7);
+        set_feature(env, ARM_FEATURE_AUXCR);
+        set_feature(env, ARM_FEATURE_THUMB2);
+        set_feature(env, ARM_FEATURE_VFP);
+        set_feature(env, ARM_FEATURE_VFP3);
+        set_feature(env, ARM_FEATURE_NEON);
+        set_feature(env, ARM_FEATURE_THUMB2EE);
+        set_feature(env, ARM_FEATURE_TRUSTZONE);
+        env->vfp.xregs[ARM_VFP_FPSID] = 0x410330c2;
+        env->vfp.xregs[ARM_VFP_MVFR0] = 0x11110222;
+        env->vfp.xregs[ARM_VFP_MVFR1] = 0x00011100; /* should be 0x00011111 */
+        memcpy(env->cp15.c0_c1, cortexa8_cp15_c0_c1, 8 * sizeof(uint32_t));
+        memcpy(env->cp15.c0_c2, cortexa8r2_cp16_c0_c2, 8 * sizeof(uint32_t));
+        env->cp15.c0_cachetype = 0x82048004;
+        env->cp15.c0_clid = (1 << 27) | (2 << 24) | (4 << 3) | 3;
+        env->cp15.c0_ccsid[0] = 0xe007e01a; /* 16k L1 dcache. */
+        env->cp15.c0_ccsid[1] = 0x2007e01a; /* 16k L1 icache. */
+        env->cp15.c0_ccsid[2] = 0xf03fe03a; /* 256k L2 cache. */
+        break;
     case ARM_CPUID_CORTEXM3:
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_THUMB2);
@@ -284,6 +310,7 @@ static const struct arm_cpu_t arm_cpu_names[] = {
     { ARM_CPUID_ARM11MPCORE, "arm11mpcore"},
     { ARM_CPUID_CORTEXM3, "cortex-m3"},
     { ARM_CPUID_CORTEXA8, "cortex-a8"},
+    { ARM_CPUID_CORTEXA8_R2, "cortex-a8-r2"},
     { ARM_CPUID_TI925T, "ti925t" },
     { ARM_CPUID_PXA250, "pxa250" },
     { ARM_CPUID_PXA255, "pxa255" },
@@ -690,7 +717,7 @@ static void do_v7m_exception_exit(CPUARMState *env)
        pointer.  */
 }
 
-void do_interrupt_v7m(CPUARMState *env)
+static void do_interrupt_v7m(CPUARMState *env)
 {
     uint32_t xpsr = xpsr_read(env);
     uint32_t lr;
@@ -1339,30 +1366,60 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
         }
         goto bad_reg;
     case 1: /* System configuration.  */
-        if (arm_feature(env, ARM_FEATURE_OMAPCP))
-            op2 = 0;
-        switch (op2) {
+        switch (crm) {
         case 0:
-            if (!arm_feature(env, ARM_FEATURE_XSCALE) || crm == 0)
-                env->cp15.c1_sys = val;
-            /* ??? Lots of these bits are not implemented.  */
-            /* This may enable/disable the MMU, so do a TLB flush.  */
-            tlb_flush(env, 1);
-            break;
-        case 1: /* Auxiliary cotrol register.  */
-            if (arm_feature(env, ARM_FEATURE_XSCALE)) {
-                env->cp15.c1_xscaleauxcr = val;
+            if (arm_feature(env, ARM_FEATURE_OMAPCP))
+                op2 = 0;
+            switch (op2) {
+            case 0:
+                if (!arm_feature(env, ARM_FEATURE_XSCALE))
+                    env->cp15.c1_sys = val;
+                /* ??? Lots of these bits are not implemented.  */
+                /* This may enable/disable the MMU, so do a TLB flush.  */
+                tlb_flush(env, 1);
+                break;
+            case 1: /* Auxiliary cotrol register.  */
+                if (arm_feature(env, ARM_FEATURE_XSCALE)) {
+                    env->cp15.c1_xscaleauxcr = val;
+                    break;
+                }
+                /* Not implemented.  */
                 break;
+            case 2:
+                if (arm_feature(env, ARM_FEATURE_XSCALE))
+                    goto bad_reg;
+                if (env->cp15.c1_coproc != val) {
+                    env->cp15.c1_coproc = val;
+                    /* ??? Is this safe when called from within a TB?  */
+                    tb_flush(env);
+                }
+                break;
+            default:
+                goto bad_reg;
             }
-            /* Not implemented.  */
             break;
-        case 2:
-            if (arm_feature(env, ARM_FEATURE_XSCALE))
+        case 1:
+            if (!arm_feature(env, ARM_FEATURE_TRUSTZONE)
+                || (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
+                goto bad_reg;
+            switch (op2) {
+            case 0: /* Secure configuration register. */
+                if (env->cp15.c1_secfg & 1)
+                    goto bad_reg;
+                env->cp15.c1_secfg = val;
+                break;
+            case 1: /* Secure debug enable register. */
+                if (env->cp15.c1_secfg & 1)
+                    goto bad_reg;
+                env->cp15.c1_sedbg = val;
+                break;
+            case 2: /* Nonsecure access control register. */
+                if (env->cp15.c1_secfg & 1)
+                    goto bad_reg;
+                env->cp15.c1_nseac = val;
+                break;
+            default:
                 goto bad_reg;
-            if (env->cp15.c1_coproc != val) {
-                env->cp15.c1_coproc = val;
-                /* ??? Is this safe when called from within a TB?  */
-                tb_flush(env);
             }
             break;
         default:
@@ -1382,22 +1439,22 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
                 goto bad_reg;
             }
         } else {
-           switch (op2) {
-           case 0:
-               env->cp15.c2_base0 = val;
-               break;
-           case 1:
-               env->cp15.c2_base1 = val;
-               break;
-           case 2:
+            switch (op2) {
+            case 0:
+                env->cp15.c2_base0 = val;
+                break;
+            case 1:
+                env->cp15.c2_base1 = val;
+                break;
+            case 2:
                 val &= 7;
                 env->cp15.c2_control = val;
-               env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> val);
+                env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> val);
                 env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> val);
-               break;
-           default:
-               goto bad_reg;
-           }
+                break;
+            default:
+                goto bad_reg;
+            }
         }
         break;
     case 3: /* MMU Domain access control / MPU write buffer control.  */
@@ -1496,26 +1553,26 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
             break;
         switch (crm) {
         case 0: /* Cache lockdown.  */
-           switch (op1) {
-           case 0: /* L1 cache.  */
-               switch (op2) {
-               case 0:
-                   env->cp15.c9_data = val;
-                   break;
-               case 1:
-                   env->cp15.c9_insn = val;
-                   break;
-               default:
-                   goto bad_reg;
-               }
-               break;
-           case 1: /* L2 cache.  */
-               /* Ignore writes to L2 lockdown/auxiliary registers.  */
-               break;
-           default:
-               goto bad_reg;
-           }
-           break;
+            switch (op1) {
+            case 0: /* L1 cache.  */
+                switch (op2) {
+                case 0:
+                    env->cp15.c9_data = val;
+                    break;
+                case 1:
+                    env->cp15.c9_insn = val;
+                    break;
+                default:
+                    goto bad_reg;
+                }
+                break;
+            case 1: /* L2 cache.  */
+                /* Ignore writes to L2 lockdown/auxiliary registers.  */
+                break;
+            default:
+                goto bad_reg;
+            }
+            break;
         case 1: /* TCM memory region registers.  */
             /* Not implemented.  */
             goto bad_reg;
@@ -1625,7 +1682,7 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
                 case 0: /* Device ID.  */
                     return env->cp15.c0_cpuid;
                 case 1: /* Cache Type.  */
-                   return env->cp15.c0_cachetype;
+                    return env->cp15.c0_cachetype;
                 case 2: /* TCM status.  */
                     return 0;
                 case 3: /* TLB type register.  */
@@ -1648,6 +1705,7 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
             default:
                 goto bad_reg;
             }
+            break;
         case 1:
             /* These registers aren't documented on arm11 cores.  However
                Linux looks at them anyway.  */
@@ -1674,37 +1732,66 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
         default:
             goto bad_reg;
         }
+        break;
     case 1: /* System configuration.  */
-        if (arm_feature(env, ARM_FEATURE_OMAPCP))
-            op2 = 0;
-        switch (op2) {
-        case 0: /* Control register.  */
-            return env->cp15.c1_sys;
-        case 1: /* Auxiliary control register.  */
-            if (arm_feature(env, ARM_FEATURE_XSCALE))
-                return env->cp15.c1_xscaleauxcr;
-            if (!arm_feature(env, ARM_FEATURE_AUXCR))
-                goto bad_reg;
-            switch (ARM_CPUID(env)) {
-            case ARM_CPUID_ARM1026:
-                return 1;
-            case ARM_CPUID_ARM1136:
-            case ARM_CPUID_ARM1136_R2:
-                return 7;
-            case ARM_CPUID_ARM11MPCORE:
-                return 1;
-            case ARM_CPUID_CORTEXA8:
-                return 0;
+        switch (crm) {
+        case 0:
+            if (arm_feature(env, ARM_FEATURE_OMAPCP))
+                op2 = 0;
+            switch (op2) {
+            case 0: /* Control register.  */
+                return env->cp15.c1_sys;
+            case 1: /* Auxiliary control register.  */
+                if (arm_feature(env, ARM_FEATURE_XSCALE))
+                    return env->cp15.c1_xscaleauxcr;
+                if (!arm_feature(env, ARM_FEATURE_AUXCR))
+                    goto bad_reg;
+                switch (ARM_CPUID(env)) {
+                case ARM_CPUID_ARM1026:
+                    return 1;
+                case ARM_CPUID_ARM1136:
+                case ARM_CPUID_ARM1136_R2:
+                    return 7;
+                case ARM_CPUID_ARM11MPCORE:
+                    return 1;
+                case ARM_CPUID_CORTEXA8:
+                case ARM_CPUID_CORTEXA8_R2:
+                    return 2;
+                default:
+                    goto bad_reg;
+                }
+                break;
+            case 2: /* Coprocessor access register.  */
+                if (arm_feature(env, ARM_FEATURE_XSCALE))
+                    goto bad_reg;
+                return env->cp15.c1_coproc;
             default:
                 goto bad_reg;
             }
-        case 2: /* Coprocessor access register.  */
-            if (arm_feature(env, ARM_FEATURE_XSCALE))
+            break;
+        case 1:
+            if (!arm_feature(env, ARM_FEATURE_TRUSTZONE)
+                || (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
                 goto bad_reg;
-            return env->cp15.c1_coproc;
+            switch (op2) {
+            case 0: /* Secure configuration register. */
+                if (env->cp15.c1_secfg & 1)
+                    goto bad_reg;
+                return env->cp15.c1_secfg;
+            case 1: /* Secure debug enable register. */
+                if (env->cp15.c1_secfg & 1)
+                    goto bad_reg;
+                return env->cp15.c1_sedbg;
+            case 2: /* Nonsecure access control register. */
+                return env->cp15.c1_nseac;
+            default:
+                goto bad_reg;
+            }
+            break;
         default:
             goto bad_reg;
         }
+        break;
     case 2: /* MMU Page table control / MPU cache control.  */
         if (arm_feature(env, ARM_FEATURE_MPU)) {
             switch (op2) {
@@ -1718,17 +1805,17 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
                 goto bad_reg;
             }
         } else {
-           switch (op2) {
-           case 0:
-               return env->cp15.c2_base0;
-           case 1:
-               return env->cp15.c2_base1;
-           case 2:
+            switch (op2) {
+            case 0:
+                return env->cp15.c2_base0;
+            case 1:
+                return env->cp15.c2_base1;
+            case 2:
                 return env->cp15.c2_control;
-           default:
-               goto bad_reg;
-           }
-       }
+            default:
+                goto bad_reg;
+            }
+        }
     case 3: /* MMU Domain access control / MPU write buffer control.  */
         return env->cp15.c3;
     case 4: /* Reserved.  */
@@ -1764,41 +1851,39 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
         } else {
             if (arm_feature(env, ARM_FEATURE_OMAPCP))
                 op2 = 0;
-           switch (op2) {
-           case 0:
-               return env->cp15.c6_data;
-           case 1:
-               if (arm_feature(env, ARM_FEATURE_V6)) {
-                   /* Watchpoint Fault Adrress.  */
-                   return 0; /* Not implemented.  */
-               } else {
-                   /* Instruction Fault Adrress.  */
-                   /* Arm9 doesn't have an IFAR, but implementing it anyway
-                      shouldn't do any harm.  */
-                   return env->cp15.c6_insn;
-               }
-           case 2:
-               if (arm_feature(env, ARM_FEATURE_V6)) {
-                   /* Instruction Fault Adrress.  */
-                   return env->cp15.c6_insn;
-               } else {
-                   goto bad_reg;
-               }
-           default:
-               goto bad_reg;
-           }
+            switch (op2) {
+            case 0:
+                return env->cp15.c6_data;
+            case 1:
+                if (arm_feature(env, ARM_FEATURE_V6)) {
+                    /* Watchpoint Fault Adrress.  */
+                    return 0; /* Not implemented.  */
+                }
+                /* Instruction Fault Adrress.  */
+                /* Arm9 doesn't have an IFAR, but implementing it anyway
+                   shouldn't do any harm.  */
+                return env->cp15.c6_insn;
+            case 2:
+                if (arm_feature(env, ARM_FEATURE_V6)) {
+                    /* Instruction Fault Adrress.  */
+                    return env->cp15.c6_insn;
+                }
+                goto bad_reg;
+            default:
+                goto bad_reg;
+            }
         }
     case 7: /* Cache control.  */
-        /* FIXME: Should only clear Z flag if destination is r15.  */
-        env->ZF = 0;
+        if (((insn >> 12) & 0xf) == 0xf) /* clear ZF only if destination is r15 */
+            env->ZF = 0;
         return 0;
     case 8: /* MMU TLB control.  */
         goto bad_reg;
     case 9: /* Cache lockdown.  */
         switch (op1) {
         case 0: /* L1 cache.  */
-           if (arm_feature(env, ARM_FEATURE_OMAPCP))
-               return 0;
+            if (arm_feature(env, ARM_FEATURE_OMAPCP))
+                return 0;
             switch (op2) {
             case 0:
                 return env->cp15.c9_data;
index 323bace..3b3b1b2 100644 (file)
@@ -23,6 +23,7 @@ void register_machines(void)
     qemu_register_machine(&mainstone2_machine);
     qemu_register_machine(&musicpal_machine);
     qemu_register_machine(&tosapda_machine);
+    qemu_register_machine(&beagle_machine);
 }
 
 void cpu_save(QEMUFile *f, void *opaque)
@@ -49,6 +50,9 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, env->cp15.c1_sys);
     qemu_put_be32(f, env->cp15.c1_coproc);
     qemu_put_be32(f, env->cp15.c1_xscaleauxcr);
+    qemu_put_be32(f, env->cp15.c1_secfg);
+    qemu_put_be32(f, env->cp15.c1_sedbg);
+    qemu_put_be32(f, env->cp15.c1_nseac);
     qemu_put_be32(f, env->cp15.c2_base0);
     qemu_put_be32(f, env->cp15.c2_base1);
     qemu_put_be32(f, env->cp15.c2_mask);
@@ -144,6 +148,9 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     env->cp15.c1_sys = qemu_get_be32(f);
     env->cp15.c1_coproc = qemu_get_be32(f);
     env->cp15.c1_xscaleauxcr = qemu_get_be32(f);
+    env->cp15.c1_secfg = qemu_get_be32(f);
+    env->cp15.c1_sedbg = qemu_get_be32(f);
+    env->cp15.c1_nseac = qemu_get_be32(f);
     env->cp15.c2_base0 = qemu_get_be32(f);
     env->cp15.c2_base1 = qemu_get_be32(f);
     env->cp15.c2_mask = qemu_get_be32(f);
index 3cef021..577d0f7 100644 (file)
@@ -6015,11 +6015,22 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
             dead_tmp(tmp2);
             store_reg(s, rd, tmp);
             break;
-        case 7: /* bkpt */
-            gen_set_condexec(s);
-            gen_set_pc_im(s->pc - 4);
-            gen_exception(EXCP_BKPT);
-            s->is_jmp = DISAS_JUMP;
+        case 7:
+            if (op1 == 1) {
+                /* bkpt */
+                gen_set_condexec(s);
+                gen_set_pc_im(s->pc - 4);
+                gen_exception(EXCP_BKPT);
+                s->is_jmp = DISAS_JUMP;
+            } else if (op1 == 3) {
+                /* smi/smc */
+                if (!(env->cp15.c0_c2[4] & 0xf000))
+                    goto illegal_op;
+                fprintf(stderr,"smc [0x%08x] pc=0x%08x\n", insn, s->pc);
+                /* unsupported at the moment, ignore. */
+            } else {
+                goto illegal_op;
+            }
             break;
         case 0x8: /* signed multiply */
         case 0xa: