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)
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
*/
};
-int cocoa_keycode_to_qemu(int keycode)
+static int cocoa_keycode_to_qemu(int keycode)
{
if((sizeof(keymap)/sizeof(int)) <= keycode)
{
[super dealloc];
}
+- (BOOL) isOpaque
+{
+ return YES;
+}
+
- (void) drawRect:(NSRect) rect
{
COCOA_DEBUG("QemuCocoaView: drawRect\n");
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
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
} 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;
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;
}
}
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:]
}
else
[normalWindow setTitle:@"QEMU"];
}
- [NSCursor unhide];
+ if (cursor_hide) [NSCursor unhide];
CGAssociateMouseAndMouseCursorPosition(TRUE);
isMouseGrabed = FALSE;
}
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 );
}
-
#pragma mark qemu
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)
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
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"
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
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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.
--- /dev/null
+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.
+
+
--- /dev/null
+qemu-arm-cvs-m
+sbrsh
--- /dev/null
+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
--- /dev/null
+.\" $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>.
--- /dev/null
+usr/share/qemu/
--- /dev/null
+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
--- /dev/null
+README
+TODO
+qemu-doc.html
+debian/tundev.c
--- /dev/null
+debian/qemu-ifup etc/
+debian/qemu-make-debian-root usr/sbin/
+debian/overrides/qemu usr/share/lintian/overrides/
--- /dev/null
+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
--- /dev/null
+debian/qemu-make-debian-root.8
+debian/qemu-user.1
--- /dev/null
+#!/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
+
--- /dev/null
+/*
+ * $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);
+}
--- /dev/null
+version=3
+
+http://bellard.org/qemu/download.html qemu-([\d.]*).tar.gz debian uupdate
--- /dev/null
+/*\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
/* tosa.c */
extern QEMUMachine tosapda_machine;
+/* beagle.c */
+extern QEMUMachine beagle_machine;
+
#endif
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
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
--- /dev/null
+/*
+ * 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;
+
+}
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));
/* 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);
# 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
# 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
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);
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
# 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,
# 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,
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,
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);
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;
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)
# 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))
# 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 {
omap2423,
omap2430,
omap3430,
+ omap3530,
} mpu_model;
CPUState *env;
omap_clk clk;
} pwt;
- struct omap_i2c_s *i2c[2];
+ struct omap_i2c_s *i2c[3];
struct omap_rtc_s *rtc;
struct omap_synctimer_s {
uint32_t val;
uint16_t readh;
+ uint32_t sysconfig; /*OMAP3*/
} synctimer;
struct omap_prcm_s *prcm;
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 */
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
# 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) */
qemu_irq parent_intr[2];
unsigned char nbanks;
int level_only;
+ uint8_t revision;
/* state */
uint32_t new_agr[2];
switch (offset) {
case 0x00: /* INTC_REVISION */
- return 0x21;
+ return s->revision;
case 0x10: /* INTC_SYSCONFIG */
return (s->autoidle >> 2) & 1;
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)
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;
#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) {
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;
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
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)
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;
}
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;
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[] = {
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 */
qemu_irq *in;
qemu_irq handler[32];
+ uint8_t revision;
uint8_t config[2];
uint32_t inputs;
uint32_t outputs;
switch (addr) {
case 0x00: /* GPIO_REVISION */
- return 0x18;
+ return s->revision;
case 0x10: /* GPIO_SYSCONFIG */
return s->config[0];
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 */
break;
default:
- OMAP_BAD_REG(addr);
+ OMAP_BAD_REGV(addr, value);
return;
}
}
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,
}
struct omap_gpif_s {
- struct omap2_gpio_s module[5];
+ struct omap2_gpio_s module[6];
int modules;
int autoidle;
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;
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);
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)
}
/* 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;
#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 */
[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 */
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__);
}
return 0x000000f0;
case omap3430:
return 0x000000f0;
+ case omap3530:
+ return 0x000f00f0;
default:
cpu_abort(cpu_single_env, "%s: Bad mpu model\n", __FUNCTION__);
}
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__);
/* 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 */
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);
uint32_t value)
{
struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
+ int cs = 0;
switch (addr) {
case 0x00: /* SDRC_REVISION */
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;
}
}
struct omap_gpmc_s {
qemu_irq irq;
+ uint8_t revision;
uint8_t sysconfig;
uint16_t irqst;
uint16_t irqen;
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;
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);
switch (addr) {
case 0x000: /* GPMC_REVISION */
- return 0x20;
+ return s->revision;
case 0x010: /* GPMC_SYSCONFIG */
return s->sysconfig;
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;
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)
{
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 */
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;
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:
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,
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;
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 */
}
/* 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"));
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) {
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"),
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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
+
+
--- /dev/null
+/*
+ * 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;
+}
#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;
.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 */
&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
};
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;
return ch->color;
default:
- OMAP_BAD_REG(addr);
+ OMAP_BAD_REG(0x80 + chnum * 0x60 + addr);
return 0;
}
}
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 */
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);
}
}
#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;
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;
int nx;
int ny;
+ int rotation_flag;
+ int gfx_format;
+ int gfx_channel;
+
target_phys_addr_t addr[3];
uint32_t attr;
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)
{
s->autoidle = 0;
s->control = 0;
+ s->sdi_control = 0;
s->enable = 0;
s->dig.enable = 0;
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);
}
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 */
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 */
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;
}
}
switch (addr) {
case 0x000: /* DISPC_REVISION */
- return 0x20;
+ return 0x20; // 0x30 in OMAP3
case 0x010: /* DISPC_SYSCONFIG */
return s->dispc.idlemode;
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);
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 "
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 */
break;
default:
- OMAP_BAD_REG(addr);
+ OMAP_BAD_REGV(addr, value);
+ break;
}
}
break;
default:
- OMAP_BAD_REG(addr);
+ OMAP_BAD_REGV(addr, value);
+ break;
}
}
break;
default:
- OMAP_BAD_REG(addr);
+ OMAP_BAD_REGV(addr, value);
+ break;
}
}
break;
default:
- OMAP_BAD_REG(addr);
+ OMAP_BAD_REGV(addr, value);
+ break;
}
}
};
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));
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
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;
+}
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;
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)
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;
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);
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;
}
}
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;
}
}
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,
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,
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;
#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
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;
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);
}
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;
}
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:
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,
--- /dev/null
+/*
+ * 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
+
+
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(env, stderr, fprintf, 0);
- exit (1);
+ _exit (1);
}
process_pending_signals (env);
}
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(env, stderr, fprintf, 0);
- exit (1);
+ _exit (1);
}
process_pending_signals (env);
}
"-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"
int main(int argc, char **argv, char **envp)
{
- const char *filename;
+ char *filename = NULL;
const char *cpu_model;
struct target_pt_regs regs1, *regs = ®s1;
struct image_info info1, *info = &info1;
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();
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")) {
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;
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)
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
}
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));
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)
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);
}
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 */
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>
#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;
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);
#include <unistd.h>
#include <signal.h>
#include <errno.h>
+#include <assert.h>
#include <sys/ucontext.h>
#include "qemu.h"
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
{ 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 },
#include <fcntl.h>
#include <time.h>
#include <limits.h>
+#include <mqueue.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#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>
#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>
#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
}
#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
_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
_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)
#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
#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);
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,
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;
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));
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;
}
#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
{
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,
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);
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);
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;
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. */
{
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:
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:
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;
}
{ 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 */
pthread_cond_t cond;
pthread_t thread;
uint32_t tid;
+ unsigned int flags;
abi_ulong child_tidptr;
abi_ulong parent_tidptr;
sigset_t sigmask;
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);
nptl_flags = flags;
flags &= ~CLONE_NPTL_FLAGS2;
- /* TODO: Implement CLONE_CHILD_CLEARTID. */
if (nptl_flags & CLONE_SETTLS)
cpu_set_tls (new_env, newtls);
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;
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);
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)
} 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
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);
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;
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;
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);
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"
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. */
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)
#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
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 };
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;
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);
{ 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" },
pointer. */
}
-void do_interrupt_v7m(CPUARMState *env)
+static void do_interrupt_v7m(CPUARMState *env)
{
uint32_t xpsr = xpsr_read(env);
uint32_t lr;
}
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:
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. */
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;
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. */
default:
goto bad_reg;
}
+ break;
case 1:
/* These registers aren't documented on arm11 cores. However
Linux looks at them anyway. */
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) {
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. */
} 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;
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)
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);
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);
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: