From f721fdc1a8d7d3908fa78040599a22dc91a1692f Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 11 Apr 2008 12:20:18 +0000 Subject: qemu: Add qemu-sdk cvs version git-svn-id: https://svn.o-hand.com/repos/poky/trunk@4233 311d38ba-8fff-0310-9ca6-ca027cbcb966 --- .../02_snapshot_use_tmpdir.patch | 23 + .../04_do_not_print_rtc_freq_if_ok.patch | 26 + .../05_non-fatal_if_linux_hd_missing.patch | 17 + .../qemu-0.9.1+cvs20080307/06_exit_segfault.patch | 45 + .../qemu-0.9.1+cvs20080307/10_signal_jobs.patch | 26 + .../11_signal_sigaction.patch | 21 + .../22_net_tuntap_stall.patch | 18 + .../qemu/qemu-0.9.1+cvs20080307/31_syscalls.patch | 48 + .../qemu-0.9.1+cvs20080307/32_syscall_sysctl.patch | 55 + .../33_syscall_ppc_clone.patch | 22 + .../39_syscall_fadvise64.patch | 21 + .../qemu-0.9.1+cvs20080307/41_arm_fpa_sigfpe.patch | 104 + .../qemu-0.9.1+cvs20080307/52_ne2000_return.patch | 17 + .../qemu-0.9.1+cvs20080307/61_safe_64bit_int.patch | 27 + .../qemu-0.9.1+cvs20080307/63_sparc_build.patch | 18 + .../64_ppc_asm_constraints.patch | 18 + .../qemu/qemu-0.9.1+cvs20080307/65_kfreebsd.patch | 35 + .../qemu/qemu-0.9.1+cvs20080307/66_tls_ld.patch | 55 + .../qemu-0.9.1+cvs20080307/91-oh-sdl-cursor.patch | 18 + .../configure_symlinkpath_fix.patch | 28 + .../disable-error-in-configure.patch | 17 + .../qemu/qemu-0.9.1+cvs20080307/fix_segfault.patch | 37 + .../qemu/qemu-0.9.1+cvs20080307/no-strip.patch | 22 + .../qemu-0.9.0-nptl-update.patch | 219 + .../qemu-0.9.1+cvs20080307/qemu-0.9.0-nptl.patch | 854 ++ .../qemu-amd64-32b-mapping-0.9.0.patch | 37 + .../qemu-0.9.1+cvs20080307/qemu-n800-support.patch | 13970 +++++++++++++++++++ meta/packages/qemu/qemu-0.9.1+cvs20080307/series | 25 + .../workaround_bad_futex_headers.patch | 25 + .../qemu/qemu-0.9.1+cvs20080307/writev_fix.patch | 17 + .../02_snapshot_use_tmpdir.patch | 23 - .../04_do_not_print_rtc_freq_if_ok.patch | 26 - .../05_non-fatal_if_linux_hd_missing.patch | 17 - .../06_exit_segfault.patch | 45 - .../10_signal_jobs.patch | 26 - .../11_signal_sigaction.patch | 21 - .../22_net_tuntap_stall.patch | 18 - .../31_syscalls.patch | 48 - .../32_syscall_sysctl.patch | 55 - .../33_syscall_ppc_clone.patch | 22 - .../39_syscall_fadvise64.patch | 21 - .../41_arm_fpa_sigfpe.patch | 104 - .../52_ne2000_return.patch | 17 - .../61_safe_64bit_int.patch | 27 - .../63_sparc_build.patch | 18 - .../64_ppc_asm_constraints.patch | 18 - .../65_kfreebsd.patch | 35 - .../qemu-native-0.9.1+cvs20080307/66_tls_ld.patch | 55 - .../91-oh-sdl-cursor.patch | 18 - .../configure_symlinkpath_fix.patch | 28 - .../disable-error-in-configure.patch | 17 - .../fix_segfault.patch | 37 - .../qemu-native-0.9.1+cvs20080307/no-strip.patch | 22 - .../qemu-0.9.0-nptl-update.patch | 219 - .../qemu-0.9.0-nptl.patch | 854 -- .../qemu-amd64-32b-mapping-0.9.0.patch | 37 - .../qemu-n800-support.patch | 13970 ------------------- .../qemu/qemu-native-0.9.1+cvs20080307/series | 25 - .../workaround_bad_futex_headers.patch | 25 - .../qemu-native-0.9.1+cvs20080307/writev_fix.patch | 17 - meta/packages/qemu/qemu-sdk_cvs.bb | 4 + meta/packages/qemu/qemu_cvs.bb | 1 + 62 files changed, 15870 insertions(+), 15865 deletions(-) create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/02_snapshot_use_tmpdir.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/04_do_not_print_rtc_freq_if_ok.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/05_non-fatal_if_linux_hd_missing.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/06_exit_segfault.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/10_signal_jobs.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/11_signal_sigaction.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/22_net_tuntap_stall.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/31_syscalls.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/32_syscall_sysctl.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/33_syscall_ppc_clone.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/39_syscall_fadvise64.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/41_arm_fpa_sigfpe.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/52_ne2000_return.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/61_safe_64bit_int.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/63_sparc_build.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/64_ppc_asm_constraints.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/65_kfreebsd.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/66_tls_ld.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/91-oh-sdl-cursor.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/configure_symlinkpath_fix.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/disable-error-in-configure.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/fix_segfault.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/no-strip.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-0.9.0-nptl-update.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-0.9.0-nptl.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-amd64-32b-mapping-0.9.0.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-n800-support.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/series create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/workaround_bad_futex_headers.patch create mode 100644 meta/packages/qemu/qemu-0.9.1+cvs20080307/writev_fix.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/02_snapshot_use_tmpdir.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/04_do_not_print_rtc_freq_if_ok.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/05_non-fatal_if_linux_hd_missing.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/06_exit_segfault.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/10_signal_jobs.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/11_signal_sigaction.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/22_net_tuntap_stall.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/31_syscalls.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/32_syscall_sysctl.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/33_syscall_ppc_clone.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/39_syscall_fadvise64.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/41_arm_fpa_sigfpe.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/52_ne2000_return.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/61_safe_64bit_int.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/63_sparc_build.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/64_ppc_asm_constraints.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/65_kfreebsd.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/66_tls_ld.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/91-oh-sdl-cursor.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/configure_symlinkpath_fix.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/disable-error-in-configure.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/fix_segfault.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/no-strip.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-0.9.0-nptl-update.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-0.9.0-nptl.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-amd64-32b-mapping-0.9.0.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-n800-support.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/series delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/workaround_bad_futex_headers.patch delete mode 100644 meta/packages/qemu/qemu-native-0.9.1+cvs20080307/writev_fix.patch create mode 100644 meta/packages/qemu/qemu-sdk_cvs.bb (limited to 'meta/packages') diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/02_snapshot_use_tmpdir.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/02_snapshot_use_tmpdir.patch new file mode 100644 index 0000000000..40264ed443 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/02_snapshot_use_tmpdir.patch @@ -0,0 +1,23 @@ +#DPATCHLEVEL=0 +--- +# block.c | 6 +++++- +# 1 file changed, 5 insertions(+), 1 deletion(-) +# +Index: block.c +=================================================================== +--- block.c.orig 2007-12-03 23:47:25.000000000 +0000 ++++ block.c 2007-12-03 23:47:31.000000000 +0000 +@@ -191,8 +191,12 @@ void get_tmp_filename(char *filename, in + void get_tmp_filename(char *filename, int size) + { + int fd; ++ char *tmpdir; + /* XXX: race condition possible */ +- pstrcpy(filename, size, "/tmp/vl.XXXXXX"); ++ tmpdir = getenv("TMPDIR"); ++ if (!tmpdir) ++ tmpdir = "/tmp"; ++ snprintf(filename, size, "%s/vl.XXXXXX", tmpdir); + fd = mkstemp(filename); + close(fd); + } diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/04_do_not_print_rtc_freq_if_ok.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/04_do_not_print_rtc_freq_if_ok.patch new file mode 100644 index 0000000000..31c9da491d --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/04_do_not_print_rtc_freq_if_ok.patch @@ -0,0 +1,26 @@ +#DPATCHLEVEL=1 +--- +# vl.c | 5 ++++- +# 1 file changed, 4 insertions(+), 1 deletion(-) +# +Index: qemu/vl.c +=================================================================== +--- qemu.orig/vl.c 2007-12-03 15:44:35.000000000 +0000 ++++ qemu/vl.c 2007-12-03 15:51:03.000000000 +0000 +@@ -1289,12 +1289,15 @@ static void hpet_stop_timer(struct qemu_ + + static int rtc_start_timer(struct qemu_alarm_timer *t) + { ++ unsigned long current_rtc_freq = 0; + int rtc_fd; + + TFR(rtc_fd = open("/dev/rtc", O_RDONLY)); + if (rtc_fd < 0) + return -1; +- if (ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) { ++ ioctl(rtc_fd, RTC_IRQP_READ, ¤t_rtc_freq); ++ if (current_rtc_freq != RTC_FREQ && ++ ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) { + fprintf(stderr, "Could not configure '/dev/rtc' to have a 1024 Hz timer. This is not a fatal\n" + "error, but for better emulation accuracy either use a 2.6 host Linux kernel or\n" + "type 'echo 1024 > /proc/sys/dev/rtc/max-user-freq' as root.\n"); diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/05_non-fatal_if_linux_hd_missing.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/05_non-fatal_if_linux_hd_missing.patch new file mode 100644 index 0000000000..fdd922605e --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/05_non-fatal_if_linux_hd_missing.patch @@ -0,0 +1,17 @@ +#DPATCHLEVEL=1 +--- +# hw/pc.c | 1 - +# 1 file changed, 1 deletion(-) +# +Index: qemu/hw/pc.c +=================================================================== +--- qemu.orig/hw/pc.c 2007-12-03 23:47:25.000000000 +0000 ++++ qemu/hw/pc.c 2007-12-03 23:47:38.000000000 +0000 +@@ -385,7 +385,6 @@ static void generate_bootsect(uint32_t g + if (bs_table[0] == NULL) { + fprintf(stderr, "A disk image must be given for 'hda' when booting " + "a Linux kernel\n"); +- exit(1); + } + + memset(bootsect, 0, sizeof(bootsect)); diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/06_exit_segfault.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/06_exit_segfault.patch new file mode 100644 index 0000000000..06123d0626 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/06_exit_segfault.patch @@ -0,0 +1,45 @@ +#DPATCHLEVEL=0 +--- +# linux-user/main.c | 8 ++++---- +# 1 file changed, 4 insertions(+), 4 deletions(-) +# +Index: linux-user/main.c +=================================================================== +--- linux-user/main.c.orig 2007-12-03 23:47:25.000000000 +0000 ++++ linux-user/main.c 2007-12-03 23:47:41.000000000 +0000 +@@ -714,7 +714,7 @@ void cpu_loop (CPUSPARCState *env) + default: + printf ("Unhandled trap: 0x%x\n", trapnr); + cpu_dump_state(env, stderr, fprintf, 0); +- exit (1); ++ _exit (1); + } + process_pending_signals (env); + } +@@ -1634,7 +1634,7 @@ void cpu_loop (CPUState *env) + default: + printf ("Unhandled trap: 0x%x\n", trapnr); + cpu_dump_state(env, stderr, fprintf, 0); +- exit (1); ++ _exit (1); + } + process_pending_signals (env); + } +@@ -1954,7 +1954,7 @@ int main(int argc, char **argv) + 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, "s")) { +@@ -1973,7 +1973,7 @@ int main(int argc, char **argv) + 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")) { + gdbstub_port = atoi(argv[optind++]); diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/10_signal_jobs.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/10_signal_jobs.patch new file mode 100644 index 0000000000..34282adc9d --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/10_signal_jobs.patch @@ -0,0 +1,26 @@ +#DPATCHLEVEL=0 +--- +# linux-user/signal.c | 7 ++++++- +# 1 file changed, 6 insertions(+), 1 deletion(-) +# +Index: linux-user/signal.c +=================================================================== +--- linux-user/signal.c.orig 2007-12-03 15:40:26.000000000 +0000 ++++ linux-user/signal.c 2007-12-03 15:55:49.000000000 +0000 +@@ -364,10 +364,15 @@ int queue_signal(int sig, target_siginfo + k = &sigact_table[sig - 1]; + handler = k->sa._sa_handler; + if (handler == TARGET_SIG_DFL) { ++ if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) { ++ kill(getpid(),SIGSTOP); ++ return 0; ++ } else + /* default handler : ignore some signal. The other are fatal */ + if (sig != TARGET_SIGCHLD && + sig != TARGET_SIGURG && +- sig != TARGET_SIGWINCH) { ++ sig != TARGET_SIGWINCH && ++ sig != TARGET_SIGCONT) { + force_sig(sig); + } else { + return 0; /* indicate ignored */ diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/11_signal_sigaction.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/11_signal_sigaction.patch new file mode 100644 index 0000000000..33c5e8b12d --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/11_signal_sigaction.patch @@ -0,0 +1,21 @@ +#DPATCHLEVEL=0 +--- +# linux-user/signal.c | 5 +++++ +# 1 file changed, 5 insertions(+) +# +Index: linux-user/signal.c +=================================================================== +--- linux-user/signal.c.orig 2007-12-03 23:47:44.000000000 +0000 ++++ linux-user/signal.c 2007-12-03 23:47:46.000000000 +0000 +@@ -512,6 +512,11 @@ int do_sigaction(int sig, const struct t + + if (sig < 1 || sig > TARGET_NSIG || sig == SIGKILL || sig == SIGSTOP) + return -EINVAL; ++ ++ /* no point doing the stuff as those are not allowed for sigaction */ ++ if ((sig == TARGET_SIGKILL) || (sig == TARGET_SIGSTOP)) ++ return -EINVAL; ++ + k = &sigact_table[sig - 1]; + #if defined(DEBUG_SIGNAL) + fprintf(stderr, "sigaction sig=%d act=0x%08x, oact=0x%08x\n", diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/22_net_tuntap_stall.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/22_net_tuntap_stall.patch new file mode 100644 index 0000000000..6017df0f6d --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/22_net_tuntap_stall.patch @@ -0,0 +1,18 @@ +#DPATCHLEVEL=0 +--- +# vl.c | 2 +- +# 1 file changed, 1 insertion(+), 1 deletion(-) +# +Index: vl.c +=================================================================== +--- vl.c.orig 2007-12-03 23:47:36.000000000 +0000 ++++ vl.c 2007-12-03 23:47:48.000000000 +0000 +@@ -4023,7 +4023,7 @@ static int tap_open(char *ifname, int if + return -1; + } + memset(&ifr, 0, sizeof(ifr)); +- ifr.ifr_flags = IFF_TAP | IFF_NO_PI; ++ ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE; + if (ifname[0] != '\0') + pstrcpy(ifr.ifr_name, IFNAMSIZ, ifname); + else diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/31_syscalls.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/31_syscalls.patch new file mode 100644 index 0000000000..95a7332ee8 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/31_syscalls.patch @@ -0,0 +1,48 @@ +#DPATCHLEVEL=0 +--- +# linux-user/syscall.c | 11 ++++++++--- +# 1 file changed, 8 insertions(+), 3 deletions(-) +# +Index: linux-user/syscall.c +=================================================================== +--- linux-user/syscall.c.orig 2007-12-03 19:32:56.000000000 +0000 ++++ linux-user/syscall.c 2007-12-03 19:33:41.000000000 +0000 +@@ -250,6 +250,7 @@ extern int getresuid(uid_t *, uid_t *, u + extern int setresgid(gid_t, gid_t, gid_t); + extern int getresgid(gid_t *, gid_t *, gid_t *); + extern int setgroups(int, gid_t *); ++extern int uselib(const char*); + + #define ERRNO_TABLE_SIZE 1200 + +@@ -4024,7 +4025,8 @@ abi_long do_syscall(void *cpu_env, int n + #endif + #ifdef TARGET_NR_uselib + case TARGET_NR_uselib: +- goto unimplemented; ++ ret = get_errno(uselib(path((const char*)arg1))); ++ break; + #endif + #ifdef TARGET_NR_swapon + case TARGET_NR_swapon: +@@ -5289,7 +5291,9 @@ abi_long do_syscall(void *cpu_env, int n + goto unimplemented; + #ifdef TARGET_NR_mincore + case TARGET_NR_mincore: +- goto unimplemented; ++ /*page_unprotect_range((void*)arg3, ((size_t)arg2 + TARGET_PAGE_SIZE - 1) / TARGET_PAGE_SIZE);*/ ++ ret = get_errno(mincore((void*)arg1, (size_t)arg2, (unsigned char*)arg3)); ++ break; + #endif + #ifdef TARGET_NR_madvise + case TARGET_NR_madvise: +@@ -5429,7 +5433,8 @@ abi_long do_syscall(void *cpu_env, int n + break; + #ifdef TARGET_NR_readahead + case TARGET_NR_readahead: +- goto unimplemented; ++ ret = get_errno(readahead((int)arg1, (off64_t)arg2, (size_t)arg3)); ++ break; + #endif + #ifdef TARGET_NR_setxattr + case TARGET_NR_setxattr: diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/32_syscall_sysctl.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/32_syscall_sysctl.patch new file mode 100644 index 0000000000..5e8dd75b0e --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/32_syscall_sysctl.patch @@ -0,0 +1,55 @@ +#DPATCHLEVEL=0 +--- +# linux-user/syscall.c | 32 +++++++++++++++++++++++++++++--- +# 1 file changed, 29 insertions(+), 3 deletions(-) +# +Index: linux-user/syscall.c +=================================================================== +--- linux-user/syscall.c.orig 2007-12-03 15:56:24.000000000 +0000 ++++ linux-user/syscall.c 2007-12-03 15:57:36.000000000 +0000 +@@ -52,6 +52,7 @@ + //#include + #include + #include ++#include + + #define termios host_termios + #define winsize host_winsize +@@ -4739,9 +4740,34 @@ abi_long do_syscall(void *cpu_env, int n + break; + #endif + case TARGET_NR__sysctl: +- /* We don't implement this, but ENOTDIR is always a safe +- return value. */ +- ret = -TARGET_ENOTDIR; ++ { ++ struct __sysctl_args *args = (struct __sysctl_args *) arg1; ++ int *name_target, *name, nlen, *oldlenp, oldlen, newlen, i; ++ void *oldval, *newval; ++ ++ name_target = (int *) tswapl((long) args->name); ++ nlen = tswapl(args->nlen); ++ oldval = (void *) tswapl((long) args->oldval); ++ oldlenp = (int *) tswapl((long) args->oldlenp); ++ oldlen = tswapl(*oldlenp); ++ newval = (void *) tswapl((long) args->newval); ++ newlen = tswapl(args->newlen); ++ ++ name = alloca(nlen * sizeof (int)); ++ for (i = 0; i < nlen; i++) ++ name[i] = tswapl(name_target[i]); ++ ++ if (nlen == 2 && name[0] == CTL_KERN && name[1] == KERN_VERSION) { ++ ret = get_errno( ++ sysctl(name, nlen, oldval, &oldlen, newval, newlen)); ++ if (!is_error(ret)) { ++ *oldlenp = tswapl(oldlen); ++ } ++ } else { ++ gemu_log("qemu: Unsupported sysctl name\n"); ++ ret = -ENOSYS; ++ } ++ } + break; + case TARGET_NR_sched_setparam: + { diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/33_syscall_ppc_clone.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/33_syscall_ppc_clone.patch new file mode 100644 index 0000000000..3f733b6ab8 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/33_syscall_ppc_clone.patch @@ -0,0 +1,22 @@ +#DPATCHLEVEL=0 +--- +# linux-user/syscall.c | 6 +----- +# 1 file changed, 1 insertion(+), 5 deletions(-) +# +Index: linux-user/syscall.c +=================================================================== +--- linux-user/syscall.c.orig 2007-12-03 15:58:11.000000000 +0000 ++++ linux-user/syscall.c 2007-12-03 15:58:46.000000000 +0000 +@@ -2750,11 +2750,7 @@ int do_fork(CPUState *env, unsigned int + if (!newsp) + newsp = env->gpr[1]; + new_env->gpr[1] = newsp; +- { +- int i; +- for (i = 7; i < 32; i++) +- new_env->gpr[i] = 0; +- } ++ new_env->gpr[3] = 0; + #elif defined(TARGET_SH4) + if (!newsp) + newsp = env->gregs[15]; diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/39_syscall_fadvise64.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/39_syscall_fadvise64.patch new file mode 100644 index 0000000000..54ee3e0948 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/39_syscall_fadvise64.patch @@ -0,0 +1,21 @@ +--- + linux-user/syscall.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +Index: linux-user/syscall.c +=================================================================== +--- linux-user/syscall.c.orig 2007-12-03 19:33:47.000000000 +0000 ++++ linux-user/syscall.c 2007-12-03 19:33:48.000000000 +0000 +@@ -5317,6 +5317,12 @@ abi_long do_syscall(void *cpu_env, int n + ret = get_errno(mincore((void*)arg1, (size_t)arg2, (unsigned char*)arg3)); + break; + #endif ++#ifdef TARGET_NR_fadvise64_64 ++ case TARGET_NR_fadvise64_64: ++ /* Just return success */ ++ ret = get_errno(0); ++ break; ++#endif + #ifdef TARGET_NR_madvise + case TARGET_NR_madvise: + /* A straight passthrough may not be safe because qemu sometimes diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/41_arm_fpa_sigfpe.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/41_arm_fpa_sigfpe.patch new file mode 100644 index 0000000000..cea3afc7ff --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/41_arm_fpa_sigfpe.patch @@ -0,0 +1,104 @@ +#DPATCHLEVEL=0 +--- +# linux-user/main.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++- +# target-arm/nwfpe/fpa11.c | 7 ++++++ +# 2 files changed, 57 insertions(+), 1 deletion(-) +# +Index: linux-user/main.c +=================================================================== +--- linux-user/main.c.orig 2007-12-03 15:59:10.000000000 +0000 ++++ linux-user/main.c 2007-12-03 16:01:27.000000000 +0000 +@@ -377,18 +377,67 @@ void cpu_loop(CPUARMState *env) + { + TaskState *ts = env->opaque; + uint32_t opcode; ++ int rc; + + /* we handle the FPU emulation here, as Linux */ + /* we get the opcode */ + /* FIXME - what to do if get_user() fails? */ + get_user_u32(opcode, env->regs[15]); + +- if (EmulateAll(opcode, &ts->fpa, env) == 0) { ++ rc = EmulateAll(opcode, &ts->fpa, env); ++ if (rc == 0) { /* illegal instruction */ + info.si_signo = SIGILL; + info.si_errno = 0; + info.si_code = TARGET_ILL_ILLOPN; + info._sifields._sigfault._addr = env->regs[15]; + queue_signal(info.si_signo, &info); ++ } else if (rc < 0) { /* FP exception */ ++ int arm_fpe=0; ++ ++ /* translate softfloat flags to FPSR flags */ ++ if (-rc & float_flag_invalid) ++ arm_fpe |= BIT_IOC; ++ if (-rc & float_flag_divbyzero) ++ arm_fpe |= BIT_DZC; ++ if (-rc & float_flag_overflow) ++ arm_fpe |= BIT_OFC; ++ if (-rc & float_flag_underflow) ++ arm_fpe |= BIT_UFC; ++ if (-rc & float_flag_inexact) ++ arm_fpe |= BIT_IXC; ++ ++ FPSR fpsr = ts->fpa.fpsr; ++ //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe); ++ ++ if (fpsr & (arm_fpe << 16)) { /* exception enabled? */ ++ info.si_signo = SIGFPE; ++ info.si_errno = 0; ++ ++ /* ordered by priority, least first */ ++ if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES; ++ if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND; ++ if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF; ++ if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV; ++ if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV; ++ ++ info._sifields._sigfault._addr = env->regs[15]; ++ queue_signal(info.si_signo, &info); ++ } else { ++ env->regs[15] += 4; ++ } ++ ++ /* accumulate unenabled exceptions */ ++ if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC)) ++ fpsr |= BIT_IXC; ++ if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC)) ++ fpsr |= BIT_UFC; ++ if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC)) ++ fpsr |= BIT_OFC; ++ if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC)) ++ fpsr |= BIT_DZC; ++ if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC)) ++ fpsr |= BIT_IOC; ++ ts->fpa.fpsr=fpsr; + } else { + /* increment PC */ + env->regs[15] += 4; +Index: target-arm/nwfpe/fpa11.c +=================================================================== +--- target-arm/nwfpe/fpa11.c.orig 2007-12-03 15:40:26.000000000 +0000 ++++ target-arm/nwfpe/fpa11.c 2007-12-03 15:59:11.000000000 +0000 +@@ -162,6 +162,8 @@ unsigned int EmulateAll(unsigned int opc + fpa11->initflag = 1; + } + ++ set_float_exception_flags(0, &fpa11->fp_status); ++ + if (TEST_OPCODE(opcode,MASK_CPRT)) + { + //fprintf(stderr,"emulating CPRT\n"); +@@ -191,6 +193,11 @@ unsigned int EmulateAll(unsigned int opc + } + + // restore_flags(flags); ++ if(nRc == 1 && get_float_exception_flags(&fpa11->fp_status)) ++ { ++ //printf("fef 0x%x\n",float_exception_flags); ++ nRc=-get_float_exception_flags(&fpa11->fp_status); ++ } + + //printf("returning %d\n",nRc); + return(nRc); diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/52_ne2000_return.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/52_ne2000_return.patch new file mode 100644 index 0000000000..e4ea33f2c6 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/52_ne2000_return.patch @@ -0,0 +1,17 @@ +--- + hw/ne2000.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: qemu/hw/ne2000.c +=================================================================== +--- qemu.orig/hw/ne2000.c 2007-12-03 19:32:52.000000000 +0000 ++++ qemu/hw/ne2000.c 2007-12-03 19:33:55.000000000 +0000 +@@ -217,7 +217,7 @@ static int ne2000_can_receive(void *opaq + NE2000State *s = opaque; + + if (s->cmd & E8390_STOP) +- return 1; ++ return 0; + return !ne2000_buffer_full(s); + } + diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/61_safe_64bit_int.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/61_safe_64bit_int.patch new file mode 100644 index 0000000000..9b1ace81a5 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/61_safe_64bit_int.patch @@ -0,0 +1,27 @@ +#DPATCHLEVEL=0 +--- +# dyngen-exec.h | 4 ++-- +# 1 file changed, 2 insertions(+), 2 deletions(-) +# +Index: dyngen-exec.h +=================================================================== +--- dyngen-exec.h.orig 2007-12-31 13:06:21.000000000 +0000 ++++ dyngen-exec.h 2007-12-31 13:08:54.000000000 +0000 +@@ -38,7 +38,7 @@ + // Linux/Sparc64 defines uint64_t + #if !(defined (__sparc_v9__) && defined(__linux__)) + /* XXX may be done for all 64 bits targets ? */ +-#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__) ++#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__) || defined(__sparc__) + typedef unsigned long uint64_t; + #else + typedef unsigned long long uint64_t; +@@ -55,7 +55,7 @@ + typedef signed int int32_t; + // Linux/Sparc64 defines int64_t + #if !(defined (__sparc_v9__) && defined(__linux__)) +-#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__) ++#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__) || defined(__sparc__) + typedef signed long int64_t; + #else + typedef signed long long int64_t; diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/63_sparc_build.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/63_sparc_build.patch new file mode 100644 index 0000000000..37b38f641b --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/63_sparc_build.patch @@ -0,0 +1,18 @@ +#DPATCHLEVEL=0 +--- +# sparc.ld | 2 +- +# 1 file changed, 1 insertion(+), 1 deletion(-) +# +Index: sparc.ld +=================================================================== +--- sparc.ld.orig 2007-12-03 15:40:26.000000000 +0000 ++++ sparc.ld 2007-12-03 16:05:06.000000000 +0000 +@@ -6,7 +6,7 @@ ENTRY(_start) + SECTIONS + { + /* Read-only sections, merged into text segment: */ +- . = 0x60000000 + SIZEOF_HEADERS; ++ . = 0x60000000 + 0x400; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/64_ppc_asm_constraints.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/64_ppc_asm_constraints.patch new file mode 100644 index 0000000000..e4858b79d7 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/64_ppc_asm_constraints.patch @@ -0,0 +1,18 @@ +#DPATCHLEVEL=1 +--- +# cpu-all.h | 2 +- +# 1 file changed, 1 insertion(+), 1 deletion(-) +# +Index: qemu/cpu-all.h +=================================================================== +--- qemu.orig/cpu-all.h 2007-06-13 11:48:22.000000000 +0100 ++++ qemu/cpu-all.h 2007-06-13 11:51:56.000000000 +0100 +@@ -250,7 +250,7 @@ static inline void stw_le_p(void *ptr, i + static inline void stl_le_p(void *ptr, int v) + { + #ifdef __powerpc__ +- __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr)); ++ __asm__ __volatile__ ("stwbrx %0,0,%1" : : "r" (v), "r" (ptr) : "memory"); + #else + uint8_t *p = ptr; + p[0] = v; diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/65_kfreebsd.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/65_kfreebsd.patch new file mode 100644 index 0000000000..dfece800ac --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/65_kfreebsd.patch @@ -0,0 +1,35 @@ +--- + configure | 6 ++++++ + vl.c | 2 ++ + 2 files changed, 8 insertions(+) + +Index: configure +=================================================================== +--- configure.orig 2007-12-03 15:40:26.000000000 +0000 ++++ configure 2007-12-03 16:05:34.000000000 +0000 +@@ -129,6 +129,12 @@ if [ "$cpu" = "i386" -o "$cpu" = "x86_64 + kqemu="yes" + fi + ;; ++GNU/kFreeBSD) ++oss="yes" ++if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then ++ kqemu="yes" ++fi ++;; + FreeBSD) + bsd="yes" + oss="yes" +Index: vl.c +=================================================================== +--- vl.c.orig 2007-12-03 16:05:32.000000000 +0000 ++++ vl.c 2007-12-03 16:05:34.000000000 +0000 +@@ -97,6 +97,8 @@ + #include + #endif + #endif ++#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__) ++#include + #else + #include + int inet_aton(const char *cp, struct in_addr *ia); diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/66_tls_ld.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/66_tls_ld.patch new file mode 100644 index 0000000000..54e02eff8b --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/66_tls_ld.patch @@ -0,0 +1,55 @@ +--- + arm.ld | 7 +++++++ + i386.ld | 7 +++++++ + 2 files changed, 14 insertions(+) + +Index: arm.ld +=================================================================== +--- arm.ld.orig 2007-06-13 11:48:22.000000000 +0100 ++++ arm.ld 2007-06-13 11:51:56.000000000 +0100 +@@ -26,6 +26,10 @@ SECTIONS + { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } + .rela.rodata : + { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } ++ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } ++ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } ++ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } ++ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } +@@ -58,6 +62,9 @@ SECTIONS + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + __exidx_end = .; + .reginfo : { *(.reginfo) } ++ /* Thread Local Storage sections */ ++ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } ++ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(0x100000) + (. & (0x100000 - 1)); +Index: i386.ld +=================================================================== +--- i386.ld.orig 2007-06-13 11:48:22.000000000 +0100 ++++ i386.ld 2007-06-13 11:51:56.000000000 +0100 +@@ -28,6 +28,10 @@ SECTIONS + { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } + .rela.rodata : + { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } ++ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } ++ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } ++ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } ++ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } +@@ -53,6 +57,9 @@ SECTIONS + _etext = .; + PROVIDE (etext = .); + .fini : { *(.fini) } =0x47ff041f ++ /* Thread Local Storage sections */ ++ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } ++ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + . = ALIGN(32 / 8); + PROVIDE (__preinit_array_start = .); + .preinit_array : { *(.preinit_array) } diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/91-oh-sdl-cursor.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/91-oh-sdl-cursor.patch new file mode 100644 index 0000000000..0d60c1c306 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/91-oh-sdl-cursor.patch @@ -0,0 +1,18 @@ +=== modified file 'sdl.c' +--- + sdl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: sdl.c +=================================================================== +--- sdl.c.orig 2007-12-03 19:32:15.000000000 +0000 ++++ sdl.c 2007-12-03 19:34:04.000000000 +0000 +@@ -247,7 +247,7 @@ static void sdl_hide_cursor(void) + + if (kbd_mouse_is_absolute()) { + SDL_ShowCursor(1); +- SDL_SetCursor(sdl_cursor_hidden); ++ /* SDL_SetCursor(sdl_cursor_hidden); */ + } else { + SDL_ShowCursor(0); + } diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/configure_symlinkpath_fix.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/configure_symlinkpath_fix.patch new file mode 100644 index 0000000000..3ec304a38c --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/configure_symlinkpath_fix.patch @@ -0,0 +1,28 @@ +Index: qemu-0.9.1/configure +=================================================================== +--- qemu-0.9.1.orig/configure 2008-01-24 15:33:13.000000000 +0000 ++++ qemu-0.9.1/configure 2008-01-24 15:45:50.000000000 +0000 +@@ -209,15 +209,17 @@ + + # find source path + source_path=`dirname "$0"` ++source_path_used="no" ++workdir=`pwd` ++workdir=`readlink -f $workdir` + if [ -z "$source_path" ]; then +- source_path=`pwd` ++ source_path=$workdir + else + source_path=`cd "$source_path"; pwd` +-fi +-if test "$source_path" = `pwd` ; then +- source_path_used="no" +-else +- source_path_used="yes" ++ source_path=`readlink -f $source_path` ++ if test "$source_path" != "$workdir" ; then ++ source_path_used="yes" ++ fi + fi + + werror="no" diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/disable-error-in-configure.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/disable-error-in-configure.patch new file mode 100644 index 0000000000..017f9f6355 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/disable-error-in-configure.patch @@ -0,0 +1,17 @@ +--- + configure | 2 -- + 1 file changed, 2 deletions(-) + +Index: qemu/configure +=================================================================== +--- qemu.orig/configure 2007-12-03 16:38:38.000000000 +0000 ++++ qemu/configure 2007-12-03 16:38:39.000000000 +0000 +@@ -323,8 +323,6 @@ for opt do + ;; + --disable-werror) werror="no" + ;; +- *) echo "ERROR: unknown option $opt"; show_help="yes" +- ;; + --disable-nptl) nptl="no" + ;; + esac diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/fix_segfault.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/fix_segfault.patch new file mode 100644 index 0000000000..443c330650 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/fix_segfault.patch @@ -0,0 +1,37 @@ +--- + linux-user/syscall.c | 22 ---------------------- + 1 file changed, 22 deletions(-) + +Index: qemu/linux-user/syscall.c +=================================================================== +--- qemu.orig/linux-user/syscall.c 2007-12-03 23:40:11.000000000 +0000 ++++ qemu/linux-user/syscall.c 2007-12-03 23:40:21.000000000 +0000 +@@ -5695,28 +5695,6 @@ abi_long do_syscall(void *cpu_env, int n + goto unimplemented_nowarn; + #endif + +-#ifdef TARGET_NR_clock_gettime +- case TARGET_NR_clock_gettime: +- { +- struct timespec ts; +- ret = get_errno(clock_gettime(arg1, &ts)); +- if (!is_error(ret)) { +- host_to_target_timespec(arg2, &ts); +- } +- break; +- } +-#endif +-#ifdef TARGET_NR_clock_getres +- case TARGET_NR_clock_getres: +- { +- struct timespec ts; +- ret = get_errno(clock_getres(arg1, &ts)); +- if (!is_error(ret)) { +- host_to_target_timespec(arg2, &ts); +- } +- break; +- } +-#endif + + #if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address) + case TARGET_NR_set_tid_address: diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/no-strip.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/no-strip.patch new file mode 100644 index 0000000000..fc69b37e16 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/no-strip.patch @@ -0,0 +1,22 @@ +--- qemu.orig/Makefile 2008-01-29 23:16:27.000000000 -0800 ++++ qemu-0.9.1/Makefile 2008-01-29 23:16:38.000000000 -0800 +@@ -174,7 +174,7 @@ + install: all $(if $(BUILD_DOCS),install-doc) + mkdir -p "$(DESTDIR)$(bindir)" + ifneq ($(TOOLS),) +- $(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)" ++ $(INSTALL) -m 755 $(TOOLS) "$(DESTDIR)$(bindir)" + endif + mkdir -p "$(DESTDIR)$(datadir)" + for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \ +--- qemu.orig/Makefile.target 2008-01-29 23:16:27.000000000 -0800 ++++ qemu-0.9.1/Makefile.target 2008-01-29 23:17:33.000000000 -0800 +@@ -632,7 +632,7 @@ + + install: all + ifneq ($(PROGS),) +- $(INSTALL) -m 755 -s $(PROGS) "$(DESTDIR)$(bindir)" ++ $(INSTALL) -m 755 $(PROGS) "$(DESTDIR)$(bindir)" + endif + + ifneq ($(wildcard .depend),) diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-0.9.0-nptl-update.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-0.9.0-nptl-update.patch new file mode 100644 index 0000000000..ebc996e873 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-0.9.0-nptl-update.patch @@ -0,0 +1,219 @@ +--- + linux-user/main.c | 7 ++- + linux-user/syscall.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 111 insertions(+), 10 deletions(-) + +Index: qemu/linux-user/main.c +=================================================================== +--- qemu.orig/linux-user/main.c 2007-12-03 19:34:09.000000000 +0000 ++++ qemu/linux-user/main.c 2007-12-03 23:44:45.000000000 +0000 +@@ -391,7 +391,7 @@ do_kernel_trap(CPUARMState *env) + cpu_unlock(); + break; + case 0xffff0fe0: /* __kernel_get_tls */ +- env->regs[0] = env->cp15.c13_tls; ++ env->regs[0] = env->cp15.c13_tls2; + break; + default: + return 1; +@@ -2037,6 +2037,11 @@ int main(int argc, char **argv) + int drop_ld_preload = 0, environ_count = 0; + char **target_environ, **wrk, **dst; + ++ char *assume_kernel = getenv("QEMU_ASSUME_KERNEL"); ++ ++ if (assume_kernel) ++ setenv("LD_ASSUME_KERNEL", assume_kernel, 1); ++ + if (argc <= 1) + usage(); + +Index: qemu/linux-user/syscall.c +=================================================================== +--- qemu.orig/linux-user/syscall.c 2007-12-03 19:34:09.000000000 +0000 ++++ qemu/linux-user/syscall.c 2007-12-03 23:46:54.000000000 +0000 +@@ -61,6 +61,7 @@ + #define tchars host_tchars /* same as target */ + #define ltchars host_ltchars /* same as target */ + ++#include + #include + #include + #include +@@ -2694,7 +2695,6 @@ abi_long do_arch_prctl(CPUX86State *env, + return 0; + } + #endif +- + #endif /* defined(TARGET_I386) */ + + /* this stack is the equivalent of the kernel stack associated with a +@@ -2729,16 +2729,19 @@ int do_fork(CPUState *env, unsigned int + TaskState *ts; + uint8_t *new_stack; + CPUState *new_env; +- ++#if defined(TARGET_I386) ++ uint64_t *new_gdt_table; ++#endif + #ifdef USE_NPTL + unsigned int nptl_flags; + + if (flags & CLONE_PARENT_SETTID) + *parent_tidptr = gettid(); + #endif +- + if (flags & CLONE_VM) { + ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE); ++ if (!ts) ++ return -ENOMEM; + memset(ts, 0, sizeof(TaskState)); + new_stack = ts->stack; + ts->used = 1; +@@ -2750,6 +2753,29 @@ int do_fork(CPUState *env, unsigned int + #if defined(TARGET_I386) + if (!newsp) + newsp = env->regs[R_ESP]; ++ new_gdt_table = malloc(9 * 8); ++ if (!new_gdt_table) { ++ free(new_env); ++ return -ENOMEM; ++ } ++ /* Copy main GDT table from parent, but clear TLS entries */ ++ memcpy(new_gdt_table, g2h(env->gdt.base), 6 * 8); ++ memset(&new_gdt_table[6], 0, 3 * 8); ++ new_env->gdt.base = h2g(new_gdt_table); ++ if (flags & 0x00080000 /* CLONE_SETTLS */) { ++ ret = do_set_thread_area(new_env, new_env->regs[R_ESI]); ++ if (ret) { ++ free(new_gdt_table); ++ free(new_env); ++ return ret; ++ } ++ } ++ cpu_x86_load_seg(env, R_CS, new_env->regs[R_CS]); ++ cpu_x86_load_seg(env, R_DS, new_env->regs[R_DS]); ++ cpu_x86_load_seg(env, R_ES, new_env->regs[R_ES]); ++ cpu_x86_load_seg(env, R_SS, new_env->regs[R_SS]); ++ cpu_x86_load_seg(env, R_FS, new_env->regs[R_FS]); ++ cpu_x86_load_seg(env, R_GS, new_env->regs[R_GS]); + new_env->regs[R_ESP] = newsp; + new_env->regs[R_EAX] = 0; + #elif defined(TARGET_ARM) +@@ -3121,6 +3147,68 @@ static inline abi_long host_to_target_ti + unlock_user_struct(target_ts, target_addr, 1); + } + ++static long do_futex(target_ulong uaddr, int op, uint32_t val, ++ target_ulong utime, target_ulong uaddr2, ++ uint32_t val3) ++{ ++ struct timespec host_utime; ++ unsigned long val2 = utime; ++ ++ if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) { ++ target_to_host_timespec(&host_utime, utime); ++ val2 = (unsigned long)&host_utime; ++ } ++ ++#ifdef BSWAP_NEEDED ++ switch(op) { ++ case FUTEX_CMP_REQUEUE: ++ val3 = tswap32(val3); ++ case FUTEX_REQUEUE: ++ val2 = tswap32(val2); ++ case FUTEX_WAIT: ++ case FUTEX_WAKE: ++ val = tswap32(val); ++ case FUTEX_LOCK_PI: /* This one's icky, but comes out OK */ ++ case FUTEX_UNLOCK_PI: ++ break; ++ default: ++ gemu_log("qemu: Unsupported futex op %d\n", op); ++ return -ENOSYS; ++ } ++#if 0 /* No, it's worse than this */ ++ if (op == FUTEX_WAKE_OP) { ++ /* Need to munge the secondary operation (val3) */ ++ val3 = tswap32(val3); ++ int op2 = (val3 >> 28) & 7; ++ int cmp = (val3 >> 24) & 15; ++ int oparg = (val3 << 8) >> 20; ++ int cmparg = (val3 << 20) >> 20; ++ int shift = val3 & (FUTEX_OP_OPARG_SHIFT << 28); ++ ++ if (shift) ++ oparg = (oparg & 7) + 24 - (oparg & 24); ++ else oparg = ++ if (op2 == FUTEX_OP_ADD) { ++ gemu_log("qemu: Unsupported wrong-endian FUTEX_OP_ADD\n"); ++ return -ENOSYS; ++ } ++ if (cmparg == FUTEX_OP_CMP_LT || cmparg == FUTEX_OP_CMP_GE || ++ cmparg == FUTEX_OP_CMP_LE || cmparg == FUTEX_OP_CMP_GT) { ++ gemu_log("qemu: Unsupported wrong-endian futex cmparg %d\n", cmparg); ++ return -ENOSYS; ++ } ++ val3 = shift | (op2<<28) | (cmp<<24) | (oparg<<12) | cmparg; ++ } ++#endif ++#endif ++ return syscall(__NR_futex, g2h(uaddr), op, val, val2, g2h(uaddr2), val3); ++} ++ ++int do_set_tid_address(target_ulong tidptr) ++{ ++ return syscall(__NR_set_tid_address, g2h(tidptr)); ++} ++ + /* do_syscall() should always have a single exit point at the end so + that actions, such as logging of syscall results, can be performed. + All errnos that do_syscall() returns must be -TARGET_. */ +@@ -3145,7 +3233,7 @@ abi_long do_syscall(void *cpu_env, int n + _mcleanup(); + #endif + gdb_exit(cpu_env, arg1); +- /* XXX: should free thread stack and CPU env */ ++ /* XXX: should free thread stack, GDT and CPU env */ + _exit(arg1); + ret = 0; /* avoid warning */ + break; +@@ -5569,6 +5657,9 @@ abi_long do_syscall(void *cpu_env, int n + #elif defined(TARGET_I386) && defined(TARGET_ABI32) + ret = do_set_thread_area(cpu_env, arg1); + break; ++#elif TARGET_i386 ++ ret = get_errno(do_set_thread_area(cpu_env, arg1)); ++ break; + #else + goto unimplemented_nowarn; + #endif +@@ -5586,6 +5677,16 @@ abi_long do_syscall(void *cpu_env, int n + goto unimplemented_nowarn; + #endif + ++#ifdef TARGET_NR_futex ++ case TARGET_NR_futex: ++ ret = get_errno(do_futex(arg1, arg2, arg3, arg4, arg5, arg6)); ++ break; ++#endif ++#ifdef TARGET_NR_set_robust_list ++ case TARGET_NR_set_robust_list: ++ goto unimplemented_nowarn; ++#endif ++ + #ifdef TARGET_NR_clock_gettime + case TARGET_NR_clock_gettime: + { +@@ -5627,11 +5728,6 @@ abi_long do_syscall(void *cpu_env, int n + break; + #endif + +-#ifdef TARGET_NR_set_robust_list +- case TARGET_NR_set_robust_list: +- goto unimplemented_nowarn; +-#endif +- + #if defined(TARGET_NR_utimensat) && defined(__NR_utimensat) + case TARGET_NR_utimensat: + { diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-0.9.0-nptl.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-0.9.0-nptl.patch new file mode 100644 index 0000000000..4a87d8d637 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-0.9.0-nptl.patch @@ -0,0 +1,854 @@ +These are Paul Brook's patches to QEMU-0.8.2 to enable the running of single +ARM binaries under QEMU's user-emulation mode. Without them, QEMU-0.8.1 +immediately dies saying: + Error: f0005 + qemu: uncaught target signal 6 (Aborted) - exiting +while qemu-0.8.2 dies saying: + qemu: Unsupported syscall: 983045 + cannot set up thread-local storage: unknown error + +This file is a rediffing of the patches visible at +https://nowt.dyndns.org/patch.qemu_nptl on 27 Sept 2006 +which "patch" fails to apply automatically. +See also http://lists.gnu.org/archive/html/qemu-devel/2006-09/msg00194.html + + Martin Guy, 27 Sept 2006 + +--- + configure | 25 ++++++ + exec-all.h | 165 ------------------------------------------ + linux-user/arm/syscall.h | 4 - + linux-user/main.c | 94 +++++++++++++++++++++--- + linux-user/qemu.h | 3 + linux-user/syscall.c | 91 ++++++++++++++++++++++- + qemu_spinlock.h | 181 +++++++++++++++++++++++++++++++++++++++++++++++ + target-arm/cpu.h | 10 ++ + target-arm/op.c | 6 + + target-arm/translate.c | 9 ++ + 10 files changed, 405 insertions(+), 183 deletions(-) + +Index: qemu/configure +=================================================================== +--- qemu.orig/configure 2008-04-09 23:02:37.000000000 +0100 ++++ qemu/configure 2008-04-09 23:06:36.000000000 +0100 +@@ -109,6 +109,7 @@ + build_docs="no" + uname_release="" + curses="yes" ++nptl="yes" + + # OS specific + targetos=`uname -s` +@@ -334,6 +335,8 @@ + ;; + *) echo "ERROR: unknown option $opt"; show_help="yes" + ;; ++ --disable-nptl) nptl="no" ++ ;; + esac + done + +@@ -429,6 +432,7 @@ + echo " --disable-linux-user disable all linux usermode emulation targets" + echo " --enable-darwin-user enable all darwin usermode emulation targets" + echo " --disable-darwin-user disable all darwin usermode emulation targets" ++echo " --disable-nptl disable usermode NPTL guest support" + echo " --fmod-lib path to FMOD library" + echo " --fmod-inc path to FMOD includes" + echo " --enable-uname-release=R Return R for uname -r in usermode emulation" +@@ -595,6 +599,23 @@ + } + EOF + ++# check NPTL support ++cat > $TMPC < ++void foo() ++{ ++#ifndef CLONE_SETTLS ++#error bork ++#endif ++} ++EOF ++ ++if $cc -c -o $TMPO $TMPC 2> /dev/null ; then ++ : ++else ++ nptl="no" ++fi ++ + ########################################## + # SDL probe + +@@ -778,6 +799,7 @@ + echo "Documentation $build_docs" + [ ! -z "$uname_release" ] && \ + echo "uname -r $uname_release" ++echo "NPTL support $nptl" + + if test $sdl_too_old = "yes"; then + echo "-> Your SDL version is too old - please upgrade to have SDL support" +@@ -1115,6 +1137,9 @@ + echo "TARGET_ARCH=arm" >> $config_mak + echo "#define TARGET_ARCH \"arm\"" >> $config_h + echo "#define TARGET_ARM 1" >> $config_h ++ if test "$nptl" = "yes" ; then ++ echo "#define USE_NPTL 1" >> $config_h ++ fi + bflt="yes" + elif test "$target_cpu" = "sparc" ; then + echo "TARGET_ARCH=sparc" >> $config_mak +Index: qemu/exec-all.h +=================================================================== +--- qemu.orig/exec-all.h 2008-04-09 22:39:38.000000000 +0100 ++++ qemu/exec-all.h 2008-04-09 23:05:55.000000000 +0100 +@@ -297,170 +297,7 @@ + extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; + extern void *io_mem_opaque[IO_MEM_NB_ENTRIES]; + +-#if defined(__powerpc__) +-static inline int testandset (int *p) +-{ +- int ret; +- __asm__ __volatile__ ( +- "0: lwarx %0,0,%1\n" +- " xor. %0,%3,%0\n" +- " bne 1f\n" +- " stwcx. %2,0,%1\n" +- " bne- 0b\n" +- "1: " +- : "=&r" (ret) +- : "r" (p), "r" (1), "r" (0) +- : "cr0", "memory"); +- return ret; +-} +-#elif defined(__i386__) +-static inline int testandset (int *p) +-{ +- long int readval = 0; +- +- __asm__ __volatile__ ("lock; cmpxchgl %2, %0" +- : "+m" (*p), "+a" (readval) +- : "r" (1) +- : "cc"); +- return readval; +-} +-#elif defined(__x86_64__) +-static inline int testandset (int *p) +-{ +- long int readval = 0; +- +- __asm__ __volatile__ ("lock; cmpxchgl %2, %0" +- : "+m" (*p), "+a" (readval) +- : "r" (1) +- : "cc"); +- return readval; +-} +-#elif defined(__s390__) +-static inline int testandset (int *p) +-{ +- int ret; +- +- __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n" +- " jl 0b" +- : "=&d" (ret) +- : "r" (1), "a" (p), "0" (*p) +- : "cc", "memory" ); +- return ret; +-} +-#elif defined(__alpha__) +-static inline int testandset (int *p) +-{ +- int ret; +- unsigned long one; +- +- __asm__ __volatile__ ("0: mov 1,%2\n" +- " ldl_l %0,%1\n" +- " stl_c %2,%1\n" +- " beq %2,1f\n" +- ".subsection 2\n" +- "1: br 0b\n" +- ".previous" +- : "=r" (ret), "=m" (*p), "=r" (one) +- : "m" (*p)); +- return ret; +-} +-#elif defined(__sparc__) +-static inline int testandset (int *p) +-{ +- int ret; +- +- __asm__ __volatile__("ldstub [%1], %0" +- : "=r" (ret) +- : "r" (p) +- : "memory"); +- +- return (ret ? 1 : 0); +-} +-#elif defined(__arm__) +-static inline int testandset (int *spinlock) +-{ +- register unsigned int ret; +- __asm__ __volatile__("swp %0, %1, [%2]" +- : "=r"(ret) +- : "0"(1), "r"(spinlock)); +- +- return ret; +-} +-#elif defined(__mc68000) +-static inline int testandset (int *p) +-{ +- char ret; +- __asm__ __volatile__("tas %1; sne %0" +- : "=r" (ret) +- : "m" (p) +- : "cc","memory"); +- return ret; +-} +-#elif defined(__ia64) +- +-#include +- +-static inline int testandset (int *p) +-{ +- return __sync_lock_test_and_set (p, 1); +-} +-#elif defined(__mips__) +-static inline int testandset (int *p) +-{ +- int ret; +- +- __asm__ __volatile__ ( +- " .set push \n" +- " .set noat \n" +- " .set mips2 \n" +- "1: li $1, 1 \n" +- " ll %0, %1 \n" +- " sc $1, %1 \n" +- " beqz $1, 1b \n" +- " .set pop " +- : "=r" (ret), "+R" (*p) +- : +- : "memory"); +- +- return ret; +-} +-#else +-#error unimplemented CPU support +-#endif +- +-typedef int spinlock_t; +- +-#define SPIN_LOCK_UNLOCKED 0 +- +-#if defined(CONFIG_USER_ONLY) +-static inline void spin_lock(spinlock_t *lock) +-{ +- while (testandset(lock)); +-} +- +-static inline void spin_unlock(spinlock_t *lock) +-{ +- *lock = 0; +-} +- +-static inline int spin_trylock(spinlock_t *lock) +-{ +- return !testandset(lock); +-} +-#else +-static inline void spin_lock(spinlock_t *lock) +-{ +-} +- +-static inline void spin_unlock(spinlock_t *lock) +-{ +-} +- +-static inline int spin_trylock(spinlock_t *lock) +-{ +- return 1; +-} +-#endif ++#include "qemu_spinlock.h" + + extern spinlock_t tb_lock; + +Index: qemu/linux-user/arm/syscall.h +=================================================================== +--- qemu.orig/linux-user/arm/syscall.h 2007-11-27 12:09:33.000000000 +0000 ++++ qemu/linux-user/arm/syscall.h 2008-04-09 23:05:55.000000000 +0100 +@@ -28,7 +28,9 @@ + #define ARM_SYSCALL_BASE 0x900000 + #define ARM_THUMB_SYSCALL 0 + +-#define ARM_NR_cacheflush (ARM_SYSCALL_BASE + 0xf0000 + 2) ++#define ARM_NR_BASE 0xf0000 ++#define ARM_NR_cacheflush (ARM_NR_BASE + 2) ++#define ARM_NR_set_tls (ARM_NR_BASE + 5) + + #define ARM_NR_semihosting 0x123456 + #define ARM_NR_thumb_semihosting 0xAB +Index: qemu/linux-user/main.c +=================================================================== +--- qemu.orig/linux-user/main.c 2008-04-09 23:02:37.000000000 +0100 ++++ qemu/linux-user/main.c 2008-04-09 23:05:55.000000000 +0100 +@@ -364,6 +364,50 @@ + } + } + ++/* Handle a jump to the kernel code page. */ ++static int ++do_kernel_trap(CPUARMState *env) ++{ ++ uint32_t addr; ++ uint32_t *ptr; ++ uint32_t cpsr; ++ ++ switch (env->regs[15]) { ++ case 0xffff0fc0: /* __kernel_cmpxchg */ ++ /* XXX: This only works between threads, not between processes. ++ Use native atomic operations. */ ++ /* ??? This probably breaks horribly if the access segfaults. */ ++ cpu_lock(); ++ ptr = (uint32_t *)env->regs[2]; ++ cpsr = cpsr_read(env); ++ if (*ptr == env->regs[0]) { ++ *ptr = env->regs[1]; ++ env->regs[0] = 0; ++ cpsr |= CPSR_C; ++ } else { ++ env->regs[0] = -1; ++ cpsr &= ~CPSR_C; ++ } ++ cpsr_write(env, cpsr, CPSR_C); ++ cpu_unlock(); ++ break; ++ case 0xffff0fe0: /* __kernel_get_tls */ ++ env->regs[0] = env->cp15.c13_tls; ++ break; ++ default: ++ return 1; ++ } ++ /* Jump back to the caller. */ ++ addr = env->regs[14]; ++ if (addr & 1) { ++ env->thumb = 1; ++ addr &= ~1; ++ } ++ env->regs[15] = addr; ++ ++ return 0; ++} ++ + void cpu_loop(CPUARMState *env) + { + int trapnr; +@@ -474,10 +518,8 @@ + } + } + +- if (n == ARM_NR_cacheflush) { +- arm_cache_flush(env->regs[0], env->regs[1]); +- } else if (n == ARM_NR_semihosting +- || n == ARM_NR_thumb_semihosting) { ++ if (n == ARM_NR_semihosting ++ || n == ARM_NR_thumb_semihosting) { + env->regs[0] = do_arm_semihosting (env); + } else if (n == 0 || n >= ARM_SYSCALL_BASE + || (env->thumb && n == ARM_THUMB_SYSCALL)) { +@@ -488,14 +530,34 @@ + n -= ARM_SYSCALL_BASE; + env->eabi = 0; + } +- env->regs[0] = do_syscall(env, +- n, +- env->regs[0], +- env->regs[1], +- env->regs[2], +- env->regs[3], +- env->regs[4], +- env->regs[5]); ++ if ( n > ARM_NR_BASE) { ++ switch (n) ++ { ++ case ARM_NR_cacheflush: ++ arm_cache_flush(env->regs[0], env->regs[1]); ++ break; ++#ifdef USE_NPTL ++ case ARM_NR_set_tls: ++ cpu_set_tls(env, env->regs[0]); ++ env->regs[0] = 0; ++ break; ++#endif ++ default: ++ printf ("Error: Bad syscall: %x\n", n); ++ goto error; ++ } ++ } ++ else ++ { ++ env->regs[0] = do_syscall(env, ++ n, ++ env->regs[0], ++ env->regs[1], ++ env->regs[2], ++ env->regs[3], ++ env->regs[4], ++ env->regs[5]); ++ } + } else { + goto error; + } +@@ -534,6 +596,10 @@ + } + } + break; ++ case EXCP_KERNEL_TRAP: ++ if (do_kernel_trap(env)) ++ goto error; ++ break; + default: + error: + fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", +@@ -2402,6 +2468,10 @@ + ts->heap_base = info->brk; + /* This will be filled in on the first SYS_HEAPINFO call. */ + ts->heap_limit = 0; ++ /* Register the magic kernel code page. The cpu will generate a ++ special exception when it tries to execute code here. We can't ++ put real code here because it may be in use by the host kernel. */ ++ page_set_flags(0xffff0000, 0xffff0fff, 0); + #endif + + if (gdbstub_port) { +Index: qemu/linux-user/qemu.h +=================================================================== +--- qemu.orig/linux-user/qemu.h 2008-01-02 15:48:21.000000000 +0000 ++++ qemu/linux-user/qemu.h 2008-04-09 23:05:55.000000000 +0100 +@@ -107,6 +107,9 @@ + uint32_t heap_base; + uint32_t heap_limit; + #endif ++#ifdef USE_NPTL ++ uint32_t *child_tidptr; ++#endif + int used; /* non zero if used */ + struct image_info *info; + uint8_t stack[0]; +Index: qemu/linux-user/syscall.c +=================================================================== +--- qemu.orig/linux-user/syscall.c 2008-04-09 23:02:38.000000000 +0100 ++++ qemu/linux-user/syscall.c 2008-04-09 23:05:55.000000000 +0100 +@@ -71,9 +71,18 @@ + #include + + #include "qemu.h" ++#include "qemu_spinlock.h" + + //#define DEBUG + ++#ifdef USE_NPTL ++#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \ ++ CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID) ++#else ++/* XXX: Hardcode the above values. */ ++#define CLONE_NPTL_FLAGS2 0 ++#endif ++ + #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \ + || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS) + /* 16 bit uid wrappers emulation */ +@@ -2702,9 +2711,19 @@ + thread/process */ + #define NEW_STACK_SIZE 8192 + ++#ifdef USE_NPTL ++static spinlock_t nptl_lock = SPIN_LOCK_UNLOCKED; ++#endif ++ + static int clone_func(void *arg) + { + CPUState *env = arg; ++#ifdef HAVE_NPTL ++ /* Wait until the parent has finshed initializing the tls state. */ ++ while (!spin_trylock(&nptl_lock)) ++ usleep(1); ++ spin_unlock(&nptl_lock); ++#endif + cpu_loop(env); + /* never exits */ + return 0; +@@ -2712,13 +2731,22 @@ + + /* do_fork() Must return host values and target errnos (unlike most + do_*() functions). */ +-int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp) ++int do_fork(CPUState *env, unsigned int flags, unsigned long newsp, ++ uint32_t *parent_tidptr, void *newtls, ++ uint32_t *child_tidptr) + { + int ret; + TaskState *ts; + uint8_t *new_stack; + CPUState *new_env; + ++#ifdef USE_NPTL ++ unsigned int nptl_flags; ++ ++ if (flags & CLONE_PARENT_SETTID) ++ *parent_tidptr = gettid(); ++#endif ++ + if (flags & CLONE_VM) { + ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE); + memset(ts, 0, sizeof(TaskState)); +@@ -2784,16 +2812,67 @@ + #error unsupported target CPU + #endif + new_env->opaque = ts; ++#ifdef USE_NPTL ++ nptl_flags = flags; ++ flags &= ~CLONE_NPTL_FLAGS2; ++ ++ if (nptl_flags & CLONE_CHILD_CLEARTID) { ++ ts->child_tidptr = child_tidptr; ++ } ++ ++ if (nptl_flags & CLONE_SETTLS) ++ cpu_set_tls (new_env, newtls); ++ ++ /* Grab the global cpu lock so that the thread setup appears ++ atomic. */ ++ if (nptl_flags & CLONE_CHILD_SETTID) ++ spin_lock(&nptl_lock); ++ ++#else ++ if (flags & CLONE_NPTL_FLAGS2) ++ return -EINVAL; ++#endif ++ ++ if (CLONE_VFORK & flags) ++ flags ^= CLONE_VM; + #ifdef __ia64__ + ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); + #else + ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); + #endif ++#ifdef USE_NPTL ++ if (ret != -1) { ++ if (nptl_flags & CLONE_CHILD_SETTID) ++ *child_tidptr = ret; ++ } ++ ++ /* Allow the child to continue. */ ++ if (nptl_flags & CLONE_CHILD_SETTID) ++ spin_unlock(&nptl_lock); ++#endif + } else { + /* if no CLONE_VM, we consider it is a fork */ +- if ((flags & ~CSIGNAL) != 0) ++ if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0) + return -EINVAL; + ret = fork(); ++#ifdef USE_NPTL ++ /* There is a race condition here. The parent process could ++ theoretically read the TID in the child process before the child ++ tid is set. This would require using either ptrace ++ (not implemented) or having *_tidptr to point at a shared memory ++ mapping. We can't repeat the spinlock hack used above because ++ the child process gets its own copy of the lock. */ ++ if (ret == 0) { ++ /* Child Process. */ ++ if (flags & CLONE_CHILD_SETTID) ++ *child_tidptr = gettid(); ++ ts = (TaskState *)env->opaque; ++ if (flags & CLONE_CHILD_CLEARTID) ++ ts->child_tidptr = child_tidptr; ++ if (flags & CLONE_SETTLS) ++ cpu_set_tls (env, newtls); ++ } ++#endif + } + return ret; + } +@@ -3118,7 +3197,7 @@ + ret = do_brk(arg1); + break; + case TARGET_NR_fork: +- ret = get_errno(do_fork(cpu_env, SIGCHLD, 0)); ++ ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, NULL, NULL, NULL)); + break; + #ifdef TARGET_NR_waitpid + case TARGET_NR_waitpid: +@@ -4481,7 +4560,8 @@ + ret = get_errno(fsync(arg1)); + break; + case TARGET_NR_clone: +- ret = get_errno(do_fork(cpu_env, arg1, arg2)); ++ ret = get_errno(do_fork(cpu_env, arg1, arg2, (uint32_t *)arg3, ++ (void *)arg4, (uint32_t *)arg5)); + break; + #ifdef __NR_exit_group + /* new thread calls */ +@@ -4928,7 +5008,8 @@ + #endif + #ifdef TARGET_NR_vfork + case TARGET_NR_vfork: +- ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0)); ++ ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0, ++ NULL, NULL, NULL)); + break; + #endif + #ifdef TARGET_NR_ugetrlimit +Index: qemu/qemu_spinlock.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ qemu/qemu_spinlock.h 2008-04-09 23:05:55.000000000 +0100 +@@ -0,0 +1,181 @@ ++/* ++ * Atomic operation helper include ++ * ++ * Copyright (c) 2005 Fabrice Bellard ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef QEMU_SPINLOCK_H ++#define QEMU_SPINLOCK_H ++ ++#ifdef __powerpc__ ++static inline int testandset (int *p) ++{ ++ int ret; ++ __asm__ __volatile__ ( ++ "0: lwarx %0,0,%1\n" ++ " xor. %0,%3,%0\n" ++ " bne 1f\n" ++ " stwcx. %2,0,%1\n" ++ " bne- 0b\n" ++ "1: " ++ : "=&r" (ret) ++ : "r" (p), "r" (1), "r" (0) ++ : "cr0", "memory"); ++ return ret; ++} ++#endif ++ ++#ifdef __i386__ ++static inline int testandset (int *p) ++{ ++ long int readval = 0; ++ ++ __asm__ __volatile__ ("lock; cmpxchgl %2, %0" ++ : "+m" (*p), "+a" (readval) ++ : "r" (1) ++ : "cc"); ++ return readval; ++} ++#endif ++ ++#ifdef __x86_64__ ++static inline int testandset (int *p) ++{ ++ long int readval = 0; ++ ++ __asm__ __volatile__ ("lock; cmpxchgl %2, %0" ++ : "+m" (*p), "+a" (readval) ++ : "r" (1) ++ : "cc"); ++ return readval; ++} ++#endif ++ ++#ifdef __s390__ ++static inline int testandset (int *p) ++{ ++ int ret; ++ ++ __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n" ++ " jl 0b" ++ : "=&d" (ret) ++ : "r" (1), "a" (p), "0" (*p) ++ : "cc", "memory" ); ++ return ret; ++} ++#endif ++ ++#ifdef __alpha__ ++static inline int testandset (int *p) ++{ ++ int ret; ++ unsigned long one; ++ ++ __asm__ __volatile__ ("0: mov 1,%2\n" ++ " ldl_l %0,%1\n" ++ " stl_c %2,%1\n" ++ " beq %2,1f\n" ++ ".subsection 2\n" ++ "1: br 0b\n" ++ ".previous" ++ : "=r" (ret), "=m" (*p), "=r" (one) ++ : "m" (*p)); ++ return ret; ++} ++#endif ++ ++#ifdef __sparc__ ++static inline int testandset (int *p) ++{ ++ int ret; ++ ++ __asm__ __volatile__("ldstub [%1], %0" ++ : "=r" (ret) ++ : "r" (p) ++ : "memory"); ++ ++ return (ret ? 1 : 0); ++} ++#endif ++ ++#ifdef __arm__ ++static inline int testandset (int *spinlock) ++{ ++ register unsigned int ret; ++ __asm__ __volatile__("swp %0, %1, [%2]" ++ : "=r"(ret) ++ : "0"(1), "r"(spinlock)); ++ ++ return ret; ++} ++#endif ++ ++#ifdef __mc68000 ++static inline int testandset (int *p) ++{ ++ char ret; ++ __asm__ __volatile__("tas %1; sne %0" ++ : "=r" (ret) ++ : "m" (p) ++ : "cc","memory"); ++ return ret; ++} ++#endif ++ ++#ifdef __ia64 ++#include ++ ++static inline int testandset (int *p) ++{ ++ return __sync_lock_test_and_set (p, 1); ++} ++#endif ++ ++typedef int spinlock_t; ++ ++#define SPIN_LOCK_UNLOCKED 0 ++ ++#if defined(CONFIG_USER_ONLY) ++static inline void spin_lock(spinlock_t *lock) ++{ ++ while (testandset(lock)); ++} ++ ++static inline void spin_unlock(spinlock_t *lock) ++{ ++ *lock = 0; ++} ++ ++static inline int spin_trylock(spinlock_t *lock) ++{ ++ return !testandset(lock); ++} ++#else ++static inline void spin_lock(spinlock_t *lock) ++{ ++} ++ ++static inline void spin_unlock(spinlock_t *lock) ++{ ++} ++ ++static inline int spin_trylock(spinlock_t *lock) ++{ ++ return 1; ++} ++#endif ++ ++#endif +Index: qemu/target-arm/cpu.h +=================================================================== +--- qemu.orig/target-arm/cpu.h 2007-11-27 12:09:57.000000000 +0000 ++++ qemu/target-arm/cpu.h 2008-04-09 23:05:55.000000000 +0100 +@@ -38,6 +38,7 @@ + #define EXCP_FIQ 6 + #define EXCP_BKPT 7 + #define EXCP_EXCEPTION_EXIT 8 /* Return from v7M exception. */ ++#define EXCP_KERNEL_TRAP 9 /* Jumped to kernel code page. */ + + #define ARMV7M_EXCP_RESET 1 + #define ARMV7M_EXCP_NMI 2 +@@ -222,6 +223,15 @@ + void cpu_lock(void); + void cpu_unlock(void); + ++void cpu_lock(void); ++void cpu_unlock(void); ++#if defined(USE_NPTL) ++static inline void cpu_set_tls(CPUARMState *env, void *newtls) ++{ ++ env->cp15.c13_tls2 = (uint32_t)(long)newtls; ++} ++#endif ++ + #define CPSR_M (0x1f) + #define CPSR_T (1 << 5) + #define CPSR_F (1 << 6) +Index: qemu/target-arm/op.c +=================================================================== +--- qemu.orig/target-arm/op.c 2008-04-09 22:40:01.000000000 +0100 ++++ qemu/target-arm/op.c 2008-04-09 23:05:55.000000000 +0100 +@@ -994,6 +994,12 @@ + cpu_loop_exit(); + } + ++void OPPROTO op_kernel_trap(void) ++{ ++ env->exception_index = EXCP_KERNEL_TRAP; ++ cpu_loop_exit(); ++} ++ + /* VFP support. We follow the convention used for VFP instrunctions: + Single precition routines have a "s" suffix, double precision a + "d" suffix. */ +Index: qemu/target-arm/translate.c +=================================================================== +--- qemu.orig/target-arm/translate.c 2008-04-09 22:40:01.000000000 +0100 ++++ qemu/target-arm/translate.c 2008-04-09 23:05:55.000000000 +0100 +@@ -7496,7 +7496,14 @@ + gen_op_exception_exit(); + } + #endif +- ++#ifdef CONFIG_USER_ONLY ++ /* Intercept jump to the magic kernel page. */ ++ if (dc->pc > 0xffff0000) { ++ gen_op_kernel_trap(); ++ dc->is_jmp = DISAS_UPDATE; ++ break; ++ } ++#endif + if (env->nb_breakpoints > 0) { + for(j = 0; j < env->nb_breakpoints; j++) { + if (env->breakpoints[j] == dc->pc) { diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-amd64-32b-mapping-0.9.0.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-amd64-32b-mapping-0.9.0.patch new file mode 100644 index 0000000000..c7f36d8110 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-amd64-32b-mapping-0.9.0.patch @@ -0,0 +1,37 @@ +--- + linux-user/mmap.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +Index: qemu/linux-user/mmap.c +=================================================================== +--- qemu.orig/linux-user/mmap.c 2007-12-03 15:40:25.000000000 +0000 ++++ qemu/linux-user/mmap.c 2007-12-03 16:37:21.000000000 +0000 +@@ -29,6 +29,10 @@ + + //#define DEBUG_MMAP + ++#ifndef MAP_32BIT ++#define MAP_32BIT 0 ++#endif ++ + /* NOTE: all the constants are the HOST ones, but addresses are target. */ + int target_mprotect(abi_ulong start, abi_ulong len, int prot) + { +@@ -251,7 +255,7 @@ abi_long target_mmap(abi_ulong start, ab + especially important if qemu_host_page_size > + qemu_real_host_page_size */ + p = mmap(g2h(mmap_start), +- host_len, prot, flags | MAP_FIXED, fd, host_offset); ++ host_len, prot, flags | MAP_FIXED | MAP_32BIT, fd, host_offset); + if (p == MAP_FAILED) + return -1; + /* update start so that it points to the file position at 'offset' */ +@@ -406,7 +410,7 @@ abi_long target_mremap(abi_ulong old_add + unsigned long host_addr; + + /* XXX: use 5 args syscall */ +- host_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags); ++ host_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags | MAP_32BIT); + if (host_addr == -1) + return -1; + new_addr = h2g(host_addr); diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-n800-support.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-n800-support.patch new file mode 100644 index 0000000000..b1b6649efc --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/qemu-n800-support.patch @@ -0,0 +1,13970 @@ +diff --git a/Makefile b/Makefile +index c36a978..cb0cf7b 100644 +--- a/Makefile ++++ b/Makefile +@@ -51,7 +51,8 @@ OBJS+=block.o + + OBJS+=irq.o + OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o +-OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o ++OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o twl92230.o ++OBJS+=tmp105.o + OBJS+=scsi-disk.o cdrom.o + OBJS+=scsi-generic.o + OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o usb-serial.o +diff --git a/Makefile.target b/Makefile.target +index d1deda1..48f31bc 100644 +--- a/Makefile.target ++++ b/Makefile.target +@@ -593,7 +593,9 @@ OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o + OBJS+= pflash_cfi01.o gumstix.o + OBJS+= spitz.o ide.o serial.o nand.o ecc.o + OBJS+= omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o ++OBJS+= omap2.o omap_dss.o + OBJS+= palm.o tsc210x.o ++OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o + OBJS+= mst_fpga.o mainstone.o + CPPFLAGS += -DHAS_AUDIO + endif +diff --git a/console.h b/console.h +index b8a5c6d..b45974e 100644 +--- a/console.h ++++ b/console.h +@@ -32,6 +32,12 @@ void kbd_put_keycode(int keycode); + void kbd_mouse_event(int dx, int dy, int dz, int buttons_state); + int kbd_mouse_is_absolute(void); + ++struct mouse_transform_info_s { ++ int x; ++ int y; ++ int a[7]; ++}; ++ + void do_info_mice(void); + void do_mouse_set(int index); + +diff --git a/cpu-all.h b/cpu-all.h +index 7a7e655..c7c9611 100644 +--- a/cpu-all.h ++++ b/cpu-all.h +@@ -810,7 +810,7 @@ extern uint8_t *phys_ram_dirty; + /* physical memory access */ + #define TLB_INVALID_MASK (1 << 3) + #define IO_MEM_SHIFT 4 +-#define IO_MEM_NB_ENTRIES (1 << (TARGET_PAGE_BITS - IO_MEM_SHIFT)) ++#define IO_MEM_NB_ENTRIES (16 << (TARGET_PAGE_BITS - IO_MEM_SHIFT)) + + #define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */ + #define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */ +diff --git a/exec.c b/exec.c +index e9a5918..c69f742 100644 +--- a/exec.c ++++ b/exec.c +@@ -1658,7 +1658,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, + { + if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { + /* IO memory case */ +- address = vaddr | pd; ++ address = vaddr | (pd & ~TARGET_PAGE_MASK); + addend = paddr; + } else { + /* standard memory */ +@@ -1692,7 +1692,9 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, + } else { + te->addr_read = -1; + } +- if (prot & PAGE_EXEC) { ++ if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { ++ te->addr_code = pd; ++ } else if (prot & PAGE_EXEC) { + te->addr_code = address; + } else { + te->addr_code = -1; +@@ -2487,7 +2489,9 @@ int cpu_register_io_memory(int io_index, + if (io_index <= 0) { + if (io_mem_nb >= IO_MEM_NB_ENTRIES) + return -1; +- io_index = io_mem_nb++; ++ do io_index = io_mem_nb++; ++ while (((io_index << IO_MEM_SHIFT) & ~TARGET_PAGE_MASK) ++ <= IO_MEM_NOTDIRTY); + } else { + if (io_index >= IO_MEM_NB_ENTRIES) + return -1; +diff --git a/hw/arm-misc.h b/hw/arm-misc.h +index 7914ff1..a1e0061 100644 +--- a/hw/arm-misc.h ++++ b/hw/arm-misc.h +@@ -21,10 +21,7 @@ qemu_irq *armv7m_init(int flash_size, int sram_size, + const char *kernel_filename, const char *cpu_model); + + /* arm_boot.c */ +- +-void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename, +- const char *kernel_cmdline, const char *initrd_filename, +- int board_id, target_phys_addr_t loader_start); ++void arm_load_kernel(CPUState *env, struct arm_boot_info *info); + + /* armv7m_nvic.c */ + int system_clock_scale; +diff --git a/hw/arm_boot.c b/hw/arm_boot.c +index 8335e69..20b1512 100644 +--- a/hw/arm_boot.c ++++ b/hw/arm_boot.c +@@ -47,21 +47,18 @@ static void main_cpu_reset(void *opaque) + CPUState *env = opaque; + + cpu_reset(env); +- if (env->kernel_filename) +- arm_load_kernel(env, env->ram_size, env->kernel_filename, +- env->kernel_cmdline, env->initrd_filename, +- env->board_id, env->loader_start); ++ if (env->boot_info) ++ arm_load_kernel(env, env->boot_info); + + /* TODO: Reset secondary CPUs. */ + } + +-static void set_kernel_args(uint32_t ram_size, int initrd_size, +- const char *kernel_cmdline, +- target_phys_addr_t loader_start) ++static void set_kernel_args(struct arm_boot_info *info, ++ int initrd_size, void *base) + { + uint32_t *p; + +- p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR); ++ p = (uint32_t *)(base + KERNEL_ARGS_ADDR); + /* ATAG_CORE */ + stl_raw(p++, 5); + stl_raw(p++, 0x54410001); +@@ -69,46 +66,55 @@ static void set_kernel_args(uint32_t ram_size, int initrd_size, + stl_raw(p++, 0x1000); + stl_raw(p++, 0); + /* ATAG_MEM */ ++ /* TODO: multiple chips */ + stl_raw(p++, 4); + stl_raw(p++, 0x54410002); +- stl_raw(p++, ram_size); +- stl_raw(p++, loader_start); ++ stl_raw(p++, info->ram_size); ++ stl_raw(p++, info->loader_start); + if (initrd_size) { + /* ATAG_INITRD2 */ + stl_raw(p++, 4); + stl_raw(p++, 0x54420005); +- stl_raw(p++, loader_start + INITRD_LOAD_ADDR); ++ stl_raw(p++, info->loader_start + INITRD_LOAD_ADDR); + stl_raw(p++, initrd_size); + } +- if (kernel_cmdline && *kernel_cmdline) { ++ if (info->kernel_cmdline && *info->kernel_cmdline) { + /* ATAG_CMDLINE */ + int cmdline_size; + +- cmdline_size = strlen(kernel_cmdline); +- memcpy (p + 2, kernel_cmdline, cmdline_size + 1); ++ cmdline_size = strlen(info->kernel_cmdline); ++ memcpy(p + 2, info->kernel_cmdline, cmdline_size + 1); + cmdline_size = (cmdline_size >> 2) + 1; + stl_raw(p++, cmdline_size + 2); + stl_raw(p++, 0x54410009); + p += cmdline_size; + } ++ if (info->atag_board) { ++ /* ATAG_BOARD */ ++ int atag_board_len; ++ ++ atag_board_len = (info->atag_board(info, p + 2) + 3) >> 2; ++ stl_raw(p++, 2 + atag_board_len); ++ stl_raw(p++, 0x414f4d50); ++ p += atag_board_len; ++ } + /* ATAG_END */ + stl_raw(p++, 0); + stl_raw(p++, 0); + } + +-static void set_kernel_args_old(uint32_t ram_size, int initrd_size, +- const char *kernel_cmdline, +- target_phys_addr_t loader_start) ++static void set_kernel_args_old(struct arm_boot_info *info, ++ int initrd_size, void *base) + { + uint32_t *p; + unsigned char *s; + + /* see linux/include/asm-arm/setup.h */ +- p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR); ++ p = (uint32_t *)(base + KERNEL_ARGS_ADDR); + /* page_size */ + stl_raw(p++, 4096); + /* nr_pages */ +- stl_raw(p++, ram_size / 4096); ++ stl_raw(p++, info->ram_size / 4096); + /* ramdisk_size */ + stl_raw(p++, 0); + #define FLAG_READONLY 1 +@@ -142,7 +148,7 @@ static void set_kernel_args_old(uint32_t ram_size, int initrd_size, + stl_raw(p++, 0); + /* initrd_start */ + if (initrd_size) +- stl_raw(p++, loader_start + INITRD_LOAD_ADDR); ++ stl_raw(p++, info->loader_start + INITRD_LOAD_ADDR); + else + stl_raw(p++, 0); + /* initrd_size */ +@@ -159,17 +165,15 @@ static void set_kernel_args_old(uint32_t ram_size, int initrd_size, + stl_raw(p++, 0); + /* zero unused fields */ + memset(p, 0, 256 + 1024 - +- (p - ((uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR)))); +- s = phys_ram_base + KERNEL_ARGS_ADDR + 256 + 1024; +- if (kernel_cmdline) +- strcpy (s, kernel_cmdline); ++ (p - ((uint32_t *)(base + KERNEL_ARGS_ADDR)))); ++ s = base + KERNEL_ARGS_ADDR + 256 + 1024; ++ if (info->kernel_cmdline) ++ strcpy (s, info->kernel_cmdline); + else + stb_raw(s, 0); + } + +-void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename, +- const char *kernel_cmdline, const char *initrd_filename, +- int board_id, target_phys_addr_t loader_start) ++void arm_load_kernel(CPUState *env, struct arm_boot_info *info) + { + int kernel_size; + int initrd_size; +@@ -177,36 +181,41 @@ void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename, + int is_linux = 0; + uint64_t elf_entry; + target_ulong entry; ++ uint32_t pd; ++ void *loader_phys; + + /* Load the kernel. */ +- if (!kernel_filename) { ++ if (!info->kernel_filename) { + fprintf(stderr, "Kernel image must be specified\n"); + exit(1); + } + +- if (!env->kernel_filename) { +- env->ram_size = ram_size; +- env->kernel_filename = kernel_filename; +- env->kernel_cmdline = kernel_cmdline; +- env->initrd_filename = initrd_filename; +- env->board_id = board_id; +- env->loader_start = loader_start; ++ if (!env->boot_info) { ++ if (info->nb_cpus == 0) ++ info->nb_cpus = 1; ++ env->boot_info = info; + qemu_register_reset(main_cpu_reset, env); + } ++ ++ pd = cpu_get_physical_page_desc(info->loader_start); ++ loader_phys = phys_ram_base + (pd & TARGET_PAGE_MASK) + ++ (info->loader_start & ~TARGET_PAGE_MASK); ++ + /* Assume that raw images are linux kernels, and ELF images are not. */ +- kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL); ++ kernel_size = load_elf(info->kernel_filename, 0, &elf_entry, NULL, NULL); + entry = elf_entry; + if (kernel_size < 0) { +- kernel_size = load_uboot(kernel_filename, &entry, &is_linux); ++ kernel_size = load_uboot(info->kernel_filename, &entry, &is_linux); + } + if (kernel_size < 0) { +- kernel_size = load_image(kernel_filename, +- phys_ram_base + KERNEL_LOAD_ADDR); +- entry = loader_start + KERNEL_LOAD_ADDR; ++ kernel_size = load_image(info->kernel_filename, ++ loader_phys + KERNEL_LOAD_ADDR); ++ entry = info->loader_start + KERNEL_LOAD_ADDR; + is_linux = 1; + } + if (kernel_size < 0) { +- fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename); ++ fprintf(stderr, "qemu: could not load kernel '%s'\n", ++ info->kernel_filename); + exit(1); + } + if (!is_linux) { +@@ -214,30 +223,29 @@ void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename, + env->regs[15] = entry & 0xfffffffe; + env->thumb = entry & 1; + } else { +- if (initrd_filename) { +- initrd_size = load_image(initrd_filename, +- phys_ram_base + INITRD_LOAD_ADDR); ++ if (info->initrd_filename) { ++ initrd_size = load_image(info->initrd_filename, ++ loader_phys + INITRD_LOAD_ADDR); + if (initrd_size < 0) { + fprintf(stderr, "qemu: could not load initrd '%s'\n", +- initrd_filename); ++ info->initrd_filename); + exit(1); + } + } else { + initrd_size = 0; + } +- bootloader[1] |= board_id & 0xff; +- bootloader[2] |= (board_id >> 8) & 0xff; +- bootloader[5] = loader_start + KERNEL_ARGS_ADDR; ++ bootloader[1] |= info->board_id & 0xff; ++ bootloader[2] |= (info->board_id >> 8) & 0xff; ++ bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR; + bootloader[6] = entry; + for (n = 0; n < sizeof(bootloader) / 4; n++) +- stl_raw(phys_ram_base + (n * 4), bootloader[n]); +- for (n = 0; n < sizeof(smpboot) / 4; n++) +- stl_raw(phys_ram_base + ram_size + (n * 4), smpboot[n]); ++ stl_raw(loader_phys + (n * 4), bootloader[n]); ++ if (info->nb_cpus > 1) ++ for (n = 0; n < sizeof(smpboot) / 4; n++) ++ stl_raw(loader_phys + info->ram_size + (n * 4), smpboot[n]); + if (old_param) +- set_kernel_args_old(ram_size, initrd_size, +- kernel_cmdline, loader_start); ++ set_kernel_args_old(info, initrd_size, loader_phys); + else +- set_kernel_args(ram_size, initrd_size, +- kernel_cmdline, loader_start); ++ set_kernel_args(info, initrd_size, loader_phys); + } + } +diff --git a/hw/blizzard.c b/hw/blizzard.c +new file mode 100644 +index 0000000..9046b5d +--- /dev/null ++++ b/hw/blizzard.c +@@ -0,0 +1,1001 @@ ++/* ++ * Epson S1D13744/S1D13745 (Blizzard/Hailstorm/Tornado) LCD/TV controller. ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Written by Andrzej Zaborowski ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ */ ++ ++#include "qemu-common.h" ++#include "sysemu.h" ++#include "console.h" ++#include "devices.h" ++#include "vga_int.h" ++#include "pixel_ops.h" ++ ++typedef void (*blizzard_fn_t)(uint8_t *, const uint8_t *, unsigned int); ++ ++struct blizzard_s { ++ uint8_t reg; ++ uint32_t addr; ++ int swallow; ++ ++ int pll; ++ int pll_range; ++ int pll_ctrl; ++ uint8_t pll_mode; ++ uint8_t clksel; ++ int memenable; ++ int memrefresh; ++ uint8_t timing[3]; ++ int priority; ++ ++ uint8_t lcd_config; ++ int x; ++ int y; ++ int skipx; ++ int skipy; ++ uint8_t hndp; ++ uint8_t vndp; ++ uint8_t hsync; ++ uint8_t vsync; ++ uint8_t pclk; ++ uint8_t u; ++ uint8_t v; ++ uint8_t yrc[2]; ++ int ix[2]; ++ int iy[2]; ++ int ox[2]; ++ int oy[2]; ++ ++ int enable; ++ int blank; ++ int bpp; ++ int invalidate; ++ int mx[2]; ++ int my[2]; ++ uint8_t mode; ++ uint8_t effect; ++ uint8_t iformat; ++ uint8_t source; ++ DisplayState *state; ++ blizzard_fn_t *line_fn_tab[2]; ++ void *fb; ++ ++ uint8_t hssi_config[3]; ++ uint8_t tv_config; ++ uint8_t tv_timing[4]; ++ uint8_t vbi; ++ uint8_t tv_x; ++ uint8_t tv_y; ++ uint8_t tv_test; ++ uint8_t tv_filter_config; ++ uint8_t tv_filter_idx; ++ uint8_t tv_filter_coeff[0x20]; ++ uint8_t border_r; ++ uint8_t border_g; ++ uint8_t border_b; ++ uint8_t gamma_config; ++ uint8_t gamma_idx; ++ uint8_t gamma_lut[0x100]; ++ uint8_t matrix_ena; ++ uint8_t matrix_coeff[0x12]; ++ uint8_t matrix_r; ++ uint8_t matrix_g; ++ uint8_t matrix_b; ++ uint8_t pm; ++ uint8_t status; ++ uint8_t rgbgpio_dir; ++ uint8_t rgbgpio; ++ uint8_t gpio_dir; ++ uint8_t gpio; ++ uint8_t gpio_edge[2]; ++ uint8_t gpio_irq; ++ uint8_t gpio_pdown; ++ ++ struct { ++ int x; ++ int y; ++ int dx; ++ int dy; ++ int len; ++ int buflen; ++ void *buf; ++ void *data; ++ uint16_t *ptr; ++ int angle; ++ int pitch; ++ blizzard_fn_t line_fn; ++ } data; ++}; ++ ++/* Bytes(!) per pixel */ ++static const int blizzard_iformat_bpp[0x10] = { ++ 0, ++ 2, /* RGB 5:6:5*/ ++ 3, /* RGB 6:6:6 mode 1 */ ++ 3, /* RGB 8:8:8 mode 1 */ ++ 0, 0, ++ 4, /* RGB 6:6:6 mode 2 */ ++ 4, /* RGB 8:8:8 mode 2 */ ++ 0, /* YUV 4:2:2 */ ++ 0, /* YUV 4:2:0 */ ++ 0, 0, 0, 0, 0, 0, ++}; ++ ++static inline void blizzard_rgb2yuv(int r, int g, int b, ++ int *y, int *u, int *v) ++{ ++ *y = 0x10 + ((0x838 * r + 0x1022 * g + 0x322 * b) >> 13); ++ *u = 0x80 + ((0xe0e * b - 0x04c1 * r - 0x94e * g) >> 13); ++ *v = 0x80 + ((0xe0e * r - 0x0bc7 * g - 0x247 * b) >> 13); ++} ++ ++static void blizzard_window(struct blizzard_s *s) ++{ ++ uint8_t *src, *dst; ++ int bypp[2]; ++ int bypl[3]; ++ int y; ++ blizzard_fn_t fn = s->data.line_fn; ++ ++ if (!fn) ++ return; ++ if (s->mx[0] > s->data.x) ++ s->mx[0] = s->data.x; ++ if (s->my[0] > s->data.y) ++ s->my[0] = s->data.y; ++ if (s->mx[1] < s->data.x + s->data.dx) ++ s->mx[1] = s->data.x + s->data.dx; ++ if (s->my[1] < s->data.y + s->data.dy) ++ s->my[1] = s->data.y + s->data.dy; ++ ++ bypp[0] = s->bpp; ++ bypp[1] = (s->state->depth + 7) >> 3; ++ bypl[0] = bypp[0] * s->data.pitch; ++ bypl[1] = bypp[1] * s->x; ++ bypl[2] = bypp[0] * s->data.dx; ++ ++ src = s->data.data; ++ dst = s->fb + bypl[1] * s->data.y + bypp[1] * s->data.x; ++ for (y = s->data.dy; y > 0; y --, src += bypl[0], dst += bypl[1]) ++ fn(dst, src, bypl[2]); ++} ++ ++static int blizzard_transfer_setup(struct blizzard_s *s) ++{ ++ if (s->source > 3 || !s->bpp || ++ s->ix[1] < s->ix[0] || s->iy[1] < s->iy[0]) ++ return 0; ++ ++ s->data.angle = s->effect & 3; ++ s->data.line_fn = s->line_fn_tab[!!s->data.angle][s->iformat]; ++ s->data.x = s->ix[0]; ++ s->data.y = s->iy[0]; ++ s->data.dx = s->ix[1] - s->ix[0] + 1; ++ s->data.dy = s->iy[1] - s->iy[0] + 1; ++ s->data.len = s->bpp * s->data.dx * s->data.dy; ++ s->data.pitch = s->data.dx; ++ if (s->data.len > s->data.buflen) { ++ s->data.buf = realloc(s->data.buf, s->data.len); ++ s->data.buflen = s->data.len; ++ } ++ s->data.ptr = s->data.buf; ++ s->data.data = s->data.buf; ++ s->data.len /= 2; ++ return 1; ++} ++ ++static void blizzard_reset(struct blizzard_s *s) ++{ ++ s->reg = 0; ++ s->swallow = 0; ++ ++ s->pll = 9; ++ s->pll_range = 1; ++ s->pll_ctrl = 0x14; ++ s->pll_mode = 0x32; ++ s->clksel = 0x00; ++ s->memenable = 0; ++ s->memrefresh = 0x25c; ++ s->timing[0] = 0x3f; ++ s->timing[1] = 0x13; ++ s->timing[2] = 0x21; ++ s->priority = 0; ++ ++ s->lcd_config = 0x74; ++ s->x = 8; ++ s->y = 1; ++ s->skipx = 0; ++ s->skipy = 0; ++ s->hndp = 3; ++ s->vndp = 2; ++ s->hsync = 1; ++ s->vsync = 1; ++ s->pclk = 0x80; ++ ++ s->ix[0] = 0; ++ s->ix[1] = 0; ++ s->iy[0] = 0; ++ s->iy[1] = 0; ++ s->ox[0] = 0; ++ s->ox[1] = 0; ++ s->oy[0] = 0; ++ s->oy[1] = 0; ++ ++ s->yrc[0] = 0x00; ++ s->yrc[1] = 0x30; ++ s->u = 0; ++ s->v = 0; ++ ++ s->iformat = 3; ++ s->source = 0; ++ s->bpp = blizzard_iformat_bpp[s->iformat]; ++ ++ s->hssi_config[0] = 0x00; ++ s->hssi_config[1] = 0x00; ++ s->hssi_config[2] = 0x01; ++ s->tv_config = 0x00; ++ s->tv_timing[0] = 0x00; ++ s->tv_timing[1] = 0x00; ++ s->tv_timing[2] = 0x00; ++ s->tv_timing[3] = 0x00; ++ s->vbi = 0x10; ++ s->tv_x = 0x14; ++ s->tv_y = 0x03; ++ s->tv_test = 0x00; ++ s->tv_filter_config = 0x80; ++ s->tv_filter_idx = 0x00; ++ s->border_r = 0x10; ++ s->border_g = 0x80; ++ s->border_b = 0x80; ++ s->gamma_config = 0x00; ++ s->gamma_idx = 0x00; ++ s->matrix_ena = 0x00; ++ memset(&s->matrix_coeff, 0, sizeof(s->matrix_coeff)); ++ s->matrix_r = 0x00; ++ s->matrix_g = 0x00; ++ s->matrix_b = 0x00; ++ s->pm = 0x02; ++ s->status = 0x00; ++ s->rgbgpio_dir = 0x00; ++ s->gpio_dir = 0x00; ++ s->gpio_edge[0] = 0x00; ++ s->gpio_edge[1] = 0x00; ++ s->gpio_irq = 0x00; ++ s->gpio_pdown = 0xff; ++} ++ ++static inline void blizzard_invalidate_display(void *opaque) { ++ struct blizzard_s *s = (struct blizzard_s *) opaque; ++ ++ s->invalidate = 1; ++} ++ ++static uint16_t blizzard_reg_read(void *opaque, uint8_t reg) ++{ ++ struct blizzard_s *s = (struct blizzard_s *) opaque; ++ ++ switch (reg) { ++ case 0x00: /* Revision Code */ ++ return 0xa5; ++ ++ case 0x02: /* Configuration Readback */ ++ return 0x83; /* Macrovision OK, CNF[2:0] = 3 */ ++ ++ case 0x04: /* PLL M-Divider */ ++ return (s->pll - 1) | (1 << 7); ++ case 0x06: /* PLL Lock Range Control */ ++ return s->pll_range; ++ case 0x08: /* PLL Lock Synthesis Control 0 */ ++ return s->pll_ctrl & 0xff; ++ case 0x0a: /* PLL Lock Synthesis Control 1 */ ++ return s->pll_ctrl >> 8; ++ case 0x0c: /* PLL Mode Control 0 */ ++ return s->pll_mode; ++ ++ case 0x0e: /* Clock-Source Select */ ++ return s->clksel; ++ ++ case 0x10: /* Memory Controller Activate */ ++ case 0x14: /* Memory Controller Bank 0 Status Flag */ ++ return s->memenable; ++ ++ case 0x18: /* Auto-Refresh Interval Setting 0 */ ++ return s->memrefresh & 0xff; ++ case 0x1a: /* Auto-Refresh Interval Setting 1 */ ++ return s->memrefresh >> 8; ++ ++ case 0x1c: /* Power-On Sequence Timing Control */ ++ return s->timing[0]; ++ case 0x1e: /* Timing Control 0 */ ++ return s->timing[1]; ++ case 0x20: /* Timing Control 1 */ ++ return s->timing[2]; ++ ++ case 0x24: /* Arbitration Priority Control */ ++ return s->priority; ++ ++ case 0x28: /* LCD Panel Configuration */ ++ return s->lcd_config; ++ ++ case 0x2a: /* LCD Horizontal Display Width */ ++ return s->x >> 3; ++ case 0x2c: /* LCD Horizontal Non-display Period */ ++ return s->hndp; ++ case 0x2e: /* LCD Vertical Display Height 0 */ ++ return s->y & 0xff; ++ case 0x30: /* LCD Vertical Display Height 1 */ ++ return s->y >> 8; ++ case 0x32: /* LCD Vertical Non-display Period */ ++ return s->vndp; ++ case 0x34: /* LCD HS Pulse-width */ ++ return s->hsync; ++ case 0x36: /* LCd HS Pulse Start Position */ ++ return s->skipx >> 3; ++ case 0x38: /* LCD VS Pulse-width */ ++ return s->vsync; ++ case 0x3a: /* LCD VS Pulse Start Position */ ++ return s->skipy; ++ ++ case 0x3c: /* PCLK Polarity */ ++ return s->pclk; ++ ++ case 0x3e: /* High-speed Serial Interface Tx Configuration Port 0 */ ++ return s->hssi_config[0]; ++ case 0x40: /* High-speed Serial Interface Tx Configuration Port 1 */ ++ return s->hssi_config[1]; ++ case 0x42: /* High-speed Serial Interface Tx Mode */ ++ return s->hssi_config[2]; ++ case 0x44: /* TV Display Configuration */ ++ return s->tv_config; ++ case 0x46 ... 0x4c: /* TV Vertical Blanking Interval Data bits */ ++ return s->tv_timing[(reg - 0x46) >> 1]; ++ case 0x4e: /* VBI: Closed Caption / XDS Control / Status */ ++ return s->vbi; ++ case 0x50: /* TV Horizontal Start Position */ ++ return s->tv_x; ++ case 0x52: /* TV Vertical Start Position */ ++ return s->tv_y; ++ case 0x54: /* TV Test Pattern Setting */ ++ return s->tv_test; ++ case 0x56: /* TV Filter Setting */ ++ return s->tv_filter_config; ++ case 0x58: /* TV Filter Coefficient Index */ ++ return s->tv_filter_idx; ++ case 0x5a: /* TV Filter Coefficient Data */ ++ if (s->tv_filter_idx < 0x20) ++ return s->tv_filter_coeff[s->tv_filter_idx ++]; ++ return 0; ++ ++ case 0x60: /* Input YUV/RGB Translate Mode 0 */ ++ return s->yrc[0]; ++ case 0x62: /* Input YUV/RGB Translate Mode 1 */ ++ return s->yrc[1]; ++ case 0x64: /* U Data Fix */ ++ return s->u; ++ case 0x66: /* V Data Fix */ ++ return s->v; ++ ++ case 0x68: /* Display Mode */ ++ return s->mode; ++ ++ case 0x6a: /* Special Effects */ ++ return s->effect; ++ ++ case 0x6c: /* Input Window X Start Position 0 */ ++ return s->ix[0] & 0xff; ++ case 0x6e: /* Input Window X Start Position 1 */ ++ return s->ix[0] >> 3; ++ case 0x70: /* Input Window Y Start Position 0 */ ++ return s->ix[0] & 0xff; ++ case 0x72: /* Input Window Y Start Position 1 */ ++ return s->ix[0] >> 3; ++ case 0x74: /* Input Window X End Position 0 */ ++ return s->ix[1] & 0xff; ++ case 0x76: /* Input Window X End Position 1 */ ++ return s->ix[1] >> 3; ++ case 0x78: /* Input Window Y End Position 0 */ ++ return s->ix[1] & 0xff; ++ case 0x7a: /* Input Window Y End Position 1 */ ++ return s->ix[1] >> 3; ++ case 0x7c: /* Output Window X Start Position 0 */ ++ return s->ox[0] & 0xff; ++ case 0x7e: /* Output Window X Start Position 1 */ ++ return s->ox[0] >> 3; ++ case 0x80: /* Output Window Y Start Position 0 */ ++ return s->oy[0] & 0xff; ++ case 0x82: /* Output Window Y Start Position 1 */ ++ return s->oy[0] >> 3; ++ case 0x84: /* Output Window X End Position 0 */ ++ return s->ox[1] & 0xff; ++ case 0x86: /* Output Window X End Position 1 */ ++ return s->ox[1] >> 3; ++ case 0x88: /* Output Window Y End Position 0 */ ++ return s->oy[1] & 0xff; ++ case 0x8a: /* Output Window Y End Position 1 */ ++ return s->oy[1] >> 3; ++ ++ case 0x8c: /* Input Data Format */ ++ return s->iformat; ++ case 0x8e: /* Data Source Select */ ++ return s->source; ++ case 0x90: /* Display Memory Data Port */ ++ return 0; ++ ++ case 0xa8: /* Border Color 0 */ ++ return s->border_r; ++ case 0xaa: /* Border Color 1 */ ++ return s->border_g; ++ case 0xac: /* Border Color 2 */ ++ return s->border_b; ++ ++ case 0xb4: /* Gamma Correction Enable */ ++ return s->gamma_config; ++ case 0xb6: /* Gamma Correction Table Index */ ++ return s->gamma_idx; ++ case 0xb8: /* Gamma Correction Table Data */ ++ return s->gamma_lut[s->gamma_idx ++]; ++ ++ case 0xba: /* 3x3 Matrix Enable */ ++ return s->matrix_ena; ++ case 0xbc ... 0xde: /* Coefficient Registers */ ++ return s->matrix_coeff[(reg - 0xbc) >> 1]; ++ case 0xe0: /* 3x3 Matrix Red Offset */ ++ return s->matrix_r; ++ case 0xe2: /* 3x3 Matrix Green Offset */ ++ return s->matrix_g; ++ case 0xe4: /* 3x3 Matrix Blue Offset */ ++ return s->matrix_b; ++ ++ case 0xe6: /* Power-save */ ++ return s->pm; ++ case 0xe8: /* Non-display Period Control / Status */ ++ return s->status | (1 << 5); ++ case 0xea: /* RGB Interface Control */ ++ return s->rgbgpio_dir; ++ case 0xec: /* RGB Interface Status */ ++ return s->rgbgpio; ++ case 0xee: /* General-purpose IO Pins Configuration */ ++ return s->gpio_dir; ++ case 0xf0: /* General-purpose IO Pins Status / Control */ ++ return s->gpio; ++ case 0xf2: /* GPIO Positive Edge Interrupt Trigger */ ++ return s->gpio_edge[0]; ++ case 0xf4: /* GPIO Negative Edge Interrupt Trigger */ ++ return s->gpio_edge[1]; ++ case 0xf6: /* GPIO Interrupt Status */ ++ return s->gpio_irq; ++ case 0xf8: /* GPIO Pull-down Control */ ++ return s->gpio_pdown; ++ ++ default: ++ fprintf(stderr, "%s: unknown register %02x\n", __FUNCTION__, reg); ++ return 0; ++ } ++} ++ ++static void blizzard_reg_write(void *opaque, uint8_t reg, uint16_t value) ++{ ++ struct blizzard_s *s = (struct blizzard_s *) opaque; ++ ++ switch (reg) { ++ case 0x04: /* PLL M-Divider */ ++ s->pll = (value & 0x3f) + 1; ++ break; ++ case 0x06: /* PLL Lock Range Control */ ++ s->pll_range = value & 3; ++ break; ++ case 0x08: /* PLL Lock Synthesis Control 0 */ ++ s->pll_ctrl &= 0xf00; ++ s->pll_ctrl |= (value << 0) & 0x0ff; ++ break; ++ case 0x0a: /* PLL Lock Synthesis Control 1 */ ++ s->pll_ctrl &= 0x0ff; ++ s->pll_ctrl |= (value << 8) & 0xf00; ++ break; ++ case 0x0c: /* PLL Mode Control 0 */ ++ s->pll_mode = value & 0x77; ++ if ((value & 3) == 0 || (value & 3) == 3) ++ fprintf(stderr, "%s: wrong PLL Control bits (%i)\n", ++ __FUNCTION__, value & 3); ++ break; ++ ++ case 0x0e: /* Clock-Source Select */ ++ s->clksel = value & 0xff; ++ break; ++ ++ case 0x10: /* Memory Controller Activate */ ++ s->memenable = value & 1; ++ break; ++ case 0x14: /* Memory Controller Bank 0 Status Flag */ ++ break; ++ ++ case 0x18: /* Auto-Refresh Interval Setting 0 */ ++ s->memrefresh &= 0xf00; ++ s->memrefresh |= (value << 0) & 0x0ff; ++ break; ++ case 0x1a: /* Auto-Refresh Interval Setting 1 */ ++ s->memrefresh &= 0x0ff; ++ s->memrefresh |= (value << 8) & 0xf00; ++ break; ++ ++ case 0x1c: /* Power-On Sequence Timing Control */ ++ s->timing[0] = value & 0x7f; ++ break; ++ case 0x1e: /* Timing Control 0 */ ++ s->timing[1] = value & 0x17; ++ break; ++ case 0x20: /* Timing Control 1 */ ++ s->timing[2] = value & 0x35; ++ break; ++ ++ case 0x24: /* Arbitration Priority Control */ ++ s->priority = value & 1; ++ break; ++ ++ case 0x28: /* LCD Panel Configuration */ ++ s->lcd_config = value & 0xff; ++ if (value & (1 << 7)) ++ fprintf(stderr, "%s: data swap not supported!\n", __FUNCTION__); ++ break; ++ ++ case 0x2a: /* LCD Horizontal Display Width */ ++ s->x = value << 3; ++ break; ++ case 0x2c: /* LCD Horizontal Non-display Period */ ++ s->hndp = value & 0xff; ++ break; ++ case 0x2e: /* LCD Vertical Display Height 0 */ ++ s->y &= 0x300; ++ s->y |= (value << 0) & 0x0ff; ++ break; ++ case 0x30: /* LCD Vertical Display Height 1 */ ++ s->y &= 0x0ff; ++ s->y |= (value << 8) & 0x300; ++ break; ++ case 0x32: /* LCD Vertical Non-display Period */ ++ s->vndp = value & 0xff; ++ break; ++ case 0x34: /* LCD HS Pulse-width */ ++ s->hsync = value & 0xff; ++ break; ++ case 0x36: /* LCD HS Pulse Start Position */ ++ s->skipx = value & 0xff; ++ break; ++ case 0x38: /* LCD VS Pulse-width */ ++ s->vsync = value & 0xbf; ++ break; ++ case 0x3a: /* LCD VS Pulse Start Position */ ++ s->skipy = value & 0xff; ++ break; ++ ++ case 0x3c: /* PCLK Polarity */ ++ s->pclk = value & 0x82; ++ /* Affects calculation of s->hndp, s->hsync and s->skipx. */ ++ break; ++ ++ case 0x3e: /* High-speed Serial Interface Tx Configuration Port 0 */ ++ s->hssi_config[0] = value; ++ break; ++ case 0x40: /* High-speed Serial Interface Tx Configuration Port 1 */ ++ s->hssi_config[1] = value; ++ if (((value >> 4) & 3) == 3) ++ fprintf(stderr, "%s: Illegal active-data-links value\n", ++ __FUNCTION__); ++ break; ++ case 0x42: /* High-speed Serial Interface Tx Mode */ ++ s->hssi_config[2] = value & 0xbd; ++ break; ++ ++ case 0x44: /* TV Display Configuration */ ++ s->tv_config = value & 0xfe; ++ break; ++ case 0x46 ... 0x4c: /* TV Vertical Blanking Interval Data bits 0 */ ++ s->tv_timing[(reg - 0x46) >> 1] = value; ++ break; ++ case 0x4e: /* VBI: Closed Caption / XDS Control / Status */ ++ s->vbi = value; ++ break; ++ case 0x50: /* TV Horizontal Start Position */ ++ s->tv_x = value; ++ break; ++ case 0x52: /* TV Vertical Start Position */ ++ s->tv_y = value & 0x7f; ++ break; ++ case 0x54: /* TV Test Pattern Setting */ ++ s->tv_test = value; ++ break; ++ case 0x56: /* TV Filter Setting */ ++ s->tv_filter_config = value & 0xbf; ++ break; ++ case 0x58: /* TV Filter Coefficient Index */ ++ s->tv_filter_idx = value & 0x1f; ++ break; ++ case 0x5a: /* TV Filter Coefficient Data */ ++ if (s->tv_filter_idx < 0x20) ++ s->tv_filter_coeff[s->tv_filter_idx ++] = value; ++ break; ++ ++ case 0x60: /* Input YUV/RGB Translate Mode 0 */ ++ s->yrc[0] = value & 0xb0; ++ break; ++ case 0x62: /* Input YUV/RGB Translate Mode 1 */ ++ s->yrc[1] = value & 0x30; ++ break; ++ case 0x64: /* U Data Fix */ ++ s->u = value & 0xff; ++ break; ++ case 0x66: /* V Data Fix */ ++ s->v = value & 0xff; ++ break; ++ ++ case 0x68: /* Display Mode */ ++ if ((s->mode ^ value) & 3) ++ s->invalidate = 1; ++ s->mode = value & 0xb7; ++ s->enable = value & 1; ++ s->blank = (value >> 1) & 1; ++ if (value & (1 << 4)) ++ fprintf(stderr, "%s: Macrovision enable attempt!\n", __FUNCTION__); ++ break; ++ ++ case 0x6a: /* Special Effects */ ++ s->effect = value & 0xfb; ++ break; ++ ++ case 0x6c: /* Input Window X Start Position 0 */ ++ s->ix[0] &= 0x300; ++ s->ix[0] |= (value << 0) & 0x0ff; ++ break; ++ case 0x6e: /* Input Window X Start Position 1 */ ++ s->ix[0] &= 0x0ff; ++ s->ix[0] |= (value << 8) & 0x300; ++ break; ++ case 0x70: /* Input Window Y Start Position 0 */ ++ s->iy[0] &= 0x300; ++ s->iy[0] |= (value << 0) & 0x0ff; ++ break; ++ case 0x72: /* Input Window Y Start Position 1 */ ++ s->iy[0] &= 0x0ff; ++ s->iy[0] |= (value << 8) & 0x300; ++ break; ++ case 0x74: /* Input Window X End Position 0 */ ++ s->ix[1] &= 0x300; ++ s->ix[1] |= (value << 0) & 0x0ff; ++ break; ++ case 0x76: /* Input Window X End Position 1 */ ++ s->ix[1] &= 0x0ff; ++ s->ix[1] |= (value << 8) & 0x300; ++ break; ++ case 0x78: /* Input Window Y End Position 0 */ ++ s->iy[1] &= 0x300; ++ s->iy[1] |= (value << 0) & 0x0ff; ++ break; ++ case 0x7a: /* Input Window Y End Position 1 */ ++ s->iy[1] &= 0x0ff; ++ s->iy[1] |= (value << 8) & 0x300; ++ break; ++ case 0x7c: /* Output Window X Start Position 0 */ ++ s->ox[0] &= 0x300; ++ s->ox[0] |= (value << 0) & 0x0ff; ++ break; ++ case 0x7e: /* Output Window X Start Position 1 */ ++ s->ox[0] &= 0x0ff; ++ s->ox[0] |= (value << 8) & 0x300; ++ break; ++ case 0x80: /* Output Window Y Start Position 0 */ ++ s->oy[0] &= 0x300; ++ s->oy[0] |= (value << 0) & 0x0ff; ++ break; ++ case 0x82: /* Output Window Y Start Position 1 */ ++ s->oy[0] &= 0x0ff; ++ s->oy[0] |= (value << 8) & 0x300; ++ break; ++ case 0x84: /* Output Window X End Position 0 */ ++ s->ox[1] &= 0x300; ++ s->ox[1] |= (value << 0) & 0x0ff; ++ break; ++ case 0x86: /* Output Window X End Position 1 */ ++ s->ox[1] &= 0x0ff; ++ s->ox[1] |= (value << 8) & 0x300; ++ break; ++ case 0x88: /* Output Window Y End Position 0 */ ++ s->oy[1] &= 0x300; ++ s->oy[1] |= (value << 0) & 0x0ff; ++ break; ++ case 0x8a: /* Output Window Y End Position 1 */ ++ s->oy[1] &= 0x0ff; ++ s->oy[1] |= (value << 8) & 0x300; ++ break; ++ ++ case 0x8c: /* Input Data Format */ ++ s->iformat = value & 0xf; ++ s->bpp = blizzard_iformat_bpp[s->iformat]; ++ if (!s->bpp) ++ fprintf(stderr, "%s: Illegal or unsupported input format %x\n", ++ __FUNCTION__, s->iformat); ++ break; ++ case 0x8e: /* Data Source Select */ ++ s->source = value & 7; ++ /* Currently all windows will be "destructive overlays". */ ++ if ((!(s->effect & (1 << 3)) && (s->ix[0] != s->ox[0] || ++ s->iy[0] != s->oy[0] || ++ s->ix[1] != s->ox[1] || ++ s->iy[1] != s->oy[1])) || ++ !((s->ix[1] - s->ix[0]) & (s->iy[1] - s->iy[0]) & ++ (s->ox[1] - s->ox[0]) & (s->oy[1] - s->oy[0]) & 1)) ++ fprintf(stderr, "%s: Illegal input/output window positions\n", ++ __FUNCTION__); ++ ++ blizzard_transfer_setup(s); ++ break; ++ ++ case 0x90: /* Display Memory Data Port */ ++ if (!s->data.len && !blizzard_transfer_setup(s)) ++ break; ++ ++ *s->data.ptr ++ = value; ++ if (-- s->data.len == 0) ++ blizzard_window(s); ++ break; ++ ++ case 0xa8: /* Border Color 0 */ ++ s->border_r = value; ++ break; ++ case 0xaa: /* Border Color 1 */ ++ s->border_g = value; ++ break; ++ case 0xac: /* Border Color 2 */ ++ s->border_b = value; ++ break; ++ ++ case 0xb4: /* Gamma Correction Enable */ ++ s->gamma_config = value & 0x87; ++ break; ++ case 0xb6: /* Gamma Correction Table Index */ ++ s->gamma_idx = value; ++ break; ++ case 0xb8: /* Gamma Correction Table Data */ ++ s->gamma_lut[s->gamma_idx ++] = value; ++ break; ++ ++ case 0xba: /* 3x3 Matrix Enable */ ++ s->matrix_ena = value & 1; ++ break; ++ case 0xbc ... 0xde: /* Coefficient Registers */ ++ s->matrix_coeff[(reg - 0xbc) >> 1] = value & ((reg & 2) ? 0x80 : 0xff); ++ break; ++ case 0xe0: /* 3x3 Matrix Red Offset */ ++ s->matrix_r = value; ++ break; ++ case 0xe2: /* 3x3 Matrix Green Offset */ ++ s->matrix_g = value; ++ break; ++ case 0xe4: /* 3x3 Matrix Blue Offset */ ++ s->matrix_b = value; ++ break; ++ ++ case 0xe6: /* Power-save */ ++ s->pm = value & 0x83; ++ if (value & s->mode & 1) ++ fprintf(stderr, "%s: The display must be disabled before entering " ++ "Standby Mode\n", __FUNCTION__); ++ break; ++ case 0xe8: /* Non-display Period Control / Status */ ++ s->status = value & 0x1b; ++ break; ++ case 0xea: /* RGB Interface Control */ ++ s->rgbgpio_dir = value & 0x8f; ++ break; ++ case 0xec: /* RGB Interface Status */ ++ s->rgbgpio = value & 0xcf; ++ break; ++ case 0xee: /* General-purpose IO Pins Configuration */ ++ s->gpio_dir = value; ++ break; ++ case 0xf0: /* General-purpose IO Pins Status / Control */ ++ s->gpio = value; ++ break; ++ case 0xf2: /* GPIO Positive Edge Interrupt Trigger */ ++ s->gpio_edge[0] = value; ++ break; ++ case 0xf4: /* GPIO Negative Edge Interrupt Trigger */ ++ s->gpio_edge[1] = value; ++ break; ++ case 0xf6: /* GPIO Interrupt Status */ ++ s->gpio_irq &= value; ++ break; ++ case 0xf8: /* GPIO Pull-down Control */ ++ s->gpio_pdown = value; ++ break; ++ ++ default: ++ fprintf(stderr, "%s: unknown register %02x\n", __FUNCTION__, reg); ++ break; ++ } ++} ++ ++uint16_t s1d13745_read(void *opaque, int dc) ++{ ++ struct blizzard_s *s = (struct blizzard_s *) opaque; ++ uint16_t value = blizzard_reg_read(s, s->reg); ++ ++ if (s->swallow -- > 0) ++ return 0; ++ if (dc) ++ s->reg ++; ++ ++ return value; ++} ++ ++void s1d13745_write(void *opaque, int dc, uint16_t value) ++{ ++ struct blizzard_s *s = (struct blizzard_s *) opaque; ++ ++ if (s->swallow -- > 0) ++ return; ++ if (dc) { ++ blizzard_reg_write(s, s->reg, value); ++ ++ if (s->reg != 0x90 && s->reg != 0x5a && s->reg != 0xb8) ++ s->reg += 2; ++ } else ++ s->reg = value & 0xff; ++} ++ ++void s1d13745_write_block(void *opaque, int dc, ++ void *buf, size_t len, int pitch) ++{ ++ struct blizzard_s *s = (struct blizzard_s *) opaque; ++ ++ while (len > 0) { ++ if (s->reg == 0x90 && dc && ++ (s->data.len || blizzard_transfer_setup(s)) && ++ len >= (s->data.len << 1)) { ++ len -= s->data.len << 1; ++ s->data.len = 0; ++ s->data.data = buf; ++ if (pitch) ++ s->data.pitch = pitch; ++ blizzard_window(s); ++ s->data.data = s->data.buf; ++ continue; ++ } ++ ++ s1d13745_write(opaque, dc, *(uint16_t *) buf); ++ len -= 2; ++ buf += 2; ++ } ++ ++ return; ++} ++ ++static void blizzard_update_display(void *opaque) ++{ ++ struct blizzard_s *s = (struct blizzard_s *) opaque; ++ int y, bypp, bypl, bwidth; ++ uint8_t *src, *dst; ++ ++ if (!s->enable) ++ return; ++ ++ if (s->x != s->state->width || s->y != s->state->height) { ++ s->invalidate = 1; ++ dpy_resize(s->state, s->x, s->y); ++ } ++ ++ if (s->invalidate) { ++ s->invalidate = 0; ++ ++ if (s->blank) { ++ bypp = (s->state->depth + 7) >> 3; ++ memset(s->state->data, 0, bypp * s->x * s->y); ++ return; ++ } ++ ++ s->mx[0] = 0; ++ s->mx[1] = s->x; ++ s->my[0] = 0; ++ s->my[1] = s->y; ++ } ++ ++ if (s->mx[1] <= s->mx[0]) ++ return; ++ ++ bypp = (s->state->depth + 7) >> 3; ++ bypl = bypp * s->x; ++ bwidth = bypp * (s->mx[1] - s->mx[0]); ++ y = s->my[0]; ++ src = s->fb + bypl * y + bypp * s->mx[0]; ++ dst = s->state->data + bypl * y + bypp * s->mx[0]; ++ for (; y < s->my[1]; y ++, src += bypl, dst += bypl) ++ memcpy(dst, src, bwidth); ++ ++ dpy_update(s->state, s->mx[0], s->my[0], ++ s->mx[1] - s->mx[0], y - s->my[0]); ++ ++ s->mx[0] = s->x; ++ s->mx[1] = 0; ++ s->my[0] = s->y; ++ s->my[1] = 0; ++} ++ ++static void blizzard_screen_dump(void *opaque, const char *filename) { ++ struct blizzard_s *s = (struct blizzard_s *) opaque; ++ ++ blizzard_update_display(opaque); ++ if (s && s->state->data) ++ ppm_save(filename, s->state->data, s->x, s->y, s->state->linesize); ++} ++ ++#define DEPTH 8 ++#include "blizzard_template.h" ++#define DEPTH 15 ++#include "blizzard_template.h" ++#define DEPTH 16 ++#include "blizzard_template.h" ++#define DEPTH 24 ++#include "blizzard_template.h" ++#define DEPTH 32 ++#include "blizzard_template.h" ++ ++void *s1d13745_init(qemu_irq gpio_int, DisplayState *ds) ++{ ++ struct blizzard_s *s = (struct blizzard_s *) qemu_mallocz(sizeof(*s)); ++ ++ s->state = ds; ++ s->fb = qemu_malloc(0x180000); ++ ++ switch (s->state->depth) { ++ case 0: ++ s->line_fn_tab[0] = s->line_fn_tab[1] = ++ qemu_mallocz(sizeof(blizzard_fn_t) * 0x10); ++ break; ++ case 8: ++ s->line_fn_tab[0] = blizzard_draw_fn_8; ++ s->line_fn_tab[1] = blizzard_draw_fn_r_8; ++ break; ++ case 15: ++ s->line_fn_tab[0] = blizzard_draw_fn_15; ++ s->line_fn_tab[1] = blizzard_draw_fn_r_15; ++ break; ++ case 16: ++ s->line_fn_tab[0] = blizzard_draw_fn_16; ++ s->line_fn_tab[1] = blizzard_draw_fn_r_16; ++ break; ++ case 24: ++ s->line_fn_tab[0] = blizzard_draw_fn_24; ++ s->line_fn_tab[1] = blizzard_draw_fn_r_24; ++ break; ++ case 32: ++ s->line_fn_tab[0] = blizzard_draw_fn_32; ++ s->line_fn_tab[1] = blizzard_draw_fn_r_32; ++ break; ++ default: ++ fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__); ++ exit(1); ++ } ++ ++ blizzard_reset(s); ++ ++ graphic_console_init(s->state, blizzard_update_display, ++ blizzard_invalidate_display, blizzard_screen_dump, ++ NULL, s); ++ ++ return s; ++} +diff --git a/hw/blizzard_template.h b/hw/blizzard_template.h +new file mode 100644 +index 0000000..8c6451d +--- /dev/null ++++ b/hw/blizzard_template.h +@@ -0,0 +1,138 @@ ++/* ++ * QEMU Epson S1D13744/S1D13745 templates ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Written by Andrzej Zaborowski ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, 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(blizzard_draw_line16_, DEPTH)(PIXEL_TYPE *dest, ++ const uint16_t *src, unsigned int width) ++{ ++#if !defined(SWAP_WORDS) && DEPTH == 16 ++ memcpy(dest, src, width << 1); ++#else ++ uint16_t data; ++ unsigned int r, g, b; ++ const uint16_t *end = (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(blizzard_draw_line24mode1_, DEPTH)(PIXEL_TYPE *dest, ++ const uint8_t *src, unsigned int width) ++{ ++ /* TODO: check if SDL 24-bit planes are not in the same format and ++ * if so, use memcpy */ ++ unsigned int r[2], g[2], b[2]; ++ const uint8_t *end = src + width; ++ while (src < end) { ++ g[0] = *src ++; ++ r[0] = *src ++; ++ r[1] = *src ++; ++ b[0] = *src ++; ++ COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[0], g[0], b[0])); ++ b[1] = *src ++; ++ g[1] = *src ++; ++ COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[1], g[1], b[1])); ++ } ++} ++ ++static void glue(blizzard_draw_line24mode2_, DEPTH)(PIXEL_TYPE *dest, ++ const uint8_t *src, unsigned int width) ++{ ++ unsigned int r, g, b; ++ const uint8_t *end = src + width; ++ while (src < end) { ++ r = *src ++; ++ src ++; ++ b = *src ++; ++ g = *src ++; ++ COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b)); ++ } ++} ++ ++/* No rotation */ ++static blizzard_fn_t glue(blizzard_draw_fn_, DEPTH)[0x10] = { ++ NULL, ++ /* RGB 5:6:5*/ ++ (blizzard_fn_t) glue(blizzard_draw_line16_, DEPTH), ++ /* RGB 6:6:6 mode 1 */ ++ (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH), ++ /* RGB 8:8:8 mode 1 */ ++ (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH), ++ NULL, NULL, ++ /* RGB 6:6:6 mode 2 */ ++ (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH), ++ /* RGB 8:8:8 mode 2 */ ++ (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH), ++ /* YUV 4:2:2 */ ++ NULL, ++ /* YUV 4:2:0 */ ++ NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, ++}; ++ ++/* 90deg, 180deg and 270deg rotation */ ++static blizzard_fn_t glue(blizzard_draw_fn_r_, DEPTH)[0x10] = { ++ /* TODO */ ++ [0 ... 0xf] = NULL, ++}; ++ ++#undef DEPTH ++#undef SKIP_PIXEL ++#undef COPY_PIXEL ++#undef COPY_PIXEL1 ++#undef PIXEL_TYPE ++ ++#undef SWAP_WORDS +diff --git a/hw/boards.h b/hw/boards.h +index affcaa6..408d1e8 100644 +--- a/hw/boards.h ++++ b/hw/boards.h +@@ -80,6 +80,9 @@ extern QEMUMachine terrierpda_machine; + /* palm.c */ + extern QEMUMachine palmte_machine; + ++/* nseries.c */ ++extern QEMUMachine n800_machine; ++ + /* gumstix.c */ + extern QEMUMachine connex_machine; + extern QEMUMachine verdex_machine; +diff --git a/hw/cbus.c b/hw/cbus.c +new file mode 100644 +index 0000000..001b007 +--- /dev/null ++++ b/hw/cbus.c +@@ -0,0 +1,565 @@ ++/* ++ * CBUS three-pin bus and the Retu / Betty / Tahvo / Vilma / Avilma / ++ * Hinku / Vinku / Ahne / Pihi chips used in various Nokia platforms. ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Written by Andrzej Zaborowski ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ */ ++ ++#include "qemu-common.h" ++#include "irq.h" ++#include "devices.h" ++#include "sysemu.h" ++ ++//#define DEBUG ++ ++struct cbus_slave_s; ++struct cbus_priv_s { ++ struct cbus_s cbus; ++ ++ int sel; ++ int dat; ++ int clk; ++ int bit; ++ int dir; ++ uint16_t val; ++ qemu_irq dat_out; ++ ++ int addr; ++ int reg; ++ int rw; ++ enum { ++ cbus_address, ++ cbus_value, ++ } cycle; ++ ++ struct cbus_slave_s *slave[8]; ++}; ++ ++struct cbus_slave_s { ++ void *opaque; ++ void (*io)(void *opaque, int rw, int reg, uint16_t *val); ++ int addr; ++}; ++ ++static void cbus_io(struct cbus_priv_s *s) ++{ ++ if (s->slave[s->addr]) ++ s->slave[s->addr]->io(s->slave[s->addr]->opaque, ++ s->rw, s->reg, &s->val); ++ else ++ cpu_abort(cpu_single_env, "%s: bad slave address %i\n", ++ __FUNCTION__, s->addr); ++} ++ ++static void cbus_cycle(struct cbus_priv_s *s) ++{ ++ switch (s->cycle) { ++ case cbus_address: ++ s->addr = (s->val >> 6) & 7; ++ s->rw = (s->val >> 5) & 1; ++ s->reg = (s->val >> 0) & 0x1f; ++ ++ s->cycle = cbus_value; ++ s->bit = 15; ++ s->dir = !s->rw; ++ s->val = 0; ++ ++ if (s->rw) ++ cbus_io(s); ++ break; ++ ++ case cbus_value: ++ if (!s->rw) ++ cbus_io(s); ++ ++ s->cycle = cbus_address; ++ s->bit = 8; ++ s->dir = 1; ++ s->val = 0; ++ break; ++ } ++} ++ ++static void cbus_clk(void *opaque, int line, int level) ++{ ++ struct cbus_priv_s *s = (struct cbus_priv_s *) opaque; ++ ++ if (!s->sel && level && !s->clk) { ++ if (s->dir) ++ s->val |= s->dat << (s->bit --); ++ else ++ qemu_set_irq(s->dat_out, (s->val >> (s->bit --)) & 1); ++ ++ if (s->bit < 0) ++ cbus_cycle(s); ++ } ++ ++ s->clk = level; ++} ++ ++static void cbus_dat(void *opaque, int line, int level) ++{ ++ struct cbus_priv_s *s = (struct cbus_priv_s *) opaque; ++ ++ s->dat = level; ++} ++ ++static void cbus_sel(void *opaque, int line, int level) ++{ ++ struct cbus_priv_s *s = (struct cbus_priv_s *) opaque; ++ ++ if (!level) { ++ s->dir = 1; ++ s->bit = 8; ++ s->val = 0; ++ } ++ ++ s->sel = level; ++} ++ ++struct cbus_s *cbus_init(qemu_irq dat) ++{ ++ struct cbus_priv_s *s = (struct cbus_priv_s *) qemu_mallocz(sizeof(*s)); ++ ++ s->dat_out = dat; ++ s->cbus.clk = qemu_allocate_irqs(cbus_clk, s, 1)[0]; ++ s->cbus.dat = qemu_allocate_irqs(cbus_dat, s, 1)[0]; ++ s->cbus.sel = qemu_allocate_irqs(cbus_sel, s, 1)[0]; ++ ++ s->sel = 1; ++ s->clk = 0; ++ s->dat = 0; ++ ++ return &s->cbus; ++} ++ ++void cbus_attach(struct cbus_s *bus, void *slave_opaque) ++{ ++ struct cbus_slave_s *slave = (struct cbus_slave_s *) slave_opaque; ++ struct cbus_priv_s *s = (struct cbus_priv_s *) bus; ++ ++ s->slave[slave->addr] = slave; ++} ++ ++/* Retu/Vilma */ ++struct cbus_retu_s { ++ uint16_t irqst; ++ uint16_t irqen; ++ uint16_t cc[2]; ++ int channel; ++ uint16_t result[16]; ++ uint16_t sample; ++ ++ struct { ++ uint16_t cal; ++ } rtc; ++ ++ int is_vilma; ++ qemu_irq irq; ++ struct cbus_slave_s cbus; ++}; ++ ++static void retu_interrupt_update(struct cbus_retu_s *s) ++{ ++ qemu_set_irq(s->irq, s->irqst & ~s->irqen); ++} ++ ++#define RETU_REG_ASICR 0x00 /* (RO) ASIC ID & revision */ ++#define RETU_REG_IDR 0x01 /* (T) Interrupt ID */ ++#define RETU_REG_IMR 0x02 /* (RW) Interrupt mask */ ++#define RETU_REG_RTCDSR 0x03 /* (RW) RTC seconds register */ ++#define RETU_REG_RTCHMR 0x04 /* (RO) RTC hours and minutes reg */ ++#define RETU_REG_RTCHMAR 0x05 /* (RW) RTC hours and minutes set reg */ ++#define RETU_REG_RTCCALR 0x06 /* (RW) RTC calibration register */ ++#define RETU_REG_ADCR 0x08 /* (RW) ADC result register */ ++#define RETU_REG_ADCSCR 0x09 /* (RW) ADC sample control register */ ++#define RETU_REG_AFCR 0x0a /* (RW) AFC register */ ++#define RETU_REG_ANTIFR 0x0b /* (RW) AntiF register */ ++#define RETU_REG_CALIBR 0x0c /* (RW) CalibR register*/ ++#define RETU_REG_CCR1 0x0d /* (RW) Common control register 1 */ ++#define RETU_REG_CCR2 0x0e /* (RW) Common control register 2 */ ++#define RETU_REG_RCTRL_CLR 0x0f /* (T) Regulator clear register */ ++#define RETU_REG_RCTRL_SET 0x10 /* (T) Regulator set register */ ++#define RETU_REG_TXCR 0x11 /* (RW) TxC register */ ++#define RETU_REG_STATUS 0x16 /* (RO) Status register */ ++#define RETU_REG_WATCHDOG 0x17 /* (RW) Watchdog register */ ++#define RETU_REG_AUDTXR 0x18 /* (RW) Audio Codec Tx register */ ++#define RETU_REG_AUDPAR 0x19 /* (RW) AudioPA register */ ++#define RETU_REG_AUDRXR1 0x1a /* (RW) Audio receive register 1 */ ++#define RETU_REG_AUDRXR2 0x1b /* (RW) Autio receive register 2 */ ++#define RETU_REG_SGR1 0x1c /* (RW) */ ++#define RETU_REG_SCR1 0x1d /* (RW) */ ++#define RETU_REG_SGR2 0x1e /* (RW) */ ++#define RETU_REG_SCR2 0x1f /* (RW) */ ++ ++/* Retu Interrupt sources */ ++enum { ++ retu_int_pwr = 0, /* Power */ ++ retu_int_char = 1, /* Charger */ ++ retu_int_rtcs = 2, /* Seconds */ ++ retu_int_rtcm = 3, /* Minutes */ ++ retu_int_rtcd = 4, /* Days */ ++ retu_int_rtca = 5, /* Alarm */ ++ retu_int_hook = 6, /* Hook */ ++ retu_int_head = 7, /* Headset */ ++ retu_int_adcs = 8, /* ADC sample */ ++}; ++ ++/* Retu ADC channel wiring */ ++enum { ++ retu_adc_bsi = 1, /* BSI */ ++ retu_adc_batt_temp = 2, /* Battery temperature */ ++ retu_adc_chg_volt = 3, /* Charger voltage */ ++ retu_adc_head_det = 4, /* Headset detection */ ++ retu_adc_hook_det = 5, /* Hook detection */ ++ retu_adc_rf_gp = 6, /* RF GP */ ++ retu_adc_tx_det = 7, /* Wideband Tx detection */ ++ retu_adc_batt_volt = 8, /* Battery voltage */ ++ retu_adc_sens = 10, /* Light sensor */ ++ retu_adc_sens_temp = 11, /* Light sensor temperature */ ++ retu_adc_bbatt_volt = 12, /* Backup battery voltage */ ++ retu_adc_self_temp = 13, /* RETU temperature */ ++}; ++ ++static inline uint16_t retu_read(struct cbus_retu_s *s, int reg) ++{ ++#ifdef DEBUG ++ printf("RETU read at %02x\n", reg); ++#endif ++ ++ switch (reg) { ++ case RETU_REG_ASICR: ++ return 0x0015 | (s->is_vilma << 7); ++ ++ case RETU_REG_IDR: ++ return s->irqst; ++ ++ case RETU_REG_IMR: ++ return s->irqen; ++ ++ case RETU_REG_RTCDSR: ++ case RETU_REG_RTCHMR: ++ case RETU_REG_RTCHMAR: ++ /* TODO */ ++ return 0x0000; ++ ++ case RETU_REG_RTCCALR: ++ return s->rtc.cal; ++ ++ case RETU_REG_ADCR: ++ return (s->channel << 10) | s->result[s->channel]; ++ case RETU_REG_ADCSCR: ++ return s->sample; ++ ++ case RETU_REG_AFCR: ++ case RETU_REG_ANTIFR: ++ case RETU_REG_CALIBR: ++ /* TODO */ ++ return 0x0000; ++ ++ case RETU_REG_CCR1: ++ return s->cc[0]; ++ case RETU_REG_CCR2: ++ return s->cc[1]; ++ ++ case RETU_REG_RCTRL_CLR: ++ case RETU_REG_RCTRL_SET: ++ case RETU_REG_TXCR: ++ case RETU_REG_STATUS: ++ case RETU_REG_WATCHDOG: ++ case RETU_REG_AUDTXR: ++ case RETU_REG_AUDPAR: ++ case RETU_REG_AUDRXR1: ++ case RETU_REG_AUDRXR2: ++ case RETU_REG_SGR1: ++ case RETU_REG_SCR1: ++ case RETU_REG_SGR2: ++ case RETU_REG_SCR2: ++ /* TODO */ ++ return 0x0000; ++ ++ default: ++ cpu_abort(cpu_single_env, "%s: bad register %02x\n", ++ __FUNCTION__, reg); ++ } ++} ++ ++static inline void retu_write(struct cbus_retu_s *s, int reg, uint16_t val) ++{ ++#ifdef DEBUG ++ printf("RETU write of %04x at %02x\n", val, reg); ++#endif ++ ++ switch (reg) { ++ case RETU_REG_IDR: ++ s->irqst ^= val; ++ retu_interrupt_update(s); ++ break; ++ ++ case RETU_REG_IMR: ++ s->irqen = val; ++ retu_interrupt_update(s); ++ break; ++ ++ case RETU_REG_RTCDSR: ++ case RETU_REG_RTCHMAR: ++ /* TODO */ ++ break; ++ ++ case RETU_REG_RTCCALR: ++ s->rtc.cal = val; ++ break; ++ ++ case RETU_REG_ADCR: ++ s->channel = (val >> 10) & 0xf; ++ s->irqst |= 1 << retu_int_adcs; ++ retu_interrupt_update(s); ++ break; ++ case RETU_REG_ADCSCR: ++ s->sample &= ~val; ++ break; ++ ++ case RETU_REG_AFCR: ++ case RETU_REG_ANTIFR: ++ case RETU_REG_CALIBR: ++ ++ case RETU_REG_CCR1: ++ s->cc[0] = val; ++ break; ++ case RETU_REG_CCR2: ++ s->cc[1] = val; ++ ++ break; ++ case RETU_REG_RCTRL_CLR: ++ case RETU_REG_RCTRL_SET: ++ case RETU_REG_STATUS: ++ /* TODO */ ++ break; ++ ++ case RETU_REG_WATCHDOG: ++ if (val == 0 && (s->cc[0] & 2)) ++ qemu_system_shutdown_request(); ++ break; ++ ++ case RETU_REG_TXCR: ++ case RETU_REG_AUDTXR: ++ case RETU_REG_AUDPAR: ++ case RETU_REG_AUDRXR1: ++ case RETU_REG_AUDRXR2: ++ case RETU_REG_SGR1: ++ case RETU_REG_SCR1: ++ case RETU_REG_SGR2: ++ case RETU_REG_SCR2: ++ /* TODO */ ++ break; ++ ++ default: ++ cpu_abort(cpu_single_env, "%s: bad register %02x\n", ++ __FUNCTION__, reg); ++ } ++} ++ ++static void retu_io(void *opaque, int rw, int reg, uint16_t *val) ++{ ++ struct cbus_retu_s *s = (struct cbus_retu_s *) opaque; ++ ++ if (rw) ++ *val = retu_read(s, reg); ++ else ++ retu_write(s, reg, *val); ++} ++ ++void *retu_init(qemu_irq irq, int vilma) ++{ ++ struct cbus_retu_s *s = (struct cbus_retu_s *) qemu_mallocz(sizeof(*s)); ++ ++ s->irq = irq; ++ s->irqen = 0xffff; ++ s->irqst = 0x0000; ++ s->is_vilma = !!vilma; ++ s->rtc.cal = 0x01; ++ s->result[retu_adc_bsi] = 0x100; ++ s->result[retu_adc_batt_temp] = 0x100; ++ s->result[retu_adc_chg_volt] = 0x200; ++ s->result[retu_adc_batt_volt] = 0x240; ++ s->result[retu_adc_sens] = 0x100; ++ s->result[retu_adc_sens_temp] = 0x100; ++ s->result[retu_adc_bbatt_volt] = 0x200; ++ s->result[retu_adc_self_temp] = 0x100; ++ ++ s->cbus.opaque = s; ++ s->cbus.io = retu_io; ++ s->cbus.addr = 1; ++ ++ return &s->cbus; ++} ++ ++/* Tahvo/Betty */ ++struct cbus_tahvo_s { ++ uint16_t irqst; ++ uint16_t irqen; ++ uint8_t charger; ++ uint8_t backlight; ++ uint16_t usbr; ++ uint16_t power; ++ ++ int is_betty; ++ qemu_irq irq; ++ struct cbus_slave_s cbus; ++}; ++ ++static void tahvo_interrupt_update(struct cbus_tahvo_s *s) ++{ ++ qemu_set_irq(s->irq, s->irqst & ~s->irqen); ++} ++ ++#define TAHVO_REG_ASICR 0x00 /* (RO) ASIC ID & revision */ ++#define TAHVO_REG_IDR 0x01 /* (T) Interrupt ID */ ++#define TAHVO_REG_IDSR 0x02 /* (RO) Interrupt status */ ++#define TAHVO_REG_IMR 0x03 /* (RW) Interrupt mask */ ++#define TAHVO_REG_CHAPWMR 0x04 /* (RW) Charger PWM */ ++#define TAHVO_REG_LEDPWMR 0x05 /* (RW) LED PWM */ ++#define TAHVO_REG_USBR 0x06 /* (RW) USB control */ ++#define TAHVO_REG_RCR 0x07 /* (RW) Some kind of power management */ ++#define TAHVO_REG_CCR1 0x08 /* (RW) Common control register 1 */ ++#define TAHVO_REG_CCR2 0x09 /* (RW) Common control register 2 */ ++#define TAHVO_REG_TESTR1 0x0a /* (RW) Test register 1 */ ++#define TAHVO_REG_TESTR2 0x0b /* (RW) Test register 2 */ ++#define TAHVO_REG_NOPR 0x0c /* (RW) Number of periods */ ++#define TAHVO_REG_FRR 0x0d /* (RO) FR */ ++ ++static inline uint16_t tahvo_read(struct cbus_tahvo_s *s, int reg) ++{ ++#ifdef DEBUG ++ printf("TAHVO read at %02x\n", reg); ++#endif ++ ++ switch (reg) { ++ case TAHVO_REG_ASICR: ++ return 0x0021 | (s->is_betty ? 0x0b00 : 0x0300); ++ ++ case TAHVO_REG_IDR: ++ case TAHVO_REG_IDSR: /* XXX: what does this do? */ ++ return s->irqst; ++ ++ case TAHVO_REG_IMR: ++ return s->irqen; ++ ++ case TAHVO_REG_CHAPWMR: ++ return s->charger; ++ ++ case TAHVO_REG_LEDPWMR: ++ return s->backlight; ++ ++ case TAHVO_REG_USBR: ++ return s->usbr; ++ ++ case TAHVO_REG_RCR: ++ return s->power; ++ ++ case TAHVO_REG_CCR1: ++ case TAHVO_REG_CCR2: ++ case TAHVO_REG_TESTR1: ++ case TAHVO_REG_TESTR2: ++ case TAHVO_REG_NOPR: ++ case TAHVO_REG_FRR: ++ return 0x0000; ++ ++ default: ++ cpu_abort(cpu_single_env, "%s: bad register %02x\n", ++ __FUNCTION__, reg); ++ } ++} ++ ++static inline void tahvo_write(struct cbus_tahvo_s *s, int reg, uint16_t val) ++{ ++#ifdef DEBUG ++ printf("TAHVO write of %04x at %02x\n", val, reg); ++#endif ++ ++ switch (reg) { ++ case TAHVO_REG_IDR: ++ s->irqst ^= val; ++ tahvo_interrupt_update(s); ++ break; ++ ++ case TAHVO_REG_IMR: ++ s->irqen = val; ++ tahvo_interrupt_update(s); ++ break; ++ ++ case TAHVO_REG_CHAPWMR: ++ s->charger = val; ++ break; ++ ++ case TAHVO_REG_LEDPWMR: ++ if (s->backlight != (val & 0x7f)) { ++ s->backlight = val & 0x7f; ++ printf("%s: LCD backlight now at %i / 127\n", ++ __FUNCTION__, s->backlight); ++ } ++ break; ++ ++ case TAHVO_REG_USBR: ++ s->usbr = val; ++ break; ++ ++ case TAHVO_REG_RCR: ++ s->power = val; ++ break; ++ ++ case TAHVO_REG_CCR1: ++ case TAHVO_REG_CCR2: ++ case TAHVO_REG_TESTR1: ++ case TAHVO_REG_TESTR2: ++ case TAHVO_REG_NOPR: ++ case TAHVO_REG_FRR: ++ break; ++ ++ default: ++ cpu_abort(cpu_single_env, "%s: bad register %02x\n", ++ __FUNCTION__, reg); ++ } ++} ++ ++static void tahvo_io(void *opaque, int rw, int reg, uint16_t *val) ++{ ++ struct cbus_tahvo_s *s = (struct cbus_tahvo_s *) opaque; ++ ++ if (rw) ++ *val = tahvo_read(s, reg); ++ else ++ tahvo_write(s, reg, *val); ++} ++ ++void *tahvo_init(qemu_irq irq, int betty) ++{ ++ struct cbus_tahvo_s *s = (struct cbus_tahvo_s *) qemu_mallocz(sizeof(*s)); ++ ++ s->irq = irq; ++ s->irqen = 0xffff; ++ s->irqst = 0x0000; ++ s->is_betty = !!betty; ++ ++ s->cbus.opaque = s; ++ s->cbus.io = tahvo_io; ++ s->cbus.addr = 2; ++ ++ return &s->cbus; ++} +diff --git a/hw/devices.h b/hw/devices.h +index 07c673b..6f1d27b 100644 +--- a/hw/devices.h ++++ b/hw/devices.h +@@ -16,7 +16,38 @@ uint32_t ads7846_read(void *opaque); + void ads7846_write(void *opaque, uint32_t value); + struct ads7846_state_s *ads7846_init(qemu_irq penirq); + ++/* tsc210x.c */ ++struct uwire_slave_s; ++struct mouse_transform_info_s; ++struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio); ++struct uwire_slave_s *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, ++ qemu_irq dav, AudioState *audio); ++struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip); ++uint32_t tsc210x_txrx(void *opaque, uint32_t value); ++void tsc210x_set_transform(struct uwire_slave_s *chip, ++ struct mouse_transform_info_s *info); ++void tsc210x_key_event(struct uwire_slave_s *chip, int key, int down); ++ + /* stellaris_input.c */ + void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode); + ++/* blizzard.c */ ++void *s1d13745_init(qemu_irq gpio_int, DisplayState *ds); ++void s1d13745_write(void *opaque, int dc, uint16_t value); ++void s1d13745_write_block(void *opaque, int dc, ++ void *buf, size_t len, int pitch); ++uint16_t s1d13745_read(void *opaque, int dc); ++ ++/* cbus.c */ ++struct cbus_s { ++ qemu_irq clk; ++ qemu_irq dat; ++ qemu_irq sel; ++}; ++struct cbus_s *cbus_init(qemu_irq dat_out); ++void cbus_attach(struct cbus_s *bus, void *slave_opaque); ++ ++void *retu_init(qemu_irq irq, int vilma); ++void *tahvo_init(qemu_irq irq, int betty); ++ + #endif +diff --git a/hw/flash.h b/hw/flash.h +index 42d25fe..c000d33 100644 +--- a/hw/flash.h ++++ b/hw/flash.h +@@ -34,6 +34,11 @@ uint8_t nand_getio(struct nand_flash_s *s); + #define NAND_MFR_HYNIX 0xad + #define NAND_MFR_MICRON 0x2c + ++/* onenand.c */ ++void onenand_base_update(void *opaque, target_phys_addr_t new); ++void onenand_base_unmap(void *opaque); ++void *onenand_init(uint32_t id, int regshift, qemu_irq irq); ++ + /* ecc.c */ + struct ecc_state_s { + uint8_t cp; /* Column parity */ +diff --git a/hw/i2c.h b/hw/i2c.h +index 2897036..fae46b7 100644 +--- a/hw/i2c.h ++++ b/hw/i2c.h +@@ -71,4 +71,14 @@ uint32_t wm8750_adc_dat(void *opaque); + /* ssd0303.c */ + void ssd0303_init(DisplayState *ds, i2c_bus *bus, int address); + ++/* twl92230.c */ ++i2c_slave *twl92230_init(i2c_bus *bus, qemu_irq irq); ++qemu_irq *twl92230_gpio_in_get(i2c_slave *i2c); ++void twl92230_gpio_out_set(i2c_slave *i2c, int line, qemu_irq handler); ++ ++/* tmp105.c */ ++struct i2c_slave *tmp105_init(i2c_bus *bus, qemu_irq alarm); ++void tmp105_reset(i2c_slave *i2c); ++void tmp105_set(i2c_slave *i2c, int temp); ++ + #endif +diff --git a/hw/integratorcp.c b/hw/integratorcp.c +index 549cc25..f6e6364 100644 +--- a/hw/integratorcp.c ++++ b/hw/integratorcp.c +@@ -469,6 +469,11 @@ static void icp_control_init(uint32_t base) + + /* Board init. */ + ++static struct arm_boot_info integrator_binfo = { ++ .loader_start = 0x0, ++ .board_id = 0x113, ++}; ++ + static void integratorcp_init(int ram_size, int vga_ram_size, + const char *boot_device, DisplayState *ds, + const char *kernel_filename, const char *kernel_cmdline, +@@ -527,8 +532,11 @@ static void integratorcp_init(int ram_size, int vga_ram_size, + } + pl110_init(ds, 0xc0000000, pic[22], 0); + +- arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline, +- initrd_filename, 0x113, 0x0); ++ integrator_binfo.ram_size = ram_size; ++ integrator_binfo.kernel_filename = kernel_filename; ++ integrator_binfo.kernel_cmdline = kernel_cmdline; ++ integrator_binfo.initrd_filename = initrd_filename; ++ arm_load_kernel(env, &integrator_binfo); + } + + QEMUMachine integratorcp_machine = { +diff --git a/hw/mainstone.c b/hw/mainstone.c +index 5856791..9564fc3 100644 +--- a/hw/mainstone.c ++++ b/hw/mainstone.c +@@ -59,12 +59,17 @@ static struct keymap map[0xE0] = { + + enum mainstone_model_e { mainstone }; + ++static struct arm_boot_info mainstone_binfo = { ++ .loader_start = PXA2XX_SDRAM_BASE, ++ .ram_size = 0x04000000, ++}; ++ + static void mainstone_common_init(int ram_size, int vga_ram_size, + DisplayState *ds, const char *kernel_filename, + const char *kernel_cmdline, const char *initrd_filename, + const char *cpu_model, enum mainstone_model_e model, int arm_id) + { +- uint32_t mainstone_ram = 0x04000000; ++ uint32_t mainstone_ram = mainstone_binfo.ram_size; + uint32_t mainstone_rom = 0x00800000; + uint32_t mainstone_flash = 0x02000000; + uint32_t sector_len = 256 * 1024; +@@ -90,7 +95,7 @@ static void mainstone_common_init(int ram_size, int vga_ram_size, + qemu_ram_alloc(mainstone_rom) | IO_MEM_ROM); + + /* Setup initial (reset) machine state */ +- cpu->env->regs[15] = PXA2XX_SDRAM_BASE; ++ cpu->env->regs[15] = mainstone_binfo.loader_start; + + /* There are two 32MiB flash devices on the board */ + for (i = 0; i < 2; i ++) { +@@ -121,8 +126,11 @@ static void mainstone_common_init(int ram_size, int vga_ram_size, + + smc91c111_init(&nd_table[0], MST_ETH_PHYS, mst_irq[ETHERNET_IRQ]); + +- arm_load_kernel(cpu->env, mainstone_ram, kernel_filename, kernel_cmdline, +- initrd_filename, arm_id, PXA2XX_SDRAM_BASE); ++ mainstone_binfo.kernel_filename = kernel_filename; ++ mainstone_binfo.kernel_cmdline = kernel_cmdline; ++ mainstone_binfo.initrd_filename = initrd_filename; ++ mainstone_binfo.board_id = arm_id; ++ arm_load_kernel(cpu->env, &mainstone_binfo); + } + + static void mainstone_init(int ram_size, int vga_ram_size, +diff --git a/hw/max7310.c b/hw/max7310.c +index 75e56c7..397950a 100644 +--- a/hw/max7310.c ++++ b/hw/max7310.c +@@ -134,8 +134,8 @@ static void max7310_event(i2c_slave *i2c, enum i2c_event event) + s->i2c_command_byte = 1; + break; + case I2C_FINISH: +- if (s->len == 1) + #ifdef VERBOSE ++ if (s->len == 1) + printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len); + #endif + break; +diff --git a/hw/nseries.c b/hw/nseries.c +new file mode 100644 +index 0000000..0425d46 +--- /dev/null ++++ b/hw/nseries.c +@@ -0,0 +1,870 @@ ++/* ++ * Nokia N-series internet tablets. ++ * ++ * Copyright (C) 2007 Nokia Corporation ++ * Written by Andrzej Zaborowski ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ */ ++ ++#include "qemu-common.h" ++#include "sysemu.h" ++#include "omap.h" ++#include "arm-misc.h" ++#include "irq.h" ++#include "console.h" ++#include "boards.h" ++#include "i2c.h" ++#include "devices.h" ++#include "flash.h" ++#include "hw.h" ++ ++/* Nokia N800 support */ ++struct n800_s { ++ struct omap_mpu_state_s *cpu; ++ ++ struct rfbi_chip_s blizzard; ++ struct uwire_slave_s *ts; ++ i2c_bus *i2c; ++ ++ int keymap[0x80]; ++}; ++ ++#define N800_MMC2_WP_GPIO 8 ++#define N800_CAM_TURN_GPIO 12 ++#define N800_BLIZZARD_POWERDOWN_GPIO 15 ++#define N800_MMC1_WP_GPIO 23 ++#define N800_ONENAND_GPIO 26 ++#define N800_BT_WKUP_GPIO 61 ++#define N800_STI_GPIO 62 ++#define N800_CBUS_SEL_GPIO 64 ++#define N800_CBUS_CLK_GPIO 65 ++#define N800_CBUS_DAT_GPIO 66 ++#define N800_WLAN_IRQ_GPIO 87 ++#define N800_BT_RESET_GPIO 92 ++#define N800_TEA5761_CS_GPIO 93 ++#define N800_UNKNOWN_GPIO 94 ++#define N800_CAM_ACT_GPIO 95 ++#define N800_MMC_CS_GPIO 96 ++#define N800_WLAN_PWR_GPIO 97 ++#define N800_BT_HOST_WKUP_GPIO 98 ++#define N800_TSC_TS_GPIO 103 ++#define N800_HEADPHONE_GPIO 107 ++#define N800_RETU_GPIO 108 ++#define N800_TSC_KP_IRQ_GPIO 109 ++#define N800_BAT_COVER_GPIO 110 ++#define N800_TAHVO_GPIO 111 ++#define N800_TSC_RESET_GPIO 119 ++#define N800_TMP105_GPIO 125 ++ ++#define XLDR_LL_UART 1 ++ ++#define N800_TMP105_ADDR 0x48 ++#define N800_MENELAUS_ADDR 0x72 ++ ++static void n800_mmc_cs_cb(void *opaque, int line, int level) ++{ ++ /* TODO: this seems to actually be connected to the menelaus, to ++ * which also both MMC slots connect. */ ++ omap_mmc_enable((struct omap_mmc_s *) opaque, !level); ++ ++ printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1); ++} ++ ++static void n800_gpio_setup(struct n800_s *s) ++{ ++ qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->cpu->mmc, 1); ++ omap2_gpio_out_set(s->cpu->gpif, N800_MMC_CS_GPIO, mmc_cs[0]); ++ ++ qemu_irq_lower(omap2_gpio_in_get(s->cpu->gpif, N800_BAT_COVER_GPIO)[0]); ++} ++ ++static void n800_nand_setup(struct n800_s *s) ++{ ++ /* Either ec40xx or ec48xx are OK for the ID */ ++ omap_gpmc_attach(s->cpu->gpmc, 0, 0, onenand_base_update, ++ onenand_base_unmap, ++ onenand_init(0xec4800, 1, ++ omap2_gpio_in_get(s->cpu->gpif, ++ N800_ONENAND_GPIO)[0])); ++} ++ ++static void n800_i2c_setup(struct n800_s *s) ++{ ++ qemu_irq tmp_irq = omap2_gpio_in_get(s->cpu->gpif, N800_TMP105_GPIO)[0]; ++ ++ /* Attach the CPU on one end of our I2C bus. */ ++ s->i2c = omap_i2c_bus(s->cpu->i2c[0]); ++ ++ /* Attach a menelaus PM chip */ ++ i2c_set_slave_address( ++ twl92230_init(s->i2c, ++ s->cpu->irq[0][OMAP_INT_24XX_SYS_NIRQ]), ++ N800_MENELAUS_ADDR); ++ ++ /* Attach a TMP105 PM chip (A0 wired to ground) */ ++ i2c_set_slave_address(tmp105_init(s->i2c, tmp_irq), N800_TMP105_ADDR); ++} ++ ++/* Touchscreen and keypad controller */ ++static void n800_key_event(void *opaque, int keycode) ++{ ++ struct n800_s *s = (struct n800_s *) opaque; ++ int code = s->keymap[keycode & 0x7f]; ++ ++ if (code == -1) ++ return; ++ ++ tsc210x_key_event(s->ts, code, !(keycode & 0x80)); ++} ++ ++static const int n800_keys[16] = { ++ -1, ++ 72, /* Up */ ++ 63, /* Home (F5) */ ++ -1, ++ 75, /* Left */ ++ 28, /* Enter */ ++ 77, /* Right */ ++ -1, ++ 1, /* Cycle (ESC) */ ++ 80, /* Down */ ++ 62, /* Menu (F4) */ ++ -1, ++ 66, /* Zoom- (F8) */ ++ 64, /* FS (F6) */ ++ 65, /* Zoom+ (F7) */ ++ -1, ++}; ++ ++static struct mouse_transform_info_s n800_pointercal = { ++ .x = 800, ++ .y = 480, ++ .a = { 14560, -68, -3455208, -39, -9621, 35152972, 65536 }, ++}; ++ ++static void n800_tsc_setup(struct n800_s *s) ++{ ++ int i; ++ ++ /* XXX: are the three pins inverted inside the chip between the ++ * tsc and the cpu (N4111)? */ ++ qemu_irq penirq = 0; /* NC */ ++ qemu_irq kbirq = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_KP_IRQ_GPIO)[0]; ++ qemu_irq dav = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_TS_GPIO)[0]; ++ ++ s->ts = tsc2301_init(penirq, kbirq, dav, 0); ++ ++ for (i = 0; i < 0x80; i ++) ++ s->keymap[i] = -1; ++ for (i = 0; i < 0x10; i ++) ++ if (n800_keys[i] >= 0) ++ s->keymap[n800_keys[i]] = i; ++ ++ qemu_add_kbd_event_handler(n800_key_event, s); ++ ++ tsc210x_set_transform(s->ts, &n800_pointercal); ++} ++ ++/* LCD MIPI DBI-C controller (URAL) */ ++struct mipid_s { ++ int resp[4]; ++ int param[4]; ++ int p; ++ int pm; ++ int cmd; ++ ++ int sleep; ++ int booster; ++ int te; ++ int selfcheck; ++ int partial; ++ int normal; ++ int vscr; ++ int invert; ++ int onoff; ++ int gamma; ++ uint32_t id; ++}; ++ ++static void mipid_reset(struct mipid_s *s) ++{ ++ if (!s->sleep) ++ fprintf(stderr, "%s: Display off\n", __FUNCTION__); ++ ++ s->pm = 0; ++ s->cmd = 0; ++ ++ s->sleep = 1; ++ s->booster = 0; ++ s->selfcheck = ++ (1 << 7) | /* Register loading OK. */ ++ (1 << 5) | /* The chip is attached. */ ++ (1 << 4); /* Display glass still in one piece. */ ++ s->te = 0; ++ s->partial = 0; ++ s->normal = 1; ++ s->vscr = 0; ++ s->invert = 0; ++ s->onoff = 1; ++ s->gamma = 0; ++} ++ ++static uint32_t mipid_txrx(void *opaque, uint32_t cmd) ++{ ++ struct mipid_s *s = (struct mipid_s *) opaque; ++ uint8_t ret; ++ ++ if (s->p >= sizeof(s->resp) / sizeof(*s->resp)) ++ ret = 0; ++ else ++ ret = s->resp[s->p ++]; ++ if (s->pm --> 0) ++ s->param[s->pm] = cmd; ++ else ++ s->cmd = cmd; ++ ++ switch (s->cmd) { ++ case 0x00: /* NOP */ ++ break; ++ ++ case 0x01: /* SWRESET */ ++ mipid_reset(s); ++ break; ++ ++ case 0x02: /* BSTROFF */ ++ s->booster = 0; ++ break; ++ case 0x03: /* BSTRON */ ++ s->booster = 1; ++ break; ++ ++ case 0x04: /* RDDID */ ++ s->p = 0; ++ s->resp[0] = (s->id >> 16) & 0xff; ++ s->resp[1] = (s->id >> 8) & 0xff; ++ s->resp[2] = (s->id >> 0) & 0xff; ++ break; ++ ++ case 0x06: /* RD_RED */ ++ case 0x07: /* RD_GREEN */ ++ /* XXX the bootloader sometimes issues RD_BLUE meaning RDDID so ++ * for the bootloader one needs to change this. */ ++ case 0x08: /* RD_BLUE */ ++ s->p = 0; ++ /* TODO: return first pixel components */ ++ s->resp[0] = 0x01; ++ break; ++ ++ case 0x09: /* RDDST */ ++ s->p = 0; ++ s->resp[0] = s->booster << 7; ++ s->resp[1] = (5 << 4) | (s->partial << 2) | ++ (s->sleep << 1) | s->normal; ++ s->resp[2] = (s->vscr << 7) | (s->invert << 5) | ++ (s->onoff << 2) | (s->te << 1) | (s->gamma >> 2); ++ s->resp[3] = s->gamma << 6; ++ break; ++ ++ case 0x0a: /* RDDPM */ ++ s->p = 0; ++ s->resp[0] = (s->onoff << 2) | (s->normal << 3) | (s->sleep << 4) | ++ (s->partial << 5) | (s->sleep << 6) | (s->booster << 7); ++ break; ++ case 0x0b: /* RDDMADCTR */ ++ s->p = 0; ++ s->resp[0] = 0; ++ break; ++ case 0x0c: /* RDDCOLMOD */ ++ s->p = 0; ++ s->resp[0] = 5; /* 65K colours */ ++ break; ++ case 0x0d: /* RDDIM */ ++ s->p = 0; ++ s->resp[0] = (s->invert << 5) | (s->vscr << 7) | s->gamma; ++ break; ++ case 0x0e: /* RDDSM */ ++ s->p = 0; ++ s->resp[0] = s->te << 7; ++ break; ++ case 0x0f: /* RDDSDR */ ++ s->p = 0; ++ s->resp[0] = s->selfcheck; ++ break; ++ ++ case 0x10: /* SLPIN */ ++ s->sleep = 1; ++ break; ++ case 0x11: /* SLPOUT */ ++ s->sleep = 0; ++ s->selfcheck ^= 1 << 6; /* POFF self-diagnosis Ok */ ++ break; ++ ++ case 0x12: /* PTLON */ ++ s->partial = 1; ++ s->normal = 0; ++ s->vscr = 0; ++ break; ++ case 0x13: /* NORON */ ++ s->partial = 0; ++ s->normal = 1; ++ s->vscr = 0; ++ break; ++ ++ case 0x20: /* INVOFF */ ++ s->invert = 0; ++ break; ++ case 0x21: /* INVON */ ++ s->invert = 1; ++ break; ++ ++ case 0x22: /* APOFF */ ++ case 0x23: /* APON */ ++ goto bad_cmd; ++ ++ case 0x25: /* WRCNTR */ ++ if (s->pm < 0) ++ s->pm = 1; ++ goto bad_cmd; ++ ++ case 0x26: /* GAMSET */ ++ if (!s->pm) ++ s->gamma = ffs(s->param[0] & 0xf) - 1; ++ else if (s->pm < 0) ++ s->pm = 1; ++ break; ++ ++ case 0x28: /* DISPOFF */ ++ s->onoff = 0; ++ fprintf(stderr, "%s: Display off\n", __FUNCTION__); ++ break; ++ case 0x29: /* DISPON */ ++ s->onoff = 1; ++ fprintf(stderr, "%s: Display on\n", __FUNCTION__); ++ break; ++ ++ case 0x2a: /* CASET */ ++ case 0x2b: /* RASET */ ++ case 0x2c: /* RAMWR */ ++ case 0x2d: /* RGBSET */ ++ case 0x2e: /* RAMRD */ ++ case 0x30: /* PTLAR */ ++ case 0x33: /* SCRLAR */ ++ goto bad_cmd; ++ ++ case 0x34: /* TEOFF */ ++ s->te = 0; ++ break; ++ case 0x35: /* TEON */ ++ if (!s->pm) ++ s->te = 1; ++ else if (s->pm < 0) ++ s->pm = 1; ++ break; ++ ++ case 0x36: /* MADCTR */ ++ goto bad_cmd; ++ ++ case 0x37: /* VSCSAD */ ++ s->partial = 0; ++ s->normal = 0; ++ s->vscr = 1; ++ break; ++ ++ case 0x38: /* IDMOFF */ ++ case 0x39: /* IDMON */ ++ case 0x3a: /* COLMOD */ ++ goto bad_cmd; ++ ++ case 0xb0: /* CLKINT / DISCTL */ ++ case 0xb1: /* CLKEXT */ ++ if (s->pm < 0) ++ s->pm = 2; ++ break; ++ ++ case 0xb4: /* FRMSEL */ ++ break; ++ ++ case 0xb5: /* FRM8SEL */ ++ case 0xb6: /* TMPRNG / INIESC */ ++ case 0xb7: /* TMPHIS / NOP2 */ ++ case 0xb8: /* TMPREAD / MADCTL */ ++ case 0xba: /* DISTCTR */ ++ case 0xbb: /* EPVOL */ ++ goto bad_cmd; ++ ++ case 0xbd: /* Unknown */ ++ s->p = 0; ++ s->resp[0] = 0; ++ s->resp[1] = 1; ++ break; ++ ++ case 0xc2: /* IFMOD */ ++ if (s->pm < 0) ++ s->pm = 2; ++ break; ++ ++ case 0xc6: /* PWRCTL */ ++ case 0xc7: /* PPWRCTL */ ++ case 0xd0: /* EPWROUT */ ++ case 0xd1: /* EPWRIN */ ++ case 0xd4: /* RDEV */ ++ case 0xd5: /* RDRR */ ++ goto bad_cmd; ++ ++ case 0xda: /* RDID1 */ ++ s->p = 0; ++ s->resp[0] = (s->id >> 16) & 0xff; ++ break; ++ case 0xdb: /* RDID2 */ ++ s->p = 0; ++ s->resp[0] = (s->id >> 8) & 0xff; ++ break; ++ case 0xdc: /* RDID3 */ ++ s->p = 0; ++ s->resp[0] = (s->id >> 0) & 0xff; ++ break; ++ ++ default: ++ bad_cmd: ++ fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, s->cmd); ++ break; ++ } ++ ++ return ret; ++} ++ ++static void *mipid_init(void) ++{ ++ struct mipid_s *s = (struct mipid_s *) qemu_mallocz(sizeof(*s)); ++ ++ s->id = 0x838f03; ++ mipid_reset(s); ++ ++ return s; ++} ++ ++static void n800_spi_setup(struct n800_s *s) ++{ ++ void *tsc2301 = s->ts->opaque; ++ void *mipid = mipid_init(); ++ ++ omap_mcspi_attach(s->cpu->mcspi[0], tsc210x_txrx, tsc2301, 0); ++ omap_mcspi_attach(s->cpu->mcspi[0], mipid_txrx, mipid, 1); ++} ++ ++/* This task is normally performed by the bootloader. If we're loading ++ * a kernel directly, we need to enable the Blizzard ourselves. */ ++static void n800_dss_init(struct rfbi_chip_s *chip) ++{ ++ chip->write(chip->opaque, 0, 0x2a); /* LCD Width register */ ++ chip->write(chip->opaque, 1, 0x64); ++ chip->write(chip->opaque, 0, 0x2c); /* LCD HNDP register */ ++ chip->write(chip->opaque, 1, 0x1e); ++ chip->write(chip->opaque, 0, 0x2e); /* LCD Height 0 register */ ++ chip->write(chip->opaque, 1, 0xe0); ++ chip->write(chip->opaque, 0, 0x30); /* LCD Height 1 register */ ++ chip->write(chip->opaque, 1, 0x01); ++ chip->write(chip->opaque, 0, 0x32); /* LCD VNDP register */ ++ chip->write(chip->opaque, 1, 0x06); ++ chip->write(chip->opaque, 0, 0x68); /* Display Mode register */ ++ chip->write(chip->opaque, 1, 1); /* Enable bit */ ++} ++ ++static void n800_dss_setup(struct n800_s *s, DisplayState *ds) ++{ ++ s->blizzard.opaque = s1d13745_init(0, ds); ++ s->blizzard.block = s1d13745_write_block; ++ s->blizzard.write = s1d13745_write; ++ s->blizzard.read = s1d13745_read; ++ ++ omap_rfbi_attach(s->cpu->dss, 0, &s->blizzard); ++} ++ ++static void n800_cbus_setup(struct n800_s *s) ++{ ++ qemu_irq dat_out = omap2_gpio_in_get(s->cpu->gpif, N800_CBUS_DAT_GPIO)[0]; ++ qemu_irq retu_irq = omap2_gpio_in_get(s->cpu->gpif, N800_RETU_GPIO)[0]; ++ qemu_irq tahvo_irq = omap2_gpio_in_get(s->cpu->gpif, N800_TAHVO_GPIO)[0]; ++ ++ struct cbus_s *cbus = cbus_init(dat_out); ++ ++ omap2_gpio_out_set(s->cpu->gpif, N800_CBUS_CLK_GPIO, cbus->clk); ++ omap2_gpio_out_set(s->cpu->gpif, N800_CBUS_DAT_GPIO, cbus->dat); ++ omap2_gpio_out_set(s->cpu->gpif, N800_CBUS_SEL_GPIO, cbus->sel); ++ ++ cbus_attach(cbus, retu_init(retu_irq, 1)); ++ cbus_attach(cbus, tahvo_init(tahvo_irq, 1)); ++} ++ ++/* This task is normally performed by the bootloader. If we're loading ++ * a kernel directly, we need to set up GPMC mappings ourselves. */ ++static void n800_gpmc_init(struct n800_s *s) ++{ ++ uint32_t config7 = ++ (0xf << 8) | /* MASKADDRESS */ ++ (1 << 6) | /* CSVALID */ ++ (4 << 0); /* BASEADDRESS */ ++ ++ cpu_physical_memory_write(0x6800a078, /* GPMC_CONFIG7_0 */ ++ (void *) &config7, sizeof(config7)); ++} ++ ++#if 0 ++static uint32_t n800_pinout[104] = { ++ 0x080f00d8, 0x00d40808, 0x03080808, 0x080800d0, ++ 0x00dc0808, 0x0b0f0f00, 0x080800b4, 0x00c00808, ++ 0x08080808, 0x180800c4, 0x00b80000, 0x08080808, ++ 0x080800bc, 0x00cc0808, 0x08081818, 0x18180128, ++ 0x01241800, 0x18181818, 0x000000f0, 0x01300000, ++ 0x00001b0b, 0x1b0f0138, 0x00e0181b, 0x1b031b0b, ++ 0x180f0078, 0x00740018, 0x0f0f0f1a, 0x00000080, ++ 0x007c0000, 0x00000000, 0x00000088, 0x00840000, ++ 0x00000000, 0x00000094, 0x00980300, 0x0f180003, ++ 0x0000008c, 0x00900f0f, 0x0f0f1b00, 0x0f00009c, ++ 0x01140000, 0x1b1b0f18, 0x0818013c, 0x01400008, ++ 0x00001818, 0x000b0110, 0x010c1800, 0x0b030b0f, ++ 0x181800f4, 0x00f81818, 0x00000018, 0x000000fc, ++ 0x00401808, 0x00000000, 0x0f1b0030, 0x003c0008, ++ 0x00000000, 0x00000038, 0x00340000, 0x00000000, ++ 0x1a080070, 0x00641a1a, 0x08080808, 0x08080060, ++ 0x005c0808, 0x08080808, 0x08080058, 0x00540808, ++ 0x08080808, 0x0808006c, 0x00680808, 0x08080808, ++ 0x000000a8, 0x00b00000, 0x08080808, 0x000000a0, ++ 0x00a40000, 0x00000000, 0x08ff0050, 0x004c0808, ++ 0xffffffff, 0xffff0048, 0x0044ffff, 0xffffffff, ++ 0x000000ac, 0x01040800, 0x08080b0f, 0x18180100, ++ 0x01081818, 0x0b0b1808, 0x1a0300e4, 0x012c0b1a, ++ 0x02020018, 0x0b000134, 0x011c0800, 0x0b1b1b00, ++ 0x0f0000c8, 0x00ec181b, 0x000f0f02, 0x00180118, ++ 0x01200000, 0x0f0b1b1b, 0x0f0200e8, 0x0000020b, ++}; ++#endif ++ ++/* Setup sequence done by the bootloader */ ++static void n800_boot_init(void *opaque) ++{ ++ struct n800_s *s = (struct n800_s *) opaque; ++ uint32_t buf; ++ ++ /* PRCM setup */ ++#define omap_writel(addr, val) \ ++ buf = (val); \ ++ cpu_physical_memory_write(addr, (void *) &buf, sizeof(buf)) ++ ++ omap_writel(0x48008060, 0x41); /* PRCM_CLKSRC_CTRL */ ++ omap_writel(0x48008070, 1); /* PRCM_CLKOUT_CTRL */ ++ omap_writel(0x48008078, 0); /* PRCM_CLKEMUL_CTRL */ ++ omap_writel(0x48008090, 0); /* PRCM_VOLTSETUP */ ++ omap_writel(0x48008094, 0); /* PRCM_CLKSSETUP */ ++ omap_writel(0x48008098, 0); /* PRCM_POLCTRL */ ++ omap_writel(0x48008140, 2); /* CM_CLKSEL_MPU */ ++ omap_writel(0x48008148, 0); /* CM_CLKSTCTRL_MPU */ ++ omap_writel(0x48008158, 1); /* RM_RSTST_MPU */ ++ omap_writel(0x480081c8, 0x15); /* PM_WKDEP_MPU */ ++ omap_writel(0x480081d4, 0x1d4); /* PM_EVGENCTRL_MPU */ ++ omap_writel(0x480081d8, 0); /* PM_EVEGENONTIM_MPU */ ++ omap_writel(0x480081dc, 0); /* PM_EVEGENOFFTIM_MPU */ ++ omap_writel(0x480081e0, 0xc); /* PM_PWSTCTRL_MPU */ ++ omap_writel(0x48008200, 0x047e7ff7); /* CM_FCLKEN1_CORE */ ++ omap_writel(0x48008204, 0x00000004); /* CM_FCLKEN2_CORE */ ++ omap_writel(0x48008210, 0x047e7ff1); /* CM_ICLKEN1_CORE */ ++ omap_writel(0x48008214, 0x00000004); /* CM_ICLKEN2_CORE */ ++ omap_writel(0x4800821c, 0x00000000); /* CM_ICLKEN4_CORE */ ++ omap_writel(0x48008230, 0); /* CM_AUTOIDLE1_CORE */ ++ omap_writel(0x48008234, 0); /* CM_AUTOIDLE2_CORE */ ++ omap_writel(0x48008238, 7); /* CM_AUTOIDLE3_CORE */ ++ omap_writel(0x4800823c, 0); /* CM_AUTOIDLE4_CORE */ ++ omap_writel(0x48008240, 0x04360626); /* CM_CLKSEL1_CORE */ ++ omap_writel(0x48008244, 0x00000014); /* CM_CLKSEL2_CORE */ ++ omap_writel(0x48008248, 0); /* CM_CLKSTCTRL_CORE */ ++ omap_writel(0x48008300, 0x00000000); /* CM_FCLKEN_GFX */ ++ omap_writel(0x48008310, 0x00000000); /* CM_ICLKEN_GFX */ ++ omap_writel(0x48008340, 0x00000001); /* CM_CLKSEL_GFX */ ++ omap_writel(0x48008400, 0x00000004); /* CM_FCLKEN_WKUP */ ++ omap_writel(0x48008410, 0x00000004); /* CM_ICLKEN_WKUP */ ++ omap_writel(0x48008440, 0x00000000); /* CM_CLKSEL_WKUP */ ++ omap_writel(0x48008500, 0x000000cf); /* CM_CLKEN_PLL */ ++ omap_writel(0x48008530, 0x0000000c); /* CM_AUTOIDLE_PLL */ ++ omap_writel(0x48008540, /* CM_CLKSEL1_PLL */ ++ (0x78 << 12) | (6 << 8)); ++ omap_writel(0x48008544, 2); /* CM_CLKSEL2_PLL */ ++ ++ /* GPMC setup */ ++ n800_gpmc_init(s); ++ ++ /* Video setup */ ++ n800_dss_init(&s->blizzard); ++ ++ /* CPU setup */ ++ s->cpu->env->regs[15] = s->cpu->env->boot_info->loader_start; ++} ++ ++#define OMAP_TAG_NOKIA_BT 0x4e01 ++#define OMAP_TAG_WLAN_CX3110X 0x4e02 ++#define OMAP_TAG_CBUS 0x4e03 ++#define OMAP_TAG_EM_ASIC_BB5 0x4e04 ++ ++static int n800_atag_setup(struct arm_boot_info *info, void *p) ++{ ++ uint8_t *b; ++ uint16_t *w; ++ uint32_t *l; ++ ++ w = p; ++ ++ stw_raw(w ++, OMAP_TAG_UART); /* u16 tag */ ++ stw_raw(w ++, 4); /* u16 len */ ++ stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */ ++ w ++; ++ ++ stw_raw(w ++, OMAP_TAG_EM_ASIC_BB5); /* u16 tag */ ++ stw_raw(w ++, 4); /* u16 len */ ++ stw_raw(w ++, N800_RETU_GPIO); /* s16 retu_irq_gpio */ ++ stw_raw(w ++, N800_TAHVO_GPIO); /* s16 tahvo_irq_gpio */ ++ ++ stw_raw(w ++, OMAP_TAG_CBUS); /* u16 tag */ ++ stw_raw(w ++, 8); /* u16 len */ ++ stw_raw(w ++, N800_CBUS_CLK_GPIO); /* s16 clk_gpio */ ++ stw_raw(w ++, N800_CBUS_DAT_GPIO); /* s16 dat_gpio */ ++ stw_raw(w ++, N800_CBUS_SEL_GPIO); /* s16 sel_gpio */ ++ w ++; ++ ++ stw_raw(w ++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */ ++ stw_raw(w ++, 20); /* u16 len */ ++ strcpy((void *) w, "bat_cover"); /* char name[12] */ ++ w += 6; ++ stw_raw(w ++, N800_BAT_COVER_GPIO); /* u16 gpio */ ++ stw_raw(w ++, 0x01); ++ stw_raw(w ++, 0); ++ stw_raw(w ++, 0); ++ ++ stw_raw(w ++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */ ++ stw_raw(w ++, 20); /* u16 len */ ++ strcpy((void *) w, "cam_act"); /* char name[12] */ ++ w += 6; ++ stw_raw(w ++, N800_CAM_ACT_GPIO); /* u16 gpio */ ++ stw_raw(w ++, 0x20); ++ stw_raw(w ++, 0); ++ stw_raw(w ++, 0); ++ ++ stw_raw(w ++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */ ++ stw_raw(w ++, 20); /* u16 len */ ++ strcpy((void *) w, "cam_turn"); /* char name[12] */ ++ w += 6; ++ stw_raw(w ++, N800_CAM_TURN_GPIO); /* u16 gpio */ ++ stw_raw(w ++, 0x21); ++ stw_raw(w ++, 0); ++ stw_raw(w ++, 0); ++ ++ stw_raw(w ++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */ ++ stw_raw(w ++, 20); /* u16 len */ ++ strcpy((void *) w, "headphone"); /* char name[12] */ ++ w += 6; ++ stw_raw(w ++, N800_HEADPHONE_GPIO); /* u16 gpio */ ++ stw_raw(w ++, 0x11); ++ stw_raw(w ++, 0); ++ stw_raw(w ++, 0); ++ ++ stw_raw(w ++, OMAP_TAG_NOKIA_BT); /* u16 tag */ ++ stw_raw(w ++, 12); /* u16 len */ ++ b = (void *) w; ++ stb_raw(b ++, 0x01); /* u8 chip_type (CSR) */ ++ stb_raw(b ++, N800_BT_WKUP_GPIO); /* u8 bt_wakeup_gpio */ ++ stb_raw(b ++, N800_BT_HOST_WKUP_GPIO); /* u8 host_wakeup_gpio */ ++ stb_raw(b ++, N800_BT_RESET_GPIO); /* u8 reset_gpio */ ++ stb_raw(b ++, 1); /* u8 bt_uart */ ++ memset(b, 0, 6); /* u8 bd_addr[6] */ ++ b += 6; ++ stb_raw(b ++, 0x02); /* u8 bt_sysclk (38.4) */ ++ w = (void *) b; ++ ++ stw_raw(w ++, OMAP_TAG_WLAN_CX3110X); /* u16 tag */ ++ stw_raw(w ++, 8); /* u16 len */ ++ stw_raw(w ++, 0x25); /* u8 chip_type */ ++ stw_raw(w ++, N800_WLAN_PWR_GPIO); /* s16 power_gpio */ ++ stw_raw(w ++, N800_WLAN_IRQ_GPIO); /* s16 irq_gpio */ ++ stw_raw(w ++, -1); /* s16 spi_cs_gpio */ ++ ++ stw_raw(w ++, OMAP_TAG_MMC); /* u16 tag */ ++ stw_raw(w ++, 16); /* u16 len */ ++ stw_raw(w ++, 0xf); /* unsigned flags */ ++ stw_raw(w ++, -1); /* s16 power_pin */ ++ stw_raw(w ++, -1); /* s16 switch_pin */ ++ stw_raw(w ++, -1); /* s16 wp_pin */ ++ stw_raw(w ++, 0); /* unsigned flags */ ++ stw_raw(w ++, 0); /* s16 power_pin */ ++ stw_raw(w ++, 0); /* s16 switch_pin */ ++ stw_raw(w ++, 0); /* s16 wp_pin */ ++ ++ stw_raw(w ++, OMAP_TAG_TEA5761); /* u16 tag */ ++ stw_raw(w ++, 4); /* u16 len */ ++ stw_raw(w ++, N800_TEA5761_CS_GPIO); /* u16 enable_gpio */ ++ w ++; ++ ++ stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */ ++ stw_raw(w ++, 28); /* u16 len */ ++ strcpy((void *) w, "bootloader"); /* char name[16] */ ++ l = (void *) (w + 8); ++ stl_raw(l ++, 0x00020000); /* unsigned int size */ ++ stl_raw(l ++, 0x00000000); /* unsigned int offset */ ++ stl_raw(l ++, 0x3); /* unsigned int mask_flags */ ++ w = (void *) l; ++ ++ stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */ ++ stw_raw(w ++, 28); /* u16 len */ ++ strcpy((void *) w, "config"); /* char name[16] */ ++ l = (void *) (w + 8); ++ stl_raw(l ++, 0x00060000); /* unsigned int size */ ++ stl_raw(l ++, 0x00020000); /* unsigned int offset */ ++ stl_raw(l ++, 0x0); /* unsigned int mask_flags */ ++ w = (void *) l; ++ ++ stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */ ++ stw_raw(w ++, 28); /* u16 len */ ++ strcpy((void *) w, "kernel"); /* char name[16] */ ++ l = (void *) (w + 8); ++ stl_raw(l ++, 0x00200000); /* unsigned int size */ ++ stl_raw(l ++, 0x00080000); /* unsigned int offset */ ++ stl_raw(l ++, 0x0); /* unsigned int mask_flags */ ++ w = (void *) l; ++ ++ stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */ ++ stw_raw(w ++, 28); /* u16 len */ ++ strcpy((void *) w, "initfs"); /* char name[16] */ ++ l = (void *) (w + 8); ++ stl_raw(l ++, 0x00200000); /* unsigned int size */ ++ stl_raw(l ++, 0x00280000); /* unsigned int offset */ ++ stl_raw(l ++, 0x3); /* unsigned int mask_flags */ ++ w = (void *) l; ++ ++ stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */ ++ stw_raw(w ++, 28); /* u16 len */ ++ strcpy((void *) w, "rootfs"); /* char name[16] */ ++ l = (void *) (w + 8); ++ stl_raw(l ++, 0x0fb80000); /* unsigned int size */ ++ stl_raw(l ++, 0x00480000); /* unsigned int offset */ ++ stl_raw(l ++, 0x3); /* unsigned int mask_flags */ ++ w = (void *) l; ++ ++ stw_raw(w ++, OMAP_TAG_BOOT_REASON); /* u16 tag */ ++ stw_raw(w ++, 12); /* u16 len */ ++#if 0 ++ strcpy((void *) w, "por"); /* char reason_str[12] */ ++ strcpy((void *) w, "charger"); /* char reason_str[12] */ ++ strcpy((void *) w, "32wd_to"); /* char reason_str[12] */ ++ strcpy((void *) w, "sw_rst"); /* char reason_str[12] */ ++ strcpy((void *) w, "mbus"); /* char reason_str[12] */ ++ strcpy((void *) w, "unknown"); /* char reason_str[12] */ ++ strcpy((void *) w, "swdg_to"); /* char reason_str[12] */ ++ strcpy((void *) w, "sec_vio"); /* char reason_str[12] */ ++ strcpy((void *) w, "pwr_key"); /* char reason_str[12] */ ++ strcpy((void *) w, "rtc_alarm"); /* char reason_str[12] */ ++#else ++ strcpy((void *) w, "pwr_key"); /* char reason_str[12] */ ++#endif ++ w += 6; ++ ++ stw_raw(w ++, OMAP_TAG_VERSION_STR); /* u16 tag */ ++ stw_raw(w ++, 24); /* u16 len */ ++ strcpy((void *) w, "product"); /* char component[12] */ ++ w += 6; ++ strcpy((void *) w, "RX-34"); /* char version[12] */ ++ w += 6; ++ ++ stw_raw(w ++, OMAP_TAG_VERSION_STR); /* u16 tag */ ++ stw_raw(w ++, 24); /* u16 len */ ++ strcpy((void *) w, "hw-build"); /* char component[12] */ ++ w += 6; ++ strcpy((void *) w, "QEMU"); /* char version[12] */ ++ w += 6; ++ ++ stw_raw(w ++, OMAP_TAG_VERSION_STR); /* u16 tag */ ++ stw_raw(w ++, 24); /* u16 len */ ++ strcpy((void *) w, "nolo"); /* char component[12] */ ++ w += 6; ++ strcpy((void *) w, "1.1.6-qemu"); /* char version[12] */ ++ w += 6; ++ ++ stw_raw(w ++, OMAP_TAG_LCD); /* u16 tag */ ++ stw_raw(w ++, 36); /* u16 len */ ++ strcpy((void *) w, "QEMU LCD panel"); /* char panel_name[16] */ ++ w += 8; ++ strcpy((void *) w, "blizzard"); /* char ctrl_name[16] */ ++ w += 8; ++ stw_raw(w ++, 5); /* TODO s16 nreset_gpio */ ++ stw_raw(w ++, 16); /* u8 data_lines */ ++ ++ return (void *) w - p; ++} ++ ++static struct arm_boot_info n800_binfo = { ++ .loader_start = OMAP2_Q2_BASE, ++ /* Actually two chips of 0x4000000 bytes each */ ++ .ram_size = 0x08000000, ++ .board_id = 0x4f7, ++ .atag_board = n800_atag_setup, ++}; ++ ++static void n800_init(int ram_size, int vga_ram_size, ++ const char *boot_device, DisplayState *ds, ++ const char *kernel_filename, const char *kernel_cmdline, ++ const char *initrd_filename, const char *cpu_model) ++{ ++ struct n800_s *s = (struct n800_s *) qemu_mallocz(sizeof(*s)); ++ int sdram_size = n800_binfo.ram_size; ++ int onenandram_size = 0x00010000; ++ ++ if (ram_size < sdram_size + onenandram_size + OMAP242X_SRAM_SIZE) { ++ fprintf(stderr, "This architecture uses %i bytes of memory\n", ++ sdram_size + onenandram_size + OMAP242X_SRAM_SIZE); ++ exit(1); ++ } ++ ++ s->cpu = omap2420_mpu_init(sdram_size, NULL, cpu_model); ++ ++ n800_gpio_setup(s); ++ n800_nand_setup(s); ++ n800_i2c_setup(s); ++ n800_tsc_setup(s); ++ n800_spi_setup(s); ++ n800_dss_setup(s, ds); ++ n800_cbus_setup(s); ++ ++ /* Setup initial (reset) machine state */ ++ ++ /* Start at the OneNAND bootloader. */ ++ s->cpu->env->regs[15] = 0; ++ ++ if (kernel_filename) { ++ /* Or at the linux loader. */ ++ n800_binfo.kernel_filename = kernel_filename; ++ n800_binfo.kernel_cmdline = kernel_cmdline; ++ n800_binfo.initrd_filename = initrd_filename; ++ arm_load_kernel(s->cpu->env, &n800_binfo); ++ ++ qemu_register_reset(n800_boot_init, s); ++ n800_boot_init(s); ++ } ++ ++ dpy_resize(ds, 800, 480); ++} ++ ++QEMUMachine n800_machine = { ++ "n800", ++ "Nokia N800 aka. RX-34 tablet (OMAP2420)", ++ n800_init, ++}; +diff --git a/hw/omap.h b/hw/omap.h +index ecfd54d..de838c9 100644 +--- a/hw/omap.h ++++ b/hw/omap.h +@@ -22,6 +22,7 @@ + # define hw_omap_h "omap.h" + + # define OMAP_EMIFS_BASE 0x00000000 ++# define OMAP2_Q0_BASE 0x00000000 + # define OMAP_CS0_BASE 0x00000000 + # define OMAP_CS1_BASE 0x04000000 + # define OMAP_CS2_BASE 0x08000000 +@@ -29,18 +30,26 @@ + # define OMAP_EMIFF_BASE 0x10000000 + # define OMAP_IMIF_BASE 0x20000000 + # define OMAP_LOCALBUS_BASE 0x30000000 ++# define OMAP2_Q1_BASE 0x40000000 ++# define OMAP2_L4_BASE 0x48000000 ++# define OMAP2_SRAM_BASE 0x40200000 ++# define OMAP2_L3_BASE 0x68000000 ++# define OMAP2_Q2_BASE 0x80000000 ++# define OMAP2_Q3_BASE 0xc0000000 + # define OMAP_MPUI_BASE 0xe1000000 + + # define OMAP730_SRAM_SIZE 0x00032000 + # define OMAP15XX_SRAM_SIZE 0x00030000 + # define OMAP16XX_SRAM_SIZE 0x00004000 + # define OMAP1611_SRAM_SIZE 0x0003e800 ++# define OMAP242X_SRAM_SIZE 0x000a0000 ++# define OMAP243X_SRAM_SIZE 0x00010000 + # define OMAP_CS0_SIZE 0x04000000 + # define OMAP_CS1_SIZE 0x04000000 + # define OMAP_CS2_SIZE 0x04000000 + # define OMAP_CS3_SIZE 0x04000000 + +-/* omap1_clk.c */ ++/* omap_clk.c */ + struct omap_mpu_state_s; + typedef struct clk *omap_clk; + omap_clk omap_findclk(struct omap_mpu_state_s *mpu, const char *name); +@@ -55,14 +64,41 @@ int64_t omap_clk_getrate(omap_clk clk); + void omap_clk_reparent(omap_clk clk, omap_clk parent); + + /* omap[123].c */ ++struct omap_l4_s; ++struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num); ++ ++struct omap_target_agent_s; ++struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, int cs); ++target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region, ++ int iotype); ++ + struct omap_intr_handler_s; + struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base, +- unsigned long size, unsigned char nbanks, ++ unsigned long size, unsigned char nbanks, qemu_irq **pins, + qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk); +- +-struct omap_target_agent_s; +-static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, +- int region, int iotype) { return 0; } ++struct omap_intr_handler_s *omap2_inth_init(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); ++void omap_inth_reset(struct omap_intr_handler_s *s); ++ ++struct omap_prcm_s; ++struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta, ++ qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int, ++ struct omap_mpu_state_s *mpu); ++ ++struct 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); ++ ++struct omap_gpmc_s; ++struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq); ++void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype, ++ void (*base_upd)(void *opaque, target_phys_addr_t new), ++ void (*unmap)(void *opaque), void *opaque); + + /* + * Common IRQ numbers for level 1 interrupt handler +@@ -295,10 +331,20 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, + * OMAP-24xx common IRQ numbers + */ + # define OMAP_INT_24XX_SYS_NIRQ 7 ++# define OMAP_INT_24XX_L3_IRQ 10 ++# define OMAP_INT_24XX_PRCM_MPU_IRQ 11 + # define OMAP_INT_24XX_SDMA_IRQ0 12 + # define OMAP_INT_24XX_SDMA_IRQ1 13 + # define OMAP_INT_24XX_SDMA_IRQ2 14 + # define OMAP_INT_24XX_SDMA_IRQ3 15 ++# define OMAP_INT_243X_MCBSP2_IRQ 16 ++# define OMAP_INT_243X_MCBSP3_IRQ 17 ++# define OMAP_INT_243X_MCBSP4_IRQ 18 ++# define OMAP_INT_243X_MCBSP5_IRQ 19 ++# define OMAP_INT_24XX_GPMC_IRQ 20 ++# define OMAP_INT_24XX_GUFFAW_IRQ 21 ++# define OMAP_INT_24XX_IVA_IRQ 22 ++# define OMAP_INT_24XX_EAC_IRQ 23 + # define OMAP_INT_24XX_CAM_IRQ 24 + # define OMAP_INT_24XX_DSS_IRQ 25 + # define OMAP_INT_24XX_MAIL_U0_MPU 26 +@@ -308,8 +354,10 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, + # define OMAP_INT_24XX_GPIO_BANK2 30 + # define OMAP_INT_24XX_GPIO_BANK3 31 + # define OMAP_INT_24XX_GPIO_BANK4 32 +-# define OMAP_INT_24XX_GPIO_BANK5 33 ++# define OMAP_INT_243X_GPIO_BANK5 33 + # define OMAP_INT_24XX_MAIL_U3_MPU 34 ++# define OMAP_INT_24XX_WDT3 35 ++# define OMAP_INT_24XX_WDT4 36 + # define OMAP_INT_24XX_GPTIMER1 37 + # define OMAP_INT_24XX_GPTIMER2 38 + # define OMAP_INT_24XX_GPTIMER3 39 +@@ -322,10 +370,24 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, + # define OMAP_INT_24XX_GPTIMER10 46 + # define OMAP_INT_24XX_GPTIMER11 47 + # define OMAP_INT_24XX_GPTIMER12 48 ++# define OMAP_INT_24XX_PKA_IRQ 50 ++# define OMAP_INT_24XX_SHA1MD5_IRQ 51 ++# define OMAP_INT_24XX_RNG_IRQ 52 ++# define OMAP_INT_24XX_MG_IRQ 53 ++# define OMAP_INT_24XX_I2C1_IRQ 56 ++# define OMAP_INT_24XX_I2C2_IRQ 57 + # define OMAP_INT_24XX_MCBSP1_IRQ_TX 59 + # define OMAP_INT_24XX_MCBSP1_IRQ_RX 60 + # define OMAP_INT_24XX_MCBSP2_IRQ_TX 62 + # define OMAP_INT_24XX_MCBSP2_IRQ_RX 63 ++# define OMAP_INT_243X_MCBSP1_IRQ 64 ++# define OMAP_INT_24XX_MCSPI1_IRQ 65 ++# define OMAP_INT_24XX_MCSPI2_IRQ 66 ++# define OMAP_INT_24XX_SSI1_IRQ0 67 ++# define OMAP_INT_24XX_SSI1_IRQ1 68 ++# define OMAP_INT_24XX_SSI2_IRQ0 69 ++# define OMAP_INT_24XX_SSI2_IRQ1 70 ++# define OMAP_INT_24XX_SSI_GDD_IRQ 71 + # define OMAP_INT_24XX_UART1_IRQ 72 + # define OMAP_INT_24XX_UART2_IRQ 73 + # define OMAP_INT_24XX_UART3_IRQ 74 +@@ -335,10 +397,15 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, + # define OMAP_INT_24XX_USB_IRQ_HGEN 78 + # define OMAP_INT_24XX_USB_IRQ_HSOF 79 + # define OMAP_INT_24XX_USB_IRQ_OTG 80 ++# define OMAP_INT_24XX_VLYNQ_IRQ 81 + # define OMAP_INT_24XX_MMC_IRQ 83 ++# define OMAP_INT_24XX_MS_IRQ 84 ++# define OMAP_INT_24XX_FAC_IRQ 85 ++# define OMAP_INT_24XX_MCSPI3_IRQ 91 + # define OMAP_INT_243X_HS_USB_MC 92 + # define OMAP_INT_243X_HS_USB_DMA 93 + # define OMAP_INT_243X_CARKIT 94 ++# define OMAP_INT_34XX_GPTIMER12 95 + + /* omap_dma.c */ + enum omap_dma_model { +@@ -352,6 +419,9 @@ struct omap_dma_s; + struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, + qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk, + enum omap_dma_model model); ++struct omap_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs, ++ struct omap_mpu_state_s *mpu, int fifo, ++ int chans, omap_clk iclk, omap_clk fclk); + void omap_dma_reset(struct omap_dma_s *s); + + struct dma_irq_map { +@@ -367,7 +437,7 @@ enum omap_dma_port { + tipb, + local, /* omap16xx: ocp_t2 */ + tipb_mpui, +- omap_dma_port_last, ++ __omap_dma_port_last, + }; + + typedef enum { +@@ -488,11 +558,83 @@ struct omap_dma_lcd_channel_s { + # define OMAP_DMA_MMC2_RX 55 + # define OMAP_DMA_CRYPTO_DES_OUT 56 + ++/* ++ * DMA request numbers for the OMAP2 ++ */ ++# define OMAP24XX_DMA_NO_DEVICE 0 ++# define OMAP24XX_DMA_XTI_DMA 1 /* Not in OMAP2420 */ ++# define OMAP24XX_DMA_EXT_DMAREQ0 2 ++# define OMAP24XX_DMA_EXT_DMAREQ1 3 ++# define OMAP24XX_DMA_GPMC 4 ++# define OMAP24XX_DMA_GFX 5 /* Not in OMAP2420 */ ++# define OMAP24XX_DMA_DSS 6 ++# define OMAP24XX_DMA_VLYNQ_TX 7 /* Not in OMAP2420 */ ++# define OMAP24XX_DMA_CWT 8 /* Not in OMAP2420 */ ++# define OMAP24XX_DMA_AES_TX 9 /* Not in OMAP2420 */ ++# define OMAP24XX_DMA_AES_RX 10 /* Not in OMAP2420 */ ++# define OMAP24XX_DMA_DES_TX 11 /* Not in OMAP2420 */ ++# define OMAP24XX_DMA_DES_RX 12 /* Not in OMAP2420 */ ++# define OMAP24XX_DMA_SHA1MD5_RX 13 /* Not in OMAP2420 */ ++# define OMAP24XX_DMA_EXT_DMAREQ2 14 ++# define OMAP24XX_DMA_EXT_DMAREQ3 15 ++# define OMAP24XX_DMA_EXT_DMAREQ4 16 ++# define OMAP24XX_DMA_EAC_AC_RD 17 ++# define OMAP24XX_DMA_EAC_AC_WR 18 ++# define OMAP24XX_DMA_EAC_MD_UL_RD 19 ++# define OMAP24XX_DMA_EAC_MD_UL_WR 20 ++# define OMAP24XX_DMA_EAC_MD_DL_RD 21 ++# define OMAP24XX_DMA_EAC_MD_DL_WR 22 ++# define OMAP24XX_DMA_EAC_BT_UL_RD 23 ++# define OMAP24XX_DMA_EAC_BT_UL_WR 24 ++# define OMAP24XX_DMA_EAC_BT_DL_RD 25 ++# define OMAP24XX_DMA_EAC_BT_DL_WR 26 ++# define OMAP24XX_DMA_I2C1_TX 27 ++# define OMAP24XX_DMA_I2C1_RX 28 ++# define OMAP24XX_DMA_I2C2_TX 29 ++# define OMAP24XX_DMA_I2C2_RX 30 ++# define OMAP24XX_DMA_MCBSP1_TX 31 ++# define OMAP24XX_DMA_MCBSP1_RX 32 ++# define OMAP24XX_DMA_MCBSP2_TX 33 ++# define OMAP24XX_DMA_MCBSP2_RX 34 ++# define OMAP24XX_DMA_SPI1_TX0 35 ++# define OMAP24XX_DMA_SPI1_RX0 36 ++# define OMAP24XX_DMA_SPI1_TX1 37 ++# define OMAP24XX_DMA_SPI1_RX1 38 ++# define OMAP24XX_DMA_SPI1_TX2 39 ++# define OMAP24XX_DMA_SPI1_RX2 40 ++# define OMAP24XX_DMA_SPI1_TX3 41 ++# define OMAP24XX_DMA_SPI1_RX3 42 ++# define OMAP24XX_DMA_SPI2_TX0 43 ++# define OMAP24XX_DMA_SPI2_RX0 44 ++# define OMAP24XX_DMA_SPI2_TX1 45 ++# define OMAP24XX_DMA_SPI2_RX1 46 ++ ++# define OMAP24XX_DMA_UART1_TX 49 ++# define OMAP24XX_DMA_UART1_RX 50 ++# define OMAP24XX_DMA_UART2_TX 51 ++# define OMAP24XX_DMA_UART2_RX 52 ++# define OMAP24XX_DMA_UART3_TX 53 ++# define OMAP24XX_DMA_UART3_RX 54 ++# define OMAP24XX_DMA_USB_W2FC_TX0 55 ++# define OMAP24XX_DMA_USB_W2FC_RX0 56 ++# define OMAP24XX_DMA_USB_W2FC_TX1 57 ++# define OMAP24XX_DMA_USB_W2FC_RX1 58 ++# define OMAP24XX_DMA_USB_W2FC_TX2 59 ++# define OMAP24XX_DMA_USB_W2FC_RX2 60 ++# define OMAP24XX_DMA_MMC1_TX 61 ++# define OMAP24XX_DMA_MMC1_RX 62 ++# define OMAP24XX_DMA_MS 63 /* Not in OMAP2420 */ ++# define OMAP24XX_DMA_EXT_DMAREQ5 64 ++ + /* omap[123].c */ + struct omap_mpu_timer_s; + struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base, + qemu_irq irq, omap_clk clk); + ++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); ++ + struct omap_watchdog_timer_s; + struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base, + qemu_irq irq, omap_clk clk); +@@ -501,13 +643,21 @@ struct omap_32khz_timer_s; + struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base, + qemu_irq irq, omap_clk clk); + ++void omap_synctimer_init(struct omap_target_agent_s *ta, ++ struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk); ++ + struct omap_tipb_bridge_s; + struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base, + qemu_irq abort_irq, omap_clk clk); + + struct omap_uart_s; + struct omap_uart_s *omap_uart_init(target_phys_addr_t base, +- qemu_irq irq, omap_clk clk, CharDriverState *chr); ++ qemu_irq irq, omap_clk fclk, omap_clk iclk, ++ qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr); ++struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta, ++ qemu_irq irq, omap_clk fclk, omap_clk iclk, ++ qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr); ++void omap_uart_reset(struct omap_uart_s *s); + + struct omap_mpuio_s; + struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base, +@@ -523,6 +673,12 @@ struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base, + qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s); + void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler); + ++struct omap_gpif_s; ++struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta, ++ qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules); ++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); ++ + struct uwire_slave_s { + uint16_t (*receive)(void *opaque); + void (*send)(void *opaque, uint16_t data); +@@ -534,6 +690,13 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base, + void omap_uwire_attach(struct omap_uwire_s *s, + struct uwire_slave_s *slave, int chipselect); + ++struct omap_mcspi_s; ++struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum, ++ qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk); ++void omap_mcspi_attach(struct omap_mcspi_s *s, ++ uint32_t (*txrx)(void *opaque, uint32_t), void *opaque, ++ int chipselect); ++ + struct omap_rtc_s; + struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base, + qemu_irq *irq, omap_clk clk); +@@ -570,6 +733,9 @@ void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave); + struct omap_lpg_s; + struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk); + ++void omap_tap_init(struct omap_target_agent_s *ta, ++ struct omap_mpu_state_s *mpu); ++ + /* omap_lcdc.c */ + struct omap_lcd_panel_s; + void omap_lcdc_reset(struct omap_lcd_panel_s *s); +@@ -577,13 +743,33 @@ struct omap_lcd_panel_s *omap_lcdc_init(target_phys_addr_t base, qemu_irq irq, + struct omap_dma_lcd_channel_s *dma, DisplayState *ds, + ram_addr_t imif_base, ram_addr_t emiff_base, omap_clk clk); + ++/* omap_dss.c */ ++struct rfbi_chip_s { ++ void *opaque; ++ void (*write)(void *opaque, int dc, uint16_t value); ++ void (*block)(void *opaque, int dc, void *buf, size_t len, int pitch); ++ uint16_t (*read)(void *opaque, int dc); ++}; ++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, DisplayState *ds, ++ qemu_irq irq, qemu_irq drq, ++ omap_clk fck1, omap_clk fck2, omap_clk ck54m, ++ omap_clk ick1, omap_clk ick2); ++void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip); ++ + /* omap_mmc.c */ + struct omap_mmc_s; + struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base, + BlockDriverState *bd, + qemu_irq irq, qemu_irq dma[], omap_clk clk); ++struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta, ++ BlockDriverState *bd, qemu_irq irq, qemu_irq dma[], ++ omap_clk fclk, omap_clk iclk); + void omap_mmc_reset(struct omap_mmc_s *s); + void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover); ++void omap_mmc_enable(struct omap_mmc_s *s, int enable); + + /* omap_i2c.c */ + struct omap_i2c_s; +@@ -596,14 +782,37 @@ 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_omap1710(cpu) (cpu->mpu_model == omap1710) ++# define cpu_is_omap2410(cpu) (cpu->mpu_model == omap2410) ++# 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_omap15xx(cpu) \ + (cpu_is_omap310(cpu) || cpu_is_omap1510(cpu)) +-# define cpu_class_omap1(cpu) 1 ++# define cpu_is_omap16xx(cpu) \ ++ (cpu_is_omap1610(cpu) || cpu_is_omap1710(cpu)) ++# define cpu_is_omap24xx(cpu) \ ++ (cpu_is_omap2410(cpu) || cpu_is_omap2420(cpu) || cpu_is_omap2430(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) + + struct omap_mpu_state_s { +- enum omap1_mpu_model { ++ enum omap_mpu_model { + omap310, + omap1510, ++ omap1610, ++ omap1710, ++ omap2410, ++ omap2420, ++ omap2422, ++ omap2423, ++ omap2430, ++ omap3430, + } mpu_model; + + CPUState *env; +@@ -620,7 +829,7 @@ struct omap_mpu_state_s { + target_phys_addr_t offset, uint32_t value); + int (*addr_valid)(struct omap_mpu_state_s *s, + target_phys_addr_t addr); +- } port[omap_dma_port_last]; ++ } port[__omap_dma_port_last]; + + unsigned long sdram_size; + unsigned long sram_size; +@@ -656,7 +865,7 @@ struct omap_mpu_state_s { + omap_clk clk; + } pwt; + +- struct omap_i2c_s *i2c; ++ struct omap_i2c_s *i2c[2]; + + struct omap_rtc_s *rtc; + +@@ -722,7 +931,38 @@ struct omap_mpu_state_s { + uint16_t dsp_idlect2; + uint16_t dsp_rstct2; + } clkm; +-} *omap310_mpu_init(unsigned long sdram_size, ++ ++ /* OMAP2-only peripherals */ ++ struct omap_l4_s *l4; ++ ++ struct omap_gp_timer_s *gptimer[12]; ++ ++ target_phys_addr_t tap_base; ++ ++ struct omap_synctimer_s { ++ target_phys_addr_t base; ++ uint32_t val; ++ uint16_t readh; ++ } synctimer; ++ ++ struct omap_prcm_s *prcm; ++ struct omap_sdrc_s *sdrc; ++ struct omap_gpmc_s *gpmc; ++ struct omap_sysctl_s *sysc; ++ ++ struct omap_gpif_s *gpif; ++ ++ struct omap_mcspi_s *mcspi[2]; ++ ++ struct omap_dss_s *dss; ++}; ++ ++/* omap1.c */ ++struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, ++ DisplayState *ds, const char *core); ++ ++/* omap2.c */ ++struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size, + DisplayState *ds, const char *core); + + # if TARGET_PHYS_ADDR_BITS == 32 +@@ -743,24 +983,46 @@ uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr); + void omap_badwidth_write32(void *opaque, target_phys_addr_t addr, + uint32_t value); + ++void omap_mpu_wakeup(void *opaque, int irq, int req); ++ + # define OMAP_BAD_REG(paddr) \ +- printf("%s: Bad register " OMAP_FMT_plx "\n", __FUNCTION__, paddr) ++ fprintf(stderr, "%s: Bad register " OMAP_FMT_plx "\n", \ ++ __FUNCTION__, paddr) + # define OMAP_RO_REG(paddr) \ +- printf("%s: Read-only register " OMAP_FMT_plx "\n", \ ++ fprintf(stderr, "%s: Read-only register " OMAP_FMT_plx "\n", \ + __FUNCTION__, paddr) + ++/* OMAP-specific Linux bootloader tags for the ATAG_BOARD area ++ (Board-specifc tags are not here) */ ++#define OMAP_TAG_CLOCK 0x4f01 ++#define OMAP_TAG_MMC 0x4f02 ++#define OMAP_TAG_SERIAL_CONSOLE 0x4f03 ++#define OMAP_TAG_USB 0x4f04 ++#define OMAP_TAG_LCD 0x4f05 ++#define OMAP_TAG_GPIO_SWITCH 0x4f06 ++#define OMAP_TAG_UART 0x4f07 ++#define OMAP_TAG_FBMEM 0x4f08 ++#define OMAP_TAG_STI_CONSOLE 0x4f09 ++#define OMAP_TAG_CAMERA_SENSOR 0x4f0a ++#define OMAP_TAG_PARTITION 0x4f0b ++#define OMAP_TAG_TEA5761 0x4f10 ++#define OMAP_TAG_TMP105 0x4f11 ++#define OMAP_TAG_BOOT_REASON 0x4f80 ++#define OMAP_TAG_FLASH_PART_STR 0x4f81 ++#define OMAP_TAG_VERSION_STR 0x4f82 ++ + # define TCMI_VERBOSE 1 + //# define MEM_VERBOSE 1 + + # ifdef TCMI_VERBOSE + # define OMAP_8B_REG(paddr) \ +- printf("%s: 8-bit register " OMAP_FMT_plx "\n", \ ++ fprintf(stderr, "%s: 8-bit register " OMAP_FMT_plx "\n", \ + __FUNCTION__, paddr) + # define OMAP_16B_REG(paddr) \ +- printf("%s: 16-bit register " OMAP_FMT_plx "\n", \ ++ fprintf(stderr, "%s: 16-bit register " OMAP_FMT_plx "\n", \ + __FUNCTION__, paddr) + # define OMAP_32B_REG(paddr) \ +- printf("%s: 32-bit register " OMAP_FMT_plx "\n", \ ++ fprintf(stderr, "%s: 32-bit register " OMAP_FMT_plx "\n", \ + __FUNCTION__, paddr) + # else + # define OMAP_8B_REG(paddr) +@@ -863,10 +1125,4 @@ inline static int debug_register_io_memory(int io_index, + # define cpu_register_io_memory debug_register_io_memory + # endif + +-/* Not really omap specific, but is the only thing that uses the +- uwire interface. */ +-/* tsc210x.c */ +-struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio); +-struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip); +- + #endif /* hw_omap_h */ +diff --git a/hw/omap1.c b/hw/omap1.c +index 3888e80..d81cbce 100644 +--- a/hw/omap1.c ++++ b/hw/omap1.c +@@ -23,10 +23,11 @@ + #include "omap.h" + #include "sysemu.h" + #include "qemu-timer.h" ++#include "qemu-char.h" + /* We use pc-style serial ports. */ + #include "pc.h" + +-/* Should signal the TCMI */ ++/* Should signal the TCMI/GPMC */ + uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr) + { + uint8_t ret; +@@ -86,6 +87,7 @@ struct omap_intr_handler_bank_s { + uint32_t mask; + uint32_t fiq; + uint32_t sens_edge; ++ uint32_t swi; + unsigned char priority[32]; + }; + +@@ -94,11 +96,14 @@ struct omap_intr_handler_s { + qemu_irq parent_intr[2]; + target_phys_addr_t base; + unsigned char nbanks; ++ int level_only; + + /* state */ + uint32_t new_agr[2]; + int sir_intr[2]; +- struct omap_intr_handler_bank_s banks[]; ++ int autoidle; ++ uint32_t mask; ++ struct omap_intr_handler_bank_s bank[]; + }; + + static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq) +@@ -113,11 +118,11 @@ static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq) + * If all interrupts have the same priority, the default order is IRQ_N, + * IRQ_N-1,...,IRQ_0. */ + for (j = 0; j < s->nbanks; ++j) { +- level = s->banks[j].irqs & ~s->banks[j].mask & +- (is_fiq ? s->banks[j].fiq : ~s->banks[j].fiq); ++ level = s->bank[j].irqs & ~s->bank[j].mask & ++ (is_fiq ? s->bank[j].fiq : ~s->bank[j].fiq); + for (f = ffs(level), i = f - 1, level >>= f - 1; f; i += f, + level >>= f) { +- p = s->banks[j].priority[i]; ++ p = s->bank[j].priority[i]; + if (p <= p_intr) { + p_intr = p; + sir_intr = 32 * j + i; +@@ -134,10 +139,10 @@ static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq) + uint32_t has_intr = 0; + + for (i = 0; i < s->nbanks; ++i) +- has_intr |= s->banks[i].irqs & ~s->banks[i].mask & +- (is_fiq ? s->banks[i].fiq : ~s->banks[i].fiq); ++ has_intr |= s->bank[i].irqs & ~s->bank[i].mask & ++ (is_fiq ? s->bank[i].fiq : ~s->bank[i].fiq); + +- if (s->new_agr[is_fiq] && has_intr) { ++ if (s->new_agr[is_fiq] & has_intr & s->mask) { + s->new_agr[is_fiq] = 0; + omap_inth_sir_update(s, is_fiq); + qemu_set_irq(s->parent_intr[is_fiq], 1); +@@ -152,13 +157,13 @@ static void omap_set_intr(void *opaque, int irq, int req) + struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque; + uint32_t rise; + +- struct omap_intr_handler_bank_s *bank = &ih->banks[irq >> 5]; ++ struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5]; + int n = irq & 31; + + if (req) { + rise = ~bank->irqs & (1 << n); + if (~bank->sens_edge & (1 << n)) +- rise &= ~bank->inputs & (1 << n); ++ rise &= ~bank->inputs; + + bank->inputs |= (1 << n); + if (rise) { +@@ -173,13 +178,33 @@ static void omap_set_intr(void *opaque, int irq, int req) + } + } + ++/* Simplified version with no edge detection */ ++static void omap_set_intr_noedge(void *opaque, int irq, int req) ++{ ++ struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque; ++ uint32_t rise; ++ ++ struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5]; ++ int n = irq & 31; ++ ++ if (req) { ++ rise = ~bank->inputs & (1 << n); ++ if (rise) { ++ bank->irqs |= bank->inputs |= rise; ++ omap_inth_update(ih, 0); ++ omap_inth_update(ih, 1); ++ } ++ } else ++ bank->irqs = (bank->inputs &= ~(1 << n)) | bank->swi; ++} ++ + static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr) + { + struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; + int i, offset = addr - s->base; + int bank_no = offset >> 8; + int line_no; +- struct omap_intr_handler_bank_s *bank = &s->banks[bank_no]; ++ struct omap_intr_handler_bank_s *bank = &s->bank[bank_no]; + offset &= 0xff; + + switch (offset) { +@@ -194,7 +219,7 @@ static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr) + if (bank_no != 0) + break; + line_no = s->sir_intr[(offset - 0x10) >> 2]; +- bank = &s->banks[line_no >> 5]; ++ bank = &s->bank[line_no >> 5]; + i = line_no & 31; + if (((bank->sens_edge >> i) & 1) == INT_FALLING_EDGE) + bank->irqs &= ~(1 << i); +@@ -256,7 +281,7 @@ static void omap_inth_write(void *opaque, target_phys_addr_t addr, + struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; + int i, offset = addr - s->base; + int bank_no = offset >> 8; +- struct omap_intr_handler_bank_s *bank = &s->banks[bank_no]; ++ struct omap_intr_handler_bank_s *bank = &s->bank[bank_no]; + offset &= 0xff; + + switch (offset) { +@@ -360,25 +385,31 @@ void omap_inth_reset(struct omap_intr_handler_s *s) + int i; + + for (i = 0; i < s->nbanks; ++i){ +- s->banks[i].irqs = 0x00000000; +- s->banks[i].mask = 0xffffffff; +- s->banks[i].sens_edge = 0x00000000; +- s->banks[i].fiq = 0x00000000; +- s->banks[i].inputs = 0x00000000; +- memset(s->banks[i].priority, 0, sizeof(s->banks[i].priority)); ++ s->bank[i].irqs = 0x00000000; ++ s->bank[i].mask = 0xffffffff; ++ s->bank[i].sens_edge = 0x00000000; ++ s->bank[i].fiq = 0x00000000; ++ s->bank[i].inputs = 0x00000000; ++ s->bank[i].swi = 0x00000000; ++ memset(s->bank[i].priority, 0, sizeof(s->bank[i].priority)); ++ ++ if (s->level_only) ++ s->bank[i].sens_edge = 0xffffffff; + } + + s->new_agr[0] = ~0; + s->new_agr[1] = ~0; + s->sir_intr[0] = 0; + s->sir_intr[1] = 0; ++ s->autoidle = 0; ++ s->mask = ~0; + + qemu_set_irq(s->parent_intr[0], 0); + qemu_set_irq(s->parent_intr[1], 0); + } + + struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base, +- unsigned long size, unsigned char nbanks, ++ unsigned long size, unsigned char nbanks, qemu_irq **pins, + qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk) + { + int iomemtype; +@@ -391,6 +422,8 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base, + s->base = base; + s->nbanks = nbanks; + s->pins = qemu_allocate_irqs(omap_set_intr, s, nbanks * 32); ++ if (pins) ++ *pins = s->pins; + + omap_inth_reset(s); + +@@ -401,6 +434,227 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base, + return s; + } + ++static uint32_t omap2_inth_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; ++ int offset = addr - s->base; ++ int bank_no, line_no; ++ struct omap_intr_handler_bank_s *bank = 0; ++ ++ if ((offset & 0xf80) == 0x80) { ++ bank_no = (offset & 0x60) >> 5; ++ if (bank_no < s->nbanks) { ++ offset &= ~0x60; ++ bank = &s->bank[bank_no]; ++ } ++ } ++ ++ switch (offset) { ++ case 0x00: /* INTC_REVISION */ ++ return 0x21; ++ ++ case 0x10: /* INTC_SYSCONFIG */ ++ return (s->autoidle >> 2) & 1; ++ ++ case 0x14: /* INTC_SYSSTATUS */ ++ return 1; /* RESETDONE */ ++ ++ case 0x40: /* INTC_SIR_IRQ */ ++ return s->sir_intr[0]; ++ ++ case 0x44: /* INTC_SIR_FIQ */ ++ return s->sir_intr[1]; ++ ++ case 0x48: /* INTC_CONTROL */ ++ return (!s->mask) << 2; /* GLOBALMASK */ ++ ++ case 0x4c: /* INTC_PROTECTION */ ++ return 0; ++ ++ case 0x50: /* INTC_IDLE */ ++ return s->autoidle & 3; ++ ++ /* Per-bank registers */ ++ case 0x80: /* INTC_ITR */ ++ return bank->inputs; ++ ++ case 0x84: /* INTC_MIR */ ++ return bank->mask; ++ ++ case 0x88: /* INTC_MIR_CLEAR */ ++ case 0x8c: /* INTC_MIR_SET */ ++ return 0; ++ ++ case 0x90: /* INTC_ISR_SET */ ++ return bank->swi; ++ ++ case 0x94: /* INTC_ISR_CLEAR */ ++ return 0; ++ ++ case 0x98: /* INTC_PENDING_IRQ */ ++ return bank->irqs & ~bank->mask & ~bank->fiq; ++ ++ case 0x9c: /* INTC_PENDING_FIQ */ ++ return bank->irqs & ~bank->mask & bank->fiq; ++ ++ /* Per-line registers */ ++ case 0x100 ... 0x300: /* INTC_ILR */ ++ bank_no = (offset - 0x100) >> 7; ++ if (bank_no > s->nbanks) ++ break; ++ bank = &s->bank[bank_no]; ++ line_no = (offset & 0x7f) >> 2; ++ return (bank->priority[line_no] << 2) | ++ ((bank->fiq >> line_no) & 1); ++ } ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap2_inth_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; ++ int offset = addr - s->base; ++ int bank_no, line_no; ++ struct omap_intr_handler_bank_s *bank = 0; ++ ++ if ((offset & 0xf80) == 0x80) { ++ bank_no = (offset & 0x60) >> 5; ++ if (bank_no < s->nbanks) { ++ offset &= ~0x60; ++ bank = &s->bank[bank_no]; ++ } ++ } ++ ++ switch (offset) { ++ case 0x10: /* INTC_SYSCONFIG */ ++ s->autoidle &= 4; ++ s->autoidle |= (value & 1) << 2; ++ if (value & 2) /* SOFTRESET */ ++ omap_inth_reset(s); ++ return; ++ ++ case 0x48: /* INTC_CONTROL */ ++ s->mask = (value & 4) ? 0 : ~0; /* GLOBALMASK */ ++ if (value & 2) { /* NEWFIQAGR */ ++ qemu_set_irq(s->parent_intr[1], 0); ++ s->new_agr[1] = ~0; ++ omap_inth_update(s, 1); ++ } ++ if (value & 1) { /* NEWIRQAGR */ ++ qemu_set_irq(s->parent_intr[0], 0); ++ s->new_agr[0] = ~0; ++ omap_inth_update(s, 0); ++ } ++ return; ++ ++ case 0x4c: /* INTC_PROTECTION */ ++ /* TODO: Make a bitmap (or sizeof(char)map) of access privileges ++ * for every register, see Chapter 3 and 4 for privileged mode. */ ++ if (value & 1) ++ fprintf(stderr, "%s: protection mode enable attempt\n", ++ __FUNCTION__); ++ return; ++ ++ case 0x50: /* INTC_IDLE */ ++ s->autoidle &= ~3; ++ s->autoidle |= value & 3; ++ return; ++ ++ /* Per-bank registers */ ++ case 0x84: /* INTC_MIR */ ++ bank->mask = value; ++ omap_inth_update(s, 0); ++ omap_inth_update(s, 1); ++ return; ++ ++ case 0x88: /* INTC_MIR_CLEAR */ ++ bank->mask &= ~value; ++ omap_inth_update(s, 0); ++ omap_inth_update(s, 1); ++ return; ++ ++ case 0x8c: /* INTC_MIR_SET */ ++ bank->mask |= value; ++ return; ++ ++ case 0x90: /* INTC_ISR_SET */ ++ bank->irqs |= bank->swi |= value; ++ omap_inth_update(s, 0); ++ omap_inth_update(s, 1); ++ return; ++ ++ case 0x94: /* INTC_ISR_CLEAR */ ++ bank->swi &= ~value; ++ bank->irqs = bank->swi & bank->inputs; ++ return; ++ ++ /* Per-line registers */ ++ case 0x100 ... 0x300: /* INTC_ILR */ ++ bank_no = (offset - 0x100) >> 7; ++ if (bank_no > s->nbanks) ++ break; ++ bank = &s->bank[bank_no]; ++ line_no = (offset & 0x7f) >> 2; ++ bank->priority[line_no] = (value >> 2) & 0x3f; ++ bank->fiq &= ~(1 << line_no); ++ bank->fiq |= (value & 1) << line_no; ++ return; ++ ++ case 0x00: /* INTC_REVISION */ ++ case 0x14: /* INTC_SYSSTATUS */ ++ case 0x40: /* INTC_SIR_IRQ */ ++ case 0x44: /* INTC_SIR_FIQ */ ++ case 0x80: /* INTC_ITR */ ++ case 0x98: /* INTC_PENDING_IRQ */ ++ case 0x9c: /* INTC_PENDING_FIQ */ ++ OMAP_RO_REG(addr); ++ return; ++ } ++ OMAP_BAD_REG(addr); ++} ++ ++static CPUReadMemoryFunc *omap2_inth_readfn[] = { ++ omap_badwidth_read32, ++ omap_badwidth_read32, ++ omap2_inth_read, ++}; ++ ++static CPUWriteMemoryFunc *omap2_inth_writefn[] = { ++ omap2_inth_write, ++ omap2_inth_write, ++ omap2_inth_write, ++}; ++ ++struct omap_intr_handler_s *omap2_inth_init(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) ++{ ++ int iomemtype; ++ struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) ++ qemu_mallocz(sizeof(struct omap_intr_handler_s) + ++ sizeof(struct omap_intr_handler_bank_s) * nbanks); ++ ++ s->parent_intr[0] = parent_irq; ++ s->parent_intr[1] = parent_fiq; ++ s->base = base; ++ s->nbanks = nbanks; ++ s->level_only = 1; ++ s->pins = qemu_allocate_irqs(omap_set_intr_noedge, s, nbanks * 32); ++ if (pins) ++ *pins = s->pins; ++ ++ omap_inth_reset(s); ++ ++ iomemtype = cpu_register_io_memory(0, omap2_inth_readfn, ++ omap2_inth_writefn, s); ++ cpu_register_physical_memory(s->base, size, iomemtype); ++ ++ return s; ++} ++ + /* MPU OS timers */ + struct omap_mpu_timer_s { + qemu_irq irq; +@@ -1289,6 +1543,8 @@ static uint32_t omap_id_read(void *opaque, target_phys_addr_t addr) + return 0x03310315; + case omap1510: + return 0x03310115; ++ default: ++ cpu_abort(cpu_single_env, "%s: bad mpu model\n", __FUNCTION__); + } + break; + +@@ -1298,6 +1554,8 @@ static uint32_t omap_id_read(void *opaque, target_phys_addr_t addr) + return 0xfb57402f; + case omap1510: + return 0xfb47002f; ++ default: ++ cpu_abort(cpu_single_env, "%s: bad mpu model\n", __FUNCTION__); + } + break; + } +@@ -1722,19 +1980,116 @@ static void omap_dpll_init(struct dpll_ctl_s *s, target_phys_addr_t base, + /* UARTs */ + struct omap_uart_s { + SerialState *serial; /* TODO */ ++ struct omap_target_agent_s *ta; ++ target_phys_addr_t base; ++ ++ uint8_t eblr; ++ uint8_t syscontrol; ++ uint8_t wkup; ++ uint8_t cfps; + }; + +-static void omap_uart_reset(struct omap_uart_s *s) ++void omap_uart_reset(struct omap_uart_s *s) + { ++ s->eblr = 0x00; ++ s->syscontrol = 0; ++ s->wkup = 0x3f; ++ s->cfps = 0x69; + } + + struct omap_uart_s *omap_uart_init(target_phys_addr_t base, +- qemu_irq irq, omap_clk clk, CharDriverState *chr) ++ qemu_irq irq, omap_clk fclk, omap_clk iclk, ++ qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr) + { + struct omap_uart_s *s = (struct omap_uart_s *) + qemu_mallocz(sizeof(struct omap_uart_s)); +- if (chr) +- s->serial = serial_mm_init(base, 2, irq, chr, 1); ++ ++ s->serial = serial_mm_init(base, 2, irq, chr ?: qemu_chr_open("null"), 1); ++ ++ return s; ++} ++ ++static uint32_t omap_uart_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_uart_s *s = (struct omap_uart_s *) opaque; ++ int offset = addr - s->base; ++ ++ switch (offset) { ++ case 0x48: /* EBLR */ ++ return s->eblr; ++ case 0x50: /* MVR */ ++ return 0x30; ++ case 0x54: /* SYSC */ ++ return s->syscontrol; ++ case 0x58: /* SYSS */ ++ return 1; ++ case 0x5c: /* WER */ ++ return s->wkup; ++ case 0x60: /* CFPS */ ++ return s->cfps; ++ } ++ ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap_uart_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_uart_s *s = (struct omap_uart_s *) opaque; ++ int offset = addr - s->base; ++ ++ switch (offset) { ++ case 0x48: /* EBLR */ ++ s->eblr = value & 0xff; ++ break; ++ case 0x50: /* MVR */ ++ case 0x58: /* SYSS */ ++ OMAP_RO_REG(addr); ++ break; ++ case 0x54: /* SYSC */ ++ s->syscontrol = value & 0x1d; ++ if (value & 2) ++ omap_uart_reset(s); ++ break; ++ case 0x5c: /* WER */ ++ s->wkup = value & 0x7f; ++ break; ++ case 0x60: /* CFPS */ ++ s->cfps = value & 0xff; ++ break; ++ default: ++ OMAP_BAD_REG(addr); ++ } ++} ++ ++static CPUReadMemoryFunc *omap_uart_readfn[] = { ++ omap_uart_read, ++ omap_uart_read, ++ omap_badwidth_read8, ++}; ++ ++static CPUWriteMemoryFunc *omap_uart_writefn[] = { ++ omap_uart_write, ++ omap_uart_write, ++ omap_badwidth_write8, ++}; ++ ++struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta, ++ qemu_irq irq, omap_clk fclk, omap_clk iclk, ++ qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr) ++{ ++ target_phys_addr_t base = omap_l4_attach(ta, 0, 0); ++ struct omap_uart_s *s = omap_uart_init(base, irq, ++ fclk, iclk, txdma, rxdma, chr); ++ int iomemtype = cpu_register_io_memory(0, omap_uart_readfn, ++ omap_uart_writefn, s); ++ ++ s->ta = ta; ++ s->base = base; ++ ++ cpu_register_physical_memory(s->base + 0x20, 0x100, iomemtype); ++ + return s; + } + +@@ -2778,9 +3133,11 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base, + void omap_uwire_attach(struct omap_uwire_s *s, + struct uwire_slave_s *slave, int chipselect) + { +- if (chipselect < 0 || chipselect > 3) +- cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n", __FUNCTION__, +- chipselect); ++ if (chipselect < 0 || chipselect > 3) { ++ fprintf(stderr, "%s: Bad chipselect %i\n", ++ __FUNCTION__, chipselect); ++ exit(-1); ++ } + + s->chip[chipselect] = slave; + } +@@ -4123,7 +4481,7 @@ static void omap_setup_mpui_io(struct omap_mpu_state_s *mpu) + } + + /* General chip reset */ +-static void omap_mpu_reset(void *opaque) ++static void omap1_mpu_reset(void *opaque) + { + struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque; + +@@ -4153,7 +4511,7 @@ static void omap_mpu_reset(void *opaque) + omap_uwire_reset(mpu->microwire); + omap_pwl_reset(mpu); + omap_pwt_reset(mpu); +- omap_i2c_reset(mpu->i2c); ++ omap_i2c_reset(mpu->i2c[0]); + omap_rtc_reset(mpu->rtc); + omap_mcbsp_reset(mpu->mcbsp1); + omap_mcbsp_reset(mpu->mcbsp2); +@@ -4205,7 +4563,7 @@ static void omap_setup_dsp_mapping(const struct omap_map_s *map) + } + } + +-static void omap_mpu_wakeup(void *opaque, int irq, int req) ++void omap_mpu_wakeup(void *opaque, int irq, int req) + { + struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque; + +@@ -4213,7 +4571,7 @@ static void omap_mpu_wakeup(void *opaque, int irq, int req) + cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB); + } + +-static const struct dma_irq_map omap_dma_irq_map[] = { ++static const struct dma_irq_map omap1_dma_irq_map[] = { + { 0, OMAP_INT_DMA_CH0_6 }, + { 0, OMAP_INT_DMA_CH1_7 }, + { 0, OMAP_INT_DMA_CH2_8 }, +@@ -4307,17 +4665,16 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, + omap_clkm_init(0xfffece00, 0xe1008000, s); + + cpu_irq = arm_pic_init_cpu(s->env); +- s->ih[0] = omap_inth_init(0xfffecb00, 0x100, 1, ++ s->ih[0] = omap_inth_init(0xfffecb00, 0x100, 1, &s->irq[0], + cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ], + omap_findclk(s, "arminth_ck")); +- s->ih[1] = omap_inth_init(0xfffe0000, 0x800, 1, ++ s->ih[1] = omap_inth_init(0xfffe0000, 0x800, 1, &s->irq[1], + s->ih[0]->pins[OMAP_INT_15XX_IH2_IRQ], NULL, + omap_findclk(s, "arminth_ck")); +- s->irq[0] = s->ih[0]->pins; +- s->irq[1] = s->ih[1]->pins; + + for (i = 0; i < 6; i ++) +- dma_irqs[i] = s->irq[omap_dma_irq_map[i].ih][omap_dma_irq_map[i].intr]; ++ dma_irqs[i] = ++ s->irq[omap1_dma_irq_map[i].ih][omap1_dma_irq_map[i].intr]; + s->dma = omap_dma_init(0xfffed800, dma_irqs, s->irq[0][OMAP_INT_DMA_LCD], + s, omap_findclk(s, "dma_ck"), omap_dma_3_1); + +@@ -4367,12 +4724,18 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, + + s->uart[0] = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1], + omap_findclk(s, "uart1_ck"), ++ omap_findclk(s, "uart1_ck"), ++ s->drq[OMAP_DMA_UART1_TX], s->drq[OMAP_DMA_UART1_RX], + serial_hds[0]); + s->uart[1] = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2], + omap_findclk(s, "uart2_ck"), ++ omap_findclk(s, "uart2_ck"), ++ s->drq[OMAP_DMA_UART2_TX], s->drq[OMAP_DMA_UART2_RX], + serial_hds[0] ? serial_hds[1] : 0); + s->uart[2] = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3], + omap_findclk(s, "uart3_ck"), ++ omap_findclk(s, "uart3_ck"), ++ s->drq[OMAP_DMA_UART3_TX], s->drq[OMAP_DMA_UART3_RX], + serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0); + + omap_dpll_init(&s->dpll[0], 0xfffecf00, omap_findclk(s, "dpll1")); +@@ -4401,7 +4764,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, + omap_pwl_init(0xfffb5800, s, omap_findclk(s, "armxor_ck")); + omap_pwt_init(0xfffb6000, s, omap_findclk(s, "armxor_ck")); + +- s->i2c = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C], ++ s->i2c[0] = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C], + &s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck")); + + s->rtc = omap_rtc_init(0xfffb4800, &s->irq[1][OMAP_INT_RTC_TIMER], +@@ -4435,7 +4798,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, + omap_setup_dsp_mapping(omap15xx_dsp_mm); + omap_setup_mpui_io(s); + +- qemu_register_reset(omap_mpu_reset, s); ++ qemu_register_reset(omap1_mpu_reset, s); + + return s; + } +diff --git a/hw/omap2.c b/hw/omap2.c +new file mode 100644 +index 0000000..1e51197 +--- /dev/null ++++ b/hw/omap2.c +@@ -0,0 +1,3872 @@ ++/* ++ * TI OMAP processors emulation. ++ * ++ * Copyright (C) 2007-2008 Nokia Corporation ++ * Written by Andrzej Zaborowski ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, 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" ++/* We use pc-style serial ports. */ ++#include "pc.h" ++ ++/* GP timers */ ++struct omap_gp_timer_s { ++ qemu_irq irq; ++ qemu_irq wkup; ++ qemu_irq in; ++ qemu_irq out; ++ omap_clk clk; ++ target_phys_addr_t base; ++ QEMUTimer *timer; ++ QEMUTimer *match; ++ struct omap_target_agent_s *ta; ++ ++ int in_val; ++ int out_val; ++ int64_t time; ++ int64_t rate; ++ int64_t ticks_per_sec; ++ ++ int16_t config; ++ int status; ++ int it_ena; ++ int wu_ena; ++ int enable; ++ int inout; ++ int capt2; ++ int pt; ++ enum { ++ gpt_trigger_none, gpt_trigger_overflow, gpt_trigger_both ++ } trigger; ++ enum { ++ gpt_capture_none, gpt_capture_rising, ++ gpt_capture_falling, gpt_capture_both ++ } capture; ++ int scpwm; ++ int ce; ++ int pre; ++ int ptv; ++ int ar; ++ int st; ++ int posted; ++ uint32_t val; ++ uint32_t load_val; ++ uint32_t capture_val[2]; ++ uint32_t match_val; ++ int capt_num; ++ ++ uint16_t writeh; /* LSB */ ++ uint16_t readh; /* MSB */ ++}; ++ ++#define GPT_TCAR_IT (1 << 2) ++#define GPT_OVF_IT (1 << 1) ++#define GPT_MAT_IT (1 << 0) ++ ++static inline void omap_gp_timer_intr(struct omap_gp_timer_s *timer, int it) ++{ ++ if (timer->it_ena & it) { ++ if (!timer->status) ++ qemu_irq_raise(timer->irq); ++ ++ timer->status |= it; ++ /* Or are the status bits set even when masked? ++ * i.e. is masking applied before or after the status register? */ ++ } ++ ++ if (timer->wu_ena & it) ++ qemu_irq_pulse(timer->wkup); ++} ++ ++static inline void omap_gp_timer_out(struct omap_gp_timer_s *timer, int level) ++{ ++ if (!timer->inout && timer->out_val != level) { ++ timer->out_val = level; ++ qemu_set_irq(timer->out, level); ++ } ++} ++ ++static inline uint32_t omap_gp_timer_read(struct omap_gp_timer_s *timer) ++{ ++ uint64_t distance; ++ ++ if (timer->st && timer->rate) { ++ distance = qemu_get_clock(vm_clock) - timer->time; ++ distance = muldiv64(distance, timer->rate, timer->ticks_per_sec); ++ ++ if (distance >= 0xffffffff - timer->val) ++ return 0xffffffff; ++ else ++ return timer->val + distance; ++ } else ++ return timer->val; ++} ++ ++static inline void omap_gp_timer_sync(struct omap_gp_timer_s *timer) ++{ ++ if (timer->st) { ++ timer->val = omap_gp_timer_read(timer); ++ timer->time = qemu_get_clock(vm_clock); ++ } ++} ++ ++static inline void omap_gp_timer_update(struct omap_gp_timer_s *timer) ++{ ++ int64_t expires, matches; ++ ++ if (timer->st && timer->rate) { ++ 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, ++ timer->ticks_per_sec, timer->rate); ++ qemu_mod_timer(timer->match, timer->time + matches); ++ } else ++ qemu_del_timer(timer->match); ++ } else { ++ qemu_del_timer(timer->timer); ++ qemu_del_timer(timer->match); ++ omap_gp_timer_out(timer, timer->scpwm); ++ } ++} ++ ++static inline void omap_gp_timer_trigger(struct omap_gp_timer_s *timer) ++{ ++ if (timer->pt) ++ /* TODO in overflow-and-match mode if the first event to ++ * occurs is the match, don't toggle. */ ++ omap_gp_timer_out(timer, !timer->out_val); ++ else ++ /* TODO inverted pulse on timer->out_val == 1? */ ++ qemu_irq_pulse(timer->out); ++} ++ ++static void omap_gp_timer_tick(void *opaque) ++{ ++ struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque; ++ ++ if (!timer->ar) { ++ timer->st = 0; ++ timer->val = 0; ++ } else { ++ timer->val = timer->load_val; ++ timer->time = qemu_get_clock(vm_clock); ++ } ++ ++ if (timer->trigger == gpt_trigger_overflow || ++ timer->trigger == gpt_trigger_both) ++ omap_gp_timer_trigger(timer); ++ ++ omap_gp_timer_intr(timer, GPT_OVF_IT); ++ omap_gp_timer_update(timer); ++} ++ ++static void omap_gp_timer_match(void *opaque) ++{ ++ struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque; ++ ++ if (timer->trigger == gpt_trigger_both) ++ omap_gp_timer_trigger(timer); ++ ++ omap_gp_timer_intr(timer, GPT_MAT_IT); ++} ++ ++static void omap_gp_timer_input(void *opaque, int line, int on) ++{ ++ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque; ++ int trigger; ++ ++ switch (s->capture) { ++ default: ++ case gpt_capture_none: ++ trigger = 0; ++ break; ++ case gpt_capture_rising: ++ trigger = !s->in_val && on; ++ break; ++ case gpt_capture_falling: ++ trigger = s->in_val && !on; ++ break; ++ case gpt_capture_both: ++ trigger = (s->in_val == !on); ++ break; ++ } ++ s->in_val = on; ++ ++ if (s->inout && trigger && s->capt_num < 2) { ++ s->capture_val[s->capt_num] = omap_gp_timer_read(s); ++ ++ if (s->capt2 == s->capt_num ++) ++ omap_gp_timer_intr(s, GPT_TCAR_IT); ++ } ++} ++ ++static void omap_gp_timer_clk_update(void *opaque, int line, int on) ++{ ++ struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque; ++ ++ omap_gp_timer_sync(timer); ++ timer->rate = on ? omap_clk_getrate(timer->clk) : 0; ++ omap_gp_timer_update(timer); ++} ++ ++static void omap_gp_timer_clk_setup(struct omap_gp_timer_s *timer) ++{ ++ omap_clk_adduser(timer->clk, ++ qemu_allocate_irqs(omap_gp_timer_clk_update, timer, 1)[0]); ++ timer->rate = omap_clk_getrate(timer->clk); ++} ++ ++static void omap_gp_timer_reset(struct omap_gp_timer_s *s) ++{ ++ s->config = 0x000; ++ s->status = 0; ++ s->it_ena = 0; ++ s->wu_ena = 0; ++ s->inout = 0; ++ s->capt2 = 0; ++ s->capt_num = 0; ++ s->pt = 0; ++ s->trigger = gpt_trigger_none; ++ s->capture = gpt_capture_none; ++ s->scpwm = 0; ++ s->ce = 0; ++ s->pre = 0; ++ s->ptv = 0; ++ s->ar = 0; ++ s->st = 0; ++ s->posted = 1; ++ s->val = 0x00000000; ++ s->load_val = 0x00000000; ++ s->capture_val[0] = 0x00000000; ++ s->capture_val[1] = 0x00000000; ++ s->match_val = 0x00000000; ++ omap_gp_timer_update(s); ++} ++ ++static uint32_t omap_gp_timer_readw(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque; ++ int offset = addr - s->base; ++ ++ switch (offset) { ++ case 0x00: /* TIDR */ ++ return 0x21; ++ ++ case 0x10: /* TIOCP_CFG */ ++ return s->config; ++ ++ case 0x14: /* TISTAT */ ++ /* ??? When's this bit reset? */ ++ return 1; /* RESETDONE */ ++ ++ case 0x18: /* TISR */ ++ return s->status; ++ ++ case 0x1c: /* TIER */ ++ return s->it_ena; ++ ++ case 0x20: /* TWER */ ++ return s->wu_ena; ++ ++ case 0x24: /* TCLR */ ++ return (s->inout << 14) | ++ (s->capt2 << 13) | ++ (s->pt << 12) | ++ (s->trigger << 10) | ++ (s->capture << 8) | ++ (s->scpwm << 7) | ++ (s->ce << 6) | ++ (s->pre << 5) | ++ (s->ptv << 2) | ++ (s->ar << 1) | ++ (s->st << 0); ++ ++ case 0x28: /* TCRR */ ++ return omap_gp_timer_read(s); ++ ++ case 0x2c: /* TLDR */ ++ return s->load_val; ++ ++ case 0x30: /* TTGR */ ++ return 0xffffffff; ++ ++ case 0x34: /* TWPS */ ++ return 0x00000000; /* No posted writes pending. */ ++ ++ case 0x38: /* TMAR */ ++ return s->match_val; ++ ++ case 0x3c: /* TCAR1 */ ++ return s->capture_val[0]; ++ ++ case 0x40: /* TSICR */ ++ return s->posted << 2; ++ ++ case 0x44: /* TCAR2 */ ++ return s->capture_val[1]; ++ } ++ ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static uint32_t omap_gp_timer_readh(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque; ++ uint32_t ret; ++ ++ if (addr & 2) ++ return s->readh; ++ else { ++ ret = omap_gp_timer_readw(opaque, addr); ++ s->readh = ret >> 16; ++ return ret & 0xffff; ++ } ++} ++ ++static CPUReadMemoryFunc *omap_gp_timer_readfn[] = { ++ omap_badwidth_read32, ++ omap_gp_timer_readh, ++ omap_gp_timer_readw, ++}; ++ ++static void omap_gp_timer_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque; ++ int offset = addr - s->base; ++ ++ switch (offset) { ++ case 0x00: /* TIDR */ ++ case 0x14: /* TISTAT */ ++ case 0x34: /* TWPS */ ++ case 0x3c: /* TCAR1 */ ++ case 0x44: /* TCAR2 */ ++ OMAP_RO_REG(addr); ++ break; ++ ++ case 0x10: /* TIOCP_CFG */ ++ s->config = value & 0x33d; ++ if (((value >> 3) & 3) == 3) /* IDLEMODE */ ++ fprintf(stderr, "%s: illegal IDLEMODE value in TIOCP_CFG\n", ++ __FUNCTION__); ++ if (value & 2) /* SOFTRESET */ ++ omap_gp_timer_reset(s); ++ break; ++ ++ case 0x18: /* TISR */ ++ if (value & GPT_TCAR_IT) ++ s->capt_num = 0; ++ if (s->status && !(s->status &= ~value)) ++ qemu_irq_lower(s->irq); ++ break; ++ ++ case 0x1c: /* TIER */ ++ s->it_ena = value & 7; ++ break; ++ ++ case 0x20: /* TWER */ ++ s->wu_ena = value & 7; ++ break; ++ ++ case 0x24: /* TCLR */ ++ omap_gp_timer_sync(s); ++ s->inout = (value >> 14) & 1; ++ s->capt2 = (value >> 13) & 1; ++ s->pt = (value >> 12) & 1; ++ s->trigger = (value >> 10) & 3; ++ if (s->capture == gpt_capture_none && ++ ((value >> 8) & 3) != gpt_capture_none) ++ s->capt_num = 0; ++ s->capture = (value >> 8) & 3; ++ s->scpwm = (value >> 7) & 1; ++ s->ce = (value >> 6) & 1; ++ s->pre = (value >> 5) & 1; ++ s->ptv = (value >> 2) & 7; ++ s->ar = (value >> 1) & 1; ++ s->st = (value >> 0) & 1; ++ if (s->inout && s->trigger != gpt_trigger_none) ++ fprintf(stderr, "%s: GP timer pin must be an output " ++ "for this trigger mode\n", __FUNCTION__); ++ if (!s->inout && s->capture != gpt_capture_none) ++ fprintf(stderr, "%s: GP timer pin must be an input " ++ "for this capture mode\n", __FUNCTION__); ++ if (s->trigger == gpt_trigger_none) ++ omap_gp_timer_out(s, s->scpwm); ++ /* TODO: make sure this doesn't overflow 32-bits */ ++ s->ticks_per_sec = ticks_per_sec << (s->pre ? s->ptv + 1 : 0); ++ omap_gp_timer_update(s); ++ break; ++ ++ case 0x28: /* TCRR */ ++ s->time = qemu_get_clock(vm_clock); ++ s->val = value; ++ omap_gp_timer_update(s); ++ break; ++ ++ case 0x2c: /* TLDR */ ++ s->load_val = value; ++ break; ++ ++ case 0x30: /* TTGR */ ++ s->time = qemu_get_clock(vm_clock); ++ s->val = s->load_val; ++ omap_gp_timer_update(s); ++ break; ++ ++ case 0x38: /* TMAR */ ++ omap_gp_timer_sync(s); ++ s->match_val = value; ++ omap_gp_timer_update(s); ++ break; ++ ++ case 0x40: /* TSICR */ ++ s->posted = (value >> 2) & 1; ++ if (value & 2) /* How much exactly are we supposed to reset? */ ++ omap_gp_timer_reset(s); ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ } ++} ++ ++static void omap_gp_timer_writeh(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque; ++ ++ if (addr & 2) ++ return omap_gp_timer_write(opaque, addr, (value << 16) | s->writeh); ++ else ++ s->writeh = (uint16_t) value; ++} ++ ++static CPUWriteMemoryFunc *omap_gp_timer_writefn[] = { ++ omap_badwidth_write32, ++ omap_gp_timer_writeh, ++ omap_gp_timer_write, ++}; ++ ++struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta, ++ qemu_irq irq, omap_clk fclk, omap_clk iclk) ++{ ++ int iomemtype; ++ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) ++ qemu_mallocz(sizeof(struct omap_gp_timer_s)); ++ ++ s->ta = ta; ++ s->irq = irq; ++ s->clk = fclk; ++ s->timer = qemu_new_timer(vm_clock, omap_gp_timer_tick, s); ++ s->match = qemu_new_timer(vm_clock, omap_gp_timer_match, s); ++ s->in = qemu_allocate_irqs(omap_gp_timer_input, s, 1)[0]; ++ omap_gp_timer_reset(s); ++ omap_gp_timer_clk_setup(s); ++ ++ iomemtype = cpu_register_io_memory(0, omap_gp_timer_readfn, ++ omap_gp_timer_writefn, s); ++ s->base = omap_l4_attach(ta, 0, iomemtype); ++ ++ return s; ++} ++ ++/* 32-kHz Sync Timer of the OMAP2 */ ++static uint32_t omap_synctimer_read(struct omap_synctimer_s *s) { ++ return muldiv64(qemu_get_clock(vm_clock), 0x8000, ticks_per_sec); ++} ++ ++static void omap_synctimer_reset(struct omap_synctimer_s *s) ++{ ++ s->val = omap_synctimer_read(s); ++} ++ ++static uint32_t omap_synctimer_readw(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque; ++ int offset = addr - s->base; ++ ++ switch (offset) { ++ case 0x00: /* 32KSYNCNT_REV */ ++ return 0x21; ++ ++ case 0x10: /* CR */ ++ return omap_synctimer_read(s) - s->val; ++ } ++ ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static uint32_t omap_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; ++ else { ++ ret = omap_synctimer_readw(opaque, addr); ++ s->readh = ret >> 16; ++ return ret & 0xffff; ++ } ++} ++ ++static CPUReadMemoryFunc *omap_synctimer_readfn[] = { ++ omap_badwidth_read32, ++ omap_synctimer_readh, ++ omap_synctimer_readw, ++}; ++ ++static void omap_synctimer_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ OMAP_BAD_REG(addr); ++} ++ ++static CPUWriteMemoryFunc *omap_synctimer_writefn[] = { ++ omap_badwidth_write32, ++ omap_synctimer_write, ++ omap_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); ++ s->base = omap_l4_attach(ta, 0, cpu_register_io_memory(0, ++ omap_synctimer_readfn, omap_synctimer_writefn, s)); ++} ++ ++/* General-Purpose Interface of OMAP2 */ ++struct omap2_gpio_s { ++ target_phys_addr_t base; ++ qemu_irq irq[2]; ++ qemu_irq wkup; ++ qemu_irq *in; ++ qemu_irq handler[32]; ++ ++ uint8_t config[2]; ++ uint32_t inputs; ++ uint32_t outputs; ++ uint32_t dir; ++ uint32_t level[2]; ++ uint32_t edge[2]; ++ uint32_t mask[2]; ++ uint32_t wumask; ++ uint32_t ints[2]; ++ uint32_t debounce; ++ uint8_t delay; ++}; ++ ++static inline void omap_gpio_module_int_update(struct omap2_gpio_s *s, ++ int line) ++{ ++ qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]); ++} ++ ++static void omap_gpio_module_wake(struct omap2_gpio_s *s, int line) ++{ ++ if (!(s->config[0] & (1 << 2))) /* ENAWAKEUP */ ++ return; ++ if (!(s->config[0] & (3 << 3))) /* Force Idle */ ++ return; ++ if (!(s->wumask & (1 << line))) ++ return; ++ ++ qemu_irq_raise(s->wkup); ++} ++ ++static inline void omap_gpio_module_out_update(struct omap2_gpio_s *s, ++ uint32_t diff) ++{ ++ int ln; ++ ++ s->outputs ^= diff; ++ diff &= ~s->dir; ++ while ((ln = ffs(diff))) { ++ ln --; ++ qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1); ++ diff &= ~(1 << ln); ++ } ++} ++ ++static void omap_gpio_module_level_update(struct omap2_gpio_s *s, int line) ++{ ++ s->ints[line] |= s->dir & ++ ((s->inputs & s->level[1]) | (~s->inputs & s->level[0])); ++ omap_gpio_module_int_update(s, line); ++} ++ ++static inline void omap_gpio_module_int(struct omap2_gpio_s *s, int line) ++{ ++ s->ints[0] |= 1 << line; ++ omap_gpio_module_int_update(s, 0); ++ s->ints[1] |= 1 << line; ++ omap_gpio_module_int_update(s, 1); ++ omap_gpio_module_wake(s, line); ++} ++ ++static void omap_gpio_module_set(void *opaque, int line, int level) ++{ ++ struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque; ++ ++ if (level) { ++ if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1])) ++ omap_gpio_module_int(s, line); ++ s->inputs |= 1 << line; ++ } else { ++ if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0])) ++ omap_gpio_module_int(s, line); ++ s->inputs &= ~(1 << line); ++ } ++} ++ ++static void omap_gpio_module_reset(struct omap2_gpio_s *s) ++{ ++ s->config[0] = 0; ++ s->config[1] = 2; ++ s->ints[0] = 0; ++ s->ints[1] = 0; ++ s->mask[0] = 0; ++ s->mask[1] = 0; ++ s->wumask = 0; ++ s->dir = ~0; ++ s->level[0] = 0; ++ s->level[1] = 0; ++ s->edge[0] = 0; ++ s->edge[1] = 0; ++ s->debounce = 0; ++ s->delay = 0; ++} ++ ++static uint32_t omap_gpio_module_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque; ++ int offset = addr - s->base; ++ ++ switch (offset) { ++ case 0x00: /* GPIO_REVISION */ ++ return 0x18; ++ ++ case 0x10: /* GPIO_SYSCONFIG */ ++ return s->config[0]; ++ ++ case 0x14: /* GPIO_SYSSTATUS */ ++ return 0x01; ++ ++ case 0x18: /* GPIO_IRQSTATUS1 */ ++ return s->ints[0]; ++ ++ case 0x1c: /* GPIO_IRQENABLE1 */ ++ case 0x60: /* GPIO_CLEARIRQENABLE1 */ ++ case 0x64: /* GPIO_SETIRQENABLE1 */ ++ return s->mask[0]; ++ ++ case 0x20: /* GPIO_WAKEUPENABLE */ ++ case 0x80: /* GPIO_CLEARWKUENA */ ++ case 0x84: /* GPIO_SETWKUENA */ ++ return s->wumask; ++ ++ case 0x28: /* GPIO_IRQSTATUS2 */ ++ return s->ints[1]; ++ ++ case 0x2c: /* GPIO_IRQENABLE2 */ ++ case 0x70: /* GPIO_CLEARIRQENABLE2 */ ++ case 0x74: /* GPIO_SETIREQNEABLE2 */ ++ return s->mask[1]; ++ ++ case 0x30: /* GPIO_CTRL */ ++ return s->config[1]; ++ ++ case 0x34: /* GPIO_OE */ ++ return s->dir; ++ ++ case 0x38: /* GPIO_DATAIN */ ++ return s->inputs; ++ ++ case 0x3c: /* GPIO_DATAOUT */ ++ case 0x90: /* GPIO_CLEARDATAOUT */ ++ case 0x94: /* GPIO_SETDATAOUT */ ++ return s->outputs; ++ ++ case 0x40: /* GPIO_LEVELDETECT0 */ ++ return s->level[0]; ++ ++ case 0x44: /* GPIO_LEVELDETECT1 */ ++ return s->level[1]; ++ ++ case 0x48: /* GPIO_RISINGDETECT */ ++ return s->edge[0]; ++ ++ case 0x4c: /* GPIO_FALLINGDETECT */ ++ return s->edge[1]; ++ ++ case 0x50: /* GPIO_DEBOUNCENABLE */ ++ return s->debounce; ++ ++ case 0x54: /* GPIO_DEBOUNCINGTIME */ ++ return s->delay; ++ } ++ ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap_gpio_module_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque; ++ int offset = addr - s->base; ++ uint32_t diff; ++ int ln; ++ ++ switch (offset) { ++ case 0x00: /* GPIO_REVISION */ ++ case 0x14: /* GPIO_SYSSTATUS */ ++ case 0x38: /* GPIO_DATAIN */ ++ OMAP_RO_REG(addr); ++ break; ++ ++ case 0x10: /* GPIO_SYSCONFIG */ ++ if (((value >> 3) & 3) == 3) ++ fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__); ++ if (value & 2) ++ omap_gpio_module_reset(s); ++ s->config[0] = value & 0x1d; ++ break; ++ ++ case 0x18: /* GPIO_IRQSTATUS1 */ ++ if (s->ints[0] & value) { ++ s->ints[0] &= ~value; ++ omap_gpio_module_level_update(s, 0); ++ } ++ break; ++ ++ case 0x1c: /* GPIO_IRQENABLE1 */ ++ s->mask[0] = value; ++ omap_gpio_module_int_update(s, 0); ++ break; ++ ++ case 0x20: /* GPIO_WAKEUPENABLE */ ++ s->wumask = value; ++ break; ++ ++ case 0x28: /* GPIO_IRQSTATUS2 */ ++ if (s->ints[1] & value) { ++ s->ints[1] &= ~value; ++ omap_gpio_module_level_update(s, 1); ++ } ++ break; ++ ++ case 0x2c: /* GPIO_IRQENABLE2 */ ++ s->mask[1] = value; ++ omap_gpio_module_int_update(s, 1); ++ break; ++ ++ case 0x30: /* GPIO_CTRL */ ++ s->config[1] = value & 7; ++ break; ++ ++ case 0x34: /* GPIO_OE */ ++ diff = s->outputs & (s->dir ^ value); ++ s->dir = value; ++ ++ value = s->outputs & ~s->dir; ++ while ((ln = ffs(diff))) { ++ diff &= ~(1 <<-- ln); ++ qemu_set_irq(s->handler[ln], (value >> ln) & 1); ++ } ++ ++ omap_gpio_module_level_update(s, 0); ++ omap_gpio_module_level_update(s, 1); ++ break; ++ ++ case 0x3c: /* GPIO_DATAOUT */ ++ omap_gpio_module_out_update(s, s->outputs ^ value); ++ break; ++ ++ case 0x40: /* GPIO_LEVELDETECT0 */ ++ s->level[0] = value; ++ omap_gpio_module_level_update(s, 0); ++ omap_gpio_module_level_update(s, 1); ++ break; ++ ++ case 0x44: /* GPIO_LEVELDETECT1 */ ++ s->level[1] = value; ++ omap_gpio_module_level_update(s, 0); ++ omap_gpio_module_level_update(s, 1); ++ break; ++ ++ case 0x48: /* GPIO_RISINGDETECT */ ++ s->edge[0] = value; ++ break; ++ ++ case 0x4c: /* GPIO_FALLINGDETECT */ ++ s->edge[1] = value; ++ break; ++ ++ case 0x50: /* GPIO_DEBOUNCENABLE */ ++ s->debounce = value; ++ break; ++ ++ case 0x54: /* GPIO_DEBOUNCINGTIME */ ++ s->delay = value; ++ break; ++ ++ case 0x60: /* GPIO_CLEARIRQENABLE1 */ ++ s->mask[0] &= ~value; ++ omap_gpio_module_int_update(s, 0); ++ break; ++ ++ case 0x64: /* GPIO_SETIRQENABLE1 */ ++ s->mask[0] |= value; ++ omap_gpio_module_int_update(s, 0); ++ break; ++ ++ case 0x70: /* GPIO_CLEARIRQENABLE2 */ ++ s->mask[1] &= ~value; ++ omap_gpio_module_int_update(s, 1); ++ break; ++ ++ case 0x74: /* GPIO_SETIREQNEABLE2 */ ++ s->mask[1] |= value; ++ omap_gpio_module_int_update(s, 1); ++ break; ++ ++ case 0x80: /* GPIO_CLEARWKUENA */ ++ s->wumask &= ~value; ++ break; ++ ++ case 0x84: /* GPIO_SETWKUENA */ ++ s->wumask |= value; ++ break; ++ ++ case 0x90: /* GPIO_CLEARDATAOUT */ ++ omap_gpio_module_out_update(s, s->outputs & value); ++ break; ++ ++ case 0x94: /* GPIO_SETDATAOUT */ ++ omap_gpio_module_out_update(s, ~s->outputs & value); ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ return; ++ } ++} ++ ++static uint32_t omap_gpio_module_readp(void *opaque, target_phys_addr_t addr) ++{ ++ return omap_gpio_module_readp(opaque, addr) >> ((addr & 3) << 3); ++} ++ ++static void omap_gpio_module_writep(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque; ++ int offset = addr - s->base; ++ uint32_t cur = 0; ++ uint32_t mask = 0xffff; ++ ++ switch (offset & ~3) { ++ case 0x00: /* GPIO_REVISION */ ++ case 0x14: /* GPIO_SYSSTATUS */ ++ case 0x38: /* GPIO_DATAIN */ ++ OMAP_RO_REG(addr); ++ break; ++ ++ case 0x10: /* GPIO_SYSCONFIG */ ++ case 0x1c: /* GPIO_IRQENABLE1 */ ++ case 0x20: /* GPIO_WAKEUPENABLE */ ++ case 0x2c: /* GPIO_IRQENABLE2 */ ++ case 0x30: /* GPIO_CTRL */ ++ case 0x34: /* GPIO_OE */ ++ case 0x3c: /* GPIO_DATAOUT */ ++ case 0x40: /* GPIO_LEVELDETECT0 */ ++ case 0x44: /* GPIO_LEVELDETECT1 */ ++ case 0x48: /* GPIO_RISINGDETECT */ ++ case 0x4c: /* GPIO_FALLINGDETECT */ ++ case 0x50: /* GPIO_DEBOUNCENABLE */ ++ case 0x54: /* GPIO_DEBOUNCINGTIME */ ++ cur = omap_gpio_module_read(opaque, addr & ~3) & ++ ~(mask << ((addr & 3) << 3)); ++ ++ /* Fall through. */ ++ case 0x18: /* GPIO_IRQSTATUS1 */ ++ case 0x28: /* GPIO_IRQSTATUS2 */ ++ case 0x60: /* GPIO_CLEARIRQENABLE1 */ ++ case 0x64: /* GPIO_SETIRQENABLE1 */ ++ case 0x70: /* GPIO_CLEARIRQENABLE2 */ ++ case 0x74: /* GPIO_SETIREQNEABLE2 */ ++ case 0x80: /* GPIO_CLEARWKUENA */ ++ case 0x84: /* GPIO_SETWKUENA */ ++ case 0x90: /* GPIO_CLEARDATAOUT */ ++ case 0x94: /* GPIO_SETDATAOUT */ ++ value <<= (addr & 3) << 3; ++ omap_gpio_module_write(opaque, addr, cur | value); ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ return; ++ } ++} ++ ++static CPUReadMemoryFunc *omap_gpio_module_readfn[] = { ++ omap_gpio_module_readp, ++ omap_gpio_module_readp, ++ omap_gpio_module_read, ++}; ++ ++static CPUWriteMemoryFunc *omap_gpio_module_writefn[] = { ++ omap_gpio_module_writep, ++ omap_gpio_module_writep, ++ omap_gpio_module_write, ++}; ++ ++static void omap_gpio_module_init(struct omap2_gpio_s *s, ++ struct omap_target_agent_s *ta, int region, ++ qemu_irq mpu, qemu_irq dsp, qemu_irq wkup, ++ omap_clk fclk, omap_clk iclk) ++{ ++ int iomemtype; ++ ++ s->irq[0] = mpu; ++ s->irq[1] = dsp; ++ s->wkup = wkup; ++ s->in = qemu_allocate_irqs(omap_gpio_module_set, s, 32); ++ ++ iomemtype = cpu_register_io_memory(0, omap_gpio_module_readfn, ++ omap_gpio_module_writefn, s); ++ s->base = omap_l4_attach(ta, region, iomemtype); ++} ++ ++struct omap_gpif_s { ++ struct omap2_gpio_s module[5]; ++ int modules; ++ ++ target_phys_addr_t topbase; ++ int autoidle; ++ int gpo; ++}; ++ ++static void omap_gpif_reset(struct omap_gpif_s *s) ++{ ++ int i; ++ ++ for (i = 0; i < s->modules; i ++) ++ omap_gpio_module_reset(s->module + i); ++ ++ s->autoidle = 0; ++ s->gpo = 0; ++} ++ ++static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_gpif_s *s = (struct omap_gpif_s *) opaque; ++ int offset = addr - s->topbase; ++ ++ switch (offset) { ++ case 0x00: /* IPGENERICOCPSPL_REVISION */ ++ return 0x18; ++ ++ case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */ ++ return s->autoidle; ++ ++ case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */ ++ return 0x01; ++ ++ case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */ ++ return 0x00; ++ ++ case 0x40: /* IPGENERICOCPSPL_GPO */ ++ return s->gpo; ++ ++ case 0x50: /* IPGENERICOCPSPL_GPI */ ++ return 0x00; ++ } ++ ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_gpif_s *s = (struct omap_gpif_s *) opaque; ++ int offset = addr - s->topbase; ++ ++ switch (offset) { ++ case 0x00: /* IPGENERICOCPSPL_REVISION */ ++ case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */ ++ case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */ ++ case 0x50: /* IPGENERICOCPSPL_GPI */ ++ OMAP_RO_REG(addr); ++ break; ++ ++ case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */ ++ if (value & (1 << 1)) /* SOFTRESET */ ++ omap_gpif_reset(s); ++ s->autoidle = value & 1; ++ break; ++ ++ case 0x40: /* IPGENERICOCPSPL_GPO */ ++ s->gpo = value & 1; ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ return; ++ } ++} ++ ++static CPUReadMemoryFunc *omap_gpif_top_readfn[] = { ++ omap_gpif_top_read, ++ omap_gpif_top_read, ++ omap_gpif_top_read, ++}; ++ ++static CPUWriteMemoryFunc *omap_gpif_top_writefn[] = { ++ omap_gpif_top_write, ++ omap_gpif_top_write, ++ omap_gpif_top_write, ++}; ++ ++struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta, ++ qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules) ++{ ++ int iomemtype, i; ++ struct omap_gpif_s *s = (struct omap_gpif_s *) ++ qemu_mallocz(sizeof(struct omap_gpif_s)); ++ int region[4] = { 0, 2, 4, 5 }; ++ ++ s->modules = modules; ++ for (i = 0; i < modules; i ++) ++ omap_gpio_module_init(s->module + i, ta, region[i], ++ irq[i], 0, 0, fclk[i], iclk); ++ ++ omap_gpif_reset(s); ++ ++ iomemtype = cpu_register_io_memory(0, omap_gpif_top_readfn, ++ omap_gpif_top_writefn, s); ++ s->topbase = omap_l4_attach(ta, 1, iomemtype); ++ ++ return s; ++} ++ ++qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start) ++{ ++ if (start >= s->modules * 32 || start < 0) ++ cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", ++ __FUNCTION__, start); ++ return s->module[start >> 5].in + (start & 31); ++} ++ ++void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler) ++{ ++ if (line >= s->modules * 32 || line < 0) ++ cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line); ++ s->module[line >> 5].handler[line & 31] = handler; ++} ++ ++/* Multichannel SPI */ ++struct omap_mcspi_s { ++ target_phys_addr_t base; ++ qemu_irq irq; ++ int chnum; ++ ++ uint32_t sysconfig; ++ uint32_t systest; ++ uint32_t irqst; ++ uint32_t irqen; ++ uint32_t wken; ++ uint32_t control; ++ ++ struct omap_mcspi_ch_s { ++ qemu_irq txdrq; ++ qemu_irq rxdrq; ++ uint32_t (*txrx)(void *opaque, uint32_t); ++ void *opaque; ++ ++ uint32_t tx; ++ uint32_t rx; ++ ++ uint32_t config; ++ uint32_t status; ++ uint32_t control; ++ } ch[4]; ++}; ++ ++static inline void omap_mcspi_interrupt_update(struct omap_mcspi_s *s) ++{ ++ qemu_set_irq(s->irq, s->irqst & s->irqen); ++} ++ ++static inline void omap_mcspi_dmarequest_update(struct omap_mcspi_ch_s *ch) ++{ ++ qemu_set_irq(ch->txdrq, ++ (ch->control & 1) && /* EN */ ++ (ch->config & (1 << 14)) && /* DMAW */ ++ (ch->status & (1 << 1)) && /* TXS */ ++ ((ch->config >> 12) & 3) != 1); /* TRM */ ++ qemu_set_irq(ch->rxdrq, ++ (ch->control & 1) && /* EN */ ++ (ch->config & (1 << 15)) && /* DMAW */ ++ (ch->status & (1 << 0)) && /* RXS */ ++ ((ch->config >> 12) & 3) != 2); /* TRM */ ++} ++ ++static void omap_mcspi_transfer_run(struct omap_mcspi_s *s, int chnum) ++{ ++ struct omap_mcspi_ch_s *ch = s->ch + chnum; ++ ++ if (!(ch->control & 1)) /* EN */ ++ return; ++ if ((ch->status & (1 << 0)) && /* RXS */ ++ ((ch->config >> 12) & 3) != 2 && /* TRM */ ++ !(ch->config & (1 << 19))) /* TURBO */ ++ goto intr_update; ++ if ((ch->status & (1 << 1)) && /* TXS */ ++ ((ch->config >> 12) & 3) != 1) /* TRM */ ++ goto intr_update; ++ ++ if (!(s->control & 1) || /* SINGLE */ ++ (ch->config & (1 << 20))) { /* FORCE */ ++ if (ch->txrx) ++ ch->rx = ch->txrx(ch->opaque, ch->tx); ++ } ++ ++ ch->tx = 0; ++ ch->status |= 1 << 2; /* EOT */ ++ ch->status |= 1 << 1; /* TXS */ ++ if (((ch->config >> 12) & 3) != 2) /* TRM */ ++ ch->status |= 1 << 0; /* RXS */ ++ ++intr_update: ++ if ((ch->status & (1 << 0)) && /* RXS */ ++ ((ch->config >> 12) & 3) != 2 && /* TRM */ ++ !(ch->config & (1 << 19))) /* TURBO */ ++ s->irqst |= 1 << (2 + 4 * chnum); /* RX_FULL */ ++ if ((ch->status & (1 << 1)) && /* TXS */ ++ ((ch->config >> 12) & 3) != 1) /* TRM */ ++ s->irqst |= 1 << (0 + 4 * chnum); /* TX_EMPTY */ ++ omap_mcspi_interrupt_update(s); ++ omap_mcspi_dmarequest_update(ch); ++} ++ ++static void omap_mcspi_reset(struct omap_mcspi_s *s) ++{ ++ int ch; ++ ++ s->sysconfig = 0; ++ s->systest = 0; ++ s->irqst = 0; ++ s->irqen = 0; ++ s->wken = 0; ++ s->control = 4; ++ ++ for (ch = 0; ch < 4; ch ++) { ++ s->ch[ch].config = 0x060000; ++ s->ch[ch].status = 2; /* TXS */ ++ s->ch[ch].control = 0; ++ ++ omap_mcspi_dmarequest_update(s->ch + ch); ++ } ++ ++ omap_mcspi_interrupt_update(s); ++} ++ ++static uint32_t omap_mcspi_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque; ++ int offset = addr - s->base; ++ int ch = 0; ++ uint32_t ret; ++ ++ switch (offset) { ++ case 0x00: /* MCSPI_REVISION */ ++ return 0x91; ++ ++ case 0x10: /* MCSPI_SYSCONFIG */ ++ return s->sysconfig; ++ ++ case 0x14: /* MCSPI_SYSSTATUS */ ++ return 1; /* RESETDONE */ ++ ++ case 0x18: /* MCSPI_IRQSTATUS */ ++ return s->irqst; ++ ++ case 0x1c: /* MCSPI_IRQENABLE */ ++ return s->irqen; ++ ++ case 0x20: /* MCSPI_WAKEUPENABLE */ ++ return s->wken; ++ ++ case 0x24: /* MCSPI_SYST */ ++ return s->systest; ++ ++ case 0x28: /* MCSPI_MODULCTRL */ ++ return s->control; ++ ++ case 0x68: ch ++; ++ case 0x54: ch ++; ++ case 0x40: ch ++; ++ case 0x2c: /* MCSPI_CHCONF */ ++ return s->ch[ch].config; ++ ++ case 0x6c: ch ++; ++ case 0x58: ch ++; ++ case 0x44: ch ++; ++ case 0x30: /* MCSPI_CHSTAT */ ++ return s->ch[ch].status; ++ ++ case 0x70: ch ++; ++ case 0x5c: ch ++; ++ case 0x48: ch ++; ++ case 0x34: /* MCSPI_CHCTRL */ ++ return s->ch[ch].control; ++ ++ case 0x74: ch ++; ++ case 0x60: ch ++; ++ case 0x4c: ch ++; ++ case 0x38: /* MCSPI_TX */ ++ return s->ch[ch].tx; ++ ++ case 0x78: ch ++; ++ case 0x64: ch ++; ++ case 0x50: ch ++; ++ case 0x3c: /* MCSPI_RX */ ++ s->ch[ch].status &= ~(1 << 0); /* RXS */ ++ ret = s->ch[ch].rx; ++ omap_mcspi_transfer_run(s, ch); ++ return ret; ++ } ++ ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap_mcspi_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque; ++ int offset = addr - s->base; ++ int ch = 0; ++ ++ switch (offset) { ++ case 0x00: /* MCSPI_REVISION */ ++ case 0x14: /* MCSPI_SYSSTATUS */ ++ case 0x30: /* MCSPI_CHSTAT0 */ ++ case 0x3c: /* MCSPI_RX0 */ ++ case 0x44: /* MCSPI_CHSTAT1 */ ++ case 0x50: /* MCSPI_RX1 */ ++ case 0x58: /* MCSPI_CHSTAT2 */ ++ case 0x64: /* MCSPI_RX2 */ ++ case 0x6c: /* MCSPI_CHSTAT3 */ ++ case 0x78: /* MCSPI_RX3 */ ++ OMAP_RO_REG(addr); ++ return; ++ ++ case 0x10: /* MCSPI_SYSCONFIG */ ++ if (value & (1 << 1)) /* SOFTRESET */ ++ omap_mcspi_reset(s); ++ s->sysconfig = value & 0x31d; ++ break; ++ ++ case 0x18: /* MCSPI_IRQSTATUS */ ++ if (!((s->control & (1 << 3)) && (s->systest & (1 << 11)))) { ++ s->irqst &= ~value; ++ omap_mcspi_interrupt_update(s); ++ } ++ break; ++ ++ case 0x1c: /* MCSPI_IRQENABLE */ ++ s->irqen = value & 0x1777f; ++ omap_mcspi_interrupt_update(s); ++ break; ++ ++ case 0x20: /* MCSPI_WAKEUPENABLE */ ++ s->wken = value & 1; ++ break; ++ ++ case 0x24: /* MCSPI_SYST */ ++ if (s->control & (1 << 3)) /* SYSTEM_TEST */ ++ if (value & (1 << 11)) { /* SSB */ ++ s->irqst |= 0x1777f; ++ omap_mcspi_interrupt_update(s); ++ } ++ s->systest = value & 0xfff; ++ break; ++ ++ case 0x28: /* MCSPI_MODULCTRL */ ++ if (value & (1 << 3)) /* SYSTEM_TEST */ ++ if (s->systest & (1 << 11)) { /* SSB */ ++ s->irqst |= 0x1777f; ++ omap_mcspi_interrupt_update(s); ++ } ++ s->control = value & 0xf; ++ break; ++ ++ case 0x68: ch ++; ++ case 0x54: ch ++; ++ case 0x40: ch ++; ++ case 0x2c: /* MCSPI_CHCONF */ ++ if ((value ^ s->ch[ch].config) & (3 << 14)) /* DMAR | DMAW */ ++ omap_mcspi_dmarequest_update(s->ch + ch); ++ if (((value >> 12) & 3) == 3) /* TRM */ ++ fprintf(stderr, "%s: invalid TRM value (3)\n", __FUNCTION__); ++ if (((value >> 7) & 0x1f) < 3) /* WL */ ++ fprintf(stderr, "%s: invalid WL value (%i)\n", ++ __FUNCTION__, (value >> 7) & 0x1f); ++ s->ch[ch].config = value & 0x7fffff; ++ break; ++ ++ case 0x70: ch ++; ++ case 0x5c: ch ++; ++ case 0x48: ch ++; ++ case 0x34: /* MCSPI_CHCTRL */ ++ if (value & ~s->ch[ch].control & 1) { /* EN */ ++ s->ch[ch].control |= 1; ++ omap_mcspi_transfer_run(s, ch); ++ } else ++ s->ch[ch].control = value & 1; ++ break; ++ ++ case 0x74: ch ++; ++ case 0x60: ch ++; ++ case 0x4c: ch ++; ++ case 0x38: /* MCSPI_TX */ ++ s->ch[ch].tx = value; ++ s->ch[ch].status &= ~(1 << 1); /* TXS */ ++ omap_mcspi_transfer_run(s, ch); ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ return; ++ } ++} ++ ++static CPUReadMemoryFunc *omap_mcspi_readfn[] = { ++ omap_badwidth_read32, ++ omap_badwidth_read32, ++ omap_mcspi_read, ++}; ++ ++static CPUWriteMemoryFunc *omap_mcspi_writefn[] = { ++ omap_badwidth_write32, ++ omap_badwidth_write32, ++ omap_mcspi_write, ++}; ++ ++struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum, ++ qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk) ++{ ++ int iomemtype; ++ struct omap_mcspi_s *s = (struct omap_mcspi_s *) ++ qemu_mallocz(sizeof(struct omap_mcspi_s)); ++ struct omap_mcspi_ch_s *ch = s->ch; ++ ++ s->irq = irq; ++ s->chnum = chnum; ++ while (chnum --) { ++ ch->txdrq = *drq ++; ++ ch->rxdrq = *drq ++; ++ ch ++; ++ } ++ omap_mcspi_reset(s); ++ ++ iomemtype = cpu_register_io_memory(0, omap_mcspi_readfn, ++ omap_mcspi_writefn, s); ++ s->base = omap_l4_attach(ta, 0, iomemtype); ++ ++ return s; ++} ++ ++void omap_mcspi_attach(struct omap_mcspi_s *s, ++ uint32_t (*txrx)(void *opaque, uint32_t), void *opaque, ++ int chipselect) ++{ ++ if (chipselect < 0 || chipselect >= s->chnum) ++ cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n", ++ __FUNCTION__, chipselect); ++ ++ s->ch[chipselect].txrx = txrx; ++ s->ch[chipselect].opaque = opaque; ++} ++ ++/* 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]; ++}; ++ ++struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num) ++{ ++ struct omap_l4_s *bus = qemu_mallocz( ++ sizeof(*bus) + ta_num * sizeof(*bus->ta)); ++ ++ bus->ta_num = ta_num; ++ bus->base = base; ++ ++ return bus; ++} ++ ++static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque; ++ target_phys_addr_t reg = addr - s->base; ++ ++ switch (reg) { ++ case 0x00: /* COMPONENT */ ++ return s->component; ++ ++ case 0x20: /* AGENT_CONTROL */ ++ return s->control; ++ ++ case 0x28: /* AGENT_STATUS */ ++ return s->status; ++ } ++ ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap_l4ta_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque; ++ target_phys_addr_t reg = addr - s->base; ++ ++ switch (reg) { ++ case 0x00: /* COMPONENT */ ++ case 0x28: /* AGENT_STATUS */ ++ OMAP_RO_REG(addr); ++ break; ++ ++ case 0x20: /* AGENT_CONTROL */ ++ s->control = value & 0x01000700; ++ if (value & 1) /* OCP_RESET */ ++ s->status &= ~1; /* REQ_TIMEOUT */ ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ } ++} ++ ++static CPUReadMemoryFunc *omap_l4ta_readfn[] = { ++ omap_badwidth_read16, ++ omap_l4ta_read, ++ omap_badwidth_read16, ++}; ++ ++static CPUWriteMemoryFunc *omap_l4ta_writefn[] = { ++ omap_badwidth_write32, ++ omap_badwidth_write32, ++ omap_l4ta_write, ++}; ++ ++#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] = { ++ [ 1] = { 0x40800, 0x800, 32 }, /* Initiator agent */ ++ [ 2] = { 0x41000, 0x1000, 32 }, /* Link agent */ ++ [ 0] = { 0x40000, 0x800, 32 }, /* Address and protection */ ++ [ 3] = { 0x00000, 0x1000, 32 | 16 | 8 }, /* System Control and Pinout */ ++ [ 4] = { 0x01000, 0x1000, 32 | 16 | 8 }, /* L4TAO1 */ ++ [ 5] = { 0x04000, 0x1000, 32 | 16 }, /* 32K Timer */ ++ [ 6] = { 0x05000, 0x1000, 32 | 16 | 8 }, /* L4TAO2 */ ++ [ 7] = { 0x08000, 0x800, 32 }, /* PRCM Region A */ ++ [ 8] = { 0x08800, 0x800, 32 }, /* PRCM Region B */ ++ [ 9] = { 0x09000, 0x1000, 32 | 16 | 8 }, /* L4TAO */ ++ [ 10] = { 0x12000, 0x1000, 32 | 16 | 8 }, /* Test (BCM) */ ++ [ 11] = { 0x13000, 0x1000, 32 | 16 | 8 }, /* L4TA1 */ ++ [ 12] = { 0x14000, 0x1000, 32 }, /* Test/emulation (TAP) */ ++ [ 13] = { 0x15000, 0x1000, 32 | 16 | 8 }, /* L4TA2 */ ++ [ 14] = { 0x18000, 0x1000, 32 | 16 | 8 }, /* GPIO1 */ ++ [ 16] = { 0x1a000, 0x1000, 32 | 16 | 8 }, /* GPIO2 */ ++ [ 18] = { 0x1c000, 0x1000, 32 | 16 | 8 }, /* GPIO3 */ ++ [ 19] = { 0x1e000, 0x1000, 32 | 16 | 8 }, /* GPIO4 */ ++ [ 15] = { 0x19000, 0x1000, 32 | 16 | 8 }, /* Quad GPIO TOP */ ++ [ 17] = { 0x1b000, 0x1000, 32 | 16 | 8 }, /* L4TA3 */ ++ [ 20] = { 0x20000, 0x1000, 32 | 16 | 8 }, /* WD Timer 1 (Secure) */ ++ [ 22] = { 0x22000, 0x1000, 32 | 16 | 8 }, /* WD Timer 2 (OMAP) */ ++ [ 21] = { 0x21000, 0x1000, 32 | 16 | 8 }, /* Dual WD timer TOP */ ++ [ 23] = { 0x23000, 0x1000, 32 | 16 | 8 }, /* L4TA4 */ ++ [ 24] = { 0x28000, 0x1000, 32 | 16 | 8 }, /* GP Timer 1 */ ++ [ 25] = { 0x29000, 0x1000, 32 | 16 | 8 }, /* L4TA7 */ ++ [ 26] = { 0x48000, 0x2000, 32 | 16 | 8 }, /* Emulation (ARM11ETB) */ ++ [ 27] = { 0x4a000, 0x1000, 32 | 16 | 8 }, /* L4TA9 */ ++ [ 28] = { 0x50000, 0x400, 32 | 16 | 8 }, /* Display top */ ++ [ 29] = { 0x50400, 0x400, 32 | 16 | 8 }, /* Display control */ ++ [ 30] = { 0x50800, 0x400, 32 | 16 | 8 }, /* Display RFBI */ ++ [ 31] = { 0x50c00, 0x400, 32 | 16 | 8 }, /* Display encoder */ ++ [ 32] = { 0x51000, 0x1000, 32 | 16 | 8 }, /* L4TA10 */ ++ [ 33] = { 0x52000, 0x400, 32 | 16 | 8 }, /* Camera top */ ++ [ 34] = { 0x52400, 0x400, 32 | 16 | 8 }, /* Camera core */ ++ [ 35] = { 0x52800, 0x400, 32 | 16 | 8 }, /* Camera DMA */ ++ [ 36] = { 0x52c00, 0x400, 32 | 16 | 8 }, /* Camera MMU */ ++ [ 37] = { 0x53000, 0x1000, 32 | 16 | 8 }, /* L4TA11 */ ++ [ 38] = { 0x56000, 0x1000, 32 | 16 | 8 }, /* sDMA */ ++ [ 39] = { 0x57000, 0x1000, 32 | 16 | 8 }, /* L4TA12 */ ++ [ 40] = { 0x58000, 0x1000, 32 | 16 | 8 }, /* SSI top */ ++ [ 41] = { 0x59000, 0x1000, 32 | 16 | 8 }, /* SSI GDD */ ++ [ 42] = { 0x5a000, 0x1000, 32 | 16 | 8 }, /* SSI Port1 */ ++ [ 43] = { 0x5b000, 0x1000, 32 | 16 | 8 }, /* SSI Port2 */ ++ [ 44] = { 0x5c000, 0x1000, 32 | 16 | 8 }, /* L4TA13 */ ++ [ 45] = { 0x5e000, 0x1000, 32 | 16 | 8 }, /* USB OTG */ ++ [ 46] = { 0x5f000, 0x1000, 32 | 16 | 8 }, /* L4TAO4 */ ++ [ 47] = { 0x60000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER1SDRC) */ ++ [ 48] = { 0x61000, 0x1000, 32 | 16 | 8 }, /* L4TA14 */ ++ [ 49] = { 0x62000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER2GPMC) */ ++ [ 50] = { 0x63000, 0x1000, 32 | 16 | 8 }, /* L4TA15 */ ++ [ 51] = { 0x64000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER3OCM) */ ++ [ 52] = { 0x65000, 0x1000, 32 | 16 | 8 }, /* L4TA16 */ ++ [ 53] = { 0x66000, 0x300, 32 | 16 | 8 }, /* Emulation (WIN_TRACER4L4) */ ++ [ 54] = { 0x67000, 0x1000, 32 | 16 | 8 }, /* L4TA17 */ ++ [ 55] = { 0x68000, 0x1000, 32 | 16 | 8 }, /* Emulation (XTI) */ ++ [ 56] = { 0x69000, 0x1000, 32 | 16 | 8 }, /* L4TA18 */ ++ [ 57] = { 0x6a000, 0x1000, 16 | 8 }, /* UART1 */ ++ [ 58] = { 0x6b000, 0x1000, 32 | 16 | 8 }, /* L4TA19 */ ++ [ 59] = { 0x6c000, 0x1000, 16 | 8 }, /* UART2 */ ++ [ 60] = { 0x6d000, 0x1000, 32 | 16 | 8 }, /* L4TA20 */ ++ [ 61] = { 0x6e000, 0x1000, 16 | 8 }, /* UART3 */ ++ [ 62] = { 0x6f000, 0x1000, 32 | 16 | 8 }, /* L4TA21 */ ++ [ 63] = { 0x70000, 0x1000, 16 }, /* I2C1 */ ++ [ 64] = { 0x71000, 0x1000, 32 | 16 | 8 }, /* L4TAO5 */ ++ [ 65] = { 0x72000, 0x1000, 16 }, /* I2C2 */ ++ [ 66] = { 0x73000, 0x1000, 32 | 16 | 8 }, /* L4TAO6 */ ++ [ 67] = { 0x74000, 0x1000, 16 }, /* McBSP1 */ ++ [ 68] = { 0x75000, 0x1000, 32 | 16 | 8 }, /* L4TAO7 */ ++ [ 69] = { 0x76000, 0x1000, 16 }, /* McBSP2 */ ++ [ 70] = { 0x77000, 0x1000, 32 | 16 | 8 }, /* L4TAO8 */ ++ [ 71] = { 0x24000, 0x1000, 32 | 16 | 8 }, /* WD Timer 3 (DSP) */ ++ [ 72] = { 0x25000, 0x1000, 32 | 16 | 8 }, /* L4TA5 */ ++ [ 73] = { 0x26000, 0x1000, 32 | 16 | 8 }, /* WD Timer 4 (IVA) */ ++ [ 74] = { 0x27000, 0x1000, 32 | 16 | 8 }, /* L4TA6 */ ++ [ 75] = { 0x2a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 2 */ ++ [ 76] = { 0x2b000, 0x1000, 32 | 16 | 8 }, /* L4TA8 */ ++ [ 77] = { 0x78000, 0x1000, 32 | 16 | 8 }, /* GP Timer 3 */ ++ [ 78] = { 0x79000, 0x1000, 32 | 16 | 8 }, /* L4TA22 */ ++ [ 79] = { 0x7a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 4 */ ++ [ 80] = { 0x7b000, 0x1000, 32 | 16 | 8 }, /* L4TA23 */ ++ [ 81] = { 0x7c000, 0x1000, 32 | 16 | 8 }, /* GP Timer 5 */ ++ [ 82] = { 0x7d000, 0x1000, 32 | 16 | 8 }, /* L4TA24 */ ++ [ 83] = { 0x7e000, 0x1000, 32 | 16 | 8 }, /* GP Timer 6 */ ++ [ 84] = { 0x7f000, 0x1000, 32 | 16 | 8 }, /* L4TA25 */ ++ [ 85] = { 0x80000, 0x1000, 32 | 16 | 8 }, /* GP Timer 7 */ ++ [ 86] = { 0x81000, 0x1000, 32 | 16 | 8 }, /* L4TA26 */ ++ [ 87] = { 0x82000, 0x1000, 32 | 16 | 8 }, /* GP Timer 8 */ ++ [ 88] = { 0x83000, 0x1000, 32 | 16 | 8 }, /* L4TA27 */ ++ [ 89] = { 0x84000, 0x1000, 32 | 16 | 8 }, /* GP Timer 9 */ ++ [ 90] = { 0x85000, 0x1000, 32 | 16 | 8 }, /* L4TA28 */ ++ [ 91] = { 0x86000, 0x1000, 32 | 16 | 8 }, /* GP Timer 10 */ ++ [ 92] = { 0x87000, 0x1000, 32 | 16 | 8 }, /* L4TA29 */ ++ [ 93] = { 0x88000, 0x1000, 32 | 16 | 8 }, /* GP Timer 11 */ ++ [ 94] = { 0x89000, 0x1000, 32 | 16 | 8 }, /* L4TA30 */ ++ [ 95] = { 0x8a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 12 */ ++ [ 96] = { 0x8b000, 0x1000, 32 | 16 | 8 }, /* L4TA31 */ ++ [ 97] = { 0x90000, 0x1000, 16 }, /* EAC */ ++ [ 98] = { 0x91000, 0x1000, 32 | 16 | 8 }, /* L4TA32 */ ++ [ 99] = { 0x92000, 0x1000, 16 }, /* FAC */ ++ [100] = { 0x93000, 0x1000, 32 | 16 | 8 }, /* L4TA33 */ ++ [101] = { 0x94000, 0x1000, 32 | 16 | 8 }, /* IPC (MAILBOX) */ ++ [102] = { 0x95000, 0x1000, 32 | 16 | 8 }, /* L4TA34 */ ++ [103] = { 0x98000, 0x1000, 32 | 16 | 8 }, /* SPI1 */ ++ [104] = { 0x99000, 0x1000, 32 | 16 | 8 }, /* L4TA35 */ ++ [105] = { 0x9a000, 0x1000, 32 | 16 | 8 }, /* SPI2 */ ++ [106] = { 0x9b000, 0x1000, 32 | 16 | 8 }, /* L4TA36 */ ++ [107] = { 0x9c000, 0x1000, 16 | 8 }, /* MMC SDIO */ ++ [108] = { 0x9d000, 0x1000, 32 | 16 | 8 }, /* L4TAO9 */ ++ [109] = { 0x9e000, 0x1000, 32 | 16 | 8 }, /* MS_PRO */ ++ [110] = { 0x9f000, 0x1000, 32 | 16 | 8 }, /* L4TAO10 */ ++ [111] = { 0xa0000, 0x1000, 32 }, /* RNG */ ++ [112] = { 0xa1000, 0x1000, 32 | 16 | 8 }, /* L4TAO11 */ ++ [113] = { 0xa2000, 0x1000, 32 }, /* DES3DES */ ++ [114] = { 0xa3000, 0x1000, 32 | 16 | 8 }, /* L4TAO12 */ ++ [115] = { 0xa4000, 0x1000, 32 }, /* SHA1MD5 */ ++ [116] = { 0xa5000, 0x1000, 32 | 16 | 8 }, /* L4TAO13 */ ++ [117] = { 0xa6000, 0x1000, 32 }, /* AES */ ++ [118] = { 0xa7000, 0x1000, 32 | 16 | 8 }, /* L4TA37 */ ++ [119] = { 0xa8000, 0x2000, 32 }, /* PKA */ ++ [120] = { 0xaa000, 0x1000, 32 | 16 | 8 }, /* L4TA38 */ ++ [121] = { 0xb0000, 0x1000, 32 }, /* MG */ ++ [122] = { 0xb1000, 0x1000, 32 | 16 | 8 }, ++ [123] = { 0xb2000, 0x1000, 32 }, /* HDQ/1-Wire */ ++ [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] = { ++ { 0, 0, 3, 2 }, /* L4IA initiatior agent */ ++ { L4TAO(1), 3, 2, 1 }, /* Control and pinout module */ ++ { L4TAO(2), 5, 2, 1 }, /* 32K timer */ ++ { L4TAO(3), 7, 3, 2 }, /* PRCM */ ++ { L4TA(1), 10, 2, 1 }, /* BCM */ ++ { L4TA(2), 12, 2, 1 }, /* Test JTAG */ ++ { L4TA(3), 14, 6, 3 }, /* Quad GPIO */ ++ { L4TA(4), 20, 4, 3 }, /* WD timer 1/2 */ ++ { L4TA(7), 24, 2, 1 }, /* GP timer 1 */ ++ { L4TA(9), 26, 2, 1 }, /* ATM11 ETB */ ++ { L4TA(10), 28, 5, 4 }, /* Display subsystem */ ++ { L4TA(11), 33, 5, 4 }, /* Camera subsystem */ ++ { L4TA(12), 38, 2, 1 }, /* sDMA */ ++ { L4TA(13), 40, 5, 4 }, /* SSI */ ++ { L4TAO(4), 45, 2, 1 }, /* USB */ ++ { L4TA(14), 47, 2, 1 }, /* Win Tracer1 */ ++ { L4TA(15), 49, 2, 1 }, /* Win Tracer2 */ ++ { L4TA(16), 51, 2, 1 }, /* Win Tracer3 */ ++ { L4TA(17), 53, 2, 1 }, /* Win Tracer4 */ ++ { L4TA(18), 55, 2, 1 }, /* XTI */ ++ { L4TA(19), 57, 2, 1 }, /* UART1 */ ++ { L4TA(20), 59, 2, 1 }, /* UART2 */ ++ { L4TA(21), 61, 2, 1 }, /* UART3 */ ++ { L4TAO(5), 63, 2, 1 }, /* I2C1 */ ++ { L4TAO(6), 65, 2, 1 }, /* I2C2 */ ++ { L4TAO(7), 67, 2, 1 }, /* McBSP1 */ ++ { L4TAO(8), 69, 2, 1 }, /* McBSP2 */ ++ { L4TA(5), 71, 2, 1 }, /* WD Timer 3 (DSP) */ ++ { L4TA(6), 73, 2, 1 }, /* WD Timer 4 (IVA) */ ++ { L4TA(8), 75, 2, 1 }, /* GP Timer 2 */ ++ { L4TA(22), 77, 2, 1 }, /* GP Timer 3 */ ++ { L4TA(23), 79, 2, 1 }, /* GP Timer 4 */ ++ { L4TA(24), 81, 2, 1 }, /* GP Timer 5 */ ++ { L4TA(25), 83, 2, 1 }, /* GP Timer 6 */ ++ { L4TA(26), 85, 2, 1 }, /* GP Timer 7 */ ++ { L4TA(27), 87, 2, 1 }, /* GP Timer 8 */ ++ { L4TA(28), 89, 2, 1 }, /* GP Timer 9 */ ++ { L4TA(29), 91, 2, 1 }, /* GP Timer 10 */ ++ { L4TA(30), 93, 2, 1 }, /* GP Timer 11 */ ++ { L4TA(31), 95, 2, 1 }, /* GP Timer 12 */ ++ { L4TA(32), 97, 2, 1 }, /* EAC */ ++ { L4TA(33), 99, 2, 1 }, /* FAC */ ++ { L4TA(34), 101, 2, 1 }, /* IPC */ ++ { L4TA(35), 103, 2, 1 }, /* SPI1 */ ++ { L4TA(36), 105, 2, 1 }, /* SPI2 */ ++ { L4TAO(9), 107, 2, 1 }, /* MMC SDIO */ ++ { L4TAO(10), 109, 2, 1 }, ++ { L4TAO(11), 111, 2, 1 }, /* RNG */ ++ { L4TAO(12), 113, 2, 1 }, /* DES3DES */ ++ { L4TAO(13), 115, 2, 1 }, /* SHA1MD5 */ ++ { L4TA(37), 117, 2, 1 }, /* AES */ ++ { L4TA(38), 119, 2, 1 }, /* PKA */ ++ { -1, 121, 2, 1 }, ++ { L4TA(39), 123, 2, 1 }, /* HDQ/1-Wire */ ++}; ++ ++#define omap_l4ta(bus, cs) omap_l4ta_get(bus, L4TA(cs)) ++#define omap_l4tao(bus, cs) omap_l4ta_get(bus, L4TAO(cs)) ++ ++struct omap_target_agent_s *omap_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 (omap_l4_agent_info[i].ta == cs) { ++ ta = &bus->ta[i]; ++ info = &omap_l4_agent_info[i]; ++ break; ++ } ++ if (!ta) { ++ fprintf(stderr, "%s: bad target agent (%i)\n", __FUNCTION__, cs); ++ exit(-1); ++ } ++ ++ ta->bus = bus; ++ ta->start = &omap_l4_region[info->region]; ++ ta->regions = info->regions; ++ ta->base = bus->base + ta->start[info->ta_region].offset; ++ ++ ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0); ++ ta->status = 0x00000000; ++ ta->control = 0x00000200; /* XXX 01000200 for L4TAO */ ++ ++ iomemtype = cpu_register_io_memory(0, omap_l4ta_readfn, ++ omap_l4ta_writefn, ta); ++ cpu_register_physical_memory(ta->base, 0x200, iomemtype); ++ ++ return ta; ++} ++ ++target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region, ++ int iotype) ++{ ++ target_phys_addr_t base; ++ size_t size; ++ ++ if (region < 0 || region >= ta->regions) { ++ fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region); ++ exit(-1); ++ } ++ ++ base = ta->bus->base + ta->start[region].offset; ++ size = ta->start[region].size; ++ if (iotype) ++ cpu_register_physical_memory(base, size, iotype); ++ ++ return base; ++} ++ ++/* TEST-Chip-level TAP */ ++static uint32_t omap_tap_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; ++ target_phys_addr_t reg = addr - s->tap_base; ++ ++ switch (reg) { ++ case 0x204: /* IDCODE_reg */ ++ switch (s->mpu_model) { ++ case omap2420: ++ case omap2422: ++ case omap2423: ++ return 0x5b5d902f; /* ES 2.2 */ ++ case omap2430: ++ return 0x5b68a02f; /* ES 2.2 */ ++ case omap3430: ++ return 0x1b7ae02f; /* ES 2 */ ++ default: ++ cpu_abort(cpu_single_env, "%s: Bad mpu model\n", __FUNCTION__); ++ } ++ ++ case 0x208: /* PRODUCTION_ID_reg for OMAP2 */ ++ case 0x210: /* PRODUCTION_ID_reg for OMAP3 */ ++ switch (s->mpu_model) { ++ case omap2420: ++ return 0x000200f0; /* POP ESHS2.1.1 in N91/93/95, ES2 in N800 */ ++ case omap2422: ++ return 0x000400f0; ++ case omap2423: ++ return 0x000800f0; ++ case omap2430: ++ return 0x000000f0; ++ case omap3430: ++ return 0x000000f0; ++ default: ++ cpu_abort(cpu_single_env, "%s: Bad mpu model\n", __FUNCTION__); ++ } ++ ++ case 0x218: /* DIE_ID_reg */ ++ return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0); ++ case 0x21c: /* DIE_ID_reg */ ++ return ( 5 << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0); ++ case 0x220: /* DIE_ID_reg */ ++ return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0); ++ case 0x224: /* DIE_ID_reg */ ++ return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0); ++ } ++ ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap_tap_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ OMAP_BAD_REG(addr); ++} ++ ++static CPUReadMemoryFunc *omap_tap_readfn[] = { ++ omap_badwidth_read32, ++ omap_badwidth_read32, ++ omap_tap_read, ++}; ++ ++static CPUWriteMemoryFunc *omap_tap_writefn[] = { ++ omap_badwidth_write32, ++ omap_badwidth_write32, ++ omap_tap_write, ++}; ++ ++void omap_tap_init(struct omap_target_agent_s *ta, ++ struct omap_mpu_state_s *mpu) ++{ ++ mpu->tap_base = omap_l4_attach(ta, 0, cpu_register_io_memory(0, ++ omap_tap_readfn, omap_tap_writefn, mpu)); ++} ++ ++/* Power, Reset, and Clock Management */ ++struct omap_prcm_s { ++ target_phys_addr_t base; ++ qemu_irq irq[3]; ++ struct omap_mpu_state_s *mpu; ++ ++ uint32_t irqst[3]; ++ uint32_t irqen[3]; ++ ++ uint32_t sysconfig; ++ uint32_t voltctrl; ++ uint32_t scratch[20]; ++ ++ uint32_t clksrc[1]; ++ uint32_t clkout[1]; ++ uint32_t clkemul[1]; ++ uint32_t clkpol[1]; ++ uint32_t clksel[8]; ++ uint32_t clken[12]; ++ uint32_t clkctrl[4]; ++ uint32_t clkidle[7]; ++ uint32_t setuptime[2]; ++ ++ uint32_t wkup[3]; ++ uint32_t wken[3]; ++ uint32_t wkst[3]; ++ uint32_t rst[4]; ++ uint32_t rstctrl[1]; ++ uint32_t power[4]; ++ uint32_t rsttime_wkup; ++ ++ uint32_t ev; ++ uint32_t evtime[2]; ++}; ++ ++static void omap_prcm_int_update(struct omap_prcm_s *s, int dom) ++{ ++ qemu_set_irq(s->irq[dom], s->irqst[dom] & s->irqen[dom]); ++ /* XXX or is the mask applied before PRCM_IRQSTATUS_* ? */ ++} ++ ++static uint32_t omap_prcm_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_prcm_s *s = (struct omap_prcm_s *) opaque; ++ int offset = addr - s->base; ++ ++ switch (offset) { ++ case 0x000: /* PRCM_REVISION */ ++ return 0x10; ++ ++ case 0x010: /* PRCM_SYSCONFIG */ ++ return s->sysconfig; ++ ++ case 0x018: /* PRCM_IRQSTATUS_MPU */ ++ return s->irqst[0]; ++ ++ case 0x01c: /* PRCM_IRQENABLE_MPU */ ++ return s->irqen[0]; ++ ++ case 0x050: /* PRCM_VOLTCTRL */ ++ return s->voltctrl; ++ case 0x054: /* PRCM_VOLTST */ ++ return s->voltctrl & 3; ++ ++ case 0x060: /* PRCM_CLKSRC_CTRL */ ++ return s->clksrc[0]; ++ case 0x070: /* PRCM_CLKOUT_CTRL */ ++ return s->clkout[0]; ++ case 0x078: /* PRCM_CLKEMUL_CTRL */ ++ return s->clkemul[0]; ++ case 0x080: /* PRCM_CLKCFG_CTRL */ ++ case 0x084: /* PRCM_CLKCFG_STATUS */ ++ return 0; ++ ++ case 0x090: /* PRCM_VOLTSETUP */ ++ return s->setuptime[0]; ++ ++ case 0x094: /* PRCM_CLKSSETUP */ ++ return s->setuptime[1]; ++ ++ case 0x098: /* PRCM_POLCTRL */ ++ return s->clkpol[0]; ++ ++ case 0x0b0: /* GENERAL_PURPOSE1 */ ++ case 0x0b4: /* GENERAL_PURPOSE2 */ ++ case 0x0b8: /* GENERAL_PURPOSE3 */ ++ case 0x0bc: /* GENERAL_PURPOSE4 */ ++ case 0x0c0: /* GENERAL_PURPOSE5 */ ++ case 0x0c4: /* GENERAL_PURPOSE6 */ ++ case 0x0c8: /* GENERAL_PURPOSE7 */ ++ case 0x0cc: /* GENERAL_PURPOSE8 */ ++ case 0x0d0: /* GENERAL_PURPOSE9 */ ++ case 0x0d4: /* GENERAL_PURPOSE10 */ ++ case 0x0d8: /* GENERAL_PURPOSE11 */ ++ case 0x0dc: /* GENERAL_PURPOSE12 */ ++ case 0x0e0: /* GENERAL_PURPOSE13 */ ++ case 0x0e4: /* GENERAL_PURPOSE14 */ ++ case 0x0e8: /* GENERAL_PURPOSE15 */ ++ case 0x0ec: /* GENERAL_PURPOSE16 */ ++ case 0x0f0: /* GENERAL_PURPOSE17 */ ++ case 0x0f4: /* GENERAL_PURPOSE18 */ ++ case 0x0f8: /* GENERAL_PURPOSE19 */ ++ case 0x0fc: /* GENERAL_PURPOSE20 */ ++ return s->scratch[(offset - 0xb0) >> 2]; ++ ++ case 0x140: /* CM_CLKSEL_MPU */ ++ return s->clksel[0]; ++ case 0x148: /* CM_CLKSTCTRL_MPU */ ++ return s->clkctrl[0]; ++ ++ case 0x158: /* RM_RSTST_MPU */ ++ return s->rst[0]; ++ case 0x1c8: /* PM_WKDEP_MPU */ ++ return s->wkup[0]; ++ case 0x1d4: /* PM_EVGENCTRL_MPU */ ++ return s->ev; ++ case 0x1d8: /* PM_EVEGENONTIM_MPU */ ++ return s->evtime[0]; ++ case 0x1dc: /* PM_EVEGENOFFTIM_MPU */ ++ return s->evtime[1]; ++ case 0x1e0: /* PM_PWSTCTRL_MPU */ ++ return s->power[0]; ++ case 0x1e4: /* PM_PWSTST_MPU */ ++ return 0; ++ ++ case 0x200: /* CM_FCLKEN1_CORE */ ++ return s->clken[0]; ++ case 0x204: /* CM_FCLKEN2_CORE */ ++ return s->clken[1]; ++ case 0x210: /* CM_ICLKEN1_CORE */ ++ return s->clken[2]; ++ case 0x214: /* CM_ICLKEN2_CORE */ ++ return s->clken[3]; ++ case 0x21c: /* CM_ICLKEN4_CORE */ ++ return s->clken[4]; ++ ++ case 0x220: /* CM_IDLEST1_CORE */ ++ /* TODO: check the actual iclk status */ ++ return 0x7ffffff9; ++ case 0x224: /* CM_IDLEST2_CORE */ ++ /* TODO: check the actual iclk status */ ++ return 0x00000007; ++ case 0x22c: /* CM_IDLEST4_CORE */ ++ /* TODO: check the actual iclk status */ ++ return 0x0000001f; ++ ++ case 0x230: /* CM_AUTOIDLE1_CORE */ ++ return s->clkidle[0]; ++ case 0x234: /* CM_AUTOIDLE2_CORE */ ++ return s->clkidle[1]; ++ case 0x238: /* CM_AUTOIDLE3_CORE */ ++ return s->clkidle[2]; ++ case 0x23c: /* CM_AUTOIDLE4_CORE */ ++ return s->clkidle[3]; ++ ++ case 0x240: /* CM_CLKSEL1_CORE */ ++ return s->clksel[1]; ++ case 0x244: /* CM_CLKSEL2_CORE */ ++ return s->clksel[2]; ++ ++ case 0x248: /* CM_CLKSTCTRL_CORE */ ++ return s->clkctrl[1]; ++ ++ case 0x2a0: /* PM_WKEN1_CORE */ ++ return s->wken[0]; ++ case 0x2a4: /* PM_WKEN2_CORE */ ++ return s->wken[1]; ++ ++ case 0x2b0: /* PM_WKST1_CORE */ ++ return s->wkst[0]; ++ case 0x2b4: /* PM_WKST2_CORE */ ++ return s->wkst[1]; ++ case 0x2c8: /* PM_WKDEP_CORE */ ++ return 0x1e; ++ ++ case 0x2e0: /* PM_PWSTCTRL_CORE */ ++ return s->power[1]; ++ case 0x2e4: /* PM_PWSTST_CORE */ ++ return 0x000030 | (s->power[1] & 0xfc00); ++ ++ case 0x300: /* CM_FCLKEN_GFX */ ++ return s->clken[5]; ++ case 0x310: /* CM_ICLKEN_GFX */ ++ return s->clken[6]; ++ case 0x320: /* CM_IDLEST_GFX */ ++ /* TODO: check the actual iclk status */ ++ return 0x00000001; ++ case 0x340: /* CM_CLKSEL_GFX */ ++ return s->clksel[3]; ++ case 0x348: /* CM_CLKSTCTRL_GFX */ ++ return s->clkctrl[2]; ++ case 0x350: /* RM_RSTCTRL_GFX */ ++ return s->rstctrl[0]; ++ case 0x358: /* RM_RSTST_GFX */ ++ return s->rst[1]; ++ case 0x3c8: /* PM_WKDEP_GFX */ ++ return s->wkup[1]; ++ ++ case 0x3e0: /* PM_PWSTCTRL_GFX */ ++ return s->power[2]; ++ case 0x3e4: /* PM_PWSTST_GFX */ ++ return s->power[2] & 3; ++ ++ case 0x400: /* CM_FCLKEN_WKUP */ ++ return s->clken[7]; ++ case 0x410: /* CM_ICLKEN_WKUP */ ++ return s->clken[8]; ++ case 0x420: /* CM_IDLEST_WKUP */ ++ /* TODO: check the actual iclk status */ ++ return 0x0000003f; ++ case 0x430: /* CM_AUTOIDLE_WKUP */ ++ return s->clkidle[4]; ++ case 0x440: /* CM_CLKSEL_WKUP */ ++ return s->clksel[4]; ++ case 0x450: /* RM_RSTCTRL_WKUP */ ++ return 0; ++ case 0x454: /* RM_RSTTIME_WKUP */ ++ return s->rsttime_wkup; ++ case 0x458: /* RM_RSTST_WKUP */ ++ return s->rst[2]; ++ case 0x4a0: /* PM_WKEN_WKUP */ ++ return s->wken[2]; ++ case 0x4b0: /* PM_WKST_WKUP */ ++ return s->wkst[2]; ++ ++ case 0x500: /* CM_CLKEN_PLL */ ++ return s->clken[9]; ++ case 0x520: /* CM_IDLEST_CKGEN */ ++ /* Core uses 32-kHz clock */ ++ if (!(s->clksel[6] & 3)) ++ return 0x00000377; ++ /* DPLL not in lock mode, core uses ref_clk */ ++ if ((s->clken[9] & 3) != 3) ++ return 0x00000375; ++ /* Core uses DPLL */ ++ return 0x00000376; ++ case 0x530: /* CM_AUTOIDLE_PLL */ ++ return s->clkidle[5]; ++ case 0x540: /* CM_CLKSEL1_PLL */ ++ return s->clksel[5]; ++ case 0x544: /* CM_CLKSEL2_PLL */ ++ return s->clksel[6]; ++ ++ case 0x800: /* CM_FCLKEN_DSP */ ++ return s->clken[10]; ++ case 0x810: /* CM_ICLKEN_DSP */ ++ return s->clken[11]; ++ case 0x820: /* CM_IDLEST_DSP */ ++ /* TODO: check the actual iclk status */ ++ return 0x00000103; ++ case 0x830: /* CM_AUTOIDLE_DSP */ ++ return s->clkidle[6]; ++ case 0x840: /* CM_CLKSEL_DSP */ ++ return s->clksel[7]; ++ case 0x848: /* CM_CLKSTCTRL_DSP */ ++ return s->clkctrl[3]; ++ case 0x850: /* RM_RSTCTRL_DSP */ ++ return 0; ++ case 0x858: /* RM_RSTST_DSP */ ++ return s->rst[3]; ++ case 0x8c8: /* PM_WKDEP_DSP */ ++ return s->wkup[2]; ++ case 0x8e0: /* PM_PWSTCTRL_DSP */ ++ return s->power[3]; ++ case 0x8e4: /* PM_PWSTST_DSP */ ++ return 0x008030 | (s->power[3] & 0x3003); ++ ++ case 0x8f0: /* PRCM_IRQSTATUS_DSP */ ++ return s->irqst[1]; ++ case 0x8f4: /* PRCM_IRQENABLE_DSP */ ++ return s->irqen[1]; ++ ++ case 0x8f8: /* PRCM_IRQSTATUS_IVA */ ++ return s->irqst[2]; ++ case 0x8fc: /* PRCM_IRQENABLE_IVA */ ++ return s->irqen[2]; ++ } ++ ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap_prcm_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_prcm_s *s = (struct omap_prcm_s *) opaque; ++ int offset = addr - s->base; ++ ++ switch (offset) { ++ case 0x000: /* PRCM_REVISION */ ++ case 0x054: /* PRCM_VOLTST */ ++ case 0x084: /* PRCM_CLKCFG_STATUS */ ++ case 0x1e4: /* PM_PWSTST_MPU */ ++ case 0x220: /* CM_IDLEST1_CORE */ ++ case 0x224: /* CM_IDLEST2_CORE */ ++ case 0x22c: /* CM_IDLEST4_CORE */ ++ case 0x2c8: /* PM_WKDEP_CORE */ ++ case 0x2e4: /* PM_PWSTST_CORE */ ++ case 0x320: /* CM_IDLEST_GFX */ ++ case 0x3e4: /* PM_PWSTST_GFX */ ++ case 0x420: /* CM_IDLEST_WKUP */ ++ case 0x520: /* CM_IDLEST_CKGEN */ ++ case 0x820: /* CM_IDLEST_DSP */ ++ case 0x8e4: /* PM_PWSTST_DSP */ ++ OMAP_RO_REG(addr); ++ return; ++ ++ case 0x010: /* PRCM_SYSCONFIG */ ++ s->sysconfig = value & 1; ++ break; ++ ++ case 0x018: /* PRCM_IRQSTATUS_MPU */ ++ s->irqst[0] &= ~value; ++ omap_prcm_int_update(s, 0); ++ break; ++ case 0x01c: /* PRCM_IRQENABLE_MPU */ ++ s->irqen[0] = value & 0x3f; ++ omap_prcm_int_update(s, 0); ++ break; ++ ++ case 0x050: /* PRCM_VOLTCTRL */ ++ s->voltctrl = value & 0xf1c3; ++ break; ++ ++ case 0x060: /* PRCM_CLKSRC_CTRL */ ++ s->clksrc[0] = value & 0xdb; ++ /* TODO update clocks */ ++ break; ++ ++ case 0x070: /* PRCM_CLKOUT_CTRL */ ++ s->clkout[0] = value & 0xbbbb; ++ /* TODO update clocks */ ++ break; ++ ++ case 0x078: /* PRCM_CLKEMUL_CTRL */ ++ s->clkemul[0] = value & 1; ++ /* TODO update clocks */ ++ break; ++ ++ case 0x080: /* PRCM_CLKCFG_CTRL */ ++ break; ++ ++ case 0x090: /* PRCM_VOLTSETUP */ ++ s->setuptime[0] = value & 0xffff; ++ break; ++ case 0x094: /* PRCM_CLKSSETUP */ ++ s->setuptime[1] = value & 0xffff; ++ break; ++ ++ case 0x098: /* PRCM_POLCTRL */ ++ s->clkpol[0] = value & 0x701; ++ break; ++ ++ case 0x0b0: /* GENERAL_PURPOSE1 */ ++ case 0x0b4: /* GENERAL_PURPOSE2 */ ++ case 0x0b8: /* GENERAL_PURPOSE3 */ ++ case 0x0bc: /* GENERAL_PURPOSE4 */ ++ case 0x0c0: /* GENERAL_PURPOSE5 */ ++ case 0x0c4: /* GENERAL_PURPOSE6 */ ++ case 0x0c8: /* GENERAL_PURPOSE7 */ ++ case 0x0cc: /* GENERAL_PURPOSE8 */ ++ case 0x0d0: /* GENERAL_PURPOSE9 */ ++ case 0x0d4: /* GENERAL_PURPOSE10 */ ++ case 0x0d8: /* GENERAL_PURPOSE11 */ ++ case 0x0dc: /* GENERAL_PURPOSE12 */ ++ case 0x0e0: /* GENERAL_PURPOSE13 */ ++ case 0x0e4: /* GENERAL_PURPOSE14 */ ++ case 0x0e8: /* GENERAL_PURPOSE15 */ ++ case 0x0ec: /* GENERAL_PURPOSE16 */ ++ case 0x0f0: /* GENERAL_PURPOSE17 */ ++ case 0x0f4: /* GENERAL_PURPOSE18 */ ++ case 0x0f8: /* GENERAL_PURPOSE19 */ ++ case 0x0fc: /* GENERAL_PURPOSE20 */ ++ s->scratch[(offset - 0xb0) >> 2] = value; ++ break; ++ ++ case 0x140: /* CM_CLKSEL_MPU */ ++ s->clksel[0] = value & 0x1f; ++ /* TODO update clocks */ ++ break; ++ case 0x148: /* CM_CLKSTCTRL_MPU */ ++ s->clkctrl[0] = value & 0x1f; ++ break; ++ ++ case 0x158: /* RM_RSTST_MPU */ ++ s->rst[0] &= ~value; ++ break; ++ case 0x1c8: /* PM_WKDEP_MPU */ ++ s->wkup[0] = value & 0x15; ++ break; ++ ++ case 0x1d4: /* PM_EVGENCTRL_MPU */ ++ s->ev = value & 0x1f; ++ break; ++ case 0x1d8: /* PM_EVEGENONTIM_MPU */ ++ s->evtime[0] = value; ++ break; ++ case 0x1dc: /* PM_EVEGENOFFTIM_MPU */ ++ s->evtime[1] = value; ++ break; ++ ++ case 0x1e0: /* PM_PWSTCTRL_MPU */ ++ s->power[0] = value & 0xc0f; ++ break; ++ ++ case 0x200: /* CM_FCLKEN1_CORE */ ++ s->clken[0] = value & 0xbfffffff; ++ /* TODO update clocks */ ++ break; ++ case 0x204: /* CM_FCLKEN2_CORE */ ++ s->clken[1] = value & 0x00000007; ++ /* TODO update clocks */ ++ break; ++ case 0x210: /* CM_ICLKEN1_CORE */ ++ s->clken[2] = value & 0xfffffff9; ++ /* TODO update clocks */ ++ break; ++ case 0x214: /* CM_ICLKEN2_CORE */ ++ s->clken[3] = value & 0x00000007; ++ /* TODO update clocks */ ++ break; ++ case 0x21c: /* CM_ICLKEN4_CORE */ ++ s->clken[4] = value & 0x0000001f; ++ /* TODO update clocks */ ++ break; ++ ++ case 0x230: /* CM_AUTOIDLE1_CORE */ ++ s->clkidle[0] = value & 0xfffffff9; ++ /* TODO update clocks */ ++ break; ++ case 0x234: /* CM_AUTOIDLE2_CORE */ ++ s->clkidle[1] = value & 0x00000007; ++ /* TODO update clocks */ ++ break; ++ case 0x238: /* CM_AUTOIDLE3_CORE */ ++ s->clkidle[2] = value & 0x00000007; ++ /* TODO update clocks */ ++ break; ++ case 0x23c: /* CM_AUTOIDLE4_CORE */ ++ s->clkidle[3] = value & 0x0000001f; ++ /* TODO update clocks */ ++ break; ++ ++ case 0x240: /* CM_CLKSEL1_CORE */ ++ s->clksel[1] = value & 0x0fffbf7f; ++ /* TODO update clocks */ ++ break; ++ ++ case 0x244: /* CM_CLKSEL2_CORE */ ++ s->clksel[2] = value & 0x00fffffc; ++ /* TODO update clocks */ ++ break; ++ ++ case 0x248: /* CM_CLKSTCTRL_CORE */ ++ s->clkctrl[1] = value & 0x7; ++ break; ++ ++ case 0x2a0: /* PM_WKEN1_CORE */ ++ s->wken[0] = value & 0x04667ff8; ++ break; ++ case 0x2a4: /* PM_WKEN2_CORE */ ++ s->wken[1] = value & 0x00000005; ++ break; ++ ++ case 0x2b0: /* PM_WKST1_CORE */ ++ s->wkst[0] &= ~value; ++ break; ++ case 0x2b4: /* PM_WKST2_CORE */ ++ s->wkst[1] &= ~value; ++ break; ++ ++ case 0x2e0: /* PM_PWSTCTRL_CORE */ ++ s->power[1] = (value & 0x00fc3f) | (1 << 2); ++ break; ++ ++ case 0x300: /* CM_FCLKEN_GFX */ ++ s->clken[5] = value & 6; ++ /* TODO update clocks */ ++ break; ++ case 0x310: /* CM_ICLKEN_GFX */ ++ s->clken[6] = value & 1; ++ /* TODO update clocks */ ++ break; ++ case 0x340: /* CM_CLKSEL_GFX */ ++ s->clksel[3] = value & 7; ++ /* TODO update clocks */ ++ break; ++ case 0x348: /* CM_CLKSTCTRL_GFX */ ++ s->clkctrl[2] = value & 1; ++ break; ++ case 0x350: /* RM_RSTCTRL_GFX */ ++ s->rstctrl[0] = value & 1; ++ /* TODO: reset */ ++ break; ++ case 0x358: /* RM_RSTST_GFX */ ++ s->rst[1] &= ~value; ++ break; ++ case 0x3c8: /* PM_WKDEP_GFX */ ++ s->wkup[1] = value & 0x13; ++ break; ++ case 0x3e0: /* PM_PWSTCTRL_GFX */ ++ s->power[2] = (value & 0x00c0f) | (3 << 2); ++ break; ++ ++ case 0x400: /* CM_FCLKEN_WKUP */ ++ s->clken[7] = value & 0xd; ++ /* TODO update clocks */ ++ break; ++ case 0x410: /* CM_ICLKEN_WKUP */ ++ s->clken[8] = value & 0x3f; ++ /* TODO update clocks */ ++ break; ++ case 0x430: /* CM_AUTOIDLE_WKUP */ ++ s->clkidle[4] = value & 0x0000003f; ++ /* TODO update clocks */ ++ break; ++ case 0x440: /* CM_CLKSEL_WKUP */ ++ s->clksel[4] = value & 3; ++ /* TODO update clocks */ ++ break; ++ case 0x450: /* RM_RSTCTRL_WKUP */ ++ /* TODO: reset */ ++ if (value & 2) ++ qemu_system_reset_request(); ++ break; ++ case 0x454: /* RM_RSTTIME_WKUP */ ++ s->rsttime_wkup = value & 0x1fff; ++ break; ++ case 0x458: /* RM_RSTST_WKUP */ ++ s->rst[2] &= ~value; ++ break; ++ case 0x4a0: /* PM_WKEN_WKUP */ ++ s->wken[2] = value & 0x00000005; ++ break; ++ case 0x4b0: /* PM_WKST_WKUP */ ++ s->wkst[2] &= ~value; ++ break; ++ ++ case 0x500: /* CM_CLKEN_PLL */ ++ s->clken[9] = value & 0xcf; ++ /* TODO update clocks */ ++ break; ++ case 0x530: /* CM_AUTOIDLE_PLL */ ++ s->clkidle[5] = value & 0x000000cf; ++ /* TODO update clocks */ ++ break; ++ case 0x540: /* CM_CLKSEL1_PLL */ ++ s->clksel[5] = value & 0x03bfff28; ++ /* TODO update clocks */ ++ break; ++ case 0x544: /* CM_CLKSEL2_PLL */ ++ s->clksel[6] = value & 3; ++ /* TODO update clocks */ ++ break; ++ ++ case 0x800: /* CM_FCLKEN_DSP */ ++ s->clken[10] = value & 0x501; ++ /* TODO update clocks */ ++ break; ++ case 0x810: /* CM_ICLKEN_DSP */ ++ s->clken[11] = value & 0x2; ++ /* TODO update clocks */ ++ break; ++ case 0x830: /* CM_AUTOIDLE_DSP */ ++ s->clkidle[6] = value & 0x2; ++ /* TODO update clocks */ ++ break; ++ case 0x840: /* CM_CLKSEL_DSP */ ++ s->clksel[7] = value & 0x3fff; ++ /* TODO update clocks */ ++ break; ++ case 0x848: /* CM_CLKSTCTRL_DSP */ ++ s->clkctrl[3] = value & 0x101; ++ break; ++ case 0x850: /* RM_RSTCTRL_DSP */ ++ /* TODO: reset */ ++ break; ++ case 0x858: /* RM_RSTST_DSP */ ++ s->rst[3] &= ~value; ++ break; ++ case 0x8c8: /* PM_WKDEP_DSP */ ++ s->wkup[2] = value & 0x13; ++ break; ++ case 0x8e0: /* PM_PWSTCTRL_DSP */ ++ s->power[3] = (value & 0x03017) | (3 << 2); ++ break; ++ ++ case 0x8f0: /* PRCM_IRQSTATUS_DSP */ ++ s->irqst[1] &= ~value; ++ omap_prcm_int_update(s, 1); ++ break; ++ case 0x8f4: /* PRCM_IRQENABLE_DSP */ ++ s->irqen[1] = value & 0x7; ++ omap_prcm_int_update(s, 1); ++ break; ++ ++ case 0x8f8: /* PRCM_IRQSTATUS_IVA */ ++ s->irqst[2] &= ~value; ++ omap_prcm_int_update(s, 2); ++ break; ++ case 0x8fc: /* PRCM_IRQENABLE_IVA */ ++ s->irqen[2] = value & 0x7; ++ omap_prcm_int_update(s, 2); ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ return; ++ } ++} ++ ++static CPUReadMemoryFunc *omap_prcm_readfn[] = { ++ omap_badwidth_read32, ++ omap_badwidth_read32, ++ omap_prcm_read, ++}; ++ ++static CPUWriteMemoryFunc *omap_prcm_writefn[] = { ++ omap_badwidth_write32, ++ omap_badwidth_write32, ++ omap_prcm_write, ++}; ++ ++static void omap_prcm_reset(struct omap_prcm_s *s) ++{ ++ s->sysconfig = 0; ++ s->irqst[0] = 0; ++ s->irqst[1] = 0; ++ s->irqst[2] = 0; ++ s->irqen[0] = 0; ++ s->irqen[1] = 0; ++ s->irqen[2] = 0; ++ s->voltctrl = 0x1040; ++ s->ev = 0x14; ++ s->evtime[0] = 0; ++ s->evtime[1] = 0; ++ s->clkctrl[0] = 0; ++ s->clkctrl[1] = 0; ++ s->clkctrl[2] = 0; ++ s->clkctrl[3] = 0; ++ s->clken[1] = 7; ++ s->clken[3] = 7; ++ s->clken[4] = 0; ++ s->clken[5] = 0; ++ s->clken[6] = 0; ++ s->clken[7] = 0xc; ++ s->clken[8] = 0x3e; ++ s->clken[9] = 0x0d; ++ s->clken[10] = 0; ++ s->clken[11] = 0; ++ s->clkidle[0] = 0; ++ s->clkidle[2] = 7; ++ s->clkidle[3] = 0; ++ s->clkidle[4] = 0; ++ s->clkidle[5] = 0x0c; ++ s->clkidle[6] = 0; ++ s->clksel[0] = 0x01; ++ s->clksel[1] = 0x02100121; ++ s->clksel[2] = 0x00000000; ++ s->clksel[3] = 0x01; ++ s->clksel[4] = 0; ++ s->clksel[7] = 0x0121; ++ s->wkup[0] = 0x15; ++ s->wkup[1] = 0x13; ++ s->wkup[2] = 0x13; ++ s->wken[0] = 0x04667ff8; ++ s->wken[1] = 0x00000005; ++ s->wken[2] = 5; ++ s->wkst[0] = 0; ++ s->wkst[1] = 0; ++ s->wkst[2] = 0; ++ s->power[0] = 0x00c; ++ s->power[1] = 4; ++ s->power[2] = 0x0000c; ++ s->power[3] = 0x14; ++ s->rstctrl[0] = 1; ++ s->rst[3] = 1; ++} ++ ++static void omap_prcm_coldreset(struct omap_prcm_s *s) ++{ ++ s->setuptime[0] = 0; ++ s->setuptime[1] = 0; ++ memset(&s->scratch, 0, sizeof(s->scratch)); ++ s->rst[0] = 0x01; ++ s->rst[1] = 0x00; ++ s->rst[2] = 0x01; ++ s->clken[0] = 0; ++ s->clken[2] = 0; ++ s->clkidle[1] = 0; ++ s->clksel[5] = 0; ++ s->clksel[6] = 2; ++ s->clksrc[0] = 0x43; ++ s->clkout[0] = 0x0303; ++ s->clkemul[0] = 0; ++ s->clkpol[0] = 0x100; ++ s->rsttime_wkup = 0x1002; ++ ++ omap_prcm_reset(s); ++} ++ ++struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta, ++ qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int, ++ struct omap_mpu_state_s *mpu) ++{ ++ int iomemtype; ++ struct omap_prcm_s *s = (struct omap_prcm_s *) ++ qemu_mallocz(sizeof(struct omap_prcm_s)); ++ ++ s->irq[0] = mpu_int; ++ s->irq[1] = dsp_int; ++ s->irq[2] = iva_int; ++ s->mpu = mpu; ++ omap_prcm_coldreset(s); ++ ++ iomemtype = cpu_register_io_memory(0, omap_prcm_readfn, ++ omap_prcm_writefn, s); ++ s->base = omap_l4_attach(ta, 0, iomemtype); ++ omap_l4_attach(ta, 1, iomemtype); ++ ++ return s; ++} ++ ++/* System and Pinout control */ ++struct omap_sysctl_s { ++ target_phys_addr_t base; ++ struct omap_mpu_state_s *mpu; ++ ++ uint32_t sysconfig; ++ uint32_t devconfig; ++ uint32_t psaconfig; ++ uint32_t padconf[0x45]; ++ uint8_t obs; ++ uint32_t msuspendmux[5]; ++}; ++ ++static uint32_t omap_sysctl_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque; ++ int offset = addr - s->base; ++ ++ switch (offset) { ++ case 0x000: /* CONTROL_REVISION */ ++ return 0x20; ++ ++ case 0x010: /* CONTROL_SYSCONFIG */ ++ return s->sysconfig; ++ ++ case 0x030 ... 0x140: /* CONTROL_PADCONF - only used in the POP */ ++ return s->padconf[(offset - 0x30) >> 2]; ++ ++ case 0x270: /* CONTROL_DEBOBS */ ++ return s->obs; ++ ++ case 0x274: /* CONTROL_DEVCONF */ ++ return s->devconfig; ++ ++ case 0x28c: /* CONTROL_EMU_SUPPORT */ ++ return 0; ++ ++ case 0x290: /* CONTROL_MSUSPENDMUX_0 */ ++ return s->msuspendmux[0]; ++ case 0x294: /* CONTROL_MSUSPENDMUX_1 */ ++ return s->msuspendmux[1]; ++ case 0x298: /* CONTROL_MSUSPENDMUX_2 */ ++ return s->msuspendmux[2]; ++ case 0x29c: /* CONTROL_MSUSPENDMUX_3 */ ++ return s->msuspendmux[3]; ++ case 0x2a0: /* CONTROL_MSUSPENDMUX_4 */ ++ return s->msuspendmux[4]; ++ case 0x2a4: /* CONTROL_MSUSPENDMUX_5 */ ++ return 0; ++ ++ case 0x2b8: /* CONTROL_PSA_CTRL */ ++ return s->psaconfig; ++ case 0x2bc: /* CONTROL_PSA_CMD */ ++ case 0x2c0: /* CONTROL_PSA_VALUE */ ++ return 0; ++ ++ case 0x2b0: /* CONTROL_SEC_CTRL */ ++ return 0x800000f1; ++ case 0x2d0: /* CONTROL_SEC_EMU */ ++ return 0x80000015; ++ case 0x2d4: /* CONTROL_SEC_TAP */ ++ return 0x8000007f; ++ case 0x2b4: /* CONTROL_SEC_TEST */ ++ case 0x2f0: /* CONTROL_SEC_STATUS */ ++ case 0x2f4: /* CONTROL_SEC_ERR_STATUS */ ++ /* Secure mode is not present on general-pusrpose device. Outside ++ * secure mode these values cannot be read or written. */ ++ return 0; ++ ++ case 0x2d8: /* CONTROL_OCM_RAM_PERM */ ++ return 0xff; ++ case 0x2dc: /* CONTROL_OCM_PUB_RAM_ADD */ ++ case 0x2e0: /* CONTROL_EXT_SEC_RAM_START_ADD */ ++ case 0x2e4: /* CONTROL_EXT_SEC_RAM_STOP_ADD */ ++ /* No secure mode so no Extended Secure RAM present. */ ++ return 0; ++ ++ case 0x2f8: /* CONTROL_STATUS */ ++ /* Device Type => General-purpose */ ++ return 0x0300; ++ case 0x2fc: /* CONTROL_GENERAL_PURPOSE_STATUS */ ++ ++ case 0x300: /* CONTROL_RPUB_KEY_H_0 */ ++ case 0x304: /* CONTROL_RPUB_KEY_H_1 */ ++ case 0x308: /* CONTROL_RPUB_KEY_H_2 */ ++ case 0x30c: /* CONTROL_RPUB_KEY_H_3 */ ++ return 0xdecafbad; ++ ++ case 0x310: /* CONTROL_RAND_KEY_0 */ ++ case 0x314: /* CONTROL_RAND_KEY_1 */ ++ case 0x318: /* CONTROL_RAND_KEY_2 */ ++ case 0x31c: /* CONTROL_RAND_KEY_3 */ ++ case 0x320: /* CONTROL_CUST_KEY_0 */ ++ case 0x324: /* CONTROL_CUST_KEY_1 */ ++ case 0x330: /* CONTROL_TEST_KEY_0 */ ++ case 0x334: /* CONTROL_TEST_KEY_1 */ ++ case 0x338: /* CONTROL_TEST_KEY_2 */ ++ case 0x33c: /* CONTROL_TEST_KEY_3 */ ++ case 0x340: /* CONTROL_TEST_KEY_4 */ ++ case 0x344: /* CONTROL_TEST_KEY_5 */ ++ case 0x348: /* CONTROL_TEST_KEY_6 */ ++ case 0x34c: /* CONTROL_TEST_KEY_7 */ ++ case 0x350: /* CONTROL_TEST_KEY_8 */ ++ case 0x354: /* CONTROL_TEST_KEY_9 */ ++ /* Can only be accessed in secure mode and when C_FieldAccEnable ++ * bit is set in CONTROL_SEC_CTRL. ++ * TODO: otherwise an interconnect access error is generated. */ ++ return 0; ++ } ++ ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap_sysctl_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque; ++ int offset = addr - s->base; ++ ++ switch (offset) { ++ case 0x000: /* CONTROL_REVISION */ ++ case 0x2a4: /* CONTROL_MSUSPENDMUX_5 */ ++ case 0x2c0: /* CONTROL_PSA_VALUE */ ++ case 0x2f8: /* CONTROL_STATUS */ ++ case 0x2fc: /* CONTROL_GENERAL_PURPOSE_STATUS */ ++ case 0x300: /* CONTROL_RPUB_KEY_H_0 */ ++ case 0x304: /* CONTROL_RPUB_KEY_H_1 */ ++ case 0x308: /* CONTROL_RPUB_KEY_H_2 */ ++ case 0x30c: /* CONTROL_RPUB_KEY_H_3 */ ++ case 0x310: /* CONTROL_RAND_KEY_0 */ ++ case 0x314: /* CONTROL_RAND_KEY_1 */ ++ case 0x318: /* CONTROL_RAND_KEY_2 */ ++ case 0x31c: /* CONTROL_RAND_KEY_3 */ ++ case 0x320: /* CONTROL_CUST_KEY_0 */ ++ case 0x324: /* CONTROL_CUST_KEY_1 */ ++ case 0x330: /* CONTROL_TEST_KEY_0 */ ++ case 0x334: /* CONTROL_TEST_KEY_1 */ ++ case 0x338: /* CONTROL_TEST_KEY_2 */ ++ case 0x33c: /* CONTROL_TEST_KEY_3 */ ++ case 0x340: /* CONTROL_TEST_KEY_4 */ ++ case 0x344: /* CONTROL_TEST_KEY_5 */ ++ case 0x348: /* CONTROL_TEST_KEY_6 */ ++ case 0x34c: /* CONTROL_TEST_KEY_7 */ ++ case 0x350: /* CONTROL_TEST_KEY_8 */ ++ case 0x354: /* CONTROL_TEST_KEY_9 */ ++ OMAP_RO_REG(addr); ++ return; ++ ++ case 0x010: /* CONTROL_SYSCONFIG */ ++ s->sysconfig = value & 0x1e; ++ break; ++ ++ case 0x030 ... 0x140: /* CONTROL_PADCONF - only used in the POP */ ++ /* XXX: should check constant bits */ ++ s->padconf[(offset - 0x30) >> 2] = value & 0x1f1f1f1f; ++ break; ++ ++ case 0x270: /* CONTROL_DEBOBS */ ++ s->obs = value & 0xff; ++ break; ++ ++ case 0x274: /* CONTROL_DEVCONF */ ++ s->devconfig = value & 0xffffc7ff; ++ break; ++ ++ case 0x28c: /* CONTROL_EMU_SUPPORT */ ++ break; ++ ++ case 0x290: /* CONTROL_MSUSPENDMUX_0 */ ++ s->msuspendmux[0] = value & 0x3fffffff; ++ break; ++ case 0x294: /* CONTROL_MSUSPENDMUX_1 */ ++ s->msuspendmux[1] = value & 0x3fffffff; ++ break; ++ case 0x298: /* CONTROL_MSUSPENDMUX_2 */ ++ s->msuspendmux[2] = value & 0x3fffffff; ++ break; ++ case 0x29c: /* CONTROL_MSUSPENDMUX_3 */ ++ s->msuspendmux[3] = value & 0x3fffffff; ++ break; ++ case 0x2a0: /* CONTROL_MSUSPENDMUX_4 */ ++ s->msuspendmux[4] = value & 0x3fffffff; ++ break; ++ ++ case 0x2b8: /* CONTROL_PSA_CTRL */ ++ s->psaconfig = value & 0x1c; ++ s->psaconfig |= (value & 0x20) ? 2 : 1; ++ break; ++ case 0x2bc: /* CONTROL_PSA_CMD */ ++ break; ++ ++ case 0x2b0: /* CONTROL_SEC_CTRL */ ++ case 0x2b4: /* CONTROL_SEC_TEST */ ++ case 0x2d0: /* CONTROL_SEC_EMU */ ++ case 0x2d4: /* CONTROL_SEC_TAP */ ++ case 0x2d8: /* CONTROL_OCM_RAM_PERM */ ++ case 0x2dc: /* CONTROL_OCM_PUB_RAM_ADD */ ++ case 0x2e0: /* CONTROL_EXT_SEC_RAM_START_ADD */ ++ case 0x2e4: /* CONTROL_EXT_SEC_RAM_STOP_ADD */ ++ case 0x2f0: /* CONTROL_SEC_STATUS */ ++ case 0x2f4: /* CONTROL_SEC_ERR_STATUS */ ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ return; ++ } ++} ++ ++static CPUReadMemoryFunc *omap_sysctl_readfn[] = { ++ omap_badwidth_read32, /* TODO */ ++ omap_badwidth_read32, /* TODO */ ++ omap_sysctl_read, ++}; ++ ++static CPUWriteMemoryFunc *omap_sysctl_writefn[] = { ++ omap_badwidth_write32, /* TODO */ ++ omap_badwidth_write32, /* TODO */ ++ omap_sysctl_write, ++}; ++ ++static void omap_sysctl_reset(struct omap_sysctl_s *s) ++{ ++ /* (power-on reset) */ ++ s->sysconfig = 0; ++ s->obs = 0; ++ s->devconfig = 0x0c000000; ++ s->msuspendmux[0] = 0x00000000; ++ s->msuspendmux[1] = 0x00000000; ++ s->msuspendmux[2] = 0x00000000; ++ s->msuspendmux[3] = 0x00000000; ++ s->msuspendmux[4] = 0x00000000; ++ s->psaconfig = 1; ++ ++ s->padconf[0x00] = 0x000f0f0f; ++ s->padconf[0x01] = 0x00000000; ++ s->padconf[0x02] = 0x00000000; ++ s->padconf[0x03] = 0x00000000; ++ s->padconf[0x04] = 0x00000000; ++ s->padconf[0x05] = 0x00000000; ++ s->padconf[0x06] = 0x00000000; ++ s->padconf[0x07] = 0x00000000; ++ s->padconf[0x08] = 0x08080800; ++ s->padconf[0x09] = 0x08080808; ++ s->padconf[0x0a] = 0x08080808; ++ s->padconf[0x0b] = 0x08080808; ++ s->padconf[0x0c] = 0x08080808; ++ s->padconf[0x0d] = 0x08080800; ++ s->padconf[0x0e] = 0x08080808; ++ s->padconf[0x0f] = 0x08080808; ++ s->padconf[0x10] = 0x18181808; /* | 0x07070700 if SBoot3 */ ++ s->padconf[0x11] = 0x18181818; /* | 0x07070707 if SBoot3 */ ++ s->padconf[0x12] = 0x18181818; /* | 0x07070707 if SBoot3 */ ++ s->padconf[0x13] = 0x18181818; /* | 0x07070707 if SBoot3 */ ++ s->padconf[0x14] = 0x18181818; /* | 0x00070707 if SBoot3 */ ++ s->padconf[0x15] = 0x18181818; ++ s->padconf[0x16] = 0x18181818; /* | 0x07000000 if SBoot3 */ ++ s->padconf[0x17] = 0x1f001f00; ++ s->padconf[0x18] = 0x1f1f1f1f; ++ s->padconf[0x19] = 0x00000000; ++ s->padconf[0x1a] = 0x1f180000; ++ s->padconf[0x1b] = 0x00001f1f; ++ s->padconf[0x1c] = 0x1f001f00; ++ s->padconf[0x1d] = 0x00000000; ++ s->padconf[0x1e] = 0x00000000; ++ s->padconf[0x1f] = 0x08000000; ++ s->padconf[0x20] = 0x08080808; ++ s->padconf[0x21] = 0x08080808; ++ s->padconf[0x22] = 0x0f080808; ++ s->padconf[0x23] = 0x0f0f0f0f; ++ s->padconf[0x24] = 0x000f0f0f; ++ s->padconf[0x25] = 0x1f1f1f0f; ++ s->padconf[0x26] = 0x080f0f1f; ++ s->padconf[0x27] = 0x070f1808; ++ s->padconf[0x28] = 0x0f070707; ++ s->padconf[0x29] = 0x000f0f1f; ++ s->padconf[0x2a] = 0x0f0f0f1f; ++ s->padconf[0x2b] = 0x08000000; ++ s->padconf[0x2c] = 0x0000001f; ++ s->padconf[0x2d] = 0x0f0f1f00; ++ s->padconf[0x2e] = 0x1f1f0f0f; ++ s->padconf[0x2f] = 0x0f1f1f1f; ++ s->padconf[0x30] = 0x0f0f0f0f; ++ s->padconf[0x31] = 0x0f1f0f1f; ++ s->padconf[0x32] = 0x0f0f0f0f; ++ s->padconf[0x33] = 0x0f1f0f1f; ++ s->padconf[0x34] = 0x1f1f0f0f; ++ s->padconf[0x35] = 0x0f0f1f1f; ++ s->padconf[0x36] = 0x0f0f1f0f; ++ s->padconf[0x37] = 0x0f0f0f0f; ++ s->padconf[0x38] = 0x1f18180f; ++ s->padconf[0x39] = 0x1f1f1f1f; ++ s->padconf[0x3a] = 0x00001f1f; ++ s->padconf[0x3b] = 0x00000000; ++ s->padconf[0x3c] = 0x00000000; ++ s->padconf[0x3d] = 0x0f0f0f0f; ++ s->padconf[0x3e] = 0x18000f0f; ++ s->padconf[0x3f] = 0x00070000; ++ s->padconf[0x40] = 0x00000707; ++ s->padconf[0x41] = 0x0f1f0700; ++ s->padconf[0x42] = 0x1f1f070f; ++ s->padconf[0x43] = 0x0008081f; ++ s->padconf[0x44] = 0x00000800; ++} ++ ++struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta, ++ omap_clk iclk, struct omap_mpu_state_s *mpu) ++{ ++ int iomemtype; ++ struct omap_sysctl_s *s = (struct omap_sysctl_s *) ++ qemu_mallocz(sizeof(struct omap_sysctl_s)); ++ ++ s->mpu = mpu; ++ omap_sysctl_reset(s); ++ ++ iomemtype = cpu_register_io_memory(0, omap_sysctl_readfn, ++ omap_sysctl_writefn, s); ++ s->base = omap_l4_attach(ta, 0, iomemtype); ++ omap_l4_attach(ta, 0, iomemtype); ++ ++ return s; ++} ++ ++/* SDRAM Controller Subsystem */ ++struct omap_sdrc_s { ++ target_phys_addr_t base; ++ ++ uint8_t config; ++}; ++ ++static void omap_sdrc_reset(struct omap_sdrc_s *s) ++{ ++ s->config = 0x10; ++} ++ ++static uint32_t omap_sdrc_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque; ++ int offset = addr - s->base; ++ ++ switch (offset) { ++ case 0x00: /* SDRC_REVISION */ ++ return 0x20; ++ ++ case 0x10: /* SDRC_SYSCONFIG */ ++ return s->config; ++ ++ case 0x14: /* SDRC_SYSSTATUS */ ++ return 1; /* RESETDONE */ ++ ++ case 0x40: /* SDRC_CS_CFG */ ++ case 0x44: /* SDRC_SHARING */ ++ case 0x48: /* SDRC_ERR_ADDR */ ++ case 0x4c: /* SDRC_ERR_TYPE */ ++ case 0x60: /* SDRC_DLLA_SCTRL */ ++ case 0x64: /* SDRC_DLLA_STATUS */ ++ 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; ++ } ++ ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap_sdrc_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque; ++ int offset = addr - s->base; ++ ++ switch (offset) { ++ case 0x00: /* SDRC_REVISION */ ++ case 0x14: /* SDRC_SYSSTATUS */ ++ case 0x48: /* SDRC_ERR_ADDR */ ++ case 0x64: /* SDRC_DLLA_STATUS */ ++ case 0x6c: /* SDRC_DLLB_STATUS */ ++ OMAP_RO_REG(addr); ++ return; ++ ++ case 0x10: /* SDRC_SYSCONFIG */ ++ if ((value >> 3) != 0x2) ++ fprintf(stderr, "%s: bad SDRAM idle mode %i\n", ++ __FUNCTION__, value >> 3); ++ if (value & 2) ++ omap_sdrc_reset(s); ++ s->config = value & 0x18; ++ break; ++ ++ case 0x40: /* SDRC_CS_CFG */ ++ case 0x44: /* SDRC_SHARING */ ++ case 0x4c: /* SDRC_ERR_TYPE */ ++ case 0x60: /* SDRC_DLLA_SCTRL */ ++ 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 */ ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ return; ++ } ++} ++ ++static CPUReadMemoryFunc *omap_sdrc_readfn[] = { ++ omap_badwidth_read32, ++ omap_badwidth_read32, ++ omap_sdrc_read, ++}; ++ ++static CPUWriteMemoryFunc *omap_sdrc_writefn[] = { ++ omap_badwidth_write32, ++ omap_badwidth_write32, ++ omap_sdrc_write, ++}; ++ ++struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base) ++{ ++ int iomemtype; ++ struct omap_sdrc_s *s = (struct omap_sdrc_s *) ++ qemu_mallocz(sizeof(struct omap_sdrc_s)); ++ ++ s->base = base; ++ omap_sdrc_reset(s); ++ ++ iomemtype = cpu_register_io_memory(0, omap_sdrc_readfn, ++ omap_sdrc_writefn, s); ++ cpu_register_physical_memory(s->base, 0x1000, iomemtype); ++ ++ return s; ++} ++ ++/* General-Purpose Memory Controller */ ++struct omap_gpmc_s { ++ target_phys_addr_t base; ++ qemu_irq irq; ++ ++ uint8_t sysconfig; ++ uint16_t irqst; ++ uint16_t irqen; ++ uint16_t timeout; ++ uint16_t config; ++ uint32_t prefconfig[2]; ++ int prefcontrol; ++ int preffifo; ++ int prefcount; ++ struct omap_gpmc_cs_file_s { ++ uint32_t config[7]; ++ target_phys_addr_t base; ++ size_t size; ++ int iomemtype; ++ void (*base_update)(void *opaque, target_phys_addr_t new); ++ void (*unmap)(void *opaque); ++ void *opaque; ++ } cs_file[8]; ++ int ecc_cs; ++ int ecc_ptr; ++ uint32_t ecc_cfg; ++ struct ecc_state_s ecc[9]; ++}; ++ ++static void omap_gpmc_int_update(struct omap_gpmc_s *s) ++{ ++ qemu_set_irq(s->irq, s->irqen & s->irqst); ++} ++ ++static void omap_gpmc_cs_map(struct omap_gpmc_cs_file_s *f, int base, int mask) ++{ ++ /* TODO: check for overlapping regions and report access errors */ ++ if ((mask != 0x8 && mask != 0xc && mask != 0xe && mask != 0xf) || ++ (base < 0 || base >= 0x40) || ++ (base & 0x0f & ~mask)) { ++ fprintf(stderr, "%s: wrong cs address mapping/decoding!\n", ++ __FUNCTION__); ++ return; ++ } ++ ++ if (!f->opaque) ++ return; ++ ++ f->base = base << 24; ++ f->size = (0x0fffffff & ~(mask << 24)) + 1; ++ /* TODO: rather than setting the size of the mapping (which should be ++ * constant), the mask should cause wrapping of the address space, so ++ * that the same memory becomes accessible at every size bytes ++ * starting from base. */ ++ if (f->iomemtype) ++ cpu_register_physical_memory(f->base, f->size, f->iomemtype); ++ ++ if (f->base_update) ++ f->base_update(f->opaque, f->base); ++} ++ ++static void omap_gpmc_cs_unmap(struct omap_gpmc_cs_file_s *f) ++{ ++ if (f->size) { ++ if (f->unmap) ++ f->unmap(f->opaque); ++ if (f->iomemtype) ++ cpu_register_physical_memory(f->base, f->size, IO_MEM_UNASSIGNED); ++ f->base = 0; ++ f->size = 0; ++ } ++} ++ ++static void omap_gpmc_reset(struct omap_gpmc_s *s) ++{ ++ int i; ++ ++ s->sysconfig = 0; ++ s->irqst = 0; ++ s->irqen = 0; ++ omap_gpmc_int_update(s); ++ s->timeout = 0; ++ s->config = 0xa00; ++ s->prefconfig[0] = 0x00004000; ++ s->prefconfig[1] = 0x00000000; ++ s->prefcontrol = 0; ++ s->preffifo = 0; ++ s->prefcount = 0; ++ for (i = 0; i < 8; i ++) { ++ if (s->cs_file[i].config[6] & (1 << 6)) /* CSVALID */ ++ omap_gpmc_cs_unmap(s->cs_file + i); ++ s->cs_file[i].config[0] = i ? 1 << 12 : 0; ++ s->cs_file[i].config[1] = 0x101001; ++ s->cs_file[i].config[2] = 0x020201; ++ s->cs_file[i].config[3] = 0x10031003; ++ s->cs_file[i].config[4] = 0x10f1111; ++ s->cs_file[i].config[5] = 0; ++ 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] >> 8 & 0xf)); /* BASEADDR */ ++ } ++ omap_gpmc_cs_map(s->cs_file, 0, 0xf); ++ s->ecc_cs = 0; ++ s->ecc_ptr = 0; ++ s->ecc_cfg = 0x3fcff000; ++ for (i = 0; i < 9; i ++) ++ ecc_reset(&s->ecc[i]); ++} ++ ++static uint32_t omap_gpmc_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque; ++ int offset = addr - s->base; ++ int cs; ++ struct omap_gpmc_cs_file_s *f; ++ ++ switch (offset) { ++ case 0x000: /* GPMC_REVISION */ ++ return 0x20; ++ ++ case 0x010: /* GPMC_SYSCONFIG */ ++ return s->sysconfig; ++ ++ case 0x014: /* GPMC_SYSSTATUS */ ++ return 1; /* RESETDONE */ ++ ++ case 0x018: /* GPMC_IRQSTATUS */ ++ return s->irqst; ++ ++ case 0x01c: /* GPMC_IRQENABLE */ ++ return s->irqen; ++ ++ case 0x040: /* GPMC_TIMEOUT_CONTROL */ ++ return s->timeout; ++ ++ case 0x044: /* GPMC_ERR_ADDRESS */ ++ case 0x048: /* GPMC_ERR_TYPE */ ++ return 0; ++ ++ case 0x050: /* GPMC_CONFIG */ ++ return s->config; ++ ++ case 0x054: /* GPMC_STATUS */ ++ return 0x001; ++ ++ case 0x060 ... 0x1d4: ++ cs = (offset - 0x060) / 0x30; ++ offset -= cs * 0x30; ++ f = s->cs_file + cs; ++ switch (offset - cs * 0x30) { ++ case 0x60: /* GPMC_CONFIG1 */ ++ return f->config[0]; ++ case 0x64: /* GPMC_CONFIG2 */ ++ return f->config[1]; ++ case 0x68: /* GPMC_CONFIG3 */ ++ return f->config[2]; ++ case 0x6c: /* GPMC_CONFIG4 */ ++ return f->config[3]; ++ case 0x70: /* GPMC_CONFIG5 */ ++ return f->config[4]; ++ case 0x74: /* GPMC_CONFIG6 */ ++ return f->config[5]; ++ case 0x78: /* GPMC_CONFIG7 */ ++ return f->config[6]; ++ case 0x84: /* GPMC_NAND_DATA */ ++ return 0; ++ } ++ break; ++ ++ case 0x1e0: /* GPMC_PREFETCH_CONFIG1 */ ++ return s->prefconfig[0]; ++ case 0x1e4: /* GPMC_PREFETCH_CONFIG2 */ ++ return s->prefconfig[1]; ++ case 0x1ec: /* GPMC_PREFETCH_CONTROL */ ++ return s->prefcontrol; ++ case 0x1f0: /* GPMC_PREFETCH_STATUS */ ++ return (s->preffifo << 24) | ++ ((s->preffifo > ++ ((s->prefconfig[0] >> 8) & 0x7f) ? 1 : 0) << 16) | ++ s->prefcount; ++ ++ case 0x1f4: /* GPMC_ECC_CONFIG */ ++ return s->ecc_cs; ++ case 0x1f8: /* GPMC_ECC_CONTROL */ ++ return s->ecc_ptr; ++ case 0x1fc: /* GPMC_ECC_SIZE_CONFIG */ ++ return s->ecc_cfg; ++ case 0x200 ... 0x220: /* GPMC_ECC_RESULT */ ++ cs = (offset & 0x1f) >> 2; ++ /* TODO: check correctness */ ++ return ++ ((s->ecc[cs].cp & 0x07) << 0) | ++ ((s->ecc[cs].cp & 0x38) << 13) | ++ ((s->ecc[cs].lp[0] & 0x1ff) << 3) | ++ ((s->ecc[cs].lp[1] & 0x1ff) << 19); ++ ++ case 0x230: /* GPMC_TESTMODE_CTRL */ ++ return 0; ++ case 0x234: /* GPMC_PSA_LSB */ ++ case 0x238: /* GPMC_PSA_MSB */ ++ return 0x00000000; ++ } ++ ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap_gpmc_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque; ++ int offset = addr - s->base; ++ int cs; ++ struct omap_gpmc_cs_file_s *f; ++ ++ switch (offset) { ++ case 0x000: /* GPMC_REVISION */ ++ case 0x014: /* GPMC_SYSSTATUS */ ++ case 0x054: /* GPMC_STATUS */ ++ case 0x1f0: /* GPMC_PREFETCH_STATUS */ ++ case 0x200 ... 0x220: /* GPMC_ECC_RESULT */ ++ case 0x234: /* GPMC_PSA_LSB */ ++ case 0x238: /* GPMC_PSA_MSB */ ++ OMAP_RO_REG(addr); ++ break; ++ ++ case 0x010: /* GPMC_SYSCONFIG */ ++ if ((value >> 3) == 0x3) ++ fprintf(stderr, "%s: bad SDRAM idle mode %i\n", ++ __FUNCTION__, value >> 3); ++ if (value & 2) ++ omap_gpmc_reset(s); ++ s->sysconfig = value & 0x19; ++ break; ++ ++ case 0x018: /* GPMC_IRQSTATUS */ ++ s->irqen = ~value; ++ omap_gpmc_int_update(s); ++ break; ++ ++ case 0x01c: /* GPMC_IRQENABLE */ ++ s->irqen = value & 0xf03; ++ omap_gpmc_int_update(s); ++ break; ++ ++ case 0x040: /* GPMC_TIMEOUT_CONTROL */ ++ s->timeout = value & 0x1ff1; ++ break; ++ ++ case 0x044: /* GPMC_ERR_ADDRESS */ ++ case 0x048: /* GPMC_ERR_TYPE */ ++ break; ++ ++ case 0x050: /* GPMC_CONFIG */ ++ s->config = value & 0xf13; ++ break; ++ ++ case 0x060 ... 0x1d4: ++ cs = (offset - 0x060) / 0x30; ++ offset -= cs * 0x30; ++ f = s->cs_file + cs; ++ switch (offset - cs * 0x30) { ++ case 0x60: /* GPMC_CONFIG1 */ ++ f->config[0] = value & 0xffef3e13; ++ break; ++ case 0x64: /* GPMC_CONFIG2 */ ++ f->config[1] = value & 0x001f1f8f; ++ break; ++ case 0x68: /* GPMC_CONFIG3 */ ++ f->config[2] = value & 0x001f1f8f; ++ break; ++ case 0x6c: /* GPMC_CONFIG4 */ ++ f->config[3] = value & 0x1f8f1f8f; ++ break; ++ case 0x70: /* GPMC_CONFIG5 */ ++ f->config[4] = value & 0x0f1f1f1f; ++ break; ++ case 0x74: /* GPMC_CONFIG6 */ ++ f->config[5] = value & 0x00000fcf; ++ break; ++ case 0x78: /* GPMC_CONFIG7 */ ++ if ((f->config[6] ^ value) & 0xf7f) { ++ 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 */ ++ (value >> 8 & 0xf)); /* BASEADDR */ ++ } ++ f->config[6] = value & 0x00000f7f; ++ break; ++ case 0x7c: /* GPMC_NAND_COMMAND */ ++ case 0x80: /* GPMC_NAND_ADDRESS */ ++ case 0x84: /* GPMC_NAND_DATA */ ++ break; ++ ++ default: ++ goto bad_reg; ++ } ++ break; ++ ++ case 0x1e0: /* GPMC_PREFETCH_CONFIG1 */ ++ s->prefconfig[0] = value & 0x7f8f7fbf; ++ /* TODO: update interrupts, fifos, dmas */ ++ break; ++ ++ case 0x1e4: /* GPMC_PREFETCH_CONFIG2 */ ++ s->prefconfig[1] = value & 0x3fff; ++ break; ++ ++ case 0x1ec: /* GPMC_PREFETCH_CONTROL */ ++ s->prefcontrol = value & 1; ++ if (s->prefcontrol) { ++ if (s->prefconfig[0] & 1) ++ s->preffifo = 0x40; ++ else ++ s->preffifo = 0x00; ++ } ++ /* TODO: start */ ++ break; ++ ++ case 0x1f4: /* GPMC_ECC_CONFIG */ ++ s->ecc_cs = 0x8f; ++ break; ++ case 0x1f8: /* GPMC_ECC_CONTROL */ ++ if (value & (1 << 8)) ++ for (cs = 0; cs < 9; cs ++) ++ ecc_reset(&s->ecc[cs]); ++ s->ecc_ptr = value & 0xf; ++ if (s->ecc_ptr == 0 || s->ecc_ptr > 9) { ++ s->ecc_ptr = 0; ++ s->ecc_cs &= ~1; ++ } ++ break; ++ case 0x1fc: /* GPMC_ECC_SIZE_CONFIG */ ++ s->ecc_cfg = value & 0x3fcff1ff; ++ break; ++ case 0x230: /* GPMC_TESTMODE_CTRL */ ++ if (value & 7) ++ fprintf(stderr, "%s: test mode enable attempt\n", __FUNCTION__); ++ break; ++ ++ default: ++ bad_reg: ++ OMAP_BAD_REG(addr); ++ return; ++ } ++} ++ ++static CPUReadMemoryFunc *omap_gpmc_readfn[] = { ++ omap_badwidth_read32, /* TODO */ ++ omap_badwidth_read32, /* TODO */ ++ omap_gpmc_read, ++}; ++ ++static CPUWriteMemoryFunc *omap_gpmc_writefn[] = { ++ omap_badwidth_write32, /* TODO */ ++ omap_badwidth_write32, /* TODO */ ++ omap_gpmc_write, ++}; ++ ++struct omap_gpmc_s *omap_gpmc_init(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->base = base; ++ omap_gpmc_reset(s); ++ ++ iomemtype = cpu_register_io_memory(0, omap_gpmc_readfn, ++ omap_gpmc_writefn, s); ++ cpu_register_physical_memory(s->base, 0x1000, iomemtype); ++ ++ return s; ++} ++ ++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) ++{ ++ struct omap_gpmc_cs_file_s *f; ++ ++ if (cs < 0 || cs >= 8) { ++ fprintf(stderr, "%s: bad chip-select %i\n", __FUNCTION__, cs); ++ exit(-1); ++ } ++ f = &s->cs_file[cs]; ++ ++ f->iomemtype = iomemtype; ++ f->base_update = base_upd; ++ f->unmap = unmap; ++ f->opaque = opaque; ++ ++ if (f->config[6] & (1 << 6)) /* CSVALID */ ++ omap_gpmc_cs_map(f, f->config[6] & 0x1f, /* MASKADDR */ ++ (f->config[6] >> 8 & 0xf)); /* BASEADDR */ ++} ++ ++/* General chip reset */ ++static void omap2_mpu_reset(void *opaque) ++{ ++ struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque; ++ ++ omap_inth_reset(mpu->ih[0]); ++ omap_dma_reset(mpu->dma); ++ omap_prcm_reset(mpu->prcm); ++ omap_sysctl_reset(mpu->sysc); ++ omap_gp_timer_reset(mpu->gptimer[0]); ++ omap_gp_timer_reset(mpu->gptimer[1]); ++ omap_gp_timer_reset(mpu->gptimer[2]); ++ omap_gp_timer_reset(mpu->gptimer[3]); ++ omap_gp_timer_reset(mpu->gptimer[4]); ++ omap_gp_timer_reset(mpu->gptimer[5]); ++ omap_gp_timer_reset(mpu->gptimer[6]); ++ omap_gp_timer_reset(mpu->gptimer[7]); ++ omap_gp_timer_reset(mpu->gptimer[8]); ++ omap_gp_timer_reset(mpu->gptimer[9]); ++ omap_gp_timer_reset(mpu->gptimer[10]); ++ omap_gp_timer_reset(mpu->gptimer[11]); ++ omap_synctimer_reset(&mpu->synctimer); ++ omap_sdrc_reset(mpu->sdrc); ++ omap_gpmc_reset(mpu->gpmc); ++ omap_dss_reset(mpu->dss); ++#if 0 ++ omap_wd_timer_reset(mpu->wdt); ++ omap_ulpd_pm_reset(mpu); ++ omap_pin_cfg_reset(mpu); ++ omap_mpui_reset(mpu); ++ omap_tipb_bridge_reset(mpu->private_tipb); ++ omap_tipb_bridge_reset(mpu->public_tipb); ++ omap_dpll_reset(&mpu->dpll[0]); ++ omap_dpll_reset(&mpu->dpll[1]); ++ omap_dpll_reset(&mpu->dpll[2]); ++#endif ++ omap_uart_reset(mpu->uart[0]); ++ omap_uart_reset(mpu->uart[1]); ++ omap_uart_reset(mpu->uart[2]); ++ omap_mmc_reset(mpu->mmc); ++ omap_gpif_reset(mpu->gpif); ++ omap_mcspi_reset(mpu->mcspi[0]); ++ omap_mcspi_reset(mpu->mcspi[1]); ++#if 0 ++ omap_pwl_reset(mpu); ++ omap_pwt_reset(mpu); ++#endif ++ omap_i2c_reset(mpu->i2c[0]); ++ omap_i2c_reset(mpu->i2c[1]); ++#if 0 ++ omap_rtc_reset(mpu->rtc); ++ omap_mcbsp_reset(mpu->mcbsp1); ++ omap_mcbsp_reset(mpu->mcbsp2); ++ omap_mcbsp_reset(mpu->mcbsp3); ++ omap_lpg_reset(mpu->led[0]); ++ omap_lpg_reset(mpu->led[1]); ++ omap_clkm_reset(mpu); ++#endif ++ cpu_reset(mpu->env); ++} ++ ++static int omap2_validate_addr(struct omap_mpu_state_s *s, ++ target_phys_addr_t addr) ++{ ++ return 1; ++} ++ ++static const struct dma_irq_map omap2_dma_irq_map[] = { ++ { 0, OMAP_INT_24XX_SDMA_IRQ0 }, ++ { 0, OMAP_INT_24XX_SDMA_IRQ1 }, ++ { 0, OMAP_INT_24XX_SDMA_IRQ2 }, ++ { 0, OMAP_INT_24XX_SDMA_IRQ3 }, ++}; ++ ++struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size, ++ DisplayState *ds, 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, q3_base; ++ qemu_irq *cpu_irq; ++ qemu_irq dma_irqs[4]; ++ omap_clk gpio_clks[4]; ++ int sdindex; ++ int i; ++ ++ /* Core */ ++ s->mpu_model = omap2420; ++ s->env = cpu_init(core ?: "arm1136-r2"); ++ if (!s->env) { ++ fprintf(stderr, "Unable to find CPU definition\n"); ++ exit(1); ++ } ++ s->sdram_size = sdram_size; ++ s->sram_size = OMAP242X_SRAM_SIZE; ++ ++ s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0]; ++ ++ /* Clocks */ ++ omap_clk_init(s); ++ ++ /* Memory-mapped stuff */ ++ cpu_register_physical_memory(OMAP2_Q2_BASE, s->sdram_size, ++ (q3_base = qemu_ram_alloc(s->sdram_size)) | IO_MEM_RAM); ++ cpu_register_physical_memory(OMAP2_SRAM_BASE, s->sram_size, ++ (sram_base = qemu_ram_alloc(s->sram_size)) | IO_MEM_RAM); ++ ++ s->l4 = omap_l4_init(OMAP2_L4_BASE, 54); ++ ++ /* 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], ++ cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ], ++ omap_findclk(s, "mpu_intc_fclk"), ++ omap_findclk(s, "mpu_intc_iclk")); ++ ++ s->prcm = omap_prcm_init(omap_l4tao(s->l4, 3), ++ s->irq[0][OMAP_INT_24XX_PRCM_MPU_IRQ], NULL, NULL, s); ++ ++ s->sysc = omap_sysctl_init(omap_l4tao(s->l4, 1), ++ omap_findclk(s, "omapctrl_iclk"), s); ++ ++ for (i = 0; i < 4; i ++) ++ dma_irqs[i] = ++ s->irq[omap2_dma_irq_map[i].ih][omap2_dma_irq_map[i].intr]; ++ s->dma = omap_dma4_init(0x48056000, dma_irqs, s, 256, 32, ++ omap_findclk(s, "sdma_iclk"), ++ omap_findclk(s, "sdma_fclk")); ++ s->port->addr_valid = omap2_validate_addr; ++ ++ s->uart[0] = omap2_uart_init(omap_l4ta(s->l4, 19), ++ s->irq[0][OMAP_INT_24XX_UART1_IRQ], ++ omap_findclk(s, "uart1_fclk"), ++ omap_findclk(s, "uart1_iclk"), ++ s->drq[OMAP24XX_DMA_UART1_TX], ++ s->drq[OMAP24XX_DMA_UART1_RX], serial_hds[0]); ++ s->uart[1] = omap2_uart_init(omap_l4ta(s->l4, 20), ++ s->irq[0][OMAP_INT_24XX_UART2_IRQ], ++ omap_findclk(s, "uart2_fclk"), ++ omap_findclk(s, "uart2_iclk"), ++ s->drq[OMAP24XX_DMA_UART2_TX], ++ s->drq[OMAP24XX_DMA_UART2_RX], ++ serial_hds[0] ? serial_hds[1] : 0); ++ s->uart[2] = omap2_uart_init(omap_l4ta(s->l4, 21), ++ s->irq[0][OMAP_INT_24XX_UART3_IRQ], ++ omap_findclk(s, "uart3_fclk"), ++ omap_findclk(s, "uart3_iclk"), ++ s->drq[OMAP24XX_DMA_UART3_TX], ++ s->drq[OMAP24XX_DMA_UART3_RX], ++ serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0); ++ ++ s->gptimer[0] = omap_gp_timer_init(omap_l4ta(s->l4, 7), ++ s->irq[0][OMAP_INT_24XX_GPTIMER1], ++ omap_findclk(s, "wu_gpt1_clk"), ++ omap_findclk(s, "wu_l4_iclk")); ++ s->gptimer[1] = omap_gp_timer_init(omap_l4ta(s->l4, 8), ++ s->irq[0][OMAP_INT_24XX_GPTIMER2], ++ omap_findclk(s, "core_gpt2_clk"), ++ omap_findclk(s, "core_l4_iclk")); ++ s->gptimer[2] = omap_gp_timer_init(omap_l4ta(s->l4, 22), ++ s->irq[0][OMAP_INT_24XX_GPTIMER3], ++ omap_findclk(s, "core_gpt3_clk"), ++ omap_findclk(s, "core_l4_iclk")); ++ s->gptimer[3] = omap_gp_timer_init(omap_l4ta(s->l4, 23), ++ s->irq[0][OMAP_INT_24XX_GPTIMER4], ++ omap_findclk(s, "core_gpt4_clk"), ++ omap_findclk(s, "core_l4_iclk")); ++ s->gptimer[4] = omap_gp_timer_init(omap_l4ta(s->l4, 24), ++ s->irq[0][OMAP_INT_24XX_GPTIMER5], ++ omap_findclk(s, "core_gpt5_clk"), ++ omap_findclk(s, "core_l4_iclk")); ++ s->gptimer[5] = omap_gp_timer_init(omap_l4ta(s->l4, 25), ++ s->irq[0][OMAP_INT_24XX_GPTIMER6], ++ omap_findclk(s, "core_gpt6_clk"), ++ omap_findclk(s, "core_l4_iclk")); ++ s->gptimer[6] = omap_gp_timer_init(omap_l4ta(s->l4, 26), ++ s->irq[0][OMAP_INT_24XX_GPTIMER7], ++ omap_findclk(s, "core_gpt7_clk"), ++ omap_findclk(s, "core_l4_iclk")); ++ s->gptimer[7] = omap_gp_timer_init(omap_l4ta(s->l4, 27), ++ s->irq[0][OMAP_INT_24XX_GPTIMER8], ++ omap_findclk(s, "core_gpt8_clk"), ++ omap_findclk(s, "core_l4_iclk")); ++ s->gptimer[8] = omap_gp_timer_init(omap_l4ta(s->l4, 28), ++ s->irq[0][OMAP_INT_24XX_GPTIMER9], ++ omap_findclk(s, "core_gpt9_clk"), ++ omap_findclk(s, "core_l4_iclk")); ++ s->gptimer[9] = omap_gp_timer_init(omap_l4ta(s->l4, 29), ++ s->irq[0][OMAP_INT_24XX_GPTIMER10], ++ omap_findclk(s, "core_gpt10_clk"), ++ omap_findclk(s, "core_l4_iclk")); ++ s->gptimer[10] = omap_gp_timer_init(omap_l4ta(s->l4, 30), ++ s->irq[0][OMAP_INT_24XX_GPTIMER11], ++ omap_findclk(s, "core_gpt11_clk"), ++ omap_findclk(s, "core_l4_iclk")); ++ s->gptimer[11] = omap_gp_timer_init(omap_l4ta(s->l4, 31), ++ s->irq[0][OMAP_INT_24XX_GPTIMER12], ++ omap_findclk(s, "core_gpt12_clk"), ++ omap_findclk(s, "core_l4_iclk")); ++ ++ omap_tap_init(omap_l4ta(s->l4, 2), s); ++ ++ omap_synctimer_init(omap_l4tao(s->l4, 2), s, ++ omap_findclk(s, "clk32-kHz"), ++ omap_findclk(s, "core_l4_iclk")); ++ ++ s->i2c[0] = omap2_i2c_init(omap_l4tao(s->l4, 5), ++ s->irq[0][OMAP_INT_24XX_I2C1_IRQ], ++ &s->drq[OMAP24XX_DMA_I2C1_TX], ++ omap_findclk(s, "i2c1.fclk"), ++ omap_findclk(s, "i2c1.iclk")); ++ s->i2c[1] = omap2_i2c_init(omap_l4tao(s->l4, 6), ++ s->irq[0][OMAP_INT_24XX_I2C2_IRQ], ++ &s->drq[OMAP24XX_DMA_I2C2_TX], ++ omap_findclk(s, "i2c2.fclk"), ++ omap_findclk(s, "i2c2.iclk")); ++ ++ gpio_clks[0] = omap_findclk(s, "gpio1_dbclk"); ++ 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->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]); ++ ++ sdindex = drive_get_index(IF_SD, 0, 0); ++ if (sdindex == -1) { ++ fprintf(stderr, "qemu: missing SecureDigital device\n"); ++ exit(1); ++ } ++ s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), drives_table[sdindex].bdrv, ++ s->irq[0][OMAP_INT_24XX_MMC_IRQ], ++ &s->drq[OMAP24XX_DMA_MMC1_TX], ++ omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk")); ++ ++ s->mcspi[0] = omap_mcspi_init(omap_l4ta(s->l4, 35), 4, ++ s->irq[0][OMAP_INT_24XX_MCSPI1_IRQ], ++ &s->drq[OMAP24XX_DMA_SPI1_TX0], ++ omap_findclk(s, "spi1_fclk"), ++ omap_findclk(s, "spi1_iclk")); ++ s->mcspi[1] = omap_mcspi_init(omap_l4ta(s->l4, 36), 2, ++ s->irq[0][OMAP_INT_24XX_MCSPI2_IRQ], ++ &s->drq[OMAP24XX_DMA_SPI2_TX0], ++ omap_findclk(s, "spi2_fclk"), ++ omap_findclk(s, "spi2_iclk")); ++ ++ s->dss = omap_dss_init(omap_l4ta(s->l4, 10), 0x68000800, ds, ++ /* XXX wire M_IRQ_25, D_L2_IRQ_30 and I_IRQ_13 together */ ++ s->irq[0][OMAP_INT_24XX_DSS_IRQ], s->drq[OMAP24XX_DMA_DSS], ++ 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")); ++ ++ /* Register mappings not currenlty implemented: ++ * SystemControlMod 48000000 - 48000fff ++ * SystemControlL4 48001000 - 48001fff ++ * 32kHz Timer Mod 48004000 - 48004fff ++ * 32kHz Timer L4 48005000 - 48005fff ++ * PRCM ModA 48008000 - 480087ff ++ * PRCM ModB 48008800 - 48008fff ++ * PRCM L4 48009000 - 48009fff ++ * TEST-BCM Mod 48012000 - 48012fff ++ * TEST-BCM L4 48013000 - 48013fff ++ * TEST-TAP Mod 48014000 - 48014fff ++ * TEST-TAP L4 48015000 - 48015fff ++ * GPIO1 Mod 48018000 - 48018fff ++ * GPIO Top 48019000 - 48019fff ++ * GPIO2 Mod 4801a000 - 4801afff ++ * GPIO L4 4801b000 - 4801bfff ++ * GPIO3 Mod 4801c000 - 4801cfff ++ * GPIO4 Mod 4801e000 - 4801efff ++ * WDTIMER1 Mod 48020000 - 48010fff ++ * WDTIMER Top 48021000 - 48011fff ++ * WDTIMER2 Mod 48022000 - 48012fff ++ * WDTIMER L4 48023000 - 48013fff ++ * WDTIMER3 Mod 48024000 - 48014fff ++ * WDTIMER3 L4 48025000 - 48015fff ++ * WDTIMER4 Mod 48026000 - 48016fff ++ * WDTIMER4 L4 48027000 - 48017fff ++ * GPTIMER1 Mod 48028000 - 48018fff ++ * GPTIMER1 L4 48029000 - 48019fff ++ * GPTIMER2 Mod 4802a000 - 4801afff ++ * GPTIMER2 L4 4802b000 - 4801bfff ++ * L4-Config AP 48040000 - 480407ff ++ * L4-Config IP 48040800 - 48040fff ++ * L4-Config LA 48041000 - 48041fff ++ * ARM11ETB Mod 48048000 - 48049fff ++ * ARM11ETB L4 4804a000 - 4804afff ++ * DISPLAY Top 48050000 - 480503ff ++ * DISPLAY DISPC 48050400 - 480507ff ++ * DISPLAY RFBI 48050800 - 48050bff ++ * DISPLAY VENC 48050c00 - 48050fff ++ * DISPLAY L4 48051000 - 48051fff ++ * CAMERA Top 48052000 - 480523ff ++ * CAMERA core 48052400 - 480527ff ++ * CAMERA DMA 48052800 - 48052bff ++ * CAMERA MMU 48052c00 - 48052fff ++ * CAMERA L4 48053000 - 48053fff ++ * SDMA Mod 48056000 - 48056fff ++ * SDMA L4 48057000 - 48057fff ++ * SSI Top 48058000 - 48058fff ++ * SSI GDD 48059000 - 48059fff ++ * SSI Port1 4805a000 - 4805afff ++ * SSI Port2 4805b000 - 4805bfff ++ * SSI L4 4805c000 - 4805cfff ++ * USB Mod 4805e000 - 480fefff ++ * USB L4 4805f000 - 480fffff ++ * WIN_TRACER1 Mod 48060000 - 48060fff ++ * WIN_TRACER1 L4 48061000 - 48061fff ++ * WIN_TRACER2 Mod 48062000 - 48062fff ++ * WIN_TRACER2 L4 48063000 - 48063fff ++ * WIN_TRACER3 Mod 48064000 - 48064fff ++ * WIN_TRACER3 L4 48065000 - 48065fff ++ * WIN_TRACER4 Top 48066000 - 480660ff ++ * WIN_TRACER4 ETT 48066100 - 480661ff ++ * WIN_TRACER4 WT 48066200 - 480662ff ++ * WIN_TRACER4 L4 48067000 - 48067fff ++ * XTI Mod 48068000 - 48068fff ++ * XTI L4 48069000 - 48069fff ++ * UART1 Mod 4806a000 - 4806afff ++ * UART1 L4 4806b000 - 4806bfff ++ * UART2 Mod 4806c000 - 4806cfff ++ * UART2 L4 4806d000 - 4806dfff ++ * UART3 Mod 4806e000 - 4806efff ++ * UART3 L4 4806f000 - 4806ffff ++ * I2C1 Mod 48070000 - 48070fff ++ * I2C1 L4 48071000 - 48071fff ++ * I2C2 Mod 48072000 - 48072fff ++ * I2C2 L4 48073000 - 48073fff ++ * McBSP1 Mod 48074000 - 48074fff ++ * McBSP1 L4 48075000 - 48075fff ++ * McBSP2 Mod 48076000 - 48076fff ++ * McBSP2 L4 48077000 - 48077fff ++ * GPTIMER3 Mod 48078000 - 48078fff ++ * GPTIMER3 L4 48079000 - 48079fff ++ * GPTIMER4 Mod 4807a000 - 4807afff ++ * GPTIMER4 L4 4807b000 - 4807bfff ++ * GPTIMER5 Mod 4807c000 - 4807cfff ++ * GPTIMER5 L4 4807d000 - 4807dfff ++ * GPTIMER6 Mod 4807e000 - 4807efff ++ * GPTIMER6 L4 4807f000 - 4807ffff ++ * GPTIMER7 Mod 48080000 - 48080fff ++ * GPTIMER7 L4 48081000 - 48081fff ++ * GPTIMER8 Mod 48082000 - 48082fff ++ * GPTIMER8 L4 48083000 - 48083fff ++ * GPTIMER9 Mod 48084000 - 48084fff ++ * GPTIMER9 L4 48085000 - 48085fff ++ * GPTIMER10 Mod 48086000 - 48086fff ++ * GPTIMER10 L4 48087000 - 48087fff ++ * GPTIMER11 Mod 48088000 - 48088fff ++ * GPTIMER11 L4 48089000 - 48089fff ++ * GPTIMER12 Mod 4808a000 - 4808afff ++ * GPTIMER12 L4 4808b000 - 4808bfff ++ * EAC Mod 48090000 - 48090fff ++ * EAC L4 48091000 - 48091fff ++ * FAC Mod 48092000 - 48092fff ++ * FAC L4 48093000 - 48093fff ++ * MAILBOX Mod 48094000 - 48094fff ++ * MAILBOX L4 48095000 - 48095fff ++ * SPI1 Mod 48098000 - 48098fff ++ * SPI1 L4 48099000 - 48099fff ++ * SPI2 Mod 4809a000 - 4809afff ++ * SPI2 L4 4809b000 - 4809bfff ++ * MMC/SDIO Mod 4809c000 - 4809cfff ++ * MMC/SDIO L4 4809d000 - 4809dfff ++ * MS_PRO Mod 4809e000 - 4809efff ++ * MS_PRO L4 4809f000 - 4809ffff ++ * RNG Mod 480a0000 - 480a0fff ++ * RNG L4 480a1000 - 480a1fff ++ * DES3DES Mod 480a2000 - 480a2fff ++ * DES3DES L4 480a3000 - 480a3fff ++ * SHA1MD5 Mod 480a4000 - 480a4fff ++ * SHA1MD5 L4 480a5000 - 480a5fff ++ * AES Mod 480a6000 - 480a6fff ++ * AES L4 480a7000 - 480a7fff ++ * PKA Mod 480a8000 - 480a9fff ++ * PKA L4 480aa000 - 480aafff ++ * MG Mod 480b0000 - 480b0fff ++ * MG L4 480b1000 - 480b1fff ++ * HDQ/1-wire Mod 480b2000 - 480b2fff ++ * HDQ/1-wire L4 480b3000 - 480b3fff ++ * MPU interrupt 480fe000 - 480fefff ++ * IVA RAM 5c000000 - 5c01ffff ++ * IVA ROM 5c020000 - 5c027fff ++ * IMG_BUF_A 5c040000 - 5c040fff ++ * IMG_BUF_B 5c042000 - 5c042fff ++ * VLCDS 5c048000 - 5c0487ff ++ * IMX_COEF 5c049000 - 5c04afff ++ * IMX_CMD 5c051000 - 5c051fff ++ * VLCDQ 5c053000 - 5c0533ff ++ * VLCDH 5c054000 - 5c054fff ++ * SEQ_CMD 5c055000 - 5c055fff ++ * IMX_REG 5c056000 - 5c0560ff ++ * VLCD_REG 5c056100 - 5c0561ff ++ * SEQ_REG 5c056200 - 5c0562ff ++ * IMG_BUF_REG 5c056300 - 5c0563ff ++ * SEQIRQ_REG 5c056400 - 5c0564ff ++ * OCP_REG 5c060000 - 5c060fff ++ * SYSC_REG 5c070000 - 5c070fff ++ * MMU_REG 5d000000 - 5d000fff ++ * sDMA R 68000400 - 680005ff ++ * sDMA W 68000600 - 680007ff ++ * Display Control 68000800 - 680009ff ++ * DSP subsystem 68000a00 - 68000bff ++ * MPU subsystem 68000c00 - 68000dff ++ * IVA subsystem 68001000 - 680011ff ++ * USB 68001200 - 680013ff ++ * Camera 68001400 - 680015ff ++ * VLYNQ (firewall) 68001800 - 68001bff ++ * VLYNQ 68001e00 - 68001fff ++ * SSI 68002000 - 680021ff ++ * L4 68002400 - 680025ff ++ * DSP (firewall) 68002800 - 68002bff ++ * DSP subsystem 68002e00 - 68002fff ++ * IVA (firewall) 68003000 - 680033ff ++ * IVA 68003600 - 680037ff ++ * GFX 68003a00 - 68003bff ++ * CMDWR emulation 68003c00 - 68003dff ++ * SMS 68004000 - 680041ff ++ * OCM 68004200 - 680043ff ++ * GPMC 68004400 - 680045ff ++ * RAM (firewall) 68005000 - 680053ff ++ * RAM (err login) 68005400 - 680057ff ++ * ROM (firewall) 68005800 - 68005bff ++ * ROM (err login) 68005c00 - 68005fff ++ * GPMC (firewall) 68006000 - 680063ff ++ * GPMC (err login) 68006400 - 680067ff ++ * SMS (err login) 68006c00 - 68006fff ++ * SMS registers 68008000 - 68008fff ++ * SDRC registers 68009000 - 68009fff ++ * GPMC registers 6800a000 6800afff ++ */ ++ ++ qemu_register_reset(omap2_mpu_reset, s); ++ ++ return s; ++} +diff --git a/hw/omap_clk.c b/hw/omap_clk.c +index 37daec2..da03e15 100644 +--- a/hw/omap_clk.c ++++ b/hw/omap_clk.c +@@ -34,6 +34,9 @@ struct clk { + #define CLOCK_IN_OMAP730 (1 << 11) + #define CLOCK_IN_OMAP1510 (1 << 12) + #define CLOCK_IN_OMAP16XX (1 << 13) ++#define CLOCK_IN_OMAP242X (1 << 14) ++#define CLOCK_IN_OMAP243X (1 << 15) ++#define CLOCK_IN_OMAP343X (1 << 16) + uint32_t flags; + int id; + +@@ -55,7 +58,8 @@ static struct clk xtal_osc12m = { + static struct clk xtal_osc32k = { + .name = "xtal_osc_32k", + .rate = 32768, +- .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, ++ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | ++ CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + }; + + static struct clk ck_ref = { +@@ -502,11 +506,441 @@ static struct clk i2c_ick = { + static struct clk clk32k = { + .name = "clk32-kHz", + .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | +- ALWAYS_ENABLED, +- .parent = &xtal_osc32k, ++ CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, ++ .parent = &xtal_osc32k, ++}; ++ ++static struct clk apll_96m = { ++ .name = "apll_96m", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, ++ .rate = 96000000, ++ /*.parent = sys.xtalin */ ++}; ++ ++static struct clk apll_54m = { ++ .name = "apll_54m", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, ++ .rate = 54000000, ++ /*.parent = sys.xtalin */ ++}; ++ ++static struct clk sys_clk = { ++ .name = "sys_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, ++ .rate = 32768, ++ /*.parent = sys.xtalin */ ++}; ++ ++static struct clk sleep_clk = { ++ .name = "sleep_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, ++ .rate = 32768, ++ /*.parent = sys.xtalin */ ++}; ++ ++static struct clk dpll_ck = { ++ .name = "dpll", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, ++ /*.parent = sys.xtalin */ ++}; ++ ++static struct clk dpll_x2_ck = { ++ .name = "dpll_x2", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, ++ /*.parent = sys.xtalin */ ++}; ++ ++static struct clk wdt1_sys_clk = { ++ .name = "wdt1_sys_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, ++ .rate = 32768, ++ /*.parent = sys.xtalin */ ++}; ++ ++static struct clk func_96m_clk = { ++ .name = "func_96m_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .divisor = 1, ++ .parent = &apll_96m, ++}; ++ ++static struct clk func_48m_clk = { ++ .name = "func_48m_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .divisor = 2, ++ .parent = &apll_96m, ++}; ++ ++static struct clk func_12m_clk = { ++ .name = "func_12m_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .divisor = 8, ++ .parent = &apll_96m, ++}; ++ ++static struct clk func_54m_clk = { ++ .name = "func_54m_clk", ++ .flags = CLOCK_IN_OMAP242X, ++ .divisor = 1, ++ .parent = &apll_54m, ++}; ++ ++static struct clk sys_clkout = { ++ .name = "clkout", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++}; ++ ++static struct clk sys_clkout2 = { ++ .name = "clkout2", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++}; ++ ++static struct clk core_clk = { ++ .name = "core_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &dpll_ck, ++}; ++ ++static struct clk l3_clk = { ++ .name = "l3_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_clk, ++}; ++ ++static struct clk core_l4_iclk = { ++ .name = "core_l4_iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &l3_clk, ++}; ++ ++static struct clk wu_l4_iclk = { ++ .name = "wu_l4_iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &l3_clk, ++}; ++ ++static struct clk core_l3_iclk = { ++ .name = "core_l3_iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_clk, ++}; ++ ++static struct clk core_l4_usb_clk = { ++ .name = "core_l4_usb_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &l3_clk, ++}; ++ ++static struct clk wu_gpt1_clk = { ++ .name = "wu_gpt1_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++}; ++ ++static struct clk wu_32k_clk = { ++ .name = "wu_32k_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++}; ++ ++static struct clk uart1_fclk = { ++ .name = "uart1_fclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &func_48m_clk, ++}; ++ ++static struct clk uart1_iclk = { ++ .name = "uart1_iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_l4_iclk, ++}; ++ ++static struct clk uart2_fclk = { ++ .name = "uart2_fclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &func_48m_clk, ++}; ++ ++static struct clk uart2_iclk = { ++ .name = "uart2_iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_l4_iclk, ++}; ++ ++static struct clk uart3_fclk = { ++ .name = "uart3_fclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &func_48m_clk, ++}; ++ ++static struct clk uart3_iclk = { ++ .name = "uart3_iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_l4_iclk, ++}; ++ ++static struct clk mpu_fclk = { ++ .name = "mpu_fclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_clk, ++}; ++ ++static struct clk mpu_iclk = { ++ .name = "mpu_iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_clk, ++}; ++ ++static struct clk int_m_fclk = { ++ .name = "int_m_fclk", ++ .alias = "mpu_intc_fclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_clk, ++}; ++ ++static struct clk int_m_iclk = { ++ .name = "int_m_iclk", ++ .alias = "mpu_intc_iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_clk, ++}; ++ ++static struct clk core_gpt2_clk = { ++ .name = "core_gpt2_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++}; ++ ++static struct clk core_gpt3_clk = { ++ .name = "core_gpt3_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++}; ++ ++static struct clk core_gpt4_clk = { ++ .name = "core_gpt4_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++}; ++ ++static struct clk core_gpt5_clk = { ++ .name = "core_gpt5_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++}; ++ ++static struct clk core_gpt6_clk = { ++ .name = "core_gpt6_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++}; ++ ++static struct clk core_gpt7_clk = { ++ .name = "core_gpt7_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++}; ++ ++static struct clk core_gpt8_clk = { ++ .name = "core_gpt8_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++}; ++ ++static struct clk core_gpt9_clk = { ++ .name = "core_gpt9_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++}; ++ ++static struct clk core_gpt10_clk = { ++ .name = "core_gpt10_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++}; ++ ++static struct clk core_gpt11_clk = { ++ .name = "core_gpt11_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++}; ++ ++static struct clk core_gpt12_clk = { ++ .name = "core_gpt12_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++}; ++ ++static struct clk mcbsp1_clk = { ++ .name = "mcbsp1_cg", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .divisor = 2, ++ .parent = &func_96m_clk, ++}; ++ ++static struct clk mcbsp2_clk = { ++ .name = "mcbsp2_cg", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .divisor = 2, ++ .parent = &func_96m_clk, ++}; ++ ++static struct clk emul_clk = { ++ .name = "emul_ck", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &func_54m_clk, ++}; ++ ++static struct clk sdma_fclk = { ++ .name = "sdma_fclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &l3_clk, ++}; ++ ++static struct clk sdma_iclk = { ++ .name = "sdma_iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_l3_iclk, /* core_l4_iclk for the configuration port */ ++}; ++ ++static struct clk i2c1_fclk = { ++ .name = "i2c1.fclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &func_12m_clk, ++ .divisor = 1, ++}; ++ ++static struct clk i2c1_iclk = { ++ .name = "i2c1.iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_l4_iclk, ++}; ++ ++static struct clk i2c2_fclk = { ++ .name = "i2c2.fclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &func_12m_clk, ++ .divisor = 1, ++}; ++ ++static struct clk i2c2_iclk = { ++ .name = "i2c2.iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_l4_iclk, ++}; ++ ++static struct clk gpio_dbclk[4] = { ++ { ++ .name = "gpio1_dbclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &wu_32k_clk, ++ }, { ++ .name = "gpio2_dbclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &wu_32k_clk, ++ }, { ++ .name = "gpio3_dbclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &wu_32k_clk, ++ }, { ++ .name = "gpio4_dbclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &wu_32k_clk, ++ }, ++}; ++ ++static struct clk gpio_iclk = { ++ .name = "gpio_iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &wu_l4_iclk, ++}; ++ ++static struct clk mmc_fck = { ++ .name = "mmc_fclk", ++ .flags = CLOCK_IN_OMAP242X, ++ .parent = &func_96m_clk, ++}; ++ ++static struct clk mmc_ick = { ++ .name = "mmc_iclk", ++ .flags = CLOCK_IN_OMAP242X, ++ .parent = &core_l4_iclk, ++}; ++ ++static struct clk spi_fclk[3] = { ++ { ++ .name = "spi1_fclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &func_48m_clk, ++ }, { ++ .name = "spi2_fclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &func_48m_clk, ++ }, { ++ .name = "spi3_fclk", ++ .flags = CLOCK_IN_OMAP243X, ++ .parent = &func_48m_clk, ++ }, ++}; ++ ++static struct clk dss_clk[2] = { ++ { ++ .name = "dss_clk1", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_clk, ++ }, { ++ .name = "dss_clk2", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &sys_clk, ++ }, ++}; ++ ++static struct clk dss_54m_clk = { ++ .name = "dss_54m_clk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &func_54m_clk, ++}; ++ ++static struct clk dss_l3_iclk = { ++ .name = "dss_l3_iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_l3_iclk, ++}; ++ ++static struct clk dss_l4_iclk = { ++ .name = "dss_l4_iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_l4_iclk, ++}; ++ ++static struct clk spi_iclk[3] = { ++ { ++ .name = "spi1_iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_l4_iclk, ++ }, { ++ .name = "spi2_iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ .parent = &core_l4_iclk, ++ }, { ++ .name = "spi3_iclk", ++ .flags = CLOCK_IN_OMAP243X, ++ .parent = &core_l4_iclk, ++ }, ++}; ++ ++static struct clk omapctrl_clk = { ++ .name = "omapctrl_iclk", ++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, ++ /* XXX Should be in WKUP domain */ ++ .parent = &core_l4_iclk, + }; + + static struct clk *onchip_clks[] = { ++ /* OMAP 1 */ ++ + /* non-ULPD clocks */ + &xtal_osc12m, + &xtal_osc32k, +@@ -572,6 +1006,80 @@ static struct clk *onchip_clks[] = { + /* Virtual clocks */ + &i2c_fck, + &i2c_ick, ++ ++ /* OMAP 2 */ ++ ++ &apll_96m, ++ &apll_54m, ++ &sys_clk, ++ &sleep_clk, ++ &dpll_ck, ++ &dpll_x2_ck, ++ &wdt1_sys_clk, ++ &func_96m_clk, ++ &func_48m_clk, ++ &func_12m_clk, ++ &func_54m_clk, ++ &sys_clkout, ++ &sys_clkout2, ++ &core_clk, ++ &l3_clk, ++ &core_l4_iclk, ++ &wu_l4_iclk, ++ &core_l3_iclk, ++ &core_l4_usb_clk, ++ &wu_gpt1_clk, ++ &wu_32k_clk, ++ &uart1_fclk, ++ &uart1_iclk, ++ &uart2_fclk, ++ &uart2_iclk, ++ &uart3_fclk, ++ &uart3_iclk, ++ &mpu_fclk, ++ &mpu_iclk, ++ &int_m_fclk, ++ &int_m_iclk, ++ &core_gpt2_clk, ++ &core_gpt3_clk, ++ &core_gpt4_clk, ++ &core_gpt5_clk, ++ &core_gpt6_clk, ++ &core_gpt7_clk, ++ &core_gpt8_clk, ++ &core_gpt9_clk, ++ &core_gpt10_clk, ++ &core_gpt11_clk, ++ &core_gpt12_clk, ++ &mcbsp1_clk, ++ &mcbsp2_clk, ++ &emul_clk, ++ &sdma_fclk, ++ &sdma_iclk, ++ &i2c1_fclk, ++ &i2c1_iclk, ++ &i2c2_fclk, ++ &i2c2_iclk, ++ &gpio_dbclk[0], ++ &gpio_dbclk[1], ++ &gpio_dbclk[2], ++ &gpio_dbclk[3], ++ &gpio_iclk, ++ &mmc_fck, ++ &mmc_ick, ++ &spi_fclk[0], ++ &spi_iclk[0], ++ &spi_fclk[1], ++ &spi_iclk[1], ++ &spi_fclk[2], ++ &spi_iclk[2], ++ &dss_clk[0], ++ &dss_clk[1], ++ &dss_54m_clk, ++ &dss_l3_iclk, ++ &dss_l4_iclk, ++ &omapctrl_clk, ++ + 0 + }; + +@@ -727,6 +1235,12 @@ void omap_clk_init(struct omap_mpu_state_s *mpu) + flag = CLOCK_IN_OMAP310; + else if (cpu_is_omap1510(mpu)) + flag = CLOCK_IN_OMAP1510; ++ else if (cpu_is_omap2410(mpu) || cpu_is_omap2420(mpu)) ++ flag = CLOCK_IN_OMAP242X; ++ else if (cpu_is_omap2430(mpu)) ++ flag = CLOCK_IN_OMAP243X; ++ else if (cpu_is_omap3430(mpu)) ++ flag = CLOCK_IN_OMAP243X; + else + return; + +diff --git a/hw/omap_dma.c b/hw/omap_dma.c +index 1835826..6c0bd82 100644 +--- a/hw/omap_dma.c ++++ b/hw/omap_dma.c +@@ -28,12 +28,15 @@ struct omap_dma_channel_s { + /* transfer data */ + int burst[2]; + int pack[2]; ++ int endian[2]; ++ int endian_lock[2]; ++ int translate[2]; + enum omap_dma_port port[2]; + target_phys_addr_t addr[2]; + omap_dma_addressing_t mode[2]; +- uint16_t elements; ++ uint32_t elements; + uint16_t frames; +- int16_t frame_index[2]; ++ int32_t frame_index[2]; + int16_t element_index[2]; + int data_type; + +@@ -41,6 +44,7 @@ struct omap_dma_channel_s { + int transparent_copy; + int constant_fill; + uint32_t color; ++ int prefetch; + + /* auto init and linked channel data */ + int end_prog; +@@ -52,11 +56,13 @@ struct omap_dma_channel_s { + /* interruption data */ + int interrupts; + int status; ++ int cstatus; + + /* state data */ + int active; + int enable; + int sync; ++ int src_sync; + int pending_request; + int waiting_end_prog; + uint16_t cpc; +@@ -75,16 +81,21 @@ struct omap_dma_channel_s { + target_phys_addr_t src, dest; + int frame; + int element; ++ int pck_element; + int frame_delta[2]; + int elem_delta[2]; + int frames; + int elements; ++ int pck_elements; + } active_set; + + /* unused parameters */ ++ int write_mode; + int priority; + int interleave_disabled; + int type; ++ int suspend; ++ int buf_disable; + }; + + struct omap_dma_s { +@@ -93,15 +104,21 @@ struct omap_dma_s { + target_phys_addr_t base; + omap_clk clk; + int64_t delay; +- uint32_t drq; ++ uint64_t drq; ++ qemu_irq irq[4]; ++ void (*intr_update)(struct omap_dma_s *s); + enum omap_dma_model model; + int omap_3_1_mapping_disabled; + +- uint16_t gcr; ++ uint32_t gcr; ++ uint32_t ocp; ++ uint32_t caps[5]; ++ uint32_t irqen[4]; ++ uint32_t irqstat[4]; + int run_count; + + int chans; +- struct omap_dma_channel_s ch[16]; ++ struct omap_dma_channel_s ch[32]; + struct omap_dma_lcd_channel_s lcd_ch; + }; + +@@ -113,23 +130,13 @@ struct omap_dma_s { + #define LAST_FRAME_INTR (1 << 4) + #define END_BLOCK_INTR (1 << 5) + #define SYNC (1 << 6) ++#define END_PKT_INTR (1 << 7) ++#define TRANS_ERR_INTR (1 << 8) ++#define MISALIGN_INTR (1 << 11) + +-static void omap_dma_interrupts_update(struct omap_dma_s *s) ++static inline void omap_dma_interrupts_update(struct omap_dma_s *s) + { +- struct omap_dma_channel_s *ch = s->ch; +- int i; +- +- if (s->omap_3_1_mapping_disabled) { +- for (i = 0; i < s->chans; i ++, ch ++) +- if (ch->status) +- qemu_irq_raise(ch->irq); +- } else { +- /* First three interrupts are shared between two channels each. */ +- for (i = 0; i < 6; i ++, ch ++) { +- if (ch->status || (ch->sibling && ch->sibling->status)) +- qemu_irq_raise(ch->irq); +- } +- } ++ return s->intr_update(s); + } + + static void omap_dma_channel_load(struct omap_dma_s *s, +@@ -148,8 +155,10 @@ static void omap_dma_channel_load(struct omap_dma_s *s, + a->dest = ch->addr[1]; + a->frames = ch->frames; + a->elements = ch->elements; ++ a->pck_elements = ch->frame_index[!ch->src_sync]; + a->frame = 0; + a->element = 0; ++ a->pck_element = 0; + + if (unlikely(!ch->elements || !ch->frames)) { + printf("%s: bad DMA request\n", __FUNCTION__); +@@ -202,16 +211,15 @@ static void omap_dma_deactivate_channel(struct omap_dma_s *s, + /* Update cpc */ + ch->cpc = ch->active_set.dest & 0xffff; + +- if (ch->pending_request && !ch->waiting_end_prog) { ++ if (ch->pending_request && !ch->waiting_end_prog && ch->enable) { + /* Don't deactivate the channel */ + ch->pending_request = 0; +- if (ch->enable) +- return; ++ return; + } + + /* Don't deactive the channel if it is synchronized and the DMA request is + active */ +- if (ch->sync && (s->drq & (1 << ch->sync)) && ch->enable) ++ if (ch->sync && ch->enable && (s->drq & (1 << ch->sync))) + return; + + if (ch->active) { +@@ -231,6 +239,9 @@ static void omap_dma_enable_channel(struct omap_dma_s *s, + ch->enable = 1; + ch->waiting_end_prog = 0; + omap_dma_channel_load(s, ch); ++ /* TODO: theoretically if ch->sync && ch->prefetch && ++ * !s->drq[ch->sync], we should also activate and fetch from source ++ * and then stall until signalled. */ + if ((!ch->sync) || (s->drq & (1 << ch->sync))) + omap_dma_activate_channel(s, ch); + } +@@ -259,16 +270,47 @@ static void omap_dma_channel_end_prog(struct omap_dma_s *s, + } + } + ++static void omap_dma_interrupts_3_1_update(struct omap_dma_s *s) ++{ ++ struct omap_dma_channel_s *ch = s->ch; ++ ++ /* First three interrupts are shared between two channels each. */ ++ if (ch[0].status | ch[6].status) ++ qemu_irq_raise(ch[0].irq); ++ if (ch[1].status | ch[7].status) ++ qemu_irq_raise(ch[1].irq); ++ if (ch[2].status | ch[8].status) ++ qemu_irq_raise(ch[2].irq); ++ if (ch[3].status) ++ qemu_irq_raise(ch[3].irq); ++ if (ch[4].status) ++ qemu_irq_raise(ch[4].irq); ++ if (ch[5].status) ++ qemu_irq_raise(ch[5].irq); ++} ++ ++static void omap_dma_interrupts_3_2_update(struct omap_dma_s *s) ++{ ++ struct omap_dma_channel_s *ch = s->ch; ++ int i; ++ ++ for (i = s->chans; i; ch ++, i --) ++ if (ch->status) ++ qemu_irq_raise(ch->irq); ++} ++ + static void omap_dma_enable_3_1_mapping(struct omap_dma_s *s) + { + s->omap_3_1_mapping_disabled = 0; + s->chans = 9; ++ s->intr_update = omap_dma_interrupts_3_1_update; + } + + static void omap_dma_disable_3_1_mapping(struct omap_dma_s *s) + { + s->omap_3_1_mapping_disabled = 1; + s->chans = 16; ++ s->intr_update = omap_dma_interrupts_3_2_update; + } + + static void omap_dma_process_request(struct omap_dma_s *s, int request) +@@ -358,6 +400,22 @@ static void omap_dma_channel_run(struct omap_dma_s *s) + if (ch->interrupts & HALF_FRAME_INTR) + ch->status |= HALF_FRAME_INTR; + ++ if (ch->fs && ch->bs) { ++ a->pck_element ++; ++ /* Check if a full packet has beed transferred. */ ++ if (a->pck_element == a->pck_elements) { ++ a->pck_element = 0; ++ ++ /* Set the END_PKT interrupt */ ++ if ((ch->interrupts & END_PKT_INTR) && !ch->src_sync) ++ ch->status |= END_PKT_INTR; ++ ++ /* If the channel is packet-synchronized, deactivate it */ ++ if (ch->sync) ++ omap_dma_deactivate_channel(s, ch); ++ } ++ } ++ + if (a->element == a->elements) { + /* End of Frame */ + a->element = 0; +@@ -366,7 +424,7 @@ static void omap_dma_channel_run(struct omap_dma_s *s) + a->frame ++; + + /* If the channel is frame synchronized, deactivate it */ +- if (ch->sync && ch->fs) ++ if (ch->sync && ch->fs && !ch->bs) + omap_dma_deactivate_channel(s, ch); + + /* If the channel is async, update cpc */ +@@ -414,50 +472,62 @@ void omap_dma_reset(struct omap_dma_s *s) + int i; + + qemu_del_timer(s->tm); +- s->gcr = 0x0004; ++ if (s->model < omap_dma_4) ++ s->gcr = 0x0004; ++ else ++ s->gcr = 0x00010010; ++ s->ocp = 0x00000000; ++ memset(&s->irqstat, 0, sizeof(s->irqstat)); ++ memset(&s->irqen, 0, sizeof(s->irqen)); + s->drq = 0x00000000; + s->run_count = 0; + s->lcd_ch.src = emiff; + s->lcd_ch.condition = 0; + s->lcd_ch.interrupts = 0; + s->lcd_ch.dual = 0; +- omap_dma_enable_3_1_mapping(s); ++ if (s->model < omap_dma_4) ++ omap_dma_enable_3_1_mapping(s); + for (i = 0; i < s->chans; i ++) { ++ s->ch[i].suspend = 0; ++ s->ch[i].prefetch = 0; ++ s->ch[i].buf_disable = 0; ++ s->ch[i].src_sync = 0; + memset(&s->ch[i].burst, 0, sizeof(s->ch[i].burst)); + memset(&s->ch[i].port, 0, sizeof(s->ch[i].port)); + memset(&s->ch[i].mode, 0, sizeof(s->ch[i].mode)); +- memset(&s->ch[i].elements, 0, sizeof(s->ch[i].elements)); +- memset(&s->ch[i].frames, 0, sizeof(s->ch[i].frames)); + memset(&s->ch[i].frame_index, 0, sizeof(s->ch[i].frame_index)); + memset(&s->ch[i].element_index, 0, sizeof(s->ch[i].element_index)); +- memset(&s->ch[i].data_type, 0, sizeof(s->ch[i].data_type)); +- memset(&s->ch[i].transparent_copy, 0, +- sizeof(s->ch[i].transparent_copy)); +- memset(&s->ch[i].constant_fill, 0, sizeof(s->ch[i].constant_fill)); +- memset(&s->ch[i].color, 0, sizeof(s->ch[i].color)); +- memset(&s->ch[i].end_prog, 0, sizeof(s->ch[i].end_prog)); +- memset(&s->ch[i].repeat, 0, sizeof(s->ch[i].repeat)); +- memset(&s->ch[i].auto_init, 0, sizeof(s->ch[i].auto_init)); +- memset(&s->ch[i].link_enabled, 0, sizeof(s->ch[i].link_enabled)); +- memset(&s->ch[i].link_next_ch, 0, sizeof(s->ch[i].link_next_ch)); +- s->ch[i].interrupts = 0x0003; +- memset(&s->ch[i].status, 0, sizeof(s->ch[i].status)); +- memset(&s->ch[i].active, 0, sizeof(s->ch[i].active)); +- memset(&s->ch[i].enable, 0, sizeof(s->ch[i].enable)); +- memset(&s->ch[i].sync, 0, sizeof(s->ch[i].sync)); +- memset(&s->ch[i].pending_request, 0, sizeof(s->ch[i].pending_request)); +- memset(&s->ch[i].waiting_end_prog, 0, +- sizeof(s->ch[i].waiting_end_prog)); +- memset(&s->ch[i].cpc, 0, sizeof(s->ch[i].cpc)); +- memset(&s->ch[i].fs, 0, sizeof(s->ch[i].fs)); +- memset(&s->ch[i].bs, 0, sizeof(s->ch[i].bs)); +- memset(&s->ch[i].omap_3_1_compatible_disable, 0, +- sizeof(s->ch[i].omap_3_1_compatible_disable)); ++ memset(&s->ch[i].endian, 0, sizeof(s->ch[i].endian)); ++ memset(&s->ch[i].endian_lock, 0, sizeof(s->ch[i].endian_lock)); ++ memset(&s->ch[i].translate, 0, sizeof(s->ch[i].translate)); ++ s->ch[i].write_mode = 0; ++ s->ch[i].data_type = 0; ++ s->ch[i].transparent_copy = 0; ++ s->ch[i].constant_fill = 0; ++ s->ch[i].color = 0x00000000; ++ s->ch[i].end_prog = 0; ++ s->ch[i].repeat = 0; ++ s->ch[i].auto_init = 0; ++ s->ch[i].link_enabled = 0; ++ if (s->model < omap_dma_4) ++ s->ch[i].interrupts = 0x0003; ++ else ++ s->ch[i].interrupts = 0x0000; ++ s->ch[i].status = 0; ++ s->ch[i].cstatus = 0; ++ s->ch[i].active = 0; ++ s->ch[i].enable = 0; ++ s->ch[i].sync = 0; ++ s->ch[i].pending_request = 0; ++ s->ch[i].waiting_end_prog = 0; ++ s->ch[i].cpc = 0x0000; ++ s->ch[i].fs = 0; ++ s->ch[i].bs = 0; ++ s->ch[i].omap_3_1_compatible_disable = 0; + memset(&s->ch[i].active_set, 0, sizeof(s->ch[i].active_set)); +- memset(&s->ch[i].priority, 0, sizeof(s->ch[i].priority)); +- memset(&s->ch[i].interleave_disabled, 0, +- sizeof(s->ch[i].interleave_disabled)); +- memset(&s->ch[i].type, 0, sizeof(s->ch[i].type)); ++ s->ch[i].priority = 0; ++ s->ch[i].interleave_disabled = 0; ++ s->ch[i].type = 0; + } + } + +@@ -476,7 +546,7 @@ static int omap_dma_ch_reg_read(struct omap_dma_s *s, + break; + + case 0x02: /* SYS_DMA_CCR_CH0 */ +- if (s->model == omap_dma_3_1) ++ if (s->model <= omap_dma_3_1) + *value = 0 << 10; /* FIFO_FLUSH reads as 0 */ + else + *value = ch->omap_3_1_compatible_disable << 10; +@@ -596,11 +666,11 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, + ch->burst[0] = (value & 0x0180) >> 7; + ch->pack[0] = (value & 0x0040) >> 6; + ch->port[0] = (enum omap_dma_port) ((value & 0x003c) >> 2); +- ch->data_type = (1 << (value & 3)); +- if (ch->port[0] >= omap_dma_port_last) ++ ch->data_type = 1 << (value & 3); ++ if (ch->port[0] >= __omap_dma_port_last) + printf("%s: invalid DMA port %i\n", __FUNCTION__, + ch->port[0]); +- if (ch->port[1] >= omap_dma_port_last) ++ if (ch->port[1] >= __omap_dma_port_last) + printf("%s: invalid DMA port %i\n", __FUNCTION__, + ch->port[1]); + if ((value & 3) == 3) +@@ -611,7 +681,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, + ch->mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14); + ch->mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12); + ch->end_prog = (value & 0x0800) >> 11; +- if (s->model > omap_dma_3_1) ++ if (s->model >= omap_dma_3_2) + ch->omap_3_1_compatible_disable = (value >> 10) & 0x1; + ch->repeat = (value & 0x0200) >> 9; + ch->auto_init = (value & 0x0100) >> 8; +@@ -630,7 +700,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, + break; + + case 0x04: /* SYS_DMA_CICR_CH0 */ +- ch->interrupts = value; ++ ch->interrupts = value & 0x3f; + break; + + case 0x06: /* SYS_DMA_CSR_CH0 */ +@@ -696,7 +766,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, + break; + + case 0x24: /* DMA_CCR2 */ +- ch->bs = (value >> 2) & 0x1; ++ ch->bs = (value >> 2) & 0x1; + ch->transparent_copy = (value >> 1) & 0x1; + ch->constant_fill = value & 0x1; + break; +@@ -1126,48 +1196,29 @@ static int omap_dma_sys_read(struct omap_dma_s *s, int offset, + break; + + case 0x44e: /* DMA_CAPS_0_U */ +- *ret = (1 << 3) | /* Constant Fill Capacity */ +- (1 << 2); /* Transparent BLT Capacity */ ++ *ret = (s->caps[0] >> 16) & 0xffff; + break; +- + case 0x450: /* DMA_CAPS_0_L */ +- case 0x452: /* DMA_CAPS_1_U */ +- *ret = 0; ++ *ret = (s->caps[0] >> 0) & 0xffff; + break; + ++ case 0x452: /* DMA_CAPS_1_U */ ++ *ret = (s->caps[1] >> 16) & 0xffff; ++ break; + case 0x454: /* DMA_CAPS_1_L */ +- *ret = (1 << 1); /* 1-bit palletized capability */ ++ *ret = (s->caps[1] >> 0) & 0xffff; + break; + + case 0x456: /* DMA_CAPS_2 */ +- *ret = (1 << 8) | /* SSDIC */ +- (1 << 7) | /* DDIAC */ +- (1 << 6) | /* DSIAC */ +- (1 << 5) | /* DPIAC */ +- (1 << 4) | /* DCAC */ +- (1 << 3) | /* SDIAC */ +- (1 << 2) | /* SSIAC */ +- (1 << 1) | /* SPIAC */ +- 1; /* SCAC */ ++ *ret = s->caps[2]; + break; + + case 0x458: /* DMA_CAPS_3 */ +- *ret = (1 << 5) | /* CCC */ +- (1 << 4) | /* IC */ +- (1 << 3) | /* ARC */ +- (1 << 2) | /* AEC */ +- (1 << 1) | /* FSC */ +- 1; /* ESC */ ++ *ret = s->caps[3]; + break; + + case 0x45a: /* DMA_CAPS_4 */ +- *ret = (1 << 6) | /* SSC */ +- (1 << 5) | /* BIC */ +- (1 << 4) | /* LFIC */ +- (1 << 3) | /* FIC */ +- (1 << 2) | /* HFIC */ +- (1 << 1) | /* EDIC */ +- 1; /* TOIC */ ++ *ret = s->caps[4]; + break; + + case 0x460: /* DMA_PCh2_SR */ +@@ -1193,7 +1244,7 @@ static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr) + + switch (offset) { + case 0x300 ... 0x3fe: +- if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) { ++ if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) { + if (omap_dma_3_1_lcd_read(&s->lcd_ch, offset, &ret)) + break; + return ret; +@@ -1207,7 +1258,7 @@ static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr) + return ret; + + case 0x404 ... 0x4fe: +- if (s->model == omap_dma_3_1) ++ if (s->model <= omap_dma_3_1) + break; + /* Fall through. */ + case 0x400: +@@ -1236,7 +1287,7 @@ static void omap_dma_write(void *opaque, target_phys_addr_t addr, + + switch (offset) { + case 0x300 ... 0x3fe: +- if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) { ++ if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) { + if (omap_dma_3_1_lcd_write(&s->lcd_ch, offset, value)) + break; + return; +@@ -1250,7 +1301,7 @@ static void omap_dma_write(void *opaque, target_phys_addr_t addr, + return; + + case 0x404 ... 0x4fe: +- if (s->model == omap_dma_3_1) ++ if (s->model <= omap_dma_3_1) + break; + case 0x400: + /* Fall through. */ +@@ -1285,7 +1336,7 @@ static CPUWriteMemoryFunc *omap_dma_writefn[] = { + static void omap_dma_request(void *opaque, int drq, int req) + { + struct omap_dma_s *s = (struct omap_dma_s *) opaque; +- /* The request pins are level triggered. */ ++ /* The request pins are level triggered in QEMU. */ + if (req) { + if (~s->drq & (1 << drq)) { + s->drq |= 1 << drq; +@@ -1310,6 +1361,52 @@ static void omap_dma_clk_update(void *opaque, int line, int on) + } + } + ++static void omap_dma_setcaps(struct omap_dma_s *s) ++{ ++ switch (s->model) { ++ default: ++ case omap_dma_3_1: ++ break; ++ case omap_dma_3_2: ++ case omap_dma_4: ++ /* XXX Only available for sDMA */ ++ s->caps[0] = ++ (1 << 19) | /* Constant Fill Capability */ ++ (1 << 18); /* Transparent BLT Capability */ ++ s->caps[1] = ++ (1 << 1); /* 1-bit palettized capability (DMA 3.2 only) */ ++ s->caps[2] = ++ (1 << 8) | /* SEPARATE_SRC_AND_DST_INDEX_CPBLTY */ ++ (1 << 7) | /* DST_DOUBLE_INDEX_ADRS_CPBLTY */ ++ (1 << 6) | /* DST_SINGLE_INDEX_ADRS_CPBLTY */ ++ (1 << 5) | /* DST_POST_INCRMNT_ADRS_CPBLTY */ ++ (1 << 4) | /* DST_CONST_ADRS_CPBLTY */ ++ (1 << 3) | /* SRC_DOUBLE_INDEX_ADRS_CPBLTY */ ++ (1 << 2) | /* SRC_SINGLE_INDEX_ADRS_CPBLTY */ ++ (1 << 1) | /* SRC_POST_INCRMNT_ADRS_CPBLTY */ ++ (1 << 0); /* SRC_CONST_ADRS_CPBLTY */ ++ s->caps[3] = ++ (1 << 6) | /* BLOCK_SYNCHR_CPBLTY (DMA 4 only) */ ++ (1 << 7) | /* PKT_SYNCHR_CPBLTY (DMA 4 only) */ ++ (1 << 5) | /* CHANNEL_CHAINING_CPBLTY */ ++ (1 << 4) | /* LCh_INTERLEAVE_CPBLTY */ ++ (1 << 3) | /* AUTOINIT_REPEAT_CPBLTY (DMA 3.2 only) */ ++ (1 << 2) | /* AUTOINIT_ENDPROG_CPBLTY (DMA 3.2 only) */ ++ (1 << 1) | /* FRAME_SYNCHR_CPBLTY */ ++ (1 << 0); /* ELMNT_SYNCHR_CPBLTY */ ++ s->caps[4] = ++ (1 << 7) | /* PKT_INTERRUPT_CPBLTY (DMA 4 only) */ ++ (1 << 6) | /* SYNC_STATUS_CPBLTY */ ++ (1 << 5) | /* BLOCK_INTERRUPT_CPBLTY */ ++ (1 << 4) | /* LAST_FRAME_INTERRUPT_CPBLTY */ ++ (1 << 3) | /* FRAME_INTERRUPT_CPBLTY */ ++ (1 << 2) | /* HALF_FRAME_INTERRUPT_CPBLTY */ ++ (1 << 1) | /* EVENT_DROP_INTERRUPT_CPBLTY */ ++ (1 << 0); /* TIMEOUT_INTERRUPT_CPBLTY (DMA 3.2 only) */ ++ break; ++ } ++} ++ + struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, + qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk, + enum omap_dma_model model) +@@ -1318,7 +1415,7 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, + struct omap_dma_s *s = (struct omap_dma_s *) + qemu_mallocz(sizeof(struct omap_dma_s)); + +- if (model == omap_dma_3_1) { ++ if (model <= omap_dma_3_1) { + num_irqs = 6; + memsize = 0x800; + } else { +@@ -1331,6 +1428,7 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, + s->clk = clk; + s->lcd_ch.irq = lcd_irq; + s->lcd_ch.mpu = mpu; ++ omap_dma_setcaps(s); + while (num_irqs --) + s->ch[num_irqs].irq = irqs[num_irqs]; + for (i = 0; i < 3; i ++) { +@@ -1350,6 +1448,393 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, + return s; + } + ++static void omap_dma_interrupts_4_update(struct omap_dma_s *s) ++{ ++ struct omap_dma_channel_s *ch = s->ch; ++ uint32_t bmp, bit; ++ ++ for (bmp = 0, bit = 1; bit; ch ++, bit <<= 1) ++ if (ch->status) { ++ bmp |= bit; ++ ch->cstatus |= ch->status; ++ ch->status = 0; ++ } ++ if ((s->irqstat[0] |= s->irqen[0] & bmp)) ++ qemu_irq_raise(s->irq[0]); ++ if ((s->irqstat[1] |= s->irqen[1] & bmp)) ++ qemu_irq_raise(s->irq[1]); ++ if ((s->irqstat[2] |= s->irqen[2] & bmp)) ++ qemu_irq_raise(s->irq[2]); ++ if ((s->irqstat[3] |= s->irqen[3] & bmp)) ++ qemu_irq_raise(s->irq[3]); ++} ++ ++static uint32_t omap_dma4_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_dma_s *s = (struct omap_dma_s *) opaque; ++ int irqn = 0, chnum, offset = addr - s->base; ++ struct omap_dma_channel_s *ch; ++ ++ switch (offset) { ++ case 0x00: /* DMA4_REVISION */ ++ return 0x40; ++ ++ case 0x14: /* DMA4_IRQSTATUS_L3 */ ++ irqn ++; ++ case 0x10: /* DMA4_IRQSTATUS_L2 */ ++ irqn ++; ++ case 0x0c: /* DMA4_IRQSTATUS_L1 */ ++ irqn ++; ++ case 0x08: /* DMA4_IRQSTATUS_L0 */ ++ return s->irqstat[irqn]; ++ ++ case 0x24: /* DMA4_IRQENABLE_L3 */ ++ irqn ++; ++ case 0x20: /* DMA4_IRQENABLE_L2 */ ++ irqn ++; ++ case 0x1c: /* DMA4_IRQENABLE_L1 */ ++ irqn ++; ++ case 0x18: /* DMA4_IRQENABLE_L0 */ ++ return s->irqen[irqn]; ++ ++ case 0x28: /* DMA4_SYSSTATUS */ ++ return 1; /* RESETDONE */ ++ ++ case 0x2c: /* DMA4_OCP_SYSCONFIG */ ++ return s->ocp; ++ ++ case 0x64: /* DMA4_CAPS_0 */ ++ return s->caps[0]; ++ case 0x6c: /* DMA4_CAPS_2 */ ++ return s->caps[2]; ++ case 0x70: /* DMA4_CAPS_3 */ ++ return s->caps[3]; ++ case 0x74: /* DMA4_CAPS_4 */ ++ return s->caps[4]; ++ ++ case 0x78: /* DMA4_GCR */ ++ return s->gcr; ++ ++ case 0x80 ... 0xfff: ++ offset -= 0x80; ++ chnum = offset / 0x60; ++ ch = s->ch + chnum; ++ offset -= chnum * 0x60; ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ return 0; ++ } ++ ++ /* Per-channel registers */ ++ switch (offset) { ++ case 0x00: /* DMA4_CCR */ ++ return (ch->buf_disable << 25) | ++ (ch->src_sync << 24) | ++ (ch->prefetch << 23) | ++ ((ch->sync & 0x60) << 14) | ++ (ch->bs << 18) | ++ (ch->transparent_copy << 17) | ++ (ch->constant_fill << 16) | ++ (ch->mode[1] << 14) | ++ (ch->mode[0] << 12) | ++ (0 << 10) | (0 << 9) | ++ (ch->suspend << 8) | ++ (ch->enable << 7) | ++ (ch->priority << 6) | ++ (ch->fs << 5) | (ch->sync & 0x1f); ++ ++ case 0x04: /* DMA4_CLNK_CTRL */ ++ return (ch->link_enabled << 15) | ch->link_next_ch; ++ ++ case 0x08: /* DMA4_CICR */ ++ return ch->interrupts; ++ ++ case 0x0c: /* DMA4_CSR */ ++ return ch->cstatus; ++ ++ case 0x10: /* DMA4_CSDP */ ++ return (ch->endian[0] << 21) | ++ (ch->endian_lock[0] << 20) | ++ (ch->endian[1] << 19) | ++ (ch->endian_lock[1] << 18) | ++ (ch->write_mode << 16) | ++ (ch->burst[1] << 14) | ++ (ch->pack[1] << 13) | ++ (ch->translate[1] << 9) | ++ (ch->burst[0] << 7) | ++ (ch->pack[0] << 6) | ++ (ch->translate[0] << 2) | ++ (ch->data_type >> 1); ++ ++ case 0x14: /* DMA4_CEN */ ++ return ch->elements; ++ ++ case 0x18: /* DMA4_CFN */ ++ return ch->frames; ++ ++ case 0x1c: /* DMA4_CSSA */ ++ return ch->addr[0]; ++ ++ case 0x20: /* DMA4_CDSA */ ++ return ch->addr[1]; ++ ++ case 0x24: /* DMA4_CSEI */ ++ return ch->element_index[0]; ++ ++ case 0x28: /* DMA4_CSFI */ ++ return ch->frame_index[0]; ++ ++ case 0x2c: /* DMA4_CDEI */ ++ return ch->element_index[1]; ++ ++ case 0x30: /* DMA4_CDFI */ ++ return ch->frame_index[1]; ++ ++ case 0x34: /* DMA4_CSAC */ ++ return ch->active_set.src & 0xffff; ++ ++ case 0x38: /* DMA4_CDAC */ ++ return ch->active_set.dest & 0xffff; ++ ++ case 0x3c: /* DMA4_CCEN */ ++ return ch->active_set.element; ++ ++ case 0x40: /* DMA4_CCFN */ ++ return ch->active_set.frame; ++ ++ case 0x44: /* DMA4_COLOR */ ++ /* XXX only in sDMA */ ++ return ch->color; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ return 0; ++ } ++} ++ ++static void omap_dma4_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_dma_s *s = (struct omap_dma_s *) opaque; ++ int chnum, irqn = 0, offset = addr - s->base; ++ struct omap_dma_channel_s *ch; ++ ++ switch (offset) { ++ case 0x14: /* DMA4_IRQSTATUS_L3 */ ++ irqn ++; ++ case 0x10: /* DMA4_IRQSTATUS_L2 */ ++ irqn ++; ++ case 0x0c: /* DMA4_IRQSTATUS_L1 */ ++ irqn ++; ++ case 0x08: /* DMA4_IRQSTATUS_L0 */ ++ s->irqstat[irqn] &= ~value; ++ if (!s->irqstat[irqn]) ++ qemu_irq_lower(s->irq[irqn]); ++ return; ++ ++ case 0x24: /* DMA4_IRQENABLE_L3 */ ++ irqn ++; ++ case 0x20: /* DMA4_IRQENABLE_L2 */ ++ irqn ++; ++ case 0x1c: /* DMA4_IRQENABLE_L1 */ ++ irqn ++; ++ case 0x18: /* DMA4_IRQENABLE_L0 */ ++ s->irqen[irqn] = value; ++ return; ++ ++ case 0x2c: /* DMA4_OCP_SYSCONFIG */ ++ if (value & 2) /* SOFTRESET */ ++ omap_dma_reset(s); ++ s->ocp = value & 0x3321; ++ if (((s->ocp >> 12) & 3) == 3) /* MIDLEMODE */ ++ fprintf(stderr, "%s: invalid DMA power mode\n", __FUNCTION__); ++ return; ++ ++ case 0x78: /* DMA4_GCR */ ++ s->gcr = value & 0x00ff00ff; ++ if ((value & 0xff) == 0x00) /* MAX_CHANNEL_FIFO_DEPTH */ ++ fprintf(stderr, "%s: wrong FIFO depth in GCR\n", __FUNCTION__); ++ return; ++ ++ case 0x80 ... 0xfff: ++ offset -= 0x80; ++ chnum = offset / 0x60; ++ ch = s->ch + chnum; ++ offset -= chnum * 0x60; ++ break; ++ ++ case 0x00: /* DMA4_REVISION */ ++ case 0x28: /* DMA4_SYSSTATUS */ ++ case 0x64: /* DMA4_CAPS_0 */ ++ case 0x6c: /* DMA4_CAPS_2 */ ++ case 0x70: /* DMA4_CAPS_3 */ ++ case 0x74: /* DMA4_CAPS_4 */ ++ OMAP_RO_REG(addr); ++ return; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ return; ++ } ++ ++ /* Per-channel registers */ ++ switch (offset) { ++ case 0x00: /* DMA4_CCR */ ++ ch->buf_disable = (value >> 25) & 1; ++ ch->src_sync = (value >> 24) & 1; /* XXX For CamDMA must be 1 */ ++ if (ch->buf_disable && !ch->src_sync) ++ fprintf(stderr, "%s: Buffering disable is not allowed in " ++ "destination synchronised mode\n", __FUNCTION__); ++ ch->prefetch = (value >> 23) & 1; ++ ch->bs = (value >> 18) & 1; ++ ch->transparent_copy = (value >> 17) & 1; ++ ch->constant_fill = (value >> 16) & 1; ++ ch->mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14); ++ ch->mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12); ++ ch->suspend = (value & 0x0100) >> 8; ++ ch->priority = (value & 0x0040) >> 6; ++ ch->fs = (value & 0x0020) >> 5; ++ if (ch->fs && ch->bs && ch->mode[0] && ch->mode[1]) ++ fprintf(stderr, "%s: For a packet transfer at least one port " ++ "must be constant-addressed\n", __FUNCTION__); ++ ch->sync = (value & 0x001f) | ((value >> 14) & 0x0060); ++ /* XXX must be 0x01 for CamDMA */ ++ ++ if (value & 0x0080) ++ omap_dma_enable_channel(s, ch); ++ else ++ omap_dma_disable_channel(s, ch); ++ ++ break; ++ ++ case 0x04: /* DMA4_CLNK_CTRL */ ++ ch->link_enabled = (value >> 15) & 0x1; ++ ch->link_next_ch = value & 0x1f; ++ break; ++ ++ case 0x08: /* DMA4_CICR */ ++ ch->interrupts = value & 0x09be; ++ break; ++ ++ case 0x0c: /* DMA4_CSR */ ++ ch->cstatus &= ~value; ++ break; ++ ++ case 0x10: /* DMA4_CSDP */ ++ ch->endian[0] =(value >> 21) & 1; ++ ch->endian_lock[0] =(value >> 20) & 1; ++ ch->endian[1] =(value >> 19) & 1; ++ ch->endian_lock[1] =(value >> 18) & 1; ++ if (ch->endian[0] != ch->endian[1]) ++ fprintf(stderr, "%s: DMA endianned conversion enable attempt\n", ++ __FUNCTION__); ++ ch->write_mode = (value >> 16) & 3; ++ ch->burst[1] = (value & 0xc000) >> 14; ++ ch->pack[1] = (value & 0x2000) >> 13; ++ ch->translate[1] = (value & 0x1e00) >> 9; ++ ch->burst[0] = (value & 0x0180) >> 7; ++ ch->pack[0] = (value & 0x0040) >> 6; ++ ch->translate[0] = (value & 0x003c) >> 2; ++ if (ch->translate[0] | ch->translate[1]) ++ fprintf(stderr, "%s: bad MReqAddressTranslate sideband signal\n", ++ __FUNCTION__); ++ ch->data_type = 1 << (value & 3); ++ if ((value & 3) == 3) ++ printf("%s: bad data_type for DMA channel\n", __FUNCTION__); ++ break; ++ ++ case 0x14: /* DMA4_CEN */ ++ ch->elements = value & 0xffffff; ++ break; ++ ++ case 0x18: /* DMA4_CFN */ ++ ch->frames = value & 0xffff; ++ break; ++ ++ case 0x1c: /* DMA4_CSSA */ ++ ch->addr[0] = (target_phys_addr_t) (uint32_t) value; ++ break; ++ ++ case 0x20: /* DMA4_CDSA */ ++ ch->addr[1] = (target_phys_addr_t) (uint32_t) value; ++ break; ++ ++ case 0x24: /* DMA4_CSEI */ ++ ch->element_index[0] = (int16_t) value; ++ break; ++ ++ case 0x28: /* DMA4_CSFI */ ++ ch->frame_index[0] = (int32_t) value; ++ break; ++ ++ case 0x2c: /* DMA4_CDEI */ ++ ch->element_index[1] = (int16_t) value; ++ break; ++ ++ case 0x30: /* DMA4_CDFI */ ++ ch->frame_index[1] = (int32_t) value; ++ break; ++ ++ case 0x44: /* DMA4_COLOR */ ++ /* XXX only in sDMA */ ++ ch->color = value; ++ break; ++ ++ case 0x34: /* DMA4_CSAC */ ++ case 0x38: /* DMA4_CDAC */ ++ case 0x3c: /* DMA4_CCEN */ ++ case 0x40: /* DMA4_CCFN */ ++ OMAP_RO_REG(addr); ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ } ++} ++ ++static CPUReadMemoryFunc *omap_dma4_readfn[] = { ++ omap_badwidth_read16, ++ omap_dma4_read, ++ omap_dma4_read, ++}; ++ ++static CPUWriteMemoryFunc *omap_dma4_writefn[] = { ++ omap_badwidth_write16, ++ omap_dma4_write, ++ omap_dma4_write, ++}; ++ ++struct omap_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs, ++ struct omap_mpu_state_s *mpu, int fifo, ++ int chans, omap_clk iclk, omap_clk fclk) ++{ ++ int iomemtype; ++ struct omap_dma_s *s = (struct omap_dma_s *) ++ qemu_mallocz(sizeof(struct omap_dma_s)); ++ ++ s->base = base; ++ s->model = omap_dma_4; ++ s->chans = chans; ++ s->mpu = mpu; ++ s->clk = fclk; ++ memcpy(&s->irq, irqs, sizeof(s->irq)); ++ s->intr_update = omap_dma_interrupts_4_update; ++ omap_dma_setcaps(s); ++ s->tm = qemu_new_timer(vm_clock, (QEMUTimerCB *) omap_dma_channel_run, s); ++ omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]); ++ mpu->drq = qemu_allocate_irqs(omap_dma_request, s, 64); ++ omap_dma_reset(s); ++ omap_dma_clk_update(s, 0, 1); ++ ++ iomemtype = cpu_register_io_memory(0, omap_dma4_readfn, ++ omap_dma4_writefn, s); ++ cpu_register_physical_memory(s->base, 0x1000, iomemtype); ++ ++ return s; ++} ++ + struct omap_dma_lcd_channel_s *omap_dma_get_lcdch(struct omap_dma_s *s) + { + return &s->lcd_ch; +diff --git a/hw/omap_dss.c b/hw/omap_dss.c +new file mode 100644 +index 0000000..1c16802 +--- /dev/null ++++ b/hw/omap_dss.c +@@ -0,0 +1,1088 @@ ++/* ++ * OMAP2 Display Subsystem. ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Written by Andrzej Zaborowski ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ */ ++#include "hw.h" ++#include "console.h" ++#include "omap.h" ++ ++struct omap_dss_s { ++ target_phys_addr_t diss_base; ++ target_phys_addr_t disc_base; ++ target_phys_addr_t rfbi_base; ++ target_phys_addr_t venc_base; ++ target_phys_addr_t im3_base; ++ qemu_irq irq; ++ qemu_irq drq; ++ DisplayState *state; ++ ++ int autoidle; ++ int control; ++ int enable; ++ ++ struct omap_dss_panel_s { ++ int enable; ++ int nx; ++ int ny; ++ ++ int x; ++ int y; ++ } dig, lcd; ++ ++ struct { ++ uint32_t idlemode; ++ uint32_t irqst; ++ uint32_t irqen; ++ uint32_t control; ++ uint32_t config; ++ uint32_t capable; ++ uint32_t timing[3]; ++ int line; ++ uint32_t bg[2]; ++ uint32_t trans[2]; ++ ++ struct omap_dss_plane_s { ++ int enable; ++ int bpp; ++ int posx; ++ int posy; ++ int nx; ++ int ny; ++ ++ target_phys_addr_t addr[3]; ++ ++ uint32_t attr; ++ uint32_t tresh; ++ int rowinc; ++ int colinc; ++ int wininc; ++ } l[3]; ++ ++ int invalidate; ++ uint16_t palette[256]; ++ } dispc; ++ ++ struct { ++ int idlemode; ++ uint32_t control; ++ int enable; ++ int pixels; ++ int busy; ++ int skiplines; ++ uint16_t rxbuf; ++ uint32_t config[2]; ++ uint32_t time[4]; ++ uint32_t data[6]; ++ uint16_t vsync; ++ uint16_t hsync; ++ struct rfbi_chip_s *chip[2]; ++ } rfbi; ++}; ++ ++static void omap_dispc_interrupt_update(struct omap_dss_s *s) ++{ ++ qemu_set_irq(s->irq, s->dispc.irqst & s->dispc.irqen); ++} ++ ++static void omap_rfbi_reset(struct omap_dss_s *s) ++{ ++ s->rfbi.idlemode = 0; ++ s->rfbi.control = 2; ++ s->rfbi.enable = 0; ++ s->rfbi.pixels = 0; ++ s->rfbi.skiplines = 0; ++ s->rfbi.busy = 0; ++ s->rfbi.config[0] = 0x00310000; ++ s->rfbi.config[1] = 0x00310000; ++ s->rfbi.time[0] = 0; ++ s->rfbi.time[1] = 0; ++ s->rfbi.time[2] = 0; ++ s->rfbi.time[3] = 0; ++ s->rfbi.data[0] = 0; ++ s->rfbi.data[1] = 0; ++ s->rfbi.data[2] = 0; ++ s->rfbi.data[3] = 0; ++ s->rfbi.data[4] = 0; ++ s->rfbi.data[5] = 0; ++ s->rfbi.vsync = 0; ++ s->rfbi.hsync = 0; ++} ++ ++void omap_dss_reset(struct omap_dss_s *s) ++{ ++ s->autoidle = 0; ++ s->control = 0; ++ s->enable = 0; ++ ++ s->dig.enable = 0; ++ s->dig.nx = 1; ++ s->dig.ny = 1; ++ ++ s->lcd.enable = 0; ++ s->lcd.nx = 1; ++ s->lcd.ny = 1; ++ ++ s->dispc.idlemode = 0; ++ s->dispc.irqst = 0; ++ s->dispc.irqen = 0; ++ s->dispc.control = 0; ++ s->dispc.config = 0; ++ s->dispc.capable = 0x161; ++ s->dispc.timing[0] = 0; ++ s->dispc.timing[1] = 0; ++ s->dispc.timing[2] = 0; ++ s->dispc.line = 0; ++ s->dispc.bg[0] = 0; ++ s->dispc.bg[1] = 0; ++ s->dispc.trans[0] = 0; ++ s->dispc.trans[1] = 0; ++ ++ s->dispc.l[0].enable = 0; ++ s->dispc.l[0].bpp = 0; ++ s->dispc.l[0].addr[0] = 0; ++ s->dispc.l[0].addr[1] = 0; ++ s->dispc.l[0].addr[2] = 0; ++ s->dispc.l[0].posx = 0; ++ s->dispc.l[0].posy = 0; ++ s->dispc.l[0].nx = 1; ++ s->dispc.l[0].ny = 1; ++ s->dispc.l[0].attr = 0; ++ s->dispc.l[0].tresh = 0; ++ s->dispc.l[0].rowinc = 1; ++ s->dispc.l[0].colinc = 1; ++ s->dispc.l[0].wininc = 0; ++ ++ omap_rfbi_reset(s); ++ omap_dispc_interrupt_update(s); ++} ++ ++static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_dss_s *s = (struct omap_dss_s *) opaque; ++ int offset = addr - s->diss_base; ++ ++ switch (offset) { ++ case 0x00: /* DSS_REVISIONNUMBER */ ++ return 0x20; ++ ++ case 0x10: /* DSS_SYSCONFIG */ ++ return s->autoidle; ++ ++ case 0x14: /* DSS_SYSSTATUS */ ++ return 1; /* RESETDONE */ ++ ++ case 0x40: /* DSS_CONTROL */ ++ return s->control; ++ ++ case 0x50: /* DSS_PSA_LCD_REG_1 */ ++ case 0x54: /* DSS_PSA_LCD_REG_2 */ ++ case 0x58: /* DSS_PSA_VIDEO_REG */ ++ /* TODO: fake some values when appropriate s->control bits are set */ ++ return 0; ++ ++ case 0x5c: /* DSS_STATUS */ ++ return 1 + (s->control & 1); ++ ++ default: ++ break; ++ } ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap_diss_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_dss_s *s = (struct omap_dss_s *) opaque; ++ int offset = addr - s->diss_base; ++ ++ switch (offset) { ++ case 0x00: /* DSS_REVISIONNUMBER */ ++ case 0x14: /* DSS_SYSSTATUS */ ++ case 0x50: /* DSS_PSA_LCD_REG_1 */ ++ case 0x54: /* DSS_PSA_LCD_REG_2 */ ++ case 0x58: /* DSS_PSA_VIDEO_REG */ ++ case 0x5c: /* DSS_STATUS */ ++ OMAP_RO_REG(addr); ++ break; ++ ++ case 0x10: /* DSS_SYSCONFIG */ ++ if (value & 2) /* SOFTRESET */ ++ omap_dss_reset(s); ++ s->autoidle = value & 1; ++ break; ++ ++ case 0x40: /* DSS_CONTROL */ ++ s->control = value & 0x3dd; ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ } ++} ++ ++static CPUReadMemoryFunc *omap_diss1_readfn[] = { ++ omap_badwidth_read32, ++ omap_badwidth_read32, ++ omap_diss_read, ++}; ++ ++static CPUWriteMemoryFunc *omap_diss1_writefn[] = { ++ omap_badwidth_write32, ++ omap_badwidth_write32, ++ omap_diss_write, ++}; ++ ++static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_dss_s *s = (struct omap_dss_s *) opaque; ++ int offset = addr - s->disc_base; ++ ++ switch (offset) { ++ case 0x000: /* DISPC_REVISION */ ++ return 0x20; ++ ++ case 0x010: /* DISPC_SYSCONFIG */ ++ return s->dispc.idlemode; ++ ++ case 0x014: /* DISPC_SYSSTATUS */ ++ return 1; /* RESETDONE */ ++ ++ case 0x018: /* DISPC_IRQSTATUS */ ++ return s->dispc.irqst; ++ ++ case 0x01c: /* DISPC_IRQENABLE */ ++ return s->dispc.irqen; ++ ++ case 0x040: /* DISPC_CONTROL */ ++ return s->dispc.control; ++ ++ case 0x044: /* DISPC_CONFIG */ ++ return s->dispc.config; ++ ++ case 0x048: /* DISPC_CAPABLE */ ++ return s->dispc.capable; ++ ++ case 0x04c: /* DISPC_DEFAULT_COLOR0 */ ++ return s->dispc.bg[0]; ++ case 0x050: /* DISPC_DEFAULT_COLOR1 */ ++ return s->dispc.bg[1]; ++ case 0x054: /* DISPC_TRANS_COLOR0 */ ++ return s->dispc.trans[0]; ++ case 0x058: /* DISPC_TRANS_COLOR1 */ ++ return s->dispc.trans[1]; ++ ++ case 0x05c: /* DISPC_LINE_STATUS */ ++ return 0x7ff; ++ case 0x060: /* DISPC_LINE_NUMBER */ ++ return s->dispc.line; ++ ++ case 0x064: /* DISPC_TIMING_H */ ++ return s->dispc.timing[0]; ++ case 0x068: /* DISPC_TIMING_V */ ++ return s->dispc.timing[1]; ++ case 0x06c: /* DISPC_POL_FREQ */ ++ return s->dispc.timing[2]; ++ case 0x070: /* DISPC_DIVISOR */ ++ return s->dispc.timing[3]; ++ ++ case 0x078: /* DISPC_SIZE_DIG */ ++ return ((s->dig.ny - 1) << 16) | (s->dig.nx - 1); ++ case 0x07c: /* DISPC_SIZE_LCD */ ++ return ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1); ++ ++ case 0x080: /* DISPC_GFX_BA0 */ ++ return s->dispc.l[0].addr[0]; ++ case 0x084: /* DISPC_GFX_BA1 */ ++ return s->dispc.l[0].addr[1]; ++ case 0x088: /* DISPC_GFX_POSITION */ ++ return (s->dispc.l[0].posy << 16) | s->dispc.l[0].posx; ++ case 0x08c: /* DISPC_GFX_SIZE */ ++ return ((s->dispc.l[0].ny - 1) << 16) | (s->dispc.l[0].nx - 1); ++ case 0x0a0: /* DISPC_GFX_ATTRIBUTES */ ++ return s->dispc.l[0].attr; ++ case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */ ++ return s->dispc.l[0].tresh; ++ case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */ ++ return 256; ++ case 0x0ac: /* DISPC_GFX_ROW_INC */ ++ return s->dispc.l[0].rowinc; ++ case 0x0b0: /* DISPC_GFX_PIXEL_INC */ ++ return s->dispc.l[0].colinc; ++ case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */ ++ return s->dispc.l[0].wininc; ++ case 0x0b8: /* DISPC_GFX_TABLE_BA */ ++ return s->dispc.l[0].addr[2]; ++ ++ case 0x0bc: /* DISPC_VID1_BA0 */ ++ case 0x0c0: /* DISPC_VID1_BA1 */ ++ case 0x0c4: /* DISPC_VID1_POSITION */ ++ case 0x0c8: /* DISPC_VID1_SIZE */ ++ case 0x0cc: /* DISPC_VID1_ATTRIBUTES */ ++ case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */ ++ case 0x0d4: /* DISPC_VID1_FIFO_SIZE_STATUS */ ++ case 0x0d8: /* DISPC_VID1_ROW_INC */ ++ case 0x0dc: /* DISPC_VID1_PIXEL_INC */ ++ case 0x0e0: /* DISPC_VID1_FIR */ ++ case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */ ++ case 0x0e8: /* DISPC_VID1_ACCU0 */ ++ case 0x0ec: /* DISPC_VID1_ACCU1 */ ++ case 0x0f0 ... 0x140: /* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */ ++ case 0x14c: /* DISPC_VID2_BA0 */ ++ case 0x150: /* DISPC_VID2_BA1 */ ++ case 0x154: /* DISPC_VID2_POSITION */ ++ case 0x158: /* DISPC_VID2_SIZE */ ++ case 0x15c: /* DISPC_VID2_ATTRIBUTES */ ++ case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */ ++ case 0x164: /* DISPC_VID2_FIFO_SIZE_STATUS */ ++ case 0x168: /* DISPC_VID2_ROW_INC */ ++ case 0x16c: /* DISPC_VID2_PIXEL_INC */ ++ case 0x170: /* DISPC_VID2_FIR */ ++ case 0x174: /* DISPC_VID2_PICTURE_SIZE */ ++ case 0x178: /* DISPC_VID2_ACCU0 */ ++ case 0x17c: /* DISPC_VID2_ACCU1 */ ++ case 0x180 ... 0x1d0: /* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */ ++ case 0x1d4: /* DISPC_DATA_CYCLE1 */ ++ case 0x1d8: /* DISPC_DATA_CYCLE2 */ ++ case 0x1dc: /* DISPC_DATA_CYCLE3 */ ++ return 0; ++ ++ default: ++ break; ++ } ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap_disc_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_dss_s *s = (struct omap_dss_s *) opaque; ++ int offset = addr - s->disc_base; ++ ++ switch (offset) { ++ case 0x010: /* DISPC_SYSCONFIG */ ++ if (value & 2) /* SOFTRESET */ ++ omap_dss_reset(s); ++ s->dispc.idlemode = value & 0x301b; ++ break; ++ ++ case 0x018: /* DISPC_IRQSTATUS */ ++ s->dispc.irqst &= ~value; ++ omap_dispc_interrupt_update(s); ++ break; ++ ++ case 0x01c: /* DISPC_IRQENABLE */ ++ s->dispc.irqen = value & 0xffff; ++ omap_dispc_interrupt_update(s); ++ break; ++ ++ case 0x040: /* DISPC_CONTROL */ ++ s->dispc.control = value & 0x07ff9fff; ++ s->dig.enable = (value >> 1) & 1; ++ s->lcd.enable = (value >> 0) & 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 " ++ "region effectively exists leads to " ++ "unpredictable behaviour!\n", __FUNCTION__); ++ if (value & (1 << 6)) { /* GODIGITAL */ ++ //// Shadows: ++ //// s->dispc.config ++ //// s->dispc.capable ++ //// s->dispc.bg[0] ++ //// s->dispc.bg[1] ++ //// s->dispc.trans[0] ++ //// s->dispc.trans[1] ++ //// s->dispc.line ++ //// s->dispc.timing[0] ++ //// s->dispc.timing[1] ++ //// s->dispc.timing[2] ++ //// s->dispc.timing[3] ++ //// s->lcd.nx ++ //// s->lcd.ny ++ //// s->dig.nx ++ //// s->dig.ny ++ //// s->dispc.l[0].addr[0] ++ //// s->dispc.l[0].addr[1] ++ //// s->dispc.l[0].addr[2] ++ //// s->dispc.l[0].posx ++ //// s->dispc.l[0].posy ++ //// s->dispc.l[0].nx ++ //// s->dispc.l[0].ny ++ //// s->dispc.l[0].tresh ++ //// s->dispc.l[0].rowinc ++ //// s->dispc.l[0].colinc ++ //// s->dispc.l[0].wininc ++ } ++ if (value & (1 << 5)) { /* GOLCD */ ++ } ++ s->dispc.invalidate = 1; ++ break; ++ ++ case 0x044: /* DISPC_CONFIG */ ++ s->dispc.config = value & 0x3fff; ++ //// bits 2:1 (LOADMODE) reset to 0 after set to 1 and palette loaded ++ //// bits 2:1 (LOADMODE) reset to 2 after set to 3 and palette loaded ++ s->dispc.invalidate = 1; ++ break; ++ ++ case 0x048: /* DISPC_CAPABLE */ ++ s->dispc.capable = value & 0x3ff; ++ break; ++ ++ case 0x04c: /* DISPC_DEFAULT_COLOR0 */ ++ s->dispc.bg[0] = value & 0xffffff; ++ s->dispc.invalidate = 1; ++ break; ++ case 0x050: /* DISPC_DEFAULT_COLOR1 */ ++ s->dispc.bg[1] = value & 0xffffff; ++ s->dispc.invalidate = 1; ++ break; ++ case 0x054: /* DISPC_TRANS_COLOR0 */ ++ s->dispc.trans[0] = value & 0xffffff; ++ s->dispc.invalidate = 1; ++ break; ++ case 0x058: /* DISPC_TRANS_COLOR1 */ ++ s->dispc.trans[1] = value & 0xffffff; ++ s->dispc.invalidate = 1; ++ break; ++ ++ case 0x060: /* DISPC_LINE_NUMBER */ ++ s->dispc.line = value & 0x7ff; ++ break; ++ ++ case 0x064: /* DISPC_TIMING_H */ ++ s->dispc.timing[0] = value & 0x0ff0ff3f; ++ break; ++ case 0x068: /* DISPC_TIMING_V */ ++ s->dispc.timing[1] = value & 0x0ff0ff3f; ++ break; ++ case 0x06c: /* DISPC_POL_FREQ */ ++ s->dispc.timing[2] = value & 0x0003ffff; ++ break; ++ case 0x070: /* DISPC_DIVISOR */ ++ s->dispc.timing[3] = value & 0x00ff00ff; ++ break; ++ ++ case 0x078: /* DISPC_SIZE_DIG */ ++ s->dig.nx = ((value >> 0) & 0x7ff) + 1; /* PPL */ ++ s->dig.ny = ((value >> 16) & 0x7ff) + 1; /* LPP */ ++ s->dispc.invalidate = 1; ++ break; ++ case 0x07c: /* DISPC_SIZE_LCD */ ++ s->lcd.nx = ((value >> 0) & 0x7ff) + 1; /* PPL */ ++ s->lcd.ny = ((value >> 16) & 0x7ff) + 1; /* LPP */ ++ s->dispc.invalidate = 1; ++ break; ++ case 0x080: /* DISPC_GFX_BA0 */ ++ s->dispc.l[0].addr[0] = (target_phys_addr_t) value; ++ s->dispc.invalidate = 1; ++ break; ++ case 0x084: /* DISPC_GFX_BA1 */ ++ s->dispc.l[0].addr[1] = (target_phys_addr_t) value; ++ s->dispc.invalidate = 1; ++ break; ++ case 0x088: /* DISPC_GFX_POSITION */ ++ s->dispc.l[0].posx = ((value >> 0) & 0x7ff); /* GFXPOSX */ ++ s->dispc.l[0].posy = ((value >> 16) & 0x7ff); /* GFXPOSY */ ++ s->dispc.invalidate = 1; ++ break; ++ case 0x08c: /* DISPC_GFX_SIZE */ ++ s->dispc.l[0].nx = ((value >> 0) & 0x7ff) + 1; /* GFXSIZEX */ ++ s->dispc.l[0].ny = ((value >> 16) & 0x7ff) + 1; /* GFXSIZEY */ ++ s->dispc.invalidate = 1; ++ break; ++ case 0x0a0: /* DISPC_GFX_ATTRIBUTES */ ++ s->dispc.l[0].attr = value & 0x7ff; ++ 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.invalidate = 1; ++ break; ++ case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */ ++ s->dispc.l[0].tresh = value & 0x01ff01ff; ++ break; ++ case 0x0ac: /* DISPC_GFX_ROW_INC */ ++ s->dispc.l[0].rowinc = value; ++ s->dispc.invalidate = 1; ++ break; ++ case 0x0b0: /* DISPC_GFX_PIXEL_INC */ ++ s->dispc.l[0].colinc = value; ++ s->dispc.invalidate = 1; ++ break; ++ case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */ ++ s->dispc.l[0].wininc = value; ++ break; ++ case 0x0b8: /* DISPC_GFX_TABLE_BA */ ++ s->dispc.l[0].addr[2] = (target_phys_addr_t) value; ++ s->dispc.invalidate = 1; ++ break; ++ ++ case 0x0bc: /* DISPC_VID1_BA0 */ ++ case 0x0c0: /* DISPC_VID1_BA1 */ ++ case 0x0c4: /* DISPC_VID1_POSITION */ ++ case 0x0c8: /* DISPC_VID1_SIZE */ ++ case 0x0cc: /* DISPC_VID1_ATTRIBUTES */ ++ case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */ ++ case 0x0d8: /* DISPC_VID1_ROW_INC */ ++ case 0x0dc: /* DISPC_VID1_PIXEL_INC */ ++ case 0x0e0: /* DISPC_VID1_FIR */ ++ case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */ ++ case 0x0e8: /* DISPC_VID1_ACCU0 */ ++ case 0x0ec: /* DISPC_VID1_ACCU1 */ ++ case 0x0f0 ... 0x140: /* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */ ++ case 0x14c: /* DISPC_VID2_BA0 */ ++ case 0x150: /* DISPC_VID2_BA1 */ ++ case 0x154: /* DISPC_VID2_POSITION */ ++ case 0x158: /* DISPC_VID2_SIZE */ ++ case 0x15c: /* DISPC_VID2_ATTRIBUTES */ ++ case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */ ++ case 0x168: /* DISPC_VID2_ROW_INC */ ++ case 0x16c: /* DISPC_VID2_PIXEL_INC */ ++ case 0x170: /* DISPC_VID2_FIR */ ++ case 0x174: /* DISPC_VID2_PICTURE_SIZE */ ++ case 0x178: /* DISPC_VID2_ACCU0 */ ++ case 0x17c: /* DISPC_VID2_ACCU1 */ ++ case 0x180 ... 0x1d0: /* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */ ++ case 0x1d4: /* DISPC_DATA_CYCLE1 */ ++ case 0x1d8: /* DISPC_DATA_CYCLE2 */ ++ case 0x1dc: /* DISPC_DATA_CYCLE3 */ ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ } ++} ++ ++static CPUReadMemoryFunc *omap_disc1_readfn[] = { ++ omap_badwidth_read32, ++ omap_badwidth_read32, ++ omap_disc_read, ++}; ++ ++static CPUWriteMemoryFunc *omap_disc1_writefn[] = { ++ omap_badwidth_write32, ++ omap_badwidth_write32, ++ omap_disc_write, ++}; ++ ++static void *omap_rfbi_get_buffer(struct omap_dss_s *s) ++{ ++ target_phys_addr_t fb; ++ uint32_t pd; ++ ++ /* TODO */ ++ fb = s->dispc.l[0].addr[0]; ++ ++ pd = cpu_get_physical_page_desc(fb); ++ if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) ++ /* TODO */ ++ cpu_abort(cpu_single_env, "%s: framebuffer outside RAM!\n", ++ __FUNCTION__); ++ else ++ return phys_ram_base + ++ (pd & TARGET_PAGE_MASK) + ++ (fb & ~TARGET_PAGE_MASK); ++} ++ ++static void omap_rfbi_transfer_stop(struct omap_dss_s *s) ++{ ++ if (!s->rfbi.busy) ++ return; ++ ++ /* TODO: in non-Bypass mode we probably need to just deassert the DRQ. */ ++ ++ s->rfbi.busy = 0; ++} ++ ++static void omap_rfbi_transfer_start(struct omap_dss_s *s) ++{ ++ void *data; ++ size_t len; ++ int pitch; ++ ++ if (!s->rfbi.enable || s->rfbi.busy) ++ return; ++ ++ if (s->rfbi.control & (1 << 1)) { /* BYPASS */ ++ /* TODO: in non-Bypass mode we probably need to just assert the ++ * DRQ and wait for DMA to write the pixels. */ ++ fprintf(stderr, "%s: Bypass mode unimplemented\n", __FUNCTION__); ++ return; ++ } ++ ++ if (!(s->dispc.control & (1 << 11))) /* RFBIMODE */ ++ return; ++ /* TODO: check that LCD output is enabled in DISPC. */ ++ ++ s->rfbi.busy = 1; ++ ++ data = omap_rfbi_get_buffer(s); ++ ++ /* TODO bpp */ ++ len = s->rfbi.pixels * 2; ++ s->rfbi.pixels = 0; ++ ++ /* TODO: negative values */ ++ pitch = s->dispc.l[0].nx + (s->dispc.l[0].rowinc - 1) / 2; ++ ++ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) ++ s->rfbi.chip[0]->block(s->rfbi.chip[0]->opaque, 1, data, len, pitch); ++ if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) ++ s->rfbi.chip[1]->block(s->rfbi.chip[1]->opaque, 1, data, len, pitch); ++ ++ omap_rfbi_transfer_stop(s); ++ ++ /* TODO */ ++ s->dispc.irqst |= 1; /* FRAMEDONE */ ++ omap_dispc_interrupt_update(s); ++} ++ ++static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_dss_s *s = (struct omap_dss_s *) opaque; ++ int offset = addr - s->rfbi_base; ++ ++ switch (offset) { ++ case 0x00: /* RFBI_REVISION */ ++ return 0x10; ++ ++ case 0x10: /* RFBI_SYSCONFIG */ ++ return s->rfbi.idlemode; ++ ++ case 0x14: /* RFBI_SYSSTATUS */ ++ return 1 | (s->rfbi.busy << 8); /* RESETDONE */ ++ ++ case 0x40: /* RFBI_CONTROL */ ++ return s->rfbi.control; ++ ++ case 0x44: /* RFBI_PIXELCNT */ ++ return s->rfbi.pixels; ++ ++ case 0x48: /* RFBI_LINE_NUMBER */ ++ return s->rfbi.skiplines; ++ ++ case 0x58: /* RFBI_READ */ ++ case 0x5c: /* RFBI_STATUS */ ++ return s->rfbi.rxbuf; ++ ++ case 0x60: /* RFBI_CONFIG0 */ ++ return s->rfbi.config[0]; ++ case 0x64: /* RFBI_ONOFF_TIME0 */ ++ return s->rfbi.time[0]; ++ case 0x68: /* RFBI_CYCLE_TIME0 */ ++ return s->rfbi.time[1]; ++ case 0x6c: /* RFBI_DATA_CYCLE1_0 */ ++ return s->rfbi.data[0]; ++ case 0x70: /* RFBI_DATA_CYCLE2_0 */ ++ return s->rfbi.data[1]; ++ case 0x74: /* RFBI_DATA_CYCLE3_0 */ ++ return s->rfbi.data[2]; ++ ++ case 0x78: /* RFBI_CONFIG1 */ ++ return s->rfbi.config[1]; ++ case 0x7c: /* RFBI_ONOFF_TIME1 */ ++ return s->rfbi.time[2]; ++ case 0x80: /* RFBI_CYCLE_TIME1 */ ++ return s->rfbi.time[3]; ++ case 0x84: /* RFBI_DATA_CYCLE1_1 */ ++ return s->rfbi.data[3]; ++ case 0x88: /* RFBI_DATA_CYCLE2_1 */ ++ return s->rfbi.data[4]; ++ case 0x8c: /* RFBI_DATA_CYCLE3_1 */ ++ return s->rfbi.data[5]; ++ ++ case 0x90: /* RFBI_VSYNC_WIDTH */ ++ return s->rfbi.vsync; ++ case 0x94: /* RFBI_HSYNC_WIDTH */ ++ return s->rfbi.hsync; ++ } ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap_rfbi_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_dss_s *s = (struct omap_dss_s *) opaque; ++ int offset = addr - s->rfbi_base; ++ ++ switch (offset) { ++ case 0x10: /* RFBI_SYSCONFIG */ ++ if (value & 2) /* SOFTRESET */ ++ omap_rfbi_reset(s); ++ s->rfbi.idlemode = value & 0x19; ++ break; ++ ++ case 0x40: /* RFBI_CONTROL */ ++ s->rfbi.control = value & 0xf; ++ s->rfbi.enable = value & 1; ++ if (value & (1 << 4) && /* ITE */ ++ !(s->rfbi.config[0] & s->rfbi.config[1] & 0xc)) ++ omap_rfbi_transfer_start(s); ++ break; ++ ++ case 0x44: /* RFBI_PIXELCNT */ ++ s->rfbi.pixels = value; ++ break; ++ ++ case 0x48: /* RFBI_LINE_NUMBER */ ++ s->rfbi.skiplines = value & 0x7ff; ++ break; ++ ++ case 0x4c: /* RFBI_CMD */ ++ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) ++ s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 0, value & 0xffff); ++ if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) ++ s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 0, value & 0xffff); ++ break; ++ case 0x50: /* RFBI_PARAM */ ++ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) ++ s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff); ++ if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) ++ s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff); ++ break; ++ case 0x54: /* RFBI_DATA */ ++ /* TODO: take into account the format set up in s->rfbi.config[?] and ++ * s->rfbi.data[?], but special-case the most usual scenario so that ++ * speed doesn't suffer. */ ++ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) { ++ s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff); ++ s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value >> 16); ++ } ++ if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) { ++ s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff); ++ s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value >> 16); ++ } ++ if (!-- s->rfbi.pixels) ++ omap_rfbi_transfer_stop(s); ++ break; ++ case 0x58: /* RFBI_READ */ ++ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) ++ s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1); ++ else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) ++ s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1); ++ if (!-- s->rfbi.pixels) ++ omap_rfbi_transfer_stop(s); ++ break; ++ ++ case 0x5c: /* RFBI_STATUS */ ++ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) ++ s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0); ++ else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) ++ s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0); ++ if (!-- s->rfbi.pixels) ++ omap_rfbi_transfer_stop(s); ++ break; ++ ++ case 0x60: /* RFBI_CONFIG0 */ ++ s->rfbi.config[0] = value & 0x003f1fff; ++ break; ++ ++ case 0x64: /* RFBI_ONOFF_TIME0 */ ++ s->rfbi.time[0] = value & 0x3fffffff; ++ break; ++ case 0x68: /* RFBI_CYCLE_TIME0 */ ++ s->rfbi.time[1] = value & 0x0fffffff; ++ break; ++ case 0x6c: /* RFBI_DATA_CYCLE1_0 */ ++ s->rfbi.data[0] = value & 0x0f1f0f1f; ++ break; ++ case 0x70: /* RFBI_DATA_CYCLE2_0 */ ++ s->rfbi.data[1] = value & 0x0f1f0f1f; ++ break; ++ case 0x74: /* RFBI_DATA_CYCLE3_0 */ ++ s->rfbi.data[2] = value & 0x0f1f0f1f; ++ break; ++ case 0x78: /* RFBI_CONFIG1 */ ++ s->rfbi.config[1] = value & 0x003f1fff; ++ break; ++ ++ case 0x7c: /* RFBI_ONOFF_TIME1 */ ++ s->rfbi.time[2] = value & 0x3fffffff; ++ break; ++ case 0x80: /* RFBI_CYCLE_TIME1 */ ++ s->rfbi.time[3] = value & 0x0fffffff; ++ break; ++ case 0x84: /* RFBI_DATA_CYCLE1_1 */ ++ s->rfbi.data[3] = value & 0x0f1f0f1f; ++ break; ++ case 0x88: /* RFBI_DATA_CYCLE2_1 */ ++ s->rfbi.data[4] = value & 0x0f1f0f1f; ++ break; ++ case 0x8c: /* RFBI_DATA_CYCLE3_1 */ ++ s->rfbi.data[5] = value & 0x0f1f0f1f; ++ break; ++ ++ case 0x90: /* RFBI_VSYNC_WIDTH */ ++ s->rfbi.vsync = value & 0xffff; ++ break; ++ case 0x94: /* RFBI_HSYNC_WIDTH */ ++ s->rfbi.hsync = value & 0xffff; ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ } ++} ++ ++static CPUReadMemoryFunc *omap_rfbi1_readfn[] = { ++ omap_badwidth_read32, ++ omap_badwidth_read32, ++ omap_rfbi_read, ++}; ++ ++static CPUWriteMemoryFunc *omap_rfbi1_writefn[] = { ++ omap_badwidth_write32, ++ omap_badwidth_write32, ++ omap_rfbi_write, ++}; ++ ++static uint32_t omap_venc_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_dss_s *s = (struct omap_dss_s *) opaque; ++ int offset = addr - s->venc_base; ++ ++ switch (offset) { ++ case 0x00: /* REV_ID */ ++ case 0x04: /* STATUS */ ++ case 0x08: /* F_CONTROL */ ++ case 0x10: /* VIDOUT_CTRL */ ++ case 0x14: /* SYNC_CTRL */ ++ case 0x1c: /* LLEN */ ++ case 0x20: /* FLENS */ ++ case 0x24: /* HFLTR_CTRL */ ++ case 0x28: /* CC_CARR_WSS_CARR */ ++ case 0x2c: /* C_PHASE */ ++ case 0x30: /* GAIN_U */ ++ case 0x34: /* GAIN_V */ ++ case 0x38: /* GAIN_Y */ ++ case 0x3c: /* BLACK_LEVEL */ ++ case 0x40: /* BLANK_LEVEL */ ++ case 0x44: /* X_COLOR */ ++ case 0x48: /* M_CONTROL */ ++ case 0x4c: /* BSTAMP_WSS_DATA */ ++ case 0x50: /* S_CARR */ ++ case 0x54: /* LINE21 */ ++ case 0x58: /* LN_SEL */ ++ case 0x5c: /* L21__WC_CTL */ ++ case 0x60: /* HTRIGGER_VTRIGGER */ ++ case 0x64: /* SAVID__EAVID */ ++ case 0x68: /* FLEN__FAL */ ++ case 0x6c: /* LAL__PHASE_RESET */ ++ case 0x70: /* HS_INT_START_STOP_X */ ++ case 0x74: /* HS_EXT_START_STOP_X */ ++ case 0x78: /* VS_INT_START_X */ ++ case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */ ++ case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */ ++ case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */ ++ case 0x88: /* VS_EXT_STOP_Y */ ++ case 0x90: /* AVID_START_STOP_X */ ++ case 0x94: /* AVID_START_STOP_Y */ ++ case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */ ++ case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */ ++ case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */ ++ case 0xb0: /* TVDETGP_INT_START_STOP_X */ ++ case 0xb4: /* TVDETGP_INT_START_STOP_Y */ ++ case 0xb8: /* GEN_CTRL */ ++ case 0xc4: /* DAC_TST__DAC_A */ ++ case 0xc8: /* DAC_B__DAC_C */ ++ return 0; ++ ++ default: ++ break; ++ } ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap_venc_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_dss_s *s = (struct omap_dss_s *) opaque; ++ int offset = addr - s->venc_base; ++ ++ switch (offset) { ++ case 0x08: /* F_CONTROL */ ++ case 0x10: /* VIDOUT_CTRL */ ++ case 0x14: /* SYNC_CTRL */ ++ case 0x1c: /* LLEN */ ++ case 0x20: /* FLENS */ ++ case 0x24: /* HFLTR_CTRL */ ++ case 0x28: /* CC_CARR_WSS_CARR */ ++ case 0x2c: /* C_PHASE */ ++ case 0x30: /* GAIN_U */ ++ case 0x34: /* GAIN_V */ ++ case 0x38: /* GAIN_Y */ ++ case 0x3c: /* BLACK_LEVEL */ ++ case 0x40: /* BLANK_LEVEL */ ++ case 0x44: /* X_COLOR */ ++ case 0x48: /* M_CONTROL */ ++ case 0x4c: /* BSTAMP_WSS_DATA */ ++ case 0x50: /* S_CARR */ ++ case 0x54: /* LINE21 */ ++ case 0x58: /* LN_SEL */ ++ case 0x5c: /* L21__WC_CTL */ ++ case 0x60: /* HTRIGGER_VTRIGGER */ ++ case 0x64: /* SAVID__EAVID */ ++ case 0x68: /* FLEN__FAL */ ++ case 0x6c: /* LAL__PHASE_RESET */ ++ case 0x70: /* HS_INT_START_STOP_X */ ++ case 0x74: /* HS_EXT_START_STOP_X */ ++ case 0x78: /* VS_INT_START_X */ ++ case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */ ++ case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */ ++ case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */ ++ case 0x88: /* VS_EXT_STOP_Y */ ++ case 0x90: /* AVID_START_STOP_X */ ++ case 0x94: /* AVID_START_STOP_Y */ ++ case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */ ++ case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */ ++ case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */ ++ case 0xb0: /* TVDETGP_INT_START_STOP_X */ ++ case 0xb4: /* TVDETGP_INT_START_STOP_Y */ ++ case 0xb8: /* GEN_CTRL */ ++ case 0xc4: /* DAC_TST__DAC_A */ ++ case 0xc8: /* DAC_B__DAC_C */ ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ } ++} ++ ++static CPUReadMemoryFunc *omap_venc1_readfn[] = { ++ omap_badwidth_read32, ++ omap_badwidth_read32, ++ omap_venc_read, ++}; ++ ++static CPUWriteMemoryFunc *omap_venc1_writefn[] = { ++ omap_badwidth_write32, ++ omap_badwidth_write32, ++ omap_venc_write, ++}; ++ ++static uint32_t omap_im3_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct omap_dss_s *s = (struct omap_dss_s *) opaque; ++ int offset = addr - s->im3_base; ++ ++ switch (offset) { ++ case 0x0a8: /* SBIMERRLOGA */ ++ case 0x0b0: /* SBIMERRLOG */ ++ case 0x190: /* SBIMSTATE */ ++ case 0x198: /* SBTMSTATE_L */ ++ case 0x19c: /* SBTMSTATE_H */ ++ case 0x1a8: /* SBIMCONFIG_L */ ++ case 0x1ac: /* SBIMCONFIG_H */ ++ case 0x1f8: /* SBID_L */ ++ case 0x1fc: /* SBID_H */ ++ return 0; ++ ++ default: ++ break; ++ } ++ OMAP_BAD_REG(addr); ++ return 0; ++} ++ ++static void omap_im3_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct omap_dss_s *s = (struct omap_dss_s *) opaque; ++ int offset = addr - s->im3_base; ++ ++ switch (offset) { ++ case 0x0b0: /* SBIMERRLOG */ ++ case 0x190: /* SBIMSTATE */ ++ case 0x198: /* SBTMSTATE_L */ ++ case 0x19c: /* SBTMSTATE_H */ ++ case 0x1a8: /* SBIMCONFIG_L */ ++ case 0x1ac: /* SBIMCONFIG_H */ ++ break; ++ ++ default: ++ OMAP_BAD_REG(addr); ++ } ++} ++ ++static CPUReadMemoryFunc *omap_im3_readfn[] = { ++ omap_badwidth_read32, ++ omap_badwidth_read32, ++ omap_im3_read, ++}; ++ ++static CPUWriteMemoryFunc *omap_im3_writefn[] = { ++ omap_badwidth_write32, ++ omap_badwidth_write32, ++ omap_im3_write, ++}; ++ ++struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta, ++ target_phys_addr_t l3_base, DisplayState *ds, ++ qemu_irq irq, qemu_irq drq, ++ omap_clk fck1, omap_clk fck2, omap_clk ck54m, ++ omap_clk ick1, omap_clk ick2) ++{ ++ int iomemtype[5]; ++ struct omap_dss_s *s = (struct omap_dss_s *) ++ qemu_mallocz(sizeof(struct omap_dss_s)); ++ ++ s->irq = irq; ++ s->drq = drq; ++ s->state = ds; ++ omap_dss_reset(s); ++ ++ iomemtype[0] = cpu_register_io_memory(0, omap_diss1_readfn, ++ omap_diss1_writefn, s); ++ iomemtype[1] = cpu_register_io_memory(0, omap_disc1_readfn, ++ omap_disc1_writefn, s); ++ iomemtype[2] = cpu_register_io_memory(0, omap_rfbi1_readfn, ++ omap_rfbi1_writefn, s); ++ iomemtype[3] = cpu_register_io_memory(0, omap_venc1_readfn, ++ omap_venc1_writefn, s); ++ iomemtype[4] = cpu_register_io_memory(0, omap_im3_readfn, ++ omap_im3_writefn, s); ++ s->diss_base = omap_l4_attach(ta, 0, iomemtype[0]); ++ s->disc_base = omap_l4_attach(ta, 1, iomemtype[1]); ++ s->rfbi_base = omap_l4_attach(ta, 2, iomemtype[2]); ++ s->venc_base = omap_l4_attach(ta, 3, iomemtype[3]); ++ s->im3_base = l3_base; ++ cpu_register_physical_memory(s->im3_base, 0x1000, iomemtype[4]); ++ ++#if 0 ++ if (ds) ++ graphic_console_init(ds, omap_update_display, ++ omap_invalidate_display, omap_screen_dump, s); ++#endif ++ ++ return s; ++} ++ ++void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip) ++{ ++ if (cs < 0 || cs > 1) ++ cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs); ++ s->rfbi.chip[cs] = chip; ++} +diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c +index de63309..9915676 100644 +--- a/hw/omap_i2c.c ++++ b/hw/omap_i2c.c +@@ -150,6 +150,8 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s) + } + 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 */ +@@ -161,6 +163,8 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s) + } + if (s->rxlen) + s->stat |= 1 << 3; /* RRDY */ ++ else ++ s->stat &= ~(1 << 3); /* RRDY */ + } + if (!s->count_cur) { + if ((s->control >> 1) & 1) { /* STP */ +@@ -321,7 +325,8 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr, + return; + } + +- s->stat &= ~(value & 0x3f); ++ /* RRDY and XRDY are reset by hardware. (in all versions???) */ ++ s->stat &= ~(value & 0x27); + omap_i2c_interrupts_update(s); + break; + +@@ -376,11 +381,13 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr, + break; + } + if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */ +- printf("%s: I^2C slave mode not supported\n", __FUNCTION__); ++ fprintf(stderr, "%s: I^2C slave mode not supported\n", ++ __FUNCTION__); + break; + } + if ((value & (1 << 15)) && value & (1 << 8)) { /* XA */ +- printf("%s: 10-bit addressing mode not supported\n", __FUNCTION__); ++ fprintf(stderr, "%s: 10-bit addressing mode not supported\n", ++ __FUNCTION__); + break; + } + if ((value & (1 << 15)) && value & (1 << 0)) { /* STT */ +@@ -427,7 +434,7 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr, + omap_i2c_interrupts_update(s); + } + if (value & (1 << 15)) /* ST_EN */ +- printf("%s: System Test not supported\n", __FUNCTION__); ++ fprintf(stderr, "%s: System Test not supported\n", __FUNCTION__); + break; + + default: +diff --git a/hw/omap_mmc.c b/hw/omap_mmc.c +index 6fbbb84..e46289a 100644 +--- a/hw/omap_mmc.c ++++ b/hw/omap_mmc.c +@@ -26,19 +26,24 @@ struct omap_mmc_s { + target_phys_addr_t base; + qemu_irq irq; + qemu_irq *dma; ++ qemu_irq coverswitch; + omap_clk clk; + SDState *card; + uint16_t last_cmd; + uint16_t sdio; + uint16_t rsp[8]; + uint32_t arg; ++ int lines; + int dw; + int mode; + int enable; ++ int be; ++ int rev; + uint16_t status; + uint16_t mask; + uint8_t cto; + uint16_t dto; ++ int clkdiv; + uint16_t fifo[32]; + int fifo_start; + int fifo_len; +@@ -53,6 +58,11 @@ struct omap_mmc_s { + + int ddir; + int transfer; ++ ++ int cdet_wakeup; ++ int cdet_enable; ++ int cdet_state; ++ qemu_irq cdet; + }; + + static void omap_mmc_interrupts_update(struct omap_mmc_s *s) +@@ -107,6 +117,11 @@ static void omap_mmc_command(struct omap_mmc_s *host, int cmd, int dir, + struct sd_request_s request; + uint8_t response[16]; + ++ if (init && cmd == 0) { ++ host->status |= 0x0001; ++ return; ++ } ++ + if (resptype == sd_r1 && busy) + resptype = sd_r1b; + +@@ -265,6 +280,34 @@ static void omap_mmc_update(void *opaque) + omap_mmc_interrupts_update(s); + } + ++void omap_mmc_reset(struct omap_mmc_s *host) ++{ ++ host->last_cmd = 0; ++ memset(host->rsp, 0, sizeof(host->rsp)); ++ host->arg = 0; ++ host->dw = 0; ++ host->mode = 0; ++ host->enable = 0; ++ host->status = 0; ++ host->mask = 0; ++ host->cto = 0; ++ host->dto = 0; ++ host->fifo_len = 0; ++ host->blen = 0; ++ host->blen_counter = 0; ++ host->nblk = 0; ++ host->nblk_counter = 0; ++ host->tx_dma = 0; ++ host->rx_dma = 0; ++ host->ae_level = 0x00; ++ host->af_level = 0x1f; ++ host->transfer = 0; ++ host->cdet_wakeup = 0; ++ host->cdet_enable = 0; ++ qemu_set_irq(host->coverswitch, host->cdet_state); ++ host->clkdiv = 0; ++} ++ + static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset) + { + uint16_t i; +@@ -282,7 +325,8 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset) + return s->arg >> 16; + + case 0x0c: /* MMC_CON */ +- return (s->dw << 15) | (s->mode << 12) | (s->enable << 11); ++ return (s->dw << 15) | (s->mode << 12) | (s->enable << 11) | ++ (s->be << 10) | s->clkdiv; + + case 0x10: /* MMC_STAT */ + return s->status; +@@ -324,12 +368,12 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset) + case 0x30: /* MMC_SPI */ + return 0x0000; + case 0x34: /* MMC_SDIO */ +- return s->sdio; ++ return (s->cdet_wakeup << 2) | (s->cdet_enable) | s->sdio; + case 0x38: /* MMC_SYST */ + return 0x0000; + + case 0x3c: /* MMC_REV */ +- return 0x0001; ++ return s->rev; + + case 0x40: /* MMC_RSP0 */ + case 0x44: /* MMC_RSP1 */ +@@ -340,6 +384,13 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset) + case 0x58: /* MMC_RSP6 */ + case 0x5c: /* MMC_RSP7 */ + return s->rsp[(offset - 0x40) >> 2]; ++ ++ /* OMAP2-specific */ ++ case 0x60: /* MMC_IOSR */ ++ case 0x64: /* MMC_SYSC */ ++ return 0; ++ case 0x68: /* MMC_SYSS */ ++ return 1; /* RSTD */ + } + + OMAP_BAD_REG(offset); +@@ -383,10 +434,16 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset, + s->dw = (value >> 15) & 1; + s->mode = (value >> 12) & 3; + s->enable = (value >> 11) & 1; ++ s->be = (value >> 10) & 1; ++ s->clkdiv = (value >> 0) & (s->rev >= 2 ? 0x3ff : 0xff); + if (s->mode != 0) + printf("SD mode %i unimplemented!\n", s->mode); +- if (s->dw != 0) ++ if (s->be != 0) ++ printf("SD FIFO byte sex unimplemented!\n"); ++ if (s->dw != 0 && s->lines < 4) + printf("4-bit SD bus enabled\n"); ++ if (!s->enable) ++ omap_mmc_reset(s); + break; + + case 0x10: /* MMC_STAT */ +@@ -395,13 +452,13 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset, + break; + + case 0x14: /* MMC_IE */ +- s->mask = value; ++ s->mask = value & 0x7fff; + omap_mmc_interrupts_update(s); + break; + + case 0x18: /* MMC_CTO */ + s->cto = value & 0xff; +- if (s->cto > 0xfd) ++ if (s->cto > 0xfd && s->rev <= 1) + printf("MMC: CTO of 0xff and 0xfe cannot be used!\n"); + break; + +@@ -446,10 +503,12 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset, + break; + + /* SPI, SDIO and TEST modes unimplemented */ +- case 0x30: /* MMC_SPI */ ++ case 0x30: /* MMC_SPI (OMAP1 only) */ + break; + case 0x34: /* MMC_SDIO */ +- s->sdio = value & 0x2020; ++ s->sdio = value & (s->rev >= 2 ? 0xfbf3 : 0x2020); ++ s->cdet_wakeup = (value >> 9) & 1; ++ s->cdet_enable = (value >> 2) & 1; + break; + case 0x38: /* MMC_SYST */ + break; +@@ -466,6 +525,19 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset, + OMAP_RO_REG(offset); + break; + ++ /* OMAP2-specific */ ++ case 0x60: /* MMC_IOSR */ ++ if (value & 0xf) ++ printf("MMC: SDIO bits used!\n"); ++ break; ++ case 0x64: /* MMC_SYSC */ ++ if (value & (1 << 2)) /* SRTS */ ++ omap_mmc_reset(s); ++ break; ++ case 0x68: /* MMC_SYSS */ ++ OMAP_RO_REG(offset); ++ break; ++ + default: + OMAP_BAD_REG(offset); + } +@@ -483,28 +555,21 @@ static CPUWriteMemoryFunc *omap_mmc_writefn[] = { + omap_badwidth_write16, + }; + +-void omap_mmc_reset(struct omap_mmc_s *host) ++static void omap_mmc_cover_cb(void *opaque, int line, int level) + { +- host->last_cmd = 0; +- memset(host->rsp, 0, sizeof(host->rsp)); +- host->arg = 0; +- host->dw = 0; +- host->mode = 0; +- host->enable = 0; +- host->status = 0; +- host->mask = 0; +- host->cto = 0; +- host->dto = 0; +- host->fifo_len = 0; +- host->blen = 0; +- host->blen_counter = 0; +- host->nblk = 0; +- host->nblk_counter = 0; +- host->tx_dma = 0; +- host->rx_dma = 0; +- host->ae_level = 0x00; +- host->af_level = 0x1f; +- host->transfer = 0; ++ struct omap_mmc_s *host = (struct omap_mmc_s *) opaque; ++ ++ if (!host->cdet_state && level) { ++ host->status |= 0x0002; ++ omap_mmc_interrupts_update(host); ++ if (host->cdet_wakeup) ++ /* TODO: Assert wake-up */; ++ } ++ ++ if (host->cdet_state != level) { ++ qemu_set_irq(host->coverswitch, level); ++ host->cdet_state = level; ++ } + } + + struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base, +@@ -519,6 +584,10 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base, + s->base = base; + s->dma = dma; + s->clk = clk; ++ s->lines = 1; /* TODO: needs to be settable per-board */ ++ s->rev = 1; ++ ++ omap_mmc_reset(s); + + iomemtype = cpu_register_io_memory(0, omap_mmc_readfn, + omap_mmc_writefn, s); +@@ -530,7 +599,46 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base, + return s; + } + ++struct omap_mmc_s *omap2_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 omap_mmc_s *s = (struct omap_mmc_s *) ++ qemu_mallocz(sizeof(struct omap_mmc_s)); ++ ++ s->irq = irq; ++ s->dma = dma; ++ s->clk = fclk; ++ s->lines = 4; ++ s->rev = 2; ++ ++ omap_mmc_reset(s); ++ ++ iomemtype = cpu_register_io_memory(0, omap_mmc_readfn, ++ omap_mmc_writefn, s); ++ s->base = omap_l4_attach(ta, 0, iomemtype); ++ ++ /* Instantiate the storage */ ++ s->card = sd_init(bd, 0); ++ ++ s->cdet = qemu_allocate_irqs(omap_mmc_cover_cb, s, 1)[0]; ++ sd_set_cb(s->card, 0, s->cdet); ++ ++ return s; ++} ++ + void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover) + { +- sd_set_cb(s->card, ro, cover); ++ if (s->cdet) { ++ sd_set_cb(s->card, ro, s->cdet); ++ s->coverswitch = cover; ++ qemu_set_irq(cover, s->cdet_state); ++ } else ++ sd_set_cb(s->card, ro, cover); ++} ++ ++void omap_mmc_enable(struct omap_mmc_s *s, int enable) ++{ ++ sd_enable(s->card, enable); + } +diff --git a/hw/onenand.c b/hw/onenand.c +new file mode 100644 +index 0000000..549d392 +--- /dev/null ++++ b/hw/onenand.c +@@ -0,0 +1,642 @@ ++/* ++ * OneNAND flash memories emulation. ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Written by Andrzej Zaborowski ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ */ ++ ++#include "qemu-common.h" ++#include "flash.h" ++#include "irq.h" ++#include "sysemu.h" ++#include "block.h" ++ ++/* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */ ++#define PAGE_SHIFT 11 ++ ++/* Fixed */ ++#define BLOCK_SHIFT (PAGE_SHIFT + 6) ++ ++struct onenand_s { ++ uint32_t id; ++ int shift; ++ target_phys_addr_t base; ++ qemu_irq intr; ++ qemu_irq rdy; ++ BlockDriverState *bdrv; ++ BlockDriverState *bdrv_cur; ++ uint8_t *image; ++ uint8_t *otp; ++ uint8_t *current; ++ ram_addr_t ram; ++ uint8_t *boot[2]; ++ uint8_t *data[2][2]; ++ int iomemtype; ++ int cycle; ++ int otpmode; ++ ++ uint16_t addr[8]; ++ uint16_t unladdr[8]; ++ int bufaddr; ++ int count; ++ uint16_t command; ++ uint16_t config[2]; ++ uint16_t status; ++ uint16_t intstatus; ++ uint16_t wpstatus; ++ ++ struct ecc_state_s ecc; ++ ++ int density_mask; ++ int secs; ++ int secs_cur; ++ int blocks; ++ uint8_t *blockwp; ++}; ++ ++enum { ++ ONEN_BUF_BLOCK = 0, ++ ONEN_BUF_BLOCK2 = 1, ++ ONEN_BUF_DEST_BLOCK = 2, ++ ONEN_BUF_DEST_PAGE = 3, ++ ONEN_BUF_PAGE = 7, ++}; ++ ++enum { ++ ONEN_ERR_CMD = 1 << 10, ++ ONEN_ERR_ERASE = 1 << 11, ++ ONEN_ERR_PROG = 1 << 12, ++ ONEN_ERR_LOAD = 1 << 13, ++}; ++ ++enum { ++ ONEN_INT_RESET = 1 << 4, ++ ONEN_INT_ERASE = 1 << 5, ++ ONEN_INT_PROG = 1 << 6, ++ ONEN_INT_LOAD = 1 << 7, ++ ONEN_INT = 1 << 15, ++}; ++ ++enum { ++ ONEN_LOCK_LOCKTIGHTEN = 1 << 0, ++ ONEN_LOCK_LOCKED = 1 << 1, ++ ONEN_LOCK_UNLOCKED = 1 << 2, ++}; ++ ++void onenand_base_update(void *opaque, target_phys_addr_t new) ++{ ++ struct onenand_s *s = (struct onenand_s *) opaque; ++ ++ s->base = new; ++ ++ /* XXX: We should use IO_MEM_ROMD but we broke it earlier... ++ * Both 0x0000 ... 0x01ff and 0x8000 ... 0x800f can be used to ++ * write boot commands. Also take note of the BWPS bit. */ ++ cpu_register_physical_memory(s->base + (0x0000 << s->shift), ++ 0x0200 << s->shift, s->iomemtype); ++ cpu_register_physical_memory(s->base + (0x0200 << s->shift), ++ 0xbe00 << s->shift, ++ (s->ram +(0x0200 << s->shift)) | IO_MEM_RAM); ++ if (s->iomemtype) ++ cpu_register_physical_memory(s->base + (0xc000 << s->shift), ++ 0x4000 << s->shift, s->iomemtype); ++} ++ ++void onenand_base_unmap(void *opaque) ++{ ++ struct onenand_s *s = (struct onenand_s *) opaque; ++ ++ cpu_register_physical_memory(s->base, ++ 0x10000 << s->shift, IO_MEM_UNASSIGNED); ++} ++ ++static void onenand_intr_update(struct onenand_s *s) ++{ ++ qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1); ++} ++ ++/* Hot reset (Reset OneNAND command) or warm reset (RP pin low) */ ++static void onenand_reset(struct onenand_s *s, int cold) ++{ ++ memset(&s->addr, 0, sizeof(s->addr)); ++ s->command = 0; ++ s->count = 1; ++ s->bufaddr = 0; ++ s->config[0] = 0x40c0; ++ s->config[1] = 0x0000; ++ onenand_intr_update(s); ++ qemu_irq_raise(s->rdy); ++ s->status = 0x0000; ++ s->intstatus = cold ? 0x8080 : 0x8010; ++ s->unladdr[0] = 0; ++ s->unladdr[1] = 0; ++ s->wpstatus = 0x0002; ++ s->cycle = 0; ++ s->otpmode = 0; ++ s->bdrv_cur = s->bdrv; ++ s->current = s->image; ++ s->secs_cur = s->secs; ++ ++ if (cold) { ++ /* Lock the whole flash */ ++ memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks); ++ ++ if (s->bdrv && bdrv_read(s->bdrv, 0, s->boot[0], 8) < 0) ++ cpu_abort(cpu_single_env, "%s: Loading the BootRAM failed.\n", ++ __FUNCTION__); ++ } ++} ++ ++static inline int onenand_load_main(struct onenand_s *s, int sec, int secn, ++ void *dest) ++{ ++ if (s->bdrv_cur) ++ return bdrv_read(s->bdrv_cur, sec, dest, secn) < 0; ++ else if (sec + secn > s->secs_cur) ++ return 1; ++ ++ memcpy(dest, s->current + (sec << 9), secn << 9); ++ ++ return 0; ++} ++ ++static inline int onenand_prog_main(struct onenand_s *s, int sec, int secn, ++ void *src) ++{ ++ if (s->bdrv_cur) ++ return bdrv_write(s->bdrv_cur, sec, src, secn) < 0; ++ else if (sec + secn > s->secs_cur) ++ return 1; ++ ++ memcpy(s->current + (sec << 9), src, secn << 9); ++ ++ return 0; ++} ++ ++static inline int onenand_load_spare(struct onenand_s *s, int sec, int secn, ++ void *dest) ++{ ++ uint8_t buf[512]; ++ ++ if (s->bdrv_cur) { ++ if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0) ++ return 1; ++ memcpy(dest, buf + ((sec & 31) << 4), secn << 4); ++ } else if (sec + secn > s->secs_cur) ++ return 1; ++ else ++ memcpy(dest, s->current + (s->secs_cur << 9) + (sec << 4), secn << 4); ++ ++ return 0; ++} ++ ++static inline int onenand_prog_spare(struct onenand_s *s, int sec, int secn, ++ void *src) ++{ ++ uint8_t buf[512]; ++ ++ if (s->bdrv_cur) { ++ if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0) ++ return 1; ++ memcpy(buf + ((sec & 31) << 4), src, secn << 4); ++ return bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0; ++ } else if (sec + secn > s->secs_cur) ++ return 1; ++ ++ memcpy(s->current + (s->secs_cur << 9) + (sec << 4), src, secn << 4); ++ ++ return 0; ++} ++ ++static inline int onenand_erase(struct onenand_s *s, int sec, int num) ++{ ++ /* TODO: optimise */ ++ uint8_t buf[512]; ++ ++ memset(buf, 0xff, sizeof(buf)); ++ for (; num > 0; num --, sec ++) { ++ if (onenand_prog_main(s, sec, 1, buf)) ++ return 1; ++ if (onenand_prog_spare(s, sec, 1, buf)) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void onenand_command(struct onenand_s *s, int cmd) ++{ ++ int b; ++ int sec; ++ void *buf; ++#define SETADDR(block, page) \ ++ sec = (s->addr[page] & 3) + \ ++ ((((s->addr[page] >> 2) & 0x3f) + \ ++ (((s->addr[block] & 0xfff) | \ ++ (s->addr[block] >> 15 ? \ ++ s->density_mask : 0)) << 6)) << (PAGE_SHIFT - 9)); ++#define SETBUF_M() \ ++ buf = (s->bufaddr & 8) ? \ ++ s->data[(s->bufaddr >> 2) & 1][0] : s->boot[0]; \ ++ buf += (s->bufaddr & 3) << 9; ++#define SETBUF_S() \ ++ buf = (s->bufaddr & 8) ? \ ++ s->data[(s->bufaddr >> 2) & 1][1] : s->boot[1]; \ ++ buf += (s->bufaddr & 3) << 4; ++ ++ switch (cmd) { ++ case 0x00: /* Load single/multiple sector data unit into buffer */ ++ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE) ++ ++ SETBUF_M() ++ if (onenand_load_main(s, sec, s->count, buf)) ++ s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD; ++ ++#if 0 ++ SETBUF_S() ++ if (onenand_load_spare(s, sec, s->count, buf)) ++ s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD; ++#endif ++ ++ /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages) ++ * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages) ++ * then we need two split the read/write into two chunks. ++ */ ++ s->intstatus |= ONEN_INT | ONEN_INT_LOAD; ++ break; ++ case 0x13: /* Load single/multiple spare sector into buffer */ ++ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE) ++ ++ SETBUF_S() ++ if (onenand_load_spare(s, sec, s->count, buf)) ++ s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD; ++ ++ /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages) ++ * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages) ++ * then we need two split the read/write into two chunks. ++ */ ++ s->intstatus |= ONEN_INT | ONEN_INT_LOAD; ++ break; ++ case 0x80: /* Program single/multiple sector data unit from buffer */ ++ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE) ++ ++ SETBUF_M() ++ if (onenand_prog_main(s, sec, s->count, buf)) ++ s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG; ++ ++#if 0 ++ SETBUF_S() ++ if (onenand_prog_spare(s, sec, s->count, buf)) ++ s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG; ++#endif ++ ++ /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages) ++ * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages) ++ * then we need two split the read/write into two chunks. ++ */ ++ s->intstatus |= ONEN_INT | ONEN_INT_PROG; ++ break; ++ case 0x1a: /* Program single/multiple spare area sector from buffer */ ++ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE) ++ ++ SETBUF_S() ++ if (onenand_prog_spare(s, sec, s->count, buf)) ++ s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG; ++ ++ /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages) ++ * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages) ++ * then we need two split the read/write into two chunks. ++ */ ++ s->intstatus |= ONEN_INT | ONEN_INT_PROG; ++ break; ++ case 0x1b: /* Copy-back program */ ++ SETBUF_S() ++ ++ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE) ++ if (onenand_load_main(s, sec, s->count, buf)) ++ s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG; ++ ++ SETADDR(ONEN_BUF_DEST_BLOCK, ONEN_BUF_DEST_PAGE) ++ if (onenand_prog_main(s, sec, s->count, buf)) ++ s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG; ++ ++ /* TODO: spare areas */ ++ ++ s->intstatus |= ONEN_INT | ONEN_INT_PROG; ++ break; ++ ++ case 0x23: /* Unlock NAND array block(s) */ ++ s->intstatus |= ONEN_INT; ++ ++ /* XXX the previous (?) area should be locked automatically */ ++ for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) { ++ if (b >= s->blocks) { ++ s->status |= ONEN_ERR_CMD; ++ break; ++ } ++ if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN) ++ break; ++ ++ s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED; ++ } ++ break; ++ case 0x2a: /* Lock NAND array block(s) */ ++ s->intstatus |= ONEN_INT; ++ ++ for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) { ++ if (b >= s->blocks) { ++ s->status |= ONEN_ERR_CMD; ++ break; ++ } ++ if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN) ++ break; ++ ++ s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKED; ++ } ++ break; ++ case 0x2c: /* Lock-tight NAND array block(s) */ ++ s->intstatus |= ONEN_INT; ++ ++ for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) { ++ if (b >= s->blocks) { ++ s->status |= ONEN_ERR_CMD; ++ break; ++ } ++ if (s->blockwp[b] == ONEN_LOCK_UNLOCKED) ++ continue; ++ ++ s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKTIGHTEN; ++ } ++ break; ++ ++ case 0x71: /* Erase-Verify-Read */ ++ s->intstatus |= ONEN_INT; ++ break; ++ case 0x95: /* Multi-block erase */ ++ qemu_irq_pulse(s->intr); ++ /* Fall through. */ ++ case 0x94: /* Block erase */ ++ sec = ((s->addr[ONEN_BUF_BLOCK] & 0xfff) | ++ (s->addr[ONEN_BUF_BLOCK] >> 15 ? s->density_mask : 0)) ++ << (BLOCK_SHIFT - 9); ++ if (onenand_erase(s, sec, 1 << (BLOCK_SHIFT - 9))) ++ s->status |= ONEN_ERR_CMD | ONEN_ERR_ERASE; ++ ++ s->intstatus |= ONEN_INT | ONEN_INT_ERASE; ++ break; ++ case 0xb0: /* Erase suspend */ ++ break; ++ case 0x30: /* Erase resume */ ++ s->intstatus |= ONEN_INT | ONEN_INT_ERASE; ++ break; ++ ++ case 0xf0: /* Reset NAND Flash core */ ++ onenand_reset(s, 0); ++ break; ++ case 0xf3: /* Reset OneNAND */ ++ onenand_reset(s, 0); ++ break; ++ ++ case 0x65: /* OTP Access */ ++ s->intstatus |= ONEN_INT; ++ s->bdrv_cur = 0; ++ s->current = s->otp; ++ s->secs_cur = 1 << (BLOCK_SHIFT - 9); ++ s->addr[ONEN_BUF_BLOCK] = 0; ++ s->otpmode = 1; ++ break; ++ ++ default: ++ s->status |= ONEN_ERR_CMD; ++ s->intstatus |= ONEN_INT; ++ fprintf(stderr, "%s: unknown OneNAND command %x\n", ++ __FUNCTION__, cmd); ++ } ++ ++ onenand_intr_update(s); ++} ++ ++static uint32_t onenand_read(void *opaque, target_phys_addr_t addr) ++{ ++ struct onenand_s *s = (struct onenand_s *) opaque; ++ int offset = (addr - s->base) >> s->shift; ++ ++ switch (offset) { ++ case 0x0000 ... 0xc000: ++ return lduw_le_p(s->boot[0] + (addr - s->base)); ++ ++ case 0xf000: /* Manufacturer ID */ ++ return (s->id >> 16) & 0xff; ++ case 0xf001: /* Device ID */ ++ return (s->id >> 8) & 0xff; ++ /* TODO: get the following values from a real chip! */ ++ case 0xf002: /* Version ID */ ++ return (s->id >> 0) & 0xff; ++ case 0xf003: /* Data Buffer size */ ++ return 1 << PAGE_SHIFT; ++ case 0xf004: /* Boot Buffer size */ ++ return 0x200; ++ case 0xf005: /* Amount of buffers */ ++ return 1 | (2 << 8); ++ case 0xf006: /* Technology */ ++ return 0; ++ ++ case 0xf100 ... 0xf107: /* Start addresses */ ++ return s->addr[offset - 0xf100]; ++ ++ case 0xf200: /* Start buffer */ ++ return (s->bufaddr << 8) | ((s->count - 1) & (1 << (PAGE_SHIFT - 10))); ++ ++ case 0xf220: /* Command */ ++ return s->command; ++ case 0xf221: /* System Configuration 1 */ ++ return s->config[0] & 0xffe0; ++ case 0xf222: /* System Configuration 2 */ ++ return s->config[1]; ++ ++ case 0xf240: /* Controller Status */ ++ return s->status; ++ case 0xf241: /* Interrupt */ ++ return s->intstatus; ++ case 0xf24c: /* Unlock Start Block Address */ ++ return s->unladdr[0]; ++ case 0xf24d: /* Unlock End Block Address */ ++ return s->unladdr[1]; ++ case 0xf24e: /* Write Protection Status */ ++ return s->wpstatus; ++ ++ case 0xff00: /* ECC Status */ ++ return 0x00; ++ case 0xff01: /* ECC Result of main area data */ ++ case 0xff02: /* ECC Result of spare area data */ ++ case 0xff03: /* ECC Result of main area data */ ++ case 0xff04: /* ECC Result of spare area data */ ++ cpu_abort(cpu_single_env, "%s: imeplement ECC\n", __FUNCTION__); ++ return 0x0000; ++ } ++ ++ fprintf(stderr, "%s: unknown OneNAND register %x\n", ++ __FUNCTION__, offset); ++ return 0; ++} ++ ++static void onenand_write(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ struct onenand_s *s = (struct onenand_s *) opaque; ++ int offset = (addr - s->base) >> s->shift; ++ int sec; ++ ++ switch (offset) { ++ case 0x0000 ... 0x01ff: ++ case 0x8000 ... 0x800f: ++ if (s->cycle) { ++ s->cycle = 0; ++ ++ if (value == 0x0000) { ++ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE) ++ onenand_load_main(s, sec, ++ 1 << (PAGE_SHIFT - 9), s->data[0][0]); ++ s->addr[ONEN_BUF_PAGE] += 4; ++ s->addr[ONEN_BUF_PAGE] &= 0xff; ++ } ++ break; ++ } ++ ++ switch (value) { ++ case 0x00f0: /* Reset OneNAND */ ++ onenand_reset(s, 0); ++ break; ++ ++ case 0x00e0: /* Load Data into Buffer */ ++ s->cycle = 1; ++ break; ++ ++ case 0x0090: /* Read Identification Data */ ++ memset(s->boot[0], 0, 3 << s->shift); ++ s->boot[0][0 << s->shift] = (s->id >> 16) & 0xff; ++ s->boot[0][1 << s->shift] = (s->id >> 8) & 0xff; ++ s->boot[0][2 << s->shift] = s->wpstatus & 0xff; ++ break; ++ ++ default: ++ fprintf(stderr, "%s: unknown OneNAND boot command %x\n", ++ __FUNCTION__, value); ++ } ++ break; ++ ++ case 0xf100 ... 0xf107: /* Start addresses */ ++ s->addr[offset - 0xf100] = value; ++ break; ++ ++ case 0xf200: /* Start buffer */ ++ s->bufaddr = (value >> 8) & 0xf; ++ if (PAGE_SHIFT == 11) ++ s->count = (value & 3) ?: 4; ++ else if (PAGE_SHIFT == 10) ++ s->count = (value & 1) ?: 2; ++ break; ++ ++ case 0xf220: /* Command */ ++ if (s->intstatus & (1 << 15)) ++ break; ++ s->command = value; ++ onenand_command(s, s->command); ++ break; ++ case 0xf221: /* System Configuration 1 */ ++ s->config[0] = value; ++ onenand_intr_update(s); ++ qemu_set_irq(s->rdy, (s->config[0] >> 7) & 1); ++ break; ++ case 0xf222: /* System Configuration 2 */ ++ s->config[1] = value; ++ break; ++ ++ case 0xf241: /* Interrupt */ ++ s->intstatus &= value; ++ if ((1 << 15) & ~s->intstatus) ++ s->status &= ~(ONEN_ERR_CMD | ONEN_ERR_ERASE | ++ ONEN_ERR_PROG | ONEN_ERR_LOAD); ++ onenand_intr_update(s); ++ break; ++ case 0xf24c: /* Unlock Start Block Address */ ++ s->unladdr[0] = value & (s->blocks - 1); ++ /* For some reason we have to set the end address to by default ++ * be same as start because the software forgets to write anything ++ * in there. */ ++ s->unladdr[1] = value & (s->blocks - 1); ++ break; ++ case 0xf24d: /* Unlock End Block Address */ ++ s->unladdr[1] = value & (s->blocks - 1); ++ break; ++ ++ default: ++ fprintf(stderr, "%s: unknown OneNAND register %x\n", ++ __FUNCTION__, offset); ++ } ++} ++ ++static CPUReadMemoryFunc *onenand_readfn[] = { ++ onenand_read, /* TODO */ ++ onenand_read, ++ onenand_read, ++}; ++ ++static CPUWriteMemoryFunc *onenand_writefn[] = { ++ onenand_write, /* TODO */ ++ onenand_write, ++ onenand_write, ++}; ++ ++void *onenand_init(uint32_t id, int regshift, qemu_irq irq) ++{ ++ struct onenand_s *s = (struct onenand_s *) qemu_mallocz(sizeof(*s)); ++ int bdrv_index = drive_get_index(IF_MTD, 0, 0); ++ uint32_t size = 1 << (24 + ((id >> 12) & 7)); ++ void *ram; ++ ++ s->shift = regshift; ++ s->intr = irq; ++ s->rdy = 0; ++ s->id = id; ++ s->blocks = size >> BLOCK_SHIFT; ++ s->secs = size >> 9; ++ s->blockwp = qemu_malloc(s->blocks); ++ s->density_mask = (id & (1 << 11)) ? (1 << (6 + ((id >> 12) & 7))) : 0; ++ s->iomemtype = cpu_register_io_memory(0, onenand_readfn, ++ onenand_writefn, s); ++ if (bdrv_index == -1) ++ s->image = memset(qemu_malloc(size + (size >> 5)), ++ 0xff, size + (size >> 5)); ++ else ++ s->bdrv = drives_table[bdrv_index].bdrv; ++ s->otp = memset(qemu_malloc((64 + 2) << PAGE_SHIFT), ++ 0xff, (64 + 2) << PAGE_SHIFT); ++ s->ram = qemu_ram_alloc(0xc000 << s->shift); ++ ram = phys_ram_base + s->ram; ++ s->boot[0] = ram + (0x0000 << s->shift); ++ s->boot[1] = ram + (0x8000 << s->shift); ++ s->data[0][0] = ram + ((0x0200 + (0 << (PAGE_SHIFT - 1))) << s->shift); ++ s->data[0][1] = ram + ((0x8010 + (0 << (PAGE_SHIFT - 6))) << s->shift); ++ s->data[1][0] = ram + ((0x0200 + (1 << (PAGE_SHIFT - 1))) << s->shift); ++ s->data[1][1] = ram + ((0x8010 + (1 << (PAGE_SHIFT - 6))) << s->shift); ++ ++ onenand_reset(s, 1); ++ ++ return s; ++} +diff --git a/hw/palm.c b/hw/palm.c +index 9400ea7..8b767e2 100644 +--- a/hw/palm.c ++++ b/hw/palm.c +@@ -25,6 +25,7 @@ + #include "omap.h" + #include "boards.h" + #include "arm-misc.h" ++#include "devices.h" + + static uint32_t static_readb(void *opaque, target_phys_addr_t offset) + { +@@ -32,12 +33,14 @@ static uint32_t static_readb(void *opaque, target_phys_addr_t offset) + return *val >> ((offset & 3) << 3); + } + +-static uint32_t static_readh(void *opaque, target_phys_addr_t offset) { ++static uint32_t static_readh(void *opaque, target_phys_addr_t offset) ++{ + uint32_t *val = (uint32_t *) opaque; + return *val >> ((offset & 1) << 3); + } + +-static uint32_t static_readw(void *opaque, target_phys_addr_t offset) { ++static uint32_t static_readw(void *opaque, target_phys_addr_t offset) ++{ + uint32_t *val = (uint32_t *) opaque; + return *val >> ((offset & 0) << 3); + } +@@ -183,6 +186,12 @@ static void palmte_gpio_setup(struct omap_mpu_state_s *cpu) + qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[11]); + } + ++static struct arm_boot_info palmte_binfo = { ++ .loader_start = OMAP_EMIFF_BASE, ++ .ram_size = 0x02000000, ++ .board_id = 0x331, ++}; ++ + static void palmte_init(int ram_size, int vga_ram_size, + const char *boot_device, DisplayState *ds, + const char *kernel_filename, const char *kernel_cmdline, +@@ -190,7 +199,7 @@ static void palmte_init(int ram_size, int vga_ram_size, + { + struct omap_mpu_state_s *cpu; + int flash_size = 0x00800000; +- int sdram_size = 0x02000000; ++ int sdram_size = palmte_binfo.ram_size; + int io; + static uint32_t cs0val = 0xffffffff; + static uint32_t cs1val = 0x0000e1a0; +@@ -250,10 +259,12 @@ static void palmte_init(int ram_size, int vga_ram_size, + /* Load the kernel. */ + if (kernel_filename) { + /* Start at bootloader. */ +- cpu->env->regs[15] = OMAP_EMIFF_BASE; ++ cpu->env->regs[15] = palmte_binfo.loader_start; + +- arm_load_kernel(cpu->env, sdram_size, kernel_filename, kernel_cmdline, +- initrd_filename, 0x331, OMAP_EMIFF_BASE); ++ palmte_binfo.kernel_filename = kernel_filename; ++ palmte_binfo.kernel_cmdline = kernel_cmdline; ++ palmte_binfo.initrd_filename = initrd_filename; ++ arm_load_kernel(cpu->env, &palmte_binfo); + } + + dpy_resize(ds, 320, 320); +diff --git a/hw/realview.c b/hw/realview.c +index 29579d8..acf3b9e 100644 +--- a/hw/realview.c ++++ b/hw/realview.c +@@ -18,6 +18,11 @@ + + /* Board init. */ + ++static struct arm_boot_info realview_binfo = { ++ .loader_start = 0x0, ++ .board_id = 0x33b, ++}; ++ + static void realview_init(int ram_size, int vga_ram_size, + const char *boot_device, DisplayState *ds, + const char *kernel_filename, const char *kernel_cmdline, +@@ -177,8 +182,12 @@ static void realview_init(int ram_size, int vga_ram_size, + /* 0x68000000 PCI mem 1. */ + /* 0x6c000000 PCI mem 2. */ + +- arm_load_kernel(first_cpu, ram_size, kernel_filename, kernel_cmdline, +- initrd_filename, 0x33b, 0x0); ++ realview_binfo.ram_size = ram_size; ++ realview_binfo.kernel_filename = kernel_filename; ++ realview_binfo.kernel_cmdline = kernel_cmdline; ++ realview_binfo.initrd_filename = initrd_filename; ++ realview_binfo.nb_cpus = ncpu; ++ arm_load_kernel(first_cpu, &realview_binfo); + + /* ??? Hack to map an additional page of ram for the secondary CPU + startup code. I guess this works on real hardware because the +diff --git a/hw/sd.c b/hw/sd.c +index 1f71d85..de7dd89 100644 +--- a/hw/sd.c ++++ b/hw/sd.c +@@ -37,7 +37,7 @@ + + #ifdef DEBUG_SD + #define DPRINTF(fmt, args...) \ +-do { printf("SD: " fmt , ##args); } while (0) ++do { fprintf(stderr, "SD: " fmt , ##args); } while (0) + #else + #define DPRINTF(fmt, args...) do {} while(0) + #endif +@@ -99,6 +99,8 @@ struct SDState { + qemu_irq inserted_cb; + BlockDriverState *bdrv; + uint8_t *buf; ++ ++ int enable; + }; + + static void sd_set_status(SDState *sd) +@@ -530,7 +532,7 @@ static void sd_lock_command(SDState *sd) + sd->card_status &= ~CARD_IS_LOCKED; + sd->pwd_len = 0; + /* Erasing the entire card here! */ +- printf("SD: Card force-erased by CMD42\n"); ++ fprintf(stderr, "SD: Card force-erased by CMD42\n"); + return; + } + +@@ -1076,7 +1078,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, + return sd_r1; + + case 56: /* CMD56: GEN_CMD */ +- printf("SD: GEN_CMD 0x%08x\n", req.arg); ++ fprintf(stderr, "SD: GEN_CMD 0x%08x\n", req.arg); + + switch (sd->state) { + case sd_transfer_state: +@@ -1096,18 +1098,18 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, + bad_cmd: + sd->card_status |= ILLEGAL_COMMAND; + +- printf("SD: Unknown CMD%i\n", req.cmd); ++ fprintf(stderr, "SD: Unknown CMD%i\n", req.cmd); + return sd_r0; + + unimplemented_cmd: + /* Commands that are recognised but not yet implemented in SPI mode. */ + sd->card_status |= ILLEGAL_COMMAND; +- printf ("SD: CMD%i not implemented in SPI mode\n", req.cmd); ++ fprintf(stderr, "SD: CMD%i not implemented in SPI mode\n", req.cmd); + return sd_r0; + } + + sd->card_status |= ILLEGAL_COMMAND; +- printf("SD: CMD%i in a wrong state\n", req.cmd); ++ fprintf(stderr, "SD: CMD%i in a wrong state\n", req.cmd); + return sd_r0; + } + +@@ -1217,7 +1219,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd, + return sd_normal_command(sd, req); + } + +- printf("SD: ACMD%i in a wrong state\n", req.cmd); ++ fprintf(stderr, "SD: ACMD%i in a wrong state\n", req.cmd); + return sd_r0; + } + +@@ -1227,7 +1229,7 @@ int sd_do_command(SDState *sd, struct sd_request_s *req, + sd_rsp_type_t rtype; + int rsplen; + +- if (!bdrv_is_inserted(sd->bdrv)) { ++ if (!bdrv_is_inserted(sd->bdrv) || !sd->enable) { + return 0; + } + +@@ -1247,7 +1249,7 @@ int sd_do_command(SDState *sd, struct sd_request_s *req, + sd_cmd_class[req->cmd] == 7 || + req->cmd == 16 || req->cmd == 55))) { + sd->card_status |= ILLEGAL_COMMAND; +- printf("SD: Card is locked\n"); ++ fprintf(stderr, "SD: Card is locked\n"); + return 0; + } + +@@ -1321,7 +1323,7 @@ static void sd_blk_read(SDState *sd, uint32_t addr, uint32_t len) + uint32_t end = addr + len; + + if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) == -1) { +- printf("sd_blk_read: read error on host side\n"); ++ fprintf(stderr, "sd_blk_read: read error on host side\n"); + return; + } + +@@ -1329,7 +1331,7 @@ static void sd_blk_read(SDState *sd, uint32_t addr, uint32_t len) + memcpy(sd->data, sd->buf + (addr & 511), 512 - (addr & 511)); + + if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) == -1) { +- printf("sd_blk_read: read error on host side\n"); ++ fprintf(stderr, "sd_blk_read: read error on host side\n"); + return; + } + memcpy(sd->data + 512 - (addr & 511), sd->buf, end & 511); +@@ -1343,28 +1345,28 @@ static void sd_blk_write(SDState *sd, uint32_t addr, uint32_t len) + + if ((addr & 511) || len < 512) + if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) == -1) { +- printf("sd_blk_write: read error on host side\n"); ++ fprintf(stderr, "sd_blk_write: read error on host side\n"); + return; + } + + if (end > (addr & ~511) + 512) { + memcpy(sd->buf + (addr & 511), sd->data, 512 - (addr & 511)); + if (bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) == -1) { +- printf("sd_blk_write: write error on host side\n"); ++ fprintf(stderr, "sd_blk_write: write error on host side\n"); + return; + } + + if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) == -1) { +- printf("sd_blk_write: read error on host side\n"); ++ fprintf(stderr, "sd_blk_write: read error on host side\n"); + return; + } + memcpy(sd->buf, sd->data + 512 - (addr & 511), end & 511); + if (bdrv_write(sd->bdrv, end >> 9, sd->buf, 1) == -1) +- printf("sd_blk_write: write error on host side\n"); ++ fprintf(stderr, "sd_blk_write: write error on host side\n"); + } else { + memcpy(sd->buf + (addr & 511), sd->data, len); + if (!sd->bdrv || bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) == -1) +- printf("sd_blk_write: write error on host side\n"); ++ fprintf(stderr, "sd_blk_write: write error on host side\n"); + } + } + +@@ -1377,11 +1379,11 @@ void sd_write_data(SDState *sd, uint8_t value) + { + int i; + +- if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv)) ++ if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable) + return; + + if (sd->state != sd_receivingdata_state) { +- printf("sd_write_data: not in Receiving-Data state\n"); ++ fprintf(stderr, "sd_write_data: not in Receiving-Data state\n"); + return; + } + +@@ -1489,7 +1491,7 @@ void sd_write_data(SDState *sd, uint8_t value) + break; + + default: +- printf("sd_write_data: unknown command\n"); ++ fprintf(stderr, "sd_write_data: unknown command\n"); + break; + } + } +@@ -1499,11 +1501,11 @@ uint8_t sd_read_data(SDState *sd) + /* TODO: Append CRCs */ + uint8_t ret; + +- if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv)) ++ if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable) + return 0x00; + + if (sd->state != sd_sendingdata_state) { +- printf("sd_read_data: not in Sending-Data state\n"); ++ fprintf(stderr, "sd_read_data: not in Sending-Data state\n"); + return 0x00; + } + +@@ -1603,7 +1605,7 @@ uint8_t sd_read_data(SDState *sd) + break; + + default: +- printf("sd_read_data: unknown command\n"); ++ fprintf(stderr, "sd_read_data: unknown command\n"); + return 0x00; + } + +@@ -1614,3 +1616,8 @@ int sd_data_ready(SDState *sd) + { + return sd->state == sd_sendingdata_state; + } ++ ++void sd_enable(SDState *sd, int enable) ++{ ++ sd->enable = enable; ++} +diff --git a/hw/sd.h b/hw/sd.h +index 85f110f..cb7bc9c 100644 +--- a/hw/sd.h ++++ b/hw/sd.h +@@ -74,6 +74,7 @@ void sd_write_data(SDState *sd, uint8_t value); + uint8_t sd_read_data(SDState *sd); + void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert); + int sd_data_ready(SDState *sd); ++void sd_enable(SDState *sd, int enable); + + /* ssi-sd.c */ + int ssi_sd_xfer(void *opaque, int val); +diff --git a/hw/spitz.c b/hw/spitz.c +index 159c633..b059f9a 100644 +--- a/hw/spitz.c ++++ b/hw/spitz.c +@@ -1180,12 +1180,17 @@ static void sl_bootparam_write(uint32_t ptr) + /* Board init. */ + enum spitz_model_e { spitz, akita, borzoi, terrier }; + ++static struct arm_boot_info spitz_binfo = { ++ .loader_start = PXA2XX_SDRAM_BASE, ++ .ram_size = 0x04000000, ++}; ++ + static void spitz_common_init(int ram_size, int vga_ram_size, + DisplayState *ds, const char *kernel_filename, + const char *kernel_cmdline, const char *initrd_filename, + const char *cpu_model, enum spitz_model_e model, int arm_id) + { +- uint32_t spitz_ram = 0x04000000; ++ uint32_t spitz_ram = spitz_binfo.ram_size; + uint32_t spitz_rom = 0x00800000; + struct pxa2xx_state_s *cpu; + struct scoop_info_s *scp; +@@ -1230,10 +1235,13 @@ static void spitz_common_init(int ram_size, int vga_ram_size, + spitz_microdrive_attach(cpu); + + /* Setup initial (reset) machine state */ +- cpu->env->regs[15] = PXA2XX_SDRAM_BASE; ++ cpu->env->regs[15] = spitz_binfo.loader_start; + +- arm_load_kernel(cpu->env, spitz_ram, kernel_filename, kernel_cmdline, +- initrd_filename, arm_id, PXA2XX_SDRAM_BASE); ++ spitz_binfo.kernel_filename = kernel_filename; ++ spitz_binfo.kernel_cmdline = kernel_cmdline; ++ spitz_binfo.initrd_filename = initrd_filename; ++ spitz_binfo.board_id = arm_id; ++ arm_load_kernel(cpu->env, &spitz_binfo); + sl_bootparam_write(SL_PXA_PARAM_BASE - PXA2XX_SDRAM_BASE); + } + +diff --git a/hw/tmp105.c b/hw/tmp105.c +new file mode 100644 +index 0000000..d9a3900 +--- /dev/null ++++ b/hw/tmp105.c +@@ -0,0 +1,249 @@ ++/* ++ * Texas Instruments TMP105 temperature sensor. ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Written by Andrzej Zaborowski ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ */ ++ ++#include "hw.h" ++#include "i2c.h" ++ ++struct tmp105_s { ++ i2c_slave i2c; ++ int len; ++ uint8_t buf[2]; ++ qemu_irq pin; ++ ++ uint8_t pointer; ++ uint8_t config; ++ int16_t temperature; ++ int16_t limit[2]; ++ int faults; ++ int alarm; ++}; ++ ++static void tmp105_interrupt_update(struct tmp105_s *s) ++{ ++ qemu_set_irq(s->pin, s->alarm ^ ((~s->config >> 2) & 1)); /* POL */ ++} ++ ++static void tmp105_alarm_update(struct tmp105_s *s) ++{ ++ if ((s->config >> 0) & 1) { /* SD */ ++ if ((s->config >> 7) & 1) /* OS */ ++ s->config &= ~(1 << 7); /* OS */ ++ else ++ return; ++ } ++ ++ if ((s->config >> 1) & 1) { /* TM */ ++ if (s->temperature >= s->limit[1]) ++ s->alarm = 1; ++ else if (s->temperature < s->limit[0]) ++ s->alarm = 1; ++ } else { ++ if (s->temperature >= s->limit[1]) ++ s->alarm = 1; ++ else if (s->temperature < s->limit[0]) ++ s->alarm = 0; ++ } ++ ++ tmp105_interrupt_update(s); ++} ++ ++/* Units are 0.001 centigrades relative to 0 C. */ ++void tmp105_set(i2c_slave *i2c, int temp) ++{ ++ struct tmp105_s *s = (struct tmp105_s *) i2c; ++ ++ if (temp >= 128000 || temp < -128000) { ++ fprintf(stderr, "%s: values is out of range (%i.%03i C)\n", ++ __FUNCTION__, temp / 1000, temp % 1000); ++ exit(-1); ++ } ++ ++ s->temperature = ((int16_t) (temp * 0x800 / 128000)) << 4; ++ ++ tmp105_alarm_update(s); ++} ++ ++static const int tmp105_faultq[4] = { 1, 2, 4, 6 }; ++ ++static void tmp105_read(struct tmp105_s *s) ++{ ++ s->len = 0; ++ ++ if ((s->config >> 1) & 1) { /* TM */ ++ s->alarm = 0; ++ tmp105_interrupt_update(s); ++ } ++ ++ switch (s->pointer & 3) { ++ case 0: /* Temperature */ ++ s->buf[s->len ++] = (((uint16_t) s->temperature) >> 8); ++ s->buf[s->len ++] = (((uint16_t) s->temperature) >> 0) & ++ (0xf0 << ((~s->config >> 5) & 3)); /* R */ ++ break; ++ ++ case 1: /* Configuration */ ++ s->buf[s->len ++] = s->config; ++ break; ++ ++ case 2: /* T_LOW */ ++ s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 8; ++ s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 0; ++ break; ++ ++ case 3: /* T_HIGH */ ++ s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 8; ++ s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 0; ++ break; ++ } ++} ++ ++static void tmp105_write(struct tmp105_s *s) ++{ ++ switch (s->pointer & 3) { ++ case 0: /* Temperature */ ++ break; ++ ++ case 1: /* Configuration */ ++ if (s->buf[0] & ~s->config & (1 << 0)) /* SD */ ++ printf("%s: TMP105 shutdown\n", __FUNCTION__); ++ s->config = s->buf[0]; ++ s->faults = tmp105_faultq[(s->config >> 3) & 3]; /* F */ ++ tmp105_alarm_update(s); ++ break; ++ ++ case 2: /* T_LOW */ ++ case 3: /* T_HIGH */ ++ if (s->len >= 3) ++ s->limit[s->pointer & 1] = (int16_t) ++ ((((uint16_t) s->buf[0]) << 8) | s->buf[1]); ++ tmp105_alarm_update(s); ++ break; ++ } ++} ++ ++static int tmp105_rx(i2c_slave *i2c) ++{ ++ struct tmp105_s *s = (struct tmp105_s *) i2c; ++ ++ if (s->len < 2) ++ return s->buf[s->len ++]; ++ else ++ return 0xff; ++} ++ ++static int tmp105_tx(i2c_slave *i2c, uint8_t data) ++{ ++ struct tmp105_s *s = (struct tmp105_s *) i2c; ++ ++ if (!s->len ++) ++ s->pointer = data; ++ else { ++ if (s->len <= 2) ++ s->buf[s->len - 1] = data; ++ tmp105_write(s); ++ } ++ ++ return 0; ++} ++ ++static void tmp105_event(i2c_slave *i2c, enum i2c_event event) ++{ ++ struct tmp105_s *s = (struct tmp105_s *) i2c; ++ ++ if (event == I2C_START_RECV) ++ tmp105_read(s); ++ ++ s->len = 0; ++} ++ ++static void tmp105_save(QEMUFile *f, void *opaque) ++{ ++ struct tmp105_s *s = (struct tmp105_s *) opaque; ++ ++ qemu_put_byte(f, s->len); ++ qemu_put_8s(f, &s->buf[0]); ++ qemu_put_8s(f, &s->buf[1]); ++ ++ qemu_put_8s(f, &s->pointer); ++ qemu_put_8s(f, &s->config); ++ qemu_put_be16s(f, &s->temperature); ++ qemu_put_be16s(f, &s->limit[0]); ++ qemu_put_be16s(f, &s->limit[1]); ++ qemu_put_byte(f, s->alarm); ++ s->faults = tmp105_faultq[(s->config >> 3) & 3]; /* F */ ++ ++ i2c_slave_save(f, &s->i2c); ++} ++ ++static int tmp105_load(QEMUFile *f, void *opaque, int version_id) ++{ ++ struct tmp105_s *s = (struct tmp105_s *) opaque; ++ ++ s->len = qemu_get_byte(f); ++ qemu_get_8s(f, &s->buf[0]); ++ qemu_get_8s(f, &s->buf[1]); ++ ++ qemu_get_8s(f, &s->pointer); ++ qemu_get_8s(f, &s->config); ++ qemu_get_be16s(f, &s->temperature); ++ qemu_get_be16s(f, &s->limit[0]); ++ qemu_get_be16s(f, &s->limit[1]); ++ s->alarm = qemu_get_byte(f); ++ ++ tmp105_interrupt_update(s); ++ ++ i2c_slave_load(f, &s->i2c); ++ return 0; ++} ++ ++void tmp105_reset(i2c_slave *i2c) ++{ ++ struct tmp105_s *s = (struct tmp105_s *) i2c; ++ ++ s->temperature = 0; ++ s->pointer = 0; ++ s->config = 0; ++ s->faults = tmp105_faultq[(s->config >> 3) & 3]; ++ s->alarm = 0; ++ ++ tmp105_interrupt_update(s); ++} ++ ++static int tmp105_iid = 0; ++ ++struct i2c_slave *tmp105_init(i2c_bus *bus, qemu_irq alarm) ++{ ++ struct tmp105_s *s = (struct tmp105_s *) ++ i2c_slave_init(bus, 0, sizeof(struct tmp105_s)); ++ ++ s->i2c.event = tmp105_event; ++ s->i2c.recv = tmp105_rx; ++ s->i2c.send = tmp105_tx; ++ s->pin = alarm; ++ ++ tmp105_reset(&s->i2c); ++ ++ register_savevm("TMP105", tmp105_iid ++, 0, ++ tmp105_save, tmp105_load, s); ++ ++ return &s->i2c; ++} +diff --git a/hw/tsc210x.c b/hw/tsc210x.c +index 96956a4..1654b8b 100644 +--- a/hw/tsc210x.c ++++ b/hw/tsc210x.c +@@ -2,6 +2,7 @@ + * TI TSC2102 (touchscreen/sensors/audio controller) emulator. + * + * Copyright (c) 2006 Andrzej Zaborowski ++ * Copyright (C) 2008 Nokia Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as +@@ -35,12 +36,15 @@ + + struct tsc210x_state_s { + qemu_irq pint; ++ qemu_irq kbint; ++ qemu_irq davint; + QEMUTimer *timer; + QEMUSoundCard card; + struct uwire_slave_s chip; + struct i2s_codec_s codec; + uint8_t in_fifo[16384]; + uint8_t out_fifo[16384]; ++ uint16_t model; + + int x, y; + int pressure; +@@ -64,7 +68,7 @@ struct tsc210x_state_s { + uint16_t audio_ctrl1; + uint16_t audio_ctrl2; + uint16_t audio_ctrl3; +- uint16_t pll[2]; ++ uint16_t pll[3]; + uint16_t volume; + int64_t volume_change; + int softstep; +@@ -78,6 +82,17 @@ struct tsc210x_state_s { + int i2s_rx_rate; + int i2s_tx_rate; + AudioState *audio; ++ ++ int tr[8]; ++ ++ struct { ++ uint16_t down; ++ uint16_t mask; ++ int scan; ++ int debounce; ++ int mode; ++ int intr; ++ } kb; + }; + + static const int resolution[4] = { 12, 8, 10, 12 }; +@@ -118,17 +133,10 @@ static const uint16_t mode_regs[16] = { + 0x0000, /* Y+, X- drivers */ + }; + +-/* +- * Convert screen coordinates to arbitrary values that the +- * touchscreen in my Palm Tungsten E device returns. +- * This shouldn't really matter (because the guest system +- * should calibrate the touchscreen anyway), but let's +- * imitate some real hardware. +- */ +-#define X_TRANSFORM(value) \ +- ((3850 - ((int) (value) * (3850 - 250) / 32768)) << 4) +-#define Y_TRANSFORM(value) \ +- ((150 + ((int) (value) * (3037 - 150) / 32768)) << 4) ++#define X_TRANSFORM(s) \ ++ ((s->y * s->tr[0] - s->x * s->tr[1]) / s->tr[2] + s->tr[3]) ++#define Y_TRANSFORM(s) \ ++ ((s->y * s->tr[4] - s->x * s->tr[5]) / s->tr[6] + s->tr[7]) + #define Z1_TRANSFORM(s) \ + ((400 - ((s)->x >> 7) + ((s)->pressure << 10)) << 4) + #define Z2_TRANSFORM(s) \ +@@ -161,6 +169,7 @@ static void tsc210x_reset(struct tsc210x_state_s *s) + s->audio_ctrl3 = 0x0000; + s->pll[0] = 0x1004; + s->pll[1] = 0x0000; ++ s->pll[2] = 0x1fff; + s->volume = 0xffff; + s->dac_power = 0x8540; + s->softstep = 1; +@@ -190,7 +199,15 @@ static void tsc210x_reset(struct tsc210x_state_s *s) + s->i2s_tx_rate = 0; + s->i2s_rx_rate = 0; + ++ s->kb.scan = 1; ++ s->kb.debounce = 0; ++ s->kb.mask = 0x0000; ++ s->kb.mode = 3; ++ s->kb.intr = 0; ++ + qemu_set_irq(s->pint, !s->irq); ++ qemu_set_irq(s->davint, !s->dav); ++ qemu_irq_raise(s->kbint); + } + + struct tsc210x_rate_info_s { +@@ -344,13 +361,13 @@ static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg) + switch (reg) { + case 0x00: /* X */ + s->dav &= 0xfbff; +- return TSC_CUT_RESOLUTION(X_TRANSFORM(s->x), s->precision) + ++ return TSC_CUT_RESOLUTION(X_TRANSFORM(s), s->precision) + + (s->noise & 3); + + case 0x01: /* Y */ + s->noise ++; + s->dav &= 0xfdff; +- return TSC_CUT_RESOLUTION(Y_TRANSFORM(s->y), s->precision) ^ ++ return TSC_CUT_RESOLUTION(Y_TRANSFORM(s), s->precision) ^ + (s->noise & 3); + + case 0x02: /* Z1 */ +@@ -364,6 +381,14 @@ static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg) + (s->noise & 3); + + case 0x04: /* KPData */ ++ if ((s->model & 0xff00) == 0x2300) { ++ if (s->kb.intr && (s->kb.mode & 2)) { ++ s->kb.intr = 0; ++ qemu_irq_raise(s->kbint); ++ } ++ return s->kb.down; ++ } ++ + return 0xffff; + + case 0x05: /* BAT1 */ +@@ -414,9 +439,19 @@ static uint16_t tsc2102_control_register_read( + return (s->pressure << 15) | ((!s->busy) << 14) | + (s->nextfunction << 10) | (s->nextprecision << 8) | s->filter; + +- case 0x01: /* Status */ +- return (s->pin_func << 14) | ((!s->enabled) << 13) | +- (s->host_mode << 12) | ((!!s->dav) << 11) | s->dav; ++ case 0x01: /* Status / Keypad Control */ ++ if ((s->model & 0xff00) == 0x2100) ++ return (s->pin_func << 14) | ((!s->enabled) << 13) | ++ (s->host_mode << 12) | ((!!s->dav) << 11) | s->dav; ++ else ++ return (s->kb.intr << 15) | ((s->kb.scan || !s->kb.down) << 14) | ++ (s->kb.debounce << 11); ++ ++ case 0x02: /* DAC Control */ ++ if ((s->model & 0xff00) == 0x2300) ++ return s->dac_power & 0x8000; ++ else ++ goto bad_reg; + + case 0x03: /* Reference */ + return s->ref; +@@ -427,7 +462,18 @@ static uint16_t tsc2102_control_register_read( + case 0x05: /* Configuration */ + return s->timing; + ++ case 0x06: /* Secondary configuration */ ++ if ((s->model & 0xff00) == 0x2100) ++ goto bad_reg; ++ return ((!s->dav) << 15) | ((s->kb.mode & 1) << 14) | s->pll[2]; ++ ++ case 0x10: /* Keypad Mask */ ++ if ((s->model & 0xff00) == 0x2100) ++ goto bad_reg; ++ return s->kb.mask; ++ + default: ++ bad_reg: + #ifdef TSC_VERBOSE + fprintf(stderr, "tsc2102_control_register_read: " + "no such register: 0x%02x\n", reg); +@@ -556,10 +602,27 @@ static void tsc2102_control_register_write( + s->filter = value & 0xff; + return; + +- case 0x01: /* Status */ +- s->pin_func = value >> 14; ++ case 0x01: /* Status / Keypad Control */ ++ if ((s->model & 0xff00) == 0x2100) ++ s->pin_func = value >> 14; ++ else { ++ s->kb.scan = (value >> 14) & 1; ++ s->kb.debounce = (value >> 11) & 7; ++ if (s->kb.intr && s->kb.scan) { ++ s->kb.intr = 0; ++ qemu_irq_raise(s->kbint); ++ } ++ } + return; + ++ case 0x02: /* DAC Control */ ++ if ((s->model & 0xff00) == 0x2300) { ++ s->dac_power &= 0x7fff; ++ s->dac_power |= 0x8000 & value; ++ } else ++ goto bad_reg; ++ break; ++ + case 0x03: /* Reference */ + s->ref = value & 0x1f; + return; +@@ -586,7 +649,21 @@ static void tsc2102_control_register_write( + #endif + return; + ++ case 0x06: /* Secondary configuration */ ++ if ((s->model & 0xff00) == 0x2100) ++ goto bad_reg; ++ s->kb.mode = value >> 14; ++ s->pll[2] = value & 0x3ffff; ++ return; ++ ++ case 0x10: /* Keypad Mask */ ++ if ((s->model & 0xff00) == 0x2100) ++ goto bad_reg; ++ s->kb.mask = value; ++ return; ++ + default: ++ bad_reg: + #ifdef TSC_VERBOSE + fprintf(stderr, "tsc2102_control_register_write: " + "no such register: 0x%02x\n", reg); +@@ -785,7 +862,7 @@ static void tsc210x_pin_update(struct tsc210x_state_s *s) + return; + } + +- if (!s->enabled || s->busy) ++ if (!s->enabled || s->busy || s->dav) + return; + + s->busy = 1; +@@ -805,6 +882,8 @@ static uint16_t tsc210x_read(struct tsc210x_state_s *s) + switch (s->page) { + case TSC_DATA_REGISTERS_PAGE: + ret = tsc2102_data_register_read(s, s->offset); ++ if (!s->dav) ++ qemu_irq_raise(s->davint); + break; + case TSC_CONTROL_REGISTERS_PAGE: + ret = tsc2102_control_register_read(s, s->offset); +@@ -859,6 +938,22 @@ static void tsc210x_write(struct tsc210x_state_s *s, uint16_t value) + } + } + ++uint32_t tsc210x_txrx(void *opaque, uint32_t value) ++{ ++ struct tsc210x_state_s *s = opaque; ++ uint32_t ret = 0; ++ ++ /* TODO: sequential reads etc - how do we make sure the host doesn't ++ * unintentionally read out a conversion result from a register while ++ * transmitting the command word of the next command? */ ++ if (!value || (s->state && s->command)) ++ ret = tsc210x_read(s); ++ if (value || (s->state && !s->command)) ++ tsc210x_write(s, value); ++ ++ return ret; ++} ++ + static void tsc210x_timer_tick(void *opaque) + { + struct tsc210x_state_s *s = opaque; +@@ -871,6 +966,7 @@ static void tsc210x_timer_tick(void *opaque) + s->busy = 0; + s->dav |= mode_regs[s->function]; + tsc210x_pin_update(s); ++ qemu_irq_lower(s->davint); + } + + static void tsc210x_touchscreen_event(void *opaque, +@@ -1001,6 +1097,7 @@ static int tsc210x_load(QEMUFile *f, void *opaque, int version_id) + + s->busy = qemu_timer_pending(s->timer); + qemu_set_irq(s->pint, !s->irq); ++ qemu_set_irq(s->davint, !s->dav); + + return 0; + } +@@ -1020,9 +1117,19 @@ struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio) + s->precision = s->nextprecision = 0; + s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s); + s->pint = pint; ++ s->model = 0x2102; + s->name = "tsc2102"; + s->audio = audio; + ++ s->tr[0] = 0; ++ s->tr[1] = 1; ++ s->tr[2] = 0; ++ s->tr[3] = 1; ++ s->tr[4] = 1; ++ s->tr[5] = 0; ++ s->tr[6] = 0; ++ s->tr[7] = 1; ++ + s->chip.opaque = s; + s->chip.send = (void *) tsc210x_write; + s->chip.receive = (void *) tsc210x_read; +@@ -1048,9 +1155,147 @@ struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio) + return &s->chip; + } + ++struct uwire_slave_s *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, ++ qemu_irq dav, AudioState *audio) ++{ ++ struct tsc210x_state_s *s; ++ ++ s = (struct tsc210x_state_s *) ++ qemu_mallocz(sizeof(struct tsc210x_state_s)); ++ memset(s, 0, sizeof(struct tsc210x_state_s)); ++ s->x = 400; ++ s->y = 240; ++ s->pressure = 0; ++ s->precision = s->nextprecision = 0; ++ s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s); ++ s->pint = penirq; ++ s->kbint = kbirq; ++ s->davint = dav; ++ s->model = 0x2301; ++ s->name = "tsc2301"; ++ s->audio = audio; ++ ++ s->tr[0] = 0; ++ s->tr[1] = 1; ++ s->tr[2] = 0; ++ s->tr[3] = 1; ++ s->tr[4] = 1; ++ s->tr[5] = 0; ++ s->tr[6] = 0; ++ s->tr[7] = 1; ++ ++ s->chip.opaque = s; ++ s->chip.send = (void *) tsc210x_write; ++ s->chip.receive = (void *) tsc210x_read; ++ ++ s->codec.opaque = s; ++ s->codec.tx_swallow = (void *) tsc210x_i2s_swallow; ++ s->codec.set_rate = (void *) tsc210x_i2s_set_rate; ++ s->codec.in.fifo = s->in_fifo; ++ s->codec.out.fifo = s->out_fifo; ++ ++ tsc210x_reset(s); ++ ++ qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1, ++ "QEMU TSC2301-driven Touchscreen"); ++ ++ if (s->audio) ++ AUD_register_card(s->audio, s->name, &s->card); ++ ++ qemu_register_reset((void *) tsc210x_reset, s); ++ register_savevm(s->name, tsc2102_iid ++, 0, ++ tsc210x_save, tsc210x_load, s); ++ ++ return &s->chip; ++} ++ + struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip) + { + struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque; + + return &s->codec; + } ++ ++/* ++ * Use tslib generated calibration data to generate ADC input values ++ * from the touchscreen. Assuming 12-bit precision was used during ++ * tslib calibration. ++ */ ++void tsc210x_set_transform(struct uwire_slave_s *chip, ++ struct mouse_transform_info_s *info) ++{ ++ struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque; ++#if 0 ++ int64_t ltr[8]; ++ ++ ltr[0] = (int64_t) info->a[1] * info->y; ++ ltr[1] = (int64_t) info->a[4] * info->x; ++ ltr[2] = (int64_t) info->a[1] * info->a[3] - ++ (int64_t) info->a[4] * info->a[0]; ++ ltr[3] = (int64_t) info->a[2] * info->a[4] - ++ (int64_t) info->a[5] * info->a[1]; ++ ltr[4] = (int64_t) info->a[0] * info->y; ++ ltr[5] = (int64_t) info->a[3] * info->x; ++ ltr[6] = (int64_t) info->a[4] * info->a[0] - ++ (int64_t) info->a[1] * info->a[3]; ++ ltr[7] = (int64_t) info->a[2] * info->a[3] - ++ (int64_t) info->a[5] * info->a[0]; ++ ++ /* Avoid integer overflow */ ++ s->tr[0] = ltr[0] >> 11; ++ s->tr[1] = ltr[1] >> 11; ++ s->tr[2] = muldiv64(ltr[2], 1, info->a[6]); ++ s->tr[3] = muldiv64(ltr[3], 1 << 4, ltr[2]); ++ s->tr[4] = ltr[4] >> 11; ++ s->tr[5] = ltr[5] >> 11; ++ s->tr[6] = muldiv64(ltr[6], 1, info->a[6]); ++ s->tr[7] = muldiv64(ltr[7], 1 << 4, ltr[6]); ++#else ++ ++ if (abs(info->a[0]) > abs(info->a[1])) { ++ s->tr[0] = 0; ++ s->tr[1] = -info->a[6] * info->x; ++ s->tr[2] = info->a[0]; ++ s->tr[3] = -info->a[2] / info->a[0]; ++ s->tr[4] = info->a[6] * info->y; ++ s->tr[5] = 0; ++ s->tr[6] = info->a[4]; ++ s->tr[7] = -info->a[5] / info->a[4]; ++ } else { ++ s->tr[0] = info->a[6] * info->y; ++ s->tr[1] = 0; ++ s->tr[2] = info->a[1]; ++ s->tr[3] = -info->a[2] / info->a[1]; ++ s->tr[4] = 0; ++ s->tr[5] = -info->a[6] * info->x; ++ s->tr[6] = info->a[3]; ++ s->tr[7] = -info->a[5] / info->a[3]; ++ } ++ ++ s->tr[0] >>= 11; ++ s->tr[1] >>= 11; ++ s->tr[3] <<= 4; ++ s->tr[4] >>= 11; ++ s->tr[5] >>= 11; ++ s->tr[7] <<= 4; ++#endif ++} ++ ++void tsc210x_key_event(struct uwire_slave_s *chip, int key, int down) ++{ ++ struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque; ++ ++ if (down) ++ s->kb.down |= 1 << key; ++ else ++ s->kb.down &= ~(1 << key); ++ ++ if (down && (s->kb.down & ~s->kb.mask) && !s->kb.intr) { ++ s->kb.intr = 1; ++ qemu_irq_lower(s->kbint); ++ } else if (s->kb.intr && !(s->kb.down & ~s->kb.mask) && ++ !(s->kb.mode & 1)) { ++ s->kb.intr = 0; ++ qemu_irq_raise(s->kbint); ++ } ++} +diff --git a/hw/twl92230.c b/hw/twl92230.c +new file mode 100644 +index 0000000..11a5d1a +--- /dev/null ++++ b/hw/twl92230.c +@@ -0,0 +1,923 @@ ++/* ++ * TI TWL92230C energy-management companion device for the OMAP24xx. ++ * Aka. Menelaus (N4200 MENELAUS1_V2.2) ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Written by Andrzej Zaborowski ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, 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" ++ ++#define VERBOSE 1 ++ ++struct menelaus_s { ++ i2c_slave i2c; ++ qemu_irq irq; ++ ++ int firstbyte; ++ uint8_t reg; ++ ++ uint8_t vcore[5]; ++ uint8_t dcdc[3]; ++ uint8_t ldo[8]; ++ uint8_t sleep[2]; ++ uint8_t osc; ++ uint8_t detect; ++ uint16_t mask; ++ uint16_t status; ++ uint8_t dir; ++ uint8_t inputs; ++ uint8_t outputs; ++ uint8_t bbsms; ++ uint8_t pull[4]; ++ uint8_t mmc_ctrl[3]; ++ uint8_t mmc_debounce; ++ struct { ++ uint8_t ctrl; ++ uint16_t comp; ++ QEMUTimer *hz; ++ int64_t next; ++ struct tm tm; ++ struct tm new; ++ struct tm alm; ++ time_t sec; ++ time_t alm_sec; ++ time_t next_comp; ++ struct tm *(*gettime)(const time_t *timep, struct tm *result); ++ } rtc; ++ qemu_irq handler[3]; ++ qemu_irq *in; ++ int pwrbtn_state; ++ qemu_irq pwrbtn; ++}; ++ ++static inline void menelaus_update(struct menelaus_s *s) ++{ ++ qemu_set_irq(s->irq, s->status & ~s->mask); ++} ++ ++static inline void menelaus_rtc_start(struct menelaus_s *s) ++{ ++ s->rtc.next =+ qemu_get_clock(rt_clock); ++ qemu_mod_timer(s->rtc.hz, s->rtc.next); ++} ++ ++static inline void menelaus_rtc_stop(struct menelaus_s *s) ++{ ++ qemu_del_timer(s->rtc.hz); ++ s->rtc.next =- qemu_get_clock(rt_clock); ++ if (s->rtc.next < 1) ++ s->rtc.next = 1; ++} ++ ++static void menelaus_rtc_update(struct menelaus_s *s) ++{ ++ s->rtc.gettime(&s->rtc.sec, &s->rtc.tm); ++} ++ ++static void menelaus_alm_update(struct menelaus_s *s) ++{ ++ if ((s->rtc.ctrl & 3) == 3) ++ s->rtc.alm_sec = mktime(&s->rtc.alm); ++} ++ ++static void menelaus_rtc_hz(void *opaque) ++{ ++ struct menelaus_s *s = (struct menelaus_s *) opaque; ++ ++ s->rtc.sec ++; ++ s->rtc.next += 1000; ++ qemu_mod_timer(s->rtc.hz, s->rtc.next); ++ if ((s->rtc.ctrl >> 3) & 3) { /* EVERY */ ++ menelaus_rtc_update(s); ++ if (((s->rtc.ctrl >> 3) & 3) == 1 && !s->rtc.tm.tm_sec) ++ s->status |= 1 << 8; /* RTCTMR */ ++ else if (((s->rtc.ctrl >> 3) & 3) == 2 && !s->rtc.tm.tm_min) ++ s->status |= 1 << 8; /* RTCTMR */ ++ else if (!s->rtc.tm.tm_hour) ++ s->status |= 1 << 8; /* RTCTMR */ ++ } else ++ s->status |= 1 << 8; /* RTCTMR */ ++ if ((s->rtc.ctrl >> 1) & 1) { /* RTC_AL_EN */ ++ if (s->rtc.sec == s->rtc.alm_sec) ++ s->status |= 1 << 9; /* RTCALM */ ++ /* TODO: wake-up */ ++ } ++ if (s->rtc.next_comp >= s->rtc.sec) { ++ s->rtc.next -= muldiv64((int16_t) s->rtc.comp, 1000, 0x8000); ++ s->rtc.next_comp = s->rtc.sec + 3600; ++ } ++ menelaus_update(s); ++} ++ ++void menelaus_reset(i2c_slave *i2c) ++{ ++ struct menelaus_s *s = (struct menelaus_s *) i2c; ++ time_t ti; ++ s->reg = 0x00; ++ ++ s->vcore[0] = 0x0c; /* XXX: X-loader needs 0x8c? check! */ ++ s->vcore[1] = 0x05; ++ s->vcore[2] = 0x02; ++ s->vcore[3] = 0x0c; ++ s->vcore[4] = 0x03; ++ s->dcdc[0] = 0x33; /* Depends on wiring */ ++ s->dcdc[1] = 0x03; ++ s->dcdc[2] = 0x00; ++ s->ldo[0] = 0x95; ++ s->ldo[1] = 0x7e; ++ s->ldo[2] = 0x00; ++ s->ldo[3] = 0x00; /* Depends on wiring */ ++ s->ldo[4] = 0x03; /* Depends on wiring */ ++ s->ldo[5] = 0x00; ++ s->ldo[6] = 0x00; ++ s->ldo[7] = 0x00; ++ s->sleep[0] = 0x00; ++ s->sleep[1] = 0x00; ++ s->osc = 0x01; ++ s->detect = 0x09; ++ s->mask = 0x0fff; ++ s->status = 0; ++ s->dir = 0x07; ++ s->outputs = 0x00; ++ s->bbsms = 0x00; ++ s->pull[0] = 0x00; ++ s->pull[1] = 0x00; ++ s->pull[2] = 0x00; ++ s->pull[3] = 0x00; ++ s->mmc_ctrl[0] = 0x03; ++ s->mmc_ctrl[1] = 0xc0; ++ s->mmc_ctrl[2] = 0x00; ++ s->mmc_debounce = 0x05; ++ ++ time(&ti); ++ if (s->rtc.ctrl & 1) ++ menelaus_rtc_stop(s); ++ s->rtc.ctrl = 0x00; ++ s->rtc.comp = 0x0000; ++ s->rtc.next = 1000; ++ s->rtc.sec = ti; ++ s->rtc.next_comp = s->rtc.sec + 1800; ++ s->rtc.alm.tm_sec = 0x00; ++ s->rtc.alm.tm_min = 0x00; ++ s->rtc.alm.tm_hour = 0x00; ++ s->rtc.alm.tm_mday = 0x01; ++ s->rtc.alm.tm_mon = 0x00; ++ s->rtc.alm.tm_year = 2004; ++ menelaus_update(s); ++} ++ ++static inline uint8_t to_bcd(int val) ++{ ++ return ((val / 10) << 4) | (val % 10); ++} ++ ++static inline int from_bcd(uint8_t val) ++{ ++ return ((val >> 4) * 10) + (val & 0x0f); ++} ++ ++static void menelaus_gpio_set(void *opaque, int line, int level) ++{ ++ struct menelaus_s *s = (struct menelaus_s *) opaque; ++ ++ /* No interrupt generated */ ++ s->inputs &= ~(1 << line); ++ s->inputs |= level << line; ++} ++ ++static void menelaus_pwrbtn_set(void *opaque, int line, int level) ++{ ++ struct menelaus_s *s = (struct menelaus_s *) opaque; ++ ++ if (!s->pwrbtn_state && level) { ++ s->status |= 1 << 11; /* PSHBTN */ ++ menelaus_update(s); ++ } ++ s->pwrbtn_state = level; ++} ++ ++#define MENELAUS_REV 0x01 ++#define MENELAUS_VCORE_CTRL1 0x02 ++#define MENELAUS_VCORE_CTRL2 0x03 ++#define MENELAUS_VCORE_CTRL3 0x04 ++#define MENELAUS_VCORE_CTRL4 0x05 ++#define MENELAUS_VCORE_CTRL5 0x06 ++#define MENELAUS_DCDC_CTRL1 0x07 ++#define MENELAUS_DCDC_CTRL2 0x08 ++#define MENELAUS_DCDC_CTRL3 0x09 ++#define MENELAUS_LDO_CTRL1 0x0a ++#define MENELAUS_LDO_CTRL2 0x0b ++#define MENELAUS_LDO_CTRL3 0x0c ++#define MENELAUS_LDO_CTRL4 0x0d ++#define MENELAUS_LDO_CTRL5 0x0e ++#define MENELAUS_LDO_CTRL6 0x0f ++#define MENELAUS_LDO_CTRL7 0x10 ++#define MENELAUS_LDO_CTRL8 0x11 ++#define MENELAUS_SLEEP_CTRL1 0x12 ++#define MENELAUS_SLEEP_CTRL2 0x13 ++#define MENELAUS_DEVICE_OFF 0x14 ++#define MENELAUS_OSC_CTRL 0x15 ++#define MENELAUS_DETECT_CTRL 0x16 ++#define MENELAUS_INT_MASK1 0x17 ++#define MENELAUS_INT_MASK2 0x18 ++#define MENELAUS_INT_STATUS1 0x19 ++#define MENELAUS_INT_STATUS2 0x1a ++#define MENELAUS_INT_ACK1 0x1b ++#define MENELAUS_INT_ACK2 0x1c ++#define MENELAUS_GPIO_CTRL 0x1d ++#define MENELAUS_GPIO_IN 0x1e ++#define MENELAUS_GPIO_OUT 0x1f ++#define MENELAUS_BBSMS 0x20 ++#define MENELAUS_RTC_CTRL 0x21 ++#define MENELAUS_RTC_UPDATE 0x22 ++#define MENELAUS_RTC_SEC 0x23 ++#define MENELAUS_RTC_MIN 0x24 ++#define MENELAUS_RTC_HR 0x25 ++#define MENELAUS_RTC_DAY 0x26 ++#define MENELAUS_RTC_MON 0x27 ++#define MENELAUS_RTC_YR 0x28 ++#define MENELAUS_RTC_WKDAY 0x29 ++#define MENELAUS_RTC_AL_SEC 0x2a ++#define MENELAUS_RTC_AL_MIN 0x2b ++#define MENELAUS_RTC_AL_HR 0x2c ++#define MENELAUS_RTC_AL_DAY 0x2d ++#define MENELAUS_RTC_AL_MON 0x2e ++#define MENELAUS_RTC_AL_YR 0x2f ++#define MENELAUS_RTC_COMP_MSB 0x30 ++#define MENELAUS_RTC_COMP_LSB 0x31 ++#define MENELAUS_S1_PULL_EN 0x32 ++#define MENELAUS_S1_PULL_DIR 0x33 ++#define MENELAUS_S2_PULL_EN 0x34 ++#define MENELAUS_S2_PULL_DIR 0x35 ++#define MENELAUS_MCT_CTRL1 0x36 ++#define MENELAUS_MCT_CTRL2 0x37 ++#define MENELAUS_MCT_CTRL3 0x38 ++#define MENELAUS_MCT_PIN_ST 0x39 ++#define MENELAUS_DEBOUNCE1 0x3a ++ ++static uint8_t menelaus_read(void *opaque, uint8_t addr) ++{ ++ struct menelaus_s *s = (struct menelaus_s *) opaque; ++ int reg = 0; ++ ++ switch (addr) { ++ case MENELAUS_REV: ++ return 0x22; ++ ++ case MENELAUS_VCORE_CTRL5: reg ++; ++ case MENELAUS_VCORE_CTRL4: reg ++; ++ case MENELAUS_VCORE_CTRL3: reg ++; ++ case MENELAUS_VCORE_CTRL2: reg ++; ++ case MENELAUS_VCORE_CTRL1: ++ return s->vcore[reg]; ++ ++ case MENELAUS_DCDC_CTRL3: reg ++; ++ case MENELAUS_DCDC_CTRL2: reg ++; ++ case MENELAUS_DCDC_CTRL1: ++ return s->dcdc[reg]; ++ ++ case MENELAUS_LDO_CTRL8: reg ++; ++ case MENELAUS_LDO_CTRL7: reg ++; ++ case MENELAUS_LDO_CTRL6: reg ++; ++ case MENELAUS_LDO_CTRL5: reg ++; ++ case MENELAUS_LDO_CTRL4: reg ++; ++ case MENELAUS_LDO_CTRL3: reg ++; ++ case MENELAUS_LDO_CTRL2: reg ++; ++ case MENELAUS_LDO_CTRL1: ++ return s->ldo[reg]; ++ ++ case MENELAUS_SLEEP_CTRL2: reg ++; ++ case MENELAUS_SLEEP_CTRL1: ++ return s->sleep[reg]; ++ ++ case MENELAUS_DEVICE_OFF: ++ return 0; ++ ++ case MENELAUS_OSC_CTRL: ++ return s->osc | (1 << 7); /* CLK32K_GOOD */ ++ ++ case MENELAUS_DETECT_CTRL: ++ return s->detect; ++ ++ case MENELAUS_INT_MASK1: ++ return (s->mask >> 0) & 0xff; ++ case MENELAUS_INT_MASK2: ++ return (s->mask >> 8) & 0xff; ++ ++ case MENELAUS_INT_STATUS1: ++ return (s->status >> 0) & 0xff; ++ case MENELAUS_INT_STATUS2: ++ return (s->status >> 8) & 0xff; ++ ++ case MENELAUS_INT_ACK1: ++ case MENELAUS_INT_ACK2: ++ return 0; ++ ++ case MENELAUS_GPIO_CTRL: ++ return s->dir; ++ case MENELAUS_GPIO_IN: ++ return s->inputs | (~s->dir & s->outputs); ++ case MENELAUS_GPIO_OUT: ++ return s->outputs; ++ ++ case MENELAUS_BBSMS: ++ return s->bbsms; ++ ++ case MENELAUS_RTC_CTRL: ++ return s->rtc.ctrl; ++ case MENELAUS_RTC_UPDATE: ++ return 0x00; ++ case MENELAUS_RTC_SEC: ++ menelaus_rtc_update(s); ++ return to_bcd(s->rtc.tm.tm_sec); ++ case MENELAUS_RTC_MIN: ++ menelaus_rtc_update(s); ++ return to_bcd(s->rtc.tm.tm_min); ++ case MENELAUS_RTC_HR: ++ menelaus_rtc_update(s); ++ if ((s->rtc.ctrl >> 2) & 1) /* MODE12_n24 */ ++ return to_bcd((s->rtc.tm.tm_hour % 12) + 1) | ++ (!!(s->rtc.tm.tm_hour >= 12) << 7); /* PM_nAM */ ++ else ++ return to_bcd(s->rtc.tm.tm_hour); ++ case MENELAUS_RTC_DAY: ++ menelaus_rtc_update(s); ++ return to_bcd(s->rtc.tm.tm_mday); ++ case MENELAUS_RTC_MON: ++ menelaus_rtc_update(s); ++ return to_bcd(s->rtc.tm.tm_mon + 1); ++ case MENELAUS_RTC_YR: ++ menelaus_rtc_update(s); ++ return to_bcd(s->rtc.tm.tm_year - 2000); ++ case MENELAUS_RTC_WKDAY: ++ menelaus_rtc_update(s); ++ return to_bcd(s->rtc.tm.tm_wday); ++ case MENELAUS_RTC_AL_SEC: ++ return to_bcd(s->rtc.alm.tm_sec); ++ case MENELAUS_RTC_AL_MIN: ++ return to_bcd(s->rtc.alm.tm_min); ++ case MENELAUS_RTC_AL_HR: ++ if ((s->rtc.ctrl >> 2) & 1) /* MODE12_n24 */ ++ return to_bcd((s->rtc.alm.tm_hour % 12) + 1) | ++ (!!(s->rtc.alm.tm_hour >= 12) << 7);/* AL_PM_nAM */ ++ else ++ return to_bcd(s->rtc.alm.tm_hour); ++ case MENELAUS_RTC_AL_DAY: ++ return to_bcd(s->rtc.alm.tm_mday); ++ case MENELAUS_RTC_AL_MON: ++ return to_bcd(s->rtc.alm.tm_mon + 1); ++ case MENELAUS_RTC_AL_YR: ++ return to_bcd(s->rtc.alm.tm_year - 2000); ++ case MENELAUS_RTC_COMP_MSB: ++ return (s->rtc.comp >> 8) & 0xff; ++ case MENELAUS_RTC_COMP_LSB: ++ return (s->rtc.comp >> 0) & 0xff; ++ ++ case MENELAUS_S1_PULL_EN: ++ return s->pull[0]; ++ case MENELAUS_S1_PULL_DIR: ++ return s->pull[1]; ++ case MENELAUS_S2_PULL_EN: ++ return s->pull[2]; ++ case MENELAUS_S2_PULL_DIR: ++ return s->pull[3]; ++ ++ case MENELAUS_MCT_CTRL3: reg ++; ++ case MENELAUS_MCT_CTRL2: reg ++; ++ case MENELAUS_MCT_CTRL1: ++ return s->mmc_ctrl[reg]; ++ case MENELAUS_MCT_PIN_ST: ++ /* TODO: return the real Card Detect */ ++ return 0; ++ case MENELAUS_DEBOUNCE1: ++ return s->mmc_debounce; ++ ++ default: ++#ifdef VERBOSE ++ printf("%s: unknown register %02x\n", __FUNCTION__, addr); ++#endif ++ break; ++ } ++ return 0; ++} ++ ++static void menelaus_write(void *opaque, uint8_t addr, uint8_t value) ++{ ++ struct menelaus_s *s = (struct menelaus_s *) opaque; ++ int line; ++ int reg = 0; ++ struct tm tm; ++ ++ switch (addr) { ++ case MENELAUS_VCORE_CTRL1: ++ s->vcore[0] = (value & 0xe) | MIN(value & 0x1f, 0x12); ++ break; ++ case MENELAUS_VCORE_CTRL2: ++ s->vcore[1] = value; ++ break; ++ case MENELAUS_VCORE_CTRL3: ++ s->vcore[2] = MIN(value & 0x1f, 0x12); ++ break; ++ case MENELAUS_VCORE_CTRL4: ++ s->vcore[3] = MIN(value & 0x1f, 0x12); ++ break; ++ case MENELAUS_VCORE_CTRL5: ++ s->vcore[4] = value & 3; ++ /* XXX ++ * auto set to 3 on M_Active, nRESWARM ++ * auto set to 0 on M_WaitOn, M_Backup ++ */ ++ break; ++ ++ case MENELAUS_DCDC_CTRL1: ++ s->dcdc[0] = value & 0x3f; ++ break; ++ case MENELAUS_DCDC_CTRL2: ++ s->dcdc[1] = value & 0x07; ++ /* XXX ++ * auto set to 3 on M_Active, nRESWARM ++ * auto set to 0 on M_WaitOn, M_Backup ++ */ ++ break; ++ case MENELAUS_DCDC_CTRL3: ++ s->dcdc[2] = value & 0x07; ++ break; ++ ++ case MENELAUS_LDO_CTRL1: ++ s->ldo[0] = value; ++ break; ++ case MENELAUS_LDO_CTRL2: ++ s->ldo[1] = value & 0x7f; ++ /* XXX ++ * auto set to 0x7e on M_WaitOn, M_Backup ++ */ ++ break; ++ case MENELAUS_LDO_CTRL3: ++ s->ldo[2] = value & 3; ++ /* XXX ++ * auto set to 3 on M_Active, nRESWARM ++ * auto set to 0 on M_WaitOn, M_Backup ++ */ ++ break; ++ case MENELAUS_LDO_CTRL4: ++ s->ldo[3] = value & 3; ++ /* XXX ++ * auto set to 3 on M_Active, nRESWARM ++ * auto set to 0 on M_WaitOn, M_Backup ++ */ ++ break; ++ case MENELAUS_LDO_CTRL5: ++ s->ldo[4] = value & 3; ++ /* XXX ++ * auto set to 3 on M_Active, nRESWARM ++ * auto set to 0 on M_WaitOn, M_Backup ++ */ ++ break; ++ case MENELAUS_LDO_CTRL6: ++ s->ldo[5] = value & 3; ++ break; ++ case MENELAUS_LDO_CTRL7: ++ s->ldo[6] = value & 3; ++ break; ++ case MENELAUS_LDO_CTRL8: ++ s->ldo[7] = value & 3; ++ break; ++ ++ case MENELAUS_SLEEP_CTRL2: reg ++; ++ case MENELAUS_SLEEP_CTRL1: ++ s->sleep[reg] = value; ++ break; ++ ++ case MENELAUS_DEVICE_OFF: ++ if (value & 1) ++ menelaus_reset(&s->i2c); ++ break; ++ ++ case MENELAUS_OSC_CTRL: ++ s->osc = value & 7; ++ break; ++ ++ case MENELAUS_DETECT_CTRL: ++ s->detect = value & 0x7f; ++ break; ++ ++ case MENELAUS_INT_MASK1: ++ s->mask &= 0xf00; ++ s->mask |= value << 0; ++ menelaus_update(s); ++ break; ++ case MENELAUS_INT_MASK2: ++ s->mask &= 0x0ff; ++ s->mask |= value << 8; ++ menelaus_update(s); ++ break; ++ ++ case MENELAUS_INT_ACK1: ++ s->status &= ~(((uint16_t) value) << 0); ++ menelaus_update(s); ++ break; ++ case MENELAUS_INT_ACK2: ++ s->status &= ~(((uint16_t) value) << 8); ++ menelaus_update(s); ++ break; ++ ++ case MENELAUS_GPIO_CTRL: ++ for (line = 0; line < 3; line ++) ++ if (((s->dir ^ value) >> line) & 1) ++ if (s->handler[line]) ++ qemu_set_irq(s->handler[line], ++ ((s->outputs & ~s->dir) >> line) & 1); ++ s->dir = value & 0x67; ++ break; ++ case MENELAUS_GPIO_OUT: ++ for (line = 0; line < 3; line ++) ++ if ((((s->outputs ^ value) & ~s->dir) >> line) & 1) ++ if (s->handler[line]) ++ qemu_set_irq(s->handler[line], (s->outputs >> line) & 1); ++ s->outputs = value & 0x07; ++ break; ++ ++ case MENELAUS_BBSMS: ++ s->bbsms = 0x0d; ++ break; ++ ++ case MENELAUS_RTC_CTRL: ++ if ((s->rtc.ctrl ^ value) & 1) { /* RTC_EN */ ++ if (value & 1) ++ menelaus_rtc_start(s); ++ else ++ menelaus_rtc_stop(s); ++ } ++ s->rtc.ctrl = value & 0x1f; ++ menelaus_alm_update(s); ++ break; ++ case MENELAUS_RTC_UPDATE: ++ menelaus_rtc_update(s); ++ memcpy(&tm, &s->rtc.tm, sizeof(tm)); ++ switch (value & 0xf) { ++ case 0: ++ break; ++ case 1: ++ tm.tm_sec = s->rtc.new.tm_sec; ++ break; ++ case 2: ++ tm.tm_min = s->rtc.new.tm_min; ++ break; ++ case 3: ++ if (s->rtc.new.tm_hour > 23) ++ goto rtc_badness; ++ tm.tm_hour = s->rtc.new.tm_hour; ++ break; ++ case 4: ++ if (s->rtc.new.tm_mday < 1) ++ goto rtc_badness; ++ /* TODO check range */ ++ tm.tm_mday = s->rtc.new.tm_mday; ++ break; ++ case 5: ++ if (s->rtc.new.tm_mon < 0 || s->rtc.new.tm_mon > 11) ++ goto rtc_badness; ++ tm.tm_mon = s->rtc.new.tm_mon; ++ break; ++ case 6: ++ tm.tm_year = s->rtc.new.tm_year; ++ break; ++ case 7: ++ /* TODO set .tm_mday instead */ ++ tm.tm_wday = s->rtc.new.tm_wday; ++ break; ++ case 8: ++ if (s->rtc.new.tm_hour > 23) ++ goto rtc_badness; ++ if (s->rtc.new.tm_mday < 1) ++ goto rtc_badness; ++ if (s->rtc.new.tm_mon < 0 || s->rtc.new.tm_mon > 11) ++ goto rtc_badness; ++ tm.tm_sec = s->rtc.new.tm_sec; ++ tm.tm_min = s->rtc.new.tm_min; ++ tm.tm_hour = s->rtc.new.tm_hour; ++ tm.tm_mday = s->rtc.new.tm_mday; ++ tm.tm_mon = s->rtc.new.tm_mon; ++ tm.tm_year = s->rtc.new.tm_year; ++ break; ++ rtc_badness: ++ default: ++ fprintf(stderr, "%s: bad RTC_UPDATE value %02x\n", ++ __FUNCTION__, value); ++ s->status |= 1 << 10; /* RTCERR */ ++ menelaus_update(s); ++ } ++ s->rtc.sec += difftime(mktime(&tm), mktime(&s->rtc.tm)); ++ break; ++ case MENELAUS_RTC_SEC: ++ s->rtc.tm.tm_sec = from_bcd(value & 0x7f); ++ break; ++ case MENELAUS_RTC_MIN: ++ s->rtc.tm.tm_min = from_bcd(value & 0x7f); ++ break; ++ case MENELAUS_RTC_HR: ++ s->rtc.tm.tm_hour = (s->rtc.ctrl & (1 << 2)) ? /* MODE12_n24 */ ++ MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) : ++ from_bcd(value & 0x3f); ++ break; ++ case MENELAUS_RTC_DAY: ++ s->rtc.tm.tm_mday = from_bcd(value); ++ break; ++ case MENELAUS_RTC_MON: ++ s->rtc.tm.tm_mon = MAX(1, from_bcd(value)) - 1; ++ break; ++ case MENELAUS_RTC_YR: ++ s->rtc.tm.tm_year = 2000 + from_bcd(value); ++ break; ++ case MENELAUS_RTC_WKDAY: ++ s->rtc.tm.tm_mday = from_bcd(value); ++ break; ++ case MENELAUS_RTC_AL_SEC: ++ s->rtc.alm.tm_sec = from_bcd(value & 0x7f); ++ menelaus_alm_update(s); ++ break; ++ case MENELAUS_RTC_AL_MIN: ++ s->rtc.alm.tm_min = from_bcd(value & 0x7f); ++ menelaus_alm_update(s); ++ break; ++ case MENELAUS_RTC_AL_HR: ++ s->rtc.alm.tm_hour = (s->rtc.ctrl & (1 << 2)) ? /* MODE12_n24 */ ++ MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) : ++ from_bcd(value & 0x3f); ++ menelaus_alm_update(s); ++ break; ++ case MENELAUS_RTC_AL_DAY: ++ s->rtc.alm.tm_mday = from_bcd(value); ++ menelaus_alm_update(s); ++ break; ++ case MENELAUS_RTC_AL_MON: ++ s->rtc.alm.tm_mon = MAX(1, from_bcd(value)) - 1; ++ menelaus_alm_update(s); ++ break; ++ case MENELAUS_RTC_AL_YR: ++ s->rtc.alm.tm_year = 2000 + from_bcd(value); ++ menelaus_alm_update(s); ++ break; ++ case MENELAUS_RTC_COMP_MSB: ++ s->rtc.comp &= 0xff; ++ s->rtc.comp |= value << 8; ++ break; ++ case MENELAUS_RTC_COMP_LSB: ++ s->rtc.comp &= 0xff << 8; ++ s->rtc.comp |= value; ++ break; ++ ++ case MENELAUS_S1_PULL_EN: ++ s->pull[0] = value; ++ break; ++ case MENELAUS_S1_PULL_DIR: ++ s->pull[1] = value & 0x1f; ++ break; ++ case MENELAUS_S2_PULL_EN: ++ s->pull[2] = value; ++ break; ++ case MENELAUS_S2_PULL_DIR: ++ s->pull[3] = value & 0x1f; ++ break; ++ ++ case MENELAUS_MCT_CTRL1: ++ s->mmc_ctrl[0] = value & 0x7f; ++ break; ++ case MENELAUS_MCT_CTRL2: ++ s->mmc_ctrl[1] = value; ++ /* TODO update Card Detect interrupts */ ++ break; ++ case MENELAUS_MCT_CTRL3: ++ s->mmc_ctrl[2] = value & 0xf; ++ break; ++ case MENELAUS_DEBOUNCE1: ++ s->mmc_debounce = value & 0x3f; ++ break; ++ ++ default: ++#ifdef VERBOSE ++ printf("%s: unknown register %02x\n", __FUNCTION__, addr); ++#endif ++ } ++} ++ ++static void menelaus_event(i2c_slave *i2c, enum i2c_event event) ++{ ++ struct menelaus_s *s = (struct menelaus_s *) i2c; ++ ++ if (event == I2C_START_SEND) ++ s->firstbyte = 1; ++} ++ ++static int menelaus_tx(i2c_slave *i2c, uint8_t data) ++{ ++ struct menelaus_s *s = (struct menelaus_s *) i2c; ++ /* Interpret register address byte */ ++ if (s->firstbyte) { ++ s->reg = data; ++ s->firstbyte = 0; ++ } else ++ menelaus_write(s, s->reg ++, data); ++ ++ return 0; ++} ++ ++static int menelaus_rx(i2c_slave *i2c) ++{ ++ struct menelaus_s *s = (struct menelaus_s *) i2c; ++ ++ return menelaus_read(s, s->reg ++); ++} ++ ++static void tm_put(QEMUFile *f, struct tm *tm) { ++ qemu_put_be16(f, tm->tm_sec); ++ qemu_put_be16(f, tm->tm_min); ++ qemu_put_be16(f, tm->tm_hour); ++ qemu_put_be16(f, tm->tm_mday); ++ qemu_put_be16(f, tm->tm_min); ++ qemu_put_be16(f, tm->tm_year); ++} ++ ++static void tm_get(QEMUFile *f, struct tm *tm) { ++ tm->tm_sec = qemu_get_be16(f); ++ tm->tm_min = qemu_get_be16(f); ++ tm->tm_hour = qemu_get_be16(f); ++ tm->tm_mday = qemu_get_be16(f); ++ tm->tm_min = qemu_get_be16(f); ++ tm->tm_year = qemu_get_be16(f); ++} ++ ++static void menelaus_save(QEMUFile *f, void *opaque) ++{ ++ struct menelaus_s *s = (struct menelaus_s *) opaque; ++ ++ qemu_put_be32(f, s->firstbyte); ++ qemu_put_8s(f, &s->reg); ++ ++ qemu_put_8s(f, &s->vcore[0]); ++ qemu_put_8s(f, &s->vcore[1]); ++ qemu_put_8s(f, &s->vcore[2]); ++ qemu_put_8s(f, &s->vcore[3]); ++ qemu_put_8s(f, &s->vcore[4]); ++ qemu_put_8s(f, &s->dcdc[3]); ++ qemu_put_8s(f, &s->dcdc[3]); ++ qemu_put_8s(f, &s->dcdc[3]); ++ qemu_put_8s(f, &s->ldo[0]); ++ qemu_put_8s(f, &s->ldo[1]); ++ qemu_put_8s(f, &s->ldo[2]); ++ qemu_put_8s(f, &s->ldo[3]); ++ qemu_put_8s(f, &s->ldo[4]); ++ qemu_put_8s(f, &s->ldo[5]); ++ qemu_put_8s(f, &s->ldo[6]); ++ qemu_put_8s(f, &s->ldo[7]); ++ qemu_put_8s(f, &s->sleep[0]); ++ qemu_put_8s(f, &s->sleep[1]); ++ qemu_put_8s(f, &s->osc); ++ qemu_put_8s(f, &s->detect); ++ qemu_put_be16s(f, &s->mask); ++ qemu_put_be16s(f, &s->status); ++ qemu_put_8s(f, &s->dir); ++ qemu_put_8s(f, &s->inputs); ++ qemu_put_8s(f, &s->outputs); ++ qemu_put_8s(f, &s->bbsms); ++ qemu_put_8s(f, &s->pull[0]); ++ qemu_put_8s(f, &s->pull[1]); ++ qemu_put_8s(f, &s->pull[2]); ++ qemu_put_8s(f, &s->pull[3]); ++ qemu_put_8s(f, &s->mmc_ctrl[0]); ++ qemu_put_8s(f, &s->mmc_ctrl[1]); ++ qemu_put_8s(f, &s->mmc_ctrl[2]); ++ qemu_put_8s(f, &s->mmc_debounce); ++ qemu_put_8s(f, &s->rtc.ctrl); ++ qemu_put_be16s(f, &s->rtc.comp); ++ /* Should be <= 1000 */ ++ qemu_put_be16(f, s->rtc.next - qemu_get_clock(rt_clock)); ++ tm_put(f, &s->rtc.new); ++ tm_put(f, &s->rtc.alm); ++ qemu_put_byte(f, s->pwrbtn_state); ++ ++ i2c_slave_save(f, &s->i2c); ++} ++ ++static int menelaus_load(QEMUFile *f, void *opaque, int version_id) ++{ ++ struct menelaus_s *s = (struct menelaus_s *) opaque; ++ ++ s->firstbyte = qemu_get_be32(f); ++ qemu_get_8s(f, &s->reg); ++ ++ if (s->rtc.ctrl & 1) /* RTC_EN */ ++ menelaus_rtc_stop(s); ++ qemu_get_8s(f, &s->vcore[0]); ++ qemu_get_8s(f, &s->vcore[1]); ++ qemu_get_8s(f, &s->vcore[2]); ++ qemu_get_8s(f, &s->vcore[3]); ++ qemu_get_8s(f, &s->vcore[4]); ++ qemu_get_8s(f, &s->dcdc[3]); ++ qemu_get_8s(f, &s->dcdc[3]); ++ qemu_get_8s(f, &s->dcdc[3]); ++ qemu_get_8s(f, &s->ldo[0]); ++ qemu_get_8s(f, &s->ldo[1]); ++ qemu_get_8s(f, &s->ldo[2]); ++ qemu_get_8s(f, &s->ldo[3]); ++ qemu_get_8s(f, &s->ldo[4]); ++ qemu_get_8s(f, &s->ldo[5]); ++ qemu_get_8s(f, &s->ldo[6]); ++ qemu_get_8s(f, &s->ldo[7]); ++ qemu_get_8s(f, &s->sleep[0]); ++ qemu_get_8s(f, &s->sleep[1]); ++ qemu_get_8s(f, &s->osc); ++ qemu_get_8s(f, &s->detect); ++ qemu_get_be16s(f, &s->mask); ++ qemu_get_be16s(f, &s->status); ++ qemu_get_8s(f, &s->dir); ++ qemu_get_8s(f, &s->inputs); ++ qemu_get_8s(f, &s->outputs); ++ qemu_get_8s(f, &s->bbsms); ++ qemu_get_8s(f, &s->pull[0]); ++ qemu_get_8s(f, &s->pull[1]); ++ qemu_get_8s(f, &s->pull[2]); ++ qemu_get_8s(f, &s->pull[3]); ++ qemu_get_8s(f, &s->mmc_ctrl[0]); ++ qemu_get_8s(f, &s->mmc_ctrl[1]); ++ qemu_get_8s(f, &s->mmc_ctrl[2]); ++ qemu_get_8s(f, &s->mmc_debounce); ++ qemu_get_8s(f, &s->rtc.ctrl); ++ qemu_get_be16s(f, &s->rtc.comp); ++ s->rtc.next = qemu_get_be16(f); ++ tm_get(f, &s->rtc.new); ++ tm_get(f, &s->rtc.alm); ++ s->pwrbtn_state = qemu_get_byte(f); ++ menelaus_alm_update(s); ++ menelaus_update(s); ++ if (s->rtc.ctrl & 1) /* RTC_EN */ ++ menelaus_rtc_start(s); ++ ++ i2c_slave_load(f, &s->i2c); ++ return 0; ++} ++ ++static int menelaus_iid = 0; ++ ++i2c_slave *twl92230_init(i2c_bus *bus, qemu_irq irq) ++{ ++ struct menelaus_s *s = (struct menelaus_s *) ++ i2c_slave_init(bus, 0, sizeof(struct menelaus_s)); ++ ++ s->i2c.event = menelaus_event; ++ s->i2c.recv = menelaus_rx; ++ s->i2c.send = menelaus_tx; ++ ++ /* TODO: use the qemu gettime functions */ ++ s->rtc.gettime = localtime_r; ++ ++ s->irq = irq; ++ s->rtc.hz = 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]; ++ ++ menelaus_reset(&s->i2c); ++ ++ register_savevm("menelaus", menelaus_iid ++, ++ 0, menelaus_save, menelaus_load, s); ++ ++ return &s->i2c; ++} ++ ++qemu_irq *twl92230_gpio_in_get(i2c_slave *i2c) ++{ ++ struct menelaus_s *s = (struct menelaus_s *) i2c; ++ ++ return s->in; ++} ++ ++void twl92230_gpio_out_set(i2c_slave *i2c, int line, qemu_irq handler) ++{ ++ struct menelaus_s *s = (struct menelaus_s *) i2c; ++ ++ if (line >= 3 || line < 0) { ++ fprintf(stderr, "%s: No GPO line %i\n", __FUNCTION__, line); ++ exit(-1); ++ } ++ s->handler[line] = handler; ++} +diff --git a/hw/versatilepb.c b/hw/versatilepb.c +index da6e4ec..ecc0037 100644 +--- a/hw/versatilepb.c ++++ b/hw/versatilepb.c +@@ -157,6 +157,8 @@ static qemu_irq *vpb_sic_init(uint32_t base, qemu_irq *parent, int irq) + peripherans and expansion busses. For now we emulate a subset of the + PB peripherals and just change the board ID. */ + ++static struct arm_boot_info versatile_binfo; ++ + static void versatile_init(int ram_size, int vga_ram_size, + const char *boot_device, DisplayState *ds, + const char *kernel_filename, const char *kernel_cmdline, +@@ -283,8 +285,12 @@ static void versatile_init(int ram_size, int vga_ram_size, + /* 0x101f3000 UART2. */ + /* 0x101f4000 SSPI. */ + +- arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline, +- initrd_filename, board_id, 0x0); ++ versatile_binfo.ram_size = ram_size; ++ versatile_binfo.kernel_filename = kernel_filename; ++ versatile_binfo.kernel_cmdline = kernel_cmdline; ++ versatile_binfo.initrd_filename = initrd_filename; ++ versatile_binfo.board_id = board_id; ++ arm_load_kernel(env, &versatile_binfo); + } + + static void vpb_init(int ram_size, int vga_ram_size, +diff --git a/softmmu_template.h b/softmmu_template.h +index 0a4bc7e..d480f34 100644 +--- a/softmmu_template.h ++++ b/softmmu_template.h +@@ -51,12 +51,15 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, + int mmu_idx, + void *retaddr); + static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr, +- target_ulong tlb_addr) ++ target_ulong tlb_addr, ++ target_ulong tlb_io) + { + DATA_TYPE res; + int index; + +- index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); ++ index = (tlb_addr & ~TARGET_PAGE_MASK) >> IO_MEM_SHIFT; ++ if (index > 4) ++ index = (tlb_io >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); + #if SHIFT <= 2 + res = io_mem_read[index][SHIFT](io_mem_opaque[index], physaddr); + #else +@@ -95,7 +98,9 @@ DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, + /* IO access */ + if ((addr & (DATA_SIZE - 1)) != 0) + goto do_unaligned_access; +- res = glue(io_read, SUFFIX)(physaddr, tlb_addr); ++ res = glue(io_read, SUFFIX)(physaddr, tlb_addr, ++ env->tlb_table[mmu_idx] ++ [index].addr_code); + } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { + /* slow unaligned access (it spans two pages or IO) */ + do_unaligned_access: +@@ -147,7 +152,9 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, + /* IO access */ + if ((addr & (DATA_SIZE - 1)) != 0) + goto do_unaligned_access; +- res = glue(io_read, SUFFIX)(physaddr, tlb_addr); ++ res = glue(io_read, SUFFIX)(physaddr, tlb_addr, ++ env->tlb_table[mmu_idx] ++ [index].addr_code); + } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { + do_unaligned_access: + /* slow unaligned access (it spans two pages) */ +@@ -186,11 +193,14 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr, + static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr, + DATA_TYPE val, + target_ulong tlb_addr, +- void *retaddr) ++ void *retaddr, ++ target_ulong tlb_io) + { + int index; + +- index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); ++ index = (tlb_addr & ~TARGET_PAGE_MASK) >> IO_MEM_SHIFT; ++ if (index > 4) ++ index = (tlb_io >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); + env->mem_write_vaddr = tlb_addr; + env->mem_write_pc = (unsigned long)retaddr; + #if SHIFT <= 2 +@@ -228,7 +238,8 @@ void REGPARM glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, + if ((addr & (DATA_SIZE - 1)) != 0) + goto do_unaligned_access; + retaddr = GETPC(); +- glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr); ++ glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr, ++ env->tlb_table[mmu_idx][index].addr_code); + } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { + do_unaligned_access: + retaddr = GETPC(); +@@ -278,7 +289,8 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr, + /* IO access */ + if ((addr & (DATA_SIZE - 1)) != 0) + goto do_unaligned_access; +- glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr); ++ glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr, ++ env->tlb_table[mmu_idx][index].addr_code); + } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { + do_unaligned_access: + /* XXX: not efficient, but simple */ +diff --git a/target-arm/cpu.h b/target-arm/cpu.h +index b284a21..633b335 100644 +--- a/target-arm/cpu.h ++++ b/target-arm/cpu.h +@@ -198,12 +198,16 @@ typedef struct CPUARMState { + CPU_COMMON + + /* These fields after the common ones so they are preserved on reset. */ +- int ram_size; +- const char *kernel_filename; +- const char *kernel_cmdline; +- const char *initrd_filename; +- int board_id; +- target_phys_addr_t loader_start; ++ struct arm_boot_info { ++ int ram_size; ++ const char *kernel_filename; ++ const char *kernel_cmdline; ++ const char *initrd_filename; ++ target_phys_addr_t loader_start; ++ int nb_cpus; ++ int board_id; ++ int (*atag_board)(struct arm_boot_info *info, void *p); ++ } *boot_info; + } CPUARMState; + + CPUARMState *cpu_arm_init(const char *cpu_model); +@@ -377,6 +381,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum, + #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 +diff --git a/target-arm/helper.c b/target-arm/helper.c +index 86470db..0709129 100644 +--- a/target-arm/helper.c ++++ b/target-arm/helper.c +@@ -53,6 +53,9 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) + env->cp15.c0_cachetype = 0x1dd20d2; + env->cp15.c1_sys = 0x00090078; + break; ++ case ARM_CPUID_ARM1136_R2: ++ /* TODO! */ ++ env->GE = 0x5; + case ARM_CPUID_ARM1136: + set_feature(env, ARM_FEATURE_V6); + set_feature(env, ARM_FEATURE_VFP); +@@ -198,6 +201,7 @@ static const struct arm_cpu_t arm_cpu_names[] = { + { ARM_CPUID_ARM946, "arm946"}, + { ARM_CPUID_ARM1026, "arm1026"}, + { ARM_CPUID_ARM1136, "arm1136"}, ++ { ARM_CPUID_ARM1136_R2, "arm1136-r2"}, + { ARM_CPUID_ARM11MPCORE, "arm11mpcore"}, + { ARM_CPUID_CORTEXM3, "cortex-m3"}, + { ARM_CPUID_CORTEXA8, "cortex-a8"}, +@@ -1539,6 +1543,7 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn) + case ARM_CPUID_ARM1026: + return 1; + case ARM_CPUID_ARM1136: ++ case ARM_CPUID_ARM1136_R2: + return 7; + case ARM_CPUID_ARM11MPCORE: + return 1; +@@ -1721,6 +1726,10 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn) + case 8: /* TI925T_status */ + return 0; + } ++ /* TODO: Peripheral port remap register: ++ * On OMAP2 mcr p15, 0, rn, c15, c2, 4 sets up the interrupt ++ * controller base address at $rn & ~0xfff and map size of ++ * 0x200 << ($rn & 0xfff), when MMU is off. */ + goto bad_reg; + } + return 0; +diff --git a/vl.c b/vl.c +index d371af7..76d8def 100644 +--- a/vl.c ++++ b/vl.c +@@ -8006,6 +8006,7 @@ static void register_machines(void) + qemu_register_machine(&borzoipda_machine); + qemu_register_machine(&terrierpda_machine); + qemu_register_machine(&palmte_machine); ++ qemu_register_machine(&n800_machine); + qemu_register_machine(&lm3s811evb_machine); + qemu_register_machine(&lm3s6965evb_machine); + qemu_register_machine(&connex_machine); diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/series b/meta/packages/qemu/qemu-0.9.1+cvs20080307/series new file mode 100644 index 0000000000..126da88288 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/series @@ -0,0 +1,25 @@ +02_snapshot_use_tmpdir.patch -p0 +05_non-fatal_if_linux_hd_missing.patch -p1 +06_exit_segfault.patch -p0 +10_signal_jobs.patch -p0 +11_signal_sigaction.patch -p0 +22_net_tuntap_stall.patch -p0 +31_syscalls.patch -p0 +32_syscall_sysctl.patch -p0 +33_syscall_ppc_clone.patch -p0 +39_syscall_fadvise64.patch -p0 +41_arm_fpa_sigfpe.patch -p0 +52_ne2000_return.patch -p1 +61_safe_64bit_int.patch -p0 +63_sparc_build.patch -p0 +64_ppc_asm_constraints.patch -p1 +65_kfreebsd.patch -p0 +66_tls_ld.patch -p0 +91-oh-sdl-cursor.patch -p0 +qemu-0.9.0-nptl.patch -p1 +qemu-0.9.0-nptl-update.patch -p1 +qemu-amd64-32b-mapping-0.9.0.patch -p1 +workaround_bad_futex_headers.patch -p1 +fix_segfault.patch -p1 +no-strip.patch -p1 +qemu-n800-support.patch -p1 diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/workaround_bad_futex_headers.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/workaround_bad_futex_headers.patch new file mode 100644 index 0000000000..cc122ebdba --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/workaround_bad_futex_headers.patch @@ -0,0 +1,25 @@ +--- + linux-user/syscall.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +Index: qemu/linux-user/syscall.c +=================================================================== +--- qemu.orig/linux-user/syscall.c 2007-08-09 20:28:06.000000000 +0100 ++++ qemu/linux-user/syscall.c 2007-08-09 20:28:41.000000000 +0100 +@@ -61,7 +61,15 @@ + #define tchars host_tchars /* same as target */ + #define ltchars host_ltchars /* same as target */ + +-#include ++#define FUTEX_WAIT 0 ++#define FUTEX_WAKE 1 ++#define FUTEX_FD 2 ++#define FUTEX_REQUEUE 3 ++#define FUTEX_CMP_REQUEUE 4 ++#define FUTEX_WAKE_OP 5 ++#define FUTEX_LOCK_PI 6 ++#define FUTEX_UNLOCK_PI 7 ++ + #include + #include + #include diff --git a/meta/packages/qemu/qemu-0.9.1+cvs20080307/writev_fix.patch b/meta/packages/qemu/qemu-0.9.1+cvs20080307/writev_fix.patch new file mode 100644 index 0000000000..e0ed4af972 --- /dev/null +++ b/meta/packages/qemu/qemu-0.9.1+cvs20080307/writev_fix.patch @@ -0,0 +1,17 @@ +--- + linux-user/syscall.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: qemu-0.9.1/linux-user/syscall.c +=================================================================== +--- qemu-0.9.1.orig/linux-user/syscall.c 2008-02-03 00:00:00.000000000 +0000 ++++ qemu-0.9.1/linux-user/syscall.c 2008-02-03 00:00:38.000000000 +0000 +@@ -1048,7 +1048,7 @@ static abi_long lock_iovec(int type, str + base = tswapl(target_vec[i].iov_base); + vec[i].iov_len = tswapl(target_vec[i].iov_len); + vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy); +- if (!vec[i].iov_base) ++ if (!vec[i].iov_base && vec[i].iov_len) + goto fail; + } + unlock_user (target_vec, target_addr, 0); diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/02_snapshot_use_tmpdir.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/02_snapshot_use_tmpdir.patch deleted file mode 100644 index 40264ed443..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/02_snapshot_use_tmpdir.patch +++ /dev/null @@ -1,23 +0,0 @@ -#DPATCHLEVEL=0 ---- -# block.c | 6 +++++- -# 1 file changed, 5 insertions(+), 1 deletion(-) -# -Index: block.c -=================================================================== ---- block.c.orig 2007-12-03 23:47:25.000000000 +0000 -+++ block.c 2007-12-03 23:47:31.000000000 +0000 -@@ -191,8 +191,12 @@ void get_tmp_filename(char *filename, in - void get_tmp_filename(char *filename, int size) - { - int fd; -+ char *tmpdir; - /* XXX: race condition possible */ -- pstrcpy(filename, size, "/tmp/vl.XXXXXX"); -+ tmpdir = getenv("TMPDIR"); -+ if (!tmpdir) -+ tmpdir = "/tmp"; -+ snprintf(filename, size, "%s/vl.XXXXXX", tmpdir); - fd = mkstemp(filename); - close(fd); - } diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/04_do_not_print_rtc_freq_if_ok.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/04_do_not_print_rtc_freq_if_ok.patch deleted file mode 100644 index 31c9da491d..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/04_do_not_print_rtc_freq_if_ok.patch +++ /dev/null @@ -1,26 +0,0 @@ -#DPATCHLEVEL=1 ---- -# vl.c | 5 ++++- -# 1 file changed, 4 insertions(+), 1 deletion(-) -# -Index: qemu/vl.c -=================================================================== ---- qemu.orig/vl.c 2007-12-03 15:44:35.000000000 +0000 -+++ qemu/vl.c 2007-12-03 15:51:03.000000000 +0000 -@@ -1289,12 +1289,15 @@ static void hpet_stop_timer(struct qemu_ - - static int rtc_start_timer(struct qemu_alarm_timer *t) - { -+ unsigned long current_rtc_freq = 0; - int rtc_fd; - - TFR(rtc_fd = open("/dev/rtc", O_RDONLY)); - if (rtc_fd < 0) - return -1; -- if (ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) { -+ ioctl(rtc_fd, RTC_IRQP_READ, ¤t_rtc_freq); -+ if (current_rtc_freq != RTC_FREQ && -+ ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) { - fprintf(stderr, "Could not configure '/dev/rtc' to have a 1024 Hz timer. This is not a fatal\n" - "error, but for better emulation accuracy either use a 2.6 host Linux kernel or\n" - "type 'echo 1024 > /proc/sys/dev/rtc/max-user-freq' as root.\n"); diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/05_non-fatal_if_linux_hd_missing.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/05_non-fatal_if_linux_hd_missing.patch deleted file mode 100644 index fdd922605e..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/05_non-fatal_if_linux_hd_missing.patch +++ /dev/null @@ -1,17 +0,0 @@ -#DPATCHLEVEL=1 ---- -# hw/pc.c | 1 - -# 1 file changed, 1 deletion(-) -# -Index: qemu/hw/pc.c -=================================================================== ---- qemu.orig/hw/pc.c 2007-12-03 23:47:25.000000000 +0000 -+++ qemu/hw/pc.c 2007-12-03 23:47:38.000000000 +0000 -@@ -385,7 +385,6 @@ static void generate_bootsect(uint32_t g - if (bs_table[0] == NULL) { - fprintf(stderr, "A disk image must be given for 'hda' when booting " - "a Linux kernel\n"); -- exit(1); - } - - memset(bootsect, 0, sizeof(bootsect)); diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/06_exit_segfault.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/06_exit_segfault.patch deleted file mode 100644 index 06123d0626..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/06_exit_segfault.patch +++ /dev/null @@ -1,45 +0,0 @@ -#DPATCHLEVEL=0 ---- -# linux-user/main.c | 8 ++++---- -# 1 file changed, 4 insertions(+), 4 deletions(-) -# -Index: linux-user/main.c -=================================================================== ---- linux-user/main.c.orig 2007-12-03 23:47:25.000000000 +0000 -+++ linux-user/main.c 2007-12-03 23:47:41.000000000 +0000 -@@ -714,7 +714,7 @@ void cpu_loop (CPUSPARCState *env) - default: - printf ("Unhandled trap: 0x%x\n", trapnr); - cpu_dump_state(env, stderr, fprintf, 0); -- exit (1); -+ _exit (1); - } - process_pending_signals (env); - } -@@ -1634,7 +1634,7 @@ void cpu_loop (CPUState *env) - default: - printf ("Unhandled trap: 0x%x\n", trapnr); - cpu_dump_state(env, stderr, fprintf, 0); -- exit (1); -+ _exit (1); - } - process_pending_signals (env); - } -@@ -1954,7 +1954,7 @@ int main(int argc, char **argv) - 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, "s")) { -@@ -1973,7 +1973,7 @@ int main(int argc, char **argv) - 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")) { - gdbstub_port = atoi(argv[optind++]); diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/10_signal_jobs.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/10_signal_jobs.patch deleted file mode 100644 index 34282adc9d..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/10_signal_jobs.patch +++ /dev/null @@ -1,26 +0,0 @@ -#DPATCHLEVEL=0 ---- -# linux-user/signal.c | 7 ++++++- -# 1 file changed, 6 insertions(+), 1 deletion(-) -# -Index: linux-user/signal.c -=================================================================== ---- linux-user/signal.c.orig 2007-12-03 15:40:26.000000000 +0000 -+++ linux-user/signal.c 2007-12-03 15:55:49.000000000 +0000 -@@ -364,10 +364,15 @@ int queue_signal(int sig, target_siginfo - k = &sigact_table[sig - 1]; - handler = k->sa._sa_handler; - if (handler == TARGET_SIG_DFL) { -+ if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) { -+ kill(getpid(),SIGSTOP); -+ return 0; -+ } else - /* default handler : ignore some signal. The other are fatal */ - if (sig != TARGET_SIGCHLD && - sig != TARGET_SIGURG && -- sig != TARGET_SIGWINCH) { -+ sig != TARGET_SIGWINCH && -+ sig != TARGET_SIGCONT) { - force_sig(sig); - } else { - return 0; /* indicate ignored */ diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/11_signal_sigaction.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/11_signal_sigaction.patch deleted file mode 100644 index 33c5e8b12d..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/11_signal_sigaction.patch +++ /dev/null @@ -1,21 +0,0 @@ -#DPATCHLEVEL=0 ---- -# linux-user/signal.c | 5 +++++ -# 1 file changed, 5 insertions(+) -# -Index: linux-user/signal.c -=================================================================== ---- linux-user/signal.c.orig 2007-12-03 23:47:44.000000000 +0000 -+++ linux-user/signal.c 2007-12-03 23:47:46.000000000 +0000 -@@ -512,6 +512,11 @@ int do_sigaction(int sig, const struct t - - if (sig < 1 || sig > TARGET_NSIG || sig == SIGKILL || sig == SIGSTOP) - return -EINVAL; -+ -+ /* no point doing the stuff as those are not allowed for sigaction */ -+ if ((sig == TARGET_SIGKILL) || (sig == TARGET_SIGSTOP)) -+ return -EINVAL; -+ - k = &sigact_table[sig - 1]; - #if defined(DEBUG_SIGNAL) - fprintf(stderr, "sigaction sig=%d act=0x%08x, oact=0x%08x\n", diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/22_net_tuntap_stall.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/22_net_tuntap_stall.patch deleted file mode 100644 index 6017df0f6d..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/22_net_tuntap_stall.patch +++ /dev/null @@ -1,18 +0,0 @@ -#DPATCHLEVEL=0 ---- -# vl.c | 2 +- -# 1 file changed, 1 insertion(+), 1 deletion(-) -# -Index: vl.c -=================================================================== ---- vl.c.orig 2007-12-03 23:47:36.000000000 +0000 -+++ vl.c 2007-12-03 23:47:48.000000000 +0000 -@@ -4023,7 +4023,7 @@ static int tap_open(char *ifname, int if - return -1; - } - memset(&ifr, 0, sizeof(ifr)); -- ifr.ifr_flags = IFF_TAP | IFF_NO_PI; -+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE; - if (ifname[0] != '\0') - pstrcpy(ifr.ifr_name, IFNAMSIZ, ifname); - else diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/31_syscalls.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/31_syscalls.patch deleted file mode 100644 index 95a7332ee8..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/31_syscalls.patch +++ /dev/null @@ -1,48 +0,0 @@ -#DPATCHLEVEL=0 ---- -# linux-user/syscall.c | 11 ++++++++--- -# 1 file changed, 8 insertions(+), 3 deletions(-) -# -Index: linux-user/syscall.c -=================================================================== ---- linux-user/syscall.c.orig 2007-12-03 19:32:56.000000000 +0000 -+++ linux-user/syscall.c 2007-12-03 19:33:41.000000000 +0000 -@@ -250,6 +250,7 @@ extern int getresuid(uid_t *, uid_t *, u - extern int setresgid(gid_t, gid_t, gid_t); - extern int getresgid(gid_t *, gid_t *, gid_t *); - extern int setgroups(int, gid_t *); -+extern int uselib(const char*); - - #define ERRNO_TABLE_SIZE 1200 - -@@ -4024,7 +4025,8 @@ abi_long do_syscall(void *cpu_env, int n - #endif - #ifdef TARGET_NR_uselib - case TARGET_NR_uselib: -- goto unimplemented; -+ ret = get_errno(uselib(path((const char*)arg1))); -+ break; - #endif - #ifdef TARGET_NR_swapon - case TARGET_NR_swapon: -@@ -5289,7 +5291,9 @@ abi_long do_syscall(void *cpu_env, int n - goto unimplemented; - #ifdef TARGET_NR_mincore - case TARGET_NR_mincore: -- goto unimplemented; -+ /*page_unprotect_range((void*)arg3, ((size_t)arg2 + TARGET_PAGE_SIZE - 1) / TARGET_PAGE_SIZE);*/ -+ ret = get_errno(mincore((void*)arg1, (size_t)arg2, (unsigned char*)arg3)); -+ break; - #endif - #ifdef TARGET_NR_madvise - case TARGET_NR_madvise: -@@ -5429,7 +5433,8 @@ abi_long do_syscall(void *cpu_env, int n - break; - #ifdef TARGET_NR_readahead - case TARGET_NR_readahead: -- goto unimplemented; -+ ret = get_errno(readahead((int)arg1, (off64_t)arg2, (size_t)arg3)); -+ break; - #endif - #ifdef TARGET_NR_setxattr - case TARGET_NR_setxattr: diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/32_syscall_sysctl.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/32_syscall_sysctl.patch deleted file mode 100644 index 5e8dd75b0e..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/32_syscall_sysctl.patch +++ /dev/null @@ -1,55 +0,0 @@ -#DPATCHLEVEL=0 ---- -# linux-user/syscall.c | 32 +++++++++++++++++++++++++++++--- -# 1 file changed, 29 insertions(+), 3 deletions(-) -# -Index: linux-user/syscall.c -=================================================================== ---- linux-user/syscall.c.orig 2007-12-03 15:56:24.000000000 +0000 -+++ linux-user/syscall.c 2007-12-03 15:57:36.000000000 +0000 -@@ -52,6 +52,7 @@ - //#include - #include - #include -+#include - - #define termios host_termios - #define winsize host_winsize -@@ -4739,9 +4740,34 @@ abi_long do_syscall(void *cpu_env, int n - break; - #endif - case TARGET_NR__sysctl: -- /* We don't implement this, but ENOTDIR is always a safe -- return value. */ -- ret = -TARGET_ENOTDIR; -+ { -+ struct __sysctl_args *args = (struct __sysctl_args *) arg1; -+ int *name_target, *name, nlen, *oldlenp, oldlen, newlen, i; -+ void *oldval, *newval; -+ -+ name_target = (int *) tswapl((long) args->name); -+ nlen = tswapl(args->nlen); -+ oldval = (void *) tswapl((long) args->oldval); -+ oldlenp = (int *) tswapl((long) args->oldlenp); -+ oldlen = tswapl(*oldlenp); -+ newval = (void *) tswapl((long) args->newval); -+ newlen = tswapl(args->newlen); -+ -+ name = alloca(nlen * sizeof (int)); -+ for (i = 0; i < nlen; i++) -+ name[i] = tswapl(name_target[i]); -+ -+ if (nlen == 2 && name[0] == CTL_KERN && name[1] == KERN_VERSION) { -+ ret = get_errno( -+ sysctl(name, nlen, oldval, &oldlen, newval, newlen)); -+ if (!is_error(ret)) { -+ *oldlenp = tswapl(oldlen); -+ } -+ } else { -+ gemu_log("qemu: Unsupported sysctl name\n"); -+ ret = -ENOSYS; -+ } -+ } - break; - case TARGET_NR_sched_setparam: - { diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/33_syscall_ppc_clone.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/33_syscall_ppc_clone.patch deleted file mode 100644 index 3f733b6ab8..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/33_syscall_ppc_clone.patch +++ /dev/null @@ -1,22 +0,0 @@ -#DPATCHLEVEL=0 ---- -# linux-user/syscall.c | 6 +----- -# 1 file changed, 1 insertion(+), 5 deletions(-) -# -Index: linux-user/syscall.c -=================================================================== ---- linux-user/syscall.c.orig 2007-12-03 15:58:11.000000000 +0000 -+++ linux-user/syscall.c 2007-12-03 15:58:46.000000000 +0000 -@@ -2750,11 +2750,7 @@ int do_fork(CPUState *env, unsigned int - if (!newsp) - newsp = env->gpr[1]; - new_env->gpr[1] = newsp; -- { -- int i; -- for (i = 7; i < 32; i++) -- new_env->gpr[i] = 0; -- } -+ new_env->gpr[3] = 0; - #elif defined(TARGET_SH4) - if (!newsp) - newsp = env->gregs[15]; diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/39_syscall_fadvise64.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/39_syscall_fadvise64.patch deleted file mode 100644 index 54ee3e0948..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/39_syscall_fadvise64.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- - linux-user/syscall.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -Index: linux-user/syscall.c -=================================================================== ---- linux-user/syscall.c.orig 2007-12-03 19:33:47.000000000 +0000 -+++ linux-user/syscall.c 2007-12-03 19:33:48.000000000 +0000 -@@ -5317,6 +5317,12 @@ abi_long do_syscall(void *cpu_env, int n - ret = get_errno(mincore((void*)arg1, (size_t)arg2, (unsigned char*)arg3)); - break; - #endif -+#ifdef TARGET_NR_fadvise64_64 -+ case TARGET_NR_fadvise64_64: -+ /* Just return success */ -+ ret = get_errno(0); -+ break; -+#endif - #ifdef TARGET_NR_madvise - case TARGET_NR_madvise: - /* A straight passthrough may not be safe because qemu sometimes diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/41_arm_fpa_sigfpe.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/41_arm_fpa_sigfpe.patch deleted file mode 100644 index cea3afc7ff..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/41_arm_fpa_sigfpe.patch +++ /dev/null @@ -1,104 +0,0 @@ -#DPATCHLEVEL=0 ---- -# linux-user/main.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++- -# target-arm/nwfpe/fpa11.c | 7 ++++++ -# 2 files changed, 57 insertions(+), 1 deletion(-) -# -Index: linux-user/main.c -=================================================================== ---- linux-user/main.c.orig 2007-12-03 15:59:10.000000000 +0000 -+++ linux-user/main.c 2007-12-03 16:01:27.000000000 +0000 -@@ -377,18 +377,67 @@ void cpu_loop(CPUARMState *env) - { - TaskState *ts = env->opaque; - uint32_t opcode; -+ int rc; - - /* we handle the FPU emulation here, as Linux */ - /* we get the opcode */ - /* FIXME - what to do if get_user() fails? */ - get_user_u32(opcode, env->regs[15]); - -- if (EmulateAll(opcode, &ts->fpa, env) == 0) { -+ rc = EmulateAll(opcode, &ts->fpa, env); -+ if (rc == 0) { /* illegal instruction */ - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLOPN; - info._sifields._sigfault._addr = env->regs[15]; - queue_signal(info.si_signo, &info); -+ } else if (rc < 0) { /* FP exception */ -+ int arm_fpe=0; -+ -+ /* translate softfloat flags to FPSR flags */ -+ if (-rc & float_flag_invalid) -+ arm_fpe |= BIT_IOC; -+ if (-rc & float_flag_divbyzero) -+ arm_fpe |= BIT_DZC; -+ if (-rc & float_flag_overflow) -+ arm_fpe |= BIT_OFC; -+ if (-rc & float_flag_underflow) -+ arm_fpe |= BIT_UFC; -+ if (-rc & float_flag_inexact) -+ arm_fpe |= BIT_IXC; -+ -+ FPSR fpsr = ts->fpa.fpsr; -+ //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe); -+ -+ if (fpsr & (arm_fpe << 16)) { /* exception enabled? */ -+ info.si_signo = SIGFPE; -+ info.si_errno = 0; -+ -+ /* ordered by priority, least first */ -+ if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES; -+ if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND; -+ if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF; -+ if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV; -+ if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV; -+ -+ info._sifields._sigfault._addr = env->regs[15]; -+ queue_signal(info.si_signo, &info); -+ } else { -+ env->regs[15] += 4; -+ } -+ -+ /* accumulate unenabled exceptions */ -+ if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC)) -+ fpsr |= BIT_IXC; -+ if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC)) -+ fpsr |= BIT_UFC; -+ if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC)) -+ fpsr |= BIT_OFC; -+ if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC)) -+ fpsr |= BIT_DZC; -+ if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC)) -+ fpsr |= BIT_IOC; -+ ts->fpa.fpsr=fpsr; - } else { - /* increment PC */ - env->regs[15] += 4; -Index: target-arm/nwfpe/fpa11.c -=================================================================== ---- target-arm/nwfpe/fpa11.c.orig 2007-12-03 15:40:26.000000000 +0000 -+++ target-arm/nwfpe/fpa11.c 2007-12-03 15:59:11.000000000 +0000 -@@ -162,6 +162,8 @@ unsigned int EmulateAll(unsigned int opc - fpa11->initflag = 1; - } - -+ set_float_exception_flags(0, &fpa11->fp_status); -+ - if (TEST_OPCODE(opcode,MASK_CPRT)) - { - //fprintf(stderr,"emulating CPRT\n"); -@@ -191,6 +193,11 @@ unsigned int EmulateAll(unsigned int opc - } - - // restore_flags(flags); -+ if(nRc == 1 && get_float_exception_flags(&fpa11->fp_status)) -+ { -+ //printf("fef 0x%x\n",float_exception_flags); -+ nRc=-get_float_exception_flags(&fpa11->fp_status); -+ } - - //printf("returning %d\n",nRc); - return(nRc); diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/52_ne2000_return.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/52_ne2000_return.patch deleted file mode 100644 index e4ea33f2c6..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/52_ne2000_return.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- - hw/ne2000.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Index: qemu/hw/ne2000.c -=================================================================== ---- qemu.orig/hw/ne2000.c 2007-12-03 19:32:52.000000000 +0000 -+++ qemu/hw/ne2000.c 2007-12-03 19:33:55.000000000 +0000 -@@ -217,7 +217,7 @@ static int ne2000_can_receive(void *opaq - NE2000State *s = opaque; - - if (s->cmd & E8390_STOP) -- return 1; -+ return 0; - return !ne2000_buffer_full(s); - } - diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/61_safe_64bit_int.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/61_safe_64bit_int.patch deleted file mode 100644 index 9b1ace81a5..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/61_safe_64bit_int.patch +++ /dev/null @@ -1,27 +0,0 @@ -#DPATCHLEVEL=0 ---- -# dyngen-exec.h | 4 ++-- -# 1 file changed, 2 insertions(+), 2 deletions(-) -# -Index: dyngen-exec.h -=================================================================== ---- dyngen-exec.h.orig 2007-12-31 13:06:21.000000000 +0000 -+++ dyngen-exec.h 2007-12-31 13:08:54.000000000 +0000 -@@ -38,7 +38,7 @@ - // Linux/Sparc64 defines uint64_t - #if !(defined (__sparc_v9__) && defined(__linux__)) - /* XXX may be done for all 64 bits targets ? */ --#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__) -+#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__) || defined(__sparc__) - typedef unsigned long uint64_t; - #else - typedef unsigned long long uint64_t; -@@ -55,7 +55,7 @@ - typedef signed int int32_t; - // Linux/Sparc64 defines int64_t - #if !(defined (__sparc_v9__) && defined(__linux__)) --#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__) -+#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__) || defined(__sparc__) - typedef signed long int64_t; - #else - typedef signed long long int64_t; diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/63_sparc_build.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/63_sparc_build.patch deleted file mode 100644 index 37b38f641b..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/63_sparc_build.patch +++ /dev/null @@ -1,18 +0,0 @@ -#DPATCHLEVEL=0 ---- -# sparc.ld | 2 +- -# 1 file changed, 1 insertion(+), 1 deletion(-) -# -Index: sparc.ld -=================================================================== ---- sparc.ld.orig 2007-12-03 15:40:26.000000000 +0000 -+++ sparc.ld 2007-12-03 16:05:06.000000000 +0000 -@@ -6,7 +6,7 @@ ENTRY(_start) - SECTIONS - { - /* Read-only sections, merged into text segment: */ -- . = 0x60000000 + SIZEOF_HEADERS; -+ . = 0x60000000 + 0x400; - .interp : { *(.interp) } - .hash : { *(.hash) } - .dynsym : { *(.dynsym) } diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/64_ppc_asm_constraints.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/64_ppc_asm_constraints.patch deleted file mode 100644 index e4858b79d7..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/64_ppc_asm_constraints.patch +++ /dev/null @@ -1,18 +0,0 @@ -#DPATCHLEVEL=1 ---- -# cpu-all.h | 2 +- -# 1 file changed, 1 insertion(+), 1 deletion(-) -# -Index: qemu/cpu-all.h -=================================================================== ---- qemu.orig/cpu-all.h 2007-06-13 11:48:22.000000000 +0100 -+++ qemu/cpu-all.h 2007-06-13 11:51:56.000000000 +0100 -@@ -250,7 +250,7 @@ static inline void stw_le_p(void *ptr, i - static inline void stl_le_p(void *ptr, int v) - { - #ifdef __powerpc__ -- __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr)); -+ __asm__ __volatile__ ("stwbrx %0,0,%1" : : "r" (v), "r" (ptr) : "memory"); - #else - uint8_t *p = ptr; - p[0] = v; diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/65_kfreebsd.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/65_kfreebsd.patch deleted file mode 100644 index dfece800ac..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/65_kfreebsd.patch +++ /dev/null @@ -1,35 +0,0 @@ ---- - configure | 6 ++++++ - vl.c | 2 ++ - 2 files changed, 8 insertions(+) - -Index: configure -=================================================================== ---- configure.orig 2007-12-03 15:40:26.000000000 +0000 -+++ configure 2007-12-03 16:05:34.000000000 +0000 -@@ -129,6 +129,12 @@ if [ "$cpu" = "i386" -o "$cpu" = "x86_64 - kqemu="yes" - fi - ;; -+GNU/kFreeBSD) -+oss="yes" -+if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then -+ kqemu="yes" -+fi -+;; - FreeBSD) - bsd="yes" - oss="yes" -Index: vl.c -=================================================================== ---- vl.c.orig 2007-12-03 16:05:32.000000000 +0000 -+++ vl.c 2007-12-03 16:05:34.000000000 +0000 -@@ -97,6 +97,8 @@ - #include - #endif - #endif -+#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__) -+#include - #else - #include - int inet_aton(const char *cp, struct in_addr *ia); diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/66_tls_ld.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/66_tls_ld.patch deleted file mode 100644 index 54e02eff8b..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/66_tls_ld.patch +++ /dev/null @@ -1,55 +0,0 @@ ---- - arm.ld | 7 +++++++ - i386.ld | 7 +++++++ - 2 files changed, 14 insertions(+) - -Index: arm.ld -=================================================================== ---- arm.ld.orig 2007-06-13 11:48:22.000000000 +0100 -+++ arm.ld 2007-06-13 11:51:56.000000000 +0100 -@@ -26,6 +26,10 @@ SECTIONS - { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } - .rela.rodata : - { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } -+ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } -+ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } -+ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } -+ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } - .rel.got : { *(.rel.got) } - .rela.got : { *(.rela.got) } - .rel.ctors : { *(.rel.ctors) } -@@ -58,6 +62,9 @@ SECTIONS - .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } - __exidx_end = .; - .reginfo : { *(.reginfo) } -+ /* Thread Local Storage sections */ -+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } -+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. */ - . = ALIGN(0x100000) + (. & (0x100000 - 1)); -Index: i386.ld -=================================================================== ---- i386.ld.orig 2007-06-13 11:48:22.000000000 +0100 -+++ i386.ld 2007-06-13 11:51:56.000000000 +0100 -@@ -28,6 +28,10 @@ SECTIONS - { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } - .rela.rodata : - { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } -+ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } -+ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } -+ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } -+ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } - .rel.got : { *(.rel.got) } - .rela.got : { *(.rela.got) } - .rel.ctors : { *(.rel.ctors) } -@@ -53,6 +57,9 @@ SECTIONS - _etext = .; - PROVIDE (etext = .); - .fini : { *(.fini) } =0x47ff041f -+ /* Thread Local Storage sections */ -+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } -+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } - . = ALIGN(32 / 8); - PROVIDE (__preinit_array_start = .); - .preinit_array : { *(.preinit_array) } diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/91-oh-sdl-cursor.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/91-oh-sdl-cursor.patch deleted file mode 100644 index 0d60c1c306..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/91-oh-sdl-cursor.patch +++ /dev/null @@ -1,18 +0,0 @@ -=== modified file 'sdl.c' ---- - sdl.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Index: sdl.c -=================================================================== ---- sdl.c.orig 2007-12-03 19:32:15.000000000 +0000 -+++ sdl.c 2007-12-03 19:34:04.000000000 +0000 -@@ -247,7 +247,7 @@ static void sdl_hide_cursor(void) - - if (kbd_mouse_is_absolute()) { - SDL_ShowCursor(1); -- SDL_SetCursor(sdl_cursor_hidden); -+ /* SDL_SetCursor(sdl_cursor_hidden); */ - } else { - SDL_ShowCursor(0); - } diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/configure_symlinkpath_fix.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/configure_symlinkpath_fix.patch deleted file mode 100644 index 3ec304a38c..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/configure_symlinkpath_fix.patch +++ /dev/null @@ -1,28 +0,0 @@ -Index: qemu-0.9.1/configure -=================================================================== ---- qemu-0.9.1.orig/configure 2008-01-24 15:33:13.000000000 +0000 -+++ qemu-0.9.1/configure 2008-01-24 15:45:50.000000000 +0000 -@@ -209,15 +209,17 @@ - - # find source path - source_path=`dirname "$0"` -+source_path_used="no" -+workdir=`pwd` -+workdir=`readlink -f $workdir` - if [ -z "$source_path" ]; then -- source_path=`pwd` -+ source_path=$workdir - else - source_path=`cd "$source_path"; pwd` --fi --if test "$source_path" = `pwd` ; then -- source_path_used="no" --else -- source_path_used="yes" -+ source_path=`readlink -f $source_path` -+ if test "$source_path" != "$workdir" ; then -+ source_path_used="yes" -+ fi - fi - - werror="no" diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/disable-error-in-configure.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/disable-error-in-configure.patch deleted file mode 100644 index 017f9f6355..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/disable-error-in-configure.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- - configure | 2 -- - 1 file changed, 2 deletions(-) - -Index: qemu/configure -=================================================================== ---- qemu.orig/configure 2007-12-03 16:38:38.000000000 +0000 -+++ qemu/configure 2007-12-03 16:38:39.000000000 +0000 -@@ -323,8 +323,6 @@ for opt do - ;; - --disable-werror) werror="no" - ;; -- *) echo "ERROR: unknown option $opt"; show_help="yes" -- ;; - --disable-nptl) nptl="no" - ;; - esac diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/fix_segfault.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/fix_segfault.patch deleted file mode 100644 index 443c330650..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/fix_segfault.patch +++ /dev/null @@ -1,37 +0,0 @@ ---- - linux-user/syscall.c | 22 ---------------------- - 1 file changed, 22 deletions(-) - -Index: qemu/linux-user/syscall.c -=================================================================== ---- qemu.orig/linux-user/syscall.c 2007-12-03 23:40:11.000000000 +0000 -+++ qemu/linux-user/syscall.c 2007-12-03 23:40:21.000000000 +0000 -@@ -5695,28 +5695,6 @@ abi_long do_syscall(void *cpu_env, int n - goto unimplemented_nowarn; - #endif - --#ifdef TARGET_NR_clock_gettime -- case TARGET_NR_clock_gettime: -- { -- struct timespec ts; -- ret = get_errno(clock_gettime(arg1, &ts)); -- if (!is_error(ret)) { -- host_to_target_timespec(arg2, &ts); -- } -- break; -- } --#endif --#ifdef TARGET_NR_clock_getres -- case TARGET_NR_clock_getres: -- { -- struct timespec ts; -- ret = get_errno(clock_getres(arg1, &ts)); -- if (!is_error(ret)) { -- host_to_target_timespec(arg2, &ts); -- } -- break; -- } --#endif - - #if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address) - case TARGET_NR_set_tid_address: diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/no-strip.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/no-strip.patch deleted file mode 100644 index fc69b37e16..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/no-strip.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- qemu.orig/Makefile 2008-01-29 23:16:27.000000000 -0800 -+++ qemu-0.9.1/Makefile 2008-01-29 23:16:38.000000000 -0800 -@@ -174,7 +174,7 @@ - install: all $(if $(BUILD_DOCS),install-doc) - mkdir -p "$(DESTDIR)$(bindir)" - ifneq ($(TOOLS),) -- $(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)" -+ $(INSTALL) -m 755 $(TOOLS) "$(DESTDIR)$(bindir)" - endif - mkdir -p "$(DESTDIR)$(datadir)" - for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \ ---- qemu.orig/Makefile.target 2008-01-29 23:16:27.000000000 -0800 -+++ qemu-0.9.1/Makefile.target 2008-01-29 23:17:33.000000000 -0800 -@@ -632,7 +632,7 @@ - - install: all - ifneq ($(PROGS),) -- $(INSTALL) -m 755 -s $(PROGS) "$(DESTDIR)$(bindir)" -+ $(INSTALL) -m 755 $(PROGS) "$(DESTDIR)$(bindir)" - endif - - ifneq ($(wildcard .depend),) diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-0.9.0-nptl-update.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-0.9.0-nptl-update.patch deleted file mode 100644 index ebc996e873..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-0.9.0-nptl-update.patch +++ /dev/null @@ -1,219 +0,0 @@ ---- - linux-user/main.c | 7 ++- - linux-user/syscall.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++----- - 2 files changed, 111 insertions(+), 10 deletions(-) - -Index: qemu/linux-user/main.c -=================================================================== ---- qemu.orig/linux-user/main.c 2007-12-03 19:34:09.000000000 +0000 -+++ qemu/linux-user/main.c 2007-12-03 23:44:45.000000000 +0000 -@@ -391,7 +391,7 @@ do_kernel_trap(CPUARMState *env) - cpu_unlock(); - break; - case 0xffff0fe0: /* __kernel_get_tls */ -- env->regs[0] = env->cp15.c13_tls; -+ env->regs[0] = env->cp15.c13_tls2; - break; - default: - return 1; -@@ -2037,6 +2037,11 @@ int main(int argc, char **argv) - int drop_ld_preload = 0, environ_count = 0; - char **target_environ, **wrk, **dst; - -+ char *assume_kernel = getenv("QEMU_ASSUME_KERNEL"); -+ -+ if (assume_kernel) -+ setenv("LD_ASSUME_KERNEL", assume_kernel, 1); -+ - if (argc <= 1) - usage(); - -Index: qemu/linux-user/syscall.c -=================================================================== ---- qemu.orig/linux-user/syscall.c 2007-12-03 19:34:09.000000000 +0000 -+++ qemu/linux-user/syscall.c 2007-12-03 23:46:54.000000000 +0000 -@@ -61,6 +61,7 @@ - #define tchars host_tchars /* same as target */ - #define ltchars host_ltchars /* same as target */ - -+#include - #include - #include - #include -@@ -2694,7 +2695,6 @@ abi_long do_arch_prctl(CPUX86State *env, - return 0; - } - #endif -- - #endif /* defined(TARGET_I386) */ - - /* this stack is the equivalent of the kernel stack associated with a -@@ -2729,16 +2729,19 @@ int do_fork(CPUState *env, unsigned int - TaskState *ts; - uint8_t *new_stack; - CPUState *new_env; -- -+#if defined(TARGET_I386) -+ uint64_t *new_gdt_table; -+#endif - #ifdef USE_NPTL - unsigned int nptl_flags; - - if (flags & CLONE_PARENT_SETTID) - *parent_tidptr = gettid(); - #endif -- - if (flags & CLONE_VM) { - ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE); -+ if (!ts) -+ return -ENOMEM; - memset(ts, 0, sizeof(TaskState)); - new_stack = ts->stack; - ts->used = 1; -@@ -2750,6 +2753,29 @@ int do_fork(CPUState *env, unsigned int - #if defined(TARGET_I386) - if (!newsp) - newsp = env->regs[R_ESP]; -+ new_gdt_table = malloc(9 * 8); -+ if (!new_gdt_table) { -+ free(new_env); -+ return -ENOMEM; -+ } -+ /* Copy main GDT table from parent, but clear TLS entries */ -+ memcpy(new_gdt_table, g2h(env->gdt.base), 6 * 8); -+ memset(&new_gdt_table[6], 0, 3 * 8); -+ new_env->gdt.base = h2g(new_gdt_table); -+ if (flags & 0x00080000 /* CLONE_SETTLS */) { -+ ret = do_set_thread_area(new_env, new_env->regs[R_ESI]); -+ if (ret) { -+ free(new_gdt_table); -+ free(new_env); -+ return ret; -+ } -+ } -+ cpu_x86_load_seg(env, R_CS, new_env->regs[R_CS]); -+ cpu_x86_load_seg(env, R_DS, new_env->regs[R_DS]); -+ cpu_x86_load_seg(env, R_ES, new_env->regs[R_ES]); -+ cpu_x86_load_seg(env, R_SS, new_env->regs[R_SS]); -+ cpu_x86_load_seg(env, R_FS, new_env->regs[R_FS]); -+ cpu_x86_load_seg(env, R_GS, new_env->regs[R_GS]); - new_env->regs[R_ESP] = newsp; - new_env->regs[R_EAX] = 0; - #elif defined(TARGET_ARM) -@@ -3121,6 +3147,68 @@ static inline abi_long host_to_target_ti - unlock_user_struct(target_ts, target_addr, 1); - } - -+static long do_futex(target_ulong uaddr, int op, uint32_t val, -+ target_ulong utime, target_ulong uaddr2, -+ uint32_t val3) -+{ -+ struct timespec host_utime; -+ unsigned long val2 = utime; -+ -+ if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) { -+ target_to_host_timespec(&host_utime, utime); -+ val2 = (unsigned long)&host_utime; -+ } -+ -+#ifdef BSWAP_NEEDED -+ switch(op) { -+ case FUTEX_CMP_REQUEUE: -+ val3 = tswap32(val3); -+ case FUTEX_REQUEUE: -+ val2 = tswap32(val2); -+ case FUTEX_WAIT: -+ case FUTEX_WAKE: -+ val = tswap32(val); -+ case FUTEX_LOCK_PI: /* This one's icky, but comes out OK */ -+ case FUTEX_UNLOCK_PI: -+ break; -+ default: -+ gemu_log("qemu: Unsupported futex op %d\n", op); -+ return -ENOSYS; -+ } -+#if 0 /* No, it's worse than this */ -+ if (op == FUTEX_WAKE_OP) { -+ /* Need to munge the secondary operation (val3) */ -+ val3 = tswap32(val3); -+ int op2 = (val3 >> 28) & 7; -+ int cmp = (val3 >> 24) & 15; -+ int oparg = (val3 << 8) >> 20; -+ int cmparg = (val3 << 20) >> 20; -+ int shift = val3 & (FUTEX_OP_OPARG_SHIFT << 28); -+ -+ if (shift) -+ oparg = (oparg & 7) + 24 - (oparg & 24); -+ else oparg = -+ if (op2 == FUTEX_OP_ADD) { -+ gemu_log("qemu: Unsupported wrong-endian FUTEX_OP_ADD\n"); -+ return -ENOSYS; -+ } -+ if (cmparg == FUTEX_OP_CMP_LT || cmparg == FUTEX_OP_CMP_GE || -+ cmparg == FUTEX_OP_CMP_LE || cmparg == FUTEX_OP_CMP_GT) { -+ gemu_log("qemu: Unsupported wrong-endian futex cmparg %d\n", cmparg); -+ return -ENOSYS; -+ } -+ val3 = shift | (op2<<28) | (cmp<<24) | (oparg<<12) | cmparg; -+ } -+#endif -+#endif -+ return syscall(__NR_futex, g2h(uaddr), op, val, val2, g2h(uaddr2), val3); -+} -+ -+int do_set_tid_address(target_ulong tidptr) -+{ -+ return syscall(__NR_set_tid_address, g2h(tidptr)); -+} -+ - /* do_syscall() should always have a single exit point at the end so - that actions, such as logging of syscall results, can be performed. - All errnos that do_syscall() returns must be -TARGET_. */ -@@ -3145,7 +3233,7 @@ abi_long do_syscall(void *cpu_env, int n - _mcleanup(); - #endif - gdb_exit(cpu_env, arg1); -- /* XXX: should free thread stack and CPU env */ -+ /* XXX: should free thread stack, GDT and CPU env */ - _exit(arg1); - ret = 0; /* avoid warning */ - break; -@@ -5569,6 +5657,9 @@ abi_long do_syscall(void *cpu_env, int n - #elif defined(TARGET_I386) && defined(TARGET_ABI32) - ret = do_set_thread_area(cpu_env, arg1); - break; -+#elif TARGET_i386 -+ ret = get_errno(do_set_thread_area(cpu_env, arg1)); -+ break; - #else - goto unimplemented_nowarn; - #endif -@@ -5586,6 +5677,16 @@ abi_long do_syscall(void *cpu_env, int n - goto unimplemented_nowarn; - #endif - -+#ifdef TARGET_NR_futex -+ case TARGET_NR_futex: -+ ret = get_errno(do_futex(arg1, arg2, arg3, arg4, arg5, arg6)); -+ break; -+#endif -+#ifdef TARGET_NR_set_robust_list -+ case TARGET_NR_set_robust_list: -+ goto unimplemented_nowarn; -+#endif -+ - #ifdef TARGET_NR_clock_gettime - case TARGET_NR_clock_gettime: - { -@@ -5627,11 +5728,6 @@ abi_long do_syscall(void *cpu_env, int n - break; - #endif - --#ifdef TARGET_NR_set_robust_list -- case TARGET_NR_set_robust_list: -- goto unimplemented_nowarn; --#endif -- - #if defined(TARGET_NR_utimensat) && defined(__NR_utimensat) - case TARGET_NR_utimensat: - { diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-0.9.0-nptl.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-0.9.0-nptl.patch deleted file mode 100644 index 4a87d8d637..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-0.9.0-nptl.patch +++ /dev/null @@ -1,854 +0,0 @@ -These are Paul Brook's patches to QEMU-0.8.2 to enable the running of single -ARM binaries under QEMU's user-emulation mode. Without them, QEMU-0.8.1 -immediately dies saying: - Error: f0005 - qemu: uncaught target signal 6 (Aborted) - exiting -while qemu-0.8.2 dies saying: - qemu: Unsupported syscall: 983045 - cannot set up thread-local storage: unknown error - -This file is a rediffing of the patches visible at -https://nowt.dyndns.org/patch.qemu_nptl on 27 Sept 2006 -which "patch" fails to apply automatically. -See also http://lists.gnu.org/archive/html/qemu-devel/2006-09/msg00194.html - - Martin Guy, 27 Sept 2006 - ---- - configure | 25 ++++++ - exec-all.h | 165 ------------------------------------------ - linux-user/arm/syscall.h | 4 - - linux-user/main.c | 94 +++++++++++++++++++++--- - linux-user/qemu.h | 3 - linux-user/syscall.c | 91 ++++++++++++++++++++++- - qemu_spinlock.h | 181 +++++++++++++++++++++++++++++++++++++++++++++++ - target-arm/cpu.h | 10 ++ - target-arm/op.c | 6 + - target-arm/translate.c | 9 ++ - 10 files changed, 405 insertions(+), 183 deletions(-) - -Index: qemu/configure -=================================================================== ---- qemu.orig/configure 2008-04-09 23:02:37.000000000 +0100 -+++ qemu/configure 2008-04-09 23:06:36.000000000 +0100 -@@ -109,6 +109,7 @@ - build_docs="no" - uname_release="" - curses="yes" -+nptl="yes" - - # OS specific - targetos=`uname -s` -@@ -334,6 +335,8 @@ - ;; - *) echo "ERROR: unknown option $opt"; show_help="yes" - ;; -+ --disable-nptl) nptl="no" -+ ;; - esac - done - -@@ -429,6 +432,7 @@ - echo " --disable-linux-user disable all linux usermode emulation targets" - echo " --enable-darwin-user enable all darwin usermode emulation targets" - echo " --disable-darwin-user disable all darwin usermode emulation targets" -+echo " --disable-nptl disable usermode NPTL guest support" - echo " --fmod-lib path to FMOD library" - echo " --fmod-inc path to FMOD includes" - echo " --enable-uname-release=R Return R for uname -r in usermode emulation" -@@ -595,6 +599,23 @@ - } - EOF - -+# check NPTL support -+cat > $TMPC < -+void foo() -+{ -+#ifndef CLONE_SETTLS -+#error bork -+#endif -+} -+EOF -+ -+if $cc -c -o $TMPO $TMPC 2> /dev/null ; then -+ : -+else -+ nptl="no" -+fi -+ - ########################################## - # SDL probe - -@@ -778,6 +799,7 @@ - echo "Documentation $build_docs" - [ ! -z "$uname_release" ] && \ - echo "uname -r $uname_release" -+echo "NPTL support $nptl" - - if test $sdl_too_old = "yes"; then - echo "-> Your SDL version is too old - please upgrade to have SDL support" -@@ -1115,6 +1137,9 @@ - echo "TARGET_ARCH=arm" >> $config_mak - echo "#define TARGET_ARCH \"arm\"" >> $config_h - echo "#define TARGET_ARM 1" >> $config_h -+ if test "$nptl" = "yes" ; then -+ echo "#define USE_NPTL 1" >> $config_h -+ fi - bflt="yes" - elif test "$target_cpu" = "sparc" ; then - echo "TARGET_ARCH=sparc" >> $config_mak -Index: qemu/exec-all.h -=================================================================== ---- qemu.orig/exec-all.h 2008-04-09 22:39:38.000000000 +0100 -+++ qemu/exec-all.h 2008-04-09 23:05:55.000000000 +0100 -@@ -297,170 +297,7 @@ - extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; - extern void *io_mem_opaque[IO_MEM_NB_ENTRIES]; - --#if defined(__powerpc__) --static inline int testandset (int *p) --{ -- int ret; -- __asm__ __volatile__ ( -- "0: lwarx %0,0,%1\n" -- " xor. %0,%3,%0\n" -- " bne 1f\n" -- " stwcx. %2,0,%1\n" -- " bne- 0b\n" -- "1: " -- : "=&r" (ret) -- : "r" (p), "r" (1), "r" (0) -- : "cr0", "memory"); -- return ret; --} --#elif defined(__i386__) --static inline int testandset (int *p) --{ -- long int readval = 0; -- -- __asm__ __volatile__ ("lock; cmpxchgl %2, %0" -- : "+m" (*p), "+a" (readval) -- : "r" (1) -- : "cc"); -- return readval; --} --#elif defined(__x86_64__) --static inline int testandset (int *p) --{ -- long int readval = 0; -- -- __asm__ __volatile__ ("lock; cmpxchgl %2, %0" -- : "+m" (*p), "+a" (readval) -- : "r" (1) -- : "cc"); -- return readval; --} --#elif defined(__s390__) --static inline int testandset (int *p) --{ -- int ret; -- -- __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n" -- " jl 0b" -- : "=&d" (ret) -- : "r" (1), "a" (p), "0" (*p) -- : "cc", "memory" ); -- return ret; --} --#elif defined(__alpha__) --static inline int testandset (int *p) --{ -- int ret; -- unsigned long one; -- -- __asm__ __volatile__ ("0: mov 1,%2\n" -- " ldl_l %0,%1\n" -- " stl_c %2,%1\n" -- " beq %2,1f\n" -- ".subsection 2\n" -- "1: br 0b\n" -- ".previous" -- : "=r" (ret), "=m" (*p), "=r" (one) -- : "m" (*p)); -- return ret; --} --#elif defined(__sparc__) --static inline int testandset (int *p) --{ -- int ret; -- -- __asm__ __volatile__("ldstub [%1], %0" -- : "=r" (ret) -- : "r" (p) -- : "memory"); -- -- return (ret ? 1 : 0); --} --#elif defined(__arm__) --static inline int testandset (int *spinlock) --{ -- register unsigned int ret; -- __asm__ __volatile__("swp %0, %1, [%2]" -- : "=r"(ret) -- : "0"(1), "r"(spinlock)); -- -- return ret; --} --#elif defined(__mc68000) --static inline int testandset (int *p) --{ -- char ret; -- __asm__ __volatile__("tas %1; sne %0" -- : "=r" (ret) -- : "m" (p) -- : "cc","memory"); -- return ret; --} --#elif defined(__ia64) -- --#include -- --static inline int testandset (int *p) --{ -- return __sync_lock_test_and_set (p, 1); --} --#elif defined(__mips__) --static inline int testandset (int *p) --{ -- int ret; -- -- __asm__ __volatile__ ( -- " .set push \n" -- " .set noat \n" -- " .set mips2 \n" -- "1: li $1, 1 \n" -- " ll %0, %1 \n" -- " sc $1, %1 \n" -- " beqz $1, 1b \n" -- " .set pop " -- : "=r" (ret), "+R" (*p) -- : -- : "memory"); -- -- return ret; --} --#else --#error unimplemented CPU support --#endif -- --typedef int spinlock_t; -- --#define SPIN_LOCK_UNLOCKED 0 -- --#if defined(CONFIG_USER_ONLY) --static inline void spin_lock(spinlock_t *lock) --{ -- while (testandset(lock)); --} -- --static inline void spin_unlock(spinlock_t *lock) --{ -- *lock = 0; --} -- --static inline int spin_trylock(spinlock_t *lock) --{ -- return !testandset(lock); --} --#else --static inline void spin_lock(spinlock_t *lock) --{ --} -- --static inline void spin_unlock(spinlock_t *lock) --{ --} -- --static inline int spin_trylock(spinlock_t *lock) --{ -- return 1; --} --#endif -+#include "qemu_spinlock.h" - - extern spinlock_t tb_lock; - -Index: qemu/linux-user/arm/syscall.h -=================================================================== ---- qemu.orig/linux-user/arm/syscall.h 2007-11-27 12:09:33.000000000 +0000 -+++ qemu/linux-user/arm/syscall.h 2008-04-09 23:05:55.000000000 +0100 -@@ -28,7 +28,9 @@ - #define ARM_SYSCALL_BASE 0x900000 - #define ARM_THUMB_SYSCALL 0 - --#define ARM_NR_cacheflush (ARM_SYSCALL_BASE + 0xf0000 + 2) -+#define ARM_NR_BASE 0xf0000 -+#define ARM_NR_cacheflush (ARM_NR_BASE + 2) -+#define ARM_NR_set_tls (ARM_NR_BASE + 5) - - #define ARM_NR_semihosting 0x123456 - #define ARM_NR_thumb_semihosting 0xAB -Index: qemu/linux-user/main.c -=================================================================== ---- qemu.orig/linux-user/main.c 2008-04-09 23:02:37.000000000 +0100 -+++ qemu/linux-user/main.c 2008-04-09 23:05:55.000000000 +0100 -@@ -364,6 +364,50 @@ - } - } - -+/* Handle a jump to the kernel code page. */ -+static int -+do_kernel_trap(CPUARMState *env) -+{ -+ uint32_t addr; -+ uint32_t *ptr; -+ uint32_t cpsr; -+ -+ switch (env->regs[15]) { -+ case 0xffff0fc0: /* __kernel_cmpxchg */ -+ /* XXX: This only works between threads, not between processes. -+ Use native atomic operations. */ -+ /* ??? This probably breaks horribly if the access segfaults. */ -+ cpu_lock(); -+ ptr = (uint32_t *)env->regs[2]; -+ cpsr = cpsr_read(env); -+ if (*ptr == env->regs[0]) { -+ *ptr = env->regs[1]; -+ env->regs[0] = 0; -+ cpsr |= CPSR_C; -+ } else { -+ env->regs[0] = -1; -+ cpsr &= ~CPSR_C; -+ } -+ cpsr_write(env, cpsr, CPSR_C); -+ cpu_unlock(); -+ break; -+ case 0xffff0fe0: /* __kernel_get_tls */ -+ env->regs[0] = env->cp15.c13_tls; -+ break; -+ default: -+ return 1; -+ } -+ /* Jump back to the caller. */ -+ addr = env->regs[14]; -+ if (addr & 1) { -+ env->thumb = 1; -+ addr &= ~1; -+ } -+ env->regs[15] = addr; -+ -+ return 0; -+} -+ - void cpu_loop(CPUARMState *env) - { - int trapnr; -@@ -474,10 +518,8 @@ - } - } - -- if (n == ARM_NR_cacheflush) { -- arm_cache_flush(env->regs[0], env->regs[1]); -- } else if (n == ARM_NR_semihosting -- || n == ARM_NR_thumb_semihosting) { -+ if (n == ARM_NR_semihosting -+ || n == ARM_NR_thumb_semihosting) { - env->regs[0] = do_arm_semihosting (env); - } else if (n == 0 || n >= ARM_SYSCALL_BASE - || (env->thumb && n == ARM_THUMB_SYSCALL)) { -@@ -488,14 +530,34 @@ - n -= ARM_SYSCALL_BASE; - env->eabi = 0; - } -- env->regs[0] = do_syscall(env, -- n, -- env->regs[0], -- env->regs[1], -- env->regs[2], -- env->regs[3], -- env->regs[4], -- env->regs[5]); -+ if ( n > ARM_NR_BASE) { -+ switch (n) -+ { -+ case ARM_NR_cacheflush: -+ arm_cache_flush(env->regs[0], env->regs[1]); -+ break; -+#ifdef USE_NPTL -+ case ARM_NR_set_tls: -+ cpu_set_tls(env, env->regs[0]); -+ env->regs[0] = 0; -+ break; -+#endif -+ default: -+ printf ("Error: Bad syscall: %x\n", n); -+ goto error; -+ } -+ } -+ else -+ { -+ env->regs[0] = do_syscall(env, -+ n, -+ env->regs[0], -+ env->regs[1], -+ env->regs[2], -+ env->regs[3], -+ env->regs[4], -+ env->regs[5]); -+ } - } else { - goto error; - } -@@ -534,6 +596,10 @@ - } - } - break; -+ case EXCP_KERNEL_TRAP: -+ if (do_kernel_trap(env)) -+ goto error; -+ break; - default: - error: - fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", -@@ -2402,6 +2468,10 @@ - ts->heap_base = info->brk; - /* This will be filled in on the first SYS_HEAPINFO call. */ - ts->heap_limit = 0; -+ /* Register the magic kernel code page. The cpu will generate a -+ special exception when it tries to execute code here. We can't -+ put real code here because it may be in use by the host kernel. */ -+ page_set_flags(0xffff0000, 0xffff0fff, 0); - #endif - - if (gdbstub_port) { -Index: qemu/linux-user/qemu.h -=================================================================== ---- qemu.orig/linux-user/qemu.h 2008-01-02 15:48:21.000000000 +0000 -+++ qemu/linux-user/qemu.h 2008-04-09 23:05:55.000000000 +0100 -@@ -107,6 +107,9 @@ - uint32_t heap_base; - uint32_t heap_limit; - #endif -+#ifdef USE_NPTL -+ uint32_t *child_tidptr; -+#endif - int used; /* non zero if used */ - struct image_info *info; - uint8_t stack[0]; -Index: qemu/linux-user/syscall.c -=================================================================== ---- qemu.orig/linux-user/syscall.c 2008-04-09 23:02:38.000000000 +0100 -+++ qemu/linux-user/syscall.c 2008-04-09 23:05:55.000000000 +0100 -@@ -71,9 +71,18 @@ - #include - - #include "qemu.h" -+#include "qemu_spinlock.h" - - //#define DEBUG - -+#ifdef USE_NPTL -+#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \ -+ CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID) -+#else -+/* XXX: Hardcode the above values. */ -+#define CLONE_NPTL_FLAGS2 0 -+#endif -+ - #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \ - || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS) - /* 16 bit uid wrappers emulation */ -@@ -2702,9 +2711,19 @@ - thread/process */ - #define NEW_STACK_SIZE 8192 - -+#ifdef USE_NPTL -+static spinlock_t nptl_lock = SPIN_LOCK_UNLOCKED; -+#endif -+ - static int clone_func(void *arg) - { - CPUState *env = arg; -+#ifdef HAVE_NPTL -+ /* Wait until the parent has finshed initializing the tls state. */ -+ while (!spin_trylock(&nptl_lock)) -+ usleep(1); -+ spin_unlock(&nptl_lock); -+#endif - cpu_loop(env); - /* never exits */ - return 0; -@@ -2712,13 +2731,22 @@ - - /* do_fork() Must return host values and target errnos (unlike most - do_*() functions). */ --int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp) -+int do_fork(CPUState *env, unsigned int flags, unsigned long newsp, -+ uint32_t *parent_tidptr, void *newtls, -+ uint32_t *child_tidptr) - { - int ret; - TaskState *ts; - uint8_t *new_stack; - CPUState *new_env; - -+#ifdef USE_NPTL -+ unsigned int nptl_flags; -+ -+ if (flags & CLONE_PARENT_SETTID) -+ *parent_tidptr = gettid(); -+#endif -+ - if (flags & CLONE_VM) { - ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE); - memset(ts, 0, sizeof(TaskState)); -@@ -2784,16 +2812,67 @@ - #error unsupported target CPU - #endif - new_env->opaque = ts; -+#ifdef USE_NPTL -+ nptl_flags = flags; -+ flags &= ~CLONE_NPTL_FLAGS2; -+ -+ if (nptl_flags & CLONE_CHILD_CLEARTID) { -+ ts->child_tidptr = child_tidptr; -+ } -+ -+ if (nptl_flags & CLONE_SETTLS) -+ cpu_set_tls (new_env, newtls); -+ -+ /* Grab the global cpu lock so that the thread setup appears -+ atomic. */ -+ if (nptl_flags & CLONE_CHILD_SETTID) -+ spin_lock(&nptl_lock); -+ -+#else -+ if (flags & CLONE_NPTL_FLAGS2) -+ return -EINVAL; -+#endif -+ -+ if (CLONE_VFORK & flags) -+ flags ^= CLONE_VM; - #ifdef __ia64__ - ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); - #else - ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); - #endif -+#ifdef USE_NPTL -+ if (ret != -1) { -+ if (nptl_flags & CLONE_CHILD_SETTID) -+ *child_tidptr = ret; -+ } -+ -+ /* Allow the child to continue. */ -+ if (nptl_flags & CLONE_CHILD_SETTID) -+ spin_unlock(&nptl_lock); -+#endif - } else { - /* if no CLONE_VM, we consider it is a fork */ -- if ((flags & ~CSIGNAL) != 0) -+ if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0) - return -EINVAL; - ret = fork(); -+#ifdef USE_NPTL -+ /* There is a race condition here. The parent process could -+ theoretically read the TID in the child process before the child -+ tid is set. This would require using either ptrace -+ (not implemented) or having *_tidptr to point at a shared memory -+ mapping. We can't repeat the spinlock hack used above because -+ the child process gets its own copy of the lock. */ -+ if (ret == 0) { -+ /* Child Process. */ -+ if (flags & CLONE_CHILD_SETTID) -+ *child_tidptr = gettid(); -+ ts = (TaskState *)env->opaque; -+ if (flags & CLONE_CHILD_CLEARTID) -+ ts->child_tidptr = child_tidptr; -+ if (flags & CLONE_SETTLS) -+ cpu_set_tls (env, newtls); -+ } -+#endif - } - return ret; - } -@@ -3118,7 +3197,7 @@ - ret = do_brk(arg1); - break; - case TARGET_NR_fork: -- ret = get_errno(do_fork(cpu_env, SIGCHLD, 0)); -+ ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, NULL, NULL, NULL)); - break; - #ifdef TARGET_NR_waitpid - case TARGET_NR_waitpid: -@@ -4481,7 +4560,8 @@ - ret = get_errno(fsync(arg1)); - break; - case TARGET_NR_clone: -- ret = get_errno(do_fork(cpu_env, arg1, arg2)); -+ ret = get_errno(do_fork(cpu_env, arg1, arg2, (uint32_t *)arg3, -+ (void *)arg4, (uint32_t *)arg5)); - break; - #ifdef __NR_exit_group - /* new thread calls */ -@@ -4928,7 +5008,8 @@ - #endif - #ifdef TARGET_NR_vfork - case TARGET_NR_vfork: -- ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0)); -+ ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0, -+ NULL, NULL, NULL)); - break; - #endif - #ifdef TARGET_NR_ugetrlimit -Index: qemu/qemu_spinlock.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ qemu/qemu_spinlock.h 2008-04-09 23:05:55.000000000 +0100 -@@ -0,0 +1,181 @@ -+/* -+ * Atomic operation helper include -+ * -+ * Copyright (c) 2005 Fabrice Bellard -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef QEMU_SPINLOCK_H -+#define QEMU_SPINLOCK_H -+ -+#ifdef __powerpc__ -+static inline int testandset (int *p) -+{ -+ int ret; -+ __asm__ __volatile__ ( -+ "0: lwarx %0,0,%1\n" -+ " xor. %0,%3,%0\n" -+ " bne 1f\n" -+ " stwcx. %2,0,%1\n" -+ " bne- 0b\n" -+ "1: " -+ : "=&r" (ret) -+ : "r" (p), "r" (1), "r" (0) -+ : "cr0", "memory"); -+ return ret; -+} -+#endif -+ -+#ifdef __i386__ -+static inline int testandset (int *p) -+{ -+ long int readval = 0; -+ -+ __asm__ __volatile__ ("lock; cmpxchgl %2, %0" -+ : "+m" (*p), "+a" (readval) -+ : "r" (1) -+ : "cc"); -+ return readval; -+} -+#endif -+ -+#ifdef __x86_64__ -+static inline int testandset (int *p) -+{ -+ long int readval = 0; -+ -+ __asm__ __volatile__ ("lock; cmpxchgl %2, %0" -+ : "+m" (*p), "+a" (readval) -+ : "r" (1) -+ : "cc"); -+ return readval; -+} -+#endif -+ -+#ifdef __s390__ -+static inline int testandset (int *p) -+{ -+ int ret; -+ -+ __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n" -+ " jl 0b" -+ : "=&d" (ret) -+ : "r" (1), "a" (p), "0" (*p) -+ : "cc", "memory" ); -+ return ret; -+} -+#endif -+ -+#ifdef __alpha__ -+static inline int testandset (int *p) -+{ -+ int ret; -+ unsigned long one; -+ -+ __asm__ __volatile__ ("0: mov 1,%2\n" -+ " ldl_l %0,%1\n" -+ " stl_c %2,%1\n" -+ " beq %2,1f\n" -+ ".subsection 2\n" -+ "1: br 0b\n" -+ ".previous" -+ : "=r" (ret), "=m" (*p), "=r" (one) -+ : "m" (*p)); -+ return ret; -+} -+#endif -+ -+#ifdef __sparc__ -+static inline int testandset (int *p) -+{ -+ int ret; -+ -+ __asm__ __volatile__("ldstub [%1], %0" -+ : "=r" (ret) -+ : "r" (p) -+ : "memory"); -+ -+ return (ret ? 1 : 0); -+} -+#endif -+ -+#ifdef __arm__ -+static inline int testandset (int *spinlock) -+{ -+ register unsigned int ret; -+ __asm__ __volatile__("swp %0, %1, [%2]" -+ : "=r"(ret) -+ : "0"(1), "r"(spinlock)); -+ -+ return ret; -+} -+#endif -+ -+#ifdef __mc68000 -+static inline int testandset (int *p) -+{ -+ char ret; -+ __asm__ __volatile__("tas %1; sne %0" -+ : "=r" (ret) -+ : "m" (p) -+ : "cc","memory"); -+ return ret; -+} -+#endif -+ -+#ifdef __ia64 -+#include -+ -+static inline int testandset (int *p) -+{ -+ return __sync_lock_test_and_set (p, 1); -+} -+#endif -+ -+typedef int spinlock_t; -+ -+#define SPIN_LOCK_UNLOCKED 0 -+ -+#if defined(CONFIG_USER_ONLY) -+static inline void spin_lock(spinlock_t *lock) -+{ -+ while (testandset(lock)); -+} -+ -+static inline void spin_unlock(spinlock_t *lock) -+{ -+ *lock = 0; -+} -+ -+static inline int spin_trylock(spinlock_t *lock) -+{ -+ return !testandset(lock); -+} -+#else -+static inline void spin_lock(spinlock_t *lock) -+{ -+} -+ -+static inline void spin_unlock(spinlock_t *lock) -+{ -+} -+ -+static inline int spin_trylock(spinlock_t *lock) -+{ -+ return 1; -+} -+#endif -+ -+#endif -Index: qemu/target-arm/cpu.h -=================================================================== ---- qemu.orig/target-arm/cpu.h 2007-11-27 12:09:57.000000000 +0000 -+++ qemu/target-arm/cpu.h 2008-04-09 23:05:55.000000000 +0100 -@@ -38,6 +38,7 @@ - #define EXCP_FIQ 6 - #define EXCP_BKPT 7 - #define EXCP_EXCEPTION_EXIT 8 /* Return from v7M exception. */ -+#define EXCP_KERNEL_TRAP 9 /* Jumped to kernel code page. */ - - #define ARMV7M_EXCP_RESET 1 - #define ARMV7M_EXCP_NMI 2 -@@ -222,6 +223,15 @@ - void cpu_lock(void); - void cpu_unlock(void); - -+void cpu_lock(void); -+void cpu_unlock(void); -+#if defined(USE_NPTL) -+static inline void cpu_set_tls(CPUARMState *env, void *newtls) -+{ -+ env->cp15.c13_tls2 = (uint32_t)(long)newtls; -+} -+#endif -+ - #define CPSR_M (0x1f) - #define CPSR_T (1 << 5) - #define CPSR_F (1 << 6) -Index: qemu/target-arm/op.c -=================================================================== ---- qemu.orig/target-arm/op.c 2008-04-09 22:40:01.000000000 +0100 -+++ qemu/target-arm/op.c 2008-04-09 23:05:55.000000000 +0100 -@@ -994,6 +994,12 @@ - cpu_loop_exit(); - } - -+void OPPROTO op_kernel_trap(void) -+{ -+ env->exception_index = EXCP_KERNEL_TRAP; -+ cpu_loop_exit(); -+} -+ - /* VFP support. We follow the convention used for VFP instrunctions: - Single precition routines have a "s" suffix, double precision a - "d" suffix. */ -Index: qemu/target-arm/translate.c -=================================================================== ---- qemu.orig/target-arm/translate.c 2008-04-09 22:40:01.000000000 +0100 -+++ qemu/target-arm/translate.c 2008-04-09 23:05:55.000000000 +0100 -@@ -7496,7 +7496,14 @@ - gen_op_exception_exit(); - } - #endif -- -+#ifdef CONFIG_USER_ONLY -+ /* Intercept jump to the magic kernel page. */ -+ if (dc->pc > 0xffff0000) { -+ gen_op_kernel_trap(); -+ dc->is_jmp = DISAS_UPDATE; -+ break; -+ } -+#endif - if (env->nb_breakpoints > 0) { - for(j = 0; j < env->nb_breakpoints; j++) { - if (env->breakpoints[j] == dc->pc) { diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-amd64-32b-mapping-0.9.0.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-amd64-32b-mapping-0.9.0.patch deleted file mode 100644 index c7f36d8110..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-amd64-32b-mapping-0.9.0.patch +++ /dev/null @@ -1,37 +0,0 @@ ---- - linux-user/mmap.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -Index: qemu/linux-user/mmap.c -=================================================================== ---- qemu.orig/linux-user/mmap.c 2007-12-03 15:40:25.000000000 +0000 -+++ qemu/linux-user/mmap.c 2007-12-03 16:37:21.000000000 +0000 -@@ -29,6 +29,10 @@ - - //#define DEBUG_MMAP - -+#ifndef MAP_32BIT -+#define MAP_32BIT 0 -+#endif -+ - /* NOTE: all the constants are the HOST ones, but addresses are target. */ - int target_mprotect(abi_ulong start, abi_ulong len, int prot) - { -@@ -251,7 +255,7 @@ abi_long target_mmap(abi_ulong start, ab - especially important if qemu_host_page_size > - qemu_real_host_page_size */ - p = mmap(g2h(mmap_start), -- host_len, prot, flags | MAP_FIXED, fd, host_offset); -+ host_len, prot, flags | MAP_FIXED | MAP_32BIT, fd, host_offset); - if (p == MAP_FAILED) - return -1; - /* update start so that it points to the file position at 'offset' */ -@@ -406,7 +410,7 @@ abi_long target_mremap(abi_ulong old_add - unsigned long host_addr; - - /* XXX: use 5 args syscall */ -- host_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags); -+ host_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags | MAP_32BIT); - if (host_addr == -1) - return -1; - new_addr = h2g(host_addr); diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-n800-support.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-n800-support.patch deleted file mode 100644 index b1b6649efc..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/qemu-n800-support.patch +++ /dev/null @@ -1,13970 +0,0 @@ -diff --git a/Makefile b/Makefile -index c36a978..cb0cf7b 100644 ---- a/Makefile -+++ b/Makefile -@@ -51,7 +51,8 @@ OBJS+=block.o - - OBJS+=irq.o - OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o --OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o -+OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o twl92230.o -+OBJS+=tmp105.o - OBJS+=scsi-disk.o cdrom.o - OBJS+=scsi-generic.o - OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o usb-serial.o -diff --git a/Makefile.target b/Makefile.target -index d1deda1..48f31bc 100644 ---- a/Makefile.target -+++ b/Makefile.target -@@ -593,7 +593,9 @@ OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o - OBJS+= pflash_cfi01.o gumstix.o - OBJS+= spitz.o ide.o serial.o nand.o ecc.o - OBJS+= omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o -+OBJS+= omap2.o omap_dss.o - OBJS+= palm.o tsc210x.o -+OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o - OBJS+= mst_fpga.o mainstone.o - CPPFLAGS += -DHAS_AUDIO - endif -diff --git a/console.h b/console.h -index b8a5c6d..b45974e 100644 ---- a/console.h -+++ b/console.h -@@ -32,6 +32,12 @@ void kbd_put_keycode(int keycode); - void kbd_mouse_event(int dx, int dy, int dz, int buttons_state); - int kbd_mouse_is_absolute(void); - -+struct mouse_transform_info_s { -+ int x; -+ int y; -+ int a[7]; -+}; -+ - void do_info_mice(void); - void do_mouse_set(int index); - -diff --git a/cpu-all.h b/cpu-all.h -index 7a7e655..c7c9611 100644 ---- a/cpu-all.h -+++ b/cpu-all.h -@@ -810,7 +810,7 @@ extern uint8_t *phys_ram_dirty; - /* physical memory access */ - #define TLB_INVALID_MASK (1 << 3) - #define IO_MEM_SHIFT 4 --#define IO_MEM_NB_ENTRIES (1 << (TARGET_PAGE_BITS - IO_MEM_SHIFT)) -+#define IO_MEM_NB_ENTRIES (16 << (TARGET_PAGE_BITS - IO_MEM_SHIFT)) - - #define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */ - #define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */ -diff --git a/exec.c b/exec.c -index e9a5918..c69f742 100644 ---- a/exec.c -+++ b/exec.c -@@ -1658,7 +1658,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, - { - if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { - /* IO memory case */ -- address = vaddr | pd; -+ address = vaddr | (pd & ~TARGET_PAGE_MASK); - addend = paddr; - } else { - /* standard memory */ -@@ -1692,7 +1692,9 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, - } else { - te->addr_read = -1; - } -- if (prot & PAGE_EXEC) { -+ if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { -+ te->addr_code = pd; -+ } else if (prot & PAGE_EXEC) { - te->addr_code = address; - } else { - te->addr_code = -1; -@@ -2487,7 +2489,9 @@ int cpu_register_io_memory(int io_index, - if (io_index <= 0) { - if (io_mem_nb >= IO_MEM_NB_ENTRIES) - return -1; -- io_index = io_mem_nb++; -+ do io_index = io_mem_nb++; -+ while (((io_index << IO_MEM_SHIFT) & ~TARGET_PAGE_MASK) -+ <= IO_MEM_NOTDIRTY); - } else { - if (io_index >= IO_MEM_NB_ENTRIES) - return -1; -diff --git a/hw/arm-misc.h b/hw/arm-misc.h -index 7914ff1..a1e0061 100644 ---- a/hw/arm-misc.h -+++ b/hw/arm-misc.h -@@ -21,10 +21,7 @@ qemu_irq *armv7m_init(int flash_size, int sram_size, - const char *kernel_filename, const char *cpu_model); - - /* arm_boot.c */ -- --void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename, -- const char *kernel_cmdline, const char *initrd_filename, -- int board_id, target_phys_addr_t loader_start); -+void arm_load_kernel(CPUState *env, struct arm_boot_info *info); - - /* armv7m_nvic.c */ - int system_clock_scale; -diff --git a/hw/arm_boot.c b/hw/arm_boot.c -index 8335e69..20b1512 100644 ---- a/hw/arm_boot.c -+++ b/hw/arm_boot.c -@@ -47,21 +47,18 @@ static void main_cpu_reset(void *opaque) - CPUState *env = opaque; - - cpu_reset(env); -- if (env->kernel_filename) -- arm_load_kernel(env, env->ram_size, env->kernel_filename, -- env->kernel_cmdline, env->initrd_filename, -- env->board_id, env->loader_start); -+ if (env->boot_info) -+ arm_load_kernel(env, env->boot_info); - - /* TODO: Reset secondary CPUs. */ - } - --static void set_kernel_args(uint32_t ram_size, int initrd_size, -- const char *kernel_cmdline, -- target_phys_addr_t loader_start) -+static void set_kernel_args(struct arm_boot_info *info, -+ int initrd_size, void *base) - { - uint32_t *p; - -- p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR); -+ p = (uint32_t *)(base + KERNEL_ARGS_ADDR); - /* ATAG_CORE */ - stl_raw(p++, 5); - stl_raw(p++, 0x54410001); -@@ -69,46 +66,55 @@ static void set_kernel_args(uint32_t ram_size, int initrd_size, - stl_raw(p++, 0x1000); - stl_raw(p++, 0); - /* ATAG_MEM */ -+ /* TODO: multiple chips */ - stl_raw(p++, 4); - stl_raw(p++, 0x54410002); -- stl_raw(p++, ram_size); -- stl_raw(p++, loader_start); -+ stl_raw(p++, info->ram_size); -+ stl_raw(p++, info->loader_start); - if (initrd_size) { - /* ATAG_INITRD2 */ - stl_raw(p++, 4); - stl_raw(p++, 0x54420005); -- stl_raw(p++, loader_start + INITRD_LOAD_ADDR); -+ stl_raw(p++, info->loader_start + INITRD_LOAD_ADDR); - stl_raw(p++, initrd_size); - } -- if (kernel_cmdline && *kernel_cmdline) { -+ if (info->kernel_cmdline && *info->kernel_cmdline) { - /* ATAG_CMDLINE */ - int cmdline_size; - -- cmdline_size = strlen(kernel_cmdline); -- memcpy (p + 2, kernel_cmdline, cmdline_size + 1); -+ cmdline_size = strlen(info->kernel_cmdline); -+ memcpy(p + 2, info->kernel_cmdline, cmdline_size + 1); - cmdline_size = (cmdline_size >> 2) + 1; - stl_raw(p++, cmdline_size + 2); - stl_raw(p++, 0x54410009); - p += cmdline_size; - } -+ if (info->atag_board) { -+ /* ATAG_BOARD */ -+ int atag_board_len; -+ -+ atag_board_len = (info->atag_board(info, p + 2) + 3) >> 2; -+ stl_raw(p++, 2 + atag_board_len); -+ stl_raw(p++, 0x414f4d50); -+ p += atag_board_len; -+ } - /* ATAG_END */ - stl_raw(p++, 0); - stl_raw(p++, 0); - } - --static void set_kernel_args_old(uint32_t ram_size, int initrd_size, -- const char *kernel_cmdline, -- target_phys_addr_t loader_start) -+static void set_kernel_args_old(struct arm_boot_info *info, -+ int initrd_size, void *base) - { - uint32_t *p; - unsigned char *s; - - /* see linux/include/asm-arm/setup.h */ -- p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR); -+ p = (uint32_t *)(base + KERNEL_ARGS_ADDR); - /* page_size */ - stl_raw(p++, 4096); - /* nr_pages */ -- stl_raw(p++, ram_size / 4096); -+ stl_raw(p++, info->ram_size / 4096); - /* ramdisk_size */ - stl_raw(p++, 0); - #define FLAG_READONLY 1 -@@ -142,7 +148,7 @@ static void set_kernel_args_old(uint32_t ram_size, int initrd_size, - stl_raw(p++, 0); - /* initrd_start */ - if (initrd_size) -- stl_raw(p++, loader_start + INITRD_LOAD_ADDR); -+ stl_raw(p++, info->loader_start + INITRD_LOAD_ADDR); - else - stl_raw(p++, 0); - /* initrd_size */ -@@ -159,17 +165,15 @@ static void set_kernel_args_old(uint32_t ram_size, int initrd_size, - stl_raw(p++, 0); - /* zero unused fields */ - memset(p, 0, 256 + 1024 - -- (p - ((uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR)))); -- s = phys_ram_base + KERNEL_ARGS_ADDR + 256 + 1024; -- if (kernel_cmdline) -- strcpy (s, kernel_cmdline); -+ (p - ((uint32_t *)(base + KERNEL_ARGS_ADDR)))); -+ s = base + KERNEL_ARGS_ADDR + 256 + 1024; -+ if (info->kernel_cmdline) -+ strcpy (s, info->kernel_cmdline); - else - stb_raw(s, 0); - } - --void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename, -- const char *kernel_cmdline, const char *initrd_filename, -- int board_id, target_phys_addr_t loader_start) -+void arm_load_kernel(CPUState *env, struct arm_boot_info *info) - { - int kernel_size; - int initrd_size; -@@ -177,36 +181,41 @@ void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename, - int is_linux = 0; - uint64_t elf_entry; - target_ulong entry; -+ uint32_t pd; -+ void *loader_phys; - - /* Load the kernel. */ -- if (!kernel_filename) { -+ if (!info->kernel_filename) { - fprintf(stderr, "Kernel image must be specified\n"); - exit(1); - } - -- if (!env->kernel_filename) { -- env->ram_size = ram_size; -- env->kernel_filename = kernel_filename; -- env->kernel_cmdline = kernel_cmdline; -- env->initrd_filename = initrd_filename; -- env->board_id = board_id; -- env->loader_start = loader_start; -+ if (!env->boot_info) { -+ if (info->nb_cpus == 0) -+ info->nb_cpus = 1; -+ env->boot_info = info; - qemu_register_reset(main_cpu_reset, env); - } -+ -+ pd = cpu_get_physical_page_desc(info->loader_start); -+ loader_phys = phys_ram_base + (pd & TARGET_PAGE_MASK) + -+ (info->loader_start & ~TARGET_PAGE_MASK); -+ - /* Assume that raw images are linux kernels, and ELF images are not. */ -- kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL); -+ kernel_size = load_elf(info->kernel_filename, 0, &elf_entry, NULL, NULL); - entry = elf_entry; - if (kernel_size < 0) { -- kernel_size = load_uboot(kernel_filename, &entry, &is_linux); -+ kernel_size = load_uboot(info->kernel_filename, &entry, &is_linux); - } - if (kernel_size < 0) { -- kernel_size = load_image(kernel_filename, -- phys_ram_base + KERNEL_LOAD_ADDR); -- entry = loader_start + KERNEL_LOAD_ADDR; -+ kernel_size = load_image(info->kernel_filename, -+ loader_phys + KERNEL_LOAD_ADDR); -+ entry = info->loader_start + KERNEL_LOAD_ADDR; - is_linux = 1; - } - if (kernel_size < 0) { -- fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename); -+ fprintf(stderr, "qemu: could not load kernel '%s'\n", -+ info->kernel_filename); - exit(1); - } - if (!is_linux) { -@@ -214,30 +223,29 @@ void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename, - env->regs[15] = entry & 0xfffffffe; - env->thumb = entry & 1; - } else { -- if (initrd_filename) { -- initrd_size = load_image(initrd_filename, -- phys_ram_base + INITRD_LOAD_ADDR); -+ if (info->initrd_filename) { -+ initrd_size = load_image(info->initrd_filename, -+ loader_phys + INITRD_LOAD_ADDR); - if (initrd_size < 0) { - fprintf(stderr, "qemu: could not load initrd '%s'\n", -- initrd_filename); -+ info->initrd_filename); - exit(1); - } - } else { - initrd_size = 0; - } -- bootloader[1] |= board_id & 0xff; -- bootloader[2] |= (board_id >> 8) & 0xff; -- bootloader[5] = loader_start + KERNEL_ARGS_ADDR; -+ bootloader[1] |= info->board_id & 0xff; -+ bootloader[2] |= (info->board_id >> 8) & 0xff; -+ bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR; - bootloader[6] = entry; - for (n = 0; n < sizeof(bootloader) / 4; n++) -- stl_raw(phys_ram_base + (n * 4), bootloader[n]); -- for (n = 0; n < sizeof(smpboot) / 4; n++) -- stl_raw(phys_ram_base + ram_size + (n * 4), smpboot[n]); -+ stl_raw(loader_phys + (n * 4), bootloader[n]); -+ if (info->nb_cpus > 1) -+ for (n = 0; n < sizeof(smpboot) / 4; n++) -+ stl_raw(loader_phys + info->ram_size + (n * 4), smpboot[n]); - if (old_param) -- set_kernel_args_old(ram_size, initrd_size, -- kernel_cmdline, loader_start); -+ set_kernel_args_old(info, initrd_size, loader_phys); - else -- set_kernel_args(ram_size, initrd_size, -- kernel_cmdline, loader_start); -+ set_kernel_args(info, initrd_size, loader_phys); - } - } -diff --git a/hw/blizzard.c b/hw/blizzard.c -new file mode 100644 -index 0000000..9046b5d ---- /dev/null -+++ b/hw/blizzard.c -@@ -0,0 +1,1001 @@ -+/* -+ * Epson S1D13744/S1D13745 (Blizzard/Hailstorm/Tornado) LCD/TV controller. -+ * -+ * Copyright (C) 2008 Nokia Corporation -+ * Written by Andrzej Zaborowski -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of -+ * the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, -+ * MA 02111-1307 USA -+ */ -+ -+#include "qemu-common.h" -+#include "sysemu.h" -+#include "console.h" -+#include "devices.h" -+#include "vga_int.h" -+#include "pixel_ops.h" -+ -+typedef void (*blizzard_fn_t)(uint8_t *, const uint8_t *, unsigned int); -+ -+struct blizzard_s { -+ uint8_t reg; -+ uint32_t addr; -+ int swallow; -+ -+ int pll; -+ int pll_range; -+ int pll_ctrl; -+ uint8_t pll_mode; -+ uint8_t clksel; -+ int memenable; -+ int memrefresh; -+ uint8_t timing[3]; -+ int priority; -+ -+ uint8_t lcd_config; -+ int x; -+ int y; -+ int skipx; -+ int skipy; -+ uint8_t hndp; -+ uint8_t vndp; -+ uint8_t hsync; -+ uint8_t vsync; -+ uint8_t pclk; -+ uint8_t u; -+ uint8_t v; -+ uint8_t yrc[2]; -+ int ix[2]; -+ int iy[2]; -+ int ox[2]; -+ int oy[2]; -+ -+ int enable; -+ int blank; -+ int bpp; -+ int invalidate; -+ int mx[2]; -+ int my[2]; -+ uint8_t mode; -+ uint8_t effect; -+ uint8_t iformat; -+ uint8_t source; -+ DisplayState *state; -+ blizzard_fn_t *line_fn_tab[2]; -+ void *fb; -+ -+ uint8_t hssi_config[3]; -+ uint8_t tv_config; -+ uint8_t tv_timing[4]; -+ uint8_t vbi; -+ uint8_t tv_x; -+ uint8_t tv_y; -+ uint8_t tv_test; -+ uint8_t tv_filter_config; -+ uint8_t tv_filter_idx; -+ uint8_t tv_filter_coeff[0x20]; -+ uint8_t border_r; -+ uint8_t border_g; -+ uint8_t border_b; -+ uint8_t gamma_config; -+ uint8_t gamma_idx; -+ uint8_t gamma_lut[0x100]; -+ uint8_t matrix_ena; -+ uint8_t matrix_coeff[0x12]; -+ uint8_t matrix_r; -+ uint8_t matrix_g; -+ uint8_t matrix_b; -+ uint8_t pm; -+ uint8_t status; -+ uint8_t rgbgpio_dir; -+ uint8_t rgbgpio; -+ uint8_t gpio_dir; -+ uint8_t gpio; -+ uint8_t gpio_edge[2]; -+ uint8_t gpio_irq; -+ uint8_t gpio_pdown; -+ -+ struct { -+ int x; -+ int y; -+ int dx; -+ int dy; -+ int len; -+ int buflen; -+ void *buf; -+ void *data; -+ uint16_t *ptr; -+ int angle; -+ int pitch; -+ blizzard_fn_t line_fn; -+ } data; -+}; -+ -+/* Bytes(!) per pixel */ -+static const int blizzard_iformat_bpp[0x10] = { -+ 0, -+ 2, /* RGB 5:6:5*/ -+ 3, /* RGB 6:6:6 mode 1 */ -+ 3, /* RGB 8:8:8 mode 1 */ -+ 0, 0, -+ 4, /* RGB 6:6:6 mode 2 */ -+ 4, /* RGB 8:8:8 mode 2 */ -+ 0, /* YUV 4:2:2 */ -+ 0, /* YUV 4:2:0 */ -+ 0, 0, 0, 0, 0, 0, -+}; -+ -+static inline void blizzard_rgb2yuv(int r, int g, int b, -+ int *y, int *u, int *v) -+{ -+ *y = 0x10 + ((0x838 * r + 0x1022 * g + 0x322 * b) >> 13); -+ *u = 0x80 + ((0xe0e * b - 0x04c1 * r - 0x94e * g) >> 13); -+ *v = 0x80 + ((0xe0e * r - 0x0bc7 * g - 0x247 * b) >> 13); -+} -+ -+static void blizzard_window(struct blizzard_s *s) -+{ -+ uint8_t *src, *dst; -+ int bypp[2]; -+ int bypl[3]; -+ int y; -+ blizzard_fn_t fn = s->data.line_fn; -+ -+ if (!fn) -+ return; -+ if (s->mx[0] > s->data.x) -+ s->mx[0] = s->data.x; -+ if (s->my[0] > s->data.y) -+ s->my[0] = s->data.y; -+ if (s->mx[1] < s->data.x + s->data.dx) -+ s->mx[1] = s->data.x + s->data.dx; -+ if (s->my[1] < s->data.y + s->data.dy) -+ s->my[1] = s->data.y + s->data.dy; -+ -+ bypp[0] = s->bpp; -+ bypp[1] = (s->state->depth + 7) >> 3; -+ bypl[0] = bypp[0] * s->data.pitch; -+ bypl[1] = bypp[1] * s->x; -+ bypl[2] = bypp[0] * s->data.dx; -+ -+ src = s->data.data; -+ dst = s->fb + bypl[1] * s->data.y + bypp[1] * s->data.x; -+ for (y = s->data.dy; y > 0; y --, src += bypl[0], dst += bypl[1]) -+ fn(dst, src, bypl[2]); -+} -+ -+static int blizzard_transfer_setup(struct blizzard_s *s) -+{ -+ if (s->source > 3 || !s->bpp || -+ s->ix[1] < s->ix[0] || s->iy[1] < s->iy[0]) -+ return 0; -+ -+ s->data.angle = s->effect & 3; -+ s->data.line_fn = s->line_fn_tab[!!s->data.angle][s->iformat]; -+ s->data.x = s->ix[0]; -+ s->data.y = s->iy[0]; -+ s->data.dx = s->ix[1] - s->ix[0] + 1; -+ s->data.dy = s->iy[1] - s->iy[0] + 1; -+ s->data.len = s->bpp * s->data.dx * s->data.dy; -+ s->data.pitch = s->data.dx; -+ if (s->data.len > s->data.buflen) { -+ s->data.buf = realloc(s->data.buf, s->data.len); -+ s->data.buflen = s->data.len; -+ } -+ s->data.ptr = s->data.buf; -+ s->data.data = s->data.buf; -+ s->data.len /= 2; -+ return 1; -+} -+ -+static void blizzard_reset(struct blizzard_s *s) -+{ -+ s->reg = 0; -+ s->swallow = 0; -+ -+ s->pll = 9; -+ s->pll_range = 1; -+ s->pll_ctrl = 0x14; -+ s->pll_mode = 0x32; -+ s->clksel = 0x00; -+ s->memenable = 0; -+ s->memrefresh = 0x25c; -+ s->timing[0] = 0x3f; -+ s->timing[1] = 0x13; -+ s->timing[2] = 0x21; -+ s->priority = 0; -+ -+ s->lcd_config = 0x74; -+ s->x = 8; -+ s->y = 1; -+ s->skipx = 0; -+ s->skipy = 0; -+ s->hndp = 3; -+ s->vndp = 2; -+ s->hsync = 1; -+ s->vsync = 1; -+ s->pclk = 0x80; -+ -+ s->ix[0] = 0; -+ s->ix[1] = 0; -+ s->iy[0] = 0; -+ s->iy[1] = 0; -+ s->ox[0] = 0; -+ s->ox[1] = 0; -+ s->oy[0] = 0; -+ s->oy[1] = 0; -+ -+ s->yrc[0] = 0x00; -+ s->yrc[1] = 0x30; -+ s->u = 0; -+ s->v = 0; -+ -+ s->iformat = 3; -+ s->source = 0; -+ s->bpp = blizzard_iformat_bpp[s->iformat]; -+ -+ s->hssi_config[0] = 0x00; -+ s->hssi_config[1] = 0x00; -+ s->hssi_config[2] = 0x01; -+ s->tv_config = 0x00; -+ s->tv_timing[0] = 0x00; -+ s->tv_timing[1] = 0x00; -+ s->tv_timing[2] = 0x00; -+ s->tv_timing[3] = 0x00; -+ s->vbi = 0x10; -+ s->tv_x = 0x14; -+ s->tv_y = 0x03; -+ s->tv_test = 0x00; -+ s->tv_filter_config = 0x80; -+ s->tv_filter_idx = 0x00; -+ s->border_r = 0x10; -+ s->border_g = 0x80; -+ s->border_b = 0x80; -+ s->gamma_config = 0x00; -+ s->gamma_idx = 0x00; -+ s->matrix_ena = 0x00; -+ memset(&s->matrix_coeff, 0, sizeof(s->matrix_coeff)); -+ s->matrix_r = 0x00; -+ s->matrix_g = 0x00; -+ s->matrix_b = 0x00; -+ s->pm = 0x02; -+ s->status = 0x00; -+ s->rgbgpio_dir = 0x00; -+ s->gpio_dir = 0x00; -+ s->gpio_edge[0] = 0x00; -+ s->gpio_edge[1] = 0x00; -+ s->gpio_irq = 0x00; -+ s->gpio_pdown = 0xff; -+} -+ -+static inline void blizzard_invalidate_display(void *opaque) { -+ struct blizzard_s *s = (struct blizzard_s *) opaque; -+ -+ s->invalidate = 1; -+} -+ -+static uint16_t blizzard_reg_read(void *opaque, uint8_t reg) -+{ -+ struct blizzard_s *s = (struct blizzard_s *) opaque; -+ -+ switch (reg) { -+ case 0x00: /* Revision Code */ -+ return 0xa5; -+ -+ case 0x02: /* Configuration Readback */ -+ return 0x83; /* Macrovision OK, CNF[2:0] = 3 */ -+ -+ case 0x04: /* PLL M-Divider */ -+ return (s->pll - 1) | (1 << 7); -+ case 0x06: /* PLL Lock Range Control */ -+ return s->pll_range; -+ case 0x08: /* PLL Lock Synthesis Control 0 */ -+ return s->pll_ctrl & 0xff; -+ case 0x0a: /* PLL Lock Synthesis Control 1 */ -+ return s->pll_ctrl >> 8; -+ case 0x0c: /* PLL Mode Control 0 */ -+ return s->pll_mode; -+ -+ case 0x0e: /* Clock-Source Select */ -+ return s->clksel; -+ -+ case 0x10: /* Memory Controller Activate */ -+ case 0x14: /* Memory Controller Bank 0 Status Flag */ -+ return s->memenable; -+ -+ case 0x18: /* Auto-Refresh Interval Setting 0 */ -+ return s->memrefresh & 0xff; -+ case 0x1a: /* Auto-Refresh Interval Setting 1 */ -+ return s->memrefresh >> 8; -+ -+ case 0x1c: /* Power-On Sequence Timing Control */ -+ return s->timing[0]; -+ case 0x1e: /* Timing Control 0 */ -+ return s->timing[1]; -+ case 0x20: /* Timing Control 1 */ -+ return s->timing[2]; -+ -+ case 0x24: /* Arbitration Priority Control */ -+ return s->priority; -+ -+ case 0x28: /* LCD Panel Configuration */ -+ return s->lcd_config; -+ -+ case 0x2a: /* LCD Horizontal Display Width */ -+ return s->x >> 3; -+ case 0x2c: /* LCD Horizontal Non-display Period */ -+ return s->hndp; -+ case 0x2e: /* LCD Vertical Display Height 0 */ -+ return s->y & 0xff; -+ case 0x30: /* LCD Vertical Display Height 1 */ -+ return s->y >> 8; -+ case 0x32: /* LCD Vertical Non-display Period */ -+ return s->vndp; -+ case 0x34: /* LCD HS Pulse-width */ -+ return s->hsync; -+ case 0x36: /* LCd HS Pulse Start Position */ -+ return s->skipx >> 3; -+ case 0x38: /* LCD VS Pulse-width */ -+ return s->vsync; -+ case 0x3a: /* LCD VS Pulse Start Position */ -+ return s->skipy; -+ -+ case 0x3c: /* PCLK Polarity */ -+ return s->pclk; -+ -+ case 0x3e: /* High-speed Serial Interface Tx Configuration Port 0 */ -+ return s->hssi_config[0]; -+ case 0x40: /* High-speed Serial Interface Tx Configuration Port 1 */ -+ return s->hssi_config[1]; -+ case 0x42: /* High-speed Serial Interface Tx Mode */ -+ return s->hssi_config[2]; -+ case 0x44: /* TV Display Configuration */ -+ return s->tv_config; -+ case 0x46 ... 0x4c: /* TV Vertical Blanking Interval Data bits */ -+ return s->tv_timing[(reg - 0x46) >> 1]; -+ case 0x4e: /* VBI: Closed Caption / XDS Control / Status */ -+ return s->vbi; -+ case 0x50: /* TV Horizontal Start Position */ -+ return s->tv_x; -+ case 0x52: /* TV Vertical Start Position */ -+ return s->tv_y; -+ case 0x54: /* TV Test Pattern Setting */ -+ return s->tv_test; -+ case 0x56: /* TV Filter Setting */ -+ return s->tv_filter_config; -+ case 0x58: /* TV Filter Coefficient Index */ -+ return s->tv_filter_idx; -+ case 0x5a: /* TV Filter Coefficient Data */ -+ if (s->tv_filter_idx < 0x20) -+ return s->tv_filter_coeff[s->tv_filter_idx ++]; -+ return 0; -+ -+ case 0x60: /* Input YUV/RGB Translate Mode 0 */ -+ return s->yrc[0]; -+ case 0x62: /* Input YUV/RGB Translate Mode 1 */ -+ return s->yrc[1]; -+ case 0x64: /* U Data Fix */ -+ return s->u; -+ case 0x66: /* V Data Fix */ -+ return s->v; -+ -+ case 0x68: /* Display Mode */ -+ return s->mode; -+ -+ case 0x6a: /* Special Effects */ -+ return s->effect; -+ -+ case 0x6c: /* Input Window X Start Position 0 */ -+ return s->ix[0] & 0xff; -+ case 0x6e: /* Input Window X Start Position 1 */ -+ return s->ix[0] >> 3; -+ case 0x70: /* Input Window Y Start Position 0 */ -+ return s->ix[0] & 0xff; -+ case 0x72: /* Input Window Y Start Position 1 */ -+ return s->ix[0] >> 3; -+ case 0x74: /* Input Window X End Position 0 */ -+ return s->ix[1] & 0xff; -+ case 0x76: /* Input Window X End Position 1 */ -+ return s->ix[1] >> 3; -+ case 0x78: /* Input Window Y End Position 0 */ -+ return s->ix[1] & 0xff; -+ case 0x7a: /* Input Window Y End Position 1 */ -+ return s->ix[1] >> 3; -+ case 0x7c: /* Output Window X Start Position 0 */ -+ return s->ox[0] & 0xff; -+ case 0x7e: /* Output Window X Start Position 1 */ -+ return s->ox[0] >> 3; -+ case 0x80: /* Output Window Y Start Position 0 */ -+ return s->oy[0] & 0xff; -+ case 0x82: /* Output Window Y Start Position 1 */ -+ return s->oy[0] >> 3; -+ case 0x84: /* Output Window X End Position 0 */ -+ return s->ox[1] & 0xff; -+ case 0x86: /* Output Window X End Position 1 */ -+ return s->ox[1] >> 3; -+ case 0x88: /* Output Window Y End Position 0 */ -+ return s->oy[1] & 0xff; -+ case 0x8a: /* Output Window Y End Position 1 */ -+ return s->oy[1] >> 3; -+ -+ case 0x8c: /* Input Data Format */ -+ return s->iformat; -+ case 0x8e: /* Data Source Select */ -+ return s->source; -+ case 0x90: /* Display Memory Data Port */ -+ return 0; -+ -+ case 0xa8: /* Border Color 0 */ -+ return s->border_r; -+ case 0xaa: /* Border Color 1 */ -+ return s->border_g; -+ case 0xac: /* Border Color 2 */ -+ return s->border_b; -+ -+ case 0xb4: /* Gamma Correction Enable */ -+ return s->gamma_config; -+ case 0xb6: /* Gamma Correction Table Index */ -+ return s->gamma_idx; -+ case 0xb8: /* Gamma Correction Table Data */ -+ return s->gamma_lut[s->gamma_idx ++]; -+ -+ case 0xba: /* 3x3 Matrix Enable */ -+ return s->matrix_ena; -+ case 0xbc ... 0xde: /* Coefficient Registers */ -+ return s->matrix_coeff[(reg - 0xbc) >> 1]; -+ case 0xe0: /* 3x3 Matrix Red Offset */ -+ return s->matrix_r; -+ case 0xe2: /* 3x3 Matrix Green Offset */ -+ return s->matrix_g; -+ case 0xe4: /* 3x3 Matrix Blue Offset */ -+ return s->matrix_b; -+ -+ case 0xe6: /* Power-save */ -+ return s->pm; -+ case 0xe8: /* Non-display Period Control / Status */ -+ return s->status | (1 << 5); -+ case 0xea: /* RGB Interface Control */ -+ return s->rgbgpio_dir; -+ case 0xec: /* RGB Interface Status */ -+ return s->rgbgpio; -+ case 0xee: /* General-purpose IO Pins Configuration */ -+ return s->gpio_dir; -+ case 0xf0: /* General-purpose IO Pins Status / Control */ -+ return s->gpio; -+ case 0xf2: /* GPIO Positive Edge Interrupt Trigger */ -+ return s->gpio_edge[0]; -+ case 0xf4: /* GPIO Negative Edge Interrupt Trigger */ -+ return s->gpio_edge[1]; -+ case 0xf6: /* GPIO Interrupt Status */ -+ return s->gpio_irq; -+ case 0xf8: /* GPIO Pull-down Control */ -+ return s->gpio_pdown; -+ -+ default: -+ fprintf(stderr, "%s: unknown register %02x\n", __FUNCTION__, reg); -+ return 0; -+ } -+} -+ -+static void blizzard_reg_write(void *opaque, uint8_t reg, uint16_t value) -+{ -+ struct blizzard_s *s = (struct blizzard_s *) opaque; -+ -+ switch (reg) { -+ case 0x04: /* PLL M-Divider */ -+ s->pll = (value & 0x3f) + 1; -+ break; -+ case 0x06: /* PLL Lock Range Control */ -+ s->pll_range = value & 3; -+ break; -+ case 0x08: /* PLL Lock Synthesis Control 0 */ -+ s->pll_ctrl &= 0xf00; -+ s->pll_ctrl |= (value << 0) & 0x0ff; -+ break; -+ case 0x0a: /* PLL Lock Synthesis Control 1 */ -+ s->pll_ctrl &= 0x0ff; -+ s->pll_ctrl |= (value << 8) & 0xf00; -+ break; -+ case 0x0c: /* PLL Mode Control 0 */ -+ s->pll_mode = value & 0x77; -+ if ((value & 3) == 0 || (value & 3) == 3) -+ fprintf(stderr, "%s: wrong PLL Control bits (%i)\n", -+ __FUNCTION__, value & 3); -+ break; -+ -+ case 0x0e: /* Clock-Source Select */ -+ s->clksel = value & 0xff; -+ break; -+ -+ case 0x10: /* Memory Controller Activate */ -+ s->memenable = value & 1; -+ break; -+ case 0x14: /* Memory Controller Bank 0 Status Flag */ -+ break; -+ -+ case 0x18: /* Auto-Refresh Interval Setting 0 */ -+ s->memrefresh &= 0xf00; -+ s->memrefresh |= (value << 0) & 0x0ff; -+ break; -+ case 0x1a: /* Auto-Refresh Interval Setting 1 */ -+ s->memrefresh &= 0x0ff; -+ s->memrefresh |= (value << 8) & 0xf00; -+ break; -+ -+ case 0x1c: /* Power-On Sequence Timing Control */ -+ s->timing[0] = value & 0x7f; -+ break; -+ case 0x1e: /* Timing Control 0 */ -+ s->timing[1] = value & 0x17; -+ break; -+ case 0x20: /* Timing Control 1 */ -+ s->timing[2] = value & 0x35; -+ break; -+ -+ case 0x24: /* Arbitration Priority Control */ -+ s->priority = value & 1; -+ break; -+ -+ case 0x28: /* LCD Panel Configuration */ -+ s->lcd_config = value & 0xff; -+ if (value & (1 << 7)) -+ fprintf(stderr, "%s: data swap not supported!\n", __FUNCTION__); -+ break; -+ -+ case 0x2a: /* LCD Horizontal Display Width */ -+ s->x = value << 3; -+ break; -+ case 0x2c: /* LCD Horizontal Non-display Period */ -+ s->hndp = value & 0xff; -+ break; -+ case 0x2e: /* LCD Vertical Display Height 0 */ -+ s->y &= 0x300; -+ s->y |= (value << 0) & 0x0ff; -+ break; -+ case 0x30: /* LCD Vertical Display Height 1 */ -+ s->y &= 0x0ff; -+ s->y |= (value << 8) & 0x300; -+ break; -+ case 0x32: /* LCD Vertical Non-display Period */ -+ s->vndp = value & 0xff; -+ break; -+ case 0x34: /* LCD HS Pulse-width */ -+ s->hsync = value & 0xff; -+ break; -+ case 0x36: /* LCD HS Pulse Start Position */ -+ s->skipx = value & 0xff; -+ break; -+ case 0x38: /* LCD VS Pulse-width */ -+ s->vsync = value & 0xbf; -+ break; -+ case 0x3a: /* LCD VS Pulse Start Position */ -+ s->skipy = value & 0xff; -+ break; -+ -+ case 0x3c: /* PCLK Polarity */ -+ s->pclk = value & 0x82; -+ /* Affects calculation of s->hndp, s->hsync and s->skipx. */ -+ break; -+ -+ case 0x3e: /* High-speed Serial Interface Tx Configuration Port 0 */ -+ s->hssi_config[0] = value; -+ break; -+ case 0x40: /* High-speed Serial Interface Tx Configuration Port 1 */ -+ s->hssi_config[1] = value; -+ if (((value >> 4) & 3) == 3) -+ fprintf(stderr, "%s: Illegal active-data-links value\n", -+ __FUNCTION__); -+ break; -+ case 0x42: /* High-speed Serial Interface Tx Mode */ -+ s->hssi_config[2] = value & 0xbd; -+ break; -+ -+ case 0x44: /* TV Display Configuration */ -+ s->tv_config = value & 0xfe; -+ break; -+ case 0x46 ... 0x4c: /* TV Vertical Blanking Interval Data bits 0 */ -+ s->tv_timing[(reg - 0x46) >> 1] = value; -+ break; -+ case 0x4e: /* VBI: Closed Caption / XDS Control / Status */ -+ s->vbi = value; -+ break; -+ case 0x50: /* TV Horizontal Start Position */ -+ s->tv_x = value; -+ break; -+ case 0x52: /* TV Vertical Start Position */ -+ s->tv_y = value & 0x7f; -+ break; -+ case 0x54: /* TV Test Pattern Setting */ -+ s->tv_test = value; -+ break; -+ case 0x56: /* TV Filter Setting */ -+ s->tv_filter_config = value & 0xbf; -+ break; -+ case 0x58: /* TV Filter Coefficient Index */ -+ s->tv_filter_idx = value & 0x1f; -+ break; -+ case 0x5a: /* TV Filter Coefficient Data */ -+ if (s->tv_filter_idx < 0x20) -+ s->tv_filter_coeff[s->tv_filter_idx ++] = value; -+ break; -+ -+ case 0x60: /* Input YUV/RGB Translate Mode 0 */ -+ s->yrc[0] = value & 0xb0; -+ break; -+ case 0x62: /* Input YUV/RGB Translate Mode 1 */ -+ s->yrc[1] = value & 0x30; -+ break; -+ case 0x64: /* U Data Fix */ -+ s->u = value & 0xff; -+ break; -+ case 0x66: /* V Data Fix */ -+ s->v = value & 0xff; -+ break; -+ -+ case 0x68: /* Display Mode */ -+ if ((s->mode ^ value) & 3) -+ s->invalidate = 1; -+ s->mode = value & 0xb7; -+ s->enable = value & 1; -+ s->blank = (value >> 1) & 1; -+ if (value & (1 << 4)) -+ fprintf(stderr, "%s: Macrovision enable attempt!\n", __FUNCTION__); -+ break; -+ -+ case 0x6a: /* Special Effects */ -+ s->effect = value & 0xfb; -+ break; -+ -+ case 0x6c: /* Input Window X Start Position 0 */ -+ s->ix[0] &= 0x300; -+ s->ix[0] |= (value << 0) & 0x0ff; -+ break; -+ case 0x6e: /* Input Window X Start Position 1 */ -+ s->ix[0] &= 0x0ff; -+ s->ix[0] |= (value << 8) & 0x300; -+ break; -+ case 0x70: /* Input Window Y Start Position 0 */ -+ s->iy[0] &= 0x300; -+ s->iy[0] |= (value << 0) & 0x0ff; -+ break; -+ case 0x72: /* Input Window Y Start Position 1 */ -+ s->iy[0] &= 0x0ff; -+ s->iy[0] |= (value << 8) & 0x300; -+ break; -+ case 0x74: /* Input Window X End Position 0 */ -+ s->ix[1] &= 0x300; -+ s->ix[1] |= (value << 0) & 0x0ff; -+ break; -+ case 0x76: /* Input Window X End Position 1 */ -+ s->ix[1] &= 0x0ff; -+ s->ix[1] |= (value << 8) & 0x300; -+ break; -+ case 0x78: /* Input Window Y End Position 0 */ -+ s->iy[1] &= 0x300; -+ s->iy[1] |= (value << 0) & 0x0ff; -+ break; -+ case 0x7a: /* Input Window Y End Position 1 */ -+ s->iy[1] &= 0x0ff; -+ s->iy[1] |= (value << 8) & 0x300; -+ break; -+ case 0x7c: /* Output Window X Start Position 0 */ -+ s->ox[0] &= 0x300; -+ s->ox[0] |= (value << 0) & 0x0ff; -+ break; -+ case 0x7e: /* Output Window X Start Position 1 */ -+ s->ox[0] &= 0x0ff; -+ s->ox[0] |= (value << 8) & 0x300; -+ break; -+ case 0x80: /* Output Window Y Start Position 0 */ -+ s->oy[0] &= 0x300; -+ s->oy[0] |= (value << 0) & 0x0ff; -+ break; -+ case 0x82: /* Output Window Y Start Position 1 */ -+ s->oy[0] &= 0x0ff; -+ s->oy[0] |= (value << 8) & 0x300; -+ break; -+ case 0x84: /* Output Window X End Position 0 */ -+ s->ox[1] &= 0x300; -+ s->ox[1] |= (value << 0) & 0x0ff; -+ break; -+ case 0x86: /* Output Window X End Position 1 */ -+ s->ox[1] &= 0x0ff; -+ s->ox[1] |= (value << 8) & 0x300; -+ break; -+ case 0x88: /* Output Window Y End Position 0 */ -+ s->oy[1] &= 0x300; -+ s->oy[1] |= (value << 0) & 0x0ff; -+ break; -+ case 0x8a: /* Output Window Y End Position 1 */ -+ s->oy[1] &= 0x0ff; -+ s->oy[1] |= (value << 8) & 0x300; -+ break; -+ -+ case 0x8c: /* Input Data Format */ -+ s->iformat = value & 0xf; -+ s->bpp = blizzard_iformat_bpp[s->iformat]; -+ if (!s->bpp) -+ fprintf(stderr, "%s: Illegal or unsupported input format %x\n", -+ __FUNCTION__, s->iformat); -+ break; -+ case 0x8e: /* Data Source Select */ -+ s->source = value & 7; -+ /* Currently all windows will be "destructive overlays". */ -+ if ((!(s->effect & (1 << 3)) && (s->ix[0] != s->ox[0] || -+ s->iy[0] != s->oy[0] || -+ s->ix[1] != s->ox[1] || -+ s->iy[1] != s->oy[1])) || -+ !((s->ix[1] - s->ix[0]) & (s->iy[1] - s->iy[0]) & -+ (s->ox[1] - s->ox[0]) & (s->oy[1] - s->oy[0]) & 1)) -+ fprintf(stderr, "%s: Illegal input/output window positions\n", -+ __FUNCTION__); -+ -+ blizzard_transfer_setup(s); -+ break; -+ -+ case 0x90: /* Display Memory Data Port */ -+ if (!s->data.len && !blizzard_transfer_setup(s)) -+ break; -+ -+ *s->data.ptr ++ = value; -+ if (-- s->data.len == 0) -+ blizzard_window(s); -+ break; -+ -+ case 0xa8: /* Border Color 0 */ -+ s->border_r = value; -+ break; -+ case 0xaa: /* Border Color 1 */ -+ s->border_g = value; -+ break; -+ case 0xac: /* Border Color 2 */ -+ s->border_b = value; -+ break; -+ -+ case 0xb4: /* Gamma Correction Enable */ -+ s->gamma_config = value & 0x87; -+ break; -+ case 0xb6: /* Gamma Correction Table Index */ -+ s->gamma_idx = value; -+ break; -+ case 0xb8: /* Gamma Correction Table Data */ -+ s->gamma_lut[s->gamma_idx ++] = value; -+ break; -+ -+ case 0xba: /* 3x3 Matrix Enable */ -+ s->matrix_ena = value & 1; -+ break; -+ case 0xbc ... 0xde: /* Coefficient Registers */ -+ s->matrix_coeff[(reg - 0xbc) >> 1] = value & ((reg & 2) ? 0x80 : 0xff); -+ break; -+ case 0xe0: /* 3x3 Matrix Red Offset */ -+ s->matrix_r = value; -+ break; -+ case 0xe2: /* 3x3 Matrix Green Offset */ -+ s->matrix_g = value; -+ break; -+ case 0xe4: /* 3x3 Matrix Blue Offset */ -+ s->matrix_b = value; -+ break; -+ -+ case 0xe6: /* Power-save */ -+ s->pm = value & 0x83; -+ if (value & s->mode & 1) -+ fprintf(stderr, "%s: The display must be disabled before entering " -+ "Standby Mode\n", __FUNCTION__); -+ break; -+ case 0xe8: /* Non-display Period Control / Status */ -+ s->status = value & 0x1b; -+ break; -+ case 0xea: /* RGB Interface Control */ -+ s->rgbgpio_dir = value & 0x8f; -+ break; -+ case 0xec: /* RGB Interface Status */ -+ s->rgbgpio = value & 0xcf; -+ break; -+ case 0xee: /* General-purpose IO Pins Configuration */ -+ s->gpio_dir = value; -+ break; -+ case 0xf0: /* General-purpose IO Pins Status / Control */ -+ s->gpio = value; -+ break; -+ case 0xf2: /* GPIO Positive Edge Interrupt Trigger */ -+ s->gpio_edge[0] = value; -+ break; -+ case 0xf4: /* GPIO Negative Edge Interrupt Trigger */ -+ s->gpio_edge[1] = value; -+ break; -+ case 0xf6: /* GPIO Interrupt Status */ -+ s->gpio_irq &= value; -+ break; -+ case 0xf8: /* GPIO Pull-down Control */ -+ s->gpio_pdown = value; -+ break; -+ -+ default: -+ fprintf(stderr, "%s: unknown register %02x\n", __FUNCTION__, reg); -+ break; -+ } -+} -+ -+uint16_t s1d13745_read(void *opaque, int dc) -+{ -+ struct blizzard_s *s = (struct blizzard_s *) opaque; -+ uint16_t value = blizzard_reg_read(s, s->reg); -+ -+ if (s->swallow -- > 0) -+ return 0; -+ if (dc) -+ s->reg ++; -+ -+ return value; -+} -+ -+void s1d13745_write(void *opaque, int dc, uint16_t value) -+{ -+ struct blizzard_s *s = (struct blizzard_s *) opaque; -+ -+ if (s->swallow -- > 0) -+ return; -+ if (dc) { -+ blizzard_reg_write(s, s->reg, value); -+ -+ if (s->reg != 0x90 && s->reg != 0x5a && s->reg != 0xb8) -+ s->reg += 2; -+ } else -+ s->reg = value & 0xff; -+} -+ -+void s1d13745_write_block(void *opaque, int dc, -+ void *buf, size_t len, int pitch) -+{ -+ struct blizzard_s *s = (struct blizzard_s *) opaque; -+ -+ while (len > 0) { -+ if (s->reg == 0x90 && dc && -+ (s->data.len || blizzard_transfer_setup(s)) && -+ len >= (s->data.len << 1)) { -+ len -= s->data.len << 1; -+ s->data.len = 0; -+ s->data.data = buf; -+ if (pitch) -+ s->data.pitch = pitch; -+ blizzard_window(s); -+ s->data.data = s->data.buf; -+ continue; -+ } -+ -+ s1d13745_write(opaque, dc, *(uint16_t *) buf); -+ len -= 2; -+ buf += 2; -+ } -+ -+ return; -+} -+ -+static void blizzard_update_display(void *opaque) -+{ -+ struct blizzard_s *s = (struct blizzard_s *) opaque; -+ int y, bypp, bypl, bwidth; -+ uint8_t *src, *dst; -+ -+ if (!s->enable) -+ return; -+ -+ if (s->x != s->state->width || s->y != s->state->height) { -+ s->invalidate = 1; -+ dpy_resize(s->state, s->x, s->y); -+ } -+ -+ if (s->invalidate) { -+ s->invalidate = 0; -+ -+ if (s->blank) { -+ bypp = (s->state->depth + 7) >> 3; -+ memset(s->state->data, 0, bypp * s->x * s->y); -+ return; -+ } -+ -+ s->mx[0] = 0; -+ s->mx[1] = s->x; -+ s->my[0] = 0; -+ s->my[1] = s->y; -+ } -+ -+ if (s->mx[1] <= s->mx[0]) -+ return; -+ -+ bypp = (s->state->depth + 7) >> 3; -+ bypl = bypp * s->x; -+ bwidth = bypp * (s->mx[1] - s->mx[0]); -+ y = s->my[0]; -+ src = s->fb + bypl * y + bypp * s->mx[0]; -+ dst = s->state->data + bypl * y + bypp * s->mx[0]; -+ for (; y < s->my[1]; y ++, src += bypl, dst += bypl) -+ memcpy(dst, src, bwidth); -+ -+ dpy_update(s->state, s->mx[0], s->my[0], -+ s->mx[1] - s->mx[0], y - s->my[0]); -+ -+ s->mx[0] = s->x; -+ s->mx[1] = 0; -+ s->my[0] = s->y; -+ s->my[1] = 0; -+} -+ -+static void blizzard_screen_dump(void *opaque, const char *filename) { -+ struct blizzard_s *s = (struct blizzard_s *) opaque; -+ -+ blizzard_update_display(opaque); -+ if (s && s->state->data) -+ ppm_save(filename, s->state->data, s->x, s->y, s->state->linesize); -+} -+ -+#define DEPTH 8 -+#include "blizzard_template.h" -+#define DEPTH 15 -+#include "blizzard_template.h" -+#define DEPTH 16 -+#include "blizzard_template.h" -+#define DEPTH 24 -+#include "blizzard_template.h" -+#define DEPTH 32 -+#include "blizzard_template.h" -+ -+void *s1d13745_init(qemu_irq gpio_int, DisplayState *ds) -+{ -+ struct blizzard_s *s = (struct blizzard_s *) qemu_mallocz(sizeof(*s)); -+ -+ s->state = ds; -+ s->fb = qemu_malloc(0x180000); -+ -+ switch (s->state->depth) { -+ case 0: -+ s->line_fn_tab[0] = s->line_fn_tab[1] = -+ qemu_mallocz(sizeof(blizzard_fn_t) * 0x10); -+ break; -+ case 8: -+ s->line_fn_tab[0] = blizzard_draw_fn_8; -+ s->line_fn_tab[1] = blizzard_draw_fn_r_8; -+ break; -+ case 15: -+ s->line_fn_tab[0] = blizzard_draw_fn_15; -+ s->line_fn_tab[1] = blizzard_draw_fn_r_15; -+ break; -+ case 16: -+ s->line_fn_tab[0] = blizzard_draw_fn_16; -+ s->line_fn_tab[1] = blizzard_draw_fn_r_16; -+ break; -+ case 24: -+ s->line_fn_tab[0] = blizzard_draw_fn_24; -+ s->line_fn_tab[1] = blizzard_draw_fn_r_24; -+ break; -+ case 32: -+ s->line_fn_tab[0] = blizzard_draw_fn_32; -+ s->line_fn_tab[1] = blizzard_draw_fn_r_32; -+ break; -+ default: -+ fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__); -+ exit(1); -+ } -+ -+ blizzard_reset(s); -+ -+ graphic_console_init(s->state, blizzard_update_display, -+ blizzard_invalidate_display, blizzard_screen_dump, -+ NULL, s); -+ -+ return s; -+} -diff --git a/hw/blizzard_template.h b/hw/blizzard_template.h -new file mode 100644 -index 0000000..8c6451d ---- /dev/null -+++ b/hw/blizzard_template.h -@@ -0,0 +1,138 @@ -+/* -+ * QEMU Epson S1D13744/S1D13745 templates -+ * -+ * Copyright (C) 2008 Nokia Corporation -+ * Written by Andrzej Zaborowski -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of -+ * the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, 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(blizzard_draw_line16_, DEPTH)(PIXEL_TYPE *dest, -+ const uint16_t *src, unsigned int width) -+{ -+#if !defined(SWAP_WORDS) && DEPTH == 16 -+ memcpy(dest, src, width << 1); -+#else -+ uint16_t data; -+ unsigned int r, g, b; -+ const uint16_t *end = (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(blizzard_draw_line24mode1_, DEPTH)(PIXEL_TYPE *dest, -+ const uint8_t *src, unsigned int width) -+{ -+ /* TODO: check if SDL 24-bit planes are not in the same format and -+ * if so, use memcpy */ -+ unsigned int r[2], g[2], b[2]; -+ const uint8_t *end = src + width; -+ while (src < end) { -+ g[0] = *src ++; -+ r[0] = *src ++; -+ r[1] = *src ++; -+ b[0] = *src ++; -+ COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[0], g[0], b[0])); -+ b[1] = *src ++; -+ g[1] = *src ++; -+ COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[1], g[1], b[1])); -+ } -+} -+ -+static void glue(blizzard_draw_line24mode2_, DEPTH)(PIXEL_TYPE *dest, -+ const uint8_t *src, unsigned int width) -+{ -+ unsigned int r, g, b; -+ const uint8_t *end = src + width; -+ while (src < end) { -+ r = *src ++; -+ src ++; -+ b = *src ++; -+ g = *src ++; -+ COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b)); -+ } -+} -+ -+/* No rotation */ -+static blizzard_fn_t glue(blizzard_draw_fn_, DEPTH)[0x10] = { -+ NULL, -+ /* RGB 5:6:5*/ -+ (blizzard_fn_t) glue(blizzard_draw_line16_, DEPTH), -+ /* RGB 6:6:6 mode 1 */ -+ (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH), -+ /* RGB 8:8:8 mode 1 */ -+ (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH), -+ NULL, NULL, -+ /* RGB 6:6:6 mode 2 */ -+ (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH), -+ /* RGB 8:8:8 mode 2 */ -+ (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH), -+ /* YUV 4:2:2 */ -+ NULL, -+ /* YUV 4:2:0 */ -+ NULL, -+ NULL, NULL, NULL, NULL, NULL, NULL, -+}; -+ -+/* 90deg, 180deg and 270deg rotation */ -+static blizzard_fn_t glue(blizzard_draw_fn_r_, DEPTH)[0x10] = { -+ /* TODO */ -+ [0 ... 0xf] = NULL, -+}; -+ -+#undef DEPTH -+#undef SKIP_PIXEL -+#undef COPY_PIXEL -+#undef COPY_PIXEL1 -+#undef PIXEL_TYPE -+ -+#undef SWAP_WORDS -diff --git a/hw/boards.h b/hw/boards.h -index affcaa6..408d1e8 100644 ---- a/hw/boards.h -+++ b/hw/boards.h -@@ -80,6 +80,9 @@ extern QEMUMachine terrierpda_machine; - /* palm.c */ - extern QEMUMachine palmte_machine; - -+/* nseries.c */ -+extern QEMUMachine n800_machine; -+ - /* gumstix.c */ - extern QEMUMachine connex_machine; - extern QEMUMachine verdex_machine; -diff --git a/hw/cbus.c b/hw/cbus.c -new file mode 100644 -index 0000000..001b007 ---- /dev/null -+++ b/hw/cbus.c -@@ -0,0 +1,565 @@ -+/* -+ * CBUS three-pin bus and the Retu / Betty / Tahvo / Vilma / Avilma / -+ * Hinku / Vinku / Ahne / Pihi chips used in various Nokia platforms. -+ * -+ * Copyright (C) 2008 Nokia Corporation -+ * Written by Andrzej Zaborowski -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of -+ * the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, -+ * MA 02111-1307 USA -+ */ -+ -+#include "qemu-common.h" -+#include "irq.h" -+#include "devices.h" -+#include "sysemu.h" -+ -+//#define DEBUG -+ -+struct cbus_slave_s; -+struct cbus_priv_s { -+ struct cbus_s cbus; -+ -+ int sel; -+ int dat; -+ int clk; -+ int bit; -+ int dir; -+ uint16_t val; -+ qemu_irq dat_out; -+ -+ int addr; -+ int reg; -+ int rw; -+ enum { -+ cbus_address, -+ cbus_value, -+ } cycle; -+ -+ struct cbus_slave_s *slave[8]; -+}; -+ -+struct cbus_slave_s { -+ void *opaque; -+ void (*io)(void *opaque, int rw, int reg, uint16_t *val); -+ int addr; -+}; -+ -+static void cbus_io(struct cbus_priv_s *s) -+{ -+ if (s->slave[s->addr]) -+ s->slave[s->addr]->io(s->slave[s->addr]->opaque, -+ s->rw, s->reg, &s->val); -+ else -+ cpu_abort(cpu_single_env, "%s: bad slave address %i\n", -+ __FUNCTION__, s->addr); -+} -+ -+static void cbus_cycle(struct cbus_priv_s *s) -+{ -+ switch (s->cycle) { -+ case cbus_address: -+ s->addr = (s->val >> 6) & 7; -+ s->rw = (s->val >> 5) & 1; -+ s->reg = (s->val >> 0) & 0x1f; -+ -+ s->cycle = cbus_value; -+ s->bit = 15; -+ s->dir = !s->rw; -+ s->val = 0; -+ -+ if (s->rw) -+ cbus_io(s); -+ break; -+ -+ case cbus_value: -+ if (!s->rw) -+ cbus_io(s); -+ -+ s->cycle = cbus_address; -+ s->bit = 8; -+ s->dir = 1; -+ s->val = 0; -+ break; -+ } -+} -+ -+static void cbus_clk(void *opaque, int line, int level) -+{ -+ struct cbus_priv_s *s = (struct cbus_priv_s *) opaque; -+ -+ if (!s->sel && level && !s->clk) { -+ if (s->dir) -+ s->val |= s->dat << (s->bit --); -+ else -+ qemu_set_irq(s->dat_out, (s->val >> (s->bit --)) & 1); -+ -+ if (s->bit < 0) -+ cbus_cycle(s); -+ } -+ -+ s->clk = level; -+} -+ -+static void cbus_dat(void *opaque, int line, int level) -+{ -+ struct cbus_priv_s *s = (struct cbus_priv_s *) opaque; -+ -+ s->dat = level; -+} -+ -+static void cbus_sel(void *opaque, int line, int level) -+{ -+ struct cbus_priv_s *s = (struct cbus_priv_s *) opaque; -+ -+ if (!level) { -+ s->dir = 1; -+ s->bit = 8; -+ s->val = 0; -+ } -+ -+ s->sel = level; -+} -+ -+struct cbus_s *cbus_init(qemu_irq dat) -+{ -+ struct cbus_priv_s *s = (struct cbus_priv_s *) qemu_mallocz(sizeof(*s)); -+ -+ s->dat_out = dat; -+ s->cbus.clk = qemu_allocate_irqs(cbus_clk, s, 1)[0]; -+ s->cbus.dat = qemu_allocate_irqs(cbus_dat, s, 1)[0]; -+ s->cbus.sel = qemu_allocate_irqs(cbus_sel, s, 1)[0]; -+ -+ s->sel = 1; -+ s->clk = 0; -+ s->dat = 0; -+ -+ return &s->cbus; -+} -+ -+void cbus_attach(struct cbus_s *bus, void *slave_opaque) -+{ -+ struct cbus_slave_s *slave = (struct cbus_slave_s *) slave_opaque; -+ struct cbus_priv_s *s = (struct cbus_priv_s *) bus; -+ -+ s->slave[slave->addr] = slave; -+} -+ -+/* Retu/Vilma */ -+struct cbus_retu_s { -+ uint16_t irqst; -+ uint16_t irqen; -+ uint16_t cc[2]; -+ int channel; -+ uint16_t result[16]; -+ uint16_t sample; -+ -+ struct { -+ uint16_t cal; -+ } rtc; -+ -+ int is_vilma; -+ qemu_irq irq; -+ struct cbus_slave_s cbus; -+}; -+ -+static void retu_interrupt_update(struct cbus_retu_s *s) -+{ -+ qemu_set_irq(s->irq, s->irqst & ~s->irqen); -+} -+ -+#define RETU_REG_ASICR 0x00 /* (RO) ASIC ID & revision */ -+#define RETU_REG_IDR 0x01 /* (T) Interrupt ID */ -+#define RETU_REG_IMR 0x02 /* (RW) Interrupt mask */ -+#define RETU_REG_RTCDSR 0x03 /* (RW) RTC seconds register */ -+#define RETU_REG_RTCHMR 0x04 /* (RO) RTC hours and minutes reg */ -+#define RETU_REG_RTCHMAR 0x05 /* (RW) RTC hours and minutes set reg */ -+#define RETU_REG_RTCCALR 0x06 /* (RW) RTC calibration register */ -+#define RETU_REG_ADCR 0x08 /* (RW) ADC result register */ -+#define RETU_REG_ADCSCR 0x09 /* (RW) ADC sample control register */ -+#define RETU_REG_AFCR 0x0a /* (RW) AFC register */ -+#define RETU_REG_ANTIFR 0x0b /* (RW) AntiF register */ -+#define RETU_REG_CALIBR 0x0c /* (RW) CalibR register*/ -+#define RETU_REG_CCR1 0x0d /* (RW) Common control register 1 */ -+#define RETU_REG_CCR2 0x0e /* (RW) Common control register 2 */ -+#define RETU_REG_RCTRL_CLR 0x0f /* (T) Regulator clear register */ -+#define RETU_REG_RCTRL_SET 0x10 /* (T) Regulator set register */ -+#define RETU_REG_TXCR 0x11 /* (RW) TxC register */ -+#define RETU_REG_STATUS 0x16 /* (RO) Status register */ -+#define RETU_REG_WATCHDOG 0x17 /* (RW) Watchdog register */ -+#define RETU_REG_AUDTXR 0x18 /* (RW) Audio Codec Tx register */ -+#define RETU_REG_AUDPAR 0x19 /* (RW) AudioPA register */ -+#define RETU_REG_AUDRXR1 0x1a /* (RW) Audio receive register 1 */ -+#define RETU_REG_AUDRXR2 0x1b /* (RW) Autio receive register 2 */ -+#define RETU_REG_SGR1 0x1c /* (RW) */ -+#define RETU_REG_SCR1 0x1d /* (RW) */ -+#define RETU_REG_SGR2 0x1e /* (RW) */ -+#define RETU_REG_SCR2 0x1f /* (RW) */ -+ -+/* Retu Interrupt sources */ -+enum { -+ retu_int_pwr = 0, /* Power */ -+ retu_int_char = 1, /* Charger */ -+ retu_int_rtcs = 2, /* Seconds */ -+ retu_int_rtcm = 3, /* Minutes */ -+ retu_int_rtcd = 4, /* Days */ -+ retu_int_rtca = 5, /* Alarm */ -+ retu_int_hook = 6, /* Hook */ -+ retu_int_head = 7, /* Headset */ -+ retu_int_adcs = 8, /* ADC sample */ -+}; -+ -+/* Retu ADC channel wiring */ -+enum { -+ retu_adc_bsi = 1, /* BSI */ -+ retu_adc_batt_temp = 2, /* Battery temperature */ -+ retu_adc_chg_volt = 3, /* Charger voltage */ -+ retu_adc_head_det = 4, /* Headset detection */ -+ retu_adc_hook_det = 5, /* Hook detection */ -+ retu_adc_rf_gp = 6, /* RF GP */ -+ retu_adc_tx_det = 7, /* Wideband Tx detection */ -+ retu_adc_batt_volt = 8, /* Battery voltage */ -+ retu_adc_sens = 10, /* Light sensor */ -+ retu_adc_sens_temp = 11, /* Light sensor temperature */ -+ retu_adc_bbatt_volt = 12, /* Backup battery voltage */ -+ retu_adc_self_temp = 13, /* RETU temperature */ -+}; -+ -+static inline uint16_t retu_read(struct cbus_retu_s *s, int reg) -+{ -+#ifdef DEBUG -+ printf("RETU read at %02x\n", reg); -+#endif -+ -+ switch (reg) { -+ case RETU_REG_ASICR: -+ return 0x0015 | (s->is_vilma << 7); -+ -+ case RETU_REG_IDR: -+ return s->irqst; -+ -+ case RETU_REG_IMR: -+ return s->irqen; -+ -+ case RETU_REG_RTCDSR: -+ case RETU_REG_RTCHMR: -+ case RETU_REG_RTCHMAR: -+ /* TODO */ -+ return 0x0000; -+ -+ case RETU_REG_RTCCALR: -+ return s->rtc.cal; -+ -+ case RETU_REG_ADCR: -+ return (s->channel << 10) | s->result[s->channel]; -+ case RETU_REG_ADCSCR: -+ return s->sample; -+ -+ case RETU_REG_AFCR: -+ case RETU_REG_ANTIFR: -+ case RETU_REG_CALIBR: -+ /* TODO */ -+ return 0x0000; -+ -+ case RETU_REG_CCR1: -+ return s->cc[0]; -+ case RETU_REG_CCR2: -+ return s->cc[1]; -+ -+ case RETU_REG_RCTRL_CLR: -+ case RETU_REG_RCTRL_SET: -+ case RETU_REG_TXCR: -+ case RETU_REG_STATUS: -+ case RETU_REG_WATCHDOG: -+ case RETU_REG_AUDTXR: -+ case RETU_REG_AUDPAR: -+ case RETU_REG_AUDRXR1: -+ case RETU_REG_AUDRXR2: -+ case RETU_REG_SGR1: -+ case RETU_REG_SCR1: -+ case RETU_REG_SGR2: -+ case RETU_REG_SCR2: -+ /* TODO */ -+ return 0x0000; -+ -+ default: -+ cpu_abort(cpu_single_env, "%s: bad register %02x\n", -+ __FUNCTION__, reg); -+ } -+} -+ -+static inline void retu_write(struct cbus_retu_s *s, int reg, uint16_t val) -+{ -+#ifdef DEBUG -+ printf("RETU write of %04x at %02x\n", val, reg); -+#endif -+ -+ switch (reg) { -+ case RETU_REG_IDR: -+ s->irqst ^= val; -+ retu_interrupt_update(s); -+ break; -+ -+ case RETU_REG_IMR: -+ s->irqen = val; -+ retu_interrupt_update(s); -+ break; -+ -+ case RETU_REG_RTCDSR: -+ case RETU_REG_RTCHMAR: -+ /* TODO */ -+ break; -+ -+ case RETU_REG_RTCCALR: -+ s->rtc.cal = val; -+ break; -+ -+ case RETU_REG_ADCR: -+ s->channel = (val >> 10) & 0xf; -+ s->irqst |= 1 << retu_int_adcs; -+ retu_interrupt_update(s); -+ break; -+ case RETU_REG_ADCSCR: -+ s->sample &= ~val; -+ break; -+ -+ case RETU_REG_AFCR: -+ case RETU_REG_ANTIFR: -+ case RETU_REG_CALIBR: -+ -+ case RETU_REG_CCR1: -+ s->cc[0] = val; -+ break; -+ case RETU_REG_CCR2: -+ s->cc[1] = val; -+ -+ break; -+ case RETU_REG_RCTRL_CLR: -+ case RETU_REG_RCTRL_SET: -+ case RETU_REG_STATUS: -+ /* TODO */ -+ break; -+ -+ case RETU_REG_WATCHDOG: -+ if (val == 0 && (s->cc[0] & 2)) -+ qemu_system_shutdown_request(); -+ break; -+ -+ case RETU_REG_TXCR: -+ case RETU_REG_AUDTXR: -+ case RETU_REG_AUDPAR: -+ case RETU_REG_AUDRXR1: -+ case RETU_REG_AUDRXR2: -+ case RETU_REG_SGR1: -+ case RETU_REG_SCR1: -+ case RETU_REG_SGR2: -+ case RETU_REG_SCR2: -+ /* TODO */ -+ break; -+ -+ default: -+ cpu_abort(cpu_single_env, "%s: bad register %02x\n", -+ __FUNCTION__, reg); -+ } -+} -+ -+static void retu_io(void *opaque, int rw, int reg, uint16_t *val) -+{ -+ struct cbus_retu_s *s = (struct cbus_retu_s *) opaque; -+ -+ if (rw) -+ *val = retu_read(s, reg); -+ else -+ retu_write(s, reg, *val); -+} -+ -+void *retu_init(qemu_irq irq, int vilma) -+{ -+ struct cbus_retu_s *s = (struct cbus_retu_s *) qemu_mallocz(sizeof(*s)); -+ -+ s->irq = irq; -+ s->irqen = 0xffff; -+ s->irqst = 0x0000; -+ s->is_vilma = !!vilma; -+ s->rtc.cal = 0x01; -+ s->result[retu_adc_bsi] = 0x100; -+ s->result[retu_adc_batt_temp] = 0x100; -+ s->result[retu_adc_chg_volt] = 0x200; -+ s->result[retu_adc_batt_volt] = 0x240; -+ s->result[retu_adc_sens] = 0x100; -+ s->result[retu_adc_sens_temp] = 0x100; -+ s->result[retu_adc_bbatt_volt] = 0x200; -+ s->result[retu_adc_self_temp] = 0x100; -+ -+ s->cbus.opaque = s; -+ s->cbus.io = retu_io; -+ s->cbus.addr = 1; -+ -+ return &s->cbus; -+} -+ -+/* Tahvo/Betty */ -+struct cbus_tahvo_s { -+ uint16_t irqst; -+ uint16_t irqen; -+ uint8_t charger; -+ uint8_t backlight; -+ uint16_t usbr; -+ uint16_t power; -+ -+ int is_betty; -+ qemu_irq irq; -+ struct cbus_slave_s cbus; -+}; -+ -+static void tahvo_interrupt_update(struct cbus_tahvo_s *s) -+{ -+ qemu_set_irq(s->irq, s->irqst & ~s->irqen); -+} -+ -+#define TAHVO_REG_ASICR 0x00 /* (RO) ASIC ID & revision */ -+#define TAHVO_REG_IDR 0x01 /* (T) Interrupt ID */ -+#define TAHVO_REG_IDSR 0x02 /* (RO) Interrupt status */ -+#define TAHVO_REG_IMR 0x03 /* (RW) Interrupt mask */ -+#define TAHVO_REG_CHAPWMR 0x04 /* (RW) Charger PWM */ -+#define TAHVO_REG_LEDPWMR 0x05 /* (RW) LED PWM */ -+#define TAHVO_REG_USBR 0x06 /* (RW) USB control */ -+#define TAHVO_REG_RCR 0x07 /* (RW) Some kind of power management */ -+#define TAHVO_REG_CCR1 0x08 /* (RW) Common control register 1 */ -+#define TAHVO_REG_CCR2 0x09 /* (RW) Common control register 2 */ -+#define TAHVO_REG_TESTR1 0x0a /* (RW) Test register 1 */ -+#define TAHVO_REG_TESTR2 0x0b /* (RW) Test register 2 */ -+#define TAHVO_REG_NOPR 0x0c /* (RW) Number of periods */ -+#define TAHVO_REG_FRR 0x0d /* (RO) FR */ -+ -+static inline uint16_t tahvo_read(struct cbus_tahvo_s *s, int reg) -+{ -+#ifdef DEBUG -+ printf("TAHVO read at %02x\n", reg); -+#endif -+ -+ switch (reg) { -+ case TAHVO_REG_ASICR: -+ return 0x0021 | (s->is_betty ? 0x0b00 : 0x0300); -+ -+ case TAHVO_REG_IDR: -+ case TAHVO_REG_IDSR: /* XXX: what does this do? */ -+ return s->irqst; -+ -+ case TAHVO_REG_IMR: -+ return s->irqen; -+ -+ case TAHVO_REG_CHAPWMR: -+ return s->charger; -+ -+ case TAHVO_REG_LEDPWMR: -+ return s->backlight; -+ -+ case TAHVO_REG_USBR: -+ return s->usbr; -+ -+ case TAHVO_REG_RCR: -+ return s->power; -+ -+ case TAHVO_REG_CCR1: -+ case TAHVO_REG_CCR2: -+ case TAHVO_REG_TESTR1: -+ case TAHVO_REG_TESTR2: -+ case TAHVO_REG_NOPR: -+ case TAHVO_REG_FRR: -+ return 0x0000; -+ -+ default: -+ cpu_abort(cpu_single_env, "%s: bad register %02x\n", -+ __FUNCTION__, reg); -+ } -+} -+ -+static inline void tahvo_write(struct cbus_tahvo_s *s, int reg, uint16_t val) -+{ -+#ifdef DEBUG -+ printf("TAHVO write of %04x at %02x\n", val, reg); -+#endif -+ -+ switch (reg) { -+ case TAHVO_REG_IDR: -+ s->irqst ^= val; -+ tahvo_interrupt_update(s); -+ break; -+ -+ case TAHVO_REG_IMR: -+ s->irqen = val; -+ tahvo_interrupt_update(s); -+ break; -+ -+ case TAHVO_REG_CHAPWMR: -+ s->charger = val; -+ break; -+ -+ case TAHVO_REG_LEDPWMR: -+ if (s->backlight != (val & 0x7f)) { -+ s->backlight = val & 0x7f; -+ printf("%s: LCD backlight now at %i / 127\n", -+ __FUNCTION__, s->backlight); -+ } -+ break; -+ -+ case TAHVO_REG_USBR: -+ s->usbr = val; -+ break; -+ -+ case TAHVO_REG_RCR: -+ s->power = val; -+ break; -+ -+ case TAHVO_REG_CCR1: -+ case TAHVO_REG_CCR2: -+ case TAHVO_REG_TESTR1: -+ case TAHVO_REG_TESTR2: -+ case TAHVO_REG_NOPR: -+ case TAHVO_REG_FRR: -+ break; -+ -+ default: -+ cpu_abort(cpu_single_env, "%s: bad register %02x\n", -+ __FUNCTION__, reg); -+ } -+} -+ -+static void tahvo_io(void *opaque, int rw, int reg, uint16_t *val) -+{ -+ struct cbus_tahvo_s *s = (struct cbus_tahvo_s *) opaque; -+ -+ if (rw) -+ *val = tahvo_read(s, reg); -+ else -+ tahvo_write(s, reg, *val); -+} -+ -+void *tahvo_init(qemu_irq irq, int betty) -+{ -+ struct cbus_tahvo_s *s = (struct cbus_tahvo_s *) qemu_mallocz(sizeof(*s)); -+ -+ s->irq = irq; -+ s->irqen = 0xffff; -+ s->irqst = 0x0000; -+ s->is_betty = !!betty; -+ -+ s->cbus.opaque = s; -+ s->cbus.io = tahvo_io; -+ s->cbus.addr = 2; -+ -+ return &s->cbus; -+} -diff --git a/hw/devices.h b/hw/devices.h -index 07c673b..6f1d27b 100644 ---- a/hw/devices.h -+++ b/hw/devices.h -@@ -16,7 +16,38 @@ uint32_t ads7846_read(void *opaque); - void ads7846_write(void *opaque, uint32_t value); - struct ads7846_state_s *ads7846_init(qemu_irq penirq); - -+/* tsc210x.c */ -+struct uwire_slave_s; -+struct mouse_transform_info_s; -+struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio); -+struct uwire_slave_s *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, -+ qemu_irq dav, AudioState *audio); -+struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip); -+uint32_t tsc210x_txrx(void *opaque, uint32_t value); -+void tsc210x_set_transform(struct uwire_slave_s *chip, -+ struct mouse_transform_info_s *info); -+void tsc210x_key_event(struct uwire_slave_s *chip, int key, int down); -+ - /* stellaris_input.c */ - void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode); - -+/* blizzard.c */ -+void *s1d13745_init(qemu_irq gpio_int, DisplayState *ds); -+void s1d13745_write(void *opaque, int dc, uint16_t value); -+void s1d13745_write_block(void *opaque, int dc, -+ void *buf, size_t len, int pitch); -+uint16_t s1d13745_read(void *opaque, int dc); -+ -+/* cbus.c */ -+struct cbus_s { -+ qemu_irq clk; -+ qemu_irq dat; -+ qemu_irq sel; -+}; -+struct cbus_s *cbus_init(qemu_irq dat_out); -+void cbus_attach(struct cbus_s *bus, void *slave_opaque); -+ -+void *retu_init(qemu_irq irq, int vilma); -+void *tahvo_init(qemu_irq irq, int betty); -+ - #endif -diff --git a/hw/flash.h b/hw/flash.h -index 42d25fe..c000d33 100644 ---- a/hw/flash.h -+++ b/hw/flash.h -@@ -34,6 +34,11 @@ uint8_t nand_getio(struct nand_flash_s *s); - #define NAND_MFR_HYNIX 0xad - #define NAND_MFR_MICRON 0x2c - -+/* onenand.c */ -+void onenand_base_update(void *opaque, target_phys_addr_t new); -+void onenand_base_unmap(void *opaque); -+void *onenand_init(uint32_t id, int regshift, qemu_irq irq); -+ - /* ecc.c */ - struct ecc_state_s { - uint8_t cp; /* Column parity */ -diff --git a/hw/i2c.h b/hw/i2c.h -index 2897036..fae46b7 100644 ---- a/hw/i2c.h -+++ b/hw/i2c.h -@@ -71,4 +71,14 @@ uint32_t wm8750_adc_dat(void *opaque); - /* ssd0303.c */ - void ssd0303_init(DisplayState *ds, i2c_bus *bus, int address); - -+/* twl92230.c */ -+i2c_slave *twl92230_init(i2c_bus *bus, qemu_irq irq); -+qemu_irq *twl92230_gpio_in_get(i2c_slave *i2c); -+void twl92230_gpio_out_set(i2c_slave *i2c, int line, qemu_irq handler); -+ -+/* tmp105.c */ -+struct i2c_slave *tmp105_init(i2c_bus *bus, qemu_irq alarm); -+void tmp105_reset(i2c_slave *i2c); -+void tmp105_set(i2c_slave *i2c, int temp); -+ - #endif -diff --git a/hw/integratorcp.c b/hw/integratorcp.c -index 549cc25..f6e6364 100644 ---- a/hw/integratorcp.c -+++ b/hw/integratorcp.c -@@ -469,6 +469,11 @@ static void icp_control_init(uint32_t base) - - /* Board init. */ - -+static struct arm_boot_info integrator_binfo = { -+ .loader_start = 0x0, -+ .board_id = 0x113, -+}; -+ - static void integratorcp_init(int ram_size, int vga_ram_size, - const char *boot_device, DisplayState *ds, - const char *kernel_filename, const char *kernel_cmdline, -@@ -527,8 +532,11 @@ static void integratorcp_init(int ram_size, int vga_ram_size, - } - pl110_init(ds, 0xc0000000, pic[22], 0); - -- arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline, -- initrd_filename, 0x113, 0x0); -+ integrator_binfo.ram_size = ram_size; -+ integrator_binfo.kernel_filename = kernel_filename; -+ integrator_binfo.kernel_cmdline = kernel_cmdline; -+ integrator_binfo.initrd_filename = initrd_filename; -+ arm_load_kernel(env, &integrator_binfo); - } - - QEMUMachine integratorcp_machine = { -diff --git a/hw/mainstone.c b/hw/mainstone.c -index 5856791..9564fc3 100644 ---- a/hw/mainstone.c -+++ b/hw/mainstone.c -@@ -59,12 +59,17 @@ static struct keymap map[0xE0] = { - - enum mainstone_model_e { mainstone }; - -+static struct arm_boot_info mainstone_binfo = { -+ .loader_start = PXA2XX_SDRAM_BASE, -+ .ram_size = 0x04000000, -+}; -+ - static void mainstone_common_init(int ram_size, int vga_ram_size, - DisplayState *ds, const char *kernel_filename, - const char *kernel_cmdline, const char *initrd_filename, - const char *cpu_model, enum mainstone_model_e model, int arm_id) - { -- uint32_t mainstone_ram = 0x04000000; -+ uint32_t mainstone_ram = mainstone_binfo.ram_size; - uint32_t mainstone_rom = 0x00800000; - uint32_t mainstone_flash = 0x02000000; - uint32_t sector_len = 256 * 1024; -@@ -90,7 +95,7 @@ static void mainstone_common_init(int ram_size, int vga_ram_size, - qemu_ram_alloc(mainstone_rom) | IO_MEM_ROM); - - /* Setup initial (reset) machine state */ -- cpu->env->regs[15] = PXA2XX_SDRAM_BASE; -+ cpu->env->regs[15] = mainstone_binfo.loader_start; - - /* There are two 32MiB flash devices on the board */ - for (i = 0; i < 2; i ++) { -@@ -121,8 +126,11 @@ static void mainstone_common_init(int ram_size, int vga_ram_size, - - smc91c111_init(&nd_table[0], MST_ETH_PHYS, mst_irq[ETHERNET_IRQ]); - -- arm_load_kernel(cpu->env, mainstone_ram, kernel_filename, kernel_cmdline, -- initrd_filename, arm_id, PXA2XX_SDRAM_BASE); -+ mainstone_binfo.kernel_filename = kernel_filename; -+ mainstone_binfo.kernel_cmdline = kernel_cmdline; -+ mainstone_binfo.initrd_filename = initrd_filename; -+ mainstone_binfo.board_id = arm_id; -+ arm_load_kernel(cpu->env, &mainstone_binfo); - } - - static void mainstone_init(int ram_size, int vga_ram_size, -diff --git a/hw/max7310.c b/hw/max7310.c -index 75e56c7..397950a 100644 ---- a/hw/max7310.c -+++ b/hw/max7310.c -@@ -134,8 +134,8 @@ static void max7310_event(i2c_slave *i2c, enum i2c_event event) - s->i2c_command_byte = 1; - break; - case I2C_FINISH: -- if (s->len == 1) - #ifdef VERBOSE -+ if (s->len == 1) - printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len); - #endif - break; -diff --git a/hw/nseries.c b/hw/nseries.c -new file mode 100644 -index 0000000..0425d46 ---- /dev/null -+++ b/hw/nseries.c -@@ -0,0 +1,870 @@ -+/* -+ * Nokia N-series internet tablets. -+ * -+ * Copyright (C) 2007 Nokia Corporation -+ * Written by Andrzej Zaborowski -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of -+ * the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, -+ * MA 02111-1307 USA -+ */ -+ -+#include "qemu-common.h" -+#include "sysemu.h" -+#include "omap.h" -+#include "arm-misc.h" -+#include "irq.h" -+#include "console.h" -+#include "boards.h" -+#include "i2c.h" -+#include "devices.h" -+#include "flash.h" -+#include "hw.h" -+ -+/* Nokia N800 support */ -+struct n800_s { -+ struct omap_mpu_state_s *cpu; -+ -+ struct rfbi_chip_s blizzard; -+ struct uwire_slave_s *ts; -+ i2c_bus *i2c; -+ -+ int keymap[0x80]; -+}; -+ -+#define N800_MMC2_WP_GPIO 8 -+#define N800_CAM_TURN_GPIO 12 -+#define N800_BLIZZARD_POWERDOWN_GPIO 15 -+#define N800_MMC1_WP_GPIO 23 -+#define N800_ONENAND_GPIO 26 -+#define N800_BT_WKUP_GPIO 61 -+#define N800_STI_GPIO 62 -+#define N800_CBUS_SEL_GPIO 64 -+#define N800_CBUS_CLK_GPIO 65 -+#define N800_CBUS_DAT_GPIO 66 -+#define N800_WLAN_IRQ_GPIO 87 -+#define N800_BT_RESET_GPIO 92 -+#define N800_TEA5761_CS_GPIO 93 -+#define N800_UNKNOWN_GPIO 94 -+#define N800_CAM_ACT_GPIO 95 -+#define N800_MMC_CS_GPIO 96 -+#define N800_WLAN_PWR_GPIO 97 -+#define N800_BT_HOST_WKUP_GPIO 98 -+#define N800_TSC_TS_GPIO 103 -+#define N800_HEADPHONE_GPIO 107 -+#define N800_RETU_GPIO 108 -+#define N800_TSC_KP_IRQ_GPIO 109 -+#define N800_BAT_COVER_GPIO 110 -+#define N800_TAHVO_GPIO 111 -+#define N800_TSC_RESET_GPIO 119 -+#define N800_TMP105_GPIO 125 -+ -+#define XLDR_LL_UART 1 -+ -+#define N800_TMP105_ADDR 0x48 -+#define N800_MENELAUS_ADDR 0x72 -+ -+static void n800_mmc_cs_cb(void *opaque, int line, int level) -+{ -+ /* TODO: this seems to actually be connected to the menelaus, to -+ * which also both MMC slots connect. */ -+ omap_mmc_enable((struct omap_mmc_s *) opaque, !level); -+ -+ printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1); -+} -+ -+static void n800_gpio_setup(struct n800_s *s) -+{ -+ qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->cpu->mmc, 1); -+ omap2_gpio_out_set(s->cpu->gpif, N800_MMC_CS_GPIO, mmc_cs[0]); -+ -+ qemu_irq_lower(omap2_gpio_in_get(s->cpu->gpif, N800_BAT_COVER_GPIO)[0]); -+} -+ -+static void n800_nand_setup(struct n800_s *s) -+{ -+ /* Either ec40xx or ec48xx are OK for the ID */ -+ omap_gpmc_attach(s->cpu->gpmc, 0, 0, onenand_base_update, -+ onenand_base_unmap, -+ onenand_init(0xec4800, 1, -+ omap2_gpio_in_get(s->cpu->gpif, -+ N800_ONENAND_GPIO)[0])); -+} -+ -+static void n800_i2c_setup(struct n800_s *s) -+{ -+ qemu_irq tmp_irq = omap2_gpio_in_get(s->cpu->gpif, N800_TMP105_GPIO)[0]; -+ -+ /* Attach the CPU on one end of our I2C bus. */ -+ s->i2c = omap_i2c_bus(s->cpu->i2c[0]); -+ -+ /* Attach a menelaus PM chip */ -+ i2c_set_slave_address( -+ twl92230_init(s->i2c, -+ s->cpu->irq[0][OMAP_INT_24XX_SYS_NIRQ]), -+ N800_MENELAUS_ADDR); -+ -+ /* Attach a TMP105 PM chip (A0 wired to ground) */ -+ i2c_set_slave_address(tmp105_init(s->i2c, tmp_irq), N800_TMP105_ADDR); -+} -+ -+/* Touchscreen and keypad controller */ -+static void n800_key_event(void *opaque, int keycode) -+{ -+ struct n800_s *s = (struct n800_s *) opaque; -+ int code = s->keymap[keycode & 0x7f]; -+ -+ if (code == -1) -+ return; -+ -+ tsc210x_key_event(s->ts, code, !(keycode & 0x80)); -+} -+ -+static const int n800_keys[16] = { -+ -1, -+ 72, /* Up */ -+ 63, /* Home (F5) */ -+ -1, -+ 75, /* Left */ -+ 28, /* Enter */ -+ 77, /* Right */ -+ -1, -+ 1, /* Cycle (ESC) */ -+ 80, /* Down */ -+ 62, /* Menu (F4) */ -+ -1, -+ 66, /* Zoom- (F8) */ -+ 64, /* FS (F6) */ -+ 65, /* Zoom+ (F7) */ -+ -1, -+}; -+ -+static struct mouse_transform_info_s n800_pointercal = { -+ .x = 800, -+ .y = 480, -+ .a = { 14560, -68, -3455208, -39, -9621, 35152972, 65536 }, -+}; -+ -+static void n800_tsc_setup(struct n800_s *s) -+{ -+ int i; -+ -+ /* XXX: are the three pins inverted inside the chip between the -+ * tsc and the cpu (N4111)? */ -+ qemu_irq penirq = 0; /* NC */ -+ qemu_irq kbirq = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_KP_IRQ_GPIO)[0]; -+ qemu_irq dav = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_TS_GPIO)[0]; -+ -+ s->ts = tsc2301_init(penirq, kbirq, dav, 0); -+ -+ for (i = 0; i < 0x80; i ++) -+ s->keymap[i] = -1; -+ for (i = 0; i < 0x10; i ++) -+ if (n800_keys[i] >= 0) -+ s->keymap[n800_keys[i]] = i; -+ -+ qemu_add_kbd_event_handler(n800_key_event, s); -+ -+ tsc210x_set_transform(s->ts, &n800_pointercal); -+} -+ -+/* LCD MIPI DBI-C controller (URAL) */ -+struct mipid_s { -+ int resp[4]; -+ int param[4]; -+ int p; -+ int pm; -+ int cmd; -+ -+ int sleep; -+ int booster; -+ int te; -+ int selfcheck; -+ int partial; -+ int normal; -+ int vscr; -+ int invert; -+ int onoff; -+ int gamma; -+ uint32_t id; -+}; -+ -+static void mipid_reset(struct mipid_s *s) -+{ -+ if (!s->sleep) -+ fprintf(stderr, "%s: Display off\n", __FUNCTION__); -+ -+ s->pm = 0; -+ s->cmd = 0; -+ -+ s->sleep = 1; -+ s->booster = 0; -+ s->selfcheck = -+ (1 << 7) | /* Register loading OK. */ -+ (1 << 5) | /* The chip is attached. */ -+ (1 << 4); /* Display glass still in one piece. */ -+ s->te = 0; -+ s->partial = 0; -+ s->normal = 1; -+ s->vscr = 0; -+ s->invert = 0; -+ s->onoff = 1; -+ s->gamma = 0; -+} -+ -+static uint32_t mipid_txrx(void *opaque, uint32_t cmd) -+{ -+ struct mipid_s *s = (struct mipid_s *) opaque; -+ uint8_t ret; -+ -+ if (s->p >= sizeof(s->resp) / sizeof(*s->resp)) -+ ret = 0; -+ else -+ ret = s->resp[s->p ++]; -+ if (s->pm --> 0) -+ s->param[s->pm] = cmd; -+ else -+ s->cmd = cmd; -+ -+ switch (s->cmd) { -+ case 0x00: /* NOP */ -+ break; -+ -+ case 0x01: /* SWRESET */ -+ mipid_reset(s); -+ break; -+ -+ case 0x02: /* BSTROFF */ -+ s->booster = 0; -+ break; -+ case 0x03: /* BSTRON */ -+ s->booster = 1; -+ break; -+ -+ case 0x04: /* RDDID */ -+ s->p = 0; -+ s->resp[0] = (s->id >> 16) & 0xff; -+ s->resp[1] = (s->id >> 8) & 0xff; -+ s->resp[2] = (s->id >> 0) & 0xff; -+ break; -+ -+ case 0x06: /* RD_RED */ -+ case 0x07: /* RD_GREEN */ -+ /* XXX the bootloader sometimes issues RD_BLUE meaning RDDID so -+ * for the bootloader one needs to change this. */ -+ case 0x08: /* RD_BLUE */ -+ s->p = 0; -+ /* TODO: return first pixel components */ -+ s->resp[0] = 0x01; -+ break; -+ -+ case 0x09: /* RDDST */ -+ s->p = 0; -+ s->resp[0] = s->booster << 7; -+ s->resp[1] = (5 << 4) | (s->partial << 2) | -+ (s->sleep << 1) | s->normal; -+ s->resp[2] = (s->vscr << 7) | (s->invert << 5) | -+ (s->onoff << 2) | (s->te << 1) | (s->gamma >> 2); -+ s->resp[3] = s->gamma << 6; -+ break; -+ -+ case 0x0a: /* RDDPM */ -+ s->p = 0; -+ s->resp[0] = (s->onoff << 2) | (s->normal << 3) | (s->sleep << 4) | -+ (s->partial << 5) | (s->sleep << 6) | (s->booster << 7); -+ break; -+ case 0x0b: /* RDDMADCTR */ -+ s->p = 0; -+ s->resp[0] = 0; -+ break; -+ case 0x0c: /* RDDCOLMOD */ -+ s->p = 0; -+ s->resp[0] = 5; /* 65K colours */ -+ break; -+ case 0x0d: /* RDDIM */ -+ s->p = 0; -+ s->resp[0] = (s->invert << 5) | (s->vscr << 7) | s->gamma; -+ break; -+ case 0x0e: /* RDDSM */ -+ s->p = 0; -+ s->resp[0] = s->te << 7; -+ break; -+ case 0x0f: /* RDDSDR */ -+ s->p = 0; -+ s->resp[0] = s->selfcheck; -+ break; -+ -+ case 0x10: /* SLPIN */ -+ s->sleep = 1; -+ break; -+ case 0x11: /* SLPOUT */ -+ s->sleep = 0; -+ s->selfcheck ^= 1 << 6; /* POFF self-diagnosis Ok */ -+ break; -+ -+ case 0x12: /* PTLON */ -+ s->partial = 1; -+ s->normal = 0; -+ s->vscr = 0; -+ break; -+ case 0x13: /* NORON */ -+ s->partial = 0; -+ s->normal = 1; -+ s->vscr = 0; -+ break; -+ -+ case 0x20: /* INVOFF */ -+ s->invert = 0; -+ break; -+ case 0x21: /* INVON */ -+ s->invert = 1; -+ break; -+ -+ case 0x22: /* APOFF */ -+ case 0x23: /* APON */ -+ goto bad_cmd; -+ -+ case 0x25: /* WRCNTR */ -+ if (s->pm < 0) -+ s->pm = 1; -+ goto bad_cmd; -+ -+ case 0x26: /* GAMSET */ -+ if (!s->pm) -+ s->gamma = ffs(s->param[0] & 0xf) - 1; -+ else if (s->pm < 0) -+ s->pm = 1; -+ break; -+ -+ case 0x28: /* DISPOFF */ -+ s->onoff = 0; -+ fprintf(stderr, "%s: Display off\n", __FUNCTION__); -+ break; -+ case 0x29: /* DISPON */ -+ s->onoff = 1; -+ fprintf(stderr, "%s: Display on\n", __FUNCTION__); -+ break; -+ -+ case 0x2a: /* CASET */ -+ case 0x2b: /* RASET */ -+ case 0x2c: /* RAMWR */ -+ case 0x2d: /* RGBSET */ -+ case 0x2e: /* RAMRD */ -+ case 0x30: /* PTLAR */ -+ case 0x33: /* SCRLAR */ -+ goto bad_cmd; -+ -+ case 0x34: /* TEOFF */ -+ s->te = 0; -+ break; -+ case 0x35: /* TEON */ -+ if (!s->pm) -+ s->te = 1; -+ else if (s->pm < 0) -+ s->pm = 1; -+ break; -+ -+ case 0x36: /* MADCTR */ -+ goto bad_cmd; -+ -+ case 0x37: /* VSCSAD */ -+ s->partial = 0; -+ s->normal = 0; -+ s->vscr = 1; -+ break; -+ -+ case 0x38: /* IDMOFF */ -+ case 0x39: /* IDMON */ -+ case 0x3a: /* COLMOD */ -+ goto bad_cmd; -+ -+ case 0xb0: /* CLKINT / DISCTL */ -+ case 0xb1: /* CLKEXT */ -+ if (s->pm < 0) -+ s->pm = 2; -+ break; -+ -+ case 0xb4: /* FRMSEL */ -+ break; -+ -+ case 0xb5: /* FRM8SEL */ -+ case 0xb6: /* TMPRNG / INIESC */ -+ case 0xb7: /* TMPHIS / NOP2 */ -+ case 0xb8: /* TMPREAD / MADCTL */ -+ case 0xba: /* DISTCTR */ -+ case 0xbb: /* EPVOL */ -+ goto bad_cmd; -+ -+ case 0xbd: /* Unknown */ -+ s->p = 0; -+ s->resp[0] = 0; -+ s->resp[1] = 1; -+ break; -+ -+ case 0xc2: /* IFMOD */ -+ if (s->pm < 0) -+ s->pm = 2; -+ break; -+ -+ case 0xc6: /* PWRCTL */ -+ case 0xc7: /* PPWRCTL */ -+ case 0xd0: /* EPWROUT */ -+ case 0xd1: /* EPWRIN */ -+ case 0xd4: /* RDEV */ -+ case 0xd5: /* RDRR */ -+ goto bad_cmd; -+ -+ case 0xda: /* RDID1 */ -+ s->p = 0; -+ s->resp[0] = (s->id >> 16) & 0xff; -+ break; -+ case 0xdb: /* RDID2 */ -+ s->p = 0; -+ s->resp[0] = (s->id >> 8) & 0xff; -+ break; -+ case 0xdc: /* RDID3 */ -+ s->p = 0; -+ s->resp[0] = (s->id >> 0) & 0xff; -+ break; -+ -+ default: -+ bad_cmd: -+ fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, s->cmd); -+ break; -+ } -+ -+ return ret; -+} -+ -+static void *mipid_init(void) -+{ -+ struct mipid_s *s = (struct mipid_s *) qemu_mallocz(sizeof(*s)); -+ -+ s->id = 0x838f03; -+ mipid_reset(s); -+ -+ return s; -+} -+ -+static void n800_spi_setup(struct n800_s *s) -+{ -+ void *tsc2301 = s->ts->opaque; -+ void *mipid = mipid_init(); -+ -+ omap_mcspi_attach(s->cpu->mcspi[0], tsc210x_txrx, tsc2301, 0); -+ omap_mcspi_attach(s->cpu->mcspi[0], mipid_txrx, mipid, 1); -+} -+ -+/* This task is normally performed by the bootloader. If we're loading -+ * a kernel directly, we need to enable the Blizzard ourselves. */ -+static void n800_dss_init(struct rfbi_chip_s *chip) -+{ -+ chip->write(chip->opaque, 0, 0x2a); /* LCD Width register */ -+ chip->write(chip->opaque, 1, 0x64); -+ chip->write(chip->opaque, 0, 0x2c); /* LCD HNDP register */ -+ chip->write(chip->opaque, 1, 0x1e); -+ chip->write(chip->opaque, 0, 0x2e); /* LCD Height 0 register */ -+ chip->write(chip->opaque, 1, 0xe0); -+ chip->write(chip->opaque, 0, 0x30); /* LCD Height 1 register */ -+ chip->write(chip->opaque, 1, 0x01); -+ chip->write(chip->opaque, 0, 0x32); /* LCD VNDP register */ -+ chip->write(chip->opaque, 1, 0x06); -+ chip->write(chip->opaque, 0, 0x68); /* Display Mode register */ -+ chip->write(chip->opaque, 1, 1); /* Enable bit */ -+} -+ -+static void n800_dss_setup(struct n800_s *s, DisplayState *ds) -+{ -+ s->blizzard.opaque = s1d13745_init(0, ds); -+ s->blizzard.block = s1d13745_write_block; -+ s->blizzard.write = s1d13745_write; -+ s->blizzard.read = s1d13745_read; -+ -+ omap_rfbi_attach(s->cpu->dss, 0, &s->blizzard); -+} -+ -+static void n800_cbus_setup(struct n800_s *s) -+{ -+ qemu_irq dat_out = omap2_gpio_in_get(s->cpu->gpif, N800_CBUS_DAT_GPIO)[0]; -+ qemu_irq retu_irq = omap2_gpio_in_get(s->cpu->gpif, N800_RETU_GPIO)[0]; -+ qemu_irq tahvo_irq = omap2_gpio_in_get(s->cpu->gpif, N800_TAHVO_GPIO)[0]; -+ -+ struct cbus_s *cbus = cbus_init(dat_out); -+ -+ omap2_gpio_out_set(s->cpu->gpif, N800_CBUS_CLK_GPIO, cbus->clk); -+ omap2_gpio_out_set(s->cpu->gpif, N800_CBUS_DAT_GPIO, cbus->dat); -+ omap2_gpio_out_set(s->cpu->gpif, N800_CBUS_SEL_GPIO, cbus->sel); -+ -+ cbus_attach(cbus, retu_init(retu_irq, 1)); -+ cbus_attach(cbus, tahvo_init(tahvo_irq, 1)); -+} -+ -+/* This task is normally performed by the bootloader. If we're loading -+ * a kernel directly, we need to set up GPMC mappings ourselves. */ -+static void n800_gpmc_init(struct n800_s *s) -+{ -+ uint32_t config7 = -+ (0xf << 8) | /* MASKADDRESS */ -+ (1 << 6) | /* CSVALID */ -+ (4 << 0); /* BASEADDRESS */ -+ -+ cpu_physical_memory_write(0x6800a078, /* GPMC_CONFIG7_0 */ -+ (void *) &config7, sizeof(config7)); -+} -+ -+#if 0 -+static uint32_t n800_pinout[104] = { -+ 0x080f00d8, 0x00d40808, 0x03080808, 0x080800d0, -+ 0x00dc0808, 0x0b0f0f00, 0x080800b4, 0x00c00808, -+ 0x08080808, 0x180800c4, 0x00b80000, 0x08080808, -+ 0x080800bc, 0x00cc0808, 0x08081818, 0x18180128, -+ 0x01241800, 0x18181818, 0x000000f0, 0x01300000, -+ 0x00001b0b, 0x1b0f0138, 0x00e0181b, 0x1b031b0b, -+ 0x180f0078, 0x00740018, 0x0f0f0f1a, 0x00000080, -+ 0x007c0000, 0x00000000, 0x00000088, 0x00840000, -+ 0x00000000, 0x00000094, 0x00980300, 0x0f180003, -+ 0x0000008c, 0x00900f0f, 0x0f0f1b00, 0x0f00009c, -+ 0x01140000, 0x1b1b0f18, 0x0818013c, 0x01400008, -+ 0x00001818, 0x000b0110, 0x010c1800, 0x0b030b0f, -+ 0x181800f4, 0x00f81818, 0x00000018, 0x000000fc, -+ 0x00401808, 0x00000000, 0x0f1b0030, 0x003c0008, -+ 0x00000000, 0x00000038, 0x00340000, 0x00000000, -+ 0x1a080070, 0x00641a1a, 0x08080808, 0x08080060, -+ 0x005c0808, 0x08080808, 0x08080058, 0x00540808, -+ 0x08080808, 0x0808006c, 0x00680808, 0x08080808, -+ 0x000000a8, 0x00b00000, 0x08080808, 0x000000a0, -+ 0x00a40000, 0x00000000, 0x08ff0050, 0x004c0808, -+ 0xffffffff, 0xffff0048, 0x0044ffff, 0xffffffff, -+ 0x000000ac, 0x01040800, 0x08080b0f, 0x18180100, -+ 0x01081818, 0x0b0b1808, 0x1a0300e4, 0x012c0b1a, -+ 0x02020018, 0x0b000134, 0x011c0800, 0x0b1b1b00, -+ 0x0f0000c8, 0x00ec181b, 0x000f0f02, 0x00180118, -+ 0x01200000, 0x0f0b1b1b, 0x0f0200e8, 0x0000020b, -+}; -+#endif -+ -+/* Setup sequence done by the bootloader */ -+static void n800_boot_init(void *opaque) -+{ -+ struct n800_s *s = (struct n800_s *) opaque; -+ uint32_t buf; -+ -+ /* PRCM setup */ -+#define omap_writel(addr, val) \ -+ buf = (val); \ -+ cpu_physical_memory_write(addr, (void *) &buf, sizeof(buf)) -+ -+ omap_writel(0x48008060, 0x41); /* PRCM_CLKSRC_CTRL */ -+ omap_writel(0x48008070, 1); /* PRCM_CLKOUT_CTRL */ -+ omap_writel(0x48008078, 0); /* PRCM_CLKEMUL_CTRL */ -+ omap_writel(0x48008090, 0); /* PRCM_VOLTSETUP */ -+ omap_writel(0x48008094, 0); /* PRCM_CLKSSETUP */ -+ omap_writel(0x48008098, 0); /* PRCM_POLCTRL */ -+ omap_writel(0x48008140, 2); /* CM_CLKSEL_MPU */ -+ omap_writel(0x48008148, 0); /* CM_CLKSTCTRL_MPU */ -+ omap_writel(0x48008158, 1); /* RM_RSTST_MPU */ -+ omap_writel(0x480081c8, 0x15); /* PM_WKDEP_MPU */ -+ omap_writel(0x480081d4, 0x1d4); /* PM_EVGENCTRL_MPU */ -+ omap_writel(0x480081d8, 0); /* PM_EVEGENONTIM_MPU */ -+ omap_writel(0x480081dc, 0); /* PM_EVEGENOFFTIM_MPU */ -+ omap_writel(0x480081e0, 0xc); /* PM_PWSTCTRL_MPU */ -+ omap_writel(0x48008200, 0x047e7ff7); /* CM_FCLKEN1_CORE */ -+ omap_writel(0x48008204, 0x00000004); /* CM_FCLKEN2_CORE */ -+ omap_writel(0x48008210, 0x047e7ff1); /* CM_ICLKEN1_CORE */ -+ omap_writel(0x48008214, 0x00000004); /* CM_ICLKEN2_CORE */ -+ omap_writel(0x4800821c, 0x00000000); /* CM_ICLKEN4_CORE */ -+ omap_writel(0x48008230, 0); /* CM_AUTOIDLE1_CORE */ -+ omap_writel(0x48008234, 0); /* CM_AUTOIDLE2_CORE */ -+ omap_writel(0x48008238, 7); /* CM_AUTOIDLE3_CORE */ -+ omap_writel(0x4800823c, 0); /* CM_AUTOIDLE4_CORE */ -+ omap_writel(0x48008240, 0x04360626); /* CM_CLKSEL1_CORE */ -+ omap_writel(0x48008244, 0x00000014); /* CM_CLKSEL2_CORE */ -+ omap_writel(0x48008248, 0); /* CM_CLKSTCTRL_CORE */ -+ omap_writel(0x48008300, 0x00000000); /* CM_FCLKEN_GFX */ -+ omap_writel(0x48008310, 0x00000000); /* CM_ICLKEN_GFX */ -+ omap_writel(0x48008340, 0x00000001); /* CM_CLKSEL_GFX */ -+ omap_writel(0x48008400, 0x00000004); /* CM_FCLKEN_WKUP */ -+ omap_writel(0x48008410, 0x00000004); /* CM_ICLKEN_WKUP */ -+ omap_writel(0x48008440, 0x00000000); /* CM_CLKSEL_WKUP */ -+ omap_writel(0x48008500, 0x000000cf); /* CM_CLKEN_PLL */ -+ omap_writel(0x48008530, 0x0000000c); /* CM_AUTOIDLE_PLL */ -+ omap_writel(0x48008540, /* CM_CLKSEL1_PLL */ -+ (0x78 << 12) | (6 << 8)); -+ omap_writel(0x48008544, 2); /* CM_CLKSEL2_PLL */ -+ -+ /* GPMC setup */ -+ n800_gpmc_init(s); -+ -+ /* Video setup */ -+ n800_dss_init(&s->blizzard); -+ -+ /* CPU setup */ -+ s->cpu->env->regs[15] = s->cpu->env->boot_info->loader_start; -+} -+ -+#define OMAP_TAG_NOKIA_BT 0x4e01 -+#define OMAP_TAG_WLAN_CX3110X 0x4e02 -+#define OMAP_TAG_CBUS 0x4e03 -+#define OMAP_TAG_EM_ASIC_BB5 0x4e04 -+ -+static int n800_atag_setup(struct arm_boot_info *info, void *p) -+{ -+ uint8_t *b; -+ uint16_t *w; -+ uint32_t *l; -+ -+ w = p; -+ -+ stw_raw(w ++, OMAP_TAG_UART); /* u16 tag */ -+ stw_raw(w ++, 4); /* u16 len */ -+ stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */ -+ w ++; -+ -+ stw_raw(w ++, OMAP_TAG_EM_ASIC_BB5); /* u16 tag */ -+ stw_raw(w ++, 4); /* u16 len */ -+ stw_raw(w ++, N800_RETU_GPIO); /* s16 retu_irq_gpio */ -+ stw_raw(w ++, N800_TAHVO_GPIO); /* s16 tahvo_irq_gpio */ -+ -+ stw_raw(w ++, OMAP_TAG_CBUS); /* u16 tag */ -+ stw_raw(w ++, 8); /* u16 len */ -+ stw_raw(w ++, N800_CBUS_CLK_GPIO); /* s16 clk_gpio */ -+ stw_raw(w ++, N800_CBUS_DAT_GPIO); /* s16 dat_gpio */ -+ stw_raw(w ++, N800_CBUS_SEL_GPIO); /* s16 sel_gpio */ -+ w ++; -+ -+ stw_raw(w ++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */ -+ stw_raw(w ++, 20); /* u16 len */ -+ strcpy((void *) w, "bat_cover"); /* char name[12] */ -+ w += 6; -+ stw_raw(w ++, N800_BAT_COVER_GPIO); /* u16 gpio */ -+ stw_raw(w ++, 0x01); -+ stw_raw(w ++, 0); -+ stw_raw(w ++, 0); -+ -+ stw_raw(w ++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */ -+ stw_raw(w ++, 20); /* u16 len */ -+ strcpy((void *) w, "cam_act"); /* char name[12] */ -+ w += 6; -+ stw_raw(w ++, N800_CAM_ACT_GPIO); /* u16 gpio */ -+ stw_raw(w ++, 0x20); -+ stw_raw(w ++, 0); -+ stw_raw(w ++, 0); -+ -+ stw_raw(w ++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */ -+ stw_raw(w ++, 20); /* u16 len */ -+ strcpy((void *) w, "cam_turn"); /* char name[12] */ -+ w += 6; -+ stw_raw(w ++, N800_CAM_TURN_GPIO); /* u16 gpio */ -+ stw_raw(w ++, 0x21); -+ stw_raw(w ++, 0); -+ stw_raw(w ++, 0); -+ -+ stw_raw(w ++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */ -+ stw_raw(w ++, 20); /* u16 len */ -+ strcpy((void *) w, "headphone"); /* char name[12] */ -+ w += 6; -+ stw_raw(w ++, N800_HEADPHONE_GPIO); /* u16 gpio */ -+ stw_raw(w ++, 0x11); -+ stw_raw(w ++, 0); -+ stw_raw(w ++, 0); -+ -+ stw_raw(w ++, OMAP_TAG_NOKIA_BT); /* u16 tag */ -+ stw_raw(w ++, 12); /* u16 len */ -+ b = (void *) w; -+ stb_raw(b ++, 0x01); /* u8 chip_type (CSR) */ -+ stb_raw(b ++, N800_BT_WKUP_GPIO); /* u8 bt_wakeup_gpio */ -+ stb_raw(b ++, N800_BT_HOST_WKUP_GPIO); /* u8 host_wakeup_gpio */ -+ stb_raw(b ++, N800_BT_RESET_GPIO); /* u8 reset_gpio */ -+ stb_raw(b ++, 1); /* u8 bt_uart */ -+ memset(b, 0, 6); /* u8 bd_addr[6] */ -+ b += 6; -+ stb_raw(b ++, 0x02); /* u8 bt_sysclk (38.4) */ -+ w = (void *) b; -+ -+ stw_raw(w ++, OMAP_TAG_WLAN_CX3110X); /* u16 tag */ -+ stw_raw(w ++, 8); /* u16 len */ -+ stw_raw(w ++, 0x25); /* u8 chip_type */ -+ stw_raw(w ++, N800_WLAN_PWR_GPIO); /* s16 power_gpio */ -+ stw_raw(w ++, N800_WLAN_IRQ_GPIO); /* s16 irq_gpio */ -+ stw_raw(w ++, -1); /* s16 spi_cs_gpio */ -+ -+ stw_raw(w ++, OMAP_TAG_MMC); /* u16 tag */ -+ stw_raw(w ++, 16); /* u16 len */ -+ stw_raw(w ++, 0xf); /* unsigned flags */ -+ stw_raw(w ++, -1); /* s16 power_pin */ -+ stw_raw(w ++, -1); /* s16 switch_pin */ -+ stw_raw(w ++, -1); /* s16 wp_pin */ -+ stw_raw(w ++, 0); /* unsigned flags */ -+ stw_raw(w ++, 0); /* s16 power_pin */ -+ stw_raw(w ++, 0); /* s16 switch_pin */ -+ stw_raw(w ++, 0); /* s16 wp_pin */ -+ -+ stw_raw(w ++, OMAP_TAG_TEA5761); /* u16 tag */ -+ stw_raw(w ++, 4); /* u16 len */ -+ stw_raw(w ++, N800_TEA5761_CS_GPIO); /* u16 enable_gpio */ -+ w ++; -+ -+ stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */ -+ stw_raw(w ++, 28); /* u16 len */ -+ strcpy((void *) w, "bootloader"); /* char name[16] */ -+ l = (void *) (w + 8); -+ stl_raw(l ++, 0x00020000); /* unsigned int size */ -+ stl_raw(l ++, 0x00000000); /* unsigned int offset */ -+ stl_raw(l ++, 0x3); /* unsigned int mask_flags */ -+ w = (void *) l; -+ -+ stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */ -+ stw_raw(w ++, 28); /* u16 len */ -+ strcpy((void *) w, "config"); /* char name[16] */ -+ l = (void *) (w + 8); -+ stl_raw(l ++, 0x00060000); /* unsigned int size */ -+ stl_raw(l ++, 0x00020000); /* unsigned int offset */ -+ stl_raw(l ++, 0x0); /* unsigned int mask_flags */ -+ w = (void *) l; -+ -+ stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */ -+ stw_raw(w ++, 28); /* u16 len */ -+ strcpy((void *) w, "kernel"); /* char name[16] */ -+ l = (void *) (w + 8); -+ stl_raw(l ++, 0x00200000); /* unsigned int size */ -+ stl_raw(l ++, 0x00080000); /* unsigned int offset */ -+ stl_raw(l ++, 0x0); /* unsigned int mask_flags */ -+ w = (void *) l; -+ -+ stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */ -+ stw_raw(w ++, 28); /* u16 len */ -+ strcpy((void *) w, "initfs"); /* char name[16] */ -+ l = (void *) (w + 8); -+ stl_raw(l ++, 0x00200000); /* unsigned int size */ -+ stl_raw(l ++, 0x00280000); /* unsigned int offset */ -+ stl_raw(l ++, 0x3); /* unsigned int mask_flags */ -+ w = (void *) l; -+ -+ stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */ -+ stw_raw(w ++, 28); /* u16 len */ -+ strcpy((void *) w, "rootfs"); /* char name[16] */ -+ l = (void *) (w + 8); -+ stl_raw(l ++, 0x0fb80000); /* unsigned int size */ -+ stl_raw(l ++, 0x00480000); /* unsigned int offset */ -+ stl_raw(l ++, 0x3); /* unsigned int mask_flags */ -+ w = (void *) l; -+ -+ stw_raw(w ++, OMAP_TAG_BOOT_REASON); /* u16 tag */ -+ stw_raw(w ++, 12); /* u16 len */ -+#if 0 -+ strcpy((void *) w, "por"); /* char reason_str[12] */ -+ strcpy((void *) w, "charger"); /* char reason_str[12] */ -+ strcpy((void *) w, "32wd_to"); /* char reason_str[12] */ -+ strcpy((void *) w, "sw_rst"); /* char reason_str[12] */ -+ strcpy((void *) w, "mbus"); /* char reason_str[12] */ -+ strcpy((void *) w, "unknown"); /* char reason_str[12] */ -+ strcpy((void *) w, "swdg_to"); /* char reason_str[12] */ -+ strcpy((void *) w, "sec_vio"); /* char reason_str[12] */ -+ strcpy((void *) w, "pwr_key"); /* char reason_str[12] */ -+ strcpy((void *) w, "rtc_alarm"); /* char reason_str[12] */ -+#else -+ strcpy((void *) w, "pwr_key"); /* char reason_str[12] */ -+#endif -+ w += 6; -+ -+ stw_raw(w ++, OMAP_TAG_VERSION_STR); /* u16 tag */ -+ stw_raw(w ++, 24); /* u16 len */ -+ strcpy((void *) w, "product"); /* char component[12] */ -+ w += 6; -+ strcpy((void *) w, "RX-34"); /* char version[12] */ -+ w += 6; -+ -+ stw_raw(w ++, OMAP_TAG_VERSION_STR); /* u16 tag */ -+ stw_raw(w ++, 24); /* u16 len */ -+ strcpy((void *) w, "hw-build"); /* char component[12] */ -+ w += 6; -+ strcpy((void *) w, "QEMU"); /* char version[12] */ -+ w += 6; -+ -+ stw_raw(w ++, OMAP_TAG_VERSION_STR); /* u16 tag */ -+ stw_raw(w ++, 24); /* u16 len */ -+ strcpy((void *) w, "nolo"); /* char component[12] */ -+ w += 6; -+ strcpy((void *) w, "1.1.6-qemu"); /* char version[12] */ -+ w += 6; -+ -+ stw_raw(w ++, OMAP_TAG_LCD); /* u16 tag */ -+ stw_raw(w ++, 36); /* u16 len */ -+ strcpy((void *) w, "QEMU LCD panel"); /* char panel_name[16] */ -+ w += 8; -+ strcpy((void *) w, "blizzard"); /* char ctrl_name[16] */ -+ w += 8; -+ stw_raw(w ++, 5); /* TODO s16 nreset_gpio */ -+ stw_raw(w ++, 16); /* u8 data_lines */ -+ -+ return (void *) w - p; -+} -+ -+static struct arm_boot_info n800_binfo = { -+ .loader_start = OMAP2_Q2_BASE, -+ /* Actually two chips of 0x4000000 bytes each */ -+ .ram_size = 0x08000000, -+ .board_id = 0x4f7, -+ .atag_board = n800_atag_setup, -+}; -+ -+static void n800_init(int ram_size, int vga_ram_size, -+ const char *boot_device, DisplayState *ds, -+ const char *kernel_filename, const char *kernel_cmdline, -+ const char *initrd_filename, const char *cpu_model) -+{ -+ struct n800_s *s = (struct n800_s *) qemu_mallocz(sizeof(*s)); -+ int sdram_size = n800_binfo.ram_size; -+ int onenandram_size = 0x00010000; -+ -+ if (ram_size < sdram_size + onenandram_size + OMAP242X_SRAM_SIZE) { -+ fprintf(stderr, "This architecture uses %i bytes of memory\n", -+ sdram_size + onenandram_size + OMAP242X_SRAM_SIZE); -+ exit(1); -+ } -+ -+ s->cpu = omap2420_mpu_init(sdram_size, NULL, cpu_model); -+ -+ n800_gpio_setup(s); -+ n800_nand_setup(s); -+ n800_i2c_setup(s); -+ n800_tsc_setup(s); -+ n800_spi_setup(s); -+ n800_dss_setup(s, ds); -+ n800_cbus_setup(s); -+ -+ /* Setup initial (reset) machine state */ -+ -+ /* Start at the OneNAND bootloader. */ -+ s->cpu->env->regs[15] = 0; -+ -+ if (kernel_filename) { -+ /* Or at the linux loader. */ -+ n800_binfo.kernel_filename = kernel_filename; -+ n800_binfo.kernel_cmdline = kernel_cmdline; -+ n800_binfo.initrd_filename = initrd_filename; -+ arm_load_kernel(s->cpu->env, &n800_binfo); -+ -+ qemu_register_reset(n800_boot_init, s); -+ n800_boot_init(s); -+ } -+ -+ dpy_resize(ds, 800, 480); -+} -+ -+QEMUMachine n800_machine = { -+ "n800", -+ "Nokia N800 aka. RX-34 tablet (OMAP2420)", -+ n800_init, -+}; -diff --git a/hw/omap.h b/hw/omap.h -index ecfd54d..de838c9 100644 ---- a/hw/omap.h -+++ b/hw/omap.h -@@ -22,6 +22,7 @@ - # define hw_omap_h "omap.h" - - # define OMAP_EMIFS_BASE 0x00000000 -+# define OMAP2_Q0_BASE 0x00000000 - # define OMAP_CS0_BASE 0x00000000 - # define OMAP_CS1_BASE 0x04000000 - # define OMAP_CS2_BASE 0x08000000 -@@ -29,18 +30,26 @@ - # define OMAP_EMIFF_BASE 0x10000000 - # define OMAP_IMIF_BASE 0x20000000 - # define OMAP_LOCALBUS_BASE 0x30000000 -+# define OMAP2_Q1_BASE 0x40000000 -+# define OMAP2_L4_BASE 0x48000000 -+# define OMAP2_SRAM_BASE 0x40200000 -+# define OMAP2_L3_BASE 0x68000000 -+# define OMAP2_Q2_BASE 0x80000000 -+# define OMAP2_Q3_BASE 0xc0000000 - # define OMAP_MPUI_BASE 0xe1000000 - - # define OMAP730_SRAM_SIZE 0x00032000 - # define OMAP15XX_SRAM_SIZE 0x00030000 - # define OMAP16XX_SRAM_SIZE 0x00004000 - # define OMAP1611_SRAM_SIZE 0x0003e800 -+# define OMAP242X_SRAM_SIZE 0x000a0000 -+# define OMAP243X_SRAM_SIZE 0x00010000 - # define OMAP_CS0_SIZE 0x04000000 - # define OMAP_CS1_SIZE 0x04000000 - # define OMAP_CS2_SIZE 0x04000000 - # define OMAP_CS3_SIZE 0x04000000 - --/* omap1_clk.c */ -+/* omap_clk.c */ - struct omap_mpu_state_s; - typedef struct clk *omap_clk; - omap_clk omap_findclk(struct omap_mpu_state_s *mpu, const char *name); -@@ -55,14 +64,41 @@ int64_t omap_clk_getrate(omap_clk clk); - void omap_clk_reparent(omap_clk clk, omap_clk parent); - - /* omap[123].c */ -+struct omap_l4_s; -+struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num); -+ -+struct omap_target_agent_s; -+struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, int cs); -+target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region, -+ int iotype); -+ - struct omap_intr_handler_s; - struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base, -- unsigned long size, unsigned char nbanks, -+ unsigned long size, unsigned char nbanks, qemu_irq **pins, - qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk); -- --struct omap_target_agent_s; --static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, -- int region, int iotype) { return 0; } -+struct omap_intr_handler_s *omap2_inth_init(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); -+void omap_inth_reset(struct omap_intr_handler_s *s); -+ -+struct omap_prcm_s; -+struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta, -+ qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int, -+ struct omap_mpu_state_s *mpu); -+ -+struct 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); -+ -+struct omap_gpmc_s; -+struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq); -+void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype, -+ void (*base_upd)(void *opaque, target_phys_addr_t new), -+ void (*unmap)(void *opaque), void *opaque); - - /* - * Common IRQ numbers for level 1 interrupt handler -@@ -295,10 +331,20 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, - * OMAP-24xx common IRQ numbers - */ - # define OMAP_INT_24XX_SYS_NIRQ 7 -+# define OMAP_INT_24XX_L3_IRQ 10 -+# define OMAP_INT_24XX_PRCM_MPU_IRQ 11 - # define OMAP_INT_24XX_SDMA_IRQ0 12 - # define OMAP_INT_24XX_SDMA_IRQ1 13 - # define OMAP_INT_24XX_SDMA_IRQ2 14 - # define OMAP_INT_24XX_SDMA_IRQ3 15 -+# define OMAP_INT_243X_MCBSP2_IRQ 16 -+# define OMAP_INT_243X_MCBSP3_IRQ 17 -+# define OMAP_INT_243X_MCBSP4_IRQ 18 -+# define OMAP_INT_243X_MCBSP5_IRQ 19 -+# define OMAP_INT_24XX_GPMC_IRQ 20 -+# define OMAP_INT_24XX_GUFFAW_IRQ 21 -+# define OMAP_INT_24XX_IVA_IRQ 22 -+# define OMAP_INT_24XX_EAC_IRQ 23 - # define OMAP_INT_24XX_CAM_IRQ 24 - # define OMAP_INT_24XX_DSS_IRQ 25 - # define OMAP_INT_24XX_MAIL_U0_MPU 26 -@@ -308,8 +354,10 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, - # define OMAP_INT_24XX_GPIO_BANK2 30 - # define OMAP_INT_24XX_GPIO_BANK3 31 - # define OMAP_INT_24XX_GPIO_BANK4 32 --# define OMAP_INT_24XX_GPIO_BANK5 33 -+# define OMAP_INT_243X_GPIO_BANK5 33 - # define OMAP_INT_24XX_MAIL_U3_MPU 34 -+# define OMAP_INT_24XX_WDT3 35 -+# define OMAP_INT_24XX_WDT4 36 - # define OMAP_INT_24XX_GPTIMER1 37 - # define OMAP_INT_24XX_GPTIMER2 38 - # define OMAP_INT_24XX_GPTIMER3 39 -@@ -322,10 +370,24 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, - # define OMAP_INT_24XX_GPTIMER10 46 - # define OMAP_INT_24XX_GPTIMER11 47 - # define OMAP_INT_24XX_GPTIMER12 48 -+# define OMAP_INT_24XX_PKA_IRQ 50 -+# define OMAP_INT_24XX_SHA1MD5_IRQ 51 -+# define OMAP_INT_24XX_RNG_IRQ 52 -+# define OMAP_INT_24XX_MG_IRQ 53 -+# define OMAP_INT_24XX_I2C1_IRQ 56 -+# define OMAP_INT_24XX_I2C2_IRQ 57 - # define OMAP_INT_24XX_MCBSP1_IRQ_TX 59 - # define OMAP_INT_24XX_MCBSP1_IRQ_RX 60 - # define OMAP_INT_24XX_MCBSP2_IRQ_TX 62 - # define OMAP_INT_24XX_MCBSP2_IRQ_RX 63 -+# define OMAP_INT_243X_MCBSP1_IRQ 64 -+# define OMAP_INT_24XX_MCSPI1_IRQ 65 -+# define OMAP_INT_24XX_MCSPI2_IRQ 66 -+# define OMAP_INT_24XX_SSI1_IRQ0 67 -+# define OMAP_INT_24XX_SSI1_IRQ1 68 -+# define OMAP_INT_24XX_SSI2_IRQ0 69 -+# define OMAP_INT_24XX_SSI2_IRQ1 70 -+# define OMAP_INT_24XX_SSI_GDD_IRQ 71 - # define OMAP_INT_24XX_UART1_IRQ 72 - # define OMAP_INT_24XX_UART2_IRQ 73 - # define OMAP_INT_24XX_UART3_IRQ 74 -@@ -335,10 +397,15 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, - # define OMAP_INT_24XX_USB_IRQ_HGEN 78 - # define OMAP_INT_24XX_USB_IRQ_HSOF 79 - # define OMAP_INT_24XX_USB_IRQ_OTG 80 -+# define OMAP_INT_24XX_VLYNQ_IRQ 81 - # define OMAP_INT_24XX_MMC_IRQ 83 -+# define OMAP_INT_24XX_MS_IRQ 84 -+# define OMAP_INT_24XX_FAC_IRQ 85 -+# define OMAP_INT_24XX_MCSPI3_IRQ 91 - # define OMAP_INT_243X_HS_USB_MC 92 - # define OMAP_INT_243X_HS_USB_DMA 93 - # define OMAP_INT_243X_CARKIT 94 -+# define OMAP_INT_34XX_GPTIMER12 95 - - /* omap_dma.c */ - enum omap_dma_model { -@@ -352,6 +419,9 @@ struct omap_dma_s; - struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, - qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk, - enum omap_dma_model model); -+struct omap_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs, -+ struct omap_mpu_state_s *mpu, int fifo, -+ int chans, omap_clk iclk, omap_clk fclk); - void omap_dma_reset(struct omap_dma_s *s); - - struct dma_irq_map { -@@ -367,7 +437,7 @@ enum omap_dma_port { - tipb, - local, /* omap16xx: ocp_t2 */ - tipb_mpui, -- omap_dma_port_last, -+ __omap_dma_port_last, - }; - - typedef enum { -@@ -488,11 +558,83 @@ struct omap_dma_lcd_channel_s { - # define OMAP_DMA_MMC2_RX 55 - # define OMAP_DMA_CRYPTO_DES_OUT 56 - -+/* -+ * DMA request numbers for the OMAP2 -+ */ -+# define OMAP24XX_DMA_NO_DEVICE 0 -+# define OMAP24XX_DMA_XTI_DMA 1 /* Not in OMAP2420 */ -+# define OMAP24XX_DMA_EXT_DMAREQ0 2 -+# define OMAP24XX_DMA_EXT_DMAREQ1 3 -+# define OMAP24XX_DMA_GPMC 4 -+# define OMAP24XX_DMA_GFX 5 /* Not in OMAP2420 */ -+# define OMAP24XX_DMA_DSS 6 -+# define OMAP24XX_DMA_VLYNQ_TX 7 /* Not in OMAP2420 */ -+# define OMAP24XX_DMA_CWT 8 /* Not in OMAP2420 */ -+# define OMAP24XX_DMA_AES_TX 9 /* Not in OMAP2420 */ -+# define OMAP24XX_DMA_AES_RX 10 /* Not in OMAP2420 */ -+# define OMAP24XX_DMA_DES_TX 11 /* Not in OMAP2420 */ -+# define OMAP24XX_DMA_DES_RX 12 /* Not in OMAP2420 */ -+# define OMAP24XX_DMA_SHA1MD5_RX 13 /* Not in OMAP2420 */ -+# define OMAP24XX_DMA_EXT_DMAREQ2 14 -+# define OMAP24XX_DMA_EXT_DMAREQ3 15 -+# define OMAP24XX_DMA_EXT_DMAREQ4 16 -+# define OMAP24XX_DMA_EAC_AC_RD 17 -+# define OMAP24XX_DMA_EAC_AC_WR 18 -+# define OMAP24XX_DMA_EAC_MD_UL_RD 19 -+# define OMAP24XX_DMA_EAC_MD_UL_WR 20 -+# define OMAP24XX_DMA_EAC_MD_DL_RD 21 -+# define OMAP24XX_DMA_EAC_MD_DL_WR 22 -+# define OMAP24XX_DMA_EAC_BT_UL_RD 23 -+# define OMAP24XX_DMA_EAC_BT_UL_WR 24 -+# define OMAP24XX_DMA_EAC_BT_DL_RD 25 -+# define OMAP24XX_DMA_EAC_BT_DL_WR 26 -+# define OMAP24XX_DMA_I2C1_TX 27 -+# define OMAP24XX_DMA_I2C1_RX 28 -+# define OMAP24XX_DMA_I2C2_TX 29 -+# define OMAP24XX_DMA_I2C2_RX 30 -+# define OMAP24XX_DMA_MCBSP1_TX 31 -+# define OMAP24XX_DMA_MCBSP1_RX 32 -+# define OMAP24XX_DMA_MCBSP2_TX 33 -+# define OMAP24XX_DMA_MCBSP2_RX 34 -+# define OMAP24XX_DMA_SPI1_TX0 35 -+# define OMAP24XX_DMA_SPI1_RX0 36 -+# define OMAP24XX_DMA_SPI1_TX1 37 -+# define OMAP24XX_DMA_SPI1_RX1 38 -+# define OMAP24XX_DMA_SPI1_TX2 39 -+# define OMAP24XX_DMA_SPI1_RX2 40 -+# define OMAP24XX_DMA_SPI1_TX3 41 -+# define OMAP24XX_DMA_SPI1_RX3 42 -+# define OMAP24XX_DMA_SPI2_TX0 43 -+# define OMAP24XX_DMA_SPI2_RX0 44 -+# define OMAP24XX_DMA_SPI2_TX1 45 -+# define OMAP24XX_DMA_SPI2_RX1 46 -+ -+# define OMAP24XX_DMA_UART1_TX 49 -+# define OMAP24XX_DMA_UART1_RX 50 -+# define OMAP24XX_DMA_UART2_TX 51 -+# define OMAP24XX_DMA_UART2_RX 52 -+# define OMAP24XX_DMA_UART3_TX 53 -+# define OMAP24XX_DMA_UART3_RX 54 -+# define OMAP24XX_DMA_USB_W2FC_TX0 55 -+# define OMAP24XX_DMA_USB_W2FC_RX0 56 -+# define OMAP24XX_DMA_USB_W2FC_TX1 57 -+# define OMAP24XX_DMA_USB_W2FC_RX1 58 -+# define OMAP24XX_DMA_USB_W2FC_TX2 59 -+# define OMAP24XX_DMA_USB_W2FC_RX2 60 -+# define OMAP24XX_DMA_MMC1_TX 61 -+# define OMAP24XX_DMA_MMC1_RX 62 -+# define OMAP24XX_DMA_MS 63 /* Not in OMAP2420 */ -+# define OMAP24XX_DMA_EXT_DMAREQ5 64 -+ - /* omap[123].c */ - struct omap_mpu_timer_s; - struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base, - qemu_irq irq, omap_clk clk); - -+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); -+ - struct omap_watchdog_timer_s; - struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base, - qemu_irq irq, omap_clk clk); -@@ -501,13 +643,21 @@ struct omap_32khz_timer_s; - struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base, - qemu_irq irq, omap_clk clk); - -+void omap_synctimer_init(struct omap_target_agent_s *ta, -+ struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk); -+ - struct omap_tipb_bridge_s; - struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base, - qemu_irq abort_irq, omap_clk clk); - - struct omap_uart_s; - struct omap_uart_s *omap_uart_init(target_phys_addr_t base, -- qemu_irq irq, omap_clk clk, CharDriverState *chr); -+ qemu_irq irq, omap_clk fclk, omap_clk iclk, -+ qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr); -+struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta, -+ qemu_irq irq, omap_clk fclk, omap_clk iclk, -+ qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr); -+void omap_uart_reset(struct omap_uart_s *s); - - struct omap_mpuio_s; - struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base, -@@ -523,6 +673,12 @@ struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base, - qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s); - void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler); - -+struct omap_gpif_s; -+struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta, -+ qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules); -+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); -+ - struct uwire_slave_s { - uint16_t (*receive)(void *opaque); - void (*send)(void *opaque, uint16_t data); -@@ -534,6 +690,13 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base, - void omap_uwire_attach(struct omap_uwire_s *s, - struct uwire_slave_s *slave, int chipselect); - -+struct omap_mcspi_s; -+struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum, -+ qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk); -+void omap_mcspi_attach(struct omap_mcspi_s *s, -+ uint32_t (*txrx)(void *opaque, uint32_t), void *opaque, -+ int chipselect); -+ - struct omap_rtc_s; - struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base, - qemu_irq *irq, omap_clk clk); -@@ -570,6 +733,9 @@ void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave); - struct omap_lpg_s; - struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk); - -+void omap_tap_init(struct omap_target_agent_s *ta, -+ struct omap_mpu_state_s *mpu); -+ - /* omap_lcdc.c */ - struct omap_lcd_panel_s; - void omap_lcdc_reset(struct omap_lcd_panel_s *s); -@@ -577,13 +743,33 @@ struct omap_lcd_panel_s *omap_lcdc_init(target_phys_addr_t base, qemu_irq irq, - struct omap_dma_lcd_channel_s *dma, DisplayState *ds, - ram_addr_t imif_base, ram_addr_t emiff_base, omap_clk clk); - -+/* omap_dss.c */ -+struct rfbi_chip_s { -+ void *opaque; -+ void (*write)(void *opaque, int dc, uint16_t value); -+ void (*block)(void *opaque, int dc, void *buf, size_t len, int pitch); -+ uint16_t (*read)(void *opaque, int dc); -+}; -+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, DisplayState *ds, -+ qemu_irq irq, qemu_irq drq, -+ omap_clk fck1, omap_clk fck2, omap_clk ck54m, -+ omap_clk ick1, omap_clk ick2); -+void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip); -+ - /* omap_mmc.c */ - struct omap_mmc_s; - struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base, - BlockDriverState *bd, - qemu_irq irq, qemu_irq dma[], omap_clk clk); -+struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta, -+ BlockDriverState *bd, qemu_irq irq, qemu_irq dma[], -+ omap_clk fclk, omap_clk iclk); - void omap_mmc_reset(struct omap_mmc_s *s); - void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover); -+void omap_mmc_enable(struct omap_mmc_s *s, int enable); - - /* omap_i2c.c */ - struct omap_i2c_s; -@@ -596,14 +782,37 @@ 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_omap1710(cpu) (cpu->mpu_model == omap1710) -+# define cpu_is_omap2410(cpu) (cpu->mpu_model == omap2410) -+# 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_omap15xx(cpu) \ - (cpu_is_omap310(cpu) || cpu_is_omap1510(cpu)) --# define cpu_class_omap1(cpu) 1 -+# define cpu_is_omap16xx(cpu) \ -+ (cpu_is_omap1610(cpu) || cpu_is_omap1710(cpu)) -+# define cpu_is_omap24xx(cpu) \ -+ (cpu_is_omap2410(cpu) || cpu_is_omap2420(cpu) || cpu_is_omap2430(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) - - struct omap_mpu_state_s { -- enum omap1_mpu_model { -+ enum omap_mpu_model { - omap310, - omap1510, -+ omap1610, -+ omap1710, -+ omap2410, -+ omap2420, -+ omap2422, -+ omap2423, -+ omap2430, -+ omap3430, - } mpu_model; - - CPUState *env; -@@ -620,7 +829,7 @@ struct omap_mpu_state_s { - target_phys_addr_t offset, uint32_t value); - int (*addr_valid)(struct omap_mpu_state_s *s, - target_phys_addr_t addr); -- } port[omap_dma_port_last]; -+ } port[__omap_dma_port_last]; - - unsigned long sdram_size; - unsigned long sram_size; -@@ -656,7 +865,7 @@ struct omap_mpu_state_s { - omap_clk clk; - } pwt; - -- struct omap_i2c_s *i2c; -+ struct omap_i2c_s *i2c[2]; - - struct omap_rtc_s *rtc; - -@@ -722,7 +931,38 @@ struct omap_mpu_state_s { - uint16_t dsp_idlect2; - uint16_t dsp_rstct2; - } clkm; --} *omap310_mpu_init(unsigned long sdram_size, -+ -+ /* OMAP2-only peripherals */ -+ struct omap_l4_s *l4; -+ -+ struct omap_gp_timer_s *gptimer[12]; -+ -+ target_phys_addr_t tap_base; -+ -+ struct omap_synctimer_s { -+ target_phys_addr_t base; -+ uint32_t val; -+ uint16_t readh; -+ } synctimer; -+ -+ struct omap_prcm_s *prcm; -+ struct omap_sdrc_s *sdrc; -+ struct omap_gpmc_s *gpmc; -+ struct omap_sysctl_s *sysc; -+ -+ struct omap_gpif_s *gpif; -+ -+ struct omap_mcspi_s *mcspi[2]; -+ -+ struct omap_dss_s *dss; -+}; -+ -+/* omap1.c */ -+struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, -+ DisplayState *ds, const char *core); -+ -+/* omap2.c */ -+struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size, - DisplayState *ds, const char *core); - - # if TARGET_PHYS_ADDR_BITS == 32 -@@ -743,24 +983,46 @@ uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr); - void omap_badwidth_write32(void *opaque, target_phys_addr_t addr, - uint32_t value); - -+void omap_mpu_wakeup(void *opaque, int irq, int req); -+ - # define OMAP_BAD_REG(paddr) \ -- printf("%s: Bad register " OMAP_FMT_plx "\n", __FUNCTION__, paddr) -+ fprintf(stderr, "%s: Bad register " OMAP_FMT_plx "\n", \ -+ __FUNCTION__, paddr) - # define OMAP_RO_REG(paddr) \ -- printf("%s: Read-only register " OMAP_FMT_plx "\n", \ -+ fprintf(stderr, "%s: Read-only register " OMAP_FMT_plx "\n", \ - __FUNCTION__, paddr) - -+/* OMAP-specific Linux bootloader tags for the ATAG_BOARD area -+ (Board-specifc tags are not here) */ -+#define OMAP_TAG_CLOCK 0x4f01 -+#define OMAP_TAG_MMC 0x4f02 -+#define OMAP_TAG_SERIAL_CONSOLE 0x4f03 -+#define OMAP_TAG_USB 0x4f04 -+#define OMAP_TAG_LCD 0x4f05 -+#define OMAP_TAG_GPIO_SWITCH 0x4f06 -+#define OMAP_TAG_UART 0x4f07 -+#define OMAP_TAG_FBMEM 0x4f08 -+#define OMAP_TAG_STI_CONSOLE 0x4f09 -+#define OMAP_TAG_CAMERA_SENSOR 0x4f0a -+#define OMAP_TAG_PARTITION 0x4f0b -+#define OMAP_TAG_TEA5761 0x4f10 -+#define OMAP_TAG_TMP105 0x4f11 -+#define OMAP_TAG_BOOT_REASON 0x4f80 -+#define OMAP_TAG_FLASH_PART_STR 0x4f81 -+#define OMAP_TAG_VERSION_STR 0x4f82 -+ - # define TCMI_VERBOSE 1 - //# define MEM_VERBOSE 1 - - # ifdef TCMI_VERBOSE - # define OMAP_8B_REG(paddr) \ -- printf("%s: 8-bit register " OMAP_FMT_plx "\n", \ -+ fprintf(stderr, "%s: 8-bit register " OMAP_FMT_plx "\n", \ - __FUNCTION__, paddr) - # define OMAP_16B_REG(paddr) \ -- printf("%s: 16-bit register " OMAP_FMT_plx "\n", \ -+ fprintf(stderr, "%s: 16-bit register " OMAP_FMT_plx "\n", \ - __FUNCTION__, paddr) - # define OMAP_32B_REG(paddr) \ -- printf("%s: 32-bit register " OMAP_FMT_plx "\n", \ -+ fprintf(stderr, "%s: 32-bit register " OMAP_FMT_plx "\n", \ - __FUNCTION__, paddr) - # else - # define OMAP_8B_REG(paddr) -@@ -863,10 +1125,4 @@ inline static int debug_register_io_memory(int io_index, - # define cpu_register_io_memory debug_register_io_memory - # endif - --/* Not really omap specific, but is the only thing that uses the -- uwire interface. */ --/* tsc210x.c */ --struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio); --struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip); -- - #endif /* hw_omap_h */ -diff --git a/hw/omap1.c b/hw/omap1.c -index 3888e80..d81cbce 100644 ---- a/hw/omap1.c -+++ b/hw/omap1.c -@@ -23,10 +23,11 @@ - #include "omap.h" - #include "sysemu.h" - #include "qemu-timer.h" -+#include "qemu-char.h" - /* We use pc-style serial ports. */ - #include "pc.h" - --/* Should signal the TCMI */ -+/* Should signal the TCMI/GPMC */ - uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr) - { - uint8_t ret; -@@ -86,6 +87,7 @@ struct omap_intr_handler_bank_s { - uint32_t mask; - uint32_t fiq; - uint32_t sens_edge; -+ uint32_t swi; - unsigned char priority[32]; - }; - -@@ -94,11 +96,14 @@ struct omap_intr_handler_s { - qemu_irq parent_intr[2]; - target_phys_addr_t base; - unsigned char nbanks; -+ int level_only; - - /* state */ - uint32_t new_agr[2]; - int sir_intr[2]; -- struct omap_intr_handler_bank_s banks[]; -+ int autoidle; -+ uint32_t mask; -+ struct omap_intr_handler_bank_s bank[]; - }; - - static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq) -@@ -113,11 +118,11 @@ static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq) - * If all interrupts have the same priority, the default order is IRQ_N, - * IRQ_N-1,...,IRQ_0. */ - for (j = 0; j < s->nbanks; ++j) { -- level = s->banks[j].irqs & ~s->banks[j].mask & -- (is_fiq ? s->banks[j].fiq : ~s->banks[j].fiq); -+ level = s->bank[j].irqs & ~s->bank[j].mask & -+ (is_fiq ? s->bank[j].fiq : ~s->bank[j].fiq); - for (f = ffs(level), i = f - 1, level >>= f - 1; f; i += f, - level >>= f) { -- p = s->banks[j].priority[i]; -+ p = s->bank[j].priority[i]; - if (p <= p_intr) { - p_intr = p; - sir_intr = 32 * j + i; -@@ -134,10 +139,10 @@ static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq) - uint32_t has_intr = 0; - - for (i = 0; i < s->nbanks; ++i) -- has_intr |= s->banks[i].irqs & ~s->banks[i].mask & -- (is_fiq ? s->banks[i].fiq : ~s->banks[i].fiq); -+ has_intr |= s->bank[i].irqs & ~s->bank[i].mask & -+ (is_fiq ? s->bank[i].fiq : ~s->bank[i].fiq); - -- if (s->new_agr[is_fiq] && has_intr) { -+ if (s->new_agr[is_fiq] & has_intr & s->mask) { - s->new_agr[is_fiq] = 0; - omap_inth_sir_update(s, is_fiq); - qemu_set_irq(s->parent_intr[is_fiq], 1); -@@ -152,13 +157,13 @@ static void omap_set_intr(void *opaque, int irq, int req) - struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque; - uint32_t rise; - -- struct omap_intr_handler_bank_s *bank = &ih->banks[irq >> 5]; -+ struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5]; - int n = irq & 31; - - if (req) { - rise = ~bank->irqs & (1 << n); - if (~bank->sens_edge & (1 << n)) -- rise &= ~bank->inputs & (1 << n); -+ rise &= ~bank->inputs; - - bank->inputs |= (1 << n); - if (rise) { -@@ -173,13 +178,33 @@ static void omap_set_intr(void *opaque, int irq, int req) - } - } - -+/* Simplified version with no edge detection */ -+static void omap_set_intr_noedge(void *opaque, int irq, int req) -+{ -+ struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque; -+ uint32_t rise; -+ -+ struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5]; -+ int n = irq & 31; -+ -+ if (req) { -+ rise = ~bank->inputs & (1 << n); -+ if (rise) { -+ bank->irqs |= bank->inputs |= rise; -+ omap_inth_update(ih, 0); -+ omap_inth_update(ih, 1); -+ } -+ } else -+ bank->irqs = (bank->inputs &= ~(1 << n)) | bank->swi; -+} -+ - static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr) - { - struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; - int i, offset = addr - s->base; - int bank_no = offset >> 8; - int line_no; -- struct omap_intr_handler_bank_s *bank = &s->banks[bank_no]; -+ struct omap_intr_handler_bank_s *bank = &s->bank[bank_no]; - offset &= 0xff; - - switch (offset) { -@@ -194,7 +219,7 @@ static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr) - if (bank_no != 0) - break; - line_no = s->sir_intr[(offset - 0x10) >> 2]; -- bank = &s->banks[line_no >> 5]; -+ bank = &s->bank[line_no >> 5]; - i = line_no & 31; - if (((bank->sens_edge >> i) & 1) == INT_FALLING_EDGE) - bank->irqs &= ~(1 << i); -@@ -256,7 +281,7 @@ static void omap_inth_write(void *opaque, target_phys_addr_t addr, - struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; - int i, offset = addr - s->base; - int bank_no = offset >> 8; -- struct omap_intr_handler_bank_s *bank = &s->banks[bank_no]; -+ struct omap_intr_handler_bank_s *bank = &s->bank[bank_no]; - offset &= 0xff; - - switch (offset) { -@@ -360,25 +385,31 @@ void omap_inth_reset(struct omap_intr_handler_s *s) - int i; - - for (i = 0; i < s->nbanks; ++i){ -- s->banks[i].irqs = 0x00000000; -- s->banks[i].mask = 0xffffffff; -- s->banks[i].sens_edge = 0x00000000; -- s->banks[i].fiq = 0x00000000; -- s->banks[i].inputs = 0x00000000; -- memset(s->banks[i].priority, 0, sizeof(s->banks[i].priority)); -+ s->bank[i].irqs = 0x00000000; -+ s->bank[i].mask = 0xffffffff; -+ s->bank[i].sens_edge = 0x00000000; -+ s->bank[i].fiq = 0x00000000; -+ s->bank[i].inputs = 0x00000000; -+ s->bank[i].swi = 0x00000000; -+ memset(s->bank[i].priority, 0, sizeof(s->bank[i].priority)); -+ -+ if (s->level_only) -+ s->bank[i].sens_edge = 0xffffffff; - } - - s->new_agr[0] = ~0; - s->new_agr[1] = ~0; - s->sir_intr[0] = 0; - s->sir_intr[1] = 0; -+ s->autoidle = 0; -+ s->mask = ~0; - - qemu_set_irq(s->parent_intr[0], 0); - qemu_set_irq(s->parent_intr[1], 0); - } - - struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base, -- unsigned long size, unsigned char nbanks, -+ unsigned long size, unsigned char nbanks, qemu_irq **pins, - qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk) - { - int iomemtype; -@@ -391,6 +422,8 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base, - s->base = base; - s->nbanks = nbanks; - s->pins = qemu_allocate_irqs(omap_set_intr, s, nbanks * 32); -+ if (pins) -+ *pins = s->pins; - - omap_inth_reset(s); - -@@ -401,6 +434,227 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base, - return s; - } - -+static uint32_t omap2_inth_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; -+ int offset = addr - s->base; -+ int bank_no, line_no; -+ struct omap_intr_handler_bank_s *bank = 0; -+ -+ if ((offset & 0xf80) == 0x80) { -+ bank_no = (offset & 0x60) >> 5; -+ if (bank_no < s->nbanks) { -+ offset &= ~0x60; -+ bank = &s->bank[bank_no]; -+ } -+ } -+ -+ switch (offset) { -+ case 0x00: /* INTC_REVISION */ -+ return 0x21; -+ -+ case 0x10: /* INTC_SYSCONFIG */ -+ return (s->autoidle >> 2) & 1; -+ -+ case 0x14: /* INTC_SYSSTATUS */ -+ return 1; /* RESETDONE */ -+ -+ case 0x40: /* INTC_SIR_IRQ */ -+ return s->sir_intr[0]; -+ -+ case 0x44: /* INTC_SIR_FIQ */ -+ return s->sir_intr[1]; -+ -+ case 0x48: /* INTC_CONTROL */ -+ return (!s->mask) << 2; /* GLOBALMASK */ -+ -+ case 0x4c: /* INTC_PROTECTION */ -+ return 0; -+ -+ case 0x50: /* INTC_IDLE */ -+ return s->autoidle & 3; -+ -+ /* Per-bank registers */ -+ case 0x80: /* INTC_ITR */ -+ return bank->inputs; -+ -+ case 0x84: /* INTC_MIR */ -+ return bank->mask; -+ -+ case 0x88: /* INTC_MIR_CLEAR */ -+ case 0x8c: /* INTC_MIR_SET */ -+ return 0; -+ -+ case 0x90: /* INTC_ISR_SET */ -+ return bank->swi; -+ -+ case 0x94: /* INTC_ISR_CLEAR */ -+ return 0; -+ -+ case 0x98: /* INTC_PENDING_IRQ */ -+ return bank->irqs & ~bank->mask & ~bank->fiq; -+ -+ case 0x9c: /* INTC_PENDING_FIQ */ -+ return bank->irqs & ~bank->mask & bank->fiq; -+ -+ /* Per-line registers */ -+ case 0x100 ... 0x300: /* INTC_ILR */ -+ bank_no = (offset - 0x100) >> 7; -+ if (bank_no > s->nbanks) -+ break; -+ bank = &s->bank[bank_no]; -+ line_no = (offset & 0x7f) >> 2; -+ return (bank->priority[line_no] << 2) | -+ ((bank->fiq >> line_no) & 1); -+ } -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap2_inth_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; -+ int offset = addr - s->base; -+ int bank_no, line_no; -+ struct omap_intr_handler_bank_s *bank = 0; -+ -+ if ((offset & 0xf80) == 0x80) { -+ bank_no = (offset & 0x60) >> 5; -+ if (bank_no < s->nbanks) { -+ offset &= ~0x60; -+ bank = &s->bank[bank_no]; -+ } -+ } -+ -+ switch (offset) { -+ case 0x10: /* INTC_SYSCONFIG */ -+ s->autoidle &= 4; -+ s->autoidle |= (value & 1) << 2; -+ if (value & 2) /* SOFTRESET */ -+ omap_inth_reset(s); -+ return; -+ -+ case 0x48: /* INTC_CONTROL */ -+ s->mask = (value & 4) ? 0 : ~0; /* GLOBALMASK */ -+ if (value & 2) { /* NEWFIQAGR */ -+ qemu_set_irq(s->parent_intr[1], 0); -+ s->new_agr[1] = ~0; -+ omap_inth_update(s, 1); -+ } -+ if (value & 1) { /* NEWIRQAGR */ -+ qemu_set_irq(s->parent_intr[0], 0); -+ s->new_agr[0] = ~0; -+ omap_inth_update(s, 0); -+ } -+ return; -+ -+ case 0x4c: /* INTC_PROTECTION */ -+ /* TODO: Make a bitmap (or sizeof(char)map) of access privileges -+ * for every register, see Chapter 3 and 4 for privileged mode. */ -+ if (value & 1) -+ fprintf(stderr, "%s: protection mode enable attempt\n", -+ __FUNCTION__); -+ return; -+ -+ case 0x50: /* INTC_IDLE */ -+ s->autoidle &= ~3; -+ s->autoidle |= value & 3; -+ return; -+ -+ /* Per-bank registers */ -+ case 0x84: /* INTC_MIR */ -+ bank->mask = value; -+ omap_inth_update(s, 0); -+ omap_inth_update(s, 1); -+ return; -+ -+ case 0x88: /* INTC_MIR_CLEAR */ -+ bank->mask &= ~value; -+ omap_inth_update(s, 0); -+ omap_inth_update(s, 1); -+ return; -+ -+ case 0x8c: /* INTC_MIR_SET */ -+ bank->mask |= value; -+ return; -+ -+ case 0x90: /* INTC_ISR_SET */ -+ bank->irqs |= bank->swi |= value; -+ omap_inth_update(s, 0); -+ omap_inth_update(s, 1); -+ return; -+ -+ case 0x94: /* INTC_ISR_CLEAR */ -+ bank->swi &= ~value; -+ bank->irqs = bank->swi & bank->inputs; -+ return; -+ -+ /* Per-line registers */ -+ case 0x100 ... 0x300: /* INTC_ILR */ -+ bank_no = (offset - 0x100) >> 7; -+ if (bank_no > s->nbanks) -+ break; -+ bank = &s->bank[bank_no]; -+ line_no = (offset & 0x7f) >> 2; -+ bank->priority[line_no] = (value >> 2) & 0x3f; -+ bank->fiq &= ~(1 << line_no); -+ bank->fiq |= (value & 1) << line_no; -+ return; -+ -+ case 0x00: /* INTC_REVISION */ -+ case 0x14: /* INTC_SYSSTATUS */ -+ case 0x40: /* INTC_SIR_IRQ */ -+ case 0x44: /* INTC_SIR_FIQ */ -+ case 0x80: /* INTC_ITR */ -+ case 0x98: /* INTC_PENDING_IRQ */ -+ case 0x9c: /* INTC_PENDING_FIQ */ -+ OMAP_RO_REG(addr); -+ return; -+ } -+ OMAP_BAD_REG(addr); -+} -+ -+static CPUReadMemoryFunc *omap2_inth_readfn[] = { -+ omap_badwidth_read32, -+ omap_badwidth_read32, -+ omap2_inth_read, -+}; -+ -+static CPUWriteMemoryFunc *omap2_inth_writefn[] = { -+ omap2_inth_write, -+ omap2_inth_write, -+ omap2_inth_write, -+}; -+ -+struct omap_intr_handler_s *omap2_inth_init(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) -+{ -+ int iomemtype; -+ struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) -+ qemu_mallocz(sizeof(struct omap_intr_handler_s) + -+ sizeof(struct omap_intr_handler_bank_s) * nbanks); -+ -+ s->parent_intr[0] = parent_irq; -+ s->parent_intr[1] = parent_fiq; -+ s->base = base; -+ s->nbanks = nbanks; -+ s->level_only = 1; -+ s->pins = qemu_allocate_irqs(omap_set_intr_noedge, s, nbanks * 32); -+ if (pins) -+ *pins = s->pins; -+ -+ omap_inth_reset(s); -+ -+ iomemtype = cpu_register_io_memory(0, omap2_inth_readfn, -+ omap2_inth_writefn, s); -+ cpu_register_physical_memory(s->base, size, iomemtype); -+ -+ return s; -+} -+ - /* MPU OS timers */ - struct omap_mpu_timer_s { - qemu_irq irq; -@@ -1289,6 +1543,8 @@ static uint32_t omap_id_read(void *opaque, target_phys_addr_t addr) - return 0x03310315; - case omap1510: - return 0x03310115; -+ default: -+ cpu_abort(cpu_single_env, "%s: bad mpu model\n", __FUNCTION__); - } - break; - -@@ -1298,6 +1554,8 @@ static uint32_t omap_id_read(void *opaque, target_phys_addr_t addr) - return 0xfb57402f; - case omap1510: - return 0xfb47002f; -+ default: -+ cpu_abort(cpu_single_env, "%s: bad mpu model\n", __FUNCTION__); - } - break; - } -@@ -1722,19 +1980,116 @@ static void omap_dpll_init(struct dpll_ctl_s *s, target_phys_addr_t base, - /* UARTs */ - struct omap_uart_s { - SerialState *serial; /* TODO */ -+ struct omap_target_agent_s *ta; -+ target_phys_addr_t base; -+ -+ uint8_t eblr; -+ uint8_t syscontrol; -+ uint8_t wkup; -+ uint8_t cfps; - }; - --static void omap_uart_reset(struct omap_uart_s *s) -+void omap_uart_reset(struct omap_uart_s *s) - { -+ s->eblr = 0x00; -+ s->syscontrol = 0; -+ s->wkup = 0x3f; -+ s->cfps = 0x69; - } - - struct omap_uart_s *omap_uart_init(target_phys_addr_t base, -- qemu_irq irq, omap_clk clk, CharDriverState *chr) -+ qemu_irq irq, omap_clk fclk, omap_clk iclk, -+ qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr) - { - struct omap_uart_s *s = (struct omap_uart_s *) - qemu_mallocz(sizeof(struct omap_uart_s)); -- if (chr) -- s->serial = serial_mm_init(base, 2, irq, chr, 1); -+ -+ s->serial = serial_mm_init(base, 2, irq, chr ?: qemu_chr_open("null"), 1); -+ -+ return s; -+} -+ -+static uint32_t omap_uart_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_uart_s *s = (struct omap_uart_s *) opaque; -+ int offset = addr - s->base; -+ -+ switch (offset) { -+ case 0x48: /* EBLR */ -+ return s->eblr; -+ case 0x50: /* MVR */ -+ return 0x30; -+ case 0x54: /* SYSC */ -+ return s->syscontrol; -+ case 0x58: /* SYSS */ -+ return 1; -+ case 0x5c: /* WER */ -+ return s->wkup; -+ case 0x60: /* CFPS */ -+ return s->cfps; -+ } -+ -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap_uart_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_uart_s *s = (struct omap_uart_s *) opaque; -+ int offset = addr - s->base; -+ -+ switch (offset) { -+ case 0x48: /* EBLR */ -+ s->eblr = value & 0xff; -+ break; -+ case 0x50: /* MVR */ -+ case 0x58: /* SYSS */ -+ OMAP_RO_REG(addr); -+ break; -+ case 0x54: /* SYSC */ -+ s->syscontrol = value & 0x1d; -+ if (value & 2) -+ omap_uart_reset(s); -+ break; -+ case 0x5c: /* WER */ -+ s->wkup = value & 0x7f; -+ break; -+ case 0x60: /* CFPS */ -+ s->cfps = value & 0xff; -+ break; -+ default: -+ OMAP_BAD_REG(addr); -+ } -+} -+ -+static CPUReadMemoryFunc *omap_uart_readfn[] = { -+ omap_uart_read, -+ omap_uart_read, -+ omap_badwidth_read8, -+}; -+ -+static CPUWriteMemoryFunc *omap_uart_writefn[] = { -+ omap_uart_write, -+ omap_uart_write, -+ omap_badwidth_write8, -+}; -+ -+struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta, -+ qemu_irq irq, omap_clk fclk, omap_clk iclk, -+ qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr) -+{ -+ target_phys_addr_t base = omap_l4_attach(ta, 0, 0); -+ struct omap_uart_s *s = omap_uart_init(base, irq, -+ fclk, iclk, txdma, rxdma, chr); -+ int iomemtype = cpu_register_io_memory(0, omap_uart_readfn, -+ omap_uart_writefn, s); -+ -+ s->ta = ta; -+ s->base = base; -+ -+ cpu_register_physical_memory(s->base + 0x20, 0x100, iomemtype); -+ - return s; - } - -@@ -2778,9 +3133,11 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base, - void omap_uwire_attach(struct omap_uwire_s *s, - struct uwire_slave_s *slave, int chipselect) - { -- if (chipselect < 0 || chipselect > 3) -- cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n", __FUNCTION__, -- chipselect); -+ if (chipselect < 0 || chipselect > 3) { -+ fprintf(stderr, "%s: Bad chipselect %i\n", -+ __FUNCTION__, chipselect); -+ exit(-1); -+ } - - s->chip[chipselect] = slave; - } -@@ -4123,7 +4481,7 @@ static void omap_setup_mpui_io(struct omap_mpu_state_s *mpu) - } - - /* General chip reset */ --static void omap_mpu_reset(void *opaque) -+static void omap1_mpu_reset(void *opaque) - { - struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque; - -@@ -4153,7 +4511,7 @@ static void omap_mpu_reset(void *opaque) - omap_uwire_reset(mpu->microwire); - omap_pwl_reset(mpu); - omap_pwt_reset(mpu); -- omap_i2c_reset(mpu->i2c); -+ omap_i2c_reset(mpu->i2c[0]); - omap_rtc_reset(mpu->rtc); - omap_mcbsp_reset(mpu->mcbsp1); - omap_mcbsp_reset(mpu->mcbsp2); -@@ -4205,7 +4563,7 @@ static void omap_setup_dsp_mapping(const struct omap_map_s *map) - } - } - --static void omap_mpu_wakeup(void *opaque, int irq, int req) -+void omap_mpu_wakeup(void *opaque, int irq, int req) - { - struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque; - -@@ -4213,7 +4571,7 @@ static void omap_mpu_wakeup(void *opaque, int irq, int req) - cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB); - } - --static const struct dma_irq_map omap_dma_irq_map[] = { -+static const struct dma_irq_map omap1_dma_irq_map[] = { - { 0, OMAP_INT_DMA_CH0_6 }, - { 0, OMAP_INT_DMA_CH1_7 }, - { 0, OMAP_INT_DMA_CH2_8 }, -@@ -4307,17 +4665,16 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, - omap_clkm_init(0xfffece00, 0xe1008000, s); - - cpu_irq = arm_pic_init_cpu(s->env); -- s->ih[0] = omap_inth_init(0xfffecb00, 0x100, 1, -+ s->ih[0] = omap_inth_init(0xfffecb00, 0x100, 1, &s->irq[0], - cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ], - omap_findclk(s, "arminth_ck")); -- s->ih[1] = omap_inth_init(0xfffe0000, 0x800, 1, -+ s->ih[1] = omap_inth_init(0xfffe0000, 0x800, 1, &s->irq[1], - s->ih[0]->pins[OMAP_INT_15XX_IH2_IRQ], NULL, - omap_findclk(s, "arminth_ck")); -- s->irq[0] = s->ih[0]->pins; -- s->irq[1] = s->ih[1]->pins; - - for (i = 0; i < 6; i ++) -- dma_irqs[i] = s->irq[omap_dma_irq_map[i].ih][omap_dma_irq_map[i].intr]; -+ dma_irqs[i] = -+ s->irq[omap1_dma_irq_map[i].ih][omap1_dma_irq_map[i].intr]; - s->dma = omap_dma_init(0xfffed800, dma_irqs, s->irq[0][OMAP_INT_DMA_LCD], - s, omap_findclk(s, "dma_ck"), omap_dma_3_1); - -@@ -4367,12 +4724,18 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, - - s->uart[0] = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1], - omap_findclk(s, "uart1_ck"), -+ omap_findclk(s, "uart1_ck"), -+ s->drq[OMAP_DMA_UART1_TX], s->drq[OMAP_DMA_UART1_RX], - serial_hds[0]); - s->uart[1] = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2], - omap_findclk(s, "uart2_ck"), -+ omap_findclk(s, "uart2_ck"), -+ s->drq[OMAP_DMA_UART2_TX], s->drq[OMAP_DMA_UART2_RX], - serial_hds[0] ? serial_hds[1] : 0); - s->uart[2] = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3], - omap_findclk(s, "uart3_ck"), -+ omap_findclk(s, "uart3_ck"), -+ s->drq[OMAP_DMA_UART3_TX], s->drq[OMAP_DMA_UART3_RX], - serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0); - - omap_dpll_init(&s->dpll[0], 0xfffecf00, omap_findclk(s, "dpll1")); -@@ -4401,7 +4764,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, - omap_pwl_init(0xfffb5800, s, omap_findclk(s, "armxor_ck")); - omap_pwt_init(0xfffb6000, s, omap_findclk(s, "armxor_ck")); - -- s->i2c = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C], -+ s->i2c[0] = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C], - &s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck")); - - s->rtc = omap_rtc_init(0xfffb4800, &s->irq[1][OMAP_INT_RTC_TIMER], -@@ -4435,7 +4798,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, - omap_setup_dsp_mapping(omap15xx_dsp_mm); - omap_setup_mpui_io(s); - -- qemu_register_reset(omap_mpu_reset, s); -+ qemu_register_reset(omap1_mpu_reset, s); - - return s; - } -diff --git a/hw/omap2.c b/hw/omap2.c -new file mode 100644 -index 0000000..1e51197 ---- /dev/null -+++ b/hw/omap2.c -@@ -0,0 +1,3872 @@ -+/* -+ * TI OMAP processors emulation. -+ * -+ * Copyright (C) 2007-2008 Nokia Corporation -+ * Written by Andrzej Zaborowski -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of -+ * the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, 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" -+/* We use pc-style serial ports. */ -+#include "pc.h" -+ -+/* GP timers */ -+struct omap_gp_timer_s { -+ qemu_irq irq; -+ qemu_irq wkup; -+ qemu_irq in; -+ qemu_irq out; -+ omap_clk clk; -+ target_phys_addr_t base; -+ QEMUTimer *timer; -+ QEMUTimer *match; -+ struct omap_target_agent_s *ta; -+ -+ int in_val; -+ int out_val; -+ int64_t time; -+ int64_t rate; -+ int64_t ticks_per_sec; -+ -+ int16_t config; -+ int status; -+ int it_ena; -+ int wu_ena; -+ int enable; -+ int inout; -+ int capt2; -+ int pt; -+ enum { -+ gpt_trigger_none, gpt_trigger_overflow, gpt_trigger_both -+ } trigger; -+ enum { -+ gpt_capture_none, gpt_capture_rising, -+ gpt_capture_falling, gpt_capture_both -+ } capture; -+ int scpwm; -+ int ce; -+ int pre; -+ int ptv; -+ int ar; -+ int st; -+ int posted; -+ uint32_t val; -+ uint32_t load_val; -+ uint32_t capture_val[2]; -+ uint32_t match_val; -+ int capt_num; -+ -+ uint16_t writeh; /* LSB */ -+ uint16_t readh; /* MSB */ -+}; -+ -+#define GPT_TCAR_IT (1 << 2) -+#define GPT_OVF_IT (1 << 1) -+#define GPT_MAT_IT (1 << 0) -+ -+static inline void omap_gp_timer_intr(struct omap_gp_timer_s *timer, int it) -+{ -+ if (timer->it_ena & it) { -+ if (!timer->status) -+ qemu_irq_raise(timer->irq); -+ -+ timer->status |= it; -+ /* Or are the status bits set even when masked? -+ * i.e. is masking applied before or after the status register? */ -+ } -+ -+ if (timer->wu_ena & it) -+ qemu_irq_pulse(timer->wkup); -+} -+ -+static inline void omap_gp_timer_out(struct omap_gp_timer_s *timer, int level) -+{ -+ if (!timer->inout && timer->out_val != level) { -+ timer->out_val = level; -+ qemu_set_irq(timer->out, level); -+ } -+} -+ -+static inline uint32_t omap_gp_timer_read(struct omap_gp_timer_s *timer) -+{ -+ uint64_t distance; -+ -+ if (timer->st && timer->rate) { -+ distance = qemu_get_clock(vm_clock) - timer->time; -+ distance = muldiv64(distance, timer->rate, timer->ticks_per_sec); -+ -+ if (distance >= 0xffffffff - timer->val) -+ return 0xffffffff; -+ else -+ return timer->val + distance; -+ } else -+ return timer->val; -+} -+ -+static inline void omap_gp_timer_sync(struct omap_gp_timer_s *timer) -+{ -+ if (timer->st) { -+ timer->val = omap_gp_timer_read(timer); -+ timer->time = qemu_get_clock(vm_clock); -+ } -+} -+ -+static inline void omap_gp_timer_update(struct omap_gp_timer_s *timer) -+{ -+ int64_t expires, matches; -+ -+ if (timer->st && timer->rate) { -+ 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, -+ timer->ticks_per_sec, timer->rate); -+ qemu_mod_timer(timer->match, timer->time + matches); -+ } else -+ qemu_del_timer(timer->match); -+ } else { -+ qemu_del_timer(timer->timer); -+ qemu_del_timer(timer->match); -+ omap_gp_timer_out(timer, timer->scpwm); -+ } -+} -+ -+static inline void omap_gp_timer_trigger(struct omap_gp_timer_s *timer) -+{ -+ if (timer->pt) -+ /* TODO in overflow-and-match mode if the first event to -+ * occurs is the match, don't toggle. */ -+ omap_gp_timer_out(timer, !timer->out_val); -+ else -+ /* TODO inverted pulse on timer->out_val == 1? */ -+ qemu_irq_pulse(timer->out); -+} -+ -+static void omap_gp_timer_tick(void *opaque) -+{ -+ struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque; -+ -+ if (!timer->ar) { -+ timer->st = 0; -+ timer->val = 0; -+ } else { -+ timer->val = timer->load_val; -+ timer->time = qemu_get_clock(vm_clock); -+ } -+ -+ if (timer->trigger == gpt_trigger_overflow || -+ timer->trigger == gpt_trigger_both) -+ omap_gp_timer_trigger(timer); -+ -+ omap_gp_timer_intr(timer, GPT_OVF_IT); -+ omap_gp_timer_update(timer); -+} -+ -+static void omap_gp_timer_match(void *opaque) -+{ -+ struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque; -+ -+ if (timer->trigger == gpt_trigger_both) -+ omap_gp_timer_trigger(timer); -+ -+ omap_gp_timer_intr(timer, GPT_MAT_IT); -+} -+ -+static void omap_gp_timer_input(void *opaque, int line, int on) -+{ -+ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque; -+ int trigger; -+ -+ switch (s->capture) { -+ default: -+ case gpt_capture_none: -+ trigger = 0; -+ break; -+ case gpt_capture_rising: -+ trigger = !s->in_val && on; -+ break; -+ case gpt_capture_falling: -+ trigger = s->in_val && !on; -+ break; -+ case gpt_capture_both: -+ trigger = (s->in_val == !on); -+ break; -+ } -+ s->in_val = on; -+ -+ if (s->inout && trigger && s->capt_num < 2) { -+ s->capture_val[s->capt_num] = omap_gp_timer_read(s); -+ -+ if (s->capt2 == s->capt_num ++) -+ omap_gp_timer_intr(s, GPT_TCAR_IT); -+ } -+} -+ -+static void omap_gp_timer_clk_update(void *opaque, int line, int on) -+{ -+ struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque; -+ -+ omap_gp_timer_sync(timer); -+ timer->rate = on ? omap_clk_getrate(timer->clk) : 0; -+ omap_gp_timer_update(timer); -+} -+ -+static void omap_gp_timer_clk_setup(struct omap_gp_timer_s *timer) -+{ -+ omap_clk_adduser(timer->clk, -+ qemu_allocate_irqs(omap_gp_timer_clk_update, timer, 1)[0]); -+ timer->rate = omap_clk_getrate(timer->clk); -+} -+ -+static void omap_gp_timer_reset(struct omap_gp_timer_s *s) -+{ -+ s->config = 0x000; -+ s->status = 0; -+ s->it_ena = 0; -+ s->wu_ena = 0; -+ s->inout = 0; -+ s->capt2 = 0; -+ s->capt_num = 0; -+ s->pt = 0; -+ s->trigger = gpt_trigger_none; -+ s->capture = gpt_capture_none; -+ s->scpwm = 0; -+ s->ce = 0; -+ s->pre = 0; -+ s->ptv = 0; -+ s->ar = 0; -+ s->st = 0; -+ s->posted = 1; -+ s->val = 0x00000000; -+ s->load_val = 0x00000000; -+ s->capture_val[0] = 0x00000000; -+ s->capture_val[1] = 0x00000000; -+ s->match_val = 0x00000000; -+ omap_gp_timer_update(s); -+} -+ -+static uint32_t omap_gp_timer_readw(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque; -+ int offset = addr - s->base; -+ -+ switch (offset) { -+ case 0x00: /* TIDR */ -+ return 0x21; -+ -+ case 0x10: /* TIOCP_CFG */ -+ return s->config; -+ -+ case 0x14: /* TISTAT */ -+ /* ??? When's this bit reset? */ -+ return 1; /* RESETDONE */ -+ -+ case 0x18: /* TISR */ -+ return s->status; -+ -+ case 0x1c: /* TIER */ -+ return s->it_ena; -+ -+ case 0x20: /* TWER */ -+ return s->wu_ena; -+ -+ case 0x24: /* TCLR */ -+ return (s->inout << 14) | -+ (s->capt2 << 13) | -+ (s->pt << 12) | -+ (s->trigger << 10) | -+ (s->capture << 8) | -+ (s->scpwm << 7) | -+ (s->ce << 6) | -+ (s->pre << 5) | -+ (s->ptv << 2) | -+ (s->ar << 1) | -+ (s->st << 0); -+ -+ case 0x28: /* TCRR */ -+ return omap_gp_timer_read(s); -+ -+ case 0x2c: /* TLDR */ -+ return s->load_val; -+ -+ case 0x30: /* TTGR */ -+ return 0xffffffff; -+ -+ case 0x34: /* TWPS */ -+ return 0x00000000; /* No posted writes pending. */ -+ -+ case 0x38: /* TMAR */ -+ return s->match_val; -+ -+ case 0x3c: /* TCAR1 */ -+ return s->capture_val[0]; -+ -+ case 0x40: /* TSICR */ -+ return s->posted << 2; -+ -+ case 0x44: /* TCAR2 */ -+ return s->capture_val[1]; -+ } -+ -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static uint32_t omap_gp_timer_readh(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque; -+ uint32_t ret; -+ -+ if (addr & 2) -+ return s->readh; -+ else { -+ ret = omap_gp_timer_readw(opaque, addr); -+ s->readh = ret >> 16; -+ return ret & 0xffff; -+ } -+} -+ -+static CPUReadMemoryFunc *omap_gp_timer_readfn[] = { -+ omap_badwidth_read32, -+ omap_gp_timer_readh, -+ omap_gp_timer_readw, -+}; -+ -+static void omap_gp_timer_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque; -+ int offset = addr - s->base; -+ -+ switch (offset) { -+ case 0x00: /* TIDR */ -+ case 0x14: /* TISTAT */ -+ case 0x34: /* TWPS */ -+ case 0x3c: /* TCAR1 */ -+ case 0x44: /* TCAR2 */ -+ OMAP_RO_REG(addr); -+ break; -+ -+ case 0x10: /* TIOCP_CFG */ -+ s->config = value & 0x33d; -+ if (((value >> 3) & 3) == 3) /* IDLEMODE */ -+ fprintf(stderr, "%s: illegal IDLEMODE value in TIOCP_CFG\n", -+ __FUNCTION__); -+ if (value & 2) /* SOFTRESET */ -+ omap_gp_timer_reset(s); -+ break; -+ -+ case 0x18: /* TISR */ -+ if (value & GPT_TCAR_IT) -+ s->capt_num = 0; -+ if (s->status && !(s->status &= ~value)) -+ qemu_irq_lower(s->irq); -+ break; -+ -+ case 0x1c: /* TIER */ -+ s->it_ena = value & 7; -+ break; -+ -+ case 0x20: /* TWER */ -+ s->wu_ena = value & 7; -+ break; -+ -+ case 0x24: /* TCLR */ -+ omap_gp_timer_sync(s); -+ s->inout = (value >> 14) & 1; -+ s->capt2 = (value >> 13) & 1; -+ s->pt = (value >> 12) & 1; -+ s->trigger = (value >> 10) & 3; -+ if (s->capture == gpt_capture_none && -+ ((value >> 8) & 3) != gpt_capture_none) -+ s->capt_num = 0; -+ s->capture = (value >> 8) & 3; -+ s->scpwm = (value >> 7) & 1; -+ s->ce = (value >> 6) & 1; -+ s->pre = (value >> 5) & 1; -+ s->ptv = (value >> 2) & 7; -+ s->ar = (value >> 1) & 1; -+ s->st = (value >> 0) & 1; -+ if (s->inout && s->trigger != gpt_trigger_none) -+ fprintf(stderr, "%s: GP timer pin must be an output " -+ "for this trigger mode\n", __FUNCTION__); -+ if (!s->inout && s->capture != gpt_capture_none) -+ fprintf(stderr, "%s: GP timer pin must be an input " -+ "for this capture mode\n", __FUNCTION__); -+ if (s->trigger == gpt_trigger_none) -+ omap_gp_timer_out(s, s->scpwm); -+ /* TODO: make sure this doesn't overflow 32-bits */ -+ s->ticks_per_sec = ticks_per_sec << (s->pre ? s->ptv + 1 : 0); -+ omap_gp_timer_update(s); -+ break; -+ -+ case 0x28: /* TCRR */ -+ s->time = qemu_get_clock(vm_clock); -+ s->val = value; -+ omap_gp_timer_update(s); -+ break; -+ -+ case 0x2c: /* TLDR */ -+ s->load_val = value; -+ break; -+ -+ case 0x30: /* TTGR */ -+ s->time = qemu_get_clock(vm_clock); -+ s->val = s->load_val; -+ omap_gp_timer_update(s); -+ break; -+ -+ case 0x38: /* TMAR */ -+ omap_gp_timer_sync(s); -+ s->match_val = value; -+ omap_gp_timer_update(s); -+ break; -+ -+ case 0x40: /* TSICR */ -+ s->posted = (value >> 2) & 1; -+ if (value & 2) /* How much exactly are we supposed to reset? */ -+ omap_gp_timer_reset(s); -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ } -+} -+ -+static void omap_gp_timer_writeh(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque; -+ -+ if (addr & 2) -+ return omap_gp_timer_write(opaque, addr, (value << 16) | s->writeh); -+ else -+ s->writeh = (uint16_t) value; -+} -+ -+static CPUWriteMemoryFunc *omap_gp_timer_writefn[] = { -+ omap_badwidth_write32, -+ omap_gp_timer_writeh, -+ omap_gp_timer_write, -+}; -+ -+struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta, -+ qemu_irq irq, omap_clk fclk, omap_clk iclk) -+{ -+ int iomemtype; -+ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) -+ qemu_mallocz(sizeof(struct omap_gp_timer_s)); -+ -+ s->ta = ta; -+ s->irq = irq; -+ s->clk = fclk; -+ s->timer = qemu_new_timer(vm_clock, omap_gp_timer_tick, s); -+ s->match = qemu_new_timer(vm_clock, omap_gp_timer_match, s); -+ s->in = qemu_allocate_irqs(omap_gp_timer_input, s, 1)[0]; -+ omap_gp_timer_reset(s); -+ omap_gp_timer_clk_setup(s); -+ -+ iomemtype = cpu_register_io_memory(0, omap_gp_timer_readfn, -+ omap_gp_timer_writefn, s); -+ s->base = omap_l4_attach(ta, 0, iomemtype); -+ -+ return s; -+} -+ -+/* 32-kHz Sync Timer of the OMAP2 */ -+static uint32_t omap_synctimer_read(struct omap_synctimer_s *s) { -+ return muldiv64(qemu_get_clock(vm_clock), 0x8000, ticks_per_sec); -+} -+ -+static void omap_synctimer_reset(struct omap_synctimer_s *s) -+{ -+ s->val = omap_synctimer_read(s); -+} -+ -+static uint32_t omap_synctimer_readw(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque; -+ int offset = addr - s->base; -+ -+ switch (offset) { -+ case 0x00: /* 32KSYNCNT_REV */ -+ return 0x21; -+ -+ case 0x10: /* CR */ -+ return omap_synctimer_read(s) - s->val; -+ } -+ -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static uint32_t omap_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; -+ else { -+ ret = omap_synctimer_readw(opaque, addr); -+ s->readh = ret >> 16; -+ return ret & 0xffff; -+ } -+} -+ -+static CPUReadMemoryFunc *omap_synctimer_readfn[] = { -+ omap_badwidth_read32, -+ omap_synctimer_readh, -+ omap_synctimer_readw, -+}; -+ -+static void omap_synctimer_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ OMAP_BAD_REG(addr); -+} -+ -+static CPUWriteMemoryFunc *omap_synctimer_writefn[] = { -+ omap_badwidth_write32, -+ omap_synctimer_write, -+ omap_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); -+ s->base = omap_l4_attach(ta, 0, cpu_register_io_memory(0, -+ omap_synctimer_readfn, omap_synctimer_writefn, s)); -+} -+ -+/* General-Purpose Interface of OMAP2 */ -+struct omap2_gpio_s { -+ target_phys_addr_t base; -+ qemu_irq irq[2]; -+ qemu_irq wkup; -+ qemu_irq *in; -+ qemu_irq handler[32]; -+ -+ uint8_t config[2]; -+ uint32_t inputs; -+ uint32_t outputs; -+ uint32_t dir; -+ uint32_t level[2]; -+ uint32_t edge[2]; -+ uint32_t mask[2]; -+ uint32_t wumask; -+ uint32_t ints[2]; -+ uint32_t debounce; -+ uint8_t delay; -+}; -+ -+static inline void omap_gpio_module_int_update(struct omap2_gpio_s *s, -+ int line) -+{ -+ qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]); -+} -+ -+static void omap_gpio_module_wake(struct omap2_gpio_s *s, int line) -+{ -+ if (!(s->config[0] & (1 << 2))) /* ENAWAKEUP */ -+ return; -+ if (!(s->config[0] & (3 << 3))) /* Force Idle */ -+ return; -+ if (!(s->wumask & (1 << line))) -+ return; -+ -+ qemu_irq_raise(s->wkup); -+} -+ -+static inline void omap_gpio_module_out_update(struct omap2_gpio_s *s, -+ uint32_t diff) -+{ -+ int ln; -+ -+ s->outputs ^= diff; -+ diff &= ~s->dir; -+ while ((ln = ffs(diff))) { -+ ln --; -+ qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1); -+ diff &= ~(1 << ln); -+ } -+} -+ -+static void omap_gpio_module_level_update(struct omap2_gpio_s *s, int line) -+{ -+ s->ints[line] |= s->dir & -+ ((s->inputs & s->level[1]) | (~s->inputs & s->level[0])); -+ omap_gpio_module_int_update(s, line); -+} -+ -+static inline void omap_gpio_module_int(struct omap2_gpio_s *s, int line) -+{ -+ s->ints[0] |= 1 << line; -+ omap_gpio_module_int_update(s, 0); -+ s->ints[1] |= 1 << line; -+ omap_gpio_module_int_update(s, 1); -+ omap_gpio_module_wake(s, line); -+} -+ -+static void omap_gpio_module_set(void *opaque, int line, int level) -+{ -+ struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque; -+ -+ if (level) { -+ if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1])) -+ omap_gpio_module_int(s, line); -+ s->inputs |= 1 << line; -+ } else { -+ if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0])) -+ omap_gpio_module_int(s, line); -+ s->inputs &= ~(1 << line); -+ } -+} -+ -+static void omap_gpio_module_reset(struct omap2_gpio_s *s) -+{ -+ s->config[0] = 0; -+ s->config[1] = 2; -+ s->ints[0] = 0; -+ s->ints[1] = 0; -+ s->mask[0] = 0; -+ s->mask[1] = 0; -+ s->wumask = 0; -+ s->dir = ~0; -+ s->level[0] = 0; -+ s->level[1] = 0; -+ s->edge[0] = 0; -+ s->edge[1] = 0; -+ s->debounce = 0; -+ s->delay = 0; -+} -+ -+static uint32_t omap_gpio_module_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque; -+ int offset = addr - s->base; -+ -+ switch (offset) { -+ case 0x00: /* GPIO_REVISION */ -+ return 0x18; -+ -+ case 0x10: /* GPIO_SYSCONFIG */ -+ return s->config[0]; -+ -+ case 0x14: /* GPIO_SYSSTATUS */ -+ return 0x01; -+ -+ case 0x18: /* GPIO_IRQSTATUS1 */ -+ return s->ints[0]; -+ -+ case 0x1c: /* GPIO_IRQENABLE1 */ -+ case 0x60: /* GPIO_CLEARIRQENABLE1 */ -+ case 0x64: /* GPIO_SETIRQENABLE1 */ -+ return s->mask[0]; -+ -+ case 0x20: /* GPIO_WAKEUPENABLE */ -+ case 0x80: /* GPIO_CLEARWKUENA */ -+ case 0x84: /* GPIO_SETWKUENA */ -+ return s->wumask; -+ -+ case 0x28: /* GPIO_IRQSTATUS2 */ -+ return s->ints[1]; -+ -+ case 0x2c: /* GPIO_IRQENABLE2 */ -+ case 0x70: /* GPIO_CLEARIRQENABLE2 */ -+ case 0x74: /* GPIO_SETIREQNEABLE2 */ -+ return s->mask[1]; -+ -+ case 0x30: /* GPIO_CTRL */ -+ return s->config[1]; -+ -+ case 0x34: /* GPIO_OE */ -+ return s->dir; -+ -+ case 0x38: /* GPIO_DATAIN */ -+ return s->inputs; -+ -+ case 0x3c: /* GPIO_DATAOUT */ -+ case 0x90: /* GPIO_CLEARDATAOUT */ -+ case 0x94: /* GPIO_SETDATAOUT */ -+ return s->outputs; -+ -+ case 0x40: /* GPIO_LEVELDETECT0 */ -+ return s->level[0]; -+ -+ case 0x44: /* GPIO_LEVELDETECT1 */ -+ return s->level[1]; -+ -+ case 0x48: /* GPIO_RISINGDETECT */ -+ return s->edge[0]; -+ -+ case 0x4c: /* GPIO_FALLINGDETECT */ -+ return s->edge[1]; -+ -+ case 0x50: /* GPIO_DEBOUNCENABLE */ -+ return s->debounce; -+ -+ case 0x54: /* GPIO_DEBOUNCINGTIME */ -+ return s->delay; -+ } -+ -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap_gpio_module_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque; -+ int offset = addr - s->base; -+ uint32_t diff; -+ int ln; -+ -+ switch (offset) { -+ case 0x00: /* GPIO_REVISION */ -+ case 0x14: /* GPIO_SYSSTATUS */ -+ case 0x38: /* GPIO_DATAIN */ -+ OMAP_RO_REG(addr); -+ break; -+ -+ case 0x10: /* GPIO_SYSCONFIG */ -+ if (((value >> 3) & 3) == 3) -+ fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__); -+ if (value & 2) -+ omap_gpio_module_reset(s); -+ s->config[0] = value & 0x1d; -+ break; -+ -+ case 0x18: /* GPIO_IRQSTATUS1 */ -+ if (s->ints[0] & value) { -+ s->ints[0] &= ~value; -+ omap_gpio_module_level_update(s, 0); -+ } -+ break; -+ -+ case 0x1c: /* GPIO_IRQENABLE1 */ -+ s->mask[0] = value; -+ omap_gpio_module_int_update(s, 0); -+ break; -+ -+ case 0x20: /* GPIO_WAKEUPENABLE */ -+ s->wumask = value; -+ break; -+ -+ case 0x28: /* GPIO_IRQSTATUS2 */ -+ if (s->ints[1] & value) { -+ s->ints[1] &= ~value; -+ omap_gpio_module_level_update(s, 1); -+ } -+ break; -+ -+ case 0x2c: /* GPIO_IRQENABLE2 */ -+ s->mask[1] = value; -+ omap_gpio_module_int_update(s, 1); -+ break; -+ -+ case 0x30: /* GPIO_CTRL */ -+ s->config[1] = value & 7; -+ break; -+ -+ case 0x34: /* GPIO_OE */ -+ diff = s->outputs & (s->dir ^ value); -+ s->dir = value; -+ -+ value = s->outputs & ~s->dir; -+ while ((ln = ffs(diff))) { -+ diff &= ~(1 <<-- ln); -+ qemu_set_irq(s->handler[ln], (value >> ln) & 1); -+ } -+ -+ omap_gpio_module_level_update(s, 0); -+ omap_gpio_module_level_update(s, 1); -+ break; -+ -+ case 0x3c: /* GPIO_DATAOUT */ -+ omap_gpio_module_out_update(s, s->outputs ^ value); -+ break; -+ -+ case 0x40: /* GPIO_LEVELDETECT0 */ -+ s->level[0] = value; -+ omap_gpio_module_level_update(s, 0); -+ omap_gpio_module_level_update(s, 1); -+ break; -+ -+ case 0x44: /* GPIO_LEVELDETECT1 */ -+ s->level[1] = value; -+ omap_gpio_module_level_update(s, 0); -+ omap_gpio_module_level_update(s, 1); -+ break; -+ -+ case 0x48: /* GPIO_RISINGDETECT */ -+ s->edge[0] = value; -+ break; -+ -+ case 0x4c: /* GPIO_FALLINGDETECT */ -+ s->edge[1] = value; -+ break; -+ -+ case 0x50: /* GPIO_DEBOUNCENABLE */ -+ s->debounce = value; -+ break; -+ -+ case 0x54: /* GPIO_DEBOUNCINGTIME */ -+ s->delay = value; -+ break; -+ -+ case 0x60: /* GPIO_CLEARIRQENABLE1 */ -+ s->mask[0] &= ~value; -+ omap_gpio_module_int_update(s, 0); -+ break; -+ -+ case 0x64: /* GPIO_SETIRQENABLE1 */ -+ s->mask[0] |= value; -+ omap_gpio_module_int_update(s, 0); -+ break; -+ -+ case 0x70: /* GPIO_CLEARIRQENABLE2 */ -+ s->mask[1] &= ~value; -+ omap_gpio_module_int_update(s, 1); -+ break; -+ -+ case 0x74: /* GPIO_SETIREQNEABLE2 */ -+ s->mask[1] |= value; -+ omap_gpio_module_int_update(s, 1); -+ break; -+ -+ case 0x80: /* GPIO_CLEARWKUENA */ -+ s->wumask &= ~value; -+ break; -+ -+ case 0x84: /* GPIO_SETWKUENA */ -+ s->wumask |= value; -+ break; -+ -+ case 0x90: /* GPIO_CLEARDATAOUT */ -+ omap_gpio_module_out_update(s, s->outputs & value); -+ break; -+ -+ case 0x94: /* GPIO_SETDATAOUT */ -+ omap_gpio_module_out_update(s, ~s->outputs & value); -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ return; -+ } -+} -+ -+static uint32_t omap_gpio_module_readp(void *opaque, target_phys_addr_t addr) -+{ -+ return omap_gpio_module_readp(opaque, addr) >> ((addr & 3) << 3); -+} -+ -+static void omap_gpio_module_writep(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque; -+ int offset = addr - s->base; -+ uint32_t cur = 0; -+ uint32_t mask = 0xffff; -+ -+ switch (offset & ~3) { -+ case 0x00: /* GPIO_REVISION */ -+ case 0x14: /* GPIO_SYSSTATUS */ -+ case 0x38: /* GPIO_DATAIN */ -+ OMAP_RO_REG(addr); -+ break; -+ -+ case 0x10: /* GPIO_SYSCONFIG */ -+ case 0x1c: /* GPIO_IRQENABLE1 */ -+ case 0x20: /* GPIO_WAKEUPENABLE */ -+ case 0x2c: /* GPIO_IRQENABLE2 */ -+ case 0x30: /* GPIO_CTRL */ -+ case 0x34: /* GPIO_OE */ -+ case 0x3c: /* GPIO_DATAOUT */ -+ case 0x40: /* GPIO_LEVELDETECT0 */ -+ case 0x44: /* GPIO_LEVELDETECT1 */ -+ case 0x48: /* GPIO_RISINGDETECT */ -+ case 0x4c: /* GPIO_FALLINGDETECT */ -+ case 0x50: /* GPIO_DEBOUNCENABLE */ -+ case 0x54: /* GPIO_DEBOUNCINGTIME */ -+ cur = omap_gpio_module_read(opaque, addr & ~3) & -+ ~(mask << ((addr & 3) << 3)); -+ -+ /* Fall through. */ -+ case 0x18: /* GPIO_IRQSTATUS1 */ -+ case 0x28: /* GPIO_IRQSTATUS2 */ -+ case 0x60: /* GPIO_CLEARIRQENABLE1 */ -+ case 0x64: /* GPIO_SETIRQENABLE1 */ -+ case 0x70: /* GPIO_CLEARIRQENABLE2 */ -+ case 0x74: /* GPIO_SETIREQNEABLE2 */ -+ case 0x80: /* GPIO_CLEARWKUENA */ -+ case 0x84: /* GPIO_SETWKUENA */ -+ case 0x90: /* GPIO_CLEARDATAOUT */ -+ case 0x94: /* GPIO_SETDATAOUT */ -+ value <<= (addr & 3) << 3; -+ omap_gpio_module_write(opaque, addr, cur | value); -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ return; -+ } -+} -+ -+static CPUReadMemoryFunc *omap_gpio_module_readfn[] = { -+ omap_gpio_module_readp, -+ omap_gpio_module_readp, -+ omap_gpio_module_read, -+}; -+ -+static CPUWriteMemoryFunc *omap_gpio_module_writefn[] = { -+ omap_gpio_module_writep, -+ omap_gpio_module_writep, -+ omap_gpio_module_write, -+}; -+ -+static void omap_gpio_module_init(struct omap2_gpio_s *s, -+ struct omap_target_agent_s *ta, int region, -+ qemu_irq mpu, qemu_irq dsp, qemu_irq wkup, -+ omap_clk fclk, omap_clk iclk) -+{ -+ int iomemtype; -+ -+ s->irq[0] = mpu; -+ s->irq[1] = dsp; -+ s->wkup = wkup; -+ s->in = qemu_allocate_irqs(omap_gpio_module_set, s, 32); -+ -+ iomemtype = cpu_register_io_memory(0, omap_gpio_module_readfn, -+ omap_gpio_module_writefn, s); -+ s->base = omap_l4_attach(ta, region, iomemtype); -+} -+ -+struct omap_gpif_s { -+ struct omap2_gpio_s module[5]; -+ int modules; -+ -+ target_phys_addr_t topbase; -+ int autoidle; -+ int gpo; -+}; -+ -+static void omap_gpif_reset(struct omap_gpif_s *s) -+{ -+ int i; -+ -+ for (i = 0; i < s->modules; i ++) -+ omap_gpio_module_reset(s->module + i); -+ -+ s->autoidle = 0; -+ s->gpo = 0; -+} -+ -+static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_gpif_s *s = (struct omap_gpif_s *) opaque; -+ int offset = addr - s->topbase; -+ -+ switch (offset) { -+ case 0x00: /* IPGENERICOCPSPL_REVISION */ -+ return 0x18; -+ -+ case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */ -+ return s->autoidle; -+ -+ case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */ -+ return 0x01; -+ -+ case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */ -+ return 0x00; -+ -+ case 0x40: /* IPGENERICOCPSPL_GPO */ -+ return s->gpo; -+ -+ case 0x50: /* IPGENERICOCPSPL_GPI */ -+ return 0x00; -+ } -+ -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_gpif_s *s = (struct omap_gpif_s *) opaque; -+ int offset = addr - s->topbase; -+ -+ switch (offset) { -+ case 0x00: /* IPGENERICOCPSPL_REVISION */ -+ case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */ -+ case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */ -+ case 0x50: /* IPGENERICOCPSPL_GPI */ -+ OMAP_RO_REG(addr); -+ break; -+ -+ case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */ -+ if (value & (1 << 1)) /* SOFTRESET */ -+ omap_gpif_reset(s); -+ s->autoidle = value & 1; -+ break; -+ -+ case 0x40: /* IPGENERICOCPSPL_GPO */ -+ s->gpo = value & 1; -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ return; -+ } -+} -+ -+static CPUReadMemoryFunc *omap_gpif_top_readfn[] = { -+ omap_gpif_top_read, -+ omap_gpif_top_read, -+ omap_gpif_top_read, -+}; -+ -+static CPUWriteMemoryFunc *omap_gpif_top_writefn[] = { -+ omap_gpif_top_write, -+ omap_gpif_top_write, -+ omap_gpif_top_write, -+}; -+ -+struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta, -+ qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules) -+{ -+ int iomemtype, i; -+ struct omap_gpif_s *s = (struct omap_gpif_s *) -+ qemu_mallocz(sizeof(struct omap_gpif_s)); -+ int region[4] = { 0, 2, 4, 5 }; -+ -+ s->modules = modules; -+ for (i = 0; i < modules; i ++) -+ omap_gpio_module_init(s->module + i, ta, region[i], -+ irq[i], 0, 0, fclk[i], iclk); -+ -+ omap_gpif_reset(s); -+ -+ iomemtype = cpu_register_io_memory(0, omap_gpif_top_readfn, -+ omap_gpif_top_writefn, s); -+ s->topbase = omap_l4_attach(ta, 1, iomemtype); -+ -+ return s; -+} -+ -+qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start) -+{ -+ if (start >= s->modules * 32 || start < 0) -+ cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", -+ __FUNCTION__, start); -+ return s->module[start >> 5].in + (start & 31); -+} -+ -+void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler) -+{ -+ if (line >= s->modules * 32 || line < 0) -+ cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line); -+ s->module[line >> 5].handler[line & 31] = handler; -+} -+ -+/* Multichannel SPI */ -+struct omap_mcspi_s { -+ target_phys_addr_t base; -+ qemu_irq irq; -+ int chnum; -+ -+ uint32_t sysconfig; -+ uint32_t systest; -+ uint32_t irqst; -+ uint32_t irqen; -+ uint32_t wken; -+ uint32_t control; -+ -+ struct omap_mcspi_ch_s { -+ qemu_irq txdrq; -+ qemu_irq rxdrq; -+ uint32_t (*txrx)(void *opaque, uint32_t); -+ void *opaque; -+ -+ uint32_t tx; -+ uint32_t rx; -+ -+ uint32_t config; -+ uint32_t status; -+ uint32_t control; -+ } ch[4]; -+}; -+ -+static inline void omap_mcspi_interrupt_update(struct omap_mcspi_s *s) -+{ -+ qemu_set_irq(s->irq, s->irqst & s->irqen); -+} -+ -+static inline void omap_mcspi_dmarequest_update(struct omap_mcspi_ch_s *ch) -+{ -+ qemu_set_irq(ch->txdrq, -+ (ch->control & 1) && /* EN */ -+ (ch->config & (1 << 14)) && /* DMAW */ -+ (ch->status & (1 << 1)) && /* TXS */ -+ ((ch->config >> 12) & 3) != 1); /* TRM */ -+ qemu_set_irq(ch->rxdrq, -+ (ch->control & 1) && /* EN */ -+ (ch->config & (1 << 15)) && /* DMAW */ -+ (ch->status & (1 << 0)) && /* RXS */ -+ ((ch->config >> 12) & 3) != 2); /* TRM */ -+} -+ -+static void omap_mcspi_transfer_run(struct omap_mcspi_s *s, int chnum) -+{ -+ struct omap_mcspi_ch_s *ch = s->ch + chnum; -+ -+ if (!(ch->control & 1)) /* EN */ -+ return; -+ if ((ch->status & (1 << 0)) && /* RXS */ -+ ((ch->config >> 12) & 3) != 2 && /* TRM */ -+ !(ch->config & (1 << 19))) /* TURBO */ -+ goto intr_update; -+ if ((ch->status & (1 << 1)) && /* TXS */ -+ ((ch->config >> 12) & 3) != 1) /* TRM */ -+ goto intr_update; -+ -+ if (!(s->control & 1) || /* SINGLE */ -+ (ch->config & (1 << 20))) { /* FORCE */ -+ if (ch->txrx) -+ ch->rx = ch->txrx(ch->opaque, ch->tx); -+ } -+ -+ ch->tx = 0; -+ ch->status |= 1 << 2; /* EOT */ -+ ch->status |= 1 << 1; /* TXS */ -+ if (((ch->config >> 12) & 3) != 2) /* TRM */ -+ ch->status |= 1 << 0; /* RXS */ -+ -+intr_update: -+ if ((ch->status & (1 << 0)) && /* RXS */ -+ ((ch->config >> 12) & 3) != 2 && /* TRM */ -+ !(ch->config & (1 << 19))) /* TURBO */ -+ s->irqst |= 1 << (2 + 4 * chnum); /* RX_FULL */ -+ if ((ch->status & (1 << 1)) && /* TXS */ -+ ((ch->config >> 12) & 3) != 1) /* TRM */ -+ s->irqst |= 1 << (0 + 4 * chnum); /* TX_EMPTY */ -+ omap_mcspi_interrupt_update(s); -+ omap_mcspi_dmarequest_update(ch); -+} -+ -+static void omap_mcspi_reset(struct omap_mcspi_s *s) -+{ -+ int ch; -+ -+ s->sysconfig = 0; -+ s->systest = 0; -+ s->irqst = 0; -+ s->irqen = 0; -+ s->wken = 0; -+ s->control = 4; -+ -+ for (ch = 0; ch < 4; ch ++) { -+ s->ch[ch].config = 0x060000; -+ s->ch[ch].status = 2; /* TXS */ -+ s->ch[ch].control = 0; -+ -+ omap_mcspi_dmarequest_update(s->ch + ch); -+ } -+ -+ omap_mcspi_interrupt_update(s); -+} -+ -+static uint32_t omap_mcspi_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque; -+ int offset = addr - s->base; -+ int ch = 0; -+ uint32_t ret; -+ -+ switch (offset) { -+ case 0x00: /* MCSPI_REVISION */ -+ return 0x91; -+ -+ case 0x10: /* MCSPI_SYSCONFIG */ -+ return s->sysconfig; -+ -+ case 0x14: /* MCSPI_SYSSTATUS */ -+ return 1; /* RESETDONE */ -+ -+ case 0x18: /* MCSPI_IRQSTATUS */ -+ return s->irqst; -+ -+ case 0x1c: /* MCSPI_IRQENABLE */ -+ return s->irqen; -+ -+ case 0x20: /* MCSPI_WAKEUPENABLE */ -+ return s->wken; -+ -+ case 0x24: /* MCSPI_SYST */ -+ return s->systest; -+ -+ case 0x28: /* MCSPI_MODULCTRL */ -+ return s->control; -+ -+ case 0x68: ch ++; -+ case 0x54: ch ++; -+ case 0x40: ch ++; -+ case 0x2c: /* MCSPI_CHCONF */ -+ return s->ch[ch].config; -+ -+ case 0x6c: ch ++; -+ case 0x58: ch ++; -+ case 0x44: ch ++; -+ case 0x30: /* MCSPI_CHSTAT */ -+ return s->ch[ch].status; -+ -+ case 0x70: ch ++; -+ case 0x5c: ch ++; -+ case 0x48: ch ++; -+ case 0x34: /* MCSPI_CHCTRL */ -+ return s->ch[ch].control; -+ -+ case 0x74: ch ++; -+ case 0x60: ch ++; -+ case 0x4c: ch ++; -+ case 0x38: /* MCSPI_TX */ -+ return s->ch[ch].tx; -+ -+ case 0x78: ch ++; -+ case 0x64: ch ++; -+ case 0x50: ch ++; -+ case 0x3c: /* MCSPI_RX */ -+ s->ch[ch].status &= ~(1 << 0); /* RXS */ -+ ret = s->ch[ch].rx; -+ omap_mcspi_transfer_run(s, ch); -+ return ret; -+ } -+ -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap_mcspi_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque; -+ int offset = addr - s->base; -+ int ch = 0; -+ -+ switch (offset) { -+ case 0x00: /* MCSPI_REVISION */ -+ case 0x14: /* MCSPI_SYSSTATUS */ -+ case 0x30: /* MCSPI_CHSTAT0 */ -+ case 0x3c: /* MCSPI_RX0 */ -+ case 0x44: /* MCSPI_CHSTAT1 */ -+ case 0x50: /* MCSPI_RX1 */ -+ case 0x58: /* MCSPI_CHSTAT2 */ -+ case 0x64: /* MCSPI_RX2 */ -+ case 0x6c: /* MCSPI_CHSTAT3 */ -+ case 0x78: /* MCSPI_RX3 */ -+ OMAP_RO_REG(addr); -+ return; -+ -+ case 0x10: /* MCSPI_SYSCONFIG */ -+ if (value & (1 << 1)) /* SOFTRESET */ -+ omap_mcspi_reset(s); -+ s->sysconfig = value & 0x31d; -+ break; -+ -+ case 0x18: /* MCSPI_IRQSTATUS */ -+ if (!((s->control & (1 << 3)) && (s->systest & (1 << 11)))) { -+ s->irqst &= ~value; -+ omap_mcspi_interrupt_update(s); -+ } -+ break; -+ -+ case 0x1c: /* MCSPI_IRQENABLE */ -+ s->irqen = value & 0x1777f; -+ omap_mcspi_interrupt_update(s); -+ break; -+ -+ case 0x20: /* MCSPI_WAKEUPENABLE */ -+ s->wken = value & 1; -+ break; -+ -+ case 0x24: /* MCSPI_SYST */ -+ if (s->control & (1 << 3)) /* SYSTEM_TEST */ -+ if (value & (1 << 11)) { /* SSB */ -+ s->irqst |= 0x1777f; -+ omap_mcspi_interrupt_update(s); -+ } -+ s->systest = value & 0xfff; -+ break; -+ -+ case 0x28: /* MCSPI_MODULCTRL */ -+ if (value & (1 << 3)) /* SYSTEM_TEST */ -+ if (s->systest & (1 << 11)) { /* SSB */ -+ s->irqst |= 0x1777f; -+ omap_mcspi_interrupt_update(s); -+ } -+ s->control = value & 0xf; -+ break; -+ -+ case 0x68: ch ++; -+ case 0x54: ch ++; -+ case 0x40: ch ++; -+ case 0x2c: /* MCSPI_CHCONF */ -+ if ((value ^ s->ch[ch].config) & (3 << 14)) /* DMAR | DMAW */ -+ omap_mcspi_dmarequest_update(s->ch + ch); -+ if (((value >> 12) & 3) == 3) /* TRM */ -+ fprintf(stderr, "%s: invalid TRM value (3)\n", __FUNCTION__); -+ if (((value >> 7) & 0x1f) < 3) /* WL */ -+ fprintf(stderr, "%s: invalid WL value (%i)\n", -+ __FUNCTION__, (value >> 7) & 0x1f); -+ s->ch[ch].config = value & 0x7fffff; -+ break; -+ -+ case 0x70: ch ++; -+ case 0x5c: ch ++; -+ case 0x48: ch ++; -+ case 0x34: /* MCSPI_CHCTRL */ -+ if (value & ~s->ch[ch].control & 1) { /* EN */ -+ s->ch[ch].control |= 1; -+ omap_mcspi_transfer_run(s, ch); -+ } else -+ s->ch[ch].control = value & 1; -+ break; -+ -+ case 0x74: ch ++; -+ case 0x60: ch ++; -+ case 0x4c: ch ++; -+ case 0x38: /* MCSPI_TX */ -+ s->ch[ch].tx = value; -+ s->ch[ch].status &= ~(1 << 1); /* TXS */ -+ omap_mcspi_transfer_run(s, ch); -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ return; -+ } -+} -+ -+static CPUReadMemoryFunc *omap_mcspi_readfn[] = { -+ omap_badwidth_read32, -+ omap_badwidth_read32, -+ omap_mcspi_read, -+}; -+ -+static CPUWriteMemoryFunc *omap_mcspi_writefn[] = { -+ omap_badwidth_write32, -+ omap_badwidth_write32, -+ omap_mcspi_write, -+}; -+ -+struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum, -+ qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk) -+{ -+ int iomemtype; -+ struct omap_mcspi_s *s = (struct omap_mcspi_s *) -+ qemu_mallocz(sizeof(struct omap_mcspi_s)); -+ struct omap_mcspi_ch_s *ch = s->ch; -+ -+ s->irq = irq; -+ s->chnum = chnum; -+ while (chnum --) { -+ ch->txdrq = *drq ++; -+ ch->rxdrq = *drq ++; -+ ch ++; -+ } -+ omap_mcspi_reset(s); -+ -+ iomemtype = cpu_register_io_memory(0, omap_mcspi_readfn, -+ omap_mcspi_writefn, s); -+ s->base = omap_l4_attach(ta, 0, iomemtype); -+ -+ return s; -+} -+ -+void omap_mcspi_attach(struct omap_mcspi_s *s, -+ uint32_t (*txrx)(void *opaque, uint32_t), void *opaque, -+ int chipselect) -+{ -+ if (chipselect < 0 || chipselect >= s->chnum) -+ cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n", -+ __FUNCTION__, chipselect); -+ -+ s->ch[chipselect].txrx = txrx; -+ s->ch[chipselect].opaque = opaque; -+} -+ -+/* 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]; -+}; -+ -+struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num) -+{ -+ struct omap_l4_s *bus = qemu_mallocz( -+ sizeof(*bus) + ta_num * sizeof(*bus->ta)); -+ -+ bus->ta_num = ta_num; -+ bus->base = base; -+ -+ return bus; -+} -+ -+static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque; -+ target_phys_addr_t reg = addr - s->base; -+ -+ switch (reg) { -+ case 0x00: /* COMPONENT */ -+ return s->component; -+ -+ case 0x20: /* AGENT_CONTROL */ -+ return s->control; -+ -+ case 0x28: /* AGENT_STATUS */ -+ return s->status; -+ } -+ -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap_l4ta_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque; -+ target_phys_addr_t reg = addr - s->base; -+ -+ switch (reg) { -+ case 0x00: /* COMPONENT */ -+ case 0x28: /* AGENT_STATUS */ -+ OMAP_RO_REG(addr); -+ break; -+ -+ case 0x20: /* AGENT_CONTROL */ -+ s->control = value & 0x01000700; -+ if (value & 1) /* OCP_RESET */ -+ s->status &= ~1; /* REQ_TIMEOUT */ -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ } -+} -+ -+static CPUReadMemoryFunc *omap_l4ta_readfn[] = { -+ omap_badwidth_read16, -+ omap_l4ta_read, -+ omap_badwidth_read16, -+}; -+ -+static CPUWriteMemoryFunc *omap_l4ta_writefn[] = { -+ omap_badwidth_write32, -+ omap_badwidth_write32, -+ omap_l4ta_write, -+}; -+ -+#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] = { -+ [ 1] = { 0x40800, 0x800, 32 }, /* Initiator agent */ -+ [ 2] = { 0x41000, 0x1000, 32 }, /* Link agent */ -+ [ 0] = { 0x40000, 0x800, 32 }, /* Address and protection */ -+ [ 3] = { 0x00000, 0x1000, 32 | 16 | 8 }, /* System Control and Pinout */ -+ [ 4] = { 0x01000, 0x1000, 32 | 16 | 8 }, /* L4TAO1 */ -+ [ 5] = { 0x04000, 0x1000, 32 | 16 }, /* 32K Timer */ -+ [ 6] = { 0x05000, 0x1000, 32 | 16 | 8 }, /* L4TAO2 */ -+ [ 7] = { 0x08000, 0x800, 32 }, /* PRCM Region A */ -+ [ 8] = { 0x08800, 0x800, 32 }, /* PRCM Region B */ -+ [ 9] = { 0x09000, 0x1000, 32 | 16 | 8 }, /* L4TAO */ -+ [ 10] = { 0x12000, 0x1000, 32 | 16 | 8 }, /* Test (BCM) */ -+ [ 11] = { 0x13000, 0x1000, 32 | 16 | 8 }, /* L4TA1 */ -+ [ 12] = { 0x14000, 0x1000, 32 }, /* Test/emulation (TAP) */ -+ [ 13] = { 0x15000, 0x1000, 32 | 16 | 8 }, /* L4TA2 */ -+ [ 14] = { 0x18000, 0x1000, 32 | 16 | 8 }, /* GPIO1 */ -+ [ 16] = { 0x1a000, 0x1000, 32 | 16 | 8 }, /* GPIO2 */ -+ [ 18] = { 0x1c000, 0x1000, 32 | 16 | 8 }, /* GPIO3 */ -+ [ 19] = { 0x1e000, 0x1000, 32 | 16 | 8 }, /* GPIO4 */ -+ [ 15] = { 0x19000, 0x1000, 32 | 16 | 8 }, /* Quad GPIO TOP */ -+ [ 17] = { 0x1b000, 0x1000, 32 | 16 | 8 }, /* L4TA3 */ -+ [ 20] = { 0x20000, 0x1000, 32 | 16 | 8 }, /* WD Timer 1 (Secure) */ -+ [ 22] = { 0x22000, 0x1000, 32 | 16 | 8 }, /* WD Timer 2 (OMAP) */ -+ [ 21] = { 0x21000, 0x1000, 32 | 16 | 8 }, /* Dual WD timer TOP */ -+ [ 23] = { 0x23000, 0x1000, 32 | 16 | 8 }, /* L4TA4 */ -+ [ 24] = { 0x28000, 0x1000, 32 | 16 | 8 }, /* GP Timer 1 */ -+ [ 25] = { 0x29000, 0x1000, 32 | 16 | 8 }, /* L4TA7 */ -+ [ 26] = { 0x48000, 0x2000, 32 | 16 | 8 }, /* Emulation (ARM11ETB) */ -+ [ 27] = { 0x4a000, 0x1000, 32 | 16 | 8 }, /* L4TA9 */ -+ [ 28] = { 0x50000, 0x400, 32 | 16 | 8 }, /* Display top */ -+ [ 29] = { 0x50400, 0x400, 32 | 16 | 8 }, /* Display control */ -+ [ 30] = { 0x50800, 0x400, 32 | 16 | 8 }, /* Display RFBI */ -+ [ 31] = { 0x50c00, 0x400, 32 | 16 | 8 }, /* Display encoder */ -+ [ 32] = { 0x51000, 0x1000, 32 | 16 | 8 }, /* L4TA10 */ -+ [ 33] = { 0x52000, 0x400, 32 | 16 | 8 }, /* Camera top */ -+ [ 34] = { 0x52400, 0x400, 32 | 16 | 8 }, /* Camera core */ -+ [ 35] = { 0x52800, 0x400, 32 | 16 | 8 }, /* Camera DMA */ -+ [ 36] = { 0x52c00, 0x400, 32 | 16 | 8 }, /* Camera MMU */ -+ [ 37] = { 0x53000, 0x1000, 32 | 16 | 8 }, /* L4TA11 */ -+ [ 38] = { 0x56000, 0x1000, 32 | 16 | 8 }, /* sDMA */ -+ [ 39] = { 0x57000, 0x1000, 32 | 16 | 8 }, /* L4TA12 */ -+ [ 40] = { 0x58000, 0x1000, 32 | 16 | 8 }, /* SSI top */ -+ [ 41] = { 0x59000, 0x1000, 32 | 16 | 8 }, /* SSI GDD */ -+ [ 42] = { 0x5a000, 0x1000, 32 | 16 | 8 }, /* SSI Port1 */ -+ [ 43] = { 0x5b000, 0x1000, 32 | 16 | 8 }, /* SSI Port2 */ -+ [ 44] = { 0x5c000, 0x1000, 32 | 16 | 8 }, /* L4TA13 */ -+ [ 45] = { 0x5e000, 0x1000, 32 | 16 | 8 }, /* USB OTG */ -+ [ 46] = { 0x5f000, 0x1000, 32 | 16 | 8 }, /* L4TAO4 */ -+ [ 47] = { 0x60000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER1SDRC) */ -+ [ 48] = { 0x61000, 0x1000, 32 | 16 | 8 }, /* L4TA14 */ -+ [ 49] = { 0x62000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER2GPMC) */ -+ [ 50] = { 0x63000, 0x1000, 32 | 16 | 8 }, /* L4TA15 */ -+ [ 51] = { 0x64000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER3OCM) */ -+ [ 52] = { 0x65000, 0x1000, 32 | 16 | 8 }, /* L4TA16 */ -+ [ 53] = { 0x66000, 0x300, 32 | 16 | 8 }, /* Emulation (WIN_TRACER4L4) */ -+ [ 54] = { 0x67000, 0x1000, 32 | 16 | 8 }, /* L4TA17 */ -+ [ 55] = { 0x68000, 0x1000, 32 | 16 | 8 }, /* Emulation (XTI) */ -+ [ 56] = { 0x69000, 0x1000, 32 | 16 | 8 }, /* L4TA18 */ -+ [ 57] = { 0x6a000, 0x1000, 16 | 8 }, /* UART1 */ -+ [ 58] = { 0x6b000, 0x1000, 32 | 16 | 8 }, /* L4TA19 */ -+ [ 59] = { 0x6c000, 0x1000, 16 | 8 }, /* UART2 */ -+ [ 60] = { 0x6d000, 0x1000, 32 | 16 | 8 }, /* L4TA20 */ -+ [ 61] = { 0x6e000, 0x1000, 16 | 8 }, /* UART3 */ -+ [ 62] = { 0x6f000, 0x1000, 32 | 16 | 8 }, /* L4TA21 */ -+ [ 63] = { 0x70000, 0x1000, 16 }, /* I2C1 */ -+ [ 64] = { 0x71000, 0x1000, 32 | 16 | 8 }, /* L4TAO5 */ -+ [ 65] = { 0x72000, 0x1000, 16 }, /* I2C2 */ -+ [ 66] = { 0x73000, 0x1000, 32 | 16 | 8 }, /* L4TAO6 */ -+ [ 67] = { 0x74000, 0x1000, 16 }, /* McBSP1 */ -+ [ 68] = { 0x75000, 0x1000, 32 | 16 | 8 }, /* L4TAO7 */ -+ [ 69] = { 0x76000, 0x1000, 16 }, /* McBSP2 */ -+ [ 70] = { 0x77000, 0x1000, 32 | 16 | 8 }, /* L4TAO8 */ -+ [ 71] = { 0x24000, 0x1000, 32 | 16 | 8 }, /* WD Timer 3 (DSP) */ -+ [ 72] = { 0x25000, 0x1000, 32 | 16 | 8 }, /* L4TA5 */ -+ [ 73] = { 0x26000, 0x1000, 32 | 16 | 8 }, /* WD Timer 4 (IVA) */ -+ [ 74] = { 0x27000, 0x1000, 32 | 16 | 8 }, /* L4TA6 */ -+ [ 75] = { 0x2a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 2 */ -+ [ 76] = { 0x2b000, 0x1000, 32 | 16 | 8 }, /* L4TA8 */ -+ [ 77] = { 0x78000, 0x1000, 32 | 16 | 8 }, /* GP Timer 3 */ -+ [ 78] = { 0x79000, 0x1000, 32 | 16 | 8 }, /* L4TA22 */ -+ [ 79] = { 0x7a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 4 */ -+ [ 80] = { 0x7b000, 0x1000, 32 | 16 | 8 }, /* L4TA23 */ -+ [ 81] = { 0x7c000, 0x1000, 32 | 16 | 8 }, /* GP Timer 5 */ -+ [ 82] = { 0x7d000, 0x1000, 32 | 16 | 8 }, /* L4TA24 */ -+ [ 83] = { 0x7e000, 0x1000, 32 | 16 | 8 }, /* GP Timer 6 */ -+ [ 84] = { 0x7f000, 0x1000, 32 | 16 | 8 }, /* L4TA25 */ -+ [ 85] = { 0x80000, 0x1000, 32 | 16 | 8 }, /* GP Timer 7 */ -+ [ 86] = { 0x81000, 0x1000, 32 | 16 | 8 }, /* L4TA26 */ -+ [ 87] = { 0x82000, 0x1000, 32 | 16 | 8 }, /* GP Timer 8 */ -+ [ 88] = { 0x83000, 0x1000, 32 | 16 | 8 }, /* L4TA27 */ -+ [ 89] = { 0x84000, 0x1000, 32 | 16 | 8 }, /* GP Timer 9 */ -+ [ 90] = { 0x85000, 0x1000, 32 | 16 | 8 }, /* L4TA28 */ -+ [ 91] = { 0x86000, 0x1000, 32 | 16 | 8 }, /* GP Timer 10 */ -+ [ 92] = { 0x87000, 0x1000, 32 | 16 | 8 }, /* L4TA29 */ -+ [ 93] = { 0x88000, 0x1000, 32 | 16 | 8 }, /* GP Timer 11 */ -+ [ 94] = { 0x89000, 0x1000, 32 | 16 | 8 }, /* L4TA30 */ -+ [ 95] = { 0x8a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 12 */ -+ [ 96] = { 0x8b000, 0x1000, 32 | 16 | 8 }, /* L4TA31 */ -+ [ 97] = { 0x90000, 0x1000, 16 }, /* EAC */ -+ [ 98] = { 0x91000, 0x1000, 32 | 16 | 8 }, /* L4TA32 */ -+ [ 99] = { 0x92000, 0x1000, 16 }, /* FAC */ -+ [100] = { 0x93000, 0x1000, 32 | 16 | 8 }, /* L4TA33 */ -+ [101] = { 0x94000, 0x1000, 32 | 16 | 8 }, /* IPC (MAILBOX) */ -+ [102] = { 0x95000, 0x1000, 32 | 16 | 8 }, /* L4TA34 */ -+ [103] = { 0x98000, 0x1000, 32 | 16 | 8 }, /* SPI1 */ -+ [104] = { 0x99000, 0x1000, 32 | 16 | 8 }, /* L4TA35 */ -+ [105] = { 0x9a000, 0x1000, 32 | 16 | 8 }, /* SPI2 */ -+ [106] = { 0x9b000, 0x1000, 32 | 16 | 8 }, /* L4TA36 */ -+ [107] = { 0x9c000, 0x1000, 16 | 8 }, /* MMC SDIO */ -+ [108] = { 0x9d000, 0x1000, 32 | 16 | 8 }, /* L4TAO9 */ -+ [109] = { 0x9e000, 0x1000, 32 | 16 | 8 }, /* MS_PRO */ -+ [110] = { 0x9f000, 0x1000, 32 | 16 | 8 }, /* L4TAO10 */ -+ [111] = { 0xa0000, 0x1000, 32 }, /* RNG */ -+ [112] = { 0xa1000, 0x1000, 32 | 16 | 8 }, /* L4TAO11 */ -+ [113] = { 0xa2000, 0x1000, 32 }, /* DES3DES */ -+ [114] = { 0xa3000, 0x1000, 32 | 16 | 8 }, /* L4TAO12 */ -+ [115] = { 0xa4000, 0x1000, 32 }, /* SHA1MD5 */ -+ [116] = { 0xa5000, 0x1000, 32 | 16 | 8 }, /* L4TAO13 */ -+ [117] = { 0xa6000, 0x1000, 32 }, /* AES */ -+ [118] = { 0xa7000, 0x1000, 32 | 16 | 8 }, /* L4TA37 */ -+ [119] = { 0xa8000, 0x2000, 32 }, /* PKA */ -+ [120] = { 0xaa000, 0x1000, 32 | 16 | 8 }, /* L4TA38 */ -+ [121] = { 0xb0000, 0x1000, 32 }, /* MG */ -+ [122] = { 0xb1000, 0x1000, 32 | 16 | 8 }, -+ [123] = { 0xb2000, 0x1000, 32 }, /* HDQ/1-Wire */ -+ [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] = { -+ { 0, 0, 3, 2 }, /* L4IA initiatior agent */ -+ { L4TAO(1), 3, 2, 1 }, /* Control and pinout module */ -+ { L4TAO(2), 5, 2, 1 }, /* 32K timer */ -+ { L4TAO(3), 7, 3, 2 }, /* PRCM */ -+ { L4TA(1), 10, 2, 1 }, /* BCM */ -+ { L4TA(2), 12, 2, 1 }, /* Test JTAG */ -+ { L4TA(3), 14, 6, 3 }, /* Quad GPIO */ -+ { L4TA(4), 20, 4, 3 }, /* WD timer 1/2 */ -+ { L4TA(7), 24, 2, 1 }, /* GP timer 1 */ -+ { L4TA(9), 26, 2, 1 }, /* ATM11 ETB */ -+ { L4TA(10), 28, 5, 4 }, /* Display subsystem */ -+ { L4TA(11), 33, 5, 4 }, /* Camera subsystem */ -+ { L4TA(12), 38, 2, 1 }, /* sDMA */ -+ { L4TA(13), 40, 5, 4 }, /* SSI */ -+ { L4TAO(4), 45, 2, 1 }, /* USB */ -+ { L4TA(14), 47, 2, 1 }, /* Win Tracer1 */ -+ { L4TA(15), 49, 2, 1 }, /* Win Tracer2 */ -+ { L4TA(16), 51, 2, 1 }, /* Win Tracer3 */ -+ { L4TA(17), 53, 2, 1 }, /* Win Tracer4 */ -+ { L4TA(18), 55, 2, 1 }, /* XTI */ -+ { L4TA(19), 57, 2, 1 }, /* UART1 */ -+ { L4TA(20), 59, 2, 1 }, /* UART2 */ -+ { L4TA(21), 61, 2, 1 }, /* UART3 */ -+ { L4TAO(5), 63, 2, 1 }, /* I2C1 */ -+ { L4TAO(6), 65, 2, 1 }, /* I2C2 */ -+ { L4TAO(7), 67, 2, 1 }, /* McBSP1 */ -+ { L4TAO(8), 69, 2, 1 }, /* McBSP2 */ -+ { L4TA(5), 71, 2, 1 }, /* WD Timer 3 (DSP) */ -+ { L4TA(6), 73, 2, 1 }, /* WD Timer 4 (IVA) */ -+ { L4TA(8), 75, 2, 1 }, /* GP Timer 2 */ -+ { L4TA(22), 77, 2, 1 }, /* GP Timer 3 */ -+ { L4TA(23), 79, 2, 1 }, /* GP Timer 4 */ -+ { L4TA(24), 81, 2, 1 }, /* GP Timer 5 */ -+ { L4TA(25), 83, 2, 1 }, /* GP Timer 6 */ -+ { L4TA(26), 85, 2, 1 }, /* GP Timer 7 */ -+ { L4TA(27), 87, 2, 1 }, /* GP Timer 8 */ -+ { L4TA(28), 89, 2, 1 }, /* GP Timer 9 */ -+ { L4TA(29), 91, 2, 1 }, /* GP Timer 10 */ -+ { L4TA(30), 93, 2, 1 }, /* GP Timer 11 */ -+ { L4TA(31), 95, 2, 1 }, /* GP Timer 12 */ -+ { L4TA(32), 97, 2, 1 }, /* EAC */ -+ { L4TA(33), 99, 2, 1 }, /* FAC */ -+ { L4TA(34), 101, 2, 1 }, /* IPC */ -+ { L4TA(35), 103, 2, 1 }, /* SPI1 */ -+ { L4TA(36), 105, 2, 1 }, /* SPI2 */ -+ { L4TAO(9), 107, 2, 1 }, /* MMC SDIO */ -+ { L4TAO(10), 109, 2, 1 }, -+ { L4TAO(11), 111, 2, 1 }, /* RNG */ -+ { L4TAO(12), 113, 2, 1 }, /* DES3DES */ -+ { L4TAO(13), 115, 2, 1 }, /* SHA1MD5 */ -+ { L4TA(37), 117, 2, 1 }, /* AES */ -+ { L4TA(38), 119, 2, 1 }, /* PKA */ -+ { -1, 121, 2, 1 }, -+ { L4TA(39), 123, 2, 1 }, /* HDQ/1-Wire */ -+}; -+ -+#define omap_l4ta(bus, cs) omap_l4ta_get(bus, L4TA(cs)) -+#define omap_l4tao(bus, cs) omap_l4ta_get(bus, L4TAO(cs)) -+ -+struct omap_target_agent_s *omap_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 (omap_l4_agent_info[i].ta == cs) { -+ ta = &bus->ta[i]; -+ info = &omap_l4_agent_info[i]; -+ break; -+ } -+ if (!ta) { -+ fprintf(stderr, "%s: bad target agent (%i)\n", __FUNCTION__, cs); -+ exit(-1); -+ } -+ -+ ta->bus = bus; -+ ta->start = &omap_l4_region[info->region]; -+ ta->regions = info->regions; -+ ta->base = bus->base + ta->start[info->ta_region].offset; -+ -+ ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0); -+ ta->status = 0x00000000; -+ ta->control = 0x00000200; /* XXX 01000200 for L4TAO */ -+ -+ iomemtype = cpu_register_io_memory(0, omap_l4ta_readfn, -+ omap_l4ta_writefn, ta); -+ cpu_register_physical_memory(ta->base, 0x200, iomemtype); -+ -+ return ta; -+} -+ -+target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region, -+ int iotype) -+{ -+ target_phys_addr_t base; -+ size_t size; -+ -+ if (region < 0 || region >= ta->regions) { -+ fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region); -+ exit(-1); -+ } -+ -+ base = ta->bus->base + ta->start[region].offset; -+ size = ta->start[region].size; -+ if (iotype) -+ cpu_register_physical_memory(base, size, iotype); -+ -+ return base; -+} -+ -+/* TEST-Chip-level TAP */ -+static uint32_t omap_tap_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; -+ target_phys_addr_t reg = addr - s->tap_base; -+ -+ switch (reg) { -+ case 0x204: /* IDCODE_reg */ -+ switch (s->mpu_model) { -+ case omap2420: -+ case omap2422: -+ case omap2423: -+ return 0x5b5d902f; /* ES 2.2 */ -+ case omap2430: -+ return 0x5b68a02f; /* ES 2.2 */ -+ case omap3430: -+ return 0x1b7ae02f; /* ES 2 */ -+ default: -+ cpu_abort(cpu_single_env, "%s: Bad mpu model\n", __FUNCTION__); -+ } -+ -+ case 0x208: /* PRODUCTION_ID_reg for OMAP2 */ -+ case 0x210: /* PRODUCTION_ID_reg for OMAP3 */ -+ switch (s->mpu_model) { -+ case omap2420: -+ return 0x000200f0; /* POP ESHS2.1.1 in N91/93/95, ES2 in N800 */ -+ case omap2422: -+ return 0x000400f0; -+ case omap2423: -+ return 0x000800f0; -+ case omap2430: -+ return 0x000000f0; -+ case omap3430: -+ return 0x000000f0; -+ default: -+ cpu_abort(cpu_single_env, "%s: Bad mpu model\n", __FUNCTION__); -+ } -+ -+ case 0x218: /* DIE_ID_reg */ -+ return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0); -+ case 0x21c: /* DIE_ID_reg */ -+ return ( 5 << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0); -+ case 0x220: /* DIE_ID_reg */ -+ return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0); -+ case 0x224: /* DIE_ID_reg */ -+ return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0); -+ } -+ -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap_tap_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ OMAP_BAD_REG(addr); -+} -+ -+static CPUReadMemoryFunc *omap_tap_readfn[] = { -+ omap_badwidth_read32, -+ omap_badwidth_read32, -+ omap_tap_read, -+}; -+ -+static CPUWriteMemoryFunc *omap_tap_writefn[] = { -+ omap_badwidth_write32, -+ omap_badwidth_write32, -+ omap_tap_write, -+}; -+ -+void omap_tap_init(struct omap_target_agent_s *ta, -+ struct omap_mpu_state_s *mpu) -+{ -+ mpu->tap_base = omap_l4_attach(ta, 0, cpu_register_io_memory(0, -+ omap_tap_readfn, omap_tap_writefn, mpu)); -+} -+ -+/* Power, Reset, and Clock Management */ -+struct omap_prcm_s { -+ target_phys_addr_t base; -+ qemu_irq irq[3]; -+ struct omap_mpu_state_s *mpu; -+ -+ uint32_t irqst[3]; -+ uint32_t irqen[3]; -+ -+ uint32_t sysconfig; -+ uint32_t voltctrl; -+ uint32_t scratch[20]; -+ -+ uint32_t clksrc[1]; -+ uint32_t clkout[1]; -+ uint32_t clkemul[1]; -+ uint32_t clkpol[1]; -+ uint32_t clksel[8]; -+ uint32_t clken[12]; -+ uint32_t clkctrl[4]; -+ uint32_t clkidle[7]; -+ uint32_t setuptime[2]; -+ -+ uint32_t wkup[3]; -+ uint32_t wken[3]; -+ uint32_t wkst[3]; -+ uint32_t rst[4]; -+ uint32_t rstctrl[1]; -+ uint32_t power[4]; -+ uint32_t rsttime_wkup; -+ -+ uint32_t ev; -+ uint32_t evtime[2]; -+}; -+ -+static void omap_prcm_int_update(struct omap_prcm_s *s, int dom) -+{ -+ qemu_set_irq(s->irq[dom], s->irqst[dom] & s->irqen[dom]); -+ /* XXX or is the mask applied before PRCM_IRQSTATUS_* ? */ -+} -+ -+static uint32_t omap_prcm_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_prcm_s *s = (struct omap_prcm_s *) opaque; -+ int offset = addr - s->base; -+ -+ switch (offset) { -+ case 0x000: /* PRCM_REVISION */ -+ return 0x10; -+ -+ case 0x010: /* PRCM_SYSCONFIG */ -+ return s->sysconfig; -+ -+ case 0x018: /* PRCM_IRQSTATUS_MPU */ -+ return s->irqst[0]; -+ -+ case 0x01c: /* PRCM_IRQENABLE_MPU */ -+ return s->irqen[0]; -+ -+ case 0x050: /* PRCM_VOLTCTRL */ -+ return s->voltctrl; -+ case 0x054: /* PRCM_VOLTST */ -+ return s->voltctrl & 3; -+ -+ case 0x060: /* PRCM_CLKSRC_CTRL */ -+ return s->clksrc[0]; -+ case 0x070: /* PRCM_CLKOUT_CTRL */ -+ return s->clkout[0]; -+ case 0x078: /* PRCM_CLKEMUL_CTRL */ -+ return s->clkemul[0]; -+ case 0x080: /* PRCM_CLKCFG_CTRL */ -+ case 0x084: /* PRCM_CLKCFG_STATUS */ -+ return 0; -+ -+ case 0x090: /* PRCM_VOLTSETUP */ -+ return s->setuptime[0]; -+ -+ case 0x094: /* PRCM_CLKSSETUP */ -+ return s->setuptime[1]; -+ -+ case 0x098: /* PRCM_POLCTRL */ -+ return s->clkpol[0]; -+ -+ case 0x0b0: /* GENERAL_PURPOSE1 */ -+ case 0x0b4: /* GENERAL_PURPOSE2 */ -+ case 0x0b8: /* GENERAL_PURPOSE3 */ -+ case 0x0bc: /* GENERAL_PURPOSE4 */ -+ case 0x0c0: /* GENERAL_PURPOSE5 */ -+ case 0x0c4: /* GENERAL_PURPOSE6 */ -+ case 0x0c8: /* GENERAL_PURPOSE7 */ -+ case 0x0cc: /* GENERAL_PURPOSE8 */ -+ case 0x0d0: /* GENERAL_PURPOSE9 */ -+ case 0x0d4: /* GENERAL_PURPOSE10 */ -+ case 0x0d8: /* GENERAL_PURPOSE11 */ -+ case 0x0dc: /* GENERAL_PURPOSE12 */ -+ case 0x0e0: /* GENERAL_PURPOSE13 */ -+ case 0x0e4: /* GENERAL_PURPOSE14 */ -+ case 0x0e8: /* GENERAL_PURPOSE15 */ -+ case 0x0ec: /* GENERAL_PURPOSE16 */ -+ case 0x0f0: /* GENERAL_PURPOSE17 */ -+ case 0x0f4: /* GENERAL_PURPOSE18 */ -+ case 0x0f8: /* GENERAL_PURPOSE19 */ -+ case 0x0fc: /* GENERAL_PURPOSE20 */ -+ return s->scratch[(offset - 0xb0) >> 2]; -+ -+ case 0x140: /* CM_CLKSEL_MPU */ -+ return s->clksel[0]; -+ case 0x148: /* CM_CLKSTCTRL_MPU */ -+ return s->clkctrl[0]; -+ -+ case 0x158: /* RM_RSTST_MPU */ -+ return s->rst[0]; -+ case 0x1c8: /* PM_WKDEP_MPU */ -+ return s->wkup[0]; -+ case 0x1d4: /* PM_EVGENCTRL_MPU */ -+ return s->ev; -+ case 0x1d8: /* PM_EVEGENONTIM_MPU */ -+ return s->evtime[0]; -+ case 0x1dc: /* PM_EVEGENOFFTIM_MPU */ -+ return s->evtime[1]; -+ case 0x1e0: /* PM_PWSTCTRL_MPU */ -+ return s->power[0]; -+ case 0x1e4: /* PM_PWSTST_MPU */ -+ return 0; -+ -+ case 0x200: /* CM_FCLKEN1_CORE */ -+ return s->clken[0]; -+ case 0x204: /* CM_FCLKEN2_CORE */ -+ return s->clken[1]; -+ case 0x210: /* CM_ICLKEN1_CORE */ -+ return s->clken[2]; -+ case 0x214: /* CM_ICLKEN2_CORE */ -+ return s->clken[3]; -+ case 0x21c: /* CM_ICLKEN4_CORE */ -+ return s->clken[4]; -+ -+ case 0x220: /* CM_IDLEST1_CORE */ -+ /* TODO: check the actual iclk status */ -+ return 0x7ffffff9; -+ case 0x224: /* CM_IDLEST2_CORE */ -+ /* TODO: check the actual iclk status */ -+ return 0x00000007; -+ case 0x22c: /* CM_IDLEST4_CORE */ -+ /* TODO: check the actual iclk status */ -+ return 0x0000001f; -+ -+ case 0x230: /* CM_AUTOIDLE1_CORE */ -+ return s->clkidle[0]; -+ case 0x234: /* CM_AUTOIDLE2_CORE */ -+ return s->clkidle[1]; -+ case 0x238: /* CM_AUTOIDLE3_CORE */ -+ return s->clkidle[2]; -+ case 0x23c: /* CM_AUTOIDLE4_CORE */ -+ return s->clkidle[3]; -+ -+ case 0x240: /* CM_CLKSEL1_CORE */ -+ return s->clksel[1]; -+ case 0x244: /* CM_CLKSEL2_CORE */ -+ return s->clksel[2]; -+ -+ case 0x248: /* CM_CLKSTCTRL_CORE */ -+ return s->clkctrl[1]; -+ -+ case 0x2a0: /* PM_WKEN1_CORE */ -+ return s->wken[0]; -+ case 0x2a4: /* PM_WKEN2_CORE */ -+ return s->wken[1]; -+ -+ case 0x2b0: /* PM_WKST1_CORE */ -+ return s->wkst[0]; -+ case 0x2b4: /* PM_WKST2_CORE */ -+ return s->wkst[1]; -+ case 0x2c8: /* PM_WKDEP_CORE */ -+ return 0x1e; -+ -+ case 0x2e0: /* PM_PWSTCTRL_CORE */ -+ return s->power[1]; -+ case 0x2e4: /* PM_PWSTST_CORE */ -+ return 0x000030 | (s->power[1] & 0xfc00); -+ -+ case 0x300: /* CM_FCLKEN_GFX */ -+ return s->clken[5]; -+ case 0x310: /* CM_ICLKEN_GFX */ -+ return s->clken[6]; -+ case 0x320: /* CM_IDLEST_GFX */ -+ /* TODO: check the actual iclk status */ -+ return 0x00000001; -+ case 0x340: /* CM_CLKSEL_GFX */ -+ return s->clksel[3]; -+ case 0x348: /* CM_CLKSTCTRL_GFX */ -+ return s->clkctrl[2]; -+ case 0x350: /* RM_RSTCTRL_GFX */ -+ return s->rstctrl[0]; -+ case 0x358: /* RM_RSTST_GFX */ -+ return s->rst[1]; -+ case 0x3c8: /* PM_WKDEP_GFX */ -+ return s->wkup[1]; -+ -+ case 0x3e0: /* PM_PWSTCTRL_GFX */ -+ return s->power[2]; -+ case 0x3e4: /* PM_PWSTST_GFX */ -+ return s->power[2] & 3; -+ -+ case 0x400: /* CM_FCLKEN_WKUP */ -+ return s->clken[7]; -+ case 0x410: /* CM_ICLKEN_WKUP */ -+ return s->clken[8]; -+ case 0x420: /* CM_IDLEST_WKUP */ -+ /* TODO: check the actual iclk status */ -+ return 0x0000003f; -+ case 0x430: /* CM_AUTOIDLE_WKUP */ -+ return s->clkidle[4]; -+ case 0x440: /* CM_CLKSEL_WKUP */ -+ return s->clksel[4]; -+ case 0x450: /* RM_RSTCTRL_WKUP */ -+ return 0; -+ case 0x454: /* RM_RSTTIME_WKUP */ -+ return s->rsttime_wkup; -+ case 0x458: /* RM_RSTST_WKUP */ -+ return s->rst[2]; -+ case 0x4a0: /* PM_WKEN_WKUP */ -+ return s->wken[2]; -+ case 0x4b0: /* PM_WKST_WKUP */ -+ return s->wkst[2]; -+ -+ case 0x500: /* CM_CLKEN_PLL */ -+ return s->clken[9]; -+ case 0x520: /* CM_IDLEST_CKGEN */ -+ /* Core uses 32-kHz clock */ -+ if (!(s->clksel[6] & 3)) -+ return 0x00000377; -+ /* DPLL not in lock mode, core uses ref_clk */ -+ if ((s->clken[9] & 3) != 3) -+ return 0x00000375; -+ /* Core uses DPLL */ -+ return 0x00000376; -+ case 0x530: /* CM_AUTOIDLE_PLL */ -+ return s->clkidle[5]; -+ case 0x540: /* CM_CLKSEL1_PLL */ -+ return s->clksel[5]; -+ case 0x544: /* CM_CLKSEL2_PLL */ -+ return s->clksel[6]; -+ -+ case 0x800: /* CM_FCLKEN_DSP */ -+ return s->clken[10]; -+ case 0x810: /* CM_ICLKEN_DSP */ -+ return s->clken[11]; -+ case 0x820: /* CM_IDLEST_DSP */ -+ /* TODO: check the actual iclk status */ -+ return 0x00000103; -+ case 0x830: /* CM_AUTOIDLE_DSP */ -+ return s->clkidle[6]; -+ case 0x840: /* CM_CLKSEL_DSP */ -+ return s->clksel[7]; -+ case 0x848: /* CM_CLKSTCTRL_DSP */ -+ return s->clkctrl[3]; -+ case 0x850: /* RM_RSTCTRL_DSP */ -+ return 0; -+ case 0x858: /* RM_RSTST_DSP */ -+ return s->rst[3]; -+ case 0x8c8: /* PM_WKDEP_DSP */ -+ return s->wkup[2]; -+ case 0x8e0: /* PM_PWSTCTRL_DSP */ -+ return s->power[3]; -+ case 0x8e4: /* PM_PWSTST_DSP */ -+ return 0x008030 | (s->power[3] & 0x3003); -+ -+ case 0x8f0: /* PRCM_IRQSTATUS_DSP */ -+ return s->irqst[1]; -+ case 0x8f4: /* PRCM_IRQENABLE_DSP */ -+ return s->irqen[1]; -+ -+ case 0x8f8: /* PRCM_IRQSTATUS_IVA */ -+ return s->irqst[2]; -+ case 0x8fc: /* PRCM_IRQENABLE_IVA */ -+ return s->irqen[2]; -+ } -+ -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap_prcm_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_prcm_s *s = (struct omap_prcm_s *) opaque; -+ int offset = addr - s->base; -+ -+ switch (offset) { -+ case 0x000: /* PRCM_REVISION */ -+ case 0x054: /* PRCM_VOLTST */ -+ case 0x084: /* PRCM_CLKCFG_STATUS */ -+ case 0x1e4: /* PM_PWSTST_MPU */ -+ case 0x220: /* CM_IDLEST1_CORE */ -+ case 0x224: /* CM_IDLEST2_CORE */ -+ case 0x22c: /* CM_IDLEST4_CORE */ -+ case 0x2c8: /* PM_WKDEP_CORE */ -+ case 0x2e4: /* PM_PWSTST_CORE */ -+ case 0x320: /* CM_IDLEST_GFX */ -+ case 0x3e4: /* PM_PWSTST_GFX */ -+ case 0x420: /* CM_IDLEST_WKUP */ -+ case 0x520: /* CM_IDLEST_CKGEN */ -+ case 0x820: /* CM_IDLEST_DSP */ -+ case 0x8e4: /* PM_PWSTST_DSP */ -+ OMAP_RO_REG(addr); -+ return; -+ -+ case 0x010: /* PRCM_SYSCONFIG */ -+ s->sysconfig = value & 1; -+ break; -+ -+ case 0x018: /* PRCM_IRQSTATUS_MPU */ -+ s->irqst[0] &= ~value; -+ omap_prcm_int_update(s, 0); -+ break; -+ case 0x01c: /* PRCM_IRQENABLE_MPU */ -+ s->irqen[0] = value & 0x3f; -+ omap_prcm_int_update(s, 0); -+ break; -+ -+ case 0x050: /* PRCM_VOLTCTRL */ -+ s->voltctrl = value & 0xf1c3; -+ break; -+ -+ case 0x060: /* PRCM_CLKSRC_CTRL */ -+ s->clksrc[0] = value & 0xdb; -+ /* TODO update clocks */ -+ break; -+ -+ case 0x070: /* PRCM_CLKOUT_CTRL */ -+ s->clkout[0] = value & 0xbbbb; -+ /* TODO update clocks */ -+ break; -+ -+ case 0x078: /* PRCM_CLKEMUL_CTRL */ -+ s->clkemul[0] = value & 1; -+ /* TODO update clocks */ -+ break; -+ -+ case 0x080: /* PRCM_CLKCFG_CTRL */ -+ break; -+ -+ case 0x090: /* PRCM_VOLTSETUP */ -+ s->setuptime[0] = value & 0xffff; -+ break; -+ case 0x094: /* PRCM_CLKSSETUP */ -+ s->setuptime[1] = value & 0xffff; -+ break; -+ -+ case 0x098: /* PRCM_POLCTRL */ -+ s->clkpol[0] = value & 0x701; -+ break; -+ -+ case 0x0b0: /* GENERAL_PURPOSE1 */ -+ case 0x0b4: /* GENERAL_PURPOSE2 */ -+ case 0x0b8: /* GENERAL_PURPOSE3 */ -+ case 0x0bc: /* GENERAL_PURPOSE4 */ -+ case 0x0c0: /* GENERAL_PURPOSE5 */ -+ case 0x0c4: /* GENERAL_PURPOSE6 */ -+ case 0x0c8: /* GENERAL_PURPOSE7 */ -+ case 0x0cc: /* GENERAL_PURPOSE8 */ -+ case 0x0d0: /* GENERAL_PURPOSE9 */ -+ case 0x0d4: /* GENERAL_PURPOSE10 */ -+ case 0x0d8: /* GENERAL_PURPOSE11 */ -+ case 0x0dc: /* GENERAL_PURPOSE12 */ -+ case 0x0e0: /* GENERAL_PURPOSE13 */ -+ case 0x0e4: /* GENERAL_PURPOSE14 */ -+ case 0x0e8: /* GENERAL_PURPOSE15 */ -+ case 0x0ec: /* GENERAL_PURPOSE16 */ -+ case 0x0f0: /* GENERAL_PURPOSE17 */ -+ case 0x0f4: /* GENERAL_PURPOSE18 */ -+ case 0x0f8: /* GENERAL_PURPOSE19 */ -+ case 0x0fc: /* GENERAL_PURPOSE20 */ -+ s->scratch[(offset - 0xb0) >> 2] = value; -+ break; -+ -+ case 0x140: /* CM_CLKSEL_MPU */ -+ s->clksel[0] = value & 0x1f; -+ /* TODO update clocks */ -+ break; -+ case 0x148: /* CM_CLKSTCTRL_MPU */ -+ s->clkctrl[0] = value & 0x1f; -+ break; -+ -+ case 0x158: /* RM_RSTST_MPU */ -+ s->rst[0] &= ~value; -+ break; -+ case 0x1c8: /* PM_WKDEP_MPU */ -+ s->wkup[0] = value & 0x15; -+ break; -+ -+ case 0x1d4: /* PM_EVGENCTRL_MPU */ -+ s->ev = value & 0x1f; -+ break; -+ case 0x1d8: /* PM_EVEGENONTIM_MPU */ -+ s->evtime[0] = value; -+ break; -+ case 0x1dc: /* PM_EVEGENOFFTIM_MPU */ -+ s->evtime[1] = value; -+ break; -+ -+ case 0x1e0: /* PM_PWSTCTRL_MPU */ -+ s->power[0] = value & 0xc0f; -+ break; -+ -+ case 0x200: /* CM_FCLKEN1_CORE */ -+ s->clken[0] = value & 0xbfffffff; -+ /* TODO update clocks */ -+ break; -+ case 0x204: /* CM_FCLKEN2_CORE */ -+ s->clken[1] = value & 0x00000007; -+ /* TODO update clocks */ -+ break; -+ case 0x210: /* CM_ICLKEN1_CORE */ -+ s->clken[2] = value & 0xfffffff9; -+ /* TODO update clocks */ -+ break; -+ case 0x214: /* CM_ICLKEN2_CORE */ -+ s->clken[3] = value & 0x00000007; -+ /* TODO update clocks */ -+ break; -+ case 0x21c: /* CM_ICLKEN4_CORE */ -+ s->clken[4] = value & 0x0000001f; -+ /* TODO update clocks */ -+ break; -+ -+ case 0x230: /* CM_AUTOIDLE1_CORE */ -+ s->clkidle[0] = value & 0xfffffff9; -+ /* TODO update clocks */ -+ break; -+ case 0x234: /* CM_AUTOIDLE2_CORE */ -+ s->clkidle[1] = value & 0x00000007; -+ /* TODO update clocks */ -+ break; -+ case 0x238: /* CM_AUTOIDLE3_CORE */ -+ s->clkidle[2] = value & 0x00000007; -+ /* TODO update clocks */ -+ break; -+ case 0x23c: /* CM_AUTOIDLE4_CORE */ -+ s->clkidle[3] = value & 0x0000001f; -+ /* TODO update clocks */ -+ break; -+ -+ case 0x240: /* CM_CLKSEL1_CORE */ -+ s->clksel[1] = value & 0x0fffbf7f; -+ /* TODO update clocks */ -+ break; -+ -+ case 0x244: /* CM_CLKSEL2_CORE */ -+ s->clksel[2] = value & 0x00fffffc; -+ /* TODO update clocks */ -+ break; -+ -+ case 0x248: /* CM_CLKSTCTRL_CORE */ -+ s->clkctrl[1] = value & 0x7; -+ break; -+ -+ case 0x2a0: /* PM_WKEN1_CORE */ -+ s->wken[0] = value & 0x04667ff8; -+ break; -+ case 0x2a4: /* PM_WKEN2_CORE */ -+ s->wken[1] = value & 0x00000005; -+ break; -+ -+ case 0x2b0: /* PM_WKST1_CORE */ -+ s->wkst[0] &= ~value; -+ break; -+ case 0x2b4: /* PM_WKST2_CORE */ -+ s->wkst[1] &= ~value; -+ break; -+ -+ case 0x2e0: /* PM_PWSTCTRL_CORE */ -+ s->power[1] = (value & 0x00fc3f) | (1 << 2); -+ break; -+ -+ case 0x300: /* CM_FCLKEN_GFX */ -+ s->clken[5] = value & 6; -+ /* TODO update clocks */ -+ break; -+ case 0x310: /* CM_ICLKEN_GFX */ -+ s->clken[6] = value & 1; -+ /* TODO update clocks */ -+ break; -+ case 0x340: /* CM_CLKSEL_GFX */ -+ s->clksel[3] = value & 7; -+ /* TODO update clocks */ -+ break; -+ case 0x348: /* CM_CLKSTCTRL_GFX */ -+ s->clkctrl[2] = value & 1; -+ break; -+ case 0x350: /* RM_RSTCTRL_GFX */ -+ s->rstctrl[0] = value & 1; -+ /* TODO: reset */ -+ break; -+ case 0x358: /* RM_RSTST_GFX */ -+ s->rst[1] &= ~value; -+ break; -+ case 0x3c8: /* PM_WKDEP_GFX */ -+ s->wkup[1] = value & 0x13; -+ break; -+ case 0x3e0: /* PM_PWSTCTRL_GFX */ -+ s->power[2] = (value & 0x00c0f) | (3 << 2); -+ break; -+ -+ case 0x400: /* CM_FCLKEN_WKUP */ -+ s->clken[7] = value & 0xd; -+ /* TODO update clocks */ -+ break; -+ case 0x410: /* CM_ICLKEN_WKUP */ -+ s->clken[8] = value & 0x3f; -+ /* TODO update clocks */ -+ break; -+ case 0x430: /* CM_AUTOIDLE_WKUP */ -+ s->clkidle[4] = value & 0x0000003f; -+ /* TODO update clocks */ -+ break; -+ case 0x440: /* CM_CLKSEL_WKUP */ -+ s->clksel[4] = value & 3; -+ /* TODO update clocks */ -+ break; -+ case 0x450: /* RM_RSTCTRL_WKUP */ -+ /* TODO: reset */ -+ if (value & 2) -+ qemu_system_reset_request(); -+ break; -+ case 0x454: /* RM_RSTTIME_WKUP */ -+ s->rsttime_wkup = value & 0x1fff; -+ break; -+ case 0x458: /* RM_RSTST_WKUP */ -+ s->rst[2] &= ~value; -+ break; -+ case 0x4a0: /* PM_WKEN_WKUP */ -+ s->wken[2] = value & 0x00000005; -+ break; -+ case 0x4b0: /* PM_WKST_WKUP */ -+ s->wkst[2] &= ~value; -+ break; -+ -+ case 0x500: /* CM_CLKEN_PLL */ -+ s->clken[9] = value & 0xcf; -+ /* TODO update clocks */ -+ break; -+ case 0x530: /* CM_AUTOIDLE_PLL */ -+ s->clkidle[5] = value & 0x000000cf; -+ /* TODO update clocks */ -+ break; -+ case 0x540: /* CM_CLKSEL1_PLL */ -+ s->clksel[5] = value & 0x03bfff28; -+ /* TODO update clocks */ -+ break; -+ case 0x544: /* CM_CLKSEL2_PLL */ -+ s->clksel[6] = value & 3; -+ /* TODO update clocks */ -+ break; -+ -+ case 0x800: /* CM_FCLKEN_DSP */ -+ s->clken[10] = value & 0x501; -+ /* TODO update clocks */ -+ break; -+ case 0x810: /* CM_ICLKEN_DSP */ -+ s->clken[11] = value & 0x2; -+ /* TODO update clocks */ -+ break; -+ case 0x830: /* CM_AUTOIDLE_DSP */ -+ s->clkidle[6] = value & 0x2; -+ /* TODO update clocks */ -+ break; -+ case 0x840: /* CM_CLKSEL_DSP */ -+ s->clksel[7] = value & 0x3fff; -+ /* TODO update clocks */ -+ break; -+ case 0x848: /* CM_CLKSTCTRL_DSP */ -+ s->clkctrl[3] = value & 0x101; -+ break; -+ case 0x850: /* RM_RSTCTRL_DSP */ -+ /* TODO: reset */ -+ break; -+ case 0x858: /* RM_RSTST_DSP */ -+ s->rst[3] &= ~value; -+ break; -+ case 0x8c8: /* PM_WKDEP_DSP */ -+ s->wkup[2] = value & 0x13; -+ break; -+ case 0x8e0: /* PM_PWSTCTRL_DSP */ -+ s->power[3] = (value & 0x03017) | (3 << 2); -+ break; -+ -+ case 0x8f0: /* PRCM_IRQSTATUS_DSP */ -+ s->irqst[1] &= ~value; -+ omap_prcm_int_update(s, 1); -+ break; -+ case 0x8f4: /* PRCM_IRQENABLE_DSP */ -+ s->irqen[1] = value & 0x7; -+ omap_prcm_int_update(s, 1); -+ break; -+ -+ case 0x8f8: /* PRCM_IRQSTATUS_IVA */ -+ s->irqst[2] &= ~value; -+ omap_prcm_int_update(s, 2); -+ break; -+ case 0x8fc: /* PRCM_IRQENABLE_IVA */ -+ s->irqen[2] = value & 0x7; -+ omap_prcm_int_update(s, 2); -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ return; -+ } -+} -+ -+static CPUReadMemoryFunc *omap_prcm_readfn[] = { -+ omap_badwidth_read32, -+ omap_badwidth_read32, -+ omap_prcm_read, -+}; -+ -+static CPUWriteMemoryFunc *omap_prcm_writefn[] = { -+ omap_badwidth_write32, -+ omap_badwidth_write32, -+ omap_prcm_write, -+}; -+ -+static void omap_prcm_reset(struct omap_prcm_s *s) -+{ -+ s->sysconfig = 0; -+ s->irqst[0] = 0; -+ s->irqst[1] = 0; -+ s->irqst[2] = 0; -+ s->irqen[0] = 0; -+ s->irqen[1] = 0; -+ s->irqen[2] = 0; -+ s->voltctrl = 0x1040; -+ s->ev = 0x14; -+ s->evtime[0] = 0; -+ s->evtime[1] = 0; -+ s->clkctrl[0] = 0; -+ s->clkctrl[1] = 0; -+ s->clkctrl[2] = 0; -+ s->clkctrl[3] = 0; -+ s->clken[1] = 7; -+ s->clken[3] = 7; -+ s->clken[4] = 0; -+ s->clken[5] = 0; -+ s->clken[6] = 0; -+ s->clken[7] = 0xc; -+ s->clken[8] = 0x3e; -+ s->clken[9] = 0x0d; -+ s->clken[10] = 0; -+ s->clken[11] = 0; -+ s->clkidle[0] = 0; -+ s->clkidle[2] = 7; -+ s->clkidle[3] = 0; -+ s->clkidle[4] = 0; -+ s->clkidle[5] = 0x0c; -+ s->clkidle[6] = 0; -+ s->clksel[0] = 0x01; -+ s->clksel[1] = 0x02100121; -+ s->clksel[2] = 0x00000000; -+ s->clksel[3] = 0x01; -+ s->clksel[4] = 0; -+ s->clksel[7] = 0x0121; -+ s->wkup[0] = 0x15; -+ s->wkup[1] = 0x13; -+ s->wkup[2] = 0x13; -+ s->wken[0] = 0x04667ff8; -+ s->wken[1] = 0x00000005; -+ s->wken[2] = 5; -+ s->wkst[0] = 0; -+ s->wkst[1] = 0; -+ s->wkst[2] = 0; -+ s->power[0] = 0x00c; -+ s->power[1] = 4; -+ s->power[2] = 0x0000c; -+ s->power[3] = 0x14; -+ s->rstctrl[0] = 1; -+ s->rst[3] = 1; -+} -+ -+static void omap_prcm_coldreset(struct omap_prcm_s *s) -+{ -+ s->setuptime[0] = 0; -+ s->setuptime[1] = 0; -+ memset(&s->scratch, 0, sizeof(s->scratch)); -+ s->rst[0] = 0x01; -+ s->rst[1] = 0x00; -+ s->rst[2] = 0x01; -+ s->clken[0] = 0; -+ s->clken[2] = 0; -+ s->clkidle[1] = 0; -+ s->clksel[5] = 0; -+ s->clksel[6] = 2; -+ s->clksrc[0] = 0x43; -+ s->clkout[0] = 0x0303; -+ s->clkemul[0] = 0; -+ s->clkpol[0] = 0x100; -+ s->rsttime_wkup = 0x1002; -+ -+ omap_prcm_reset(s); -+} -+ -+struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta, -+ qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int, -+ struct omap_mpu_state_s *mpu) -+{ -+ int iomemtype; -+ struct omap_prcm_s *s = (struct omap_prcm_s *) -+ qemu_mallocz(sizeof(struct omap_prcm_s)); -+ -+ s->irq[0] = mpu_int; -+ s->irq[1] = dsp_int; -+ s->irq[2] = iva_int; -+ s->mpu = mpu; -+ omap_prcm_coldreset(s); -+ -+ iomemtype = cpu_register_io_memory(0, omap_prcm_readfn, -+ omap_prcm_writefn, s); -+ s->base = omap_l4_attach(ta, 0, iomemtype); -+ omap_l4_attach(ta, 1, iomemtype); -+ -+ return s; -+} -+ -+/* System and Pinout control */ -+struct omap_sysctl_s { -+ target_phys_addr_t base; -+ struct omap_mpu_state_s *mpu; -+ -+ uint32_t sysconfig; -+ uint32_t devconfig; -+ uint32_t psaconfig; -+ uint32_t padconf[0x45]; -+ uint8_t obs; -+ uint32_t msuspendmux[5]; -+}; -+ -+static uint32_t omap_sysctl_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque; -+ int offset = addr - s->base; -+ -+ switch (offset) { -+ case 0x000: /* CONTROL_REVISION */ -+ return 0x20; -+ -+ case 0x010: /* CONTROL_SYSCONFIG */ -+ return s->sysconfig; -+ -+ case 0x030 ... 0x140: /* CONTROL_PADCONF - only used in the POP */ -+ return s->padconf[(offset - 0x30) >> 2]; -+ -+ case 0x270: /* CONTROL_DEBOBS */ -+ return s->obs; -+ -+ case 0x274: /* CONTROL_DEVCONF */ -+ return s->devconfig; -+ -+ case 0x28c: /* CONTROL_EMU_SUPPORT */ -+ return 0; -+ -+ case 0x290: /* CONTROL_MSUSPENDMUX_0 */ -+ return s->msuspendmux[0]; -+ case 0x294: /* CONTROL_MSUSPENDMUX_1 */ -+ return s->msuspendmux[1]; -+ case 0x298: /* CONTROL_MSUSPENDMUX_2 */ -+ return s->msuspendmux[2]; -+ case 0x29c: /* CONTROL_MSUSPENDMUX_3 */ -+ return s->msuspendmux[3]; -+ case 0x2a0: /* CONTROL_MSUSPENDMUX_4 */ -+ return s->msuspendmux[4]; -+ case 0x2a4: /* CONTROL_MSUSPENDMUX_5 */ -+ return 0; -+ -+ case 0x2b8: /* CONTROL_PSA_CTRL */ -+ return s->psaconfig; -+ case 0x2bc: /* CONTROL_PSA_CMD */ -+ case 0x2c0: /* CONTROL_PSA_VALUE */ -+ return 0; -+ -+ case 0x2b0: /* CONTROL_SEC_CTRL */ -+ return 0x800000f1; -+ case 0x2d0: /* CONTROL_SEC_EMU */ -+ return 0x80000015; -+ case 0x2d4: /* CONTROL_SEC_TAP */ -+ return 0x8000007f; -+ case 0x2b4: /* CONTROL_SEC_TEST */ -+ case 0x2f0: /* CONTROL_SEC_STATUS */ -+ case 0x2f4: /* CONTROL_SEC_ERR_STATUS */ -+ /* Secure mode is not present on general-pusrpose device. Outside -+ * secure mode these values cannot be read or written. */ -+ return 0; -+ -+ case 0x2d8: /* CONTROL_OCM_RAM_PERM */ -+ return 0xff; -+ case 0x2dc: /* CONTROL_OCM_PUB_RAM_ADD */ -+ case 0x2e0: /* CONTROL_EXT_SEC_RAM_START_ADD */ -+ case 0x2e4: /* CONTROL_EXT_SEC_RAM_STOP_ADD */ -+ /* No secure mode so no Extended Secure RAM present. */ -+ return 0; -+ -+ case 0x2f8: /* CONTROL_STATUS */ -+ /* Device Type => General-purpose */ -+ return 0x0300; -+ case 0x2fc: /* CONTROL_GENERAL_PURPOSE_STATUS */ -+ -+ case 0x300: /* CONTROL_RPUB_KEY_H_0 */ -+ case 0x304: /* CONTROL_RPUB_KEY_H_1 */ -+ case 0x308: /* CONTROL_RPUB_KEY_H_2 */ -+ case 0x30c: /* CONTROL_RPUB_KEY_H_3 */ -+ return 0xdecafbad; -+ -+ case 0x310: /* CONTROL_RAND_KEY_0 */ -+ case 0x314: /* CONTROL_RAND_KEY_1 */ -+ case 0x318: /* CONTROL_RAND_KEY_2 */ -+ case 0x31c: /* CONTROL_RAND_KEY_3 */ -+ case 0x320: /* CONTROL_CUST_KEY_0 */ -+ case 0x324: /* CONTROL_CUST_KEY_1 */ -+ case 0x330: /* CONTROL_TEST_KEY_0 */ -+ case 0x334: /* CONTROL_TEST_KEY_1 */ -+ case 0x338: /* CONTROL_TEST_KEY_2 */ -+ case 0x33c: /* CONTROL_TEST_KEY_3 */ -+ case 0x340: /* CONTROL_TEST_KEY_4 */ -+ case 0x344: /* CONTROL_TEST_KEY_5 */ -+ case 0x348: /* CONTROL_TEST_KEY_6 */ -+ case 0x34c: /* CONTROL_TEST_KEY_7 */ -+ case 0x350: /* CONTROL_TEST_KEY_8 */ -+ case 0x354: /* CONTROL_TEST_KEY_9 */ -+ /* Can only be accessed in secure mode and when C_FieldAccEnable -+ * bit is set in CONTROL_SEC_CTRL. -+ * TODO: otherwise an interconnect access error is generated. */ -+ return 0; -+ } -+ -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap_sysctl_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque; -+ int offset = addr - s->base; -+ -+ switch (offset) { -+ case 0x000: /* CONTROL_REVISION */ -+ case 0x2a4: /* CONTROL_MSUSPENDMUX_5 */ -+ case 0x2c0: /* CONTROL_PSA_VALUE */ -+ case 0x2f8: /* CONTROL_STATUS */ -+ case 0x2fc: /* CONTROL_GENERAL_PURPOSE_STATUS */ -+ case 0x300: /* CONTROL_RPUB_KEY_H_0 */ -+ case 0x304: /* CONTROL_RPUB_KEY_H_1 */ -+ case 0x308: /* CONTROL_RPUB_KEY_H_2 */ -+ case 0x30c: /* CONTROL_RPUB_KEY_H_3 */ -+ case 0x310: /* CONTROL_RAND_KEY_0 */ -+ case 0x314: /* CONTROL_RAND_KEY_1 */ -+ case 0x318: /* CONTROL_RAND_KEY_2 */ -+ case 0x31c: /* CONTROL_RAND_KEY_3 */ -+ case 0x320: /* CONTROL_CUST_KEY_0 */ -+ case 0x324: /* CONTROL_CUST_KEY_1 */ -+ case 0x330: /* CONTROL_TEST_KEY_0 */ -+ case 0x334: /* CONTROL_TEST_KEY_1 */ -+ case 0x338: /* CONTROL_TEST_KEY_2 */ -+ case 0x33c: /* CONTROL_TEST_KEY_3 */ -+ case 0x340: /* CONTROL_TEST_KEY_4 */ -+ case 0x344: /* CONTROL_TEST_KEY_5 */ -+ case 0x348: /* CONTROL_TEST_KEY_6 */ -+ case 0x34c: /* CONTROL_TEST_KEY_7 */ -+ case 0x350: /* CONTROL_TEST_KEY_8 */ -+ case 0x354: /* CONTROL_TEST_KEY_9 */ -+ OMAP_RO_REG(addr); -+ return; -+ -+ case 0x010: /* CONTROL_SYSCONFIG */ -+ s->sysconfig = value & 0x1e; -+ break; -+ -+ case 0x030 ... 0x140: /* CONTROL_PADCONF - only used in the POP */ -+ /* XXX: should check constant bits */ -+ s->padconf[(offset - 0x30) >> 2] = value & 0x1f1f1f1f; -+ break; -+ -+ case 0x270: /* CONTROL_DEBOBS */ -+ s->obs = value & 0xff; -+ break; -+ -+ case 0x274: /* CONTROL_DEVCONF */ -+ s->devconfig = value & 0xffffc7ff; -+ break; -+ -+ case 0x28c: /* CONTROL_EMU_SUPPORT */ -+ break; -+ -+ case 0x290: /* CONTROL_MSUSPENDMUX_0 */ -+ s->msuspendmux[0] = value & 0x3fffffff; -+ break; -+ case 0x294: /* CONTROL_MSUSPENDMUX_1 */ -+ s->msuspendmux[1] = value & 0x3fffffff; -+ break; -+ case 0x298: /* CONTROL_MSUSPENDMUX_2 */ -+ s->msuspendmux[2] = value & 0x3fffffff; -+ break; -+ case 0x29c: /* CONTROL_MSUSPENDMUX_3 */ -+ s->msuspendmux[3] = value & 0x3fffffff; -+ break; -+ case 0x2a0: /* CONTROL_MSUSPENDMUX_4 */ -+ s->msuspendmux[4] = value & 0x3fffffff; -+ break; -+ -+ case 0x2b8: /* CONTROL_PSA_CTRL */ -+ s->psaconfig = value & 0x1c; -+ s->psaconfig |= (value & 0x20) ? 2 : 1; -+ break; -+ case 0x2bc: /* CONTROL_PSA_CMD */ -+ break; -+ -+ case 0x2b0: /* CONTROL_SEC_CTRL */ -+ case 0x2b4: /* CONTROL_SEC_TEST */ -+ case 0x2d0: /* CONTROL_SEC_EMU */ -+ case 0x2d4: /* CONTROL_SEC_TAP */ -+ case 0x2d8: /* CONTROL_OCM_RAM_PERM */ -+ case 0x2dc: /* CONTROL_OCM_PUB_RAM_ADD */ -+ case 0x2e0: /* CONTROL_EXT_SEC_RAM_START_ADD */ -+ case 0x2e4: /* CONTROL_EXT_SEC_RAM_STOP_ADD */ -+ case 0x2f0: /* CONTROL_SEC_STATUS */ -+ case 0x2f4: /* CONTROL_SEC_ERR_STATUS */ -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ return; -+ } -+} -+ -+static CPUReadMemoryFunc *omap_sysctl_readfn[] = { -+ omap_badwidth_read32, /* TODO */ -+ omap_badwidth_read32, /* TODO */ -+ omap_sysctl_read, -+}; -+ -+static CPUWriteMemoryFunc *omap_sysctl_writefn[] = { -+ omap_badwidth_write32, /* TODO */ -+ omap_badwidth_write32, /* TODO */ -+ omap_sysctl_write, -+}; -+ -+static void omap_sysctl_reset(struct omap_sysctl_s *s) -+{ -+ /* (power-on reset) */ -+ s->sysconfig = 0; -+ s->obs = 0; -+ s->devconfig = 0x0c000000; -+ s->msuspendmux[0] = 0x00000000; -+ s->msuspendmux[1] = 0x00000000; -+ s->msuspendmux[2] = 0x00000000; -+ s->msuspendmux[3] = 0x00000000; -+ s->msuspendmux[4] = 0x00000000; -+ s->psaconfig = 1; -+ -+ s->padconf[0x00] = 0x000f0f0f; -+ s->padconf[0x01] = 0x00000000; -+ s->padconf[0x02] = 0x00000000; -+ s->padconf[0x03] = 0x00000000; -+ s->padconf[0x04] = 0x00000000; -+ s->padconf[0x05] = 0x00000000; -+ s->padconf[0x06] = 0x00000000; -+ s->padconf[0x07] = 0x00000000; -+ s->padconf[0x08] = 0x08080800; -+ s->padconf[0x09] = 0x08080808; -+ s->padconf[0x0a] = 0x08080808; -+ s->padconf[0x0b] = 0x08080808; -+ s->padconf[0x0c] = 0x08080808; -+ s->padconf[0x0d] = 0x08080800; -+ s->padconf[0x0e] = 0x08080808; -+ s->padconf[0x0f] = 0x08080808; -+ s->padconf[0x10] = 0x18181808; /* | 0x07070700 if SBoot3 */ -+ s->padconf[0x11] = 0x18181818; /* | 0x07070707 if SBoot3 */ -+ s->padconf[0x12] = 0x18181818; /* | 0x07070707 if SBoot3 */ -+ s->padconf[0x13] = 0x18181818; /* | 0x07070707 if SBoot3 */ -+ s->padconf[0x14] = 0x18181818; /* | 0x00070707 if SBoot3 */ -+ s->padconf[0x15] = 0x18181818; -+ s->padconf[0x16] = 0x18181818; /* | 0x07000000 if SBoot3 */ -+ s->padconf[0x17] = 0x1f001f00; -+ s->padconf[0x18] = 0x1f1f1f1f; -+ s->padconf[0x19] = 0x00000000; -+ s->padconf[0x1a] = 0x1f180000; -+ s->padconf[0x1b] = 0x00001f1f; -+ s->padconf[0x1c] = 0x1f001f00; -+ s->padconf[0x1d] = 0x00000000; -+ s->padconf[0x1e] = 0x00000000; -+ s->padconf[0x1f] = 0x08000000; -+ s->padconf[0x20] = 0x08080808; -+ s->padconf[0x21] = 0x08080808; -+ s->padconf[0x22] = 0x0f080808; -+ s->padconf[0x23] = 0x0f0f0f0f; -+ s->padconf[0x24] = 0x000f0f0f; -+ s->padconf[0x25] = 0x1f1f1f0f; -+ s->padconf[0x26] = 0x080f0f1f; -+ s->padconf[0x27] = 0x070f1808; -+ s->padconf[0x28] = 0x0f070707; -+ s->padconf[0x29] = 0x000f0f1f; -+ s->padconf[0x2a] = 0x0f0f0f1f; -+ s->padconf[0x2b] = 0x08000000; -+ s->padconf[0x2c] = 0x0000001f; -+ s->padconf[0x2d] = 0x0f0f1f00; -+ s->padconf[0x2e] = 0x1f1f0f0f; -+ s->padconf[0x2f] = 0x0f1f1f1f; -+ s->padconf[0x30] = 0x0f0f0f0f; -+ s->padconf[0x31] = 0x0f1f0f1f; -+ s->padconf[0x32] = 0x0f0f0f0f; -+ s->padconf[0x33] = 0x0f1f0f1f; -+ s->padconf[0x34] = 0x1f1f0f0f; -+ s->padconf[0x35] = 0x0f0f1f1f; -+ s->padconf[0x36] = 0x0f0f1f0f; -+ s->padconf[0x37] = 0x0f0f0f0f; -+ s->padconf[0x38] = 0x1f18180f; -+ s->padconf[0x39] = 0x1f1f1f1f; -+ s->padconf[0x3a] = 0x00001f1f; -+ s->padconf[0x3b] = 0x00000000; -+ s->padconf[0x3c] = 0x00000000; -+ s->padconf[0x3d] = 0x0f0f0f0f; -+ s->padconf[0x3e] = 0x18000f0f; -+ s->padconf[0x3f] = 0x00070000; -+ s->padconf[0x40] = 0x00000707; -+ s->padconf[0x41] = 0x0f1f0700; -+ s->padconf[0x42] = 0x1f1f070f; -+ s->padconf[0x43] = 0x0008081f; -+ s->padconf[0x44] = 0x00000800; -+} -+ -+struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta, -+ omap_clk iclk, struct omap_mpu_state_s *mpu) -+{ -+ int iomemtype; -+ struct omap_sysctl_s *s = (struct omap_sysctl_s *) -+ qemu_mallocz(sizeof(struct omap_sysctl_s)); -+ -+ s->mpu = mpu; -+ omap_sysctl_reset(s); -+ -+ iomemtype = cpu_register_io_memory(0, omap_sysctl_readfn, -+ omap_sysctl_writefn, s); -+ s->base = omap_l4_attach(ta, 0, iomemtype); -+ omap_l4_attach(ta, 0, iomemtype); -+ -+ return s; -+} -+ -+/* SDRAM Controller Subsystem */ -+struct omap_sdrc_s { -+ target_phys_addr_t base; -+ -+ uint8_t config; -+}; -+ -+static void omap_sdrc_reset(struct omap_sdrc_s *s) -+{ -+ s->config = 0x10; -+} -+ -+static uint32_t omap_sdrc_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque; -+ int offset = addr - s->base; -+ -+ switch (offset) { -+ case 0x00: /* SDRC_REVISION */ -+ return 0x20; -+ -+ case 0x10: /* SDRC_SYSCONFIG */ -+ return s->config; -+ -+ case 0x14: /* SDRC_SYSSTATUS */ -+ return 1; /* RESETDONE */ -+ -+ case 0x40: /* SDRC_CS_CFG */ -+ case 0x44: /* SDRC_SHARING */ -+ case 0x48: /* SDRC_ERR_ADDR */ -+ case 0x4c: /* SDRC_ERR_TYPE */ -+ case 0x60: /* SDRC_DLLA_SCTRL */ -+ case 0x64: /* SDRC_DLLA_STATUS */ -+ 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; -+ } -+ -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap_sdrc_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque; -+ int offset = addr - s->base; -+ -+ switch (offset) { -+ case 0x00: /* SDRC_REVISION */ -+ case 0x14: /* SDRC_SYSSTATUS */ -+ case 0x48: /* SDRC_ERR_ADDR */ -+ case 0x64: /* SDRC_DLLA_STATUS */ -+ case 0x6c: /* SDRC_DLLB_STATUS */ -+ OMAP_RO_REG(addr); -+ return; -+ -+ case 0x10: /* SDRC_SYSCONFIG */ -+ if ((value >> 3) != 0x2) -+ fprintf(stderr, "%s: bad SDRAM idle mode %i\n", -+ __FUNCTION__, value >> 3); -+ if (value & 2) -+ omap_sdrc_reset(s); -+ s->config = value & 0x18; -+ break; -+ -+ case 0x40: /* SDRC_CS_CFG */ -+ case 0x44: /* SDRC_SHARING */ -+ case 0x4c: /* SDRC_ERR_TYPE */ -+ case 0x60: /* SDRC_DLLA_SCTRL */ -+ 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 */ -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ return; -+ } -+} -+ -+static CPUReadMemoryFunc *omap_sdrc_readfn[] = { -+ omap_badwidth_read32, -+ omap_badwidth_read32, -+ omap_sdrc_read, -+}; -+ -+static CPUWriteMemoryFunc *omap_sdrc_writefn[] = { -+ omap_badwidth_write32, -+ omap_badwidth_write32, -+ omap_sdrc_write, -+}; -+ -+struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base) -+{ -+ int iomemtype; -+ struct omap_sdrc_s *s = (struct omap_sdrc_s *) -+ qemu_mallocz(sizeof(struct omap_sdrc_s)); -+ -+ s->base = base; -+ omap_sdrc_reset(s); -+ -+ iomemtype = cpu_register_io_memory(0, omap_sdrc_readfn, -+ omap_sdrc_writefn, s); -+ cpu_register_physical_memory(s->base, 0x1000, iomemtype); -+ -+ return s; -+} -+ -+/* General-Purpose Memory Controller */ -+struct omap_gpmc_s { -+ target_phys_addr_t base; -+ qemu_irq irq; -+ -+ uint8_t sysconfig; -+ uint16_t irqst; -+ uint16_t irqen; -+ uint16_t timeout; -+ uint16_t config; -+ uint32_t prefconfig[2]; -+ int prefcontrol; -+ int preffifo; -+ int prefcount; -+ struct omap_gpmc_cs_file_s { -+ uint32_t config[7]; -+ target_phys_addr_t base; -+ size_t size; -+ int iomemtype; -+ void (*base_update)(void *opaque, target_phys_addr_t new); -+ void (*unmap)(void *opaque); -+ void *opaque; -+ } cs_file[8]; -+ int ecc_cs; -+ int ecc_ptr; -+ uint32_t ecc_cfg; -+ struct ecc_state_s ecc[9]; -+}; -+ -+static void omap_gpmc_int_update(struct omap_gpmc_s *s) -+{ -+ qemu_set_irq(s->irq, s->irqen & s->irqst); -+} -+ -+static void omap_gpmc_cs_map(struct omap_gpmc_cs_file_s *f, int base, int mask) -+{ -+ /* TODO: check for overlapping regions and report access errors */ -+ if ((mask != 0x8 && mask != 0xc && mask != 0xe && mask != 0xf) || -+ (base < 0 || base >= 0x40) || -+ (base & 0x0f & ~mask)) { -+ fprintf(stderr, "%s: wrong cs address mapping/decoding!\n", -+ __FUNCTION__); -+ return; -+ } -+ -+ if (!f->opaque) -+ return; -+ -+ f->base = base << 24; -+ f->size = (0x0fffffff & ~(mask << 24)) + 1; -+ /* TODO: rather than setting the size of the mapping (which should be -+ * constant), the mask should cause wrapping of the address space, so -+ * that the same memory becomes accessible at every size bytes -+ * starting from base. */ -+ if (f->iomemtype) -+ cpu_register_physical_memory(f->base, f->size, f->iomemtype); -+ -+ if (f->base_update) -+ f->base_update(f->opaque, f->base); -+} -+ -+static void omap_gpmc_cs_unmap(struct omap_gpmc_cs_file_s *f) -+{ -+ if (f->size) { -+ if (f->unmap) -+ f->unmap(f->opaque); -+ if (f->iomemtype) -+ cpu_register_physical_memory(f->base, f->size, IO_MEM_UNASSIGNED); -+ f->base = 0; -+ f->size = 0; -+ } -+} -+ -+static void omap_gpmc_reset(struct omap_gpmc_s *s) -+{ -+ int i; -+ -+ s->sysconfig = 0; -+ s->irqst = 0; -+ s->irqen = 0; -+ omap_gpmc_int_update(s); -+ s->timeout = 0; -+ s->config = 0xa00; -+ s->prefconfig[0] = 0x00004000; -+ s->prefconfig[1] = 0x00000000; -+ s->prefcontrol = 0; -+ s->preffifo = 0; -+ s->prefcount = 0; -+ for (i = 0; i < 8; i ++) { -+ if (s->cs_file[i].config[6] & (1 << 6)) /* CSVALID */ -+ omap_gpmc_cs_unmap(s->cs_file + i); -+ s->cs_file[i].config[0] = i ? 1 << 12 : 0; -+ s->cs_file[i].config[1] = 0x101001; -+ s->cs_file[i].config[2] = 0x020201; -+ s->cs_file[i].config[3] = 0x10031003; -+ s->cs_file[i].config[4] = 0x10f1111; -+ s->cs_file[i].config[5] = 0; -+ 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] >> 8 & 0xf)); /* BASEADDR */ -+ } -+ omap_gpmc_cs_map(s->cs_file, 0, 0xf); -+ s->ecc_cs = 0; -+ s->ecc_ptr = 0; -+ s->ecc_cfg = 0x3fcff000; -+ for (i = 0; i < 9; i ++) -+ ecc_reset(&s->ecc[i]); -+} -+ -+static uint32_t omap_gpmc_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque; -+ int offset = addr - s->base; -+ int cs; -+ struct omap_gpmc_cs_file_s *f; -+ -+ switch (offset) { -+ case 0x000: /* GPMC_REVISION */ -+ return 0x20; -+ -+ case 0x010: /* GPMC_SYSCONFIG */ -+ return s->sysconfig; -+ -+ case 0x014: /* GPMC_SYSSTATUS */ -+ return 1; /* RESETDONE */ -+ -+ case 0x018: /* GPMC_IRQSTATUS */ -+ return s->irqst; -+ -+ case 0x01c: /* GPMC_IRQENABLE */ -+ return s->irqen; -+ -+ case 0x040: /* GPMC_TIMEOUT_CONTROL */ -+ return s->timeout; -+ -+ case 0x044: /* GPMC_ERR_ADDRESS */ -+ case 0x048: /* GPMC_ERR_TYPE */ -+ return 0; -+ -+ case 0x050: /* GPMC_CONFIG */ -+ return s->config; -+ -+ case 0x054: /* GPMC_STATUS */ -+ return 0x001; -+ -+ case 0x060 ... 0x1d4: -+ cs = (offset - 0x060) / 0x30; -+ offset -= cs * 0x30; -+ f = s->cs_file + cs; -+ switch (offset - cs * 0x30) { -+ case 0x60: /* GPMC_CONFIG1 */ -+ return f->config[0]; -+ case 0x64: /* GPMC_CONFIG2 */ -+ return f->config[1]; -+ case 0x68: /* GPMC_CONFIG3 */ -+ return f->config[2]; -+ case 0x6c: /* GPMC_CONFIG4 */ -+ return f->config[3]; -+ case 0x70: /* GPMC_CONFIG5 */ -+ return f->config[4]; -+ case 0x74: /* GPMC_CONFIG6 */ -+ return f->config[5]; -+ case 0x78: /* GPMC_CONFIG7 */ -+ return f->config[6]; -+ case 0x84: /* GPMC_NAND_DATA */ -+ return 0; -+ } -+ break; -+ -+ case 0x1e0: /* GPMC_PREFETCH_CONFIG1 */ -+ return s->prefconfig[0]; -+ case 0x1e4: /* GPMC_PREFETCH_CONFIG2 */ -+ return s->prefconfig[1]; -+ case 0x1ec: /* GPMC_PREFETCH_CONTROL */ -+ return s->prefcontrol; -+ case 0x1f0: /* GPMC_PREFETCH_STATUS */ -+ return (s->preffifo << 24) | -+ ((s->preffifo > -+ ((s->prefconfig[0] >> 8) & 0x7f) ? 1 : 0) << 16) | -+ s->prefcount; -+ -+ case 0x1f4: /* GPMC_ECC_CONFIG */ -+ return s->ecc_cs; -+ case 0x1f8: /* GPMC_ECC_CONTROL */ -+ return s->ecc_ptr; -+ case 0x1fc: /* GPMC_ECC_SIZE_CONFIG */ -+ return s->ecc_cfg; -+ case 0x200 ... 0x220: /* GPMC_ECC_RESULT */ -+ cs = (offset & 0x1f) >> 2; -+ /* TODO: check correctness */ -+ return -+ ((s->ecc[cs].cp & 0x07) << 0) | -+ ((s->ecc[cs].cp & 0x38) << 13) | -+ ((s->ecc[cs].lp[0] & 0x1ff) << 3) | -+ ((s->ecc[cs].lp[1] & 0x1ff) << 19); -+ -+ case 0x230: /* GPMC_TESTMODE_CTRL */ -+ return 0; -+ case 0x234: /* GPMC_PSA_LSB */ -+ case 0x238: /* GPMC_PSA_MSB */ -+ return 0x00000000; -+ } -+ -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap_gpmc_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque; -+ int offset = addr - s->base; -+ int cs; -+ struct omap_gpmc_cs_file_s *f; -+ -+ switch (offset) { -+ case 0x000: /* GPMC_REVISION */ -+ case 0x014: /* GPMC_SYSSTATUS */ -+ case 0x054: /* GPMC_STATUS */ -+ case 0x1f0: /* GPMC_PREFETCH_STATUS */ -+ case 0x200 ... 0x220: /* GPMC_ECC_RESULT */ -+ case 0x234: /* GPMC_PSA_LSB */ -+ case 0x238: /* GPMC_PSA_MSB */ -+ OMAP_RO_REG(addr); -+ break; -+ -+ case 0x010: /* GPMC_SYSCONFIG */ -+ if ((value >> 3) == 0x3) -+ fprintf(stderr, "%s: bad SDRAM idle mode %i\n", -+ __FUNCTION__, value >> 3); -+ if (value & 2) -+ omap_gpmc_reset(s); -+ s->sysconfig = value & 0x19; -+ break; -+ -+ case 0x018: /* GPMC_IRQSTATUS */ -+ s->irqen = ~value; -+ omap_gpmc_int_update(s); -+ break; -+ -+ case 0x01c: /* GPMC_IRQENABLE */ -+ s->irqen = value & 0xf03; -+ omap_gpmc_int_update(s); -+ break; -+ -+ case 0x040: /* GPMC_TIMEOUT_CONTROL */ -+ s->timeout = value & 0x1ff1; -+ break; -+ -+ case 0x044: /* GPMC_ERR_ADDRESS */ -+ case 0x048: /* GPMC_ERR_TYPE */ -+ break; -+ -+ case 0x050: /* GPMC_CONFIG */ -+ s->config = value & 0xf13; -+ break; -+ -+ case 0x060 ... 0x1d4: -+ cs = (offset - 0x060) / 0x30; -+ offset -= cs * 0x30; -+ f = s->cs_file + cs; -+ switch (offset - cs * 0x30) { -+ case 0x60: /* GPMC_CONFIG1 */ -+ f->config[0] = value & 0xffef3e13; -+ break; -+ case 0x64: /* GPMC_CONFIG2 */ -+ f->config[1] = value & 0x001f1f8f; -+ break; -+ case 0x68: /* GPMC_CONFIG3 */ -+ f->config[2] = value & 0x001f1f8f; -+ break; -+ case 0x6c: /* GPMC_CONFIG4 */ -+ f->config[3] = value & 0x1f8f1f8f; -+ break; -+ case 0x70: /* GPMC_CONFIG5 */ -+ f->config[4] = value & 0x0f1f1f1f; -+ break; -+ case 0x74: /* GPMC_CONFIG6 */ -+ f->config[5] = value & 0x00000fcf; -+ break; -+ case 0x78: /* GPMC_CONFIG7 */ -+ if ((f->config[6] ^ value) & 0xf7f) { -+ 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 */ -+ (value >> 8 & 0xf)); /* BASEADDR */ -+ } -+ f->config[6] = value & 0x00000f7f; -+ break; -+ case 0x7c: /* GPMC_NAND_COMMAND */ -+ case 0x80: /* GPMC_NAND_ADDRESS */ -+ case 0x84: /* GPMC_NAND_DATA */ -+ break; -+ -+ default: -+ goto bad_reg; -+ } -+ break; -+ -+ case 0x1e0: /* GPMC_PREFETCH_CONFIG1 */ -+ s->prefconfig[0] = value & 0x7f8f7fbf; -+ /* TODO: update interrupts, fifos, dmas */ -+ break; -+ -+ case 0x1e4: /* GPMC_PREFETCH_CONFIG2 */ -+ s->prefconfig[1] = value & 0x3fff; -+ break; -+ -+ case 0x1ec: /* GPMC_PREFETCH_CONTROL */ -+ s->prefcontrol = value & 1; -+ if (s->prefcontrol) { -+ if (s->prefconfig[0] & 1) -+ s->preffifo = 0x40; -+ else -+ s->preffifo = 0x00; -+ } -+ /* TODO: start */ -+ break; -+ -+ case 0x1f4: /* GPMC_ECC_CONFIG */ -+ s->ecc_cs = 0x8f; -+ break; -+ case 0x1f8: /* GPMC_ECC_CONTROL */ -+ if (value & (1 << 8)) -+ for (cs = 0; cs < 9; cs ++) -+ ecc_reset(&s->ecc[cs]); -+ s->ecc_ptr = value & 0xf; -+ if (s->ecc_ptr == 0 || s->ecc_ptr > 9) { -+ s->ecc_ptr = 0; -+ s->ecc_cs &= ~1; -+ } -+ break; -+ case 0x1fc: /* GPMC_ECC_SIZE_CONFIG */ -+ s->ecc_cfg = value & 0x3fcff1ff; -+ break; -+ case 0x230: /* GPMC_TESTMODE_CTRL */ -+ if (value & 7) -+ fprintf(stderr, "%s: test mode enable attempt\n", __FUNCTION__); -+ break; -+ -+ default: -+ bad_reg: -+ OMAP_BAD_REG(addr); -+ return; -+ } -+} -+ -+static CPUReadMemoryFunc *omap_gpmc_readfn[] = { -+ omap_badwidth_read32, /* TODO */ -+ omap_badwidth_read32, /* TODO */ -+ omap_gpmc_read, -+}; -+ -+static CPUWriteMemoryFunc *omap_gpmc_writefn[] = { -+ omap_badwidth_write32, /* TODO */ -+ omap_badwidth_write32, /* TODO */ -+ omap_gpmc_write, -+}; -+ -+struct omap_gpmc_s *omap_gpmc_init(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->base = base; -+ omap_gpmc_reset(s); -+ -+ iomemtype = cpu_register_io_memory(0, omap_gpmc_readfn, -+ omap_gpmc_writefn, s); -+ cpu_register_physical_memory(s->base, 0x1000, iomemtype); -+ -+ return s; -+} -+ -+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) -+{ -+ struct omap_gpmc_cs_file_s *f; -+ -+ if (cs < 0 || cs >= 8) { -+ fprintf(stderr, "%s: bad chip-select %i\n", __FUNCTION__, cs); -+ exit(-1); -+ } -+ f = &s->cs_file[cs]; -+ -+ f->iomemtype = iomemtype; -+ f->base_update = base_upd; -+ f->unmap = unmap; -+ f->opaque = opaque; -+ -+ if (f->config[6] & (1 << 6)) /* CSVALID */ -+ omap_gpmc_cs_map(f, f->config[6] & 0x1f, /* MASKADDR */ -+ (f->config[6] >> 8 & 0xf)); /* BASEADDR */ -+} -+ -+/* General chip reset */ -+static void omap2_mpu_reset(void *opaque) -+{ -+ struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque; -+ -+ omap_inth_reset(mpu->ih[0]); -+ omap_dma_reset(mpu->dma); -+ omap_prcm_reset(mpu->prcm); -+ omap_sysctl_reset(mpu->sysc); -+ omap_gp_timer_reset(mpu->gptimer[0]); -+ omap_gp_timer_reset(mpu->gptimer[1]); -+ omap_gp_timer_reset(mpu->gptimer[2]); -+ omap_gp_timer_reset(mpu->gptimer[3]); -+ omap_gp_timer_reset(mpu->gptimer[4]); -+ omap_gp_timer_reset(mpu->gptimer[5]); -+ omap_gp_timer_reset(mpu->gptimer[6]); -+ omap_gp_timer_reset(mpu->gptimer[7]); -+ omap_gp_timer_reset(mpu->gptimer[8]); -+ omap_gp_timer_reset(mpu->gptimer[9]); -+ omap_gp_timer_reset(mpu->gptimer[10]); -+ omap_gp_timer_reset(mpu->gptimer[11]); -+ omap_synctimer_reset(&mpu->synctimer); -+ omap_sdrc_reset(mpu->sdrc); -+ omap_gpmc_reset(mpu->gpmc); -+ omap_dss_reset(mpu->dss); -+#if 0 -+ omap_wd_timer_reset(mpu->wdt); -+ omap_ulpd_pm_reset(mpu); -+ omap_pin_cfg_reset(mpu); -+ omap_mpui_reset(mpu); -+ omap_tipb_bridge_reset(mpu->private_tipb); -+ omap_tipb_bridge_reset(mpu->public_tipb); -+ omap_dpll_reset(&mpu->dpll[0]); -+ omap_dpll_reset(&mpu->dpll[1]); -+ omap_dpll_reset(&mpu->dpll[2]); -+#endif -+ omap_uart_reset(mpu->uart[0]); -+ omap_uart_reset(mpu->uart[1]); -+ omap_uart_reset(mpu->uart[2]); -+ omap_mmc_reset(mpu->mmc); -+ omap_gpif_reset(mpu->gpif); -+ omap_mcspi_reset(mpu->mcspi[0]); -+ omap_mcspi_reset(mpu->mcspi[1]); -+#if 0 -+ omap_pwl_reset(mpu); -+ omap_pwt_reset(mpu); -+#endif -+ omap_i2c_reset(mpu->i2c[0]); -+ omap_i2c_reset(mpu->i2c[1]); -+#if 0 -+ omap_rtc_reset(mpu->rtc); -+ omap_mcbsp_reset(mpu->mcbsp1); -+ omap_mcbsp_reset(mpu->mcbsp2); -+ omap_mcbsp_reset(mpu->mcbsp3); -+ omap_lpg_reset(mpu->led[0]); -+ omap_lpg_reset(mpu->led[1]); -+ omap_clkm_reset(mpu); -+#endif -+ cpu_reset(mpu->env); -+} -+ -+static int omap2_validate_addr(struct omap_mpu_state_s *s, -+ target_phys_addr_t addr) -+{ -+ return 1; -+} -+ -+static const struct dma_irq_map omap2_dma_irq_map[] = { -+ { 0, OMAP_INT_24XX_SDMA_IRQ0 }, -+ { 0, OMAP_INT_24XX_SDMA_IRQ1 }, -+ { 0, OMAP_INT_24XX_SDMA_IRQ2 }, -+ { 0, OMAP_INT_24XX_SDMA_IRQ3 }, -+}; -+ -+struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size, -+ DisplayState *ds, 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, q3_base; -+ qemu_irq *cpu_irq; -+ qemu_irq dma_irqs[4]; -+ omap_clk gpio_clks[4]; -+ int sdindex; -+ int i; -+ -+ /* Core */ -+ s->mpu_model = omap2420; -+ s->env = cpu_init(core ?: "arm1136-r2"); -+ if (!s->env) { -+ fprintf(stderr, "Unable to find CPU definition\n"); -+ exit(1); -+ } -+ s->sdram_size = sdram_size; -+ s->sram_size = OMAP242X_SRAM_SIZE; -+ -+ s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0]; -+ -+ /* Clocks */ -+ omap_clk_init(s); -+ -+ /* Memory-mapped stuff */ -+ cpu_register_physical_memory(OMAP2_Q2_BASE, s->sdram_size, -+ (q3_base = qemu_ram_alloc(s->sdram_size)) | IO_MEM_RAM); -+ cpu_register_physical_memory(OMAP2_SRAM_BASE, s->sram_size, -+ (sram_base = qemu_ram_alloc(s->sram_size)) | IO_MEM_RAM); -+ -+ s->l4 = omap_l4_init(OMAP2_L4_BASE, 54); -+ -+ /* 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], -+ cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ], -+ omap_findclk(s, "mpu_intc_fclk"), -+ omap_findclk(s, "mpu_intc_iclk")); -+ -+ s->prcm = omap_prcm_init(omap_l4tao(s->l4, 3), -+ s->irq[0][OMAP_INT_24XX_PRCM_MPU_IRQ], NULL, NULL, s); -+ -+ s->sysc = omap_sysctl_init(omap_l4tao(s->l4, 1), -+ omap_findclk(s, "omapctrl_iclk"), s); -+ -+ for (i = 0; i < 4; i ++) -+ dma_irqs[i] = -+ s->irq[omap2_dma_irq_map[i].ih][omap2_dma_irq_map[i].intr]; -+ s->dma = omap_dma4_init(0x48056000, dma_irqs, s, 256, 32, -+ omap_findclk(s, "sdma_iclk"), -+ omap_findclk(s, "sdma_fclk")); -+ s->port->addr_valid = omap2_validate_addr; -+ -+ s->uart[0] = omap2_uart_init(omap_l4ta(s->l4, 19), -+ s->irq[0][OMAP_INT_24XX_UART1_IRQ], -+ omap_findclk(s, "uart1_fclk"), -+ omap_findclk(s, "uart1_iclk"), -+ s->drq[OMAP24XX_DMA_UART1_TX], -+ s->drq[OMAP24XX_DMA_UART1_RX], serial_hds[0]); -+ s->uart[1] = omap2_uart_init(omap_l4ta(s->l4, 20), -+ s->irq[0][OMAP_INT_24XX_UART2_IRQ], -+ omap_findclk(s, "uart2_fclk"), -+ omap_findclk(s, "uart2_iclk"), -+ s->drq[OMAP24XX_DMA_UART2_TX], -+ s->drq[OMAP24XX_DMA_UART2_RX], -+ serial_hds[0] ? serial_hds[1] : 0); -+ s->uart[2] = omap2_uart_init(omap_l4ta(s->l4, 21), -+ s->irq[0][OMAP_INT_24XX_UART3_IRQ], -+ omap_findclk(s, "uart3_fclk"), -+ omap_findclk(s, "uart3_iclk"), -+ s->drq[OMAP24XX_DMA_UART3_TX], -+ s->drq[OMAP24XX_DMA_UART3_RX], -+ serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0); -+ -+ s->gptimer[0] = omap_gp_timer_init(omap_l4ta(s->l4, 7), -+ s->irq[0][OMAP_INT_24XX_GPTIMER1], -+ omap_findclk(s, "wu_gpt1_clk"), -+ omap_findclk(s, "wu_l4_iclk")); -+ s->gptimer[1] = omap_gp_timer_init(omap_l4ta(s->l4, 8), -+ s->irq[0][OMAP_INT_24XX_GPTIMER2], -+ omap_findclk(s, "core_gpt2_clk"), -+ omap_findclk(s, "core_l4_iclk")); -+ s->gptimer[2] = omap_gp_timer_init(omap_l4ta(s->l4, 22), -+ s->irq[0][OMAP_INT_24XX_GPTIMER3], -+ omap_findclk(s, "core_gpt3_clk"), -+ omap_findclk(s, "core_l4_iclk")); -+ s->gptimer[3] = omap_gp_timer_init(omap_l4ta(s->l4, 23), -+ s->irq[0][OMAP_INT_24XX_GPTIMER4], -+ omap_findclk(s, "core_gpt4_clk"), -+ omap_findclk(s, "core_l4_iclk")); -+ s->gptimer[4] = omap_gp_timer_init(omap_l4ta(s->l4, 24), -+ s->irq[0][OMAP_INT_24XX_GPTIMER5], -+ omap_findclk(s, "core_gpt5_clk"), -+ omap_findclk(s, "core_l4_iclk")); -+ s->gptimer[5] = omap_gp_timer_init(omap_l4ta(s->l4, 25), -+ s->irq[0][OMAP_INT_24XX_GPTIMER6], -+ omap_findclk(s, "core_gpt6_clk"), -+ omap_findclk(s, "core_l4_iclk")); -+ s->gptimer[6] = omap_gp_timer_init(omap_l4ta(s->l4, 26), -+ s->irq[0][OMAP_INT_24XX_GPTIMER7], -+ omap_findclk(s, "core_gpt7_clk"), -+ omap_findclk(s, "core_l4_iclk")); -+ s->gptimer[7] = omap_gp_timer_init(omap_l4ta(s->l4, 27), -+ s->irq[0][OMAP_INT_24XX_GPTIMER8], -+ omap_findclk(s, "core_gpt8_clk"), -+ omap_findclk(s, "core_l4_iclk")); -+ s->gptimer[8] = omap_gp_timer_init(omap_l4ta(s->l4, 28), -+ s->irq[0][OMAP_INT_24XX_GPTIMER9], -+ omap_findclk(s, "core_gpt9_clk"), -+ omap_findclk(s, "core_l4_iclk")); -+ s->gptimer[9] = omap_gp_timer_init(omap_l4ta(s->l4, 29), -+ s->irq[0][OMAP_INT_24XX_GPTIMER10], -+ omap_findclk(s, "core_gpt10_clk"), -+ omap_findclk(s, "core_l4_iclk")); -+ s->gptimer[10] = omap_gp_timer_init(omap_l4ta(s->l4, 30), -+ s->irq[0][OMAP_INT_24XX_GPTIMER11], -+ omap_findclk(s, "core_gpt11_clk"), -+ omap_findclk(s, "core_l4_iclk")); -+ s->gptimer[11] = omap_gp_timer_init(omap_l4ta(s->l4, 31), -+ s->irq[0][OMAP_INT_24XX_GPTIMER12], -+ omap_findclk(s, "core_gpt12_clk"), -+ omap_findclk(s, "core_l4_iclk")); -+ -+ omap_tap_init(omap_l4ta(s->l4, 2), s); -+ -+ omap_synctimer_init(omap_l4tao(s->l4, 2), s, -+ omap_findclk(s, "clk32-kHz"), -+ omap_findclk(s, "core_l4_iclk")); -+ -+ s->i2c[0] = omap2_i2c_init(omap_l4tao(s->l4, 5), -+ s->irq[0][OMAP_INT_24XX_I2C1_IRQ], -+ &s->drq[OMAP24XX_DMA_I2C1_TX], -+ omap_findclk(s, "i2c1.fclk"), -+ omap_findclk(s, "i2c1.iclk")); -+ s->i2c[1] = omap2_i2c_init(omap_l4tao(s->l4, 6), -+ s->irq[0][OMAP_INT_24XX_I2C2_IRQ], -+ &s->drq[OMAP24XX_DMA_I2C2_TX], -+ omap_findclk(s, "i2c2.fclk"), -+ omap_findclk(s, "i2c2.iclk")); -+ -+ gpio_clks[0] = omap_findclk(s, "gpio1_dbclk"); -+ 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->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]); -+ -+ sdindex = drive_get_index(IF_SD, 0, 0); -+ if (sdindex == -1) { -+ fprintf(stderr, "qemu: missing SecureDigital device\n"); -+ exit(1); -+ } -+ s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), drives_table[sdindex].bdrv, -+ s->irq[0][OMAP_INT_24XX_MMC_IRQ], -+ &s->drq[OMAP24XX_DMA_MMC1_TX], -+ omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk")); -+ -+ s->mcspi[0] = omap_mcspi_init(omap_l4ta(s->l4, 35), 4, -+ s->irq[0][OMAP_INT_24XX_MCSPI1_IRQ], -+ &s->drq[OMAP24XX_DMA_SPI1_TX0], -+ omap_findclk(s, "spi1_fclk"), -+ omap_findclk(s, "spi1_iclk")); -+ s->mcspi[1] = omap_mcspi_init(omap_l4ta(s->l4, 36), 2, -+ s->irq[0][OMAP_INT_24XX_MCSPI2_IRQ], -+ &s->drq[OMAP24XX_DMA_SPI2_TX0], -+ omap_findclk(s, "spi2_fclk"), -+ omap_findclk(s, "spi2_iclk")); -+ -+ s->dss = omap_dss_init(omap_l4ta(s->l4, 10), 0x68000800, ds, -+ /* XXX wire M_IRQ_25, D_L2_IRQ_30 and I_IRQ_13 together */ -+ s->irq[0][OMAP_INT_24XX_DSS_IRQ], s->drq[OMAP24XX_DMA_DSS], -+ 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")); -+ -+ /* Register mappings not currenlty implemented: -+ * SystemControlMod 48000000 - 48000fff -+ * SystemControlL4 48001000 - 48001fff -+ * 32kHz Timer Mod 48004000 - 48004fff -+ * 32kHz Timer L4 48005000 - 48005fff -+ * PRCM ModA 48008000 - 480087ff -+ * PRCM ModB 48008800 - 48008fff -+ * PRCM L4 48009000 - 48009fff -+ * TEST-BCM Mod 48012000 - 48012fff -+ * TEST-BCM L4 48013000 - 48013fff -+ * TEST-TAP Mod 48014000 - 48014fff -+ * TEST-TAP L4 48015000 - 48015fff -+ * GPIO1 Mod 48018000 - 48018fff -+ * GPIO Top 48019000 - 48019fff -+ * GPIO2 Mod 4801a000 - 4801afff -+ * GPIO L4 4801b000 - 4801bfff -+ * GPIO3 Mod 4801c000 - 4801cfff -+ * GPIO4 Mod 4801e000 - 4801efff -+ * WDTIMER1 Mod 48020000 - 48010fff -+ * WDTIMER Top 48021000 - 48011fff -+ * WDTIMER2 Mod 48022000 - 48012fff -+ * WDTIMER L4 48023000 - 48013fff -+ * WDTIMER3 Mod 48024000 - 48014fff -+ * WDTIMER3 L4 48025000 - 48015fff -+ * WDTIMER4 Mod 48026000 - 48016fff -+ * WDTIMER4 L4 48027000 - 48017fff -+ * GPTIMER1 Mod 48028000 - 48018fff -+ * GPTIMER1 L4 48029000 - 48019fff -+ * GPTIMER2 Mod 4802a000 - 4801afff -+ * GPTIMER2 L4 4802b000 - 4801bfff -+ * L4-Config AP 48040000 - 480407ff -+ * L4-Config IP 48040800 - 48040fff -+ * L4-Config LA 48041000 - 48041fff -+ * ARM11ETB Mod 48048000 - 48049fff -+ * ARM11ETB L4 4804a000 - 4804afff -+ * DISPLAY Top 48050000 - 480503ff -+ * DISPLAY DISPC 48050400 - 480507ff -+ * DISPLAY RFBI 48050800 - 48050bff -+ * DISPLAY VENC 48050c00 - 48050fff -+ * DISPLAY L4 48051000 - 48051fff -+ * CAMERA Top 48052000 - 480523ff -+ * CAMERA core 48052400 - 480527ff -+ * CAMERA DMA 48052800 - 48052bff -+ * CAMERA MMU 48052c00 - 48052fff -+ * CAMERA L4 48053000 - 48053fff -+ * SDMA Mod 48056000 - 48056fff -+ * SDMA L4 48057000 - 48057fff -+ * SSI Top 48058000 - 48058fff -+ * SSI GDD 48059000 - 48059fff -+ * SSI Port1 4805a000 - 4805afff -+ * SSI Port2 4805b000 - 4805bfff -+ * SSI L4 4805c000 - 4805cfff -+ * USB Mod 4805e000 - 480fefff -+ * USB L4 4805f000 - 480fffff -+ * WIN_TRACER1 Mod 48060000 - 48060fff -+ * WIN_TRACER1 L4 48061000 - 48061fff -+ * WIN_TRACER2 Mod 48062000 - 48062fff -+ * WIN_TRACER2 L4 48063000 - 48063fff -+ * WIN_TRACER3 Mod 48064000 - 48064fff -+ * WIN_TRACER3 L4 48065000 - 48065fff -+ * WIN_TRACER4 Top 48066000 - 480660ff -+ * WIN_TRACER4 ETT 48066100 - 480661ff -+ * WIN_TRACER4 WT 48066200 - 480662ff -+ * WIN_TRACER4 L4 48067000 - 48067fff -+ * XTI Mod 48068000 - 48068fff -+ * XTI L4 48069000 - 48069fff -+ * UART1 Mod 4806a000 - 4806afff -+ * UART1 L4 4806b000 - 4806bfff -+ * UART2 Mod 4806c000 - 4806cfff -+ * UART2 L4 4806d000 - 4806dfff -+ * UART3 Mod 4806e000 - 4806efff -+ * UART3 L4 4806f000 - 4806ffff -+ * I2C1 Mod 48070000 - 48070fff -+ * I2C1 L4 48071000 - 48071fff -+ * I2C2 Mod 48072000 - 48072fff -+ * I2C2 L4 48073000 - 48073fff -+ * McBSP1 Mod 48074000 - 48074fff -+ * McBSP1 L4 48075000 - 48075fff -+ * McBSP2 Mod 48076000 - 48076fff -+ * McBSP2 L4 48077000 - 48077fff -+ * GPTIMER3 Mod 48078000 - 48078fff -+ * GPTIMER3 L4 48079000 - 48079fff -+ * GPTIMER4 Mod 4807a000 - 4807afff -+ * GPTIMER4 L4 4807b000 - 4807bfff -+ * GPTIMER5 Mod 4807c000 - 4807cfff -+ * GPTIMER5 L4 4807d000 - 4807dfff -+ * GPTIMER6 Mod 4807e000 - 4807efff -+ * GPTIMER6 L4 4807f000 - 4807ffff -+ * GPTIMER7 Mod 48080000 - 48080fff -+ * GPTIMER7 L4 48081000 - 48081fff -+ * GPTIMER8 Mod 48082000 - 48082fff -+ * GPTIMER8 L4 48083000 - 48083fff -+ * GPTIMER9 Mod 48084000 - 48084fff -+ * GPTIMER9 L4 48085000 - 48085fff -+ * GPTIMER10 Mod 48086000 - 48086fff -+ * GPTIMER10 L4 48087000 - 48087fff -+ * GPTIMER11 Mod 48088000 - 48088fff -+ * GPTIMER11 L4 48089000 - 48089fff -+ * GPTIMER12 Mod 4808a000 - 4808afff -+ * GPTIMER12 L4 4808b000 - 4808bfff -+ * EAC Mod 48090000 - 48090fff -+ * EAC L4 48091000 - 48091fff -+ * FAC Mod 48092000 - 48092fff -+ * FAC L4 48093000 - 48093fff -+ * MAILBOX Mod 48094000 - 48094fff -+ * MAILBOX L4 48095000 - 48095fff -+ * SPI1 Mod 48098000 - 48098fff -+ * SPI1 L4 48099000 - 48099fff -+ * SPI2 Mod 4809a000 - 4809afff -+ * SPI2 L4 4809b000 - 4809bfff -+ * MMC/SDIO Mod 4809c000 - 4809cfff -+ * MMC/SDIO L4 4809d000 - 4809dfff -+ * MS_PRO Mod 4809e000 - 4809efff -+ * MS_PRO L4 4809f000 - 4809ffff -+ * RNG Mod 480a0000 - 480a0fff -+ * RNG L4 480a1000 - 480a1fff -+ * DES3DES Mod 480a2000 - 480a2fff -+ * DES3DES L4 480a3000 - 480a3fff -+ * SHA1MD5 Mod 480a4000 - 480a4fff -+ * SHA1MD5 L4 480a5000 - 480a5fff -+ * AES Mod 480a6000 - 480a6fff -+ * AES L4 480a7000 - 480a7fff -+ * PKA Mod 480a8000 - 480a9fff -+ * PKA L4 480aa000 - 480aafff -+ * MG Mod 480b0000 - 480b0fff -+ * MG L4 480b1000 - 480b1fff -+ * HDQ/1-wire Mod 480b2000 - 480b2fff -+ * HDQ/1-wire L4 480b3000 - 480b3fff -+ * MPU interrupt 480fe000 - 480fefff -+ * IVA RAM 5c000000 - 5c01ffff -+ * IVA ROM 5c020000 - 5c027fff -+ * IMG_BUF_A 5c040000 - 5c040fff -+ * IMG_BUF_B 5c042000 - 5c042fff -+ * VLCDS 5c048000 - 5c0487ff -+ * IMX_COEF 5c049000 - 5c04afff -+ * IMX_CMD 5c051000 - 5c051fff -+ * VLCDQ 5c053000 - 5c0533ff -+ * VLCDH 5c054000 - 5c054fff -+ * SEQ_CMD 5c055000 - 5c055fff -+ * IMX_REG 5c056000 - 5c0560ff -+ * VLCD_REG 5c056100 - 5c0561ff -+ * SEQ_REG 5c056200 - 5c0562ff -+ * IMG_BUF_REG 5c056300 - 5c0563ff -+ * SEQIRQ_REG 5c056400 - 5c0564ff -+ * OCP_REG 5c060000 - 5c060fff -+ * SYSC_REG 5c070000 - 5c070fff -+ * MMU_REG 5d000000 - 5d000fff -+ * sDMA R 68000400 - 680005ff -+ * sDMA W 68000600 - 680007ff -+ * Display Control 68000800 - 680009ff -+ * DSP subsystem 68000a00 - 68000bff -+ * MPU subsystem 68000c00 - 68000dff -+ * IVA subsystem 68001000 - 680011ff -+ * USB 68001200 - 680013ff -+ * Camera 68001400 - 680015ff -+ * VLYNQ (firewall) 68001800 - 68001bff -+ * VLYNQ 68001e00 - 68001fff -+ * SSI 68002000 - 680021ff -+ * L4 68002400 - 680025ff -+ * DSP (firewall) 68002800 - 68002bff -+ * DSP subsystem 68002e00 - 68002fff -+ * IVA (firewall) 68003000 - 680033ff -+ * IVA 68003600 - 680037ff -+ * GFX 68003a00 - 68003bff -+ * CMDWR emulation 68003c00 - 68003dff -+ * SMS 68004000 - 680041ff -+ * OCM 68004200 - 680043ff -+ * GPMC 68004400 - 680045ff -+ * RAM (firewall) 68005000 - 680053ff -+ * RAM (err login) 68005400 - 680057ff -+ * ROM (firewall) 68005800 - 68005bff -+ * ROM (err login) 68005c00 - 68005fff -+ * GPMC (firewall) 68006000 - 680063ff -+ * GPMC (err login) 68006400 - 680067ff -+ * SMS (err login) 68006c00 - 68006fff -+ * SMS registers 68008000 - 68008fff -+ * SDRC registers 68009000 - 68009fff -+ * GPMC registers 6800a000 6800afff -+ */ -+ -+ qemu_register_reset(omap2_mpu_reset, s); -+ -+ return s; -+} -diff --git a/hw/omap_clk.c b/hw/omap_clk.c -index 37daec2..da03e15 100644 ---- a/hw/omap_clk.c -+++ b/hw/omap_clk.c -@@ -34,6 +34,9 @@ struct clk { - #define CLOCK_IN_OMAP730 (1 << 11) - #define CLOCK_IN_OMAP1510 (1 << 12) - #define CLOCK_IN_OMAP16XX (1 << 13) -+#define CLOCK_IN_OMAP242X (1 << 14) -+#define CLOCK_IN_OMAP243X (1 << 15) -+#define CLOCK_IN_OMAP343X (1 << 16) - uint32_t flags; - int id; - -@@ -55,7 +58,8 @@ static struct clk xtal_osc12m = { - static struct clk xtal_osc32k = { - .name = "xtal_osc_32k", - .rate = 32768, -- .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, -+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | -+ CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - }; - - static struct clk ck_ref = { -@@ -502,11 +506,441 @@ static struct clk i2c_ick = { - static struct clk clk32k = { - .name = "clk32-kHz", - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | -- ALWAYS_ENABLED, -- .parent = &xtal_osc32k, -+ CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, -+ .parent = &xtal_osc32k, -+}; -+ -+static struct clk apll_96m = { -+ .name = "apll_96m", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, -+ .rate = 96000000, -+ /*.parent = sys.xtalin */ -+}; -+ -+static struct clk apll_54m = { -+ .name = "apll_54m", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, -+ .rate = 54000000, -+ /*.parent = sys.xtalin */ -+}; -+ -+static struct clk sys_clk = { -+ .name = "sys_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, -+ .rate = 32768, -+ /*.parent = sys.xtalin */ -+}; -+ -+static struct clk sleep_clk = { -+ .name = "sleep_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, -+ .rate = 32768, -+ /*.parent = sys.xtalin */ -+}; -+ -+static struct clk dpll_ck = { -+ .name = "dpll", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, -+ /*.parent = sys.xtalin */ -+}; -+ -+static struct clk dpll_x2_ck = { -+ .name = "dpll_x2", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, -+ /*.parent = sys.xtalin */ -+}; -+ -+static struct clk wdt1_sys_clk = { -+ .name = "wdt1_sys_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED, -+ .rate = 32768, -+ /*.parent = sys.xtalin */ -+}; -+ -+static struct clk func_96m_clk = { -+ .name = "func_96m_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .divisor = 1, -+ .parent = &apll_96m, -+}; -+ -+static struct clk func_48m_clk = { -+ .name = "func_48m_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .divisor = 2, -+ .parent = &apll_96m, -+}; -+ -+static struct clk func_12m_clk = { -+ .name = "func_12m_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .divisor = 8, -+ .parent = &apll_96m, -+}; -+ -+static struct clk func_54m_clk = { -+ .name = "func_54m_clk", -+ .flags = CLOCK_IN_OMAP242X, -+ .divisor = 1, -+ .parent = &apll_54m, -+}; -+ -+static struct clk sys_clkout = { -+ .name = "clkout", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+}; -+ -+static struct clk sys_clkout2 = { -+ .name = "clkout2", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+}; -+ -+static struct clk core_clk = { -+ .name = "core_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &dpll_ck, -+}; -+ -+static struct clk l3_clk = { -+ .name = "l3_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_clk, -+}; -+ -+static struct clk core_l4_iclk = { -+ .name = "core_l4_iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &l3_clk, -+}; -+ -+static struct clk wu_l4_iclk = { -+ .name = "wu_l4_iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &l3_clk, -+}; -+ -+static struct clk core_l3_iclk = { -+ .name = "core_l3_iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_clk, -+}; -+ -+static struct clk core_l4_usb_clk = { -+ .name = "core_l4_usb_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &l3_clk, -+}; -+ -+static struct clk wu_gpt1_clk = { -+ .name = "wu_gpt1_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+}; -+ -+static struct clk wu_32k_clk = { -+ .name = "wu_32k_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+}; -+ -+static struct clk uart1_fclk = { -+ .name = "uart1_fclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &func_48m_clk, -+}; -+ -+static struct clk uart1_iclk = { -+ .name = "uart1_iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_l4_iclk, -+}; -+ -+static struct clk uart2_fclk = { -+ .name = "uart2_fclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &func_48m_clk, -+}; -+ -+static struct clk uart2_iclk = { -+ .name = "uart2_iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_l4_iclk, -+}; -+ -+static struct clk uart3_fclk = { -+ .name = "uart3_fclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &func_48m_clk, -+}; -+ -+static struct clk uart3_iclk = { -+ .name = "uart3_iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_l4_iclk, -+}; -+ -+static struct clk mpu_fclk = { -+ .name = "mpu_fclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_clk, -+}; -+ -+static struct clk mpu_iclk = { -+ .name = "mpu_iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_clk, -+}; -+ -+static struct clk int_m_fclk = { -+ .name = "int_m_fclk", -+ .alias = "mpu_intc_fclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_clk, -+}; -+ -+static struct clk int_m_iclk = { -+ .name = "int_m_iclk", -+ .alias = "mpu_intc_iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_clk, -+}; -+ -+static struct clk core_gpt2_clk = { -+ .name = "core_gpt2_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+}; -+ -+static struct clk core_gpt3_clk = { -+ .name = "core_gpt3_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+}; -+ -+static struct clk core_gpt4_clk = { -+ .name = "core_gpt4_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+}; -+ -+static struct clk core_gpt5_clk = { -+ .name = "core_gpt5_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+}; -+ -+static struct clk core_gpt6_clk = { -+ .name = "core_gpt6_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+}; -+ -+static struct clk core_gpt7_clk = { -+ .name = "core_gpt7_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+}; -+ -+static struct clk core_gpt8_clk = { -+ .name = "core_gpt8_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+}; -+ -+static struct clk core_gpt9_clk = { -+ .name = "core_gpt9_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+}; -+ -+static struct clk core_gpt10_clk = { -+ .name = "core_gpt10_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+}; -+ -+static struct clk core_gpt11_clk = { -+ .name = "core_gpt11_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+}; -+ -+static struct clk core_gpt12_clk = { -+ .name = "core_gpt12_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+}; -+ -+static struct clk mcbsp1_clk = { -+ .name = "mcbsp1_cg", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .divisor = 2, -+ .parent = &func_96m_clk, -+}; -+ -+static struct clk mcbsp2_clk = { -+ .name = "mcbsp2_cg", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .divisor = 2, -+ .parent = &func_96m_clk, -+}; -+ -+static struct clk emul_clk = { -+ .name = "emul_ck", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &func_54m_clk, -+}; -+ -+static struct clk sdma_fclk = { -+ .name = "sdma_fclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &l3_clk, -+}; -+ -+static struct clk sdma_iclk = { -+ .name = "sdma_iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_l3_iclk, /* core_l4_iclk for the configuration port */ -+}; -+ -+static struct clk i2c1_fclk = { -+ .name = "i2c1.fclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &func_12m_clk, -+ .divisor = 1, -+}; -+ -+static struct clk i2c1_iclk = { -+ .name = "i2c1.iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_l4_iclk, -+}; -+ -+static struct clk i2c2_fclk = { -+ .name = "i2c2.fclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &func_12m_clk, -+ .divisor = 1, -+}; -+ -+static struct clk i2c2_iclk = { -+ .name = "i2c2.iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_l4_iclk, -+}; -+ -+static struct clk gpio_dbclk[4] = { -+ { -+ .name = "gpio1_dbclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &wu_32k_clk, -+ }, { -+ .name = "gpio2_dbclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &wu_32k_clk, -+ }, { -+ .name = "gpio3_dbclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &wu_32k_clk, -+ }, { -+ .name = "gpio4_dbclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &wu_32k_clk, -+ }, -+}; -+ -+static struct clk gpio_iclk = { -+ .name = "gpio_iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &wu_l4_iclk, -+}; -+ -+static struct clk mmc_fck = { -+ .name = "mmc_fclk", -+ .flags = CLOCK_IN_OMAP242X, -+ .parent = &func_96m_clk, -+}; -+ -+static struct clk mmc_ick = { -+ .name = "mmc_iclk", -+ .flags = CLOCK_IN_OMAP242X, -+ .parent = &core_l4_iclk, -+}; -+ -+static struct clk spi_fclk[3] = { -+ { -+ .name = "spi1_fclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &func_48m_clk, -+ }, { -+ .name = "spi2_fclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &func_48m_clk, -+ }, { -+ .name = "spi3_fclk", -+ .flags = CLOCK_IN_OMAP243X, -+ .parent = &func_48m_clk, -+ }, -+}; -+ -+static struct clk dss_clk[2] = { -+ { -+ .name = "dss_clk1", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_clk, -+ }, { -+ .name = "dss_clk2", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &sys_clk, -+ }, -+}; -+ -+static struct clk dss_54m_clk = { -+ .name = "dss_54m_clk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &func_54m_clk, -+}; -+ -+static struct clk dss_l3_iclk = { -+ .name = "dss_l3_iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_l3_iclk, -+}; -+ -+static struct clk dss_l4_iclk = { -+ .name = "dss_l4_iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_l4_iclk, -+}; -+ -+static struct clk spi_iclk[3] = { -+ { -+ .name = "spi1_iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_l4_iclk, -+ }, { -+ .name = "spi2_iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ .parent = &core_l4_iclk, -+ }, { -+ .name = "spi3_iclk", -+ .flags = CLOCK_IN_OMAP243X, -+ .parent = &core_l4_iclk, -+ }, -+}; -+ -+static struct clk omapctrl_clk = { -+ .name = "omapctrl_iclk", -+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, -+ /* XXX Should be in WKUP domain */ -+ .parent = &core_l4_iclk, - }; - - static struct clk *onchip_clks[] = { -+ /* OMAP 1 */ -+ - /* non-ULPD clocks */ - &xtal_osc12m, - &xtal_osc32k, -@@ -572,6 +1006,80 @@ static struct clk *onchip_clks[] = { - /* Virtual clocks */ - &i2c_fck, - &i2c_ick, -+ -+ /* OMAP 2 */ -+ -+ &apll_96m, -+ &apll_54m, -+ &sys_clk, -+ &sleep_clk, -+ &dpll_ck, -+ &dpll_x2_ck, -+ &wdt1_sys_clk, -+ &func_96m_clk, -+ &func_48m_clk, -+ &func_12m_clk, -+ &func_54m_clk, -+ &sys_clkout, -+ &sys_clkout2, -+ &core_clk, -+ &l3_clk, -+ &core_l4_iclk, -+ &wu_l4_iclk, -+ &core_l3_iclk, -+ &core_l4_usb_clk, -+ &wu_gpt1_clk, -+ &wu_32k_clk, -+ &uart1_fclk, -+ &uart1_iclk, -+ &uart2_fclk, -+ &uart2_iclk, -+ &uart3_fclk, -+ &uart3_iclk, -+ &mpu_fclk, -+ &mpu_iclk, -+ &int_m_fclk, -+ &int_m_iclk, -+ &core_gpt2_clk, -+ &core_gpt3_clk, -+ &core_gpt4_clk, -+ &core_gpt5_clk, -+ &core_gpt6_clk, -+ &core_gpt7_clk, -+ &core_gpt8_clk, -+ &core_gpt9_clk, -+ &core_gpt10_clk, -+ &core_gpt11_clk, -+ &core_gpt12_clk, -+ &mcbsp1_clk, -+ &mcbsp2_clk, -+ &emul_clk, -+ &sdma_fclk, -+ &sdma_iclk, -+ &i2c1_fclk, -+ &i2c1_iclk, -+ &i2c2_fclk, -+ &i2c2_iclk, -+ &gpio_dbclk[0], -+ &gpio_dbclk[1], -+ &gpio_dbclk[2], -+ &gpio_dbclk[3], -+ &gpio_iclk, -+ &mmc_fck, -+ &mmc_ick, -+ &spi_fclk[0], -+ &spi_iclk[0], -+ &spi_fclk[1], -+ &spi_iclk[1], -+ &spi_fclk[2], -+ &spi_iclk[2], -+ &dss_clk[0], -+ &dss_clk[1], -+ &dss_54m_clk, -+ &dss_l3_iclk, -+ &dss_l4_iclk, -+ &omapctrl_clk, -+ - 0 - }; - -@@ -727,6 +1235,12 @@ void omap_clk_init(struct omap_mpu_state_s *mpu) - flag = CLOCK_IN_OMAP310; - else if (cpu_is_omap1510(mpu)) - flag = CLOCK_IN_OMAP1510; -+ else if (cpu_is_omap2410(mpu) || cpu_is_omap2420(mpu)) -+ flag = CLOCK_IN_OMAP242X; -+ else if (cpu_is_omap2430(mpu)) -+ flag = CLOCK_IN_OMAP243X; -+ else if (cpu_is_omap3430(mpu)) -+ flag = CLOCK_IN_OMAP243X; - else - return; - -diff --git a/hw/omap_dma.c b/hw/omap_dma.c -index 1835826..6c0bd82 100644 ---- a/hw/omap_dma.c -+++ b/hw/omap_dma.c -@@ -28,12 +28,15 @@ struct omap_dma_channel_s { - /* transfer data */ - int burst[2]; - int pack[2]; -+ int endian[2]; -+ int endian_lock[2]; -+ int translate[2]; - enum omap_dma_port port[2]; - target_phys_addr_t addr[2]; - omap_dma_addressing_t mode[2]; -- uint16_t elements; -+ uint32_t elements; - uint16_t frames; -- int16_t frame_index[2]; -+ int32_t frame_index[2]; - int16_t element_index[2]; - int data_type; - -@@ -41,6 +44,7 @@ struct omap_dma_channel_s { - int transparent_copy; - int constant_fill; - uint32_t color; -+ int prefetch; - - /* auto init and linked channel data */ - int end_prog; -@@ -52,11 +56,13 @@ struct omap_dma_channel_s { - /* interruption data */ - int interrupts; - int status; -+ int cstatus; - - /* state data */ - int active; - int enable; - int sync; -+ int src_sync; - int pending_request; - int waiting_end_prog; - uint16_t cpc; -@@ -75,16 +81,21 @@ struct omap_dma_channel_s { - target_phys_addr_t src, dest; - int frame; - int element; -+ int pck_element; - int frame_delta[2]; - int elem_delta[2]; - int frames; - int elements; -+ int pck_elements; - } active_set; - - /* unused parameters */ -+ int write_mode; - int priority; - int interleave_disabled; - int type; -+ int suspend; -+ int buf_disable; - }; - - struct omap_dma_s { -@@ -93,15 +104,21 @@ struct omap_dma_s { - target_phys_addr_t base; - omap_clk clk; - int64_t delay; -- uint32_t drq; -+ uint64_t drq; -+ qemu_irq irq[4]; -+ void (*intr_update)(struct omap_dma_s *s); - enum omap_dma_model model; - int omap_3_1_mapping_disabled; - -- uint16_t gcr; -+ uint32_t gcr; -+ uint32_t ocp; -+ uint32_t caps[5]; -+ uint32_t irqen[4]; -+ uint32_t irqstat[4]; - int run_count; - - int chans; -- struct omap_dma_channel_s ch[16]; -+ struct omap_dma_channel_s ch[32]; - struct omap_dma_lcd_channel_s lcd_ch; - }; - -@@ -113,23 +130,13 @@ struct omap_dma_s { - #define LAST_FRAME_INTR (1 << 4) - #define END_BLOCK_INTR (1 << 5) - #define SYNC (1 << 6) -+#define END_PKT_INTR (1 << 7) -+#define TRANS_ERR_INTR (1 << 8) -+#define MISALIGN_INTR (1 << 11) - --static void omap_dma_interrupts_update(struct omap_dma_s *s) -+static inline void omap_dma_interrupts_update(struct omap_dma_s *s) - { -- struct omap_dma_channel_s *ch = s->ch; -- int i; -- -- if (s->omap_3_1_mapping_disabled) { -- for (i = 0; i < s->chans; i ++, ch ++) -- if (ch->status) -- qemu_irq_raise(ch->irq); -- } else { -- /* First three interrupts are shared between two channels each. */ -- for (i = 0; i < 6; i ++, ch ++) { -- if (ch->status || (ch->sibling && ch->sibling->status)) -- qemu_irq_raise(ch->irq); -- } -- } -+ return s->intr_update(s); - } - - static void omap_dma_channel_load(struct omap_dma_s *s, -@@ -148,8 +155,10 @@ static void omap_dma_channel_load(struct omap_dma_s *s, - a->dest = ch->addr[1]; - a->frames = ch->frames; - a->elements = ch->elements; -+ a->pck_elements = ch->frame_index[!ch->src_sync]; - a->frame = 0; - a->element = 0; -+ a->pck_element = 0; - - if (unlikely(!ch->elements || !ch->frames)) { - printf("%s: bad DMA request\n", __FUNCTION__); -@@ -202,16 +211,15 @@ static void omap_dma_deactivate_channel(struct omap_dma_s *s, - /* Update cpc */ - ch->cpc = ch->active_set.dest & 0xffff; - -- if (ch->pending_request && !ch->waiting_end_prog) { -+ if (ch->pending_request && !ch->waiting_end_prog && ch->enable) { - /* Don't deactivate the channel */ - ch->pending_request = 0; -- if (ch->enable) -- return; -+ return; - } - - /* Don't deactive the channel if it is synchronized and the DMA request is - active */ -- if (ch->sync && (s->drq & (1 << ch->sync)) && ch->enable) -+ if (ch->sync && ch->enable && (s->drq & (1 << ch->sync))) - return; - - if (ch->active) { -@@ -231,6 +239,9 @@ static void omap_dma_enable_channel(struct omap_dma_s *s, - ch->enable = 1; - ch->waiting_end_prog = 0; - omap_dma_channel_load(s, ch); -+ /* TODO: theoretically if ch->sync && ch->prefetch && -+ * !s->drq[ch->sync], we should also activate and fetch from source -+ * and then stall until signalled. */ - if ((!ch->sync) || (s->drq & (1 << ch->sync))) - omap_dma_activate_channel(s, ch); - } -@@ -259,16 +270,47 @@ static void omap_dma_channel_end_prog(struct omap_dma_s *s, - } - } - -+static void omap_dma_interrupts_3_1_update(struct omap_dma_s *s) -+{ -+ struct omap_dma_channel_s *ch = s->ch; -+ -+ /* First three interrupts are shared between two channels each. */ -+ if (ch[0].status | ch[6].status) -+ qemu_irq_raise(ch[0].irq); -+ if (ch[1].status | ch[7].status) -+ qemu_irq_raise(ch[1].irq); -+ if (ch[2].status | ch[8].status) -+ qemu_irq_raise(ch[2].irq); -+ if (ch[3].status) -+ qemu_irq_raise(ch[3].irq); -+ if (ch[4].status) -+ qemu_irq_raise(ch[4].irq); -+ if (ch[5].status) -+ qemu_irq_raise(ch[5].irq); -+} -+ -+static void omap_dma_interrupts_3_2_update(struct omap_dma_s *s) -+{ -+ struct omap_dma_channel_s *ch = s->ch; -+ int i; -+ -+ for (i = s->chans; i; ch ++, i --) -+ if (ch->status) -+ qemu_irq_raise(ch->irq); -+} -+ - static void omap_dma_enable_3_1_mapping(struct omap_dma_s *s) - { - s->omap_3_1_mapping_disabled = 0; - s->chans = 9; -+ s->intr_update = omap_dma_interrupts_3_1_update; - } - - static void omap_dma_disable_3_1_mapping(struct omap_dma_s *s) - { - s->omap_3_1_mapping_disabled = 1; - s->chans = 16; -+ s->intr_update = omap_dma_interrupts_3_2_update; - } - - static void omap_dma_process_request(struct omap_dma_s *s, int request) -@@ -358,6 +400,22 @@ static void omap_dma_channel_run(struct omap_dma_s *s) - if (ch->interrupts & HALF_FRAME_INTR) - ch->status |= HALF_FRAME_INTR; - -+ if (ch->fs && ch->bs) { -+ a->pck_element ++; -+ /* Check if a full packet has beed transferred. */ -+ if (a->pck_element == a->pck_elements) { -+ a->pck_element = 0; -+ -+ /* Set the END_PKT interrupt */ -+ if ((ch->interrupts & END_PKT_INTR) && !ch->src_sync) -+ ch->status |= END_PKT_INTR; -+ -+ /* If the channel is packet-synchronized, deactivate it */ -+ if (ch->sync) -+ omap_dma_deactivate_channel(s, ch); -+ } -+ } -+ - if (a->element == a->elements) { - /* End of Frame */ - a->element = 0; -@@ -366,7 +424,7 @@ static void omap_dma_channel_run(struct omap_dma_s *s) - a->frame ++; - - /* If the channel is frame synchronized, deactivate it */ -- if (ch->sync && ch->fs) -+ if (ch->sync && ch->fs && !ch->bs) - omap_dma_deactivate_channel(s, ch); - - /* If the channel is async, update cpc */ -@@ -414,50 +472,62 @@ void omap_dma_reset(struct omap_dma_s *s) - int i; - - qemu_del_timer(s->tm); -- s->gcr = 0x0004; -+ if (s->model < omap_dma_4) -+ s->gcr = 0x0004; -+ else -+ s->gcr = 0x00010010; -+ s->ocp = 0x00000000; -+ memset(&s->irqstat, 0, sizeof(s->irqstat)); -+ memset(&s->irqen, 0, sizeof(s->irqen)); - s->drq = 0x00000000; - s->run_count = 0; - s->lcd_ch.src = emiff; - s->lcd_ch.condition = 0; - s->lcd_ch.interrupts = 0; - s->lcd_ch.dual = 0; -- omap_dma_enable_3_1_mapping(s); -+ if (s->model < omap_dma_4) -+ omap_dma_enable_3_1_mapping(s); - for (i = 0; i < s->chans; i ++) { -+ s->ch[i].suspend = 0; -+ s->ch[i].prefetch = 0; -+ s->ch[i].buf_disable = 0; -+ s->ch[i].src_sync = 0; - memset(&s->ch[i].burst, 0, sizeof(s->ch[i].burst)); - memset(&s->ch[i].port, 0, sizeof(s->ch[i].port)); - memset(&s->ch[i].mode, 0, sizeof(s->ch[i].mode)); -- memset(&s->ch[i].elements, 0, sizeof(s->ch[i].elements)); -- memset(&s->ch[i].frames, 0, sizeof(s->ch[i].frames)); - memset(&s->ch[i].frame_index, 0, sizeof(s->ch[i].frame_index)); - memset(&s->ch[i].element_index, 0, sizeof(s->ch[i].element_index)); -- memset(&s->ch[i].data_type, 0, sizeof(s->ch[i].data_type)); -- memset(&s->ch[i].transparent_copy, 0, -- sizeof(s->ch[i].transparent_copy)); -- memset(&s->ch[i].constant_fill, 0, sizeof(s->ch[i].constant_fill)); -- memset(&s->ch[i].color, 0, sizeof(s->ch[i].color)); -- memset(&s->ch[i].end_prog, 0, sizeof(s->ch[i].end_prog)); -- memset(&s->ch[i].repeat, 0, sizeof(s->ch[i].repeat)); -- memset(&s->ch[i].auto_init, 0, sizeof(s->ch[i].auto_init)); -- memset(&s->ch[i].link_enabled, 0, sizeof(s->ch[i].link_enabled)); -- memset(&s->ch[i].link_next_ch, 0, sizeof(s->ch[i].link_next_ch)); -- s->ch[i].interrupts = 0x0003; -- memset(&s->ch[i].status, 0, sizeof(s->ch[i].status)); -- memset(&s->ch[i].active, 0, sizeof(s->ch[i].active)); -- memset(&s->ch[i].enable, 0, sizeof(s->ch[i].enable)); -- memset(&s->ch[i].sync, 0, sizeof(s->ch[i].sync)); -- memset(&s->ch[i].pending_request, 0, sizeof(s->ch[i].pending_request)); -- memset(&s->ch[i].waiting_end_prog, 0, -- sizeof(s->ch[i].waiting_end_prog)); -- memset(&s->ch[i].cpc, 0, sizeof(s->ch[i].cpc)); -- memset(&s->ch[i].fs, 0, sizeof(s->ch[i].fs)); -- memset(&s->ch[i].bs, 0, sizeof(s->ch[i].bs)); -- memset(&s->ch[i].omap_3_1_compatible_disable, 0, -- sizeof(s->ch[i].omap_3_1_compatible_disable)); -+ memset(&s->ch[i].endian, 0, sizeof(s->ch[i].endian)); -+ memset(&s->ch[i].endian_lock, 0, sizeof(s->ch[i].endian_lock)); -+ memset(&s->ch[i].translate, 0, sizeof(s->ch[i].translate)); -+ s->ch[i].write_mode = 0; -+ s->ch[i].data_type = 0; -+ s->ch[i].transparent_copy = 0; -+ s->ch[i].constant_fill = 0; -+ s->ch[i].color = 0x00000000; -+ s->ch[i].end_prog = 0; -+ s->ch[i].repeat = 0; -+ s->ch[i].auto_init = 0; -+ s->ch[i].link_enabled = 0; -+ if (s->model < omap_dma_4) -+ s->ch[i].interrupts = 0x0003; -+ else -+ s->ch[i].interrupts = 0x0000; -+ s->ch[i].status = 0; -+ s->ch[i].cstatus = 0; -+ s->ch[i].active = 0; -+ s->ch[i].enable = 0; -+ s->ch[i].sync = 0; -+ s->ch[i].pending_request = 0; -+ s->ch[i].waiting_end_prog = 0; -+ s->ch[i].cpc = 0x0000; -+ s->ch[i].fs = 0; -+ s->ch[i].bs = 0; -+ s->ch[i].omap_3_1_compatible_disable = 0; - memset(&s->ch[i].active_set, 0, sizeof(s->ch[i].active_set)); -- memset(&s->ch[i].priority, 0, sizeof(s->ch[i].priority)); -- memset(&s->ch[i].interleave_disabled, 0, -- sizeof(s->ch[i].interleave_disabled)); -- memset(&s->ch[i].type, 0, sizeof(s->ch[i].type)); -+ s->ch[i].priority = 0; -+ s->ch[i].interleave_disabled = 0; -+ s->ch[i].type = 0; - } - } - -@@ -476,7 +546,7 @@ static int omap_dma_ch_reg_read(struct omap_dma_s *s, - break; - - case 0x02: /* SYS_DMA_CCR_CH0 */ -- if (s->model == omap_dma_3_1) -+ if (s->model <= omap_dma_3_1) - *value = 0 << 10; /* FIFO_FLUSH reads as 0 */ - else - *value = ch->omap_3_1_compatible_disable << 10; -@@ -596,11 +666,11 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, - ch->burst[0] = (value & 0x0180) >> 7; - ch->pack[0] = (value & 0x0040) >> 6; - ch->port[0] = (enum omap_dma_port) ((value & 0x003c) >> 2); -- ch->data_type = (1 << (value & 3)); -- if (ch->port[0] >= omap_dma_port_last) -+ ch->data_type = 1 << (value & 3); -+ if (ch->port[0] >= __omap_dma_port_last) - printf("%s: invalid DMA port %i\n", __FUNCTION__, - ch->port[0]); -- if (ch->port[1] >= omap_dma_port_last) -+ if (ch->port[1] >= __omap_dma_port_last) - printf("%s: invalid DMA port %i\n", __FUNCTION__, - ch->port[1]); - if ((value & 3) == 3) -@@ -611,7 +681,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, - ch->mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14); - ch->mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12); - ch->end_prog = (value & 0x0800) >> 11; -- if (s->model > omap_dma_3_1) -+ if (s->model >= omap_dma_3_2) - ch->omap_3_1_compatible_disable = (value >> 10) & 0x1; - ch->repeat = (value & 0x0200) >> 9; - ch->auto_init = (value & 0x0100) >> 8; -@@ -630,7 +700,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, - break; - - case 0x04: /* SYS_DMA_CICR_CH0 */ -- ch->interrupts = value; -+ ch->interrupts = value & 0x3f; - break; - - case 0x06: /* SYS_DMA_CSR_CH0 */ -@@ -696,7 +766,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, - break; - - case 0x24: /* DMA_CCR2 */ -- ch->bs = (value >> 2) & 0x1; -+ ch->bs = (value >> 2) & 0x1; - ch->transparent_copy = (value >> 1) & 0x1; - ch->constant_fill = value & 0x1; - break; -@@ -1126,48 +1196,29 @@ static int omap_dma_sys_read(struct omap_dma_s *s, int offset, - break; - - case 0x44e: /* DMA_CAPS_0_U */ -- *ret = (1 << 3) | /* Constant Fill Capacity */ -- (1 << 2); /* Transparent BLT Capacity */ -+ *ret = (s->caps[0] >> 16) & 0xffff; - break; -- - case 0x450: /* DMA_CAPS_0_L */ -- case 0x452: /* DMA_CAPS_1_U */ -- *ret = 0; -+ *ret = (s->caps[0] >> 0) & 0xffff; - break; - -+ case 0x452: /* DMA_CAPS_1_U */ -+ *ret = (s->caps[1] >> 16) & 0xffff; -+ break; - case 0x454: /* DMA_CAPS_1_L */ -- *ret = (1 << 1); /* 1-bit palletized capability */ -+ *ret = (s->caps[1] >> 0) & 0xffff; - break; - - case 0x456: /* DMA_CAPS_2 */ -- *ret = (1 << 8) | /* SSDIC */ -- (1 << 7) | /* DDIAC */ -- (1 << 6) | /* DSIAC */ -- (1 << 5) | /* DPIAC */ -- (1 << 4) | /* DCAC */ -- (1 << 3) | /* SDIAC */ -- (1 << 2) | /* SSIAC */ -- (1 << 1) | /* SPIAC */ -- 1; /* SCAC */ -+ *ret = s->caps[2]; - break; - - case 0x458: /* DMA_CAPS_3 */ -- *ret = (1 << 5) | /* CCC */ -- (1 << 4) | /* IC */ -- (1 << 3) | /* ARC */ -- (1 << 2) | /* AEC */ -- (1 << 1) | /* FSC */ -- 1; /* ESC */ -+ *ret = s->caps[3]; - break; - - case 0x45a: /* DMA_CAPS_4 */ -- *ret = (1 << 6) | /* SSC */ -- (1 << 5) | /* BIC */ -- (1 << 4) | /* LFIC */ -- (1 << 3) | /* FIC */ -- (1 << 2) | /* HFIC */ -- (1 << 1) | /* EDIC */ -- 1; /* TOIC */ -+ *ret = s->caps[4]; - break; - - case 0x460: /* DMA_PCh2_SR */ -@@ -1193,7 +1244,7 @@ static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr) - - switch (offset) { - case 0x300 ... 0x3fe: -- if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) { -+ if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) { - if (omap_dma_3_1_lcd_read(&s->lcd_ch, offset, &ret)) - break; - return ret; -@@ -1207,7 +1258,7 @@ static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr) - return ret; - - case 0x404 ... 0x4fe: -- if (s->model == omap_dma_3_1) -+ if (s->model <= omap_dma_3_1) - break; - /* Fall through. */ - case 0x400: -@@ -1236,7 +1287,7 @@ static void omap_dma_write(void *opaque, target_phys_addr_t addr, - - switch (offset) { - case 0x300 ... 0x3fe: -- if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) { -+ if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) { - if (omap_dma_3_1_lcd_write(&s->lcd_ch, offset, value)) - break; - return; -@@ -1250,7 +1301,7 @@ static void omap_dma_write(void *opaque, target_phys_addr_t addr, - return; - - case 0x404 ... 0x4fe: -- if (s->model == omap_dma_3_1) -+ if (s->model <= omap_dma_3_1) - break; - case 0x400: - /* Fall through. */ -@@ -1285,7 +1336,7 @@ static CPUWriteMemoryFunc *omap_dma_writefn[] = { - static void omap_dma_request(void *opaque, int drq, int req) - { - struct omap_dma_s *s = (struct omap_dma_s *) opaque; -- /* The request pins are level triggered. */ -+ /* The request pins are level triggered in QEMU. */ - if (req) { - if (~s->drq & (1 << drq)) { - s->drq |= 1 << drq; -@@ -1310,6 +1361,52 @@ static void omap_dma_clk_update(void *opaque, int line, int on) - } - } - -+static void omap_dma_setcaps(struct omap_dma_s *s) -+{ -+ switch (s->model) { -+ default: -+ case omap_dma_3_1: -+ break; -+ case omap_dma_3_2: -+ case omap_dma_4: -+ /* XXX Only available for sDMA */ -+ s->caps[0] = -+ (1 << 19) | /* Constant Fill Capability */ -+ (1 << 18); /* Transparent BLT Capability */ -+ s->caps[1] = -+ (1 << 1); /* 1-bit palettized capability (DMA 3.2 only) */ -+ s->caps[2] = -+ (1 << 8) | /* SEPARATE_SRC_AND_DST_INDEX_CPBLTY */ -+ (1 << 7) | /* DST_DOUBLE_INDEX_ADRS_CPBLTY */ -+ (1 << 6) | /* DST_SINGLE_INDEX_ADRS_CPBLTY */ -+ (1 << 5) | /* DST_POST_INCRMNT_ADRS_CPBLTY */ -+ (1 << 4) | /* DST_CONST_ADRS_CPBLTY */ -+ (1 << 3) | /* SRC_DOUBLE_INDEX_ADRS_CPBLTY */ -+ (1 << 2) | /* SRC_SINGLE_INDEX_ADRS_CPBLTY */ -+ (1 << 1) | /* SRC_POST_INCRMNT_ADRS_CPBLTY */ -+ (1 << 0); /* SRC_CONST_ADRS_CPBLTY */ -+ s->caps[3] = -+ (1 << 6) | /* BLOCK_SYNCHR_CPBLTY (DMA 4 only) */ -+ (1 << 7) | /* PKT_SYNCHR_CPBLTY (DMA 4 only) */ -+ (1 << 5) | /* CHANNEL_CHAINING_CPBLTY */ -+ (1 << 4) | /* LCh_INTERLEAVE_CPBLTY */ -+ (1 << 3) | /* AUTOINIT_REPEAT_CPBLTY (DMA 3.2 only) */ -+ (1 << 2) | /* AUTOINIT_ENDPROG_CPBLTY (DMA 3.2 only) */ -+ (1 << 1) | /* FRAME_SYNCHR_CPBLTY */ -+ (1 << 0); /* ELMNT_SYNCHR_CPBLTY */ -+ s->caps[4] = -+ (1 << 7) | /* PKT_INTERRUPT_CPBLTY (DMA 4 only) */ -+ (1 << 6) | /* SYNC_STATUS_CPBLTY */ -+ (1 << 5) | /* BLOCK_INTERRUPT_CPBLTY */ -+ (1 << 4) | /* LAST_FRAME_INTERRUPT_CPBLTY */ -+ (1 << 3) | /* FRAME_INTERRUPT_CPBLTY */ -+ (1 << 2) | /* HALF_FRAME_INTERRUPT_CPBLTY */ -+ (1 << 1) | /* EVENT_DROP_INTERRUPT_CPBLTY */ -+ (1 << 0); /* TIMEOUT_INTERRUPT_CPBLTY (DMA 3.2 only) */ -+ break; -+ } -+} -+ - struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, - qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk, - enum omap_dma_model model) -@@ -1318,7 +1415,7 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, - struct omap_dma_s *s = (struct omap_dma_s *) - qemu_mallocz(sizeof(struct omap_dma_s)); - -- if (model == omap_dma_3_1) { -+ if (model <= omap_dma_3_1) { - num_irqs = 6; - memsize = 0x800; - } else { -@@ -1331,6 +1428,7 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, - s->clk = clk; - s->lcd_ch.irq = lcd_irq; - s->lcd_ch.mpu = mpu; -+ omap_dma_setcaps(s); - while (num_irqs --) - s->ch[num_irqs].irq = irqs[num_irqs]; - for (i = 0; i < 3; i ++) { -@@ -1350,6 +1448,393 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, - return s; - } - -+static void omap_dma_interrupts_4_update(struct omap_dma_s *s) -+{ -+ struct omap_dma_channel_s *ch = s->ch; -+ uint32_t bmp, bit; -+ -+ for (bmp = 0, bit = 1; bit; ch ++, bit <<= 1) -+ if (ch->status) { -+ bmp |= bit; -+ ch->cstatus |= ch->status; -+ ch->status = 0; -+ } -+ if ((s->irqstat[0] |= s->irqen[0] & bmp)) -+ qemu_irq_raise(s->irq[0]); -+ if ((s->irqstat[1] |= s->irqen[1] & bmp)) -+ qemu_irq_raise(s->irq[1]); -+ if ((s->irqstat[2] |= s->irqen[2] & bmp)) -+ qemu_irq_raise(s->irq[2]); -+ if ((s->irqstat[3] |= s->irqen[3] & bmp)) -+ qemu_irq_raise(s->irq[3]); -+} -+ -+static uint32_t omap_dma4_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_dma_s *s = (struct omap_dma_s *) opaque; -+ int irqn = 0, chnum, offset = addr - s->base; -+ struct omap_dma_channel_s *ch; -+ -+ switch (offset) { -+ case 0x00: /* DMA4_REVISION */ -+ return 0x40; -+ -+ case 0x14: /* DMA4_IRQSTATUS_L3 */ -+ irqn ++; -+ case 0x10: /* DMA4_IRQSTATUS_L2 */ -+ irqn ++; -+ case 0x0c: /* DMA4_IRQSTATUS_L1 */ -+ irqn ++; -+ case 0x08: /* DMA4_IRQSTATUS_L0 */ -+ return s->irqstat[irqn]; -+ -+ case 0x24: /* DMA4_IRQENABLE_L3 */ -+ irqn ++; -+ case 0x20: /* DMA4_IRQENABLE_L2 */ -+ irqn ++; -+ case 0x1c: /* DMA4_IRQENABLE_L1 */ -+ irqn ++; -+ case 0x18: /* DMA4_IRQENABLE_L0 */ -+ return s->irqen[irqn]; -+ -+ case 0x28: /* DMA4_SYSSTATUS */ -+ return 1; /* RESETDONE */ -+ -+ case 0x2c: /* DMA4_OCP_SYSCONFIG */ -+ return s->ocp; -+ -+ case 0x64: /* DMA4_CAPS_0 */ -+ return s->caps[0]; -+ case 0x6c: /* DMA4_CAPS_2 */ -+ return s->caps[2]; -+ case 0x70: /* DMA4_CAPS_3 */ -+ return s->caps[3]; -+ case 0x74: /* DMA4_CAPS_4 */ -+ return s->caps[4]; -+ -+ case 0x78: /* DMA4_GCR */ -+ return s->gcr; -+ -+ case 0x80 ... 0xfff: -+ offset -= 0x80; -+ chnum = offset / 0x60; -+ ch = s->ch + chnum; -+ offset -= chnum * 0x60; -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ return 0; -+ } -+ -+ /* Per-channel registers */ -+ switch (offset) { -+ case 0x00: /* DMA4_CCR */ -+ return (ch->buf_disable << 25) | -+ (ch->src_sync << 24) | -+ (ch->prefetch << 23) | -+ ((ch->sync & 0x60) << 14) | -+ (ch->bs << 18) | -+ (ch->transparent_copy << 17) | -+ (ch->constant_fill << 16) | -+ (ch->mode[1] << 14) | -+ (ch->mode[0] << 12) | -+ (0 << 10) | (0 << 9) | -+ (ch->suspend << 8) | -+ (ch->enable << 7) | -+ (ch->priority << 6) | -+ (ch->fs << 5) | (ch->sync & 0x1f); -+ -+ case 0x04: /* DMA4_CLNK_CTRL */ -+ return (ch->link_enabled << 15) | ch->link_next_ch; -+ -+ case 0x08: /* DMA4_CICR */ -+ return ch->interrupts; -+ -+ case 0x0c: /* DMA4_CSR */ -+ return ch->cstatus; -+ -+ case 0x10: /* DMA4_CSDP */ -+ return (ch->endian[0] << 21) | -+ (ch->endian_lock[0] << 20) | -+ (ch->endian[1] << 19) | -+ (ch->endian_lock[1] << 18) | -+ (ch->write_mode << 16) | -+ (ch->burst[1] << 14) | -+ (ch->pack[1] << 13) | -+ (ch->translate[1] << 9) | -+ (ch->burst[0] << 7) | -+ (ch->pack[0] << 6) | -+ (ch->translate[0] << 2) | -+ (ch->data_type >> 1); -+ -+ case 0x14: /* DMA4_CEN */ -+ return ch->elements; -+ -+ case 0x18: /* DMA4_CFN */ -+ return ch->frames; -+ -+ case 0x1c: /* DMA4_CSSA */ -+ return ch->addr[0]; -+ -+ case 0x20: /* DMA4_CDSA */ -+ return ch->addr[1]; -+ -+ case 0x24: /* DMA4_CSEI */ -+ return ch->element_index[0]; -+ -+ case 0x28: /* DMA4_CSFI */ -+ return ch->frame_index[0]; -+ -+ case 0x2c: /* DMA4_CDEI */ -+ return ch->element_index[1]; -+ -+ case 0x30: /* DMA4_CDFI */ -+ return ch->frame_index[1]; -+ -+ case 0x34: /* DMA4_CSAC */ -+ return ch->active_set.src & 0xffff; -+ -+ case 0x38: /* DMA4_CDAC */ -+ return ch->active_set.dest & 0xffff; -+ -+ case 0x3c: /* DMA4_CCEN */ -+ return ch->active_set.element; -+ -+ case 0x40: /* DMA4_CCFN */ -+ return ch->active_set.frame; -+ -+ case 0x44: /* DMA4_COLOR */ -+ /* XXX only in sDMA */ -+ return ch->color; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ return 0; -+ } -+} -+ -+static void omap_dma4_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_dma_s *s = (struct omap_dma_s *) opaque; -+ int chnum, irqn = 0, offset = addr - s->base; -+ struct omap_dma_channel_s *ch; -+ -+ switch (offset) { -+ case 0x14: /* DMA4_IRQSTATUS_L3 */ -+ irqn ++; -+ case 0x10: /* DMA4_IRQSTATUS_L2 */ -+ irqn ++; -+ case 0x0c: /* DMA4_IRQSTATUS_L1 */ -+ irqn ++; -+ case 0x08: /* DMA4_IRQSTATUS_L0 */ -+ s->irqstat[irqn] &= ~value; -+ if (!s->irqstat[irqn]) -+ qemu_irq_lower(s->irq[irqn]); -+ return; -+ -+ case 0x24: /* DMA4_IRQENABLE_L3 */ -+ irqn ++; -+ case 0x20: /* DMA4_IRQENABLE_L2 */ -+ irqn ++; -+ case 0x1c: /* DMA4_IRQENABLE_L1 */ -+ irqn ++; -+ case 0x18: /* DMA4_IRQENABLE_L0 */ -+ s->irqen[irqn] = value; -+ return; -+ -+ case 0x2c: /* DMA4_OCP_SYSCONFIG */ -+ if (value & 2) /* SOFTRESET */ -+ omap_dma_reset(s); -+ s->ocp = value & 0x3321; -+ if (((s->ocp >> 12) & 3) == 3) /* MIDLEMODE */ -+ fprintf(stderr, "%s: invalid DMA power mode\n", __FUNCTION__); -+ return; -+ -+ case 0x78: /* DMA4_GCR */ -+ s->gcr = value & 0x00ff00ff; -+ if ((value & 0xff) == 0x00) /* MAX_CHANNEL_FIFO_DEPTH */ -+ fprintf(stderr, "%s: wrong FIFO depth in GCR\n", __FUNCTION__); -+ return; -+ -+ case 0x80 ... 0xfff: -+ offset -= 0x80; -+ chnum = offset / 0x60; -+ ch = s->ch + chnum; -+ offset -= chnum * 0x60; -+ break; -+ -+ case 0x00: /* DMA4_REVISION */ -+ case 0x28: /* DMA4_SYSSTATUS */ -+ case 0x64: /* DMA4_CAPS_0 */ -+ case 0x6c: /* DMA4_CAPS_2 */ -+ case 0x70: /* DMA4_CAPS_3 */ -+ case 0x74: /* DMA4_CAPS_4 */ -+ OMAP_RO_REG(addr); -+ return; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ return; -+ } -+ -+ /* Per-channel registers */ -+ switch (offset) { -+ case 0x00: /* DMA4_CCR */ -+ ch->buf_disable = (value >> 25) & 1; -+ ch->src_sync = (value >> 24) & 1; /* XXX For CamDMA must be 1 */ -+ if (ch->buf_disable && !ch->src_sync) -+ fprintf(stderr, "%s: Buffering disable is not allowed in " -+ "destination synchronised mode\n", __FUNCTION__); -+ ch->prefetch = (value >> 23) & 1; -+ ch->bs = (value >> 18) & 1; -+ ch->transparent_copy = (value >> 17) & 1; -+ ch->constant_fill = (value >> 16) & 1; -+ ch->mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14); -+ ch->mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12); -+ ch->suspend = (value & 0x0100) >> 8; -+ ch->priority = (value & 0x0040) >> 6; -+ ch->fs = (value & 0x0020) >> 5; -+ if (ch->fs && ch->bs && ch->mode[0] && ch->mode[1]) -+ fprintf(stderr, "%s: For a packet transfer at least one port " -+ "must be constant-addressed\n", __FUNCTION__); -+ ch->sync = (value & 0x001f) | ((value >> 14) & 0x0060); -+ /* XXX must be 0x01 for CamDMA */ -+ -+ if (value & 0x0080) -+ omap_dma_enable_channel(s, ch); -+ else -+ omap_dma_disable_channel(s, ch); -+ -+ break; -+ -+ case 0x04: /* DMA4_CLNK_CTRL */ -+ ch->link_enabled = (value >> 15) & 0x1; -+ ch->link_next_ch = value & 0x1f; -+ break; -+ -+ case 0x08: /* DMA4_CICR */ -+ ch->interrupts = value & 0x09be; -+ break; -+ -+ case 0x0c: /* DMA4_CSR */ -+ ch->cstatus &= ~value; -+ break; -+ -+ case 0x10: /* DMA4_CSDP */ -+ ch->endian[0] =(value >> 21) & 1; -+ ch->endian_lock[0] =(value >> 20) & 1; -+ ch->endian[1] =(value >> 19) & 1; -+ ch->endian_lock[1] =(value >> 18) & 1; -+ if (ch->endian[0] != ch->endian[1]) -+ fprintf(stderr, "%s: DMA endianned conversion enable attempt\n", -+ __FUNCTION__); -+ ch->write_mode = (value >> 16) & 3; -+ ch->burst[1] = (value & 0xc000) >> 14; -+ ch->pack[1] = (value & 0x2000) >> 13; -+ ch->translate[1] = (value & 0x1e00) >> 9; -+ ch->burst[0] = (value & 0x0180) >> 7; -+ ch->pack[0] = (value & 0x0040) >> 6; -+ ch->translate[0] = (value & 0x003c) >> 2; -+ if (ch->translate[0] | ch->translate[1]) -+ fprintf(stderr, "%s: bad MReqAddressTranslate sideband signal\n", -+ __FUNCTION__); -+ ch->data_type = 1 << (value & 3); -+ if ((value & 3) == 3) -+ printf("%s: bad data_type for DMA channel\n", __FUNCTION__); -+ break; -+ -+ case 0x14: /* DMA4_CEN */ -+ ch->elements = value & 0xffffff; -+ break; -+ -+ case 0x18: /* DMA4_CFN */ -+ ch->frames = value & 0xffff; -+ break; -+ -+ case 0x1c: /* DMA4_CSSA */ -+ ch->addr[0] = (target_phys_addr_t) (uint32_t) value; -+ break; -+ -+ case 0x20: /* DMA4_CDSA */ -+ ch->addr[1] = (target_phys_addr_t) (uint32_t) value; -+ break; -+ -+ case 0x24: /* DMA4_CSEI */ -+ ch->element_index[0] = (int16_t) value; -+ break; -+ -+ case 0x28: /* DMA4_CSFI */ -+ ch->frame_index[0] = (int32_t) value; -+ break; -+ -+ case 0x2c: /* DMA4_CDEI */ -+ ch->element_index[1] = (int16_t) value; -+ break; -+ -+ case 0x30: /* DMA4_CDFI */ -+ ch->frame_index[1] = (int32_t) value; -+ break; -+ -+ case 0x44: /* DMA4_COLOR */ -+ /* XXX only in sDMA */ -+ ch->color = value; -+ break; -+ -+ case 0x34: /* DMA4_CSAC */ -+ case 0x38: /* DMA4_CDAC */ -+ case 0x3c: /* DMA4_CCEN */ -+ case 0x40: /* DMA4_CCFN */ -+ OMAP_RO_REG(addr); -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ } -+} -+ -+static CPUReadMemoryFunc *omap_dma4_readfn[] = { -+ omap_badwidth_read16, -+ omap_dma4_read, -+ omap_dma4_read, -+}; -+ -+static CPUWriteMemoryFunc *omap_dma4_writefn[] = { -+ omap_badwidth_write16, -+ omap_dma4_write, -+ omap_dma4_write, -+}; -+ -+struct omap_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs, -+ struct omap_mpu_state_s *mpu, int fifo, -+ int chans, omap_clk iclk, omap_clk fclk) -+{ -+ int iomemtype; -+ struct omap_dma_s *s = (struct omap_dma_s *) -+ qemu_mallocz(sizeof(struct omap_dma_s)); -+ -+ s->base = base; -+ s->model = omap_dma_4; -+ s->chans = chans; -+ s->mpu = mpu; -+ s->clk = fclk; -+ memcpy(&s->irq, irqs, sizeof(s->irq)); -+ s->intr_update = omap_dma_interrupts_4_update; -+ omap_dma_setcaps(s); -+ s->tm = qemu_new_timer(vm_clock, (QEMUTimerCB *) omap_dma_channel_run, s); -+ omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]); -+ mpu->drq = qemu_allocate_irqs(omap_dma_request, s, 64); -+ omap_dma_reset(s); -+ omap_dma_clk_update(s, 0, 1); -+ -+ iomemtype = cpu_register_io_memory(0, omap_dma4_readfn, -+ omap_dma4_writefn, s); -+ cpu_register_physical_memory(s->base, 0x1000, iomemtype); -+ -+ return s; -+} -+ - struct omap_dma_lcd_channel_s *omap_dma_get_lcdch(struct omap_dma_s *s) - { - return &s->lcd_ch; -diff --git a/hw/omap_dss.c b/hw/omap_dss.c -new file mode 100644 -index 0000000..1c16802 ---- /dev/null -+++ b/hw/omap_dss.c -@@ -0,0 +1,1088 @@ -+/* -+ * OMAP2 Display Subsystem. -+ * -+ * Copyright (C) 2008 Nokia Corporation -+ * Written by Andrzej Zaborowski -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of -+ * the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, -+ * MA 02111-1307 USA -+ */ -+#include "hw.h" -+#include "console.h" -+#include "omap.h" -+ -+struct omap_dss_s { -+ target_phys_addr_t diss_base; -+ target_phys_addr_t disc_base; -+ target_phys_addr_t rfbi_base; -+ target_phys_addr_t venc_base; -+ target_phys_addr_t im3_base; -+ qemu_irq irq; -+ qemu_irq drq; -+ DisplayState *state; -+ -+ int autoidle; -+ int control; -+ int enable; -+ -+ struct omap_dss_panel_s { -+ int enable; -+ int nx; -+ int ny; -+ -+ int x; -+ int y; -+ } dig, lcd; -+ -+ struct { -+ uint32_t idlemode; -+ uint32_t irqst; -+ uint32_t irqen; -+ uint32_t control; -+ uint32_t config; -+ uint32_t capable; -+ uint32_t timing[3]; -+ int line; -+ uint32_t bg[2]; -+ uint32_t trans[2]; -+ -+ struct omap_dss_plane_s { -+ int enable; -+ int bpp; -+ int posx; -+ int posy; -+ int nx; -+ int ny; -+ -+ target_phys_addr_t addr[3]; -+ -+ uint32_t attr; -+ uint32_t tresh; -+ int rowinc; -+ int colinc; -+ int wininc; -+ } l[3]; -+ -+ int invalidate; -+ uint16_t palette[256]; -+ } dispc; -+ -+ struct { -+ int idlemode; -+ uint32_t control; -+ int enable; -+ int pixels; -+ int busy; -+ int skiplines; -+ uint16_t rxbuf; -+ uint32_t config[2]; -+ uint32_t time[4]; -+ uint32_t data[6]; -+ uint16_t vsync; -+ uint16_t hsync; -+ struct rfbi_chip_s *chip[2]; -+ } rfbi; -+}; -+ -+static void omap_dispc_interrupt_update(struct omap_dss_s *s) -+{ -+ qemu_set_irq(s->irq, s->dispc.irqst & s->dispc.irqen); -+} -+ -+static void omap_rfbi_reset(struct omap_dss_s *s) -+{ -+ s->rfbi.idlemode = 0; -+ s->rfbi.control = 2; -+ s->rfbi.enable = 0; -+ s->rfbi.pixels = 0; -+ s->rfbi.skiplines = 0; -+ s->rfbi.busy = 0; -+ s->rfbi.config[0] = 0x00310000; -+ s->rfbi.config[1] = 0x00310000; -+ s->rfbi.time[0] = 0; -+ s->rfbi.time[1] = 0; -+ s->rfbi.time[2] = 0; -+ s->rfbi.time[3] = 0; -+ s->rfbi.data[0] = 0; -+ s->rfbi.data[1] = 0; -+ s->rfbi.data[2] = 0; -+ s->rfbi.data[3] = 0; -+ s->rfbi.data[4] = 0; -+ s->rfbi.data[5] = 0; -+ s->rfbi.vsync = 0; -+ s->rfbi.hsync = 0; -+} -+ -+void omap_dss_reset(struct omap_dss_s *s) -+{ -+ s->autoidle = 0; -+ s->control = 0; -+ s->enable = 0; -+ -+ s->dig.enable = 0; -+ s->dig.nx = 1; -+ s->dig.ny = 1; -+ -+ s->lcd.enable = 0; -+ s->lcd.nx = 1; -+ s->lcd.ny = 1; -+ -+ s->dispc.idlemode = 0; -+ s->dispc.irqst = 0; -+ s->dispc.irqen = 0; -+ s->dispc.control = 0; -+ s->dispc.config = 0; -+ s->dispc.capable = 0x161; -+ s->dispc.timing[0] = 0; -+ s->dispc.timing[1] = 0; -+ s->dispc.timing[2] = 0; -+ s->dispc.line = 0; -+ s->dispc.bg[0] = 0; -+ s->dispc.bg[1] = 0; -+ s->dispc.trans[0] = 0; -+ s->dispc.trans[1] = 0; -+ -+ s->dispc.l[0].enable = 0; -+ s->dispc.l[0].bpp = 0; -+ s->dispc.l[0].addr[0] = 0; -+ s->dispc.l[0].addr[1] = 0; -+ s->dispc.l[0].addr[2] = 0; -+ s->dispc.l[0].posx = 0; -+ s->dispc.l[0].posy = 0; -+ s->dispc.l[0].nx = 1; -+ s->dispc.l[0].ny = 1; -+ s->dispc.l[0].attr = 0; -+ s->dispc.l[0].tresh = 0; -+ s->dispc.l[0].rowinc = 1; -+ s->dispc.l[0].colinc = 1; -+ s->dispc.l[0].wininc = 0; -+ -+ omap_rfbi_reset(s); -+ omap_dispc_interrupt_update(s); -+} -+ -+static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_dss_s *s = (struct omap_dss_s *) opaque; -+ int offset = addr - s->diss_base; -+ -+ switch (offset) { -+ case 0x00: /* DSS_REVISIONNUMBER */ -+ return 0x20; -+ -+ case 0x10: /* DSS_SYSCONFIG */ -+ return s->autoidle; -+ -+ case 0x14: /* DSS_SYSSTATUS */ -+ return 1; /* RESETDONE */ -+ -+ case 0x40: /* DSS_CONTROL */ -+ return s->control; -+ -+ case 0x50: /* DSS_PSA_LCD_REG_1 */ -+ case 0x54: /* DSS_PSA_LCD_REG_2 */ -+ case 0x58: /* DSS_PSA_VIDEO_REG */ -+ /* TODO: fake some values when appropriate s->control bits are set */ -+ return 0; -+ -+ case 0x5c: /* DSS_STATUS */ -+ return 1 + (s->control & 1); -+ -+ default: -+ break; -+ } -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap_diss_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_dss_s *s = (struct omap_dss_s *) opaque; -+ int offset = addr - s->diss_base; -+ -+ switch (offset) { -+ case 0x00: /* DSS_REVISIONNUMBER */ -+ case 0x14: /* DSS_SYSSTATUS */ -+ case 0x50: /* DSS_PSA_LCD_REG_1 */ -+ case 0x54: /* DSS_PSA_LCD_REG_2 */ -+ case 0x58: /* DSS_PSA_VIDEO_REG */ -+ case 0x5c: /* DSS_STATUS */ -+ OMAP_RO_REG(addr); -+ break; -+ -+ case 0x10: /* DSS_SYSCONFIG */ -+ if (value & 2) /* SOFTRESET */ -+ omap_dss_reset(s); -+ s->autoidle = value & 1; -+ break; -+ -+ case 0x40: /* DSS_CONTROL */ -+ s->control = value & 0x3dd; -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ } -+} -+ -+static CPUReadMemoryFunc *omap_diss1_readfn[] = { -+ omap_badwidth_read32, -+ omap_badwidth_read32, -+ omap_diss_read, -+}; -+ -+static CPUWriteMemoryFunc *omap_diss1_writefn[] = { -+ omap_badwidth_write32, -+ omap_badwidth_write32, -+ omap_diss_write, -+}; -+ -+static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_dss_s *s = (struct omap_dss_s *) opaque; -+ int offset = addr - s->disc_base; -+ -+ switch (offset) { -+ case 0x000: /* DISPC_REVISION */ -+ return 0x20; -+ -+ case 0x010: /* DISPC_SYSCONFIG */ -+ return s->dispc.idlemode; -+ -+ case 0x014: /* DISPC_SYSSTATUS */ -+ return 1; /* RESETDONE */ -+ -+ case 0x018: /* DISPC_IRQSTATUS */ -+ return s->dispc.irqst; -+ -+ case 0x01c: /* DISPC_IRQENABLE */ -+ return s->dispc.irqen; -+ -+ case 0x040: /* DISPC_CONTROL */ -+ return s->dispc.control; -+ -+ case 0x044: /* DISPC_CONFIG */ -+ return s->dispc.config; -+ -+ case 0x048: /* DISPC_CAPABLE */ -+ return s->dispc.capable; -+ -+ case 0x04c: /* DISPC_DEFAULT_COLOR0 */ -+ return s->dispc.bg[0]; -+ case 0x050: /* DISPC_DEFAULT_COLOR1 */ -+ return s->dispc.bg[1]; -+ case 0x054: /* DISPC_TRANS_COLOR0 */ -+ return s->dispc.trans[0]; -+ case 0x058: /* DISPC_TRANS_COLOR1 */ -+ return s->dispc.trans[1]; -+ -+ case 0x05c: /* DISPC_LINE_STATUS */ -+ return 0x7ff; -+ case 0x060: /* DISPC_LINE_NUMBER */ -+ return s->dispc.line; -+ -+ case 0x064: /* DISPC_TIMING_H */ -+ return s->dispc.timing[0]; -+ case 0x068: /* DISPC_TIMING_V */ -+ return s->dispc.timing[1]; -+ case 0x06c: /* DISPC_POL_FREQ */ -+ return s->dispc.timing[2]; -+ case 0x070: /* DISPC_DIVISOR */ -+ return s->dispc.timing[3]; -+ -+ case 0x078: /* DISPC_SIZE_DIG */ -+ return ((s->dig.ny - 1) << 16) | (s->dig.nx - 1); -+ case 0x07c: /* DISPC_SIZE_LCD */ -+ return ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1); -+ -+ case 0x080: /* DISPC_GFX_BA0 */ -+ return s->dispc.l[0].addr[0]; -+ case 0x084: /* DISPC_GFX_BA1 */ -+ return s->dispc.l[0].addr[1]; -+ case 0x088: /* DISPC_GFX_POSITION */ -+ return (s->dispc.l[0].posy << 16) | s->dispc.l[0].posx; -+ case 0x08c: /* DISPC_GFX_SIZE */ -+ return ((s->dispc.l[0].ny - 1) << 16) | (s->dispc.l[0].nx - 1); -+ case 0x0a0: /* DISPC_GFX_ATTRIBUTES */ -+ return s->dispc.l[0].attr; -+ case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */ -+ return s->dispc.l[0].tresh; -+ case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */ -+ return 256; -+ case 0x0ac: /* DISPC_GFX_ROW_INC */ -+ return s->dispc.l[0].rowinc; -+ case 0x0b0: /* DISPC_GFX_PIXEL_INC */ -+ return s->dispc.l[0].colinc; -+ case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */ -+ return s->dispc.l[0].wininc; -+ case 0x0b8: /* DISPC_GFX_TABLE_BA */ -+ return s->dispc.l[0].addr[2]; -+ -+ case 0x0bc: /* DISPC_VID1_BA0 */ -+ case 0x0c0: /* DISPC_VID1_BA1 */ -+ case 0x0c4: /* DISPC_VID1_POSITION */ -+ case 0x0c8: /* DISPC_VID1_SIZE */ -+ case 0x0cc: /* DISPC_VID1_ATTRIBUTES */ -+ case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */ -+ case 0x0d4: /* DISPC_VID1_FIFO_SIZE_STATUS */ -+ case 0x0d8: /* DISPC_VID1_ROW_INC */ -+ case 0x0dc: /* DISPC_VID1_PIXEL_INC */ -+ case 0x0e0: /* DISPC_VID1_FIR */ -+ case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */ -+ case 0x0e8: /* DISPC_VID1_ACCU0 */ -+ case 0x0ec: /* DISPC_VID1_ACCU1 */ -+ case 0x0f0 ... 0x140: /* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */ -+ case 0x14c: /* DISPC_VID2_BA0 */ -+ case 0x150: /* DISPC_VID2_BA1 */ -+ case 0x154: /* DISPC_VID2_POSITION */ -+ case 0x158: /* DISPC_VID2_SIZE */ -+ case 0x15c: /* DISPC_VID2_ATTRIBUTES */ -+ case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */ -+ case 0x164: /* DISPC_VID2_FIFO_SIZE_STATUS */ -+ case 0x168: /* DISPC_VID2_ROW_INC */ -+ case 0x16c: /* DISPC_VID2_PIXEL_INC */ -+ case 0x170: /* DISPC_VID2_FIR */ -+ case 0x174: /* DISPC_VID2_PICTURE_SIZE */ -+ case 0x178: /* DISPC_VID2_ACCU0 */ -+ case 0x17c: /* DISPC_VID2_ACCU1 */ -+ case 0x180 ... 0x1d0: /* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */ -+ case 0x1d4: /* DISPC_DATA_CYCLE1 */ -+ case 0x1d8: /* DISPC_DATA_CYCLE2 */ -+ case 0x1dc: /* DISPC_DATA_CYCLE3 */ -+ return 0; -+ -+ default: -+ break; -+ } -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap_disc_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_dss_s *s = (struct omap_dss_s *) opaque; -+ int offset = addr - s->disc_base; -+ -+ switch (offset) { -+ case 0x010: /* DISPC_SYSCONFIG */ -+ if (value & 2) /* SOFTRESET */ -+ omap_dss_reset(s); -+ s->dispc.idlemode = value & 0x301b; -+ break; -+ -+ case 0x018: /* DISPC_IRQSTATUS */ -+ s->dispc.irqst &= ~value; -+ omap_dispc_interrupt_update(s); -+ break; -+ -+ case 0x01c: /* DISPC_IRQENABLE */ -+ s->dispc.irqen = value & 0xffff; -+ omap_dispc_interrupt_update(s); -+ break; -+ -+ case 0x040: /* DISPC_CONTROL */ -+ s->dispc.control = value & 0x07ff9fff; -+ s->dig.enable = (value >> 1) & 1; -+ s->lcd.enable = (value >> 0) & 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 " -+ "region effectively exists leads to " -+ "unpredictable behaviour!\n", __FUNCTION__); -+ if (value & (1 << 6)) { /* GODIGITAL */ -+ //// Shadows: -+ //// s->dispc.config -+ //// s->dispc.capable -+ //// s->dispc.bg[0] -+ //// s->dispc.bg[1] -+ //// s->dispc.trans[0] -+ //// s->dispc.trans[1] -+ //// s->dispc.line -+ //// s->dispc.timing[0] -+ //// s->dispc.timing[1] -+ //// s->dispc.timing[2] -+ //// s->dispc.timing[3] -+ //// s->lcd.nx -+ //// s->lcd.ny -+ //// s->dig.nx -+ //// s->dig.ny -+ //// s->dispc.l[0].addr[0] -+ //// s->dispc.l[0].addr[1] -+ //// s->dispc.l[0].addr[2] -+ //// s->dispc.l[0].posx -+ //// s->dispc.l[0].posy -+ //// s->dispc.l[0].nx -+ //// s->dispc.l[0].ny -+ //// s->dispc.l[0].tresh -+ //// s->dispc.l[0].rowinc -+ //// s->dispc.l[0].colinc -+ //// s->dispc.l[0].wininc -+ } -+ if (value & (1 << 5)) { /* GOLCD */ -+ } -+ s->dispc.invalidate = 1; -+ break; -+ -+ case 0x044: /* DISPC_CONFIG */ -+ s->dispc.config = value & 0x3fff; -+ //// bits 2:1 (LOADMODE) reset to 0 after set to 1 and palette loaded -+ //// bits 2:1 (LOADMODE) reset to 2 after set to 3 and palette loaded -+ s->dispc.invalidate = 1; -+ break; -+ -+ case 0x048: /* DISPC_CAPABLE */ -+ s->dispc.capable = value & 0x3ff; -+ break; -+ -+ case 0x04c: /* DISPC_DEFAULT_COLOR0 */ -+ s->dispc.bg[0] = value & 0xffffff; -+ s->dispc.invalidate = 1; -+ break; -+ case 0x050: /* DISPC_DEFAULT_COLOR1 */ -+ s->dispc.bg[1] = value & 0xffffff; -+ s->dispc.invalidate = 1; -+ break; -+ case 0x054: /* DISPC_TRANS_COLOR0 */ -+ s->dispc.trans[0] = value & 0xffffff; -+ s->dispc.invalidate = 1; -+ break; -+ case 0x058: /* DISPC_TRANS_COLOR1 */ -+ s->dispc.trans[1] = value & 0xffffff; -+ s->dispc.invalidate = 1; -+ break; -+ -+ case 0x060: /* DISPC_LINE_NUMBER */ -+ s->dispc.line = value & 0x7ff; -+ break; -+ -+ case 0x064: /* DISPC_TIMING_H */ -+ s->dispc.timing[0] = value & 0x0ff0ff3f; -+ break; -+ case 0x068: /* DISPC_TIMING_V */ -+ s->dispc.timing[1] = value & 0x0ff0ff3f; -+ break; -+ case 0x06c: /* DISPC_POL_FREQ */ -+ s->dispc.timing[2] = value & 0x0003ffff; -+ break; -+ case 0x070: /* DISPC_DIVISOR */ -+ s->dispc.timing[3] = value & 0x00ff00ff; -+ break; -+ -+ case 0x078: /* DISPC_SIZE_DIG */ -+ s->dig.nx = ((value >> 0) & 0x7ff) + 1; /* PPL */ -+ s->dig.ny = ((value >> 16) & 0x7ff) + 1; /* LPP */ -+ s->dispc.invalidate = 1; -+ break; -+ case 0x07c: /* DISPC_SIZE_LCD */ -+ s->lcd.nx = ((value >> 0) & 0x7ff) + 1; /* PPL */ -+ s->lcd.ny = ((value >> 16) & 0x7ff) + 1; /* LPP */ -+ s->dispc.invalidate = 1; -+ break; -+ case 0x080: /* DISPC_GFX_BA0 */ -+ s->dispc.l[0].addr[0] = (target_phys_addr_t) value; -+ s->dispc.invalidate = 1; -+ break; -+ case 0x084: /* DISPC_GFX_BA1 */ -+ s->dispc.l[0].addr[1] = (target_phys_addr_t) value; -+ s->dispc.invalidate = 1; -+ break; -+ case 0x088: /* DISPC_GFX_POSITION */ -+ s->dispc.l[0].posx = ((value >> 0) & 0x7ff); /* GFXPOSX */ -+ s->dispc.l[0].posy = ((value >> 16) & 0x7ff); /* GFXPOSY */ -+ s->dispc.invalidate = 1; -+ break; -+ case 0x08c: /* DISPC_GFX_SIZE */ -+ s->dispc.l[0].nx = ((value >> 0) & 0x7ff) + 1; /* GFXSIZEX */ -+ s->dispc.l[0].ny = ((value >> 16) & 0x7ff) + 1; /* GFXSIZEY */ -+ s->dispc.invalidate = 1; -+ break; -+ case 0x0a0: /* DISPC_GFX_ATTRIBUTES */ -+ s->dispc.l[0].attr = value & 0x7ff; -+ 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.invalidate = 1; -+ break; -+ case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */ -+ s->dispc.l[0].tresh = value & 0x01ff01ff; -+ break; -+ case 0x0ac: /* DISPC_GFX_ROW_INC */ -+ s->dispc.l[0].rowinc = value; -+ s->dispc.invalidate = 1; -+ break; -+ case 0x0b0: /* DISPC_GFX_PIXEL_INC */ -+ s->dispc.l[0].colinc = value; -+ s->dispc.invalidate = 1; -+ break; -+ case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */ -+ s->dispc.l[0].wininc = value; -+ break; -+ case 0x0b8: /* DISPC_GFX_TABLE_BA */ -+ s->dispc.l[0].addr[2] = (target_phys_addr_t) value; -+ s->dispc.invalidate = 1; -+ break; -+ -+ case 0x0bc: /* DISPC_VID1_BA0 */ -+ case 0x0c0: /* DISPC_VID1_BA1 */ -+ case 0x0c4: /* DISPC_VID1_POSITION */ -+ case 0x0c8: /* DISPC_VID1_SIZE */ -+ case 0x0cc: /* DISPC_VID1_ATTRIBUTES */ -+ case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */ -+ case 0x0d8: /* DISPC_VID1_ROW_INC */ -+ case 0x0dc: /* DISPC_VID1_PIXEL_INC */ -+ case 0x0e0: /* DISPC_VID1_FIR */ -+ case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */ -+ case 0x0e8: /* DISPC_VID1_ACCU0 */ -+ case 0x0ec: /* DISPC_VID1_ACCU1 */ -+ case 0x0f0 ... 0x140: /* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */ -+ case 0x14c: /* DISPC_VID2_BA0 */ -+ case 0x150: /* DISPC_VID2_BA1 */ -+ case 0x154: /* DISPC_VID2_POSITION */ -+ case 0x158: /* DISPC_VID2_SIZE */ -+ case 0x15c: /* DISPC_VID2_ATTRIBUTES */ -+ case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */ -+ case 0x168: /* DISPC_VID2_ROW_INC */ -+ case 0x16c: /* DISPC_VID2_PIXEL_INC */ -+ case 0x170: /* DISPC_VID2_FIR */ -+ case 0x174: /* DISPC_VID2_PICTURE_SIZE */ -+ case 0x178: /* DISPC_VID2_ACCU0 */ -+ case 0x17c: /* DISPC_VID2_ACCU1 */ -+ case 0x180 ... 0x1d0: /* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */ -+ case 0x1d4: /* DISPC_DATA_CYCLE1 */ -+ case 0x1d8: /* DISPC_DATA_CYCLE2 */ -+ case 0x1dc: /* DISPC_DATA_CYCLE3 */ -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ } -+} -+ -+static CPUReadMemoryFunc *omap_disc1_readfn[] = { -+ omap_badwidth_read32, -+ omap_badwidth_read32, -+ omap_disc_read, -+}; -+ -+static CPUWriteMemoryFunc *omap_disc1_writefn[] = { -+ omap_badwidth_write32, -+ omap_badwidth_write32, -+ omap_disc_write, -+}; -+ -+static void *omap_rfbi_get_buffer(struct omap_dss_s *s) -+{ -+ target_phys_addr_t fb; -+ uint32_t pd; -+ -+ /* TODO */ -+ fb = s->dispc.l[0].addr[0]; -+ -+ pd = cpu_get_physical_page_desc(fb); -+ if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) -+ /* TODO */ -+ cpu_abort(cpu_single_env, "%s: framebuffer outside RAM!\n", -+ __FUNCTION__); -+ else -+ return phys_ram_base + -+ (pd & TARGET_PAGE_MASK) + -+ (fb & ~TARGET_PAGE_MASK); -+} -+ -+static void omap_rfbi_transfer_stop(struct omap_dss_s *s) -+{ -+ if (!s->rfbi.busy) -+ return; -+ -+ /* TODO: in non-Bypass mode we probably need to just deassert the DRQ. */ -+ -+ s->rfbi.busy = 0; -+} -+ -+static void omap_rfbi_transfer_start(struct omap_dss_s *s) -+{ -+ void *data; -+ size_t len; -+ int pitch; -+ -+ if (!s->rfbi.enable || s->rfbi.busy) -+ return; -+ -+ if (s->rfbi.control & (1 << 1)) { /* BYPASS */ -+ /* TODO: in non-Bypass mode we probably need to just assert the -+ * DRQ and wait for DMA to write the pixels. */ -+ fprintf(stderr, "%s: Bypass mode unimplemented\n", __FUNCTION__); -+ return; -+ } -+ -+ if (!(s->dispc.control & (1 << 11))) /* RFBIMODE */ -+ return; -+ /* TODO: check that LCD output is enabled in DISPC. */ -+ -+ s->rfbi.busy = 1; -+ -+ data = omap_rfbi_get_buffer(s); -+ -+ /* TODO bpp */ -+ len = s->rfbi.pixels * 2; -+ s->rfbi.pixels = 0; -+ -+ /* TODO: negative values */ -+ pitch = s->dispc.l[0].nx + (s->dispc.l[0].rowinc - 1) / 2; -+ -+ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) -+ s->rfbi.chip[0]->block(s->rfbi.chip[0]->opaque, 1, data, len, pitch); -+ if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) -+ s->rfbi.chip[1]->block(s->rfbi.chip[1]->opaque, 1, data, len, pitch); -+ -+ omap_rfbi_transfer_stop(s); -+ -+ /* TODO */ -+ s->dispc.irqst |= 1; /* FRAMEDONE */ -+ omap_dispc_interrupt_update(s); -+} -+ -+static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_dss_s *s = (struct omap_dss_s *) opaque; -+ int offset = addr - s->rfbi_base; -+ -+ switch (offset) { -+ case 0x00: /* RFBI_REVISION */ -+ return 0x10; -+ -+ case 0x10: /* RFBI_SYSCONFIG */ -+ return s->rfbi.idlemode; -+ -+ case 0x14: /* RFBI_SYSSTATUS */ -+ return 1 | (s->rfbi.busy << 8); /* RESETDONE */ -+ -+ case 0x40: /* RFBI_CONTROL */ -+ return s->rfbi.control; -+ -+ case 0x44: /* RFBI_PIXELCNT */ -+ return s->rfbi.pixels; -+ -+ case 0x48: /* RFBI_LINE_NUMBER */ -+ return s->rfbi.skiplines; -+ -+ case 0x58: /* RFBI_READ */ -+ case 0x5c: /* RFBI_STATUS */ -+ return s->rfbi.rxbuf; -+ -+ case 0x60: /* RFBI_CONFIG0 */ -+ return s->rfbi.config[0]; -+ case 0x64: /* RFBI_ONOFF_TIME0 */ -+ return s->rfbi.time[0]; -+ case 0x68: /* RFBI_CYCLE_TIME0 */ -+ return s->rfbi.time[1]; -+ case 0x6c: /* RFBI_DATA_CYCLE1_0 */ -+ return s->rfbi.data[0]; -+ case 0x70: /* RFBI_DATA_CYCLE2_0 */ -+ return s->rfbi.data[1]; -+ case 0x74: /* RFBI_DATA_CYCLE3_0 */ -+ return s->rfbi.data[2]; -+ -+ case 0x78: /* RFBI_CONFIG1 */ -+ return s->rfbi.config[1]; -+ case 0x7c: /* RFBI_ONOFF_TIME1 */ -+ return s->rfbi.time[2]; -+ case 0x80: /* RFBI_CYCLE_TIME1 */ -+ return s->rfbi.time[3]; -+ case 0x84: /* RFBI_DATA_CYCLE1_1 */ -+ return s->rfbi.data[3]; -+ case 0x88: /* RFBI_DATA_CYCLE2_1 */ -+ return s->rfbi.data[4]; -+ case 0x8c: /* RFBI_DATA_CYCLE3_1 */ -+ return s->rfbi.data[5]; -+ -+ case 0x90: /* RFBI_VSYNC_WIDTH */ -+ return s->rfbi.vsync; -+ case 0x94: /* RFBI_HSYNC_WIDTH */ -+ return s->rfbi.hsync; -+ } -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap_rfbi_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_dss_s *s = (struct omap_dss_s *) opaque; -+ int offset = addr - s->rfbi_base; -+ -+ switch (offset) { -+ case 0x10: /* RFBI_SYSCONFIG */ -+ if (value & 2) /* SOFTRESET */ -+ omap_rfbi_reset(s); -+ s->rfbi.idlemode = value & 0x19; -+ break; -+ -+ case 0x40: /* RFBI_CONTROL */ -+ s->rfbi.control = value & 0xf; -+ s->rfbi.enable = value & 1; -+ if (value & (1 << 4) && /* ITE */ -+ !(s->rfbi.config[0] & s->rfbi.config[1] & 0xc)) -+ omap_rfbi_transfer_start(s); -+ break; -+ -+ case 0x44: /* RFBI_PIXELCNT */ -+ s->rfbi.pixels = value; -+ break; -+ -+ case 0x48: /* RFBI_LINE_NUMBER */ -+ s->rfbi.skiplines = value & 0x7ff; -+ break; -+ -+ case 0x4c: /* RFBI_CMD */ -+ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) -+ s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 0, value & 0xffff); -+ if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) -+ s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 0, value & 0xffff); -+ break; -+ case 0x50: /* RFBI_PARAM */ -+ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) -+ s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff); -+ if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) -+ s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff); -+ break; -+ case 0x54: /* RFBI_DATA */ -+ /* TODO: take into account the format set up in s->rfbi.config[?] and -+ * s->rfbi.data[?], but special-case the most usual scenario so that -+ * speed doesn't suffer. */ -+ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) { -+ s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff); -+ s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value >> 16); -+ } -+ if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) { -+ s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff); -+ s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value >> 16); -+ } -+ if (!-- s->rfbi.pixels) -+ omap_rfbi_transfer_stop(s); -+ break; -+ case 0x58: /* RFBI_READ */ -+ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) -+ s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1); -+ else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) -+ s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1); -+ if (!-- s->rfbi.pixels) -+ omap_rfbi_transfer_stop(s); -+ break; -+ -+ case 0x5c: /* RFBI_STATUS */ -+ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) -+ s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0); -+ else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) -+ s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0); -+ if (!-- s->rfbi.pixels) -+ omap_rfbi_transfer_stop(s); -+ break; -+ -+ case 0x60: /* RFBI_CONFIG0 */ -+ s->rfbi.config[0] = value & 0x003f1fff; -+ break; -+ -+ case 0x64: /* RFBI_ONOFF_TIME0 */ -+ s->rfbi.time[0] = value & 0x3fffffff; -+ break; -+ case 0x68: /* RFBI_CYCLE_TIME0 */ -+ s->rfbi.time[1] = value & 0x0fffffff; -+ break; -+ case 0x6c: /* RFBI_DATA_CYCLE1_0 */ -+ s->rfbi.data[0] = value & 0x0f1f0f1f; -+ break; -+ case 0x70: /* RFBI_DATA_CYCLE2_0 */ -+ s->rfbi.data[1] = value & 0x0f1f0f1f; -+ break; -+ case 0x74: /* RFBI_DATA_CYCLE3_0 */ -+ s->rfbi.data[2] = value & 0x0f1f0f1f; -+ break; -+ case 0x78: /* RFBI_CONFIG1 */ -+ s->rfbi.config[1] = value & 0x003f1fff; -+ break; -+ -+ case 0x7c: /* RFBI_ONOFF_TIME1 */ -+ s->rfbi.time[2] = value & 0x3fffffff; -+ break; -+ case 0x80: /* RFBI_CYCLE_TIME1 */ -+ s->rfbi.time[3] = value & 0x0fffffff; -+ break; -+ case 0x84: /* RFBI_DATA_CYCLE1_1 */ -+ s->rfbi.data[3] = value & 0x0f1f0f1f; -+ break; -+ case 0x88: /* RFBI_DATA_CYCLE2_1 */ -+ s->rfbi.data[4] = value & 0x0f1f0f1f; -+ break; -+ case 0x8c: /* RFBI_DATA_CYCLE3_1 */ -+ s->rfbi.data[5] = value & 0x0f1f0f1f; -+ break; -+ -+ case 0x90: /* RFBI_VSYNC_WIDTH */ -+ s->rfbi.vsync = value & 0xffff; -+ break; -+ case 0x94: /* RFBI_HSYNC_WIDTH */ -+ s->rfbi.hsync = value & 0xffff; -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ } -+} -+ -+static CPUReadMemoryFunc *omap_rfbi1_readfn[] = { -+ omap_badwidth_read32, -+ omap_badwidth_read32, -+ omap_rfbi_read, -+}; -+ -+static CPUWriteMemoryFunc *omap_rfbi1_writefn[] = { -+ omap_badwidth_write32, -+ omap_badwidth_write32, -+ omap_rfbi_write, -+}; -+ -+static uint32_t omap_venc_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_dss_s *s = (struct omap_dss_s *) opaque; -+ int offset = addr - s->venc_base; -+ -+ switch (offset) { -+ case 0x00: /* REV_ID */ -+ case 0x04: /* STATUS */ -+ case 0x08: /* F_CONTROL */ -+ case 0x10: /* VIDOUT_CTRL */ -+ case 0x14: /* SYNC_CTRL */ -+ case 0x1c: /* LLEN */ -+ case 0x20: /* FLENS */ -+ case 0x24: /* HFLTR_CTRL */ -+ case 0x28: /* CC_CARR_WSS_CARR */ -+ case 0x2c: /* C_PHASE */ -+ case 0x30: /* GAIN_U */ -+ case 0x34: /* GAIN_V */ -+ case 0x38: /* GAIN_Y */ -+ case 0x3c: /* BLACK_LEVEL */ -+ case 0x40: /* BLANK_LEVEL */ -+ case 0x44: /* X_COLOR */ -+ case 0x48: /* M_CONTROL */ -+ case 0x4c: /* BSTAMP_WSS_DATA */ -+ case 0x50: /* S_CARR */ -+ case 0x54: /* LINE21 */ -+ case 0x58: /* LN_SEL */ -+ case 0x5c: /* L21__WC_CTL */ -+ case 0x60: /* HTRIGGER_VTRIGGER */ -+ case 0x64: /* SAVID__EAVID */ -+ case 0x68: /* FLEN__FAL */ -+ case 0x6c: /* LAL__PHASE_RESET */ -+ case 0x70: /* HS_INT_START_STOP_X */ -+ case 0x74: /* HS_EXT_START_STOP_X */ -+ case 0x78: /* VS_INT_START_X */ -+ case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */ -+ case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */ -+ case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */ -+ case 0x88: /* VS_EXT_STOP_Y */ -+ case 0x90: /* AVID_START_STOP_X */ -+ case 0x94: /* AVID_START_STOP_Y */ -+ case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */ -+ case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */ -+ case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */ -+ case 0xb0: /* TVDETGP_INT_START_STOP_X */ -+ case 0xb4: /* TVDETGP_INT_START_STOP_Y */ -+ case 0xb8: /* GEN_CTRL */ -+ case 0xc4: /* DAC_TST__DAC_A */ -+ case 0xc8: /* DAC_B__DAC_C */ -+ return 0; -+ -+ default: -+ break; -+ } -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap_venc_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_dss_s *s = (struct omap_dss_s *) opaque; -+ int offset = addr - s->venc_base; -+ -+ switch (offset) { -+ case 0x08: /* F_CONTROL */ -+ case 0x10: /* VIDOUT_CTRL */ -+ case 0x14: /* SYNC_CTRL */ -+ case 0x1c: /* LLEN */ -+ case 0x20: /* FLENS */ -+ case 0x24: /* HFLTR_CTRL */ -+ case 0x28: /* CC_CARR_WSS_CARR */ -+ case 0x2c: /* C_PHASE */ -+ case 0x30: /* GAIN_U */ -+ case 0x34: /* GAIN_V */ -+ case 0x38: /* GAIN_Y */ -+ case 0x3c: /* BLACK_LEVEL */ -+ case 0x40: /* BLANK_LEVEL */ -+ case 0x44: /* X_COLOR */ -+ case 0x48: /* M_CONTROL */ -+ case 0x4c: /* BSTAMP_WSS_DATA */ -+ case 0x50: /* S_CARR */ -+ case 0x54: /* LINE21 */ -+ case 0x58: /* LN_SEL */ -+ case 0x5c: /* L21__WC_CTL */ -+ case 0x60: /* HTRIGGER_VTRIGGER */ -+ case 0x64: /* SAVID__EAVID */ -+ case 0x68: /* FLEN__FAL */ -+ case 0x6c: /* LAL__PHASE_RESET */ -+ case 0x70: /* HS_INT_START_STOP_X */ -+ case 0x74: /* HS_EXT_START_STOP_X */ -+ case 0x78: /* VS_INT_START_X */ -+ case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */ -+ case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */ -+ case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */ -+ case 0x88: /* VS_EXT_STOP_Y */ -+ case 0x90: /* AVID_START_STOP_X */ -+ case 0x94: /* AVID_START_STOP_Y */ -+ case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */ -+ case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */ -+ case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */ -+ case 0xb0: /* TVDETGP_INT_START_STOP_X */ -+ case 0xb4: /* TVDETGP_INT_START_STOP_Y */ -+ case 0xb8: /* GEN_CTRL */ -+ case 0xc4: /* DAC_TST__DAC_A */ -+ case 0xc8: /* DAC_B__DAC_C */ -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ } -+} -+ -+static CPUReadMemoryFunc *omap_venc1_readfn[] = { -+ omap_badwidth_read32, -+ omap_badwidth_read32, -+ omap_venc_read, -+}; -+ -+static CPUWriteMemoryFunc *omap_venc1_writefn[] = { -+ omap_badwidth_write32, -+ omap_badwidth_write32, -+ omap_venc_write, -+}; -+ -+static uint32_t omap_im3_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct omap_dss_s *s = (struct omap_dss_s *) opaque; -+ int offset = addr - s->im3_base; -+ -+ switch (offset) { -+ case 0x0a8: /* SBIMERRLOGA */ -+ case 0x0b0: /* SBIMERRLOG */ -+ case 0x190: /* SBIMSTATE */ -+ case 0x198: /* SBTMSTATE_L */ -+ case 0x19c: /* SBTMSTATE_H */ -+ case 0x1a8: /* SBIMCONFIG_L */ -+ case 0x1ac: /* SBIMCONFIG_H */ -+ case 0x1f8: /* SBID_L */ -+ case 0x1fc: /* SBID_H */ -+ return 0; -+ -+ default: -+ break; -+ } -+ OMAP_BAD_REG(addr); -+ return 0; -+} -+ -+static void omap_im3_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct omap_dss_s *s = (struct omap_dss_s *) opaque; -+ int offset = addr - s->im3_base; -+ -+ switch (offset) { -+ case 0x0b0: /* SBIMERRLOG */ -+ case 0x190: /* SBIMSTATE */ -+ case 0x198: /* SBTMSTATE_L */ -+ case 0x19c: /* SBTMSTATE_H */ -+ case 0x1a8: /* SBIMCONFIG_L */ -+ case 0x1ac: /* SBIMCONFIG_H */ -+ break; -+ -+ default: -+ OMAP_BAD_REG(addr); -+ } -+} -+ -+static CPUReadMemoryFunc *omap_im3_readfn[] = { -+ omap_badwidth_read32, -+ omap_badwidth_read32, -+ omap_im3_read, -+}; -+ -+static CPUWriteMemoryFunc *omap_im3_writefn[] = { -+ omap_badwidth_write32, -+ omap_badwidth_write32, -+ omap_im3_write, -+}; -+ -+struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta, -+ target_phys_addr_t l3_base, DisplayState *ds, -+ qemu_irq irq, qemu_irq drq, -+ omap_clk fck1, omap_clk fck2, omap_clk ck54m, -+ omap_clk ick1, omap_clk ick2) -+{ -+ int iomemtype[5]; -+ struct omap_dss_s *s = (struct omap_dss_s *) -+ qemu_mallocz(sizeof(struct omap_dss_s)); -+ -+ s->irq = irq; -+ s->drq = drq; -+ s->state = ds; -+ omap_dss_reset(s); -+ -+ iomemtype[0] = cpu_register_io_memory(0, omap_diss1_readfn, -+ omap_diss1_writefn, s); -+ iomemtype[1] = cpu_register_io_memory(0, omap_disc1_readfn, -+ omap_disc1_writefn, s); -+ iomemtype[2] = cpu_register_io_memory(0, omap_rfbi1_readfn, -+ omap_rfbi1_writefn, s); -+ iomemtype[3] = cpu_register_io_memory(0, omap_venc1_readfn, -+ omap_venc1_writefn, s); -+ iomemtype[4] = cpu_register_io_memory(0, omap_im3_readfn, -+ omap_im3_writefn, s); -+ s->diss_base = omap_l4_attach(ta, 0, iomemtype[0]); -+ s->disc_base = omap_l4_attach(ta, 1, iomemtype[1]); -+ s->rfbi_base = omap_l4_attach(ta, 2, iomemtype[2]); -+ s->venc_base = omap_l4_attach(ta, 3, iomemtype[3]); -+ s->im3_base = l3_base; -+ cpu_register_physical_memory(s->im3_base, 0x1000, iomemtype[4]); -+ -+#if 0 -+ if (ds) -+ graphic_console_init(ds, omap_update_display, -+ omap_invalidate_display, omap_screen_dump, s); -+#endif -+ -+ return s; -+} -+ -+void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip) -+{ -+ if (cs < 0 || cs > 1) -+ cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs); -+ s->rfbi.chip[cs] = chip; -+} -diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c -index de63309..9915676 100644 ---- a/hw/omap_i2c.c -+++ b/hw/omap_i2c.c -@@ -150,6 +150,8 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s) - } - 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 */ -@@ -161,6 +163,8 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s) - } - if (s->rxlen) - s->stat |= 1 << 3; /* RRDY */ -+ else -+ s->stat &= ~(1 << 3); /* RRDY */ - } - if (!s->count_cur) { - if ((s->control >> 1) & 1) { /* STP */ -@@ -321,7 +325,8 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr, - return; - } - -- s->stat &= ~(value & 0x3f); -+ /* RRDY and XRDY are reset by hardware. (in all versions???) */ -+ s->stat &= ~(value & 0x27); - omap_i2c_interrupts_update(s); - break; - -@@ -376,11 +381,13 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr, - break; - } - if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */ -- printf("%s: I^2C slave mode not supported\n", __FUNCTION__); -+ fprintf(stderr, "%s: I^2C slave mode not supported\n", -+ __FUNCTION__); - break; - } - if ((value & (1 << 15)) && value & (1 << 8)) { /* XA */ -- printf("%s: 10-bit addressing mode not supported\n", __FUNCTION__); -+ fprintf(stderr, "%s: 10-bit addressing mode not supported\n", -+ __FUNCTION__); - break; - } - if ((value & (1 << 15)) && value & (1 << 0)) { /* STT */ -@@ -427,7 +434,7 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr, - omap_i2c_interrupts_update(s); - } - if (value & (1 << 15)) /* ST_EN */ -- printf("%s: System Test not supported\n", __FUNCTION__); -+ fprintf(stderr, "%s: System Test not supported\n", __FUNCTION__); - break; - - default: -diff --git a/hw/omap_mmc.c b/hw/omap_mmc.c -index 6fbbb84..e46289a 100644 ---- a/hw/omap_mmc.c -+++ b/hw/omap_mmc.c -@@ -26,19 +26,24 @@ struct omap_mmc_s { - target_phys_addr_t base; - qemu_irq irq; - qemu_irq *dma; -+ qemu_irq coverswitch; - omap_clk clk; - SDState *card; - uint16_t last_cmd; - uint16_t sdio; - uint16_t rsp[8]; - uint32_t arg; -+ int lines; - int dw; - int mode; - int enable; -+ int be; -+ int rev; - uint16_t status; - uint16_t mask; - uint8_t cto; - uint16_t dto; -+ int clkdiv; - uint16_t fifo[32]; - int fifo_start; - int fifo_len; -@@ -53,6 +58,11 @@ struct omap_mmc_s { - - int ddir; - int transfer; -+ -+ int cdet_wakeup; -+ int cdet_enable; -+ int cdet_state; -+ qemu_irq cdet; - }; - - static void omap_mmc_interrupts_update(struct omap_mmc_s *s) -@@ -107,6 +117,11 @@ static void omap_mmc_command(struct omap_mmc_s *host, int cmd, int dir, - struct sd_request_s request; - uint8_t response[16]; - -+ if (init && cmd == 0) { -+ host->status |= 0x0001; -+ return; -+ } -+ - if (resptype == sd_r1 && busy) - resptype = sd_r1b; - -@@ -265,6 +280,34 @@ static void omap_mmc_update(void *opaque) - omap_mmc_interrupts_update(s); - } - -+void omap_mmc_reset(struct omap_mmc_s *host) -+{ -+ host->last_cmd = 0; -+ memset(host->rsp, 0, sizeof(host->rsp)); -+ host->arg = 0; -+ host->dw = 0; -+ host->mode = 0; -+ host->enable = 0; -+ host->status = 0; -+ host->mask = 0; -+ host->cto = 0; -+ host->dto = 0; -+ host->fifo_len = 0; -+ host->blen = 0; -+ host->blen_counter = 0; -+ host->nblk = 0; -+ host->nblk_counter = 0; -+ host->tx_dma = 0; -+ host->rx_dma = 0; -+ host->ae_level = 0x00; -+ host->af_level = 0x1f; -+ host->transfer = 0; -+ host->cdet_wakeup = 0; -+ host->cdet_enable = 0; -+ qemu_set_irq(host->coverswitch, host->cdet_state); -+ host->clkdiv = 0; -+} -+ - static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset) - { - uint16_t i; -@@ -282,7 +325,8 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset) - return s->arg >> 16; - - case 0x0c: /* MMC_CON */ -- return (s->dw << 15) | (s->mode << 12) | (s->enable << 11); -+ return (s->dw << 15) | (s->mode << 12) | (s->enable << 11) | -+ (s->be << 10) | s->clkdiv; - - case 0x10: /* MMC_STAT */ - return s->status; -@@ -324,12 +368,12 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset) - case 0x30: /* MMC_SPI */ - return 0x0000; - case 0x34: /* MMC_SDIO */ -- return s->sdio; -+ return (s->cdet_wakeup << 2) | (s->cdet_enable) | s->sdio; - case 0x38: /* MMC_SYST */ - return 0x0000; - - case 0x3c: /* MMC_REV */ -- return 0x0001; -+ return s->rev; - - case 0x40: /* MMC_RSP0 */ - case 0x44: /* MMC_RSP1 */ -@@ -340,6 +384,13 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset) - case 0x58: /* MMC_RSP6 */ - case 0x5c: /* MMC_RSP7 */ - return s->rsp[(offset - 0x40) >> 2]; -+ -+ /* OMAP2-specific */ -+ case 0x60: /* MMC_IOSR */ -+ case 0x64: /* MMC_SYSC */ -+ return 0; -+ case 0x68: /* MMC_SYSS */ -+ return 1; /* RSTD */ - } - - OMAP_BAD_REG(offset); -@@ -383,10 +434,16 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset, - s->dw = (value >> 15) & 1; - s->mode = (value >> 12) & 3; - s->enable = (value >> 11) & 1; -+ s->be = (value >> 10) & 1; -+ s->clkdiv = (value >> 0) & (s->rev >= 2 ? 0x3ff : 0xff); - if (s->mode != 0) - printf("SD mode %i unimplemented!\n", s->mode); -- if (s->dw != 0) -+ if (s->be != 0) -+ printf("SD FIFO byte sex unimplemented!\n"); -+ if (s->dw != 0 && s->lines < 4) - printf("4-bit SD bus enabled\n"); -+ if (!s->enable) -+ omap_mmc_reset(s); - break; - - case 0x10: /* MMC_STAT */ -@@ -395,13 +452,13 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset, - break; - - case 0x14: /* MMC_IE */ -- s->mask = value; -+ s->mask = value & 0x7fff; - omap_mmc_interrupts_update(s); - break; - - case 0x18: /* MMC_CTO */ - s->cto = value & 0xff; -- if (s->cto > 0xfd) -+ if (s->cto > 0xfd && s->rev <= 1) - printf("MMC: CTO of 0xff and 0xfe cannot be used!\n"); - break; - -@@ -446,10 +503,12 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset, - break; - - /* SPI, SDIO and TEST modes unimplemented */ -- case 0x30: /* MMC_SPI */ -+ case 0x30: /* MMC_SPI (OMAP1 only) */ - break; - case 0x34: /* MMC_SDIO */ -- s->sdio = value & 0x2020; -+ s->sdio = value & (s->rev >= 2 ? 0xfbf3 : 0x2020); -+ s->cdet_wakeup = (value >> 9) & 1; -+ s->cdet_enable = (value >> 2) & 1; - break; - case 0x38: /* MMC_SYST */ - break; -@@ -466,6 +525,19 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset, - OMAP_RO_REG(offset); - break; - -+ /* OMAP2-specific */ -+ case 0x60: /* MMC_IOSR */ -+ if (value & 0xf) -+ printf("MMC: SDIO bits used!\n"); -+ break; -+ case 0x64: /* MMC_SYSC */ -+ if (value & (1 << 2)) /* SRTS */ -+ omap_mmc_reset(s); -+ break; -+ case 0x68: /* MMC_SYSS */ -+ OMAP_RO_REG(offset); -+ break; -+ - default: - OMAP_BAD_REG(offset); - } -@@ -483,28 +555,21 @@ static CPUWriteMemoryFunc *omap_mmc_writefn[] = { - omap_badwidth_write16, - }; - --void omap_mmc_reset(struct omap_mmc_s *host) -+static void omap_mmc_cover_cb(void *opaque, int line, int level) - { -- host->last_cmd = 0; -- memset(host->rsp, 0, sizeof(host->rsp)); -- host->arg = 0; -- host->dw = 0; -- host->mode = 0; -- host->enable = 0; -- host->status = 0; -- host->mask = 0; -- host->cto = 0; -- host->dto = 0; -- host->fifo_len = 0; -- host->blen = 0; -- host->blen_counter = 0; -- host->nblk = 0; -- host->nblk_counter = 0; -- host->tx_dma = 0; -- host->rx_dma = 0; -- host->ae_level = 0x00; -- host->af_level = 0x1f; -- host->transfer = 0; -+ struct omap_mmc_s *host = (struct omap_mmc_s *) opaque; -+ -+ if (!host->cdet_state && level) { -+ host->status |= 0x0002; -+ omap_mmc_interrupts_update(host); -+ if (host->cdet_wakeup) -+ /* TODO: Assert wake-up */; -+ } -+ -+ if (host->cdet_state != level) { -+ qemu_set_irq(host->coverswitch, level); -+ host->cdet_state = level; -+ } - } - - struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base, -@@ -519,6 +584,10 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base, - s->base = base; - s->dma = dma; - s->clk = clk; -+ s->lines = 1; /* TODO: needs to be settable per-board */ -+ s->rev = 1; -+ -+ omap_mmc_reset(s); - - iomemtype = cpu_register_io_memory(0, omap_mmc_readfn, - omap_mmc_writefn, s); -@@ -530,7 +599,46 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base, - return s; - } - -+struct omap_mmc_s *omap2_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 omap_mmc_s *s = (struct omap_mmc_s *) -+ qemu_mallocz(sizeof(struct omap_mmc_s)); -+ -+ s->irq = irq; -+ s->dma = dma; -+ s->clk = fclk; -+ s->lines = 4; -+ s->rev = 2; -+ -+ omap_mmc_reset(s); -+ -+ iomemtype = cpu_register_io_memory(0, omap_mmc_readfn, -+ omap_mmc_writefn, s); -+ s->base = omap_l4_attach(ta, 0, iomemtype); -+ -+ /* Instantiate the storage */ -+ s->card = sd_init(bd, 0); -+ -+ s->cdet = qemu_allocate_irqs(omap_mmc_cover_cb, s, 1)[0]; -+ sd_set_cb(s->card, 0, s->cdet); -+ -+ return s; -+} -+ - void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover) - { -- sd_set_cb(s->card, ro, cover); -+ if (s->cdet) { -+ sd_set_cb(s->card, ro, s->cdet); -+ s->coverswitch = cover; -+ qemu_set_irq(cover, s->cdet_state); -+ } else -+ sd_set_cb(s->card, ro, cover); -+} -+ -+void omap_mmc_enable(struct omap_mmc_s *s, int enable) -+{ -+ sd_enable(s->card, enable); - } -diff --git a/hw/onenand.c b/hw/onenand.c -new file mode 100644 -index 0000000..549d392 ---- /dev/null -+++ b/hw/onenand.c -@@ -0,0 +1,642 @@ -+/* -+ * OneNAND flash memories emulation. -+ * -+ * Copyright (C) 2008 Nokia Corporation -+ * Written by Andrzej Zaborowski -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of -+ * the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, -+ * MA 02111-1307 USA -+ */ -+ -+#include "qemu-common.h" -+#include "flash.h" -+#include "irq.h" -+#include "sysemu.h" -+#include "block.h" -+ -+/* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */ -+#define PAGE_SHIFT 11 -+ -+/* Fixed */ -+#define BLOCK_SHIFT (PAGE_SHIFT + 6) -+ -+struct onenand_s { -+ uint32_t id; -+ int shift; -+ target_phys_addr_t base; -+ qemu_irq intr; -+ qemu_irq rdy; -+ BlockDriverState *bdrv; -+ BlockDriverState *bdrv_cur; -+ uint8_t *image; -+ uint8_t *otp; -+ uint8_t *current; -+ ram_addr_t ram; -+ uint8_t *boot[2]; -+ uint8_t *data[2][2]; -+ int iomemtype; -+ int cycle; -+ int otpmode; -+ -+ uint16_t addr[8]; -+ uint16_t unladdr[8]; -+ int bufaddr; -+ int count; -+ uint16_t command; -+ uint16_t config[2]; -+ uint16_t status; -+ uint16_t intstatus; -+ uint16_t wpstatus; -+ -+ struct ecc_state_s ecc; -+ -+ int density_mask; -+ int secs; -+ int secs_cur; -+ int blocks; -+ uint8_t *blockwp; -+}; -+ -+enum { -+ ONEN_BUF_BLOCK = 0, -+ ONEN_BUF_BLOCK2 = 1, -+ ONEN_BUF_DEST_BLOCK = 2, -+ ONEN_BUF_DEST_PAGE = 3, -+ ONEN_BUF_PAGE = 7, -+}; -+ -+enum { -+ ONEN_ERR_CMD = 1 << 10, -+ ONEN_ERR_ERASE = 1 << 11, -+ ONEN_ERR_PROG = 1 << 12, -+ ONEN_ERR_LOAD = 1 << 13, -+}; -+ -+enum { -+ ONEN_INT_RESET = 1 << 4, -+ ONEN_INT_ERASE = 1 << 5, -+ ONEN_INT_PROG = 1 << 6, -+ ONEN_INT_LOAD = 1 << 7, -+ ONEN_INT = 1 << 15, -+}; -+ -+enum { -+ ONEN_LOCK_LOCKTIGHTEN = 1 << 0, -+ ONEN_LOCK_LOCKED = 1 << 1, -+ ONEN_LOCK_UNLOCKED = 1 << 2, -+}; -+ -+void onenand_base_update(void *opaque, target_phys_addr_t new) -+{ -+ struct onenand_s *s = (struct onenand_s *) opaque; -+ -+ s->base = new; -+ -+ /* XXX: We should use IO_MEM_ROMD but we broke it earlier... -+ * Both 0x0000 ... 0x01ff and 0x8000 ... 0x800f can be used to -+ * write boot commands. Also take note of the BWPS bit. */ -+ cpu_register_physical_memory(s->base + (0x0000 << s->shift), -+ 0x0200 << s->shift, s->iomemtype); -+ cpu_register_physical_memory(s->base + (0x0200 << s->shift), -+ 0xbe00 << s->shift, -+ (s->ram +(0x0200 << s->shift)) | IO_MEM_RAM); -+ if (s->iomemtype) -+ cpu_register_physical_memory(s->base + (0xc000 << s->shift), -+ 0x4000 << s->shift, s->iomemtype); -+} -+ -+void onenand_base_unmap(void *opaque) -+{ -+ struct onenand_s *s = (struct onenand_s *) opaque; -+ -+ cpu_register_physical_memory(s->base, -+ 0x10000 << s->shift, IO_MEM_UNASSIGNED); -+} -+ -+static void onenand_intr_update(struct onenand_s *s) -+{ -+ qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1); -+} -+ -+/* Hot reset (Reset OneNAND command) or warm reset (RP pin low) */ -+static void onenand_reset(struct onenand_s *s, int cold) -+{ -+ memset(&s->addr, 0, sizeof(s->addr)); -+ s->command = 0; -+ s->count = 1; -+ s->bufaddr = 0; -+ s->config[0] = 0x40c0; -+ s->config[1] = 0x0000; -+ onenand_intr_update(s); -+ qemu_irq_raise(s->rdy); -+ s->status = 0x0000; -+ s->intstatus = cold ? 0x8080 : 0x8010; -+ s->unladdr[0] = 0; -+ s->unladdr[1] = 0; -+ s->wpstatus = 0x0002; -+ s->cycle = 0; -+ s->otpmode = 0; -+ s->bdrv_cur = s->bdrv; -+ s->current = s->image; -+ s->secs_cur = s->secs; -+ -+ if (cold) { -+ /* Lock the whole flash */ -+ memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks); -+ -+ if (s->bdrv && bdrv_read(s->bdrv, 0, s->boot[0], 8) < 0) -+ cpu_abort(cpu_single_env, "%s: Loading the BootRAM failed.\n", -+ __FUNCTION__); -+ } -+} -+ -+static inline int onenand_load_main(struct onenand_s *s, int sec, int secn, -+ void *dest) -+{ -+ if (s->bdrv_cur) -+ return bdrv_read(s->bdrv_cur, sec, dest, secn) < 0; -+ else if (sec + secn > s->secs_cur) -+ return 1; -+ -+ memcpy(dest, s->current + (sec << 9), secn << 9); -+ -+ return 0; -+} -+ -+static inline int onenand_prog_main(struct onenand_s *s, int sec, int secn, -+ void *src) -+{ -+ if (s->bdrv_cur) -+ return bdrv_write(s->bdrv_cur, sec, src, secn) < 0; -+ else if (sec + secn > s->secs_cur) -+ return 1; -+ -+ memcpy(s->current + (sec << 9), src, secn << 9); -+ -+ return 0; -+} -+ -+static inline int onenand_load_spare(struct onenand_s *s, int sec, int secn, -+ void *dest) -+{ -+ uint8_t buf[512]; -+ -+ if (s->bdrv_cur) { -+ if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0) -+ return 1; -+ memcpy(dest, buf + ((sec & 31) << 4), secn << 4); -+ } else if (sec + secn > s->secs_cur) -+ return 1; -+ else -+ memcpy(dest, s->current + (s->secs_cur << 9) + (sec << 4), secn << 4); -+ -+ return 0; -+} -+ -+static inline int onenand_prog_spare(struct onenand_s *s, int sec, int secn, -+ void *src) -+{ -+ uint8_t buf[512]; -+ -+ if (s->bdrv_cur) { -+ if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0) -+ return 1; -+ memcpy(buf + ((sec & 31) << 4), src, secn << 4); -+ return bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0; -+ } else if (sec + secn > s->secs_cur) -+ return 1; -+ -+ memcpy(s->current + (s->secs_cur << 9) + (sec << 4), src, secn << 4); -+ -+ return 0; -+} -+ -+static inline int onenand_erase(struct onenand_s *s, int sec, int num) -+{ -+ /* TODO: optimise */ -+ uint8_t buf[512]; -+ -+ memset(buf, 0xff, sizeof(buf)); -+ for (; num > 0; num --, sec ++) { -+ if (onenand_prog_main(s, sec, 1, buf)) -+ return 1; -+ if (onenand_prog_spare(s, sec, 1, buf)) -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static void onenand_command(struct onenand_s *s, int cmd) -+{ -+ int b; -+ int sec; -+ void *buf; -+#define SETADDR(block, page) \ -+ sec = (s->addr[page] & 3) + \ -+ ((((s->addr[page] >> 2) & 0x3f) + \ -+ (((s->addr[block] & 0xfff) | \ -+ (s->addr[block] >> 15 ? \ -+ s->density_mask : 0)) << 6)) << (PAGE_SHIFT - 9)); -+#define SETBUF_M() \ -+ buf = (s->bufaddr & 8) ? \ -+ s->data[(s->bufaddr >> 2) & 1][0] : s->boot[0]; \ -+ buf += (s->bufaddr & 3) << 9; -+#define SETBUF_S() \ -+ buf = (s->bufaddr & 8) ? \ -+ s->data[(s->bufaddr >> 2) & 1][1] : s->boot[1]; \ -+ buf += (s->bufaddr & 3) << 4; -+ -+ switch (cmd) { -+ case 0x00: /* Load single/multiple sector data unit into buffer */ -+ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE) -+ -+ SETBUF_M() -+ if (onenand_load_main(s, sec, s->count, buf)) -+ s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD; -+ -+#if 0 -+ SETBUF_S() -+ if (onenand_load_spare(s, sec, s->count, buf)) -+ s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD; -+#endif -+ -+ /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages) -+ * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages) -+ * then we need two split the read/write into two chunks. -+ */ -+ s->intstatus |= ONEN_INT | ONEN_INT_LOAD; -+ break; -+ case 0x13: /* Load single/multiple spare sector into buffer */ -+ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE) -+ -+ SETBUF_S() -+ if (onenand_load_spare(s, sec, s->count, buf)) -+ s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD; -+ -+ /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages) -+ * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages) -+ * then we need two split the read/write into two chunks. -+ */ -+ s->intstatus |= ONEN_INT | ONEN_INT_LOAD; -+ break; -+ case 0x80: /* Program single/multiple sector data unit from buffer */ -+ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE) -+ -+ SETBUF_M() -+ if (onenand_prog_main(s, sec, s->count, buf)) -+ s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG; -+ -+#if 0 -+ SETBUF_S() -+ if (onenand_prog_spare(s, sec, s->count, buf)) -+ s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG; -+#endif -+ -+ /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages) -+ * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages) -+ * then we need two split the read/write into two chunks. -+ */ -+ s->intstatus |= ONEN_INT | ONEN_INT_PROG; -+ break; -+ case 0x1a: /* Program single/multiple spare area sector from buffer */ -+ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE) -+ -+ SETBUF_S() -+ if (onenand_prog_spare(s, sec, s->count, buf)) -+ s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG; -+ -+ /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages) -+ * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages) -+ * then we need two split the read/write into two chunks. -+ */ -+ s->intstatus |= ONEN_INT | ONEN_INT_PROG; -+ break; -+ case 0x1b: /* Copy-back program */ -+ SETBUF_S() -+ -+ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE) -+ if (onenand_load_main(s, sec, s->count, buf)) -+ s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG; -+ -+ SETADDR(ONEN_BUF_DEST_BLOCK, ONEN_BUF_DEST_PAGE) -+ if (onenand_prog_main(s, sec, s->count, buf)) -+ s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG; -+ -+ /* TODO: spare areas */ -+ -+ s->intstatus |= ONEN_INT | ONEN_INT_PROG; -+ break; -+ -+ case 0x23: /* Unlock NAND array block(s) */ -+ s->intstatus |= ONEN_INT; -+ -+ /* XXX the previous (?) area should be locked automatically */ -+ for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) { -+ if (b >= s->blocks) { -+ s->status |= ONEN_ERR_CMD; -+ break; -+ } -+ if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN) -+ break; -+ -+ s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED; -+ } -+ break; -+ case 0x2a: /* Lock NAND array block(s) */ -+ s->intstatus |= ONEN_INT; -+ -+ for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) { -+ if (b >= s->blocks) { -+ s->status |= ONEN_ERR_CMD; -+ break; -+ } -+ if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN) -+ break; -+ -+ s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKED; -+ } -+ break; -+ case 0x2c: /* Lock-tight NAND array block(s) */ -+ s->intstatus |= ONEN_INT; -+ -+ for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) { -+ if (b >= s->blocks) { -+ s->status |= ONEN_ERR_CMD; -+ break; -+ } -+ if (s->blockwp[b] == ONEN_LOCK_UNLOCKED) -+ continue; -+ -+ s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKTIGHTEN; -+ } -+ break; -+ -+ case 0x71: /* Erase-Verify-Read */ -+ s->intstatus |= ONEN_INT; -+ break; -+ case 0x95: /* Multi-block erase */ -+ qemu_irq_pulse(s->intr); -+ /* Fall through. */ -+ case 0x94: /* Block erase */ -+ sec = ((s->addr[ONEN_BUF_BLOCK] & 0xfff) | -+ (s->addr[ONEN_BUF_BLOCK] >> 15 ? s->density_mask : 0)) -+ << (BLOCK_SHIFT - 9); -+ if (onenand_erase(s, sec, 1 << (BLOCK_SHIFT - 9))) -+ s->status |= ONEN_ERR_CMD | ONEN_ERR_ERASE; -+ -+ s->intstatus |= ONEN_INT | ONEN_INT_ERASE; -+ break; -+ case 0xb0: /* Erase suspend */ -+ break; -+ case 0x30: /* Erase resume */ -+ s->intstatus |= ONEN_INT | ONEN_INT_ERASE; -+ break; -+ -+ case 0xf0: /* Reset NAND Flash core */ -+ onenand_reset(s, 0); -+ break; -+ case 0xf3: /* Reset OneNAND */ -+ onenand_reset(s, 0); -+ break; -+ -+ case 0x65: /* OTP Access */ -+ s->intstatus |= ONEN_INT; -+ s->bdrv_cur = 0; -+ s->current = s->otp; -+ s->secs_cur = 1 << (BLOCK_SHIFT - 9); -+ s->addr[ONEN_BUF_BLOCK] = 0; -+ s->otpmode = 1; -+ break; -+ -+ default: -+ s->status |= ONEN_ERR_CMD; -+ s->intstatus |= ONEN_INT; -+ fprintf(stderr, "%s: unknown OneNAND command %x\n", -+ __FUNCTION__, cmd); -+ } -+ -+ onenand_intr_update(s); -+} -+ -+static uint32_t onenand_read(void *opaque, target_phys_addr_t addr) -+{ -+ struct onenand_s *s = (struct onenand_s *) opaque; -+ int offset = (addr - s->base) >> s->shift; -+ -+ switch (offset) { -+ case 0x0000 ... 0xc000: -+ return lduw_le_p(s->boot[0] + (addr - s->base)); -+ -+ case 0xf000: /* Manufacturer ID */ -+ return (s->id >> 16) & 0xff; -+ case 0xf001: /* Device ID */ -+ return (s->id >> 8) & 0xff; -+ /* TODO: get the following values from a real chip! */ -+ case 0xf002: /* Version ID */ -+ return (s->id >> 0) & 0xff; -+ case 0xf003: /* Data Buffer size */ -+ return 1 << PAGE_SHIFT; -+ case 0xf004: /* Boot Buffer size */ -+ return 0x200; -+ case 0xf005: /* Amount of buffers */ -+ return 1 | (2 << 8); -+ case 0xf006: /* Technology */ -+ return 0; -+ -+ case 0xf100 ... 0xf107: /* Start addresses */ -+ return s->addr[offset - 0xf100]; -+ -+ case 0xf200: /* Start buffer */ -+ return (s->bufaddr << 8) | ((s->count - 1) & (1 << (PAGE_SHIFT - 10))); -+ -+ case 0xf220: /* Command */ -+ return s->command; -+ case 0xf221: /* System Configuration 1 */ -+ return s->config[0] & 0xffe0; -+ case 0xf222: /* System Configuration 2 */ -+ return s->config[1]; -+ -+ case 0xf240: /* Controller Status */ -+ return s->status; -+ case 0xf241: /* Interrupt */ -+ return s->intstatus; -+ case 0xf24c: /* Unlock Start Block Address */ -+ return s->unladdr[0]; -+ case 0xf24d: /* Unlock End Block Address */ -+ return s->unladdr[1]; -+ case 0xf24e: /* Write Protection Status */ -+ return s->wpstatus; -+ -+ case 0xff00: /* ECC Status */ -+ return 0x00; -+ case 0xff01: /* ECC Result of main area data */ -+ case 0xff02: /* ECC Result of spare area data */ -+ case 0xff03: /* ECC Result of main area data */ -+ case 0xff04: /* ECC Result of spare area data */ -+ cpu_abort(cpu_single_env, "%s: imeplement ECC\n", __FUNCTION__); -+ return 0x0000; -+ } -+ -+ fprintf(stderr, "%s: unknown OneNAND register %x\n", -+ __FUNCTION__, offset); -+ return 0; -+} -+ -+static void onenand_write(void *opaque, target_phys_addr_t addr, -+ uint32_t value) -+{ -+ struct onenand_s *s = (struct onenand_s *) opaque; -+ int offset = (addr - s->base) >> s->shift; -+ int sec; -+ -+ switch (offset) { -+ case 0x0000 ... 0x01ff: -+ case 0x8000 ... 0x800f: -+ if (s->cycle) { -+ s->cycle = 0; -+ -+ if (value == 0x0000) { -+ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE) -+ onenand_load_main(s, sec, -+ 1 << (PAGE_SHIFT - 9), s->data[0][0]); -+ s->addr[ONEN_BUF_PAGE] += 4; -+ s->addr[ONEN_BUF_PAGE] &= 0xff; -+ } -+ break; -+ } -+ -+ switch (value) { -+ case 0x00f0: /* Reset OneNAND */ -+ onenand_reset(s, 0); -+ break; -+ -+ case 0x00e0: /* Load Data into Buffer */ -+ s->cycle = 1; -+ break; -+ -+ case 0x0090: /* Read Identification Data */ -+ memset(s->boot[0], 0, 3 << s->shift); -+ s->boot[0][0 << s->shift] = (s->id >> 16) & 0xff; -+ s->boot[0][1 << s->shift] = (s->id >> 8) & 0xff; -+ s->boot[0][2 << s->shift] = s->wpstatus & 0xff; -+ break; -+ -+ default: -+ fprintf(stderr, "%s: unknown OneNAND boot command %x\n", -+ __FUNCTION__, value); -+ } -+ break; -+ -+ case 0xf100 ... 0xf107: /* Start addresses */ -+ s->addr[offset - 0xf100] = value; -+ break; -+ -+ case 0xf200: /* Start buffer */ -+ s->bufaddr = (value >> 8) & 0xf; -+ if (PAGE_SHIFT == 11) -+ s->count = (value & 3) ?: 4; -+ else if (PAGE_SHIFT == 10) -+ s->count = (value & 1) ?: 2; -+ break; -+ -+ case 0xf220: /* Command */ -+ if (s->intstatus & (1 << 15)) -+ break; -+ s->command = value; -+ onenand_command(s, s->command); -+ break; -+ case 0xf221: /* System Configuration 1 */ -+ s->config[0] = value; -+ onenand_intr_update(s); -+ qemu_set_irq(s->rdy, (s->config[0] >> 7) & 1); -+ break; -+ case 0xf222: /* System Configuration 2 */ -+ s->config[1] = value; -+ break; -+ -+ case 0xf241: /* Interrupt */ -+ s->intstatus &= value; -+ if ((1 << 15) & ~s->intstatus) -+ s->status &= ~(ONEN_ERR_CMD | ONEN_ERR_ERASE | -+ ONEN_ERR_PROG | ONEN_ERR_LOAD); -+ onenand_intr_update(s); -+ break; -+ case 0xf24c: /* Unlock Start Block Address */ -+ s->unladdr[0] = value & (s->blocks - 1); -+ /* For some reason we have to set the end address to by default -+ * be same as start because the software forgets to write anything -+ * in there. */ -+ s->unladdr[1] = value & (s->blocks - 1); -+ break; -+ case 0xf24d: /* Unlock End Block Address */ -+ s->unladdr[1] = value & (s->blocks - 1); -+ break; -+ -+ default: -+ fprintf(stderr, "%s: unknown OneNAND register %x\n", -+ __FUNCTION__, offset); -+ } -+} -+ -+static CPUReadMemoryFunc *onenand_readfn[] = { -+ onenand_read, /* TODO */ -+ onenand_read, -+ onenand_read, -+}; -+ -+static CPUWriteMemoryFunc *onenand_writefn[] = { -+ onenand_write, /* TODO */ -+ onenand_write, -+ onenand_write, -+}; -+ -+void *onenand_init(uint32_t id, int regshift, qemu_irq irq) -+{ -+ struct onenand_s *s = (struct onenand_s *) qemu_mallocz(sizeof(*s)); -+ int bdrv_index = drive_get_index(IF_MTD, 0, 0); -+ uint32_t size = 1 << (24 + ((id >> 12) & 7)); -+ void *ram; -+ -+ s->shift = regshift; -+ s->intr = irq; -+ s->rdy = 0; -+ s->id = id; -+ s->blocks = size >> BLOCK_SHIFT; -+ s->secs = size >> 9; -+ s->blockwp = qemu_malloc(s->blocks); -+ s->density_mask = (id & (1 << 11)) ? (1 << (6 + ((id >> 12) & 7))) : 0; -+ s->iomemtype = cpu_register_io_memory(0, onenand_readfn, -+ onenand_writefn, s); -+ if (bdrv_index == -1) -+ s->image = memset(qemu_malloc(size + (size >> 5)), -+ 0xff, size + (size >> 5)); -+ else -+ s->bdrv = drives_table[bdrv_index].bdrv; -+ s->otp = memset(qemu_malloc((64 + 2) << PAGE_SHIFT), -+ 0xff, (64 + 2) << PAGE_SHIFT); -+ s->ram = qemu_ram_alloc(0xc000 << s->shift); -+ ram = phys_ram_base + s->ram; -+ s->boot[0] = ram + (0x0000 << s->shift); -+ s->boot[1] = ram + (0x8000 << s->shift); -+ s->data[0][0] = ram + ((0x0200 + (0 << (PAGE_SHIFT - 1))) << s->shift); -+ s->data[0][1] = ram + ((0x8010 + (0 << (PAGE_SHIFT - 6))) << s->shift); -+ s->data[1][0] = ram + ((0x0200 + (1 << (PAGE_SHIFT - 1))) << s->shift); -+ s->data[1][1] = ram + ((0x8010 + (1 << (PAGE_SHIFT - 6))) << s->shift); -+ -+ onenand_reset(s, 1); -+ -+ return s; -+} -diff --git a/hw/palm.c b/hw/palm.c -index 9400ea7..8b767e2 100644 ---- a/hw/palm.c -+++ b/hw/palm.c -@@ -25,6 +25,7 @@ - #include "omap.h" - #include "boards.h" - #include "arm-misc.h" -+#include "devices.h" - - static uint32_t static_readb(void *opaque, target_phys_addr_t offset) - { -@@ -32,12 +33,14 @@ static uint32_t static_readb(void *opaque, target_phys_addr_t offset) - return *val >> ((offset & 3) << 3); - } - --static uint32_t static_readh(void *opaque, target_phys_addr_t offset) { -+static uint32_t static_readh(void *opaque, target_phys_addr_t offset) -+{ - uint32_t *val = (uint32_t *) opaque; - return *val >> ((offset & 1) << 3); - } - --static uint32_t static_readw(void *opaque, target_phys_addr_t offset) { -+static uint32_t static_readw(void *opaque, target_phys_addr_t offset) -+{ - uint32_t *val = (uint32_t *) opaque; - return *val >> ((offset & 0) << 3); - } -@@ -183,6 +186,12 @@ static void palmte_gpio_setup(struct omap_mpu_state_s *cpu) - qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[11]); - } - -+static struct arm_boot_info palmte_binfo = { -+ .loader_start = OMAP_EMIFF_BASE, -+ .ram_size = 0x02000000, -+ .board_id = 0x331, -+}; -+ - static void palmte_init(int ram_size, int vga_ram_size, - const char *boot_device, DisplayState *ds, - const char *kernel_filename, const char *kernel_cmdline, -@@ -190,7 +199,7 @@ static void palmte_init(int ram_size, int vga_ram_size, - { - struct omap_mpu_state_s *cpu; - int flash_size = 0x00800000; -- int sdram_size = 0x02000000; -+ int sdram_size = palmte_binfo.ram_size; - int io; - static uint32_t cs0val = 0xffffffff; - static uint32_t cs1val = 0x0000e1a0; -@@ -250,10 +259,12 @@ static void palmte_init(int ram_size, int vga_ram_size, - /* Load the kernel. */ - if (kernel_filename) { - /* Start at bootloader. */ -- cpu->env->regs[15] = OMAP_EMIFF_BASE; -+ cpu->env->regs[15] = palmte_binfo.loader_start; - -- arm_load_kernel(cpu->env, sdram_size, kernel_filename, kernel_cmdline, -- initrd_filename, 0x331, OMAP_EMIFF_BASE); -+ palmte_binfo.kernel_filename = kernel_filename; -+ palmte_binfo.kernel_cmdline = kernel_cmdline; -+ palmte_binfo.initrd_filename = initrd_filename; -+ arm_load_kernel(cpu->env, &palmte_binfo); - } - - dpy_resize(ds, 320, 320); -diff --git a/hw/realview.c b/hw/realview.c -index 29579d8..acf3b9e 100644 ---- a/hw/realview.c -+++ b/hw/realview.c -@@ -18,6 +18,11 @@ - - /* Board init. */ - -+static struct arm_boot_info realview_binfo = { -+ .loader_start = 0x0, -+ .board_id = 0x33b, -+}; -+ - static void realview_init(int ram_size, int vga_ram_size, - const char *boot_device, DisplayState *ds, - const char *kernel_filename, const char *kernel_cmdline, -@@ -177,8 +182,12 @@ static void realview_init(int ram_size, int vga_ram_size, - /* 0x68000000 PCI mem 1. */ - /* 0x6c000000 PCI mem 2. */ - -- arm_load_kernel(first_cpu, ram_size, kernel_filename, kernel_cmdline, -- initrd_filename, 0x33b, 0x0); -+ realview_binfo.ram_size = ram_size; -+ realview_binfo.kernel_filename = kernel_filename; -+ realview_binfo.kernel_cmdline = kernel_cmdline; -+ realview_binfo.initrd_filename = initrd_filename; -+ realview_binfo.nb_cpus = ncpu; -+ arm_load_kernel(first_cpu, &realview_binfo); - - /* ??? Hack to map an additional page of ram for the secondary CPU - startup code. I guess this works on real hardware because the -diff --git a/hw/sd.c b/hw/sd.c -index 1f71d85..de7dd89 100644 ---- a/hw/sd.c -+++ b/hw/sd.c -@@ -37,7 +37,7 @@ - - #ifdef DEBUG_SD - #define DPRINTF(fmt, args...) \ --do { printf("SD: " fmt , ##args); } while (0) -+do { fprintf(stderr, "SD: " fmt , ##args); } while (0) - #else - #define DPRINTF(fmt, args...) do {} while(0) - #endif -@@ -99,6 +99,8 @@ struct SDState { - qemu_irq inserted_cb; - BlockDriverState *bdrv; - uint8_t *buf; -+ -+ int enable; - }; - - static void sd_set_status(SDState *sd) -@@ -530,7 +532,7 @@ static void sd_lock_command(SDState *sd) - sd->card_status &= ~CARD_IS_LOCKED; - sd->pwd_len = 0; - /* Erasing the entire card here! */ -- printf("SD: Card force-erased by CMD42\n"); -+ fprintf(stderr, "SD: Card force-erased by CMD42\n"); - return; - } - -@@ -1076,7 +1078,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, - return sd_r1; - - case 56: /* CMD56: GEN_CMD */ -- printf("SD: GEN_CMD 0x%08x\n", req.arg); -+ fprintf(stderr, "SD: GEN_CMD 0x%08x\n", req.arg); - - switch (sd->state) { - case sd_transfer_state: -@@ -1096,18 +1098,18 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, - bad_cmd: - sd->card_status |= ILLEGAL_COMMAND; - -- printf("SD: Unknown CMD%i\n", req.cmd); -+ fprintf(stderr, "SD: Unknown CMD%i\n", req.cmd); - return sd_r0; - - unimplemented_cmd: - /* Commands that are recognised but not yet implemented in SPI mode. */ - sd->card_status |= ILLEGAL_COMMAND; -- printf ("SD: CMD%i not implemented in SPI mode\n", req.cmd); -+ fprintf(stderr, "SD: CMD%i not implemented in SPI mode\n", req.cmd); - return sd_r0; - } - - sd->card_status |= ILLEGAL_COMMAND; -- printf("SD: CMD%i in a wrong state\n", req.cmd); -+ fprintf(stderr, "SD: CMD%i in a wrong state\n", req.cmd); - return sd_r0; - } - -@@ -1217,7 +1219,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd, - return sd_normal_command(sd, req); - } - -- printf("SD: ACMD%i in a wrong state\n", req.cmd); -+ fprintf(stderr, "SD: ACMD%i in a wrong state\n", req.cmd); - return sd_r0; - } - -@@ -1227,7 +1229,7 @@ int sd_do_command(SDState *sd, struct sd_request_s *req, - sd_rsp_type_t rtype; - int rsplen; - -- if (!bdrv_is_inserted(sd->bdrv)) { -+ if (!bdrv_is_inserted(sd->bdrv) || !sd->enable) { - return 0; - } - -@@ -1247,7 +1249,7 @@ int sd_do_command(SDState *sd, struct sd_request_s *req, - sd_cmd_class[req->cmd] == 7 || - req->cmd == 16 || req->cmd == 55))) { - sd->card_status |= ILLEGAL_COMMAND; -- printf("SD: Card is locked\n"); -+ fprintf(stderr, "SD: Card is locked\n"); - return 0; - } - -@@ -1321,7 +1323,7 @@ static void sd_blk_read(SDState *sd, uint32_t addr, uint32_t len) - uint32_t end = addr + len; - - if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) == -1) { -- printf("sd_blk_read: read error on host side\n"); -+ fprintf(stderr, "sd_blk_read: read error on host side\n"); - return; - } - -@@ -1329,7 +1331,7 @@ static void sd_blk_read(SDState *sd, uint32_t addr, uint32_t len) - memcpy(sd->data, sd->buf + (addr & 511), 512 - (addr & 511)); - - if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) == -1) { -- printf("sd_blk_read: read error on host side\n"); -+ fprintf(stderr, "sd_blk_read: read error on host side\n"); - return; - } - memcpy(sd->data + 512 - (addr & 511), sd->buf, end & 511); -@@ -1343,28 +1345,28 @@ static void sd_blk_write(SDState *sd, uint32_t addr, uint32_t len) - - if ((addr & 511) || len < 512) - if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) == -1) { -- printf("sd_blk_write: read error on host side\n"); -+ fprintf(stderr, "sd_blk_write: read error on host side\n"); - return; - } - - if (end > (addr & ~511) + 512) { - memcpy(sd->buf + (addr & 511), sd->data, 512 - (addr & 511)); - if (bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) == -1) { -- printf("sd_blk_write: write error on host side\n"); -+ fprintf(stderr, "sd_blk_write: write error on host side\n"); - return; - } - - if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) == -1) { -- printf("sd_blk_write: read error on host side\n"); -+ fprintf(stderr, "sd_blk_write: read error on host side\n"); - return; - } - memcpy(sd->buf, sd->data + 512 - (addr & 511), end & 511); - if (bdrv_write(sd->bdrv, end >> 9, sd->buf, 1) == -1) -- printf("sd_blk_write: write error on host side\n"); -+ fprintf(stderr, "sd_blk_write: write error on host side\n"); - } else { - memcpy(sd->buf + (addr & 511), sd->data, len); - if (!sd->bdrv || bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) == -1) -- printf("sd_blk_write: write error on host side\n"); -+ fprintf(stderr, "sd_blk_write: write error on host side\n"); - } - } - -@@ -1377,11 +1379,11 @@ void sd_write_data(SDState *sd, uint8_t value) - { - int i; - -- if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv)) -+ if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable) - return; - - if (sd->state != sd_receivingdata_state) { -- printf("sd_write_data: not in Receiving-Data state\n"); -+ fprintf(stderr, "sd_write_data: not in Receiving-Data state\n"); - return; - } - -@@ -1489,7 +1491,7 @@ void sd_write_data(SDState *sd, uint8_t value) - break; - - default: -- printf("sd_write_data: unknown command\n"); -+ fprintf(stderr, "sd_write_data: unknown command\n"); - break; - } - } -@@ -1499,11 +1501,11 @@ uint8_t sd_read_data(SDState *sd) - /* TODO: Append CRCs */ - uint8_t ret; - -- if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv)) -+ if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable) - return 0x00; - - if (sd->state != sd_sendingdata_state) { -- printf("sd_read_data: not in Sending-Data state\n"); -+ fprintf(stderr, "sd_read_data: not in Sending-Data state\n"); - return 0x00; - } - -@@ -1603,7 +1605,7 @@ uint8_t sd_read_data(SDState *sd) - break; - - default: -- printf("sd_read_data: unknown command\n"); -+ fprintf(stderr, "sd_read_data: unknown command\n"); - return 0x00; - } - -@@ -1614,3 +1616,8 @@ int sd_data_ready(SDState *sd) - { - return sd->state == sd_sendingdata_state; - } -+ -+void sd_enable(SDState *sd, int enable) -+{ -+ sd->enable = enable; -+} -diff --git a/hw/sd.h b/hw/sd.h -index 85f110f..cb7bc9c 100644 ---- a/hw/sd.h -+++ b/hw/sd.h -@@ -74,6 +74,7 @@ void sd_write_data(SDState *sd, uint8_t value); - uint8_t sd_read_data(SDState *sd); - void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert); - int sd_data_ready(SDState *sd); -+void sd_enable(SDState *sd, int enable); - - /* ssi-sd.c */ - int ssi_sd_xfer(void *opaque, int val); -diff --git a/hw/spitz.c b/hw/spitz.c -index 159c633..b059f9a 100644 ---- a/hw/spitz.c -+++ b/hw/spitz.c -@@ -1180,12 +1180,17 @@ static void sl_bootparam_write(uint32_t ptr) - /* Board init. */ - enum spitz_model_e { spitz, akita, borzoi, terrier }; - -+static struct arm_boot_info spitz_binfo = { -+ .loader_start = PXA2XX_SDRAM_BASE, -+ .ram_size = 0x04000000, -+}; -+ - static void spitz_common_init(int ram_size, int vga_ram_size, - DisplayState *ds, const char *kernel_filename, - const char *kernel_cmdline, const char *initrd_filename, - const char *cpu_model, enum spitz_model_e model, int arm_id) - { -- uint32_t spitz_ram = 0x04000000; -+ uint32_t spitz_ram = spitz_binfo.ram_size; - uint32_t spitz_rom = 0x00800000; - struct pxa2xx_state_s *cpu; - struct scoop_info_s *scp; -@@ -1230,10 +1235,13 @@ static void spitz_common_init(int ram_size, int vga_ram_size, - spitz_microdrive_attach(cpu); - - /* Setup initial (reset) machine state */ -- cpu->env->regs[15] = PXA2XX_SDRAM_BASE; -+ cpu->env->regs[15] = spitz_binfo.loader_start; - -- arm_load_kernel(cpu->env, spitz_ram, kernel_filename, kernel_cmdline, -- initrd_filename, arm_id, PXA2XX_SDRAM_BASE); -+ spitz_binfo.kernel_filename = kernel_filename; -+ spitz_binfo.kernel_cmdline = kernel_cmdline; -+ spitz_binfo.initrd_filename = initrd_filename; -+ spitz_binfo.board_id = arm_id; -+ arm_load_kernel(cpu->env, &spitz_binfo); - sl_bootparam_write(SL_PXA_PARAM_BASE - PXA2XX_SDRAM_BASE); - } - -diff --git a/hw/tmp105.c b/hw/tmp105.c -new file mode 100644 -index 0000000..d9a3900 ---- /dev/null -+++ b/hw/tmp105.c -@@ -0,0 +1,249 @@ -+/* -+ * Texas Instruments TMP105 temperature sensor. -+ * -+ * Copyright (C) 2008 Nokia Corporation -+ * Written by Andrzej Zaborowski -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of -+ * the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, -+ * MA 02111-1307 USA -+ */ -+ -+#include "hw.h" -+#include "i2c.h" -+ -+struct tmp105_s { -+ i2c_slave i2c; -+ int len; -+ uint8_t buf[2]; -+ qemu_irq pin; -+ -+ uint8_t pointer; -+ uint8_t config; -+ int16_t temperature; -+ int16_t limit[2]; -+ int faults; -+ int alarm; -+}; -+ -+static void tmp105_interrupt_update(struct tmp105_s *s) -+{ -+ qemu_set_irq(s->pin, s->alarm ^ ((~s->config >> 2) & 1)); /* POL */ -+} -+ -+static void tmp105_alarm_update(struct tmp105_s *s) -+{ -+ if ((s->config >> 0) & 1) { /* SD */ -+ if ((s->config >> 7) & 1) /* OS */ -+ s->config &= ~(1 << 7); /* OS */ -+ else -+ return; -+ } -+ -+ if ((s->config >> 1) & 1) { /* TM */ -+ if (s->temperature >= s->limit[1]) -+ s->alarm = 1; -+ else if (s->temperature < s->limit[0]) -+ s->alarm = 1; -+ } else { -+ if (s->temperature >= s->limit[1]) -+ s->alarm = 1; -+ else if (s->temperature < s->limit[0]) -+ s->alarm = 0; -+ } -+ -+ tmp105_interrupt_update(s); -+} -+ -+/* Units are 0.001 centigrades relative to 0 C. */ -+void tmp105_set(i2c_slave *i2c, int temp) -+{ -+ struct tmp105_s *s = (struct tmp105_s *) i2c; -+ -+ if (temp >= 128000 || temp < -128000) { -+ fprintf(stderr, "%s: values is out of range (%i.%03i C)\n", -+ __FUNCTION__, temp / 1000, temp % 1000); -+ exit(-1); -+ } -+ -+ s->temperature = ((int16_t) (temp * 0x800 / 128000)) << 4; -+ -+ tmp105_alarm_update(s); -+} -+ -+static const int tmp105_faultq[4] = { 1, 2, 4, 6 }; -+ -+static void tmp105_read(struct tmp105_s *s) -+{ -+ s->len = 0; -+ -+ if ((s->config >> 1) & 1) { /* TM */ -+ s->alarm = 0; -+ tmp105_interrupt_update(s); -+ } -+ -+ switch (s->pointer & 3) { -+ case 0: /* Temperature */ -+ s->buf[s->len ++] = (((uint16_t) s->temperature) >> 8); -+ s->buf[s->len ++] = (((uint16_t) s->temperature) >> 0) & -+ (0xf0 << ((~s->config >> 5) & 3)); /* R */ -+ break; -+ -+ case 1: /* Configuration */ -+ s->buf[s->len ++] = s->config; -+ break; -+ -+ case 2: /* T_LOW */ -+ s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 8; -+ s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 0; -+ break; -+ -+ case 3: /* T_HIGH */ -+ s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 8; -+ s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 0; -+ break; -+ } -+} -+ -+static void tmp105_write(struct tmp105_s *s) -+{ -+ switch (s->pointer & 3) { -+ case 0: /* Temperature */ -+ break; -+ -+ case 1: /* Configuration */ -+ if (s->buf[0] & ~s->config & (1 << 0)) /* SD */ -+ printf("%s: TMP105 shutdown\n", __FUNCTION__); -+ s->config = s->buf[0]; -+ s->faults = tmp105_faultq[(s->config >> 3) & 3]; /* F */ -+ tmp105_alarm_update(s); -+ break; -+ -+ case 2: /* T_LOW */ -+ case 3: /* T_HIGH */ -+ if (s->len >= 3) -+ s->limit[s->pointer & 1] = (int16_t) -+ ((((uint16_t) s->buf[0]) << 8) | s->buf[1]); -+ tmp105_alarm_update(s); -+ break; -+ } -+} -+ -+static int tmp105_rx(i2c_slave *i2c) -+{ -+ struct tmp105_s *s = (struct tmp105_s *) i2c; -+ -+ if (s->len < 2) -+ return s->buf[s->len ++]; -+ else -+ return 0xff; -+} -+ -+static int tmp105_tx(i2c_slave *i2c, uint8_t data) -+{ -+ struct tmp105_s *s = (struct tmp105_s *) i2c; -+ -+ if (!s->len ++) -+ s->pointer = data; -+ else { -+ if (s->len <= 2) -+ s->buf[s->len - 1] = data; -+ tmp105_write(s); -+ } -+ -+ return 0; -+} -+ -+static void tmp105_event(i2c_slave *i2c, enum i2c_event event) -+{ -+ struct tmp105_s *s = (struct tmp105_s *) i2c; -+ -+ if (event == I2C_START_RECV) -+ tmp105_read(s); -+ -+ s->len = 0; -+} -+ -+static void tmp105_save(QEMUFile *f, void *opaque) -+{ -+ struct tmp105_s *s = (struct tmp105_s *) opaque; -+ -+ qemu_put_byte(f, s->len); -+ qemu_put_8s(f, &s->buf[0]); -+ qemu_put_8s(f, &s->buf[1]); -+ -+ qemu_put_8s(f, &s->pointer); -+ qemu_put_8s(f, &s->config); -+ qemu_put_be16s(f, &s->temperature); -+ qemu_put_be16s(f, &s->limit[0]); -+ qemu_put_be16s(f, &s->limit[1]); -+ qemu_put_byte(f, s->alarm); -+ s->faults = tmp105_faultq[(s->config >> 3) & 3]; /* F */ -+ -+ i2c_slave_save(f, &s->i2c); -+} -+ -+static int tmp105_load(QEMUFile *f, void *opaque, int version_id) -+{ -+ struct tmp105_s *s = (struct tmp105_s *) opaque; -+ -+ s->len = qemu_get_byte(f); -+ qemu_get_8s(f, &s->buf[0]); -+ qemu_get_8s(f, &s->buf[1]); -+ -+ qemu_get_8s(f, &s->pointer); -+ qemu_get_8s(f, &s->config); -+ qemu_get_be16s(f, &s->temperature); -+ qemu_get_be16s(f, &s->limit[0]); -+ qemu_get_be16s(f, &s->limit[1]); -+ s->alarm = qemu_get_byte(f); -+ -+ tmp105_interrupt_update(s); -+ -+ i2c_slave_load(f, &s->i2c); -+ return 0; -+} -+ -+void tmp105_reset(i2c_slave *i2c) -+{ -+ struct tmp105_s *s = (struct tmp105_s *) i2c; -+ -+ s->temperature = 0; -+ s->pointer = 0; -+ s->config = 0; -+ s->faults = tmp105_faultq[(s->config >> 3) & 3]; -+ s->alarm = 0; -+ -+ tmp105_interrupt_update(s); -+} -+ -+static int tmp105_iid = 0; -+ -+struct i2c_slave *tmp105_init(i2c_bus *bus, qemu_irq alarm) -+{ -+ struct tmp105_s *s = (struct tmp105_s *) -+ i2c_slave_init(bus, 0, sizeof(struct tmp105_s)); -+ -+ s->i2c.event = tmp105_event; -+ s->i2c.recv = tmp105_rx; -+ s->i2c.send = tmp105_tx; -+ s->pin = alarm; -+ -+ tmp105_reset(&s->i2c); -+ -+ register_savevm("TMP105", tmp105_iid ++, 0, -+ tmp105_save, tmp105_load, s); -+ -+ return &s->i2c; -+} -diff --git a/hw/tsc210x.c b/hw/tsc210x.c -index 96956a4..1654b8b 100644 ---- a/hw/tsc210x.c -+++ b/hw/tsc210x.c -@@ -2,6 +2,7 @@ - * TI TSC2102 (touchscreen/sensors/audio controller) emulator. - * - * Copyright (c) 2006 Andrzej Zaborowski -+ * Copyright (C) 2008 Nokia Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as -@@ -35,12 +36,15 @@ - - struct tsc210x_state_s { - qemu_irq pint; -+ qemu_irq kbint; -+ qemu_irq davint; - QEMUTimer *timer; - QEMUSoundCard card; - struct uwire_slave_s chip; - struct i2s_codec_s codec; - uint8_t in_fifo[16384]; - uint8_t out_fifo[16384]; -+ uint16_t model; - - int x, y; - int pressure; -@@ -64,7 +68,7 @@ struct tsc210x_state_s { - uint16_t audio_ctrl1; - uint16_t audio_ctrl2; - uint16_t audio_ctrl3; -- uint16_t pll[2]; -+ uint16_t pll[3]; - uint16_t volume; - int64_t volume_change; - int softstep; -@@ -78,6 +82,17 @@ struct tsc210x_state_s { - int i2s_rx_rate; - int i2s_tx_rate; - AudioState *audio; -+ -+ int tr[8]; -+ -+ struct { -+ uint16_t down; -+ uint16_t mask; -+ int scan; -+ int debounce; -+ int mode; -+ int intr; -+ } kb; - }; - - static const int resolution[4] = { 12, 8, 10, 12 }; -@@ -118,17 +133,10 @@ static const uint16_t mode_regs[16] = { - 0x0000, /* Y+, X- drivers */ - }; - --/* -- * Convert screen coordinates to arbitrary values that the -- * touchscreen in my Palm Tungsten E device returns. -- * This shouldn't really matter (because the guest system -- * should calibrate the touchscreen anyway), but let's -- * imitate some real hardware. -- */ --#define X_TRANSFORM(value) \ -- ((3850 - ((int) (value) * (3850 - 250) / 32768)) << 4) --#define Y_TRANSFORM(value) \ -- ((150 + ((int) (value) * (3037 - 150) / 32768)) << 4) -+#define X_TRANSFORM(s) \ -+ ((s->y * s->tr[0] - s->x * s->tr[1]) / s->tr[2] + s->tr[3]) -+#define Y_TRANSFORM(s) \ -+ ((s->y * s->tr[4] - s->x * s->tr[5]) / s->tr[6] + s->tr[7]) - #define Z1_TRANSFORM(s) \ - ((400 - ((s)->x >> 7) + ((s)->pressure << 10)) << 4) - #define Z2_TRANSFORM(s) \ -@@ -161,6 +169,7 @@ static void tsc210x_reset(struct tsc210x_state_s *s) - s->audio_ctrl3 = 0x0000; - s->pll[0] = 0x1004; - s->pll[1] = 0x0000; -+ s->pll[2] = 0x1fff; - s->volume = 0xffff; - s->dac_power = 0x8540; - s->softstep = 1; -@@ -190,7 +199,15 @@ static void tsc210x_reset(struct tsc210x_state_s *s) - s->i2s_tx_rate = 0; - s->i2s_rx_rate = 0; - -+ s->kb.scan = 1; -+ s->kb.debounce = 0; -+ s->kb.mask = 0x0000; -+ s->kb.mode = 3; -+ s->kb.intr = 0; -+ - qemu_set_irq(s->pint, !s->irq); -+ qemu_set_irq(s->davint, !s->dav); -+ qemu_irq_raise(s->kbint); - } - - struct tsc210x_rate_info_s { -@@ -344,13 +361,13 @@ static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg) - switch (reg) { - case 0x00: /* X */ - s->dav &= 0xfbff; -- return TSC_CUT_RESOLUTION(X_TRANSFORM(s->x), s->precision) + -+ return TSC_CUT_RESOLUTION(X_TRANSFORM(s), s->precision) + - (s->noise & 3); - - case 0x01: /* Y */ - s->noise ++; - s->dav &= 0xfdff; -- return TSC_CUT_RESOLUTION(Y_TRANSFORM(s->y), s->precision) ^ -+ return TSC_CUT_RESOLUTION(Y_TRANSFORM(s), s->precision) ^ - (s->noise & 3); - - case 0x02: /* Z1 */ -@@ -364,6 +381,14 @@ static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg) - (s->noise & 3); - - case 0x04: /* KPData */ -+ if ((s->model & 0xff00) == 0x2300) { -+ if (s->kb.intr && (s->kb.mode & 2)) { -+ s->kb.intr = 0; -+ qemu_irq_raise(s->kbint); -+ } -+ return s->kb.down; -+ } -+ - return 0xffff; - - case 0x05: /* BAT1 */ -@@ -414,9 +439,19 @@ static uint16_t tsc2102_control_register_read( - return (s->pressure << 15) | ((!s->busy) << 14) | - (s->nextfunction << 10) | (s->nextprecision << 8) | s->filter; - -- case 0x01: /* Status */ -- return (s->pin_func << 14) | ((!s->enabled) << 13) | -- (s->host_mode << 12) | ((!!s->dav) << 11) | s->dav; -+ case 0x01: /* Status / Keypad Control */ -+ if ((s->model & 0xff00) == 0x2100) -+ return (s->pin_func << 14) | ((!s->enabled) << 13) | -+ (s->host_mode << 12) | ((!!s->dav) << 11) | s->dav; -+ else -+ return (s->kb.intr << 15) | ((s->kb.scan || !s->kb.down) << 14) | -+ (s->kb.debounce << 11); -+ -+ case 0x02: /* DAC Control */ -+ if ((s->model & 0xff00) == 0x2300) -+ return s->dac_power & 0x8000; -+ else -+ goto bad_reg; - - case 0x03: /* Reference */ - return s->ref; -@@ -427,7 +462,18 @@ static uint16_t tsc2102_control_register_read( - case 0x05: /* Configuration */ - return s->timing; - -+ case 0x06: /* Secondary configuration */ -+ if ((s->model & 0xff00) == 0x2100) -+ goto bad_reg; -+ return ((!s->dav) << 15) | ((s->kb.mode & 1) << 14) | s->pll[2]; -+ -+ case 0x10: /* Keypad Mask */ -+ if ((s->model & 0xff00) == 0x2100) -+ goto bad_reg; -+ return s->kb.mask; -+ - default: -+ bad_reg: - #ifdef TSC_VERBOSE - fprintf(stderr, "tsc2102_control_register_read: " - "no such register: 0x%02x\n", reg); -@@ -556,10 +602,27 @@ static void tsc2102_control_register_write( - s->filter = value & 0xff; - return; - -- case 0x01: /* Status */ -- s->pin_func = value >> 14; -+ case 0x01: /* Status / Keypad Control */ -+ if ((s->model & 0xff00) == 0x2100) -+ s->pin_func = value >> 14; -+ else { -+ s->kb.scan = (value >> 14) & 1; -+ s->kb.debounce = (value >> 11) & 7; -+ if (s->kb.intr && s->kb.scan) { -+ s->kb.intr = 0; -+ qemu_irq_raise(s->kbint); -+ } -+ } - return; - -+ case 0x02: /* DAC Control */ -+ if ((s->model & 0xff00) == 0x2300) { -+ s->dac_power &= 0x7fff; -+ s->dac_power |= 0x8000 & value; -+ } else -+ goto bad_reg; -+ break; -+ - case 0x03: /* Reference */ - s->ref = value & 0x1f; - return; -@@ -586,7 +649,21 @@ static void tsc2102_control_register_write( - #endif - return; - -+ case 0x06: /* Secondary configuration */ -+ if ((s->model & 0xff00) == 0x2100) -+ goto bad_reg; -+ s->kb.mode = value >> 14; -+ s->pll[2] = value & 0x3ffff; -+ return; -+ -+ case 0x10: /* Keypad Mask */ -+ if ((s->model & 0xff00) == 0x2100) -+ goto bad_reg; -+ s->kb.mask = value; -+ return; -+ - default: -+ bad_reg: - #ifdef TSC_VERBOSE - fprintf(stderr, "tsc2102_control_register_write: " - "no such register: 0x%02x\n", reg); -@@ -785,7 +862,7 @@ static void tsc210x_pin_update(struct tsc210x_state_s *s) - return; - } - -- if (!s->enabled || s->busy) -+ if (!s->enabled || s->busy || s->dav) - return; - - s->busy = 1; -@@ -805,6 +882,8 @@ static uint16_t tsc210x_read(struct tsc210x_state_s *s) - switch (s->page) { - case TSC_DATA_REGISTERS_PAGE: - ret = tsc2102_data_register_read(s, s->offset); -+ if (!s->dav) -+ qemu_irq_raise(s->davint); - break; - case TSC_CONTROL_REGISTERS_PAGE: - ret = tsc2102_control_register_read(s, s->offset); -@@ -859,6 +938,22 @@ static void tsc210x_write(struct tsc210x_state_s *s, uint16_t value) - } - } - -+uint32_t tsc210x_txrx(void *opaque, uint32_t value) -+{ -+ struct tsc210x_state_s *s = opaque; -+ uint32_t ret = 0; -+ -+ /* TODO: sequential reads etc - how do we make sure the host doesn't -+ * unintentionally read out a conversion result from a register while -+ * transmitting the command word of the next command? */ -+ if (!value || (s->state && s->command)) -+ ret = tsc210x_read(s); -+ if (value || (s->state && !s->command)) -+ tsc210x_write(s, value); -+ -+ return ret; -+} -+ - static void tsc210x_timer_tick(void *opaque) - { - struct tsc210x_state_s *s = opaque; -@@ -871,6 +966,7 @@ static void tsc210x_timer_tick(void *opaque) - s->busy = 0; - s->dav |= mode_regs[s->function]; - tsc210x_pin_update(s); -+ qemu_irq_lower(s->davint); - } - - static void tsc210x_touchscreen_event(void *opaque, -@@ -1001,6 +1097,7 @@ static int tsc210x_load(QEMUFile *f, void *opaque, int version_id) - - s->busy = qemu_timer_pending(s->timer); - qemu_set_irq(s->pint, !s->irq); -+ qemu_set_irq(s->davint, !s->dav); - - return 0; - } -@@ -1020,9 +1117,19 @@ struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio) - s->precision = s->nextprecision = 0; - s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s); - s->pint = pint; -+ s->model = 0x2102; - s->name = "tsc2102"; - s->audio = audio; - -+ s->tr[0] = 0; -+ s->tr[1] = 1; -+ s->tr[2] = 0; -+ s->tr[3] = 1; -+ s->tr[4] = 1; -+ s->tr[5] = 0; -+ s->tr[6] = 0; -+ s->tr[7] = 1; -+ - s->chip.opaque = s; - s->chip.send = (void *) tsc210x_write; - s->chip.receive = (void *) tsc210x_read; -@@ -1048,9 +1155,147 @@ struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio) - return &s->chip; - } - -+struct uwire_slave_s *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, -+ qemu_irq dav, AudioState *audio) -+{ -+ struct tsc210x_state_s *s; -+ -+ s = (struct tsc210x_state_s *) -+ qemu_mallocz(sizeof(struct tsc210x_state_s)); -+ memset(s, 0, sizeof(struct tsc210x_state_s)); -+ s->x = 400; -+ s->y = 240; -+ s->pressure = 0; -+ s->precision = s->nextprecision = 0; -+ s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s); -+ s->pint = penirq; -+ s->kbint = kbirq; -+ s->davint = dav; -+ s->model = 0x2301; -+ s->name = "tsc2301"; -+ s->audio = audio; -+ -+ s->tr[0] = 0; -+ s->tr[1] = 1; -+ s->tr[2] = 0; -+ s->tr[3] = 1; -+ s->tr[4] = 1; -+ s->tr[5] = 0; -+ s->tr[6] = 0; -+ s->tr[7] = 1; -+ -+ s->chip.opaque = s; -+ s->chip.send = (void *) tsc210x_write; -+ s->chip.receive = (void *) tsc210x_read; -+ -+ s->codec.opaque = s; -+ s->codec.tx_swallow = (void *) tsc210x_i2s_swallow; -+ s->codec.set_rate = (void *) tsc210x_i2s_set_rate; -+ s->codec.in.fifo = s->in_fifo; -+ s->codec.out.fifo = s->out_fifo; -+ -+ tsc210x_reset(s); -+ -+ qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1, -+ "QEMU TSC2301-driven Touchscreen"); -+ -+ if (s->audio) -+ AUD_register_card(s->audio, s->name, &s->card); -+ -+ qemu_register_reset((void *) tsc210x_reset, s); -+ register_savevm(s->name, tsc2102_iid ++, 0, -+ tsc210x_save, tsc210x_load, s); -+ -+ return &s->chip; -+} -+ - struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip) - { - struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque; - - return &s->codec; - } -+ -+/* -+ * Use tslib generated calibration data to generate ADC input values -+ * from the touchscreen. Assuming 12-bit precision was used during -+ * tslib calibration. -+ */ -+void tsc210x_set_transform(struct uwire_slave_s *chip, -+ struct mouse_transform_info_s *info) -+{ -+ struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque; -+#if 0 -+ int64_t ltr[8]; -+ -+ ltr[0] = (int64_t) info->a[1] * info->y; -+ ltr[1] = (int64_t) info->a[4] * info->x; -+ ltr[2] = (int64_t) info->a[1] * info->a[3] - -+ (int64_t) info->a[4] * info->a[0]; -+ ltr[3] = (int64_t) info->a[2] * info->a[4] - -+ (int64_t) info->a[5] * info->a[1]; -+ ltr[4] = (int64_t) info->a[0] * info->y; -+ ltr[5] = (int64_t) info->a[3] * info->x; -+ ltr[6] = (int64_t) info->a[4] * info->a[0] - -+ (int64_t) info->a[1] * info->a[3]; -+ ltr[7] = (int64_t) info->a[2] * info->a[3] - -+ (int64_t) info->a[5] * info->a[0]; -+ -+ /* Avoid integer overflow */ -+ s->tr[0] = ltr[0] >> 11; -+ s->tr[1] = ltr[1] >> 11; -+ s->tr[2] = muldiv64(ltr[2], 1, info->a[6]); -+ s->tr[3] = muldiv64(ltr[3], 1 << 4, ltr[2]); -+ s->tr[4] = ltr[4] >> 11; -+ s->tr[5] = ltr[5] >> 11; -+ s->tr[6] = muldiv64(ltr[6], 1, info->a[6]); -+ s->tr[7] = muldiv64(ltr[7], 1 << 4, ltr[6]); -+#else -+ -+ if (abs(info->a[0]) > abs(info->a[1])) { -+ s->tr[0] = 0; -+ s->tr[1] = -info->a[6] * info->x; -+ s->tr[2] = info->a[0]; -+ s->tr[3] = -info->a[2] / info->a[0]; -+ s->tr[4] = info->a[6] * info->y; -+ s->tr[5] = 0; -+ s->tr[6] = info->a[4]; -+ s->tr[7] = -info->a[5] / info->a[4]; -+ } else { -+ s->tr[0] = info->a[6] * info->y; -+ s->tr[1] = 0; -+ s->tr[2] = info->a[1]; -+ s->tr[3] = -info->a[2] / info->a[1]; -+ s->tr[4] = 0; -+ s->tr[5] = -info->a[6] * info->x; -+ s->tr[6] = info->a[3]; -+ s->tr[7] = -info->a[5] / info->a[3]; -+ } -+ -+ s->tr[0] >>= 11; -+ s->tr[1] >>= 11; -+ s->tr[3] <<= 4; -+ s->tr[4] >>= 11; -+ s->tr[5] >>= 11; -+ s->tr[7] <<= 4; -+#endif -+} -+ -+void tsc210x_key_event(struct uwire_slave_s *chip, int key, int down) -+{ -+ struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque; -+ -+ if (down) -+ s->kb.down |= 1 << key; -+ else -+ s->kb.down &= ~(1 << key); -+ -+ if (down && (s->kb.down & ~s->kb.mask) && !s->kb.intr) { -+ s->kb.intr = 1; -+ qemu_irq_lower(s->kbint); -+ } else if (s->kb.intr && !(s->kb.down & ~s->kb.mask) && -+ !(s->kb.mode & 1)) { -+ s->kb.intr = 0; -+ qemu_irq_raise(s->kbint); -+ } -+} -diff --git a/hw/twl92230.c b/hw/twl92230.c -new file mode 100644 -index 0000000..11a5d1a ---- /dev/null -+++ b/hw/twl92230.c -@@ -0,0 +1,923 @@ -+/* -+ * TI TWL92230C energy-management companion device for the OMAP24xx. -+ * Aka. Menelaus (N4200 MENELAUS1_V2.2) -+ * -+ * Copyright (C) 2008 Nokia Corporation -+ * Written by Andrzej Zaborowski -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of -+ * the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, 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" -+ -+#define VERBOSE 1 -+ -+struct menelaus_s { -+ i2c_slave i2c; -+ qemu_irq irq; -+ -+ int firstbyte; -+ uint8_t reg; -+ -+ uint8_t vcore[5]; -+ uint8_t dcdc[3]; -+ uint8_t ldo[8]; -+ uint8_t sleep[2]; -+ uint8_t osc; -+ uint8_t detect; -+ uint16_t mask; -+ uint16_t status; -+ uint8_t dir; -+ uint8_t inputs; -+ uint8_t outputs; -+ uint8_t bbsms; -+ uint8_t pull[4]; -+ uint8_t mmc_ctrl[3]; -+ uint8_t mmc_debounce; -+ struct { -+ uint8_t ctrl; -+ uint16_t comp; -+ QEMUTimer *hz; -+ int64_t next; -+ struct tm tm; -+ struct tm new; -+ struct tm alm; -+ time_t sec; -+ time_t alm_sec; -+ time_t next_comp; -+ struct tm *(*gettime)(const time_t *timep, struct tm *result); -+ } rtc; -+ qemu_irq handler[3]; -+ qemu_irq *in; -+ int pwrbtn_state; -+ qemu_irq pwrbtn; -+}; -+ -+static inline void menelaus_update(struct menelaus_s *s) -+{ -+ qemu_set_irq(s->irq, s->status & ~s->mask); -+} -+ -+static inline void menelaus_rtc_start(struct menelaus_s *s) -+{ -+ s->rtc.next =+ qemu_get_clock(rt_clock); -+ qemu_mod_timer(s->rtc.hz, s->rtc.next); -+} -+ -+static inline void menelaus_rtc_stop(struct menelaus_s *s) -+{ -+ qemu_del_timer(s->rtc.hz); -+ s->rtc.next =- qemu_get_clock(rt_clock); -+ if (s->rtc.next < 1) -+ s->rtc.next = 1; -+} -+ -+static void menelaus_rtc_update(struct menelaus_s *s) -+{ -+ s->rtc.gettime(&s->rtc.sec, &s->rtc.tm); -+} -+ -+static void menelaus_alm_update(struct menelaus_s *s) -+{ -+ if ((s->rtc.ctrl & 3) == 3) -+ s->rtc.alm_sec = mktime(&s->rtc.alm); -+} -+ -+static void menelaus_rtc_hz(void *opaque) -+{ -+ struct menelaus_s *s = (struct menelaus_s *) opaque; -+ -+ s->rtc.sec ++; -+ s->rtc.next += 1000; -+ qemu_mod_timer(s->rtc.hz, s->rtc.next); -+ if ((s->rtc.ctrl >> 3) & 3) { /* EVERY */ -+ menelaus_rtc_update(s); -+ if (((s->rtc.ctrl >> 3) & 3) == 1 && !s->rtc.tm.tm_sec) -+ s->status |= 1 << 8; /* RTCTMR */ -+ else if (((s->rtc.ctrl >> 3) & 3) == 2 && !s->rtc.tm.tm_min) -+ s->status |= 1 << 8; /* RTCTMR */ -+ else if (!s->rtc.tm.tm_hour) -+ s->status |= 1 << 8; /* RTCTMR */ -+ } else -+ s->status |= 1 << 8; /* RTCTMR */ -+ if ((s->rtc.ctrl >> 1) & 1) { /* RTC_AL_EN */ -+ if (s->rtc.sec == s->rtc.alm_sec) -+ s->status |= 1 << 9; /* RTCALM */ -+ /* TODO: wake-up */ -+ } -+ if (s->rtc.next_comp >= s->rtc.sec) { -+ s->rtc.next -= muldiv64((int16_t) s->rtc.comp, 1000, 0x8000); -+ s->rtc.next_comp = s->rtc.sec + 3600; -+ } -+ menelaus_update(s); -+} -+ -+void menelaus_reset(i2c_slave *i2c) -+{ -+ struct menelaus_s *s = (struct menelaus_s *) i2c; -+ time_t ti; -+ s->reg = 0x00; -+ -+ s->vcore[0] = 0x0c; /* XXX: X-loader needs 0x8c? check! */ -+ s->vcore[1] = 0x05; -+ s->vcore[2] = 0x02; -+ s->vcore[3] = 0x0c; -+ s->vcore[4] = 0x03; -+ s->dcdc[0] = 0x33; /* Depends on wiring */ -+ s->dcdc[1] = 0x03; -+ s->dcdc[2] = 0x00; -+ s->ldo[0] = 0x95; -+ s->ldo[1] = 0x7e; -+ s->ldo[2] = 0x00; -+ s->ldo[3] = 0x00; /* Depends on wiring */ -+ s->ldo[4] = 0x03; /* Depends on wiring */ -+ s->ldo[5] = 0x00; -+ s->ldo[6] = 0x00; -+ s->ldo[7] = 0x00; -+ s->sleep[0] = 0x00; -+ s->sleep[1] = 0x00; -+ s->osc = 0x01; -+ s->detect = 0x09; -+ s->mask = 0x0fff; -+ s->status = 0; -+ s->dir = 0x07; -+ s->outputs = 0x00; -+ s->bbsms = 0x00; -+ s->pull[0] = 0x00; -+ s->pull[1] = 0x00; -+ s->pull[2] = 0x00; -+ s->pull[3] = 0x00; -+ s->mmc_ctrl[0] = 0x03; -+ s->mmc_ctrl[1] = 0xc0; -+ s->mmc_ctrl[2] = 0x00; -+ s->mmc_debounce = 0x05; -+ -+ time(&ti); -+ if (s->rtc.ctrl & 1) -+ menelaus_rtc_stop(s); -+ s->rtc.ctrl = 0x00; -+ s->rtc.comp = 0x0000; -+ s->rtc.next = 1000; -+ s->rtc.sec = ti; -+ s->rtc.next_comp = s->rtc.sec + 1800; -+ s->rtc.alm.tm_sec = 0x00; -+ s->rtc.alm.tm_min = 0x00; -+ s->rtc.alm.tm_hour = 0x00; -+ s->rtc.alm.tm_mday = 0x01; -+ s->rtc.alm.tm_mon = 0x00; -+ s->rtc.alm.tm_year = 2004; -+ menelaus_update(s); -+} -+ -+static inline uint8_t to_bcd(int val) -+{ -+ return ((val / 10) << 4) | (val % 10); -+} -+ -+static inline int from_bcd(uint8_t val) -+{ -+ return ((val >> 4) * 10) + (val & 0x0f); -+} -+ -+static void menelaus_gpio_set(void *opaque, int line, int level) -+{ -+ struct menelaus_s *s = (struct menelaus_s *) opaque; -+ -+ /* No interrupt generated */ -+ s->inputs &= ~(1 << line); -+ s->inputs |= level << line; -+} -+ -+static void menelaus_pwrbtn_set(void *opaque, int line, int level) -+{ -+ struct menelaus_s *s = (struct menelaus_s *) opaque; -+ -+ if (!s->pwrbtn_state && level) { -+ s->status |= 1 << 11; /* PSHBTN */ -+ menelaus_update(s); -+ } -+ s->pwrbtn_state = level; -+} -+ -+#define MENELAUS_REV 0x01 -+#define MENELAUS_VCORE_CTRL1 0x02 -+#define MENELAUS_VCORE_CTRL2 0x03 -+#define MENELAUS_VCORE_CTRL3 0x04 -+#define MENELAUS_VCORE_CTRL4 0x05 -+#define MENELAUS_VCORE_CTRL5 0x06 -+#define MENELAUS_DCDC_CTRL1 0x07 -+#define MENELAUS_DCDC_CTRL2 0x08 -+#define MENELAUS_DCDC_CTRL3 0x09 -+#define MENELAUS_LDO_CTRL1 0x0a -+#define MENELAUS_LDO_CTRL2 0x0b -+#define MENELAUS_LDO_CTRL3 0x0c -+#define MENELAUS_LDO_CTRL4 0x0d -+#define MENELAUS_LDO_CTRL5 0x0e -+#define MENELAUS_LDO_CTRL6 0x0f -+#define MENELAUS_LDO_CTRL7 0x10 -+#define MENELAUS_LDO_CTRL8 0x11 -+#define MENELAUS_SLEEP_CTRL1 0x12 -+#define MENELAUS_SLEEP_CTRL2 0x13 -+#define MENELAUS_DEVICE_OFF 0x14 -+#define MENELAUS_OSC_CTRL 0x15 -+#define MENELAUS_DETECT_CTRL 0x16 -+#define MENELAUS_INT_MASK1 0x17 -+#define MENELAUS_INT_MASK2 0x18 -+#define MENELAUS_INT_STATUS1 0x19 -+#define MENELAUS_INT_STATUS2 0x1a -+#define MENELAUS_INT_ACK1 0x1b -+#define MENELAUS_INT_ACK2 0x1c -+#define MENELAUS_GPIO_CTRL 0x1d -+#define MENELAUS_GPIO_IN 0x1e -+#define MENELAUS_GPIO_OUT 0x1f -+#define MENELAUS_BBSMS 0x20 -+#define MENELAUS_RTC_CTRL 0x21 -+#define MENELAUS_RTC_UPDATE 0x22 -+#define MENELAUS_RTC_SEC 0x23 -+#define MENELAUS_RTC_MIN 0x24 -+#define MENELAUS_RTC_HR 0x25 -+#define MENELAUS_RTC_DAY 0x26 -+#define MENELAUS_RTC_MON 0x27 -+#define MENELAUS_RTC_YR 0x28 -+#define MENELAUS_RTC_WKDAY 0x29 -+#define MENELAUS_RTC_AL_SEC 0x2a -+#define MENELAUS_RTC_AL_MIN 0x2b -+#define MENELAUS_RTC_AL_HR 0x2c -+#define MENELAUS_RTC_AL_DAY 0x2d -+#define MENELAUS_RTC_AL_MON 0x2e -+#define MENELAUS_RTC_AL_YR 0x2f -+#define MENELAUS_RTC_COMP_MSB 0x30 -+#define MENELAUS_RTC_COMP_LSB 0x31 -+#define MENELAUS_S1_PULL_EN 0x32 -+#define MENELAUS_S1_PULL_DIR 0x33 -+#define MENELAUS_S2_PULL_EN 0x34 -+#define MENELAUS_S2_PULL_DIR 0x35 -+#define MENELAUS_MCT_CTRL1 0x36 -+#define MENELAUS_MCT_CTRL2 0x37 -+#define MENELAUS_MCT_CTRL3 0x38 -+#define MENELAUS_MCT_PIN_ST 0x39 -+#define MENELAUS_DEBOUNCE1 0x3a -+ -+static uint8_t menelaus_read(void *opaque, uint8_t addr) -+{ -+ struct menelaus_s *s = (struct menelaus_s *) opaque; -+ int reg = 0; -+ -+ switch (addr) { -+ case MENELAUS_REV: -+ return 0x22; -+ -+ case MENELAUS_VCORE_CTRL5: reg ++; -+ case MENELAUS_VCORE_CTRL4: reg ++; -+ case MENELAUS_VCORE_CTRL3: reg ++; -+ case MENELAUS_VCORE_CTRL2: reg ++; -+ case MENELAUS_VCORE_CTRL1: -+ return s->vcore[reg]; -+ -+ case MENELAUS_DCDC_CTRL3: reg ++; -+ case MENELAUS_DCDC_CTRL2: reg ++; -+ case MENELAUS_DCDC_CTRL1: -+ return s->dcdc[reg]; -+ -+ case MENELAUS_LDO_CTRL8: reg ++; -+ case MENELAUS_LDO_CTRL7: reg ++; -+ case MENELAUS_LDO_CTRL6: reg ++; -+ case MENELAUS_LDO_CTRL5: reg ++; -+ case MENELAUS_LDO_CTRL4: reg ++; -+ case MENELAUS_LDO_CTRL3: reg ++; -+ case MENELAUS_LDO_CTRL2: reg ++; -+ case MENELAUS_LDO_CTRL1: -+ return s->ldo[reg]; -+ -+ case MENELAUS_SLEEP_CTRL2: reg ++; -+ case MENELAUS_SLEEP_CTRL1: -+ return s->sleep[reg]; -+ -+ case MENELAUS_DEVICE_OFF: -+ return 0; -+ -+ case MENELAUS_OSC_CTRL: -+ return s->osc | (1 << 7); /* CLK32K_GOOD */ -+ -+ case MENELAUS_DETECT_CTRL: -+ return s->detect; -+ -+ case MENELAUS_INT_MASK1: -+ return (s->mask >> 0) & 0xff; -+ case MENELAUS_INT_MASK2: -+ return (s->mask >> 8) & 0xff; -+ -+ case MENELAUS_INT_STATUS1: -+ return (s->status >> 0) & 0xff; -+ case MENELAUS_INT_STATUS2: -+ return (s->status >> 8) & 0xff; -+ -+ case MENELAUS_INT_ACK1: -+ case MENELAUS_INT_ACK2: -+ return 0; -+ -+ case MENELAUS_GPIO_CTRL: -+ return s->dir; -+ case MENELAUS_GPIO_IN: -+ return s->inputs | (~s->dir & s->outputs); -+ case MENELAUS_GPIO_OUT: -+ return s->outputs; -+ -+ case MENELAUS_BBSMS: -+ return s->bbsms; -+ -+ case MENELAUS_RTC_CTRL: -+ return s->rtc.ctrl; -+ case MENELAUS_RTC_UPDATE: -+ return 0x00; -+ case MENELAUS_RTC_SEC: -+ menelaus_rtc_update(s); -+ return to_bcd(s->rtc.tm.tm_sec); -+ case MENELAUS_RTC_MIN: -+ menelaus_rtc_update(s); -+ return to_bcd(s->rtc.tm.tm_min); -+ case MENELAUS_RTC_HR: -+ menelaus_rtc_update(s); -+ if ((s->rtc.ctrl >> 2) & 1) /* MODE12_n24 */ -+ return to_bcd((s->rtc.tm.tm_hour % 12) + 1) | -+ (!!(s->rtc.tm.tm_hour >= 12) << 7); /* PM_nAM */ -+ else -+ return to_bcd(s->rtc.tm.tm_hour); -+ case MENELAUS_RTC_DAY: -+ menelaus_rtc_update(s); -+ return to_bcd(s->rtc.tm.tm_mday); -+ case MENELAUS_RTC_MON: -+ menelaus_rtc_update(s); -+ return to_bcd(s->rtc.tm.tm_mon + 1); -+ case MENELAUS_RTC_YR: -+ menelaus_rtc_update(s); -+ return to_bcd(s->rtc.tm.tm_year - 2000); -+ case MENELAUS_RTC_WKDAY: -+ menelaus_rtc_update(s); -+ return to_bcd(s->rtc.tm.tm_wday); -+ case MENELAUS_RTC_AL_SEC: -+ return to_bcd(s->rtc.alm.tm_sec); -+ case MENELAUS_RTC_AL_MIN: -+ return to_bcd(s->rtc.alm.tm_min); -+ case MENELAUS_RTC_AL_HR: -+ if ((s->rtc.ctrl >> 2) & 1) /* MODE12_n24 */ -+ return to_bcd((s->rtc.alm.tm_hour % 12) + 1) | -+ (!!(s->rtc.alm.tm_hour >= 12) << 7);/* AL_PM_nAM */ -+ else -+ return to_bcd(s->rtc.alm.tm_hour); -+ case MENELAUS_RTC_AL_DAY: -+ return to_bcd(s->rtc.alm.tm_mday); -+ case MENELAUS_RTC_AL_MON: -+ return to_bcd(s->rtc.alm.tm_mon + 1); -+ case MENELAUS_RTC_AL_YR: -+ return to_bcd(s->rtc.alm.tm_year - 2000); -+ case MENELAUS_RTC_COMP_MSB: -+ return (s->rtc.comp >> 8) & 0xff; -+ case MENELAUS_RTC_COMP_LSB: -+ return (s->rtc.comp >> 0) & 0xff; -+ -+ case MENELAUS_S1_PULL_EN: -+ return s->pull[0]; -+ case MENELAUS_S1_PULL_DIR: -+ return s->pull[1]; -+ case MENELAUS_S2_PULL_EN: -+ return s->pull[2]; -+ case MENELAUS_S2_PULL_DIR: -+ return s->pull[3]; -+ -+ case MENELAUS_MCT_CTRL3: reg ++; -+ case MENELAUS_MCT_CTRL2: reg ++; -+ case MENELAUS_MCT_CTRL1: -+ return s->mmc_ctrl[reg]; -+ case MENELAUS_MCT_PIN_ST: -+ /* TODO: return the real Card Detect */ -+ return 0; -+ case MENELAUS_DEBOUNCE1: -+ return s->mmc_debounce; -+ -+ default: -+#ifdef VERBOSE -+ printf("%s: unknown register %02x\n", __FUNCTION__, addr); -+#endif -+ break; -+ } -+ return 0; -+} -+ -+static void menelaus_write(void *opaque, uint8_t addr, uint8_t value) -+{ -+ struct menelaus_s *s = (struct menelaus_s *) opaque; -+ int line; -+ int reg = 0; -+ struct tm tm; -+ -+ switch (addr) { -+ case MENELAUS_VCORE_CTRL1: -+ s->vcore[0] = (value & 0xe) | MIN(value & 0x1f, 0x12); -+ break; -+ case MENELAUS_VCORE_CTRL2: -+ s->vcore[1] = value; -+ break; -+ case MENELAUS_VCORE_CTRL3: -+ s->vcore[2] = MIN(value & 0x1f, 0x12); -+ break; -+ case MENELAUS_VCORE_CTRL4: -+ s->vcore[3] = MIN(value & 0x1f, 0x12); -+ break; -+ case MENELAUS_VCORE_CTRL5: -+ s->vcore[4] = value & 3; -+ /* XXX -+ * auto set to 3 on M_Active, nRESWARM -+ * auto set to 0 on M_WaitOn, M_Backup -+ */ -+ break; -+ -+ case MENELAUS_DCDC_CTRL1: -+ s->dcdc[0] = value & 0x3f; -+ break; -+ case MENELAUS_DCDC_CTRL2: -+ s->dcdc[1] = value & 0x07; -+ /* XXX -+ * auto set to 3 on M_Active, nRESWARM -+ * auto set to 0 on M_WaitOn, M_Backup -+ */ -+ break; -+ case MENELAUS_DCDC_CTRL3: -+ s->dcdc[2] = value & 0x07; -+ break; -+ -+ case MENELAUS_LDO_CTRL1: -+ s->ldo[0] = value; -+ break; -+ case MENELAUS_LDO_CTRL2: -+ s->ldo[1] = value & 0x7f; -+ /* XXX -+ * auto set to 0x7e on M_WaitOn, M_Backup -+ */ -+ break; -+ case MENELAUS_LDO_CTRL3: -+ s->ldo[2] = value & 3; -+ /* XXX -+ * auto set to 3 on M_Active, nRESWARM -+ * auto set to 0 on M_WaitOn, M_Backup -+ */ -+ break; -+ case MENELAUS_LDO_CTRL4: -+ s->ldo[3] = value & 3; -+ /* XXX -+ * auto set to 3 on M_Active, nRESWARM -+ * auto set to 0 on M_WaitOn, M_Backup -+ */ -+ break; -+ case MENELAUS_LDO_CTRL5: -+ s->ldo[4] = value & 3; -+ /* XXX -+ * auto set to 3 on M_Active, nRESWARM -+ * auto set to 0 on M_WaitOn, M_Backup -+ */ -+ break; -+ case MENELAUS_LDO_CTRL6: -+ s->ldo[5] = value & 3; -+ break; -+ case MENELAUS_LDO_CTRL7: -+ s->ldo[6] = value & 3; -+ break; -+ case MENELAUS_LDO_CTRL8: -+ s->ldo[7] = value & 3; -+ break; -+ -+ case MENELAUS_SLEEP_CTRL2: reg ++; -+ case MENELAUS_SLEEP_CTRL1: -+ s->sleep[reg] = value; -+ break; -+ -+ case MENELAUS_DEVICE_OFF: -+ if (value & 1) -+ menelaus_reset(&s->i2c); -+ break; -+ -+ case MENELAUS_OSC_CTRL: -+ s->osc = value & 7; -+ break; -+ -+ case MENELAUS_DETECT_CTRL: -+ s->detect = value & 0x7f; -+ break; -+ -+ case MENELAUS_INT_MASK1: -+ s->mask &= 0xf00; -+ s->mask |= value << 0; -+ menelaus_update(s); -+ break; -+ case MENELAUS_INT_MASK2: -+ s->mask &= 0x0ff; -+ s->mask |= value << 8; -+ menelaus_update(s); -+ break; -+ -+ case MENELAUS_INT_ACK1: -+ s->status &= ~(((uint16_t) value) << 0); -+ menelaus_update(s); -+ break; -+ case MENELAUS_INT_ACK2: -+ s->status &= ~(((uint16_t) value) << 8); -+ menelaus_update(s); -+ break; -+ -+ case MENELAUS_GPIO_CTRL: -+ for (line = 0; line < 3; line ++) -+ if (((s->dir ^ value) >> line) & 1) -+ if (s->handler[line]) -+ qemu_set_irq(s->handler[line], -+ ((s->outputs & ~s->dir) >> line) & 1); -+ s->dir = value & 0x67; -+ break; -+ case MENELAUS_GPIO_OUT: -+ for (line = 0; line < 3; line ++) -+ if ((((s->outputs ^ value) & ~s->dir) >> line) & 1) -+ if (s->handler[line]) -+ qemu_set_irq(s->handler[line], (s->outputs >> line) & 1); -+ s->outputs = value & 0x07; -+ break; -+ -+ case MENELAUS_BBSMS: -+ s->bbsms = 0x0d; -+ break; -+ -+ case MENELAUS_RTC_CTRL: -+ if ((s->rtc.ctrl ^ value) & 1) { /* RTC_EN */ -+ if (value & 1) -+ menelaus_rtc_start(s); -+ else -+ menelaus_rtc_stop(s); -+ } -+ s->rtc.ctrl = value & 0x1f; -+ menelaus_alm_update(s); -+ break; -+ case MENELAUS_RTC_UPDATE: -+ menelaus_rtc_update(s); -+ memcpy(&tm, &s->rtc.tm, sizeof(tm)); -+ switch (value & 0xf) { -+ case 0: -+ break; -+ case 1: -+ tm.tm_sec = s->rtc.new.tm_sec; -+ break; -+ case 2: -+ tm.tm_min = s->rtc.new.tm_min; -+ break; -+ case 3: -+ if (s->rtc.new.tm_hour > 23) -+ goto rtc_badness; -+ tm.tm_hour = s->rtc.new.tm_hour; -+ break; -+ case 4: -+ if (s->rtc.new.tm_mday < 1) -+ goto rtc_badness; -+ /* TODO check range */ -+ tm.tm_mday = s->rtc.new.tm_mday; -+ break; -+ case 5: -+ if (s->rtc.new.tm_mon < 0 || s->rtc.new.tm_mon > 11) -+ goto rtc_badness; -+ tm.tm_mon = s->rtc.new.tm_mon; -+ break; -+ case 6: -+ tm.tm_year = s->rtc.new.tm_year; -+ break; -+ case 7: -+ /* TODO set .tm_mday instead */ -+ tm.tm_wday = s->rtc.new.tm_wday; -+ break; -+ case 8: -+ if (s->rtc.new.tm_hour > 23) -+ goto rtc_badness; -+ if (s->rtc.new.tm_mday < 1) -+ goto rtc_badness; -+ if (s->rtc.new.tm_mon < 0 || s->rtc.new.tm_mon > 11) -+ goto rtc_badness; -+ tm.tm_sec = s->rtc.new.tm_sec; -+ tm.tm_min = s->rtc.new.tm_min; -+ tm.tm_hour = s->rtc.new.tm_hour; -+ tm.tm_mday = s->rtc.new.tm_mday; -+ tm.tm_mon = s->rtc.new.tm_mon; -+ tm.tm_year = s->rtc.new.tm_year; -+ break; -+ rtc_badness: -+ default: -+ fprintf(stderr, "%s: bad RTC_UPDATE value %02x\n", -+ __FUNCTION__, value); -+ s->status |= 1 << 10; /* RTCERR */ -+ menelaus_update(s); -+ } -+ s->rtc.sec += difftime(mktime(&tm), mktime(&s->rtc.tm)); -+ break; -+ case MENELAUS_RTC_SEC: -+ s->rtc.tm.tm_sec = from_bcd(value & 0x7f); -+ break; -+ case MENELAUS_RTC_MIN: -+ s->rtc.tm.tm_min = from_bcd(value & 0x7f); -+ break; -+ case MENELAUS_RTC_HR: -+ s->rtc.tm.tm_hour = (s->rtc.ctrl & (1 << 2)) ? /* MODE12_n24 */ -+ MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) : -+ from_bcd(value & 0x3f); -+ break; -+ case MENELAUS_RTC_DAY: -+ s->rtc.tm.tm_mday = from_bcd(value); -+ break; -+ case MENELAUS_RTC_MON: -+ s->rtc.tm.tm_mon = MAX(1, from_bcd(value)) - 1; -+ break; -+ case MENELAUS_RTC_YR: -+ s->rtc.tm.tm_year = 2000 + from_bcd(value); -+ break; -+ case MENELAUS_RTC_WKDAY: -+ s->rtc.tm.tm_mday = from_bcd(value); -+ break; -+ case MENELAUS_RTC_AL_SEC: -+ s->rtc.alm.tm_sec = from_bcd(value & 0x7f); -+ menelaus_alm_update(s); -+ break; -+ case MENELAUS_RTC_AL_MIN: -+ s->rtc.alm.tm_min = from_bcd(value & 0x7f); -+ menelaus_alm_update(s); -+ break; -+ case MENELAUS_RTC_AL_HR: -+ s->rtc.alm.tm_hour = (s->rtc.ctrl & (1 << 2)) ? /* MODE12_n24 */ -+ MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) : -+ from_bcd(value & 0x3f); -+ menelaus_alm_update(s); -+ break; -+ case MENELAUS_RTC_AL_DAY: -+ s->rtc.alm.tm_mday = from_bcd(value); -+ menelaus_alm_update(s); -+ break; -+ case MENELAUS_RTC_AL_MON: -+ s->rtc.alm.tm_mon = MAX(1, from_bcd(value)) - 1; -+ menelaus_alm_update(s); -+ break; -+ case MENELAUS_RTC_AL_YR: -+ s->rtc.alm.tm_year = 2000 + from_bcd(value); -+ menelaus_alm_update(s); -+ break; -+ case MENELAUS_RTC_COMP_MSB: -+ s->rtc.comp &= 0xff; -+ s->rtc.comp |= value << 8; -+ break; -+ case MENELAUS_RTC_COMP_LSB: -+ s->rtc.comp &= 0xff << 8; -+ s->rtc.comp |= value; -+ break; -+ -+ case MENELAUS_S1_PULL_EN: -+ s->pull[0] = value; -+ break; -+ case MENELAUS_S1_PULL_DIR: -+ s->pull[1] = value & 0x1f; -+ break; -+ case MENELAUS_S2_PULL_EN: -+ s->pull[2] = value; -+ break; -+ case MENELAUS_S2_PULL_DIR: -+ s->pull[3] = value & 0x1f; -+ break; -+ -+ case MENELAUS_MCT_CTRL1: -+ s->mmc_ctrl[0] = value & 0x7f; -+ break; -+ case MENELAUS_MCT_CTRL2: -+ s->mmc_ctrl[1] = value; -+ /* TODO update Card Detect interrupts */ -+ break; -+ case MENELAUS_MCT_CTRL3: -+ s->mmc_ctrl[2] = value & 0xf; -+ break; -+ case MENELAUS_DEBOUNCE1: -+ s->mmc_debounce = value & 0x3f; -+ break; -+ -+ default: -+#ifdef VERBOSE -+ printf("%s: unknown register %02x\n", __FUNCTION__, addr); -+#endif -+ } -+} -+ -+static void menelaus_event(i2c_slave *i2c, enum i2c_event event) -+{ -+ struct menelaus_s *s = (struct menelaus_s *) i2c; -+ -+ if (event == I2C_START_SEND) -+ s->firstbyte = 1; -+} -+ -+static int menelaus_tx(i2c_slave *i2c, uint8_t data) -+{ -+ struct menelaus_s *s = (struct menelaus_s *) i2c; -+ /* Interpret register address byte */ -+ if (s->firstbyte) { -+ s->reg = data; -+ s->firstbyte = 0; -+ } else -+ menelaus_write(s, s->reg ++, data); -+ -+ return 0; -+} -+ -+static int menelaus_rx(i2c_slave *i2c) -+{ -+ struct menelaus_s *s = (struct menelaus_s *) i2c; -+ -+ return menelaus_read(s, s->reg ++); -+} -+ -+static void tm_put(QEMUFile *f, struct tm *tm) { -+ qemu_put_be16(f, tm->tm_sec); -+ qemu_put_be16(f, tm->tm_min); -+ qemu_put_be16(f, tm->tm_hour); -+ qemu_put_be16(f, tm->tm_mday); -+ qemu_put_be16(f, tm->tm_min); -+ qemu_put_be16(f, tm->tm_year); -+} -+ -+static void tm_get(QEMUFile *f, struct tm *tm) { -+ tm->tm_sec = qemu_get_be16(f); -+ tm->tm_min = qemu_get_be16(f); -+ tm->tm_hour = qemu_get_be16(f); -+ tm->tm_mday = qemu_get_be16(f); -+ tm->tm_min = qemu_get_be16(f); -+ tm->tm_year = qemu_get_be16(f); -+} -+ -+static void menelaus_save(QEMUFile *f, void *opaque) -+{ -+ struct menelaus_s *s = (struct menelaus_s *) opaque; -+ -+ qemu_put_be32(f, s->firstbyte); -+ qemu_put_8s(f, &s->reg); -+ -+ qemu_put_8s(f, &s->vcore[0]); -+ qemu_put_8s(f, &s->vcore[1]); -+ qemu_put_8s(f, &s->vcore[2]); -+ qemu_put_8s(f, &s->vcore[3]); -+ qemu_put_8s(f, &s->vcore[4]); -+ qemu_put_8s(f, &s->dcdc[3]); -+ qemu_put_8s(f, &s->dcdc[3]); -+ qemu_put_8s(f, &s->dcdc[3]); -+ qemu_put_8s(f, &s->ldo[0]); -+ qemu_put_8s(f, &s->ldo[1]); -+ qemu_put_8s(f, &s->ldo[2]); -+ qemu_put_8s(f, &s->ldo[3]); -+ qemu_put_8s(f, &s->ldo[4]); -+ qemu_put_8s(f, &s->ldo[5]); -+ qemu_put_8s(f, &s->ldo[6]); -+ qemu_put_8s(f, &s->ldo[7]); -+ qemu_put_8s(f, &s->sleep[0]); -+ qemu_put_8s(f, &s->sleep[1]); -+ qemu_put_8s(f, &s->osc); -+ qemu_put_8s(f, &s->detect); -+ qemu_put_be16s(f, &s->mask); -+ qemu_put_be16s(f, &s->status); -+ qemu_put_8s(f, &s->dir); -+ qemu_put_8s(f, &s->inputs); -+ qemu_put_8s(f, &s->outputs); -+ qemu_put_8s(f, &s->bbsms); -+ qemu_put_8s(f, &s->pull[0]); -+ qemu_put_8s(f, &s->pull[1]); -+ qemu_put_8s(f, &s->pull[2]); -+ qemu_put_8s(f, &s->pull[3]); -+ qemu_put_8s(f, &s->mmc_ctrl[0]); -+ qemu_put_8s(f, &s->mmc_ctrl[1]); -+ qemu_put_8s(f, &s->mmc_ctrl[2]); -+ qemu_put_8s(f, &s->mmc_debounce); -+ qemu_put_8s(f, &s->rtc.ctrl); -+ qemu_put_be16s(f, &s->rtc.comp); -+ /* Should be <= 1000 */ -+ qemu_put_be16(f, s->rtc.next - qemu_get_clock(rt_clock)); -+ tm_put(f, &s->rtc.new); -+ tm_put(f, &s->rtc.alm); -+ qemu_put_byte(f, s->pwrbtn_state); -+ -+ i2c_slave_save(f, &s->i2c); -+} -+ -+static int menelaus_load(QEMUFile *f, void *opaque, int version_id) -+{ -+ struct menelaus_s *s = (struct menelaus_s *) opaque; -+ -+ s->firstbyte = qemu_get_be32(f); -+ qemu_get_8s(f, &s->reg); -+ -+ if (s->rtc.ctrl & 1) /* RTC_EN */ -+ menelaus_rtc_stop(s); -+ qemu_get_8s(f, &s->vcore[0]); -+ qemu_get_8s(f, &s->vcore[1]); -+ qemu_get_8s(f, &s->vcore[2]); -+ qemu_get_8s(f, &s->vcore[3]); -+ qemu_get_8s(f, &s->vcore[4]); -+ qemu_get_8s(f, &s->dcdc[3]); -+ qemu_get_8s(f, &s->dcdc[3]); -+ qemu_get_8s(f, &s->dcdc[3]); -+ qemu_get_8s(f, &s->ldo[0]); -+ qemu_get_8s(f, &s->ldo[1]); -+ qemu_get_8s(f, &s->ldo[2]); -+ qemu_get_8s(f, &s->ldo[3]); -+ qemu_get_8s(f, &s->ldo[4]); -+ qemu_get_8s(f, &s->ldo[5]); -+ qemu_get_8s(f, &s->ldo[6]); -+ qemu_get_8s(f, &s->ldo[7]); -+ qemu_get_8s(f, &s->sleep[0]); -+ qemu_get_8s(f, &s->sleep[1]); -+ qemu_get_8s(f, &s->osc); -+ qemu_get_8s(f, &s->detect); -+ qemu_get_be16s(f, &s->mask); -+ qemu_get_be16s(f, &s->status); -+ qemu_get_8s(f, &s->dir); -+ qemu_get_8s(f, &s->inputs); -+ qemu_get_8s(f, &s->outputs); -+ qemu_get_8s(f, &s->bbsms); -+ qemu_get_8s(f, &s->pull[0]); -+ qemu_get_8s(f, &s->pull[1]); -+ qemu_get_8s(f, &s->pull[2]); -+ qemu_get_8s(f, &s->pull[3]); -+ qemu_get_8s(f, &s->mmc_ctrl[0]); -+ qemu_get_8s(f, &s->mmc_ctrl[1]); -+ qemu_get_8s(f, &s->mmc_ctrl[2]); -+ qemu_get_8s(f, &s->mmc_debounce); -+ qemu_get_8s(f, &s->rtc.ctrl); -+ qemu_get_be16s(f, &s->rtc.comp); -+ s->rtc.next = qemu_get_be16(f); -+ tm_get(f, &s->rtc.new); -+ tm_get(f, &s->rtc.alm); -+ s->pwrbtn_state = qemu_get_byte(f); -+ menelaus_alm_update(s); -+ menelaus_update(s); -+ if (s->rtc.ctrl & 1) /* RTC_EN */ -+ menelaus_rtc_start(s); -+ -+ i2c_slave_load(f, &s->i2c); -+ return 0; -+} -+ -+static int menelaus_iid = 0; -+ -+i2c_slave *twl92230_init(i2c_bus *bus, qemu_irq irq) -+{ -+ struct menelaus_s *s = (struct menelaus_s *) -+ i2c_slave_init(bus, 0, sizeof(struct menelaus_s)); -+ -+ s->i2c.event = menelaus_event; -+ s->i2c.recv = menelaus_rx; -+ s->i2c.send = menelaus_tx; -+ -+ /* TODO: use the qemu gettime functions */ -+ s->rtc.gettime = localtime_r; -+ -+ s->irq = irq; -+ s->rtc.hz = 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]; -+ -+ menelaus_reset(&s->i2c); -+ -+ register_savevm("menelaus", menelaus_iid ++, -+ 0, menelaus_save, menelaus_load, s); -+ -+ return &s->i2c; -+} -+ -+qemu_irq *twl92230_gpio_in_get(i2c_slave *i2c) -+{ -+ struct menelaus_s *s = (struct menelaus_s *) i2c; -+ -+ return s->in; -+} -+ -+void twl92230_gpio_out_set(i2c_slave *i2c, int line, qemu_irq handler) -+{ -+ struct menelaus_s *s = (struct menelaus_s *) i2c; -+ -+ if (line >= 3 || line < 0) { -+ fprintf(stderr, "%s: No GPO line %i\n", __FUNCTION__, line); -+ exit(-1); -+ } -+ s->handler[line] = handler; -+} -diff --git a/hw/versatilepb.c b/hw/versatilepb.c -index da6e4ec..ecc0037 100644 ---- a/hw/versatilepb.c -+++ b/hw/versatilepb.c -@@ -157,6 +157,8 @@ static qemu_irq *vpb_sic_init(uint32_t base, qemu_irq *parent, int irq) - peripherans and expansion busses. For now we emulate a subset of the - PB peripherals and just change the board ID. */ - -+static struct arm_boot_info versatile_binfo; -+ - static void versatile_init(int ram_size, int vga_ram_size, - const char *boot_device, DisplayState *ds, - const char *kernel_filename, const char *kernel_cmdline, -@@ -283,8 +285,12 @@ static void versatile_init(int ram_size, int vga_ram_size, - /* 0x101f3000 UART2. */ - /* 0x101f4000 SSPI. */ - -- arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline, -- initrd_filename, board_id, 0x0); -+ versatile_binfo.ram_size = ram_size; -+ versatile_binfo.kernel_filename = kernel_filename; -+ versatile_binfo.kernel_cmdline = kernel_cmdline; -+ versatile_binfo.initrd_filename = initrd_filename; -+ versatile_binfo.board_id = board_id; -+ arm_load_kernel(env, &versatile_binfo); - } - - static void vpb_init(int ram_size, int vga_ram_size, -diff --git a/softmmu_template.h b/softmmu_template.h -index 0a4bc7e..d480f34 100644 ---- a/softmmu_template.h -+++ b/softmmu_template.h -@@ -51,12 +51,15 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, - int mmu_idx, - void *retaddr); - static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr, -- target_ulong tlb_addr) -+ target_ulong tlb_addr, -+ target_ulong tlb_io) - { - DATA_TYPE res; - int index; - -- index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); -+ index = (tlb_addr & ~TARGET_PAGE_MASK) >> IO_MEM_SHIFT; -+ if (index > 4) -+ index = (tlb_io >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); - #if SHIFT <= 2 - res = io_mem_read[index][SHIFT](io_mem_opaque[index], physaddr); - #else -@@ -95,7 +98,9 @@ DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, - /* IO access */ - if ((addr & (DATA_SIZE - 1)) != 0) - goto do_unaligned_access; -- res = glue(io_read, SUFFIX)(physaddr, tlb_addr); -+ res = glue(io_read, SUFFIX)(physaddr, tlb_addr, -+ env->tlb_table[mmu_idx] -+ [index].addr_code); - } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { - /* slow unaligned access (it spans two pages or IO) */ - do_unaligned_access: -@@ -147,7 +152,9 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, - /* IO access */ - if ((addr & (DATA_SIZE - 1)) != 0) - goto do_unaligned_access; -- res = glue(io_read, SUFFIX)(physaddr, tlb_addr); -+ res = glue(io_read, SUFFIX)(physaddr, tlb_addr, -+ env->tlb_table[mmu_idx] -+ [index].addr_code); - } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { - do_unaligned_access: - /* slow unaligned access (it spans two pages) */ -@@ -186,11 +193,14 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr, - static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr, - DATA_TYPE val, - target_ulong tlb_addr, -- void *retaddr) -+ void *retaddr, -+ target_ulong tlb_io) - { - int index; - -- index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); -+ index = (tlb_addr & ~TARGET_PAGE_MASK) >> IO_MEM_SHIFT; -+ if (index > 4) -+ index = (tlb_io >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); - env->mem_write_vaddr = tlb_addr; - env->mem_write_pc = (unsigned long)retaddr; - #if SHIFT <= 2 -@@ -228,7 +238,8 @@ void REGPARM glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, - if ((addr & (DATA_SIZE - 1)) != 0) - goto do_unaligned_access; - retaddr = GETPC(); -- glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr); -+ glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr, -+ env->tlb_table[mmu_idx][index].addr_code); - } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { - do_unaligned_access: - retaddr = GETPC(); -@@ -278,7 +289,8 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr, - /* IO access */ - if ((addr & (DATA_SIZE - 1)) != 0) - goto do_unaligned_access; -- glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr); -+ glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr, -+ env->tlb_table[mmu_idx][index].addr_code); - } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { - do_unaligned_access: - /* XXX: not efficient, but simple */ -diff --git a/target-arm/cpu.h b/target-arm/cpu.h -index b284a21..633b335 100644 ---- a/target-arm/cpu.h -+++ b/target-arm/cpu.h -@@ -198,12 +198,16 @@ typedef struct CPUARMState { - CPU_COMMON - - /* These fields after the common ones so they are preserved on reset. */ -- int ram_size; -- const char *kernel_filename; -- const char *kernel_cmdline; -- const char *initrd_filename; -- int board_id; -- target_phys_addr_t loader_start; -+ struct arm_boot_info { -+ int ram_size; -+ const char *kernel_filename; -+ const char *kernel_cmdline; -+ const char *initrd_filename; -+ target_phys_addr_t loader_start; -+ int nb_cpus; -+ int board_id; -+ int (*atag_board)(struct arm_boot_info *info, void *p); -+ } *boot_info; - } CPUARMState; - - CPUARMState *cpu_arm_init(const char *cpu_model); -@@ -377,6 +381,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum, - #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 -diff --git a/target-arm/helper.c b/target-arm/helper.c -index 86470db..0709129 100644 ---- a/target-arm/helper.c -+++ b/target-arm/helper.c -@@ -53,6 +53,9 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) - env->cp15.c0_cachetype = 0x1dd20d2; - env->cp15.c1_sys = 0x00090078; - break; -+ case ARM_CPUID_ARM1136_R2: -+ /* TODO! */ -+ env->GE = 0x5; - case ARM_CPUID_ARM1136: - set_feature(env, ARM_FEATURE_V6); - set_feature(env, ARM_FEATURE_VFP); -@@ -198,6 +201,7 @@ static const struct arm_cpu_t arm_cpu_names[] = { - { ARM_CPUID_ARM946, "arm946"}, - { ARM_CPUID_ARM1026, "arm1026"}, - { ARM_CPUID_ARM1136, "arm1136"}, -+ { ARM_CPUID_ARM1136_R2, "arm1136-r2"}, - { ARM_CPUID_ARM11MPCORE, "arm11mpcore"}, - { ARM_CPUID_CORTEXM3, "cortex-m3"}, - { ARM_CPUID_CORTEXA8, "cortex-a8"}, -@@ -1539,6 +1543,7 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn) - case ARM_CPUID_ARM1026: - return 1; - case ARM_CPUID_ARM1136: -+ case ARM_CPUID_ARM1136_R2: - return 7; - case ARM_CPUID_ARM11MPCORE: - return 1; -@@ -1721,6 +1726,10 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn) - case 8: /* TI925T_status */ - return 0; - } -+ /* TODO: Peripheral port remap register: -+ * On OMAP2 mcr p15, 0, rn, c15, c2, 4 sets up the interrupt -+ * controller base address at $rn & ~0xfff and map size of -+ * 0x200 << ($rn & 0xfff), when MMU is off. */ - goto bad_reg; - } - return 0; -diff --git a/vl.c b/vl.c -index d371af7..76d8def 100644 ---- a/vl.c -+++ b/vl.c -@@ -8006,6 +8006,7 @@ static void register_machines(void) - qemu_register_machine(&borzoipda_machine); - qemu_register_machine(&terrierpda_machine); - qemu_register_machine(&palmte_machine); -+ qemu_register_machine(&n800_machine); - qemu_register_machine(&lm3s811evb_machine); - qemu_register_machine(&lm3s6965evb_machine); - qemu_register_machine(&connex_machine); diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/series b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/series deleted file mode 100644 index 126da88288..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/series +++ /dev/null @@ -1,25 +0,0 @@ -02_snapshot_use_tmpdir.patch -p0 -05_non-fatal_if_linux_hd_missing.patch -p1 -06_exit_segfault.patch -p0 -10_signal_jobs.patch -p0 -11_signal_sigaction.patch -p0 -22_net_tuntap_stall.patch -p0 -31_syscalls.patch -p0 -32_syscall_sysctl.patch -p0 -33_syscall_ppc_clone.patch -p0 -39_syscall_fadvise64.patch -p0 -41_arm_fpa_sigfpe.patch -p0 -52_ne2000_return.patch -p1 -61_safe_64bit_int.patch -p0 -63_sparc_build.patch -p0 -64_ppc_asm_constraints.patch -p1 -65_kfreebsd.patch -p0 -66_tls_ld.patch -p0 -91-oh-sdl-cursor.patch -p0 -qemu-0.9.0-nptl.patch -p1 -qemu-0.9.0-nptl-update.patch -p1 -qemu-amd64-32b-mapping-0.9.0.patch -p1 -workaround_bad_futex_headers.patch -p1 -fix_segfault.patch -p1 -no-strip.patch -p1 -qemu-n800-support.patch -p1 diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/workaround_bad_futex_headers.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/workaround_bad_futex_headers.patch deleted file mode 100644 index cc122ebdba..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/workaround_bad_futex_headers.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- - linux-user/syscall.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -Index: qemu/linux-user/syscall.c -=================================================================== ---- qemu.orig/linux-user/syscall.c 2007-08-09 20:28:06.000000000 +0100 -+++ qemu/linux-user/syscall.c 2007-08-09 20:28:41.000000000 +0100 -@@ -61,7 +61,15 @@ - #define tchars host_tchars /* same as target */ - #define ltchars host_ltchars /* same as target */ - --#include -+#define FUTEX_WAIT 0 -+#define FUTEX_WAKE 1 -+#define FUTEX_FD 2 -+#define FUTEX_REQUEUE 3 -+#define FUTEX_CMP_REQUEUE 4 -+#define FUTEX_WAKE_OP 5 -+#define FUTEX_LOCK_PI 6 -+#define FUTEX_UNLOCK_PI 7 -+ - #include - #include - #include diff --git a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/writev_fix.patch b/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/writev_fix.patch deleted file mode 100644 index e0ed4af972..0000000000 --- a/meta/packages/qemu/qemu-native-0.9.1+cvs20080307/writev_fix.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- - linux-user/syscall.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Index: qemu-0.9.1/linux-user/syscall.c -=================================================================== ---- qemu-0.9.1.orig/linux-user/syscall.c 2008-02-03 00:00:00.000000000 +0000 -+++ qemu-0.9.1/linux-user/syscall.c 2008-02-03 00:00:38.000000000 +0000 -@@ -1048,7 +1048,7 @@ static abi_long lock_iovec(int type, str - base = tswapl(target_vec[i].iov_base); - vec[i].iov_len = tswapl(target_vec[i].iov_len); - vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy); -- if (!vec[i].iov_base) -+ if (!vec[i].iov_base && vec[i].iov_len) - goto fail; - } - unlock_user (target_vec, target_addr, 0); diff --git a/meta/packages/qemu/qemu-sdk_cvs.bb b/meta/packages/qemu/qemu-sdk_cvs.bb new file mode 100644 index 0000000000..e93e6bb757 --- /dev/null +++ b/meta/packages/qemu/qemu-sdk_cvs.bb @@ -0,0 +1,4 @@ +require qemu_${PV}.bb +require qemu-sdk.inc + +EXTRA_OECONF += "--target-list=arm-linux-user,arm-softmmu" diff --git a/meta/packages/qemu/qemu_cvs.bb b/meta/packages/qemu/qemu_cvs.bb index 6cf70bd874..f21efbc146 100644 --- a/meta/packages/qemu/qemu_cvs.bb +++ b/meta/packages/qemu/qemu_cvs.bb @@ -3,6 +3,7 @@ DEPENDS = "zlib" PV = "0.9.1+cvs${SRCDATE}" PR = "r2" +FILESPATH = "${FILE_DIRNAME}/qemu-${PV}" FILESDIR = "${WORKDIR}" SRC_URI = "\ -- cgit v1.2.3