summaryrefslogtreecommitdiffstats
path: root/meta/packages/qemu
diff options
context:
space:
mode:
authorMarcin Juszkiewicz <hrw@openedhand.com>2008-04-23 10:40:00 +0000
committerMarcin Juszkiewicz <hrw@openedhand.com>2008-04-23 10:40:00 +0000
commitb37a06703c214768619cc2816ae3af34bf6a7511 (patch)
tree72efae4280a66a7aa813fb072b76f8ceb84f797d /meta/packages/qemu
parenta2513fb4c43954296aab493312bb6dbd8299c4c9 (diff)
downloadpoky-b37a06703c214768619cc2816ae3af34bf6a7511.tar.gz
qemu: added SVN recipes
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@4322 311d38ba-8fff-0310-9ca6-ca027cbcb966
Diffstat (limited to 'meta/packages/qemu')
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/02_snapshot_use_tmpdir.patch23
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/04_do_not_print_rtc_freq_if_ok.patch26
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/05_non-fatal_if_linux_hd_missing.patch17
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/06_exit_segfault.patch45
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/10_signal_jobs.patch26
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/11_signal_sigaction.patch21
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/22_net_tuntap_stall.patch18
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/31_syscalls.patch48
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/32_syscall_sysctl.patch55
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/33_syscall_ppc_clone.patch22
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/39_syscall_fadvise64.patch21
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/41_arm_fpa_sigfpe.patch104
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/52_ne2000_return.patch17
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/61_safe_64bit_int.patch27
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/63_sparc_build.patch18
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/64_ppc_asm_constraints.patch18
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/65_kfreebsd.patch35
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/66_tls_ld.patch55
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/91-oh-sdl-cursor.patch18
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/configure_symlinkpath_fix.patch28
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/disable-error-in-configure.patch17
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/fix_segfault.patch37
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/no-strip.patch22
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl-update.patch219
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl.patch854
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/qemu-amd64-32b-mapping-0.9.0.patch37
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/qemu-n800-support.patch13970
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/series25
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/workaround_bad_futex_headers.patch25
-rw-r--r--meta/packages/qemu/qemu-0.9.1+svn/writev_fix.patch17
-rw-r--r--meta/packages/qemu/qemu-native_svn.bb2
-rw-r--r--meta/packages/qemu/qemu-sdk_svn.bb4
-rw-r--r--meta/packages/qemu/qemu_svn.bb46
33 files changed, 15917 insertions, 0 deletions
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/02_snapshot_use_tmpdir.patch b/meta/packages/qemu/qemu-0.9.1+svn/02_snapshot_use_tmpdir.patch
new file mode 100644
index 0000000000..40264ed443
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/02_snapshot_use_tmpdir.patch
@@ -0,0 +1,23 @@
1#DPATCHLEVEL=0
2---
3# block.c | 6 +++++-
4# 1 file changed, 5 insertions(+), 1 deletion(-)
5#
6Index: block.c
7===================================================================
8--- block.c.orig 2007-12-03 23:47:25.000000000 +0000
9+++ block.c 2007-12-03 23:47:31.000000000 +0000
10@@ -191,8 +191,12 @@ void get_tmp_filename(char *filename, in
11 void get_tmp_filename(char *filename, int size)
12 {
13 int fd;
14+ char *tmpdir;
15 /* XXX: race condition possible */
16- pstrcpy(filename, size, "/tmp/vl.XXXXXX");
17+ tmpdir = getenv("TMPDIR");
18+ if (!tmpdir)
19+ tmpdir = "/tmp";
20+ snprintf(filename, size, "%s/vl.XXXXXX", tmpdir);
21 fd = mkstemp(filename);
22 close(fd);
23 }
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/04_do_not_print_rtc_freq_if_ok.patch b/meta/packages/qemu/qemu-0.9.1+svn/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+svn/04_do_not_print_rtc_freq_if_ok.patch
@@ -0,0 +1,26 @@
1#DPATCHLEVEL=1
2---
3# vl.c | 5 ++++-
4# 1 file changed, 4 insertions(+), 1 deletion(-)
5#
6Index: qemu/vl.c
7===================================================================
8--- qemu.orig/vl.c 2007-12-03 15:44:35.000000000 +0000
9+++ qemu/vl.c 2007-12-03 15:51:03.000000000 +0000
10@@ -1289,12 +1289,15 @@ static void hpet_stop_timer(struct qemu_
11
12 static int rtc_start_timer(struct qemu_alarm_timer *t)
13 {
14+ unsigned long current_rtc_freq = 0;
15 int rtc_fd;
16
17 TFR(rtc_fd = open("/dev/rtc", O_RDONLY));
18 if (rtc_fd < 0)
19 return -1;
20- if (ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) {
21+ ioctl(rtc_fd, RTC_IRQP_READ, &current_rtc_freq);
22+ if (current_rtc_freq != RTC_FREQ &&
23+ ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) {
24 fprintf(stderr, "Could not configure '/dev/rtc' to have a 1024 Hz timer. This is not a fatal\n"
25 "error, but for better emulation accuracy either use a 2.6 host Linux kernel or\n"
26 "type 'echo 1024 > /proc/sys/dev/rtc/max-user-freq' as root.\n");
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/05_non-fatal_if_linux_hd_missing.patch b/meta/packages/qemu/qemu-0.9.1+svn/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+svn/05_non-fatal_if_linux_hd_missing.patch
@@ -0,0 +1,17 @@
1#DPATCHLEVEL=1
2---
3# hw/pc.c | 1 -
4# 1 file changed, 1 deletion(-)
5#
6Index: qemu/hw/pc.c
7===================================================================
8--- qemu.orig/hw/pc.c 2007-12-03 23:47:25.000000000 +0000
9+++ qemu/hw/pc.c 2007-12-03 23:47:38.000000000 +0000
10@@ -385,7 +385,6 @@ static void generate_bootsect(uint32_t g
11 if (bs_table[0] == NULL) {
12 fprintf(stderr, "A disk image must be given for 'hda' when booting "
13 "a Linux kernel\n");
14- exit(1);
15 }
16
17 memset(bootsect, 0, sizeof(bootsect));
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/06_exit_segfault.patch b/meta/packages/qemu/qemu-0.9.1+svn/06_exit_segfault.patch
new file mode 100644
index 0000000000..06123d0626
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/06_exit_segfault.patch
@@ -0,0 +1,45 @@
1#DPATCHLEVEL=0
2---
3# linux-user/main.c | 8 ++++----
4# 1 file changed, 4 insertions(+), 4 deletions(-)
5#
6Index: linux-user/main.c
7===================================================================
8--- linux-user/main.c.orig 2007-12-03 23:47:25.000000000 +0000
9+++ linux-user/main.c 2007-12-03 23:47:41.000000000 +0000
10@@ -714,7 +714,7 @@ void cpu_loop (CPUSPARCState *env)
11 default:
12 printf ("Unhandled trap: 0x%x\n", trapnr);
13 cpu_dump_state(env, stderr, fprintf, 0);
14- exit (1);
15+ _exit (1);
16 }
17 process_pending_signals (env);
18 }
19@@ -1634,7 +1634,7 @@ void cpu_loop (CPUState *env)
20 default:
21 printf ("Unhandled trap: 0x%x\n", trapnr);
22 cpu_dump_state(env, stderr, fprintf, 0);
23- exit (1);
24+ _exit (1);
25 }
26 process_pending_signals (env);
27 }
28@@ -1954,7 +1954,7 @@ int main(int argc, char **argv)
29 for(item = cpu_log_items; item->mask != 0; item++) {
30 printf("%-10s %s\n", item->name, item->help);
31 }
32- exit(1);
33+ _exit(1);
34 }
35 cpu_set_log(mask);
36 } else if (!strcmp(r, "s")) {
37@@ -1973,7 +1973,7 @@ int main(int argc, char **argv)
38 if (qemu_host_page_size == 0 ||
39 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
40 fprintf(stderr, "page size must be a power of two\n");
41- exit(1);
42+ _exit(1);
43 }
44 } else if (!strcmp(r, "g")) {
45 gdbstub_port = atoi(argv[optind++]);
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/10_signal_jobs.patch b/meta/packages/qemu/qemu-0.9.1+svn/10_signal_jobs.patch
new file mode 100644
index 0000000000..34282adc9d
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/10_signal_jobs.patch
@@ -0,0 +1,26 @@
1#DPATCHLEVEL=0
2---
3# linux-user/signal.c | 7 ++++++-
4# 1 file changed, 6 insertions(+), 1 deletion(-)
5#
6Index: linux-user/signal.c
7===================================================================
8--- linux-user/signal.c.orig 2007-12-03 15:40:26.000000000 +0000
9+++ linux-user/signal.c 2007-12-03 15:55:49.000000000 +0000
10@@ -364,10 +364,15 @@ int queue_signal(int sig, target_siginfo
11 k = &sigact_table[sig - 1];
12 handler = k->sa._sa_handler;
13 if (handler == TARGET_SIG_DFL) {
14+ if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
15+ kill(getpid(),SIGSTOP);
16+ return 0;
17+ } else
18 /* default handler : ignore some signal. The other are fatal */
19 if (sig != TARGET_SIGCHLD &&
20 sig != TARGET_SIGURG &&
21- sig != TARGET_SIGWINCH) {
22+ sig != TARGET_SIGWINCH &&
23+ sig != TARGET_SIGCONT) {
24 force_sig(sig);
25 } else {
26 return 0; /* indicate ignored */
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/11_signal_sigaction.patch b/meta/packages/qemu/qemu-0.9.1+svn/11_signal_sigaction.patch
new file mode 100644
index 0000000000..33c5e8b12d
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/11_signal_sigaction.patch
@@ -0,0 +1,21 @@
1#DPATCHLEVEL=0
2---
3# linux-user/signal.c | 5 +++++
4# 1 file changed, 5 insertions(+)
5#
6Index: linux-user/signal.c
7===================================================================
8--- linux-user/signal.c.orig 2007-12-03 23:47:44.000000000 +0000
9+++ linux-user/signal.c 2007-12-03 23:47:46.000000000 +0000
10@@ -512,6 +512,11 @@ int do_sigaction(int sig, const struct t
11
12 if (sig < 1 || sig > TARGET_NSIG || sig == SIGKILL || sig == SIGSTOP)
13 return -EINVAL;
14+
15+ /* no point doing the stuff as those are not allowed for sigaction */
16+ if ((sig == TARGET_SIGKILL) || (sig == TARGET_SIGSTOP))
17+ return -EINVAL;
18+
19 k = &sigact_table[sig - 1];
20 #if defined(DEBUG_SIGNAL)
21 fprintf(stderr, "sigaction sig=%d act=0x%08x, oact=0x%08x\n",
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/22_net_tuntap_stall.patch b/meta/packages/qemu/qemu-0.9.1+svn/22_net_tuntap_stall.patch
new file mode 100644
index 0000000000..6017df0f6d
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/22_net_tuntap_stall.patch
@@ -0,0 +1,18 @@
1#DPATCHLEVEL=0
2---
3# vl.c | 2 +-
4# 1 file changed, 1 insertion(+), 1 deletion(-)
5#
6Index: vl.c
7===================================================================
8--- vl.c.orig 2007-12-03 23:47:36.000000000 +0000
9+++ vl.c 2007-12-03 23:47:48.000000000 +0000
10@@ -4023,7 +4023,7 @@ static int tap_open(char *ifname, int if
11 return -1;
12 }
13 memset(&ifr, 0, sizeof(ifr));
14- ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
15+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE;
16 if (ifname[0] != '\0')
17 pstrcpy(ifr.ifr_name, IFNAMSIZ, ifname);
18 else
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/31_syscalls.patch b/meta/packages/qemu/qemu-0.9.1+svn/31_syscalls.patch
new file mode 100644
index 0000000000..95a7332ee8
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/31_syscalls.patch
@@ -0,0 +1,48 @@
1#DPATCHLEVEL=0
2---
3# linux-user/syscall.c | 11 ++++++++---
4# 1 file changed, 8 insertions(+), 3 deletions(-)
5#
6Index: linux-user/syscall.c
7===================================================================
8--- linux-user/syscall.c.orig 2007-12-03 19:32:56.000000000 +0000
9+++ linux-user/syscall.c 2007-12-03 19:33:41.000000000 +0000
10@@ -250,6 +250,7 @@ extern int getresuid(uid_t *, uid_t *, u
11 extern int setresgid(gid_t, gid_t, gid_t);
12 extern int getresgid(gid_t *, gid_t *, gid_t *);
13 extern int setgroups(int, gid_t *);
14+extern int uselib(const char*);
15
16 #define ERRNO_TABLE_SIZE 1200
17
18@@ -4024,7 +4025,8 @@ abi_long do_syscall(void *cpu_env, int n
19 #endif
20 #ifdef TARGET_NR_uselib
21 case TARGET_NR_uselib:
22- goto unimplemented;
23+ ret = get_errno(uselib(path((const char*)arg1)));
24+ break;
25 #endif
26 #ifdef TARGET_NR_swapon
27 case TARGET_NR_swapon:
28@@ -5289,7 +5291,9 @@ abi_long do_syscall(void *cpu_env, int n
29 goto unimplemented;
30 #ifdef TARGET_NR_mincore
31 case TARGET_NR_mincore:
32- goto unimplemented;
33+ /*page_unprotect_range((void*)arg3, ((size_t)arg2 + TARGET_PAGE_SIZE - 1) / TARGET_PAGE_SIZE);*/
34+ ret = get_errno(mincore((void*)arg1, (size_t)arg2, (unsigned char*)arg3));
35+ break;
36 #endif
37 #ifdef TARGET_NR_madvise
38 case TARGET_NR_madvise:
39@@ -5429,7 +5433,8 @@ abi_long do_syscall(void *cpu_env, int n
40 break;
41 #ifdef TARGET_NR_readahead
42 case TARGET_NR_readahead:
43- goto unimplemented;
44+ ret = get_errno(readahead((int)arg1, (off64_t)arg2, (size_t)arg3));
45+ break;
46 #endif
47 #ifdef TARGET_NR_setxattr
48 case TARGET_NR_setxattr:
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/32_syscall_sysctl.patch b/meta/packages/qemu/qemu-0.9.1+svn/32_syscall_sysctl.patch
new file mode 100644
index 0000000000..5e8dd75b0e
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/32_syscall_sysctl.patch
@@ -0,0 +1,55 @@
1#DPATCHLEVEL=0
2---
3# linux-user/syscall.c | 32 +++++++++++++++++++++++++++++---
4# 1 file changed, 29 insertions(+), 3 deletions(-)
5#
6Index: linux-user/syscall.c
7===================================================================
8--- linux-user/syscall.c.orig 2007-12-03 15:56:24.000000000 +0000
9+++ linux-user/syscall.c 2007-12-03 15:57:36.000000000 +0000
10@@ -52,6 +52,7 @@
11 //#include <sys/user.h>
12 #include <netinet/ip.h>
13 #include <netinet/tcp.h>
14+#include <sys/sysctl.h>
15
16 #define termios host_termios
17 #define winsize host_winsize
18@@ -4739,9 +4740,34 @@ abi_long do_syscall(void *cpu_env, int n
19 break;
20 #endif
21 case TARGET_NR__sysctl:
22- /* We don't implement this, but ENOTDIR is always a safe
23- return value. */
24- ret = -TARGET_ENOTDIR;
25+ {
26+ struct __sysctl_args *args = (struct __sysctl_args *) arg1;
27+ int *name_target, *name, nlen, *oldlenp, oldlen, newlen, i;
28+ void *oldval, *newval;
29+
30+ name_target = (int *) tswapl((long) args->name);
31+ nlen = tswapl(args->nlen);
32+ oldval = (void *) tswapl((long) args->oldval);
33+ oldlenp = (int *) tswapl((long) args->oldlenp);
34+ oldlen = tswapl(*oldlenp);
35+ newval = (void *) tswapl((long) args->newval);
36+ newlen = tswapl(args->newlen);
37+
38+ name = alloca(nlen * sizeof (int));
39+ for (i = 0; i < nlen; i++)
40+ name[i] = tswapl(name_target[i]);
41+
42+ if (nlen == 2 && name[0] == CTL_KERN && name[1] == KERN_VERSION) {
43+ ret = get_errno(
44+ sysctl(name, nlen, oldval, &oldlen, newval, newlen));
45+ if (!is_error(ret)) {
46+ *oldlenp = tswapl(oldlen);
47+ }
48+ } else {
49+ gemu_log("qemu: Unsupported sysctl name\n");
50+ ret = -ENOSYS;
51+ }
52+ }
53 break;
54 case TARGET_NR_sched_setparam:
55 {
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/33_syscall_ppc_clone.patch b/meta/packages/qemu/qemu-0.9.1+svn/33_syscall_ppc_clone.patch
new file mode 100644
index 0000000000..3f733b6ab8
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/33_syscall_ppc_clone.patch
@@ -0,0 +1,22 @@
1#DPATCHLEVEL=0
2---
3# linux-user/syscall.c | 6 +-----
4# 1 file changed, 1 insertion(+), 5 deletions(-)
5#
6Index: linux-user/syscall.c
7===================================================================
8--- linux-user/syscall.c.orig 2007-12-03 15:58:11.000000000 +0000
9+++ linux-user/syscall.c 2007-12-03 15:58:46.000000000 +0000
10@@ -2750,11 +2750,7 @@ int do_fork(CPUState *env, unsigned int
11 if (!newsp)
12 newsp = env->gpr[1];
13 new_env->gpr[1] = newsp;
14- {
15- int i;
16- for (i = 7; i < 32; i++)
17- new_env->gpr[i] = 0;
18- }
19+ new_env->gpr[3] = 0;
20 #elif defined(TARGET_SH4)
21 if (!newsp)
22 newsp = env->gregs[15];
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/39_syscall_fadvise64.patch b/meta/packages/qemu/qemu-0.9.1+svn/39_syscall_fadvise64.patch
new file mode 100644
index 0000000000..54ee3e0948
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/39_syscall_fadvise64.patch
@@ -0,0 +1,21 @@
1---
2 linux-user/syscall.c | 6 ++++++
3 1 file changed, 6 insertions(+)
4
5Index: linux-user/syscall.c
6===================================================================
7--- linux-user/syscall.c.orig 2007-12-03 19:33:47.000000000 +0000
8+++ linux-user/syscall.c 2007-12-03 19:33:48.000000000 +0000
9@@ -5317,6 +5317,12 @@ abi_long do_syscall(void *cpu_env, int n
10 ret = get_errno(mincore((void*)arg1, (size_t)arg2, (unsigned char*)arg3));
11 break;
12 #endif
13+#ifdef TARGET_NR_fadvise64_64
14+ case TARGET_NR_fadvise64_64:
15+ /* Just return success */
16+ ret = get_errno(0);
17+ break;
18+#endif
19 #ifdef TARGET_NR_madvise
20 case TARGET_NR_madvise:
21 /* A straight passthrough may not be safe because qemu sometimes
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/41_arm_fpa_sigfpe.patch b/meta/packages/qemu/qemu-0.9.1+svn/41_arm_fpa_sigfpe.patch
new file mode 100644
index 0000000000..cea3afc7ff
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/41_arm_fpa_sigfpe.patch
@@ -0,0 +1,104 @@
1#DPATCHLEVEL=0
2---
3# linux-user/main.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++-
4# target-arm/nwfpe/fpa11.c | 7 ++++++
5# 2 files changed, 57 insertions(+), 1 deletion(-)
6#
7Index: linux-user/main.c
8===================================================================
9--- linux-user/main.c.orig 2007-12-03 15:59:10.000000000 +0000
10+++ linux-user/main.c 2007-12-03 16:01:27.000000000 +0000
11@@ -377,18 +377,67 @@ void cpu_loop(CPUARMState *env)
12 {
13 TaskState *ts = env->opaque;
14 uint32_t opcode;
15+ int rc;
16
17 /* we handle the FPU emulation here, as Linux */
18 /* we get the opcode */
19 /* FIXME - what to do if get_user() fails? */
20 get_user_u32(opcode, env->regs[15]);
21
22- if (EmulateAll(opcode, &ts->fpa, env) == 0) {
23+ rc = EmulateAll(opcode, &ts->fpa, env);
24+ if (rc == 0) { /* illegal instruction */
25 info.si_signo = SIGILL;
26 info.si_errno = 0;
27 info.si_code = TARGET_ILL_ILLOPN;
28 info._sifields._sigfault._addr = env->regs[15];
29 queue_signal(info.si_signo, &info);
30+ } else if (rc < 0) { /* FP exception */
31+ int arm_fpe=0;
32+
33+ /* translate softfloat flags to FPSR flags */
34+ if (-rc & float_flag_invalid)
35+ arm_fpe |= BIT_IOC;
36+ if (-rc & float_flag_divbyzero)
37+ arm_fpe |= BIT_DZC;
38+ if (-rc & float_flag_overflow)
39+ arm_fpe |= BIT_OFC;
40+ if (-rc & float_flag_underflow)
41+ arm_fpe |= BIT_UFC;
42+ if (-rc & float_flag_inexact)
43+ arm_fpe |= BIT_IXC;
44+
45+ FPSR fpsr = ts->fpa.fpsr;
46+ //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe);
47+
48+ if (fpsr & (arm_fpe << 16)) { /* exception enabled? */
49+ info.si_signo = SIGFPE;
50+ info.si_errno = 0;
51+
52+ /* ordered by priority, least first */
53+ if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES;
54+ if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND;
55+ if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF;
56+ if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV;
57+ if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV;
58+
59+ info._sifields._sigfault._addr = env->regs[15];
60+ queue_signal(info.si_signo, &info);
61+ } else {
62+ env->regs[15] += 4;
63+ }
64+
65+ /* accumulate unenabled exceptions */
66+ if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC))
67+ fpsr |= BIT_IXC;
68+ if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC))
69+ fpsr |= BIT_UFC;
70+ if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC))
71+ fpsr |= BIT_OFC;
72+ if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC))
73+ fpsr |= BIT_DZC;
74+ if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC))
75+ fpsr |= BIT_IOC;
76+ ts->fpa.fpsr=fpsr;
77 } else {
78 /* increment PC */
79 env->regs[15] += 4;
80Index: target-arm/nwfpe/fpa11.c
81===================================================================
82--- target-arm/nwfpe/fpa11.c.orig 2007-12-03 15:40:26.000000000 +0000
83+++ target-arm/nwfpe/fpa11.c 2007-12-03 15:59:11.000000000 +0000
84@@ -162,6 +162,8 @@ unsigned int EmulateAll(unsigned int opc
85 fpa11->initflag = 1;
86 }
87
88+ set_float_exception_flags(0, &fpa11->fp_status);
89+
90 if (TEST_OPCODE(opcode,MASK_CPRT))
91 {
92 //fprintf(stderr,"emulating CPRT\n");
93@@ -191,6 +193,11 @@ unsigned int EmulateAll(unsigned int opc
94 }
95
96 // restore_flags(flags);
97+ if(nRc == 1 && get_float_exception_flags(&fpa11->fp_status))
98+ {
99+ //printf("fef 0x%x\n",float_exception_flags);
100+ nRc=-get_float_exception_flags(&fpa11->fp_status);
101+ }
102
103 //printf("returning %d\n",nRc);
104 return(nRc);
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/52_ne2000_return.patch b/meta/packages/qemu/qemu-0.9.1+svn/52_ne2000_return.patch
new file mode 100644
index 0000000000..e4ea33f2c6
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/52_ne2000_return.patch
@@ -0,0 +1,17 @@
1---
2 hw/ne2000.c | 2 +-
3 1 file changed, 1 insertion(+), 1 deletion(-)
4
5Index: qemu/hw/ne2000.c
6===================================================================
7--- qemu.orig/hw/ne2000.c 2007-12-03 19:32:52.000000000 +0000
8+++ qemu/hw/ne2000.c 2007-12-03 19:33:55.000000000 +0000
9@@ -217,7 +217,7 @@ static int ne2000_can_receive(void *opaq
10 NE2000State *s = opaque;
11
12 if (s->cmd & E8390_STOP)
13- return 1;
14+ return 0;
15 return !ne2000_buffer_full(s);
16 }
17
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/61_safe_64bit_int.patch b/meta/packages/qemu/qemu-0.9.1+svn/61_safe_64bit_int.patch
new file mode 100644
index 0000000000..9b1ace81a5
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/61_safe_64bit_int.patch
@@ -0,0 +1,27 @@
1#DPATCHLEVEL=0
2---
3# dyngen-exec.h | 4 ++--
4# 1 file changed, 2 insertions(+), 2 deletions(-)
5#
6Index: dyngen-exec.h
7===================================================================
8--- dyngen-exec.h.orig 2007-12-31 13:06:21.000000000 +0000
9+++ dyngen-exec.h 2007-12-31 13:08:54.000000000 +0000
10@@ -38,7 +38,7 @@
11 // Linux/Sparc64 defines uint64_t
12 #if !(defined (__sparc_v9__) && defined(__linux__))
13 /* XXX may be done for all 64 bits targets ? */
14-#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__)
15+#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__) || defined(__sparc__)
16 typedef unsigned long uint64_t;
17 #else
18 typedef unsigned long long uint64_t;
19@@ -55,7 +55,7 @@
20 typedef signed int int32_t;
21 // Linux/Sparc64 defines int64_t
22 #if !(defined (__sparc_v9__) && defined(__linux__))
23-#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__)
24+#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__) || defined(__sparc__)
25 typedef signed long int64_t;
26 #else
27 typedef signed long long int64_t;
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/63_sparc_build.patch b/meta/packages/qemu/qemu-0.9.1+svn/63_sparc_build.patch
new file mode 100644
index 0000000000..37b38f641b
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/63_sparc_build.patch
@@ -0,0 +1,18 @@
1#DPATCHLEVEL=0
2---
3# sparc.ld | 2 +-
4# 1 file changed, 1 insertion(+), 1 deletion(-)
5#
6Index: sparc.ld
7===================================================================
8--- sparc.ld.orig 2007-12-03 15:40:26.000000000 +0000
9+++ sparc.ld 2007-12-03 16:05:06.000000000 +0000
10@@ -6,7 +6,7 @@ ENTRY(_start)
11 SECTIONS
12 {
13 /* Read-only sections, merged into text segment: */
14- . = 0x60000000 + SIZEOF_HEADERS;
15+ . = 0x60000000 + 0x400;
16 .interp : { *(.interp) }
17 .hash : { *(.hash) }
18 .dynsym : { *(.dynsym) }
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/64_ppc_asm_constraints.patch b/meta/packages/qemu/qemu-0.9.1+svn/64_ppc_asm_constraints.patch
new file mode 100644
index 0000000000..e4858b79d7
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/64_ppc_asm_constraints.patch
@@ -0,0 +1,18 @@
1#DPATCHLEVEL=1
2---
3# cpu-all.h | 2 +-
4# 1 file changed, 1 insertion(+), 1 deletion(-)
5#
6Index: qemu/cpu-all.h
7===================================================================
8--- qemu.orig/cpu-all.h 2007-06-13 11:48:22.000000000 +0100
9+++ qemu/cpu-all.h 2007-06-13 11:51:56.000000000 +0100
10@@ -250,7 +250,7 @@ static inline void stw_le_p(void *ptr, i
11 static inline void stl_le_p(void *ptr, int v)
12 {
13 #ifdef __powerpc__
14- __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
15+ __asm__ __volatile__ ("stwbrx %0,0,%1" : : "r" (v), "r" (ptr) : "memory");
16 #else
17 uint8_t *p = ptr;
18 p[0] = v;
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/65_kfreebsd.patch b/meta/packages/qemu/qemu-0.9.1+svn/65_kfreebsd.patch
new file mode 100644
index 0000000000..dfece800ac
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/65_kfreebsd.patch
@@ -0,0 +1,35 @@
1---
2 configure | 6 ++++++
3 vl.c | 2 ++
4 2 files changed, 8 insertions(+)
5
6Index: configure
7===================================================================
8--- configure.orig 2007-12-03 15:40:26.000000000 +0000
9+++ configure 2007-12-03 16:05:34.000000000 +0000
10@@ -129,6 +129,12 @@ if [ "$cpu" = "i386" -o "$cpu" = "x86_64
11 kqemu="yes"
12 fi
13 ;;
14+GNU/kFreeBSD)
15+oss="yes"
16+if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
17+ kqemu="yes"
18+fi
19+;;
20 FreeBSD)
21 bsd="yes"
22 oss="yes"
23Index: vl.c
24===================================================================
25--- vl.c.orig 2007-12-03 16:05:32.000000000 +0000
26+++ vl.c 2007-12-03 16:05:34.000000000 +0000
27@@ -97,6 +97,8 @@
28 #include <stropts.h>
29 #endif
30 #endif
31+#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__)
32+#include <freebsd/stdlib.h>
33 #else
34 #include <winsock2.h>
35 int inet_aton(const char *cp, struct in_addr *ia);
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/66_tls_ld.patch b/meta/packages/qemu/qemu-0.9.1+svn/66_tls_ld.patch
new file mode 100644
index 0000000000..54e02eff8b
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/66_tls_ld.patch
@@ -0,0 +1,55 @@
1---
2 arm.ld | 7 +++++++
3 i386.ld | 7 +++++++
4 2 files changed, 14 insertions(+)
5
6Index: arm.ld
7===================================================================
8--- arm.ld.orig 2007-06-13 11:48:22.000000000 +0100
9+++ arm.ld 2007-06-13 11:51:56.000000000 +0100
10@@ -26,6 +26,10 @@ SECTIONS
11 { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
12 .rela.rodata :
13 { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
14+ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
15+ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
16+ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
17+ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
18 .rel.got : { *(.rel.got) }
19 .rela.got : { *(.rela.got) }
20 .rel.ctors : { *(.rel.ctors) }
21@@ -58,6 +62,9 @@ SECTIONS
22 .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
23 __exidx_end = .;
24 .reginfo : { *(.reginfo) }
25+ /* Thread Local Storage sections */
26+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
27+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
28 /* Adjust the address for the data segment. We want to adjust up to
29 the same address within the page on the next page up. */
30 . = ALIGN(0x100000) + (. & (0x100000 - 1));
31Index: i386.ld
32===================================================================
33--- i386.ld.orig 2007-06-13 11:48:22.000000000 +0100
34+++ i386.ld 2007-06-13 11:51:56.000000000 +0100
35@@ -28,6 +28,10 @@ SECTIONS
36 { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
37 .rela.rodata :
38 { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
39+ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
40+ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
41+ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
42+ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
43 .rel.got : { *(.rel.got) }
44 .rela.got : { *(.rela.got) }
45 .rel.ctors : { *(.rel.ctors) }
46@@ -53,6 +57,9 @@ SECTIONS
47 _etext = .;
48 PROVIDE (etext = .);
49 .fini : { *(.fini) } =0x47ff041f
50+ /* Thread Local Storage sections */
51+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
52+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
53 . = ALIGN(32 / 8);
54 PROVIDE (__preinit_array_start = .);
55 .preinit_array : { *(.preinit_array) }
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/91-oh-sdl-cursor.patch b/meta/packages/qemu/qemu-0.9.1+svn/91-oh-sdl-cursor.patch
new file mode 100644
index 0000000000..0d60c1c306
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/91-oh-sdl-cursor.patch
@@ -0,0 +1,18 @@
1=== modified file 'sdl.c'
2---
3 sdl.c | 2 +-
4 1 file changed, 1 insertion(+), 1 deletion(-)
5
6Index: sdl.c
7===================================================================
8--- sdl.c.orig 2007-12-03 19:32:15.000000000 +0000
9+++ sdl.c 2007-12-03 19:34:04.000000000 +0000
10@@ -247,7 +247,7 @@ static void sdl_hide_cursor(void)
11
12 if (kbd_mouse_is_absolute()) {
13 SDL_ShowCursor(1);
14- SDL_SetCursor(sdl_cursor_hidden);
15+ /* SDL_SetCursor(sdl_cursor_hidden); */
16 } else {
17 SDL_ShowCursor(0);
18 }
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/configure_symlinkpath_fix.patch b/meta/packages/qemu/qemu-0.9.1+svn/configure_symlinkpath_fix.patch
new file mode 100644
index 0000000000..3ec304a38c
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/configure_symlinkpath_fix.patch
@@ -0,0 +1,28 @@
1Index: qemu-0.9.1/configure
2===================================================================
3--- qemu-0.9.1.orig/configure 2008-01-24 15:33:13.000000000 +0000
4+++ qemu-0.9.1/configure 2008-01-24 15:45:50.000000000 +0000
5@@ -209,15 +209,17 @@
6
7 # find source path
8 source_path=`dirname "$0"`
9+source_path_used="no"
10+workdir=`pwd`
11+workdir=`readlink -f $workdir`
12 if [ -z "$source_path" ]; then
13- source_path=`pwd`
14+ source_path=$workdir
15 else
16 source_path=`cd "$source_path"; pwd`
17-fi
18-if test "$source_path" = `pwd` ; then
19- source_path_used="no"
20-else
21- source_path_used="yes"
22+ source_path=`readlink -f $source_path`
23+ if test "$source_path" != "$workdir" ; then
24+ source_path_used="yes"
25+ fi
26 fi
27
28 werror="no"
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/disable-error-in-configure.patch b/meta/packages/qemu/qemu-0.9.1+svn/disable-error-in-configure.patch
new file mode 100644
index 0000000000..017f9f6355
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/disable-error-in-configure.patch
@@ -0,0 +1,17 @@
1---
2 configure | 2 --
3 1 file changed, 2 deletions(-)
4
5Index: qemu/configure
6===================================================================
7--- qemu.orig/configure 2007-12-03 16:38:38.000000000 +0000
8+++ qemu/configure 2007-12-03 16:38:39.000000000 +0000
9@@ -323,8 +323,6 @@ for opt do
10 ;;
11 --disable-werror) werror="no"
12 ;;
13- *) echo "ERROR: unknown option $opt"; show_help="yes"
14- ;;
15 --disable-nptl) nptl="no"
16 ;;
17 esac
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/fix_segfault.patch b/meta/packages/qemu/qemu-0.9.1+svn/fix_segfault.patch
new file mode 100644
index 0000000000..443c330650
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/fix_segfault.patch
@@ -0,0 +1,37 @@
1---
2 linux-user/syscall.c | 22 ----------------------
3 1 file changed, 22 deletions(-)
4
5Index: qemu/linux-user/syscall.c
6===================================================================
7--- qemu.orig/linux-user/syscall.c 2007-12-03 23:40:11.000000000 +0000
8+++ qemu/linux-user/syscall.c 2007-12-03 23:40:21.000000000 +0000
9@@ -5695,28 +5695,6 @@ abi_long do_syscall(void *cpu_env, int n
10 goto unimplemented_nowarn;
11 #endif
12
13-#ifdef TARGET_NR_clock_gettime
14- case TARGET_NR_clock_gettime:
15- {
16- struct timespec ts;
17- ret = get_errno(clock_gettime(arg1, &ts));
18- if (!is_error(ret)) {
19- host_to_target_timespec(arg2, &ts);
20- }
21- break;
22- }
23-#endif
24-#ifdef TARGET_NR_clock_getres
25- case TARGET_NR_clock_getres:
26- {
27- struct timespec ts;
28- ret = get_errno(clock_getres(arg1, &ts));
29- if (!is_error(ret)) {
30- host_to_target_timespec(arg2, &ts);
31- }
32- break;
33- }
34-#endif
35
36 #if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
37 case TARGET_NR_set_tid_address:
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/no-strip.patch b/meta/packages/qemu/qemu-0.9.1+svn/no-strip.patch
new file mode 100644
index 0000000000..fc69b37e16
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/no-strip.patch
@@ -0,0 +1,22 @@
1--- qemu.orig/Makefile 2008-01-29 23:16:27.000000000 -0800
2+++ qemu-0.9.1/Makefile 2008-01-29 23:16:38.000000000 -0800
3@@ -174,7 +174,7 @@
4 install: all $(if $(BUILD_DOCS),install-doc)
5 mkdir -p "$(DESTDIR)$(bindir)"
6 ifneq ($(TOOLS),)
7- $(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
8+ $(INSTALL) -m 755 $(TOOLS) "$(DESTDIR)$(bindir)"
9 endif
10 mkdir -p "$(DESTDIR)$(datadir)"
11 for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
12--- qemu.orig/Makefile.target 2008-01-29 23:16:27.000000000 -0800
13+++ qemu-0.9.1/Makefile.target 2008-01-29 23:17:33.000000000 -0800
14@@ -632,7 +632,7 @@
15
16 install: all
17 ifneq ($(PROGS),)
18- $(INSTALL) -m 755 -s $(PROGS) "$(DESTDIR)$(bindir)"
19+ $(INSTALL) -m 755 $(PROGS) "$(DESTDIR)$(bindir)"
20 endif
21
22 ifneq ($(wildcard .depend),)
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl-update.patch b/meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl-update.patch
new file mode 100644
index 0000000000..ebc996e873
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl-update.patch
@@ -0,0 +1,219 @@
1---
2 linux-user/main.c | 7 ++-
3 linux-user/syscall.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++-----
4 2 files changed, 111 insertions(+), 10 deletions(-)
5
6Index: qemu/linux-user/main.c
7===================================================================
8--- qemu.orig/linux-user/main.c 2007-12-03 19:34:09.000000000 +0000
9+++ qemu/linux-user/main.c 2007-12-03 23:44:45.000000000 +0000
10@@ -391,7 +391,7 @@ do_kernel_trap(CPUARMState *env)
11 cpu_unlock();
12 break;
13 case 0xffff0fe0: /* __kernel_get_tls */
14- env->regs[0] = env->cp15.c13_tls;
15+ env->regs[0] = env->cp15.c13_tls2;
16 break;
17 default:
18 return 1;
19@@ -2037,6 +2037,11 @@ int main(int argc, char **argv)
20 int drop_ld_preload = 0, environ_count = 0;
21 char **target_environ, **wrk, **dst;
22
23+ char *assume_kernel = getenv("QEMU_ASSUME_KERNEL");
24+
25+ if (assume_kernel)
26+ setenv("LD_ASSUME_KERNEL", assume_kernel, 1);
27+
28 if (argc <= 1)
29 usage();
30
31Index: qemu/linux-user/syscall.c
32===================================================================
33--- qemu.orig/linux-user/syscall.c 2007-12-03 19:34:09.000000000 +0000
34+++ qemu/linux-user/syscall.c 2007-12-03 23:46:54.000000000 +0000
35@@ -61,6 +61,7 @@
36 #define tchars host_tchars /* same as target */
37 #define ltchars host_ltchars /* same as target */
38
39+#include <linux/futex.h>
40 #include <linux/termios.h>
41 #include <linux/unistd.h>
42 #include <linux/utsname.h>
43@@ -2694,7 +2695,6 @@ abi_long do_arch_prctl(CPUX86State *env,
44 return 0;
45 }
46 #endif
47-
48 #endif /* defined(TARGET_I386) */
49
50 /* this stack is the equivalent of the kernel stack associated with a
51@@ -2729,16 +2729,19 @@ int do_fork(CPUState *env, unsigned int
52 TaskState *ts;
53 uint8_t *new_stack;
54 CPUState *new_env;
55-
56+#if defined(TARGET_I386)
57+ uint64_t *new_gdt_table;
58+#endif
59 #ifdef USE_NPTL
60 unsigned int nptl_flags;
61
62 if (flags & CLONE_PARENT_SETTID)
63 *parent_tidptr = gettid();
64 #endif
65-
66 if (flags & CLONE_VM) {
67 ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE);
68+ if (!ts)
69+ return -ENOMEM;
70 memset(ts, 0, sizeof(TaskState));
71 new_stack = ts->stack;
72 ts->used = 1;
73@@ -2750,6 +2753,29 @@ int do_fork(CPUState *env, unsigned int
74 #if defined(TARGET_I386)
75 if (!newsp)
76 newsp = env->regs[R_ESP];
77+ new_gdt_table = malloc(9 * 8);
78+ if (!new_gdt_table) {
79+ free(new_env);
80+ return -ENOMEM;
81+ }
82+ /* Copy main GDT table from parent, but clear TLS entries */
83+ memcpy(new_gdt_table, g2h(env->gdt.base), 6 * 8);
84+ memset(&new_gdt_table[6], 0, 3 * 8);
85+ new_env->gdt.base = h2g(new_gdt_table);
86+ if (flags & 0x00080000 /* CLONE_SETTLS */) {
87+ ret = do_set_thread_area(new_env, new_env->regs[R_ESI]);
88+ if (ret) {
89+ free(new_gdt_table);
90+ free(new_env);
91+ return ret;
92+ }
93+ }
94+ cpu_x86_load_seg(env, R_CS, new_env->regs[R_CS]);
95+ cpu_x86_load_seg(env, R_DS, new_env->regs[R_DS]);
96+ cpu_x86_load_seg(env, R_ES, new_env->regs[R_ES]);
97+ cpu_x86_load_seg(env, R_SS, new_env->regs[R_SS]);
98+ cpu_x86_load_seg(env, R_FS, new_env->regs[R_FS]);
99+ cpu_x86_load_seg(env, R_GS, new_env->regs[R_GS]);
100 new_env->regs[R_ESP] = newsp;
101 new_env->regs[R_EAX] = 0;
102 #elif defined(TARGET_ARM)
103@@ -3121,6 +3147,68 @@ static inline abi_long host_to_target_ti
104 unlock_user_struct(target_ts, target_addr, 1);
105 }
106
107+static long do_futex(target_ulong uaddr, int op, uint32_t val,
108+ target_ulong utime, target_ulong uaddr2,
109+ uint32_t val3)
110+{
111+ struct timespec host_utime;
112+ unsigned long val2 = utime;
113+
114+ if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) {
115+ target_to_host_timespec(&host_utime, utime);
116+ val2 = (unsigned long)&host_utime;
117+ }
118+
119+#ifdef BSWAP_NEEDED
120+ switch(op) {
121+ case FUTEX_CMP_REQUEUE:
122+ val3 = tswap32(val3);
123+ case FUTEX_REQUEUE:
124+ val2 = tswap32(val2);
125+ case FUTEX_WAIT:
126+ case FUTEX_WAKE:
127+ val = tswap32(val);
128+ case FUTEX_LOCK_PI: /* This one's icky, but comes out OK */
129+ case FUTEX_UNLOCK_PI:
130+ break;
131+ default:
132+ gemu_log("qemu: Unsupported futex op %d\n", op);
133+ return -ENOSYS;
134+ }
135+#if 0 /* No, it's worse than this */
136+ if (op == FUTEX_WAKE_OP) {
137+ /* Need to munge the secondary operation (val3) */
138+ val3 = tswap32(val3);
139+ int op2 = (val3 >> 28) & 7;
140+ int cmp = (val3 >> 24) & 15;
141+ int oparg = (val3 << 8) >> 20;
142+ int cmparg = (val3 << 20) >> 20;
143+ int shift = val3 & (FUTEX_OP_OPARG_SHIFT << 28);
144+
145+ if (shift)
146+ oparg = (oparg & 7) + 24 - (oparg & 24);
147+ else oparg =
148+ if (op2 == FUTEX_OP_ADD) {
149+ gemu_log("qemu: Unsupported wrong-endian FUTEX_OP_ADD\n");
150+ return -ENOSYS;
151+ }
152+ if (cmparg == FUTEX_OP_CMP_LT || cmparg == FUTEX_OP_CMP_GE ||
153+ cmparg == FUTEX_OP_CMP_LE || cmparg == FUTEX_OP_CMP_GT) {
154+ gemu_log("qemu: Unsupported wrong-endian futex cmparg %d\n", cmparg);
155+ return -ENOSYS;
156+ }
157+ val3 = shift | (op2<<28) | (cmp<<24) | (oparg<<12) | cmparg;
158+ }
159+#endif
160+#endif
161+ return syscall(__NR_futex, g2h(uaddr), op, val, val2, g2h(uaddr2), val3);
162+}
163+
164+int do_set_tid_address(target_ulong tidptr)
165+{
166+ return syscall(__NR_set_tid_address, g2h(tidptr));
167+}
168+
169 /* do_syscall() should always have a single exit point at the end so
170 that actions, such as logging of syscall results, can be performed.
171 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
172@@ -3145,7 +3233,7 @@ abi_long do_syscall(void *cpu_env, int n
173 _mcleanup();
174 #endif
175 gdb_exit(cpu_env, arg1);
176- /* XXX: should free thread stack and CPU env */
177+ /* XXX: should free thread stack, GDT and CPU env */
178 _exit(arg1);
179 ret = 0; /* avoid warning */
180 break;
181@@ -5569,6 +5657,9 @@ abi_long do_syscall(void *cpu_env, int n
182 #elif defined(TARGET_I386) && defined(TARGET_ABI32)
183 ret = do_set_thread_area(cpu_env, arg1);
184 break;
185+#elif TARGET_i386
186+ ret = get_errno(do_set_thread_area(cpu_env, arg1));
187+ break;
188 #else
189 goto unimplemented_nowarn;
190 #endif
191@@ -5586,6 +5677,16 @@ abi_long do_syscall(void *cpu_env, int n
192 goto unimplemented_nowarn;
193 #endif
194
195+#ifdef TARGET_NR_futex
196+ case TARGET_NR_futex:
197+ ret = get_errno(do_futex(arg1, arg2, arg3, arg4, arg5, arg6));
198+ break;
199+#endif
200+#ifdef TARGET_NR_set_robust_list
201+ case TARGET_NR_set_robust_list:
202+ goto unimplemented_nowarn;
203+#endif
204+
205 #ifdef TARGET_NR_clock_gettime
206 case TARGET_NR_clock_gettime:
207 {
208@@ -5627,11 +5728,6 @@ abi_long do_syscall(void *cpu_env, int n
209 break;
210 #endif
211
212-#ifdef TARGET_NR_set_robust_list
213- case TARGET_NR_set_robust_list:
214- goto unimplemented_nowarn;
215-#endif
216-
217 #if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
218 case TARGET_NR_utimensat:
219 {
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl.patch b/meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl.patch
new file mode 100644
index 0000000000..4a87d8d637
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl.patch
@@ -0,0 +1,854 @@
1These are Paul Brook's patches to QEMU-0.8.2 to enable the running of single
2ARM binaries under QEMU's user-emulation mode. Without them, QEMU-0.8.1
3immediately dies saying:
4 Error: f0005
5 qemu: uncaught target signal 6 (Aborted) - exiting
6while qemu-0.8.2 dies saying:
7 qemu: Unsupported syscall: 983045
8 cannot set up thread-local storage: unknown error
9
10This file is a rediffing of the patches visible at
11https://nowt.dyndns.org/patch.qemu_nptl on 27 Sept 2006
12which "patch" fails to apply automatically.
13See also http://lists.gnu.org/archive/html/qemu-devel/2006-09/msg00194.html
14
15 Martin Guy, 27 Sept 2006
16
17---
18 configure | 25 ++++++
19 exec-all.h | 165 ------------------------------------------
20 linux-user/arm/syscall.h | 4 -
21 linux-user/main.c | 94 +++++++++++++++++++++---
22 linux-user/qemu.h | 3
23 linux-user/syscall.c | 91 ++++++++++++++++++++++-
24 qemu_spinlock.h | 181 +++++++++++++++++++++++++++++++++++++++++++++++
25 target-arm/cpu.h | 10 ++
26 target-arm/op.c | 6 +
27 target-arm/translate.c | 9 ++
28 10 files changed, 405 insertions(+), 183 deletions(-)
29
30Index: qemu/configure
31===================================================================
32--- qemu.orig/configure 2008-04-09 23:02:37.000000000 +0100
33+++ qemu/configure 2008-04-09 23:06:36.000000000 +0100
34@@ -109,6 +109,7 @@
35 build_docs="no"
36 uname_release=""
37 curses="yes"
38+nptl="yes"
39
40 # OS specific
41 targetos=`uname -s`
42@@ -334,6 +335,8 @@
43 ;;
44 *) echo "ERROR: unknown option $opt"; show_help="yes"
45 ;;
46+ --disable-nptl) nptl="no"
47+ ;;
48 esac
49 done
50
51@@ -429,6 +432,7 @@
52 echo " --disable-linux-user disable all linux usermode emulation targets"
53 echo " --enable-darwin-user enable all darwin usermode emulation targets"
54 echo " --disable-darwin-user disable all darwin usermode emulation targets"
55+echo " --disable-nptl disable usermode NPTL guest support"
56 echo " --fmod-lib path to FMOD library"
57 echo " --fmod-inc path to FMOD includes"
58 echo " --enable-uname-release=R Return R for uname -r in usermode emulation"
59@@ -595,6 +599,23 @@
60 }
61 EOF
62
63+# check NPTL support
64+cat > $TMPC <<EOF
65+#include <sched.h>
66+void foo()
67+{
68+#ifndef CLONE_SETTLS
69+#error bork
70+#endif
71+}
72+EOF
73+
74+if $cc -c -o $TMPO $TMPC 2> /dev/null ; then
75+ :
76+else
77+ nptl="no"
78+fi
79+
80 ##########################################
81 # SDL probe
82
83@@ -778,6 +799,7 @@
84 echo "Documentation $build_docs"
85 [ ! -z "$uname_release" ] && \
86 echo "uname -r $uname_release"
87+echo "NPTL support $nptl"
88
89 if test $sdl_too_old = "yes"; then
90 echo "-> Your SDL version is too old - please upgrade to have SDL support"
91@@ -1115,6 +1137,9 @@
92 echo "TARGET_ARCH=arm" >> $config_mak
93 echo "#define TARGET_ARCH \"arm\"" >> $config_h
94 echo "#define TARGET_ARM 1" >> $config_h
95+ if test "$nptl" = "yes" ; then
96+ echo "#define USE_NPTL 1" >> $config_h
97+ fi
98 bflt="yes"
99 elif test "$target_cpu" = "sparc" ; then
100 echo "TARGET_ARCH=sparc" >> $config_mak
101Index: qemu/exec-all.h
102===================================================================
103--- qemu.orig/exec-all.h 2008-04-09 22:39:38.000000000 +0100
104+++ qemu/exec-all.h 2008-04-09 23:05:55.000000000 +0100
105@@ -297,170 +297,7 @@
106 extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
107 extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
108
109-#if defined(__powerpc__)
110-static inline int testandset (int *p)
111-{
112- int ret;
113- __asm__ __volatile__ (
114- "0: lwarx %0,0,%1\n"
115- " xor. %0,%3,%0\n"
116- " bne 1f\n"
117- " stwcx. %2,0,%1\n"
118- " bne- 0b\n"
119- "1: "
120- : "=&r" (ret)
121- : "r" (p), "r" (1), "r" (0)
122- : "cr0", "memory");
123- return ret;
124-}
125-#elif defined(__i386__)
126-static inline int testandset (int *p)
127-{
128- long int readval = 0;
129-
130- __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
131- : "+m" (*p), "+a" (readval)
132- : "r" (1)
133- : "cc");
134- return readval;
135-}
136-#elif defined(__x86_64__)
137-static inline int testandset (int *p)
138-{
139- long int readval = 0;
140-
141- __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
142- : "+m" (*p), "+a" (readval)
143- : "r" (1)
144- : "cc");
145- return readval;
146-}
147-#elif defined(__s390__)
148-static inline int testandset (int *p)
149-{
150- int ret;
151-
152- __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
153- " jl 0b"
154- : "=&d" (ret)
155- : "r" (1), "a" (p), "0" (*p)
156- : "cc", "memory" );
157- return ret;
158-}
159-#elif defined(__alpha__)
160-static inline int testandset (int *p)
161-{
162- int ret;
163- unsigned long one;
164-
165- __asm__ __volatile__ ("0: mov 1,%2\n"
166- " ldl_l %0,%1\n"
167- " stl_c %2,%1\n"
168- " beq %2,1f\n"
169- ".subsection 2\n"
170- "1: br 0b\n"
171- ".previous"
172- : "=r" (ret), "=m" (*p), "=r" (one)
173- : "m" (*p));
174- return ret;
175-}
176-#elif defined(__sparc__)
177-static inline int testandset (int *p)
178-{
179- int ret;
180-
181- __asm__ __volatile__("ldstub [%1], %0"
182- : "=r" (ret)
183- : "r" (p)
184- : "memory");
185-
186- return (ret ? 1 : 0);
187-}
188-#elif defined(__arm__)
189-static inline int testandset (int *spinlock)
190-{
191- register unsigned int ret;
192- __asm__ __volatile__("swp %0, %1, [%2]"
193- : "=r"(ret)
194- : "0"(1), "r"(spinlock));
195-
196- return ret;
197-}
198-#elif defined(__mc68000)
199-static inline int testandset (int *p)
200-{
201- char ret;
202- __asm__ __volatile__("tas %1; sne %0"
203- : "=r" (ret)
204- : "m" (p)
205- : "cc","memory");
206- return ret;
207-}
208-#elif defined(__ia64)
209-
210-#include <ia64intrin.h>
211-
212-static inline int testandset (int *p)
213-{
214- return __sync_lock_test_and_set (p, 1);
215-}
216-#elif defined(__mips__)
217-static inline int testandset (int *p)
218-{
219- int ret;
220-
221- __asm__ __volatile__ (
222- " .set push \n"
223- " .set noat \n"
224- " .set mips2 \n"
225- "1: li $1, 1 \n"
226- " ll %0, %1 \n"
227- " sc $1, %1 \n"
228- " beqz $1, 1b \n"
229- " .set pop "
230- : "=r" (ret), "+R" (*p)
231- :
232- : "memory");
233-
234- return ret;
235-}
236-#else
237-#error unimplemented CPU support
238-#endif
239-
240-typedef int spinlock_t;
241-
242-#define SPIN_LOCK_UNLOCKED 0
243-
244-#if defined(CONFIG_USER_ONLY)
245-static inline void spin_lock(spinlock_t *lock)
246-{
247- while (testandset(lock));
248-}
249-
250-static inline void spin_unlock(spinlock_t *lock)
251-{
252- *lock = 0;
253-}
254-
255-static inline int spin_trylock(spinlock_t *lock)
256-{
257- return !testandset(lock);
258-}
259-#else
260-static inline void spin_lock(spinlock_t *lock)
261-{
262-}
263-
264-static inline void spin_unlock(spinlock_t *lock)
265-{
266-}
267-
268-static inline int spin_trylock(spinlock_t *lock)
269-{
270- return 1;
271-}
272-#endif
273+#include "qemu_spinlock.h"
274
275 extern spinlock_t tb_lock;
276
277Index: qemu/linux-user/arm/syscall.h
278===================================================================
279--- qemu.orig/linux-user/arm/syscall.h 2007-11-27 12:09:33.000000000 +0000
280+++ qemu/linux-user/arm/syscall.h 2008-04-09 23:05:55.000000000 +0100
281@@ -28,7 +28,9 @@
282 #define ARM_SYSCALL_BASE 0x900000
283 #define ARM_THUMB_SYSCALL 0
284
285-#define ARM_NR_cacheflush (ARM_SYSCALL_BASE + 0xf0000 + 2)
286+#define ARM_NR_BASE 0xf0000
287+#define ARM_NR_cacheflush (ARM_NR_BASE + 2)
288+#define ARM_NR_set_tls (ARM_NR_BASE + 5)
289
290 #define ARM_NR_semihosting 0x123456
291 #define ARM_NR_thumb_semihosting 0xAB
292Index: qemu/linux-user/main.c
293===================================================================
294--- qemu.orig/linux-user/main.c 2008-04-09 23:02:37.000000000 +0100
295+++ qemu/linux-user/main.c 2008-04-09 23:05:55.000000000 +0100
296@@ -364,6 +364,50 @@
297 }
298 }
299
300+/* Handle a jump to the kernel code page. */
301+static int
302+do_kernel_trap(CPUARMState *env)
303+{
304+ uint32_t addr;
305+ uint32_t *ptr;
306+ uint32_t cpsr;
307+
308+ switch (env->regs[15]) {
309+ case 0xffff0fc0: /* __kernel_cmpxchg */
310+ /* XXX: This only works between threads, not between processes.
311+ Use native atomic operations. */
312+ /* ??? This probably breaks horribly if the access segfaults. */
313+ cpu_lock();
314+ ptr = (uint32_t *)env->regs[2];
315+ cpsr = cpsr_read(env);
316+ if (*ptr == env->regs[0]) {
317+ *ptr = env->regs[1];
318+ env->regs[0] = 0;
319+ cpsr |= CPSR_C;
320+ } else {
321+ env->regs[0] = -1;
322+ cpsr &= ~CPSR_C;
323+ }
324+ cpsr_write(env, cpsr, CPSR_C);
325+ cpu_unlock();
326+ break;
327+ case 0xffff0fe0: /* __kernel_get_tls */
328+ env->regs[0] = env->cp15.c13_tls;
329+ break;
330+ default:
331+ return 1;
332+ }
333+ /* Jump back to the caller. */
334+ addr = env->regs[14];
335+ if (addr & 1) {
336+ env->thumb = 1;
337+ addr &= ~1;
338+ }
339+ env->regs[15] = addr;
340+
341+ return 0;
342+}
343+
344 void cpu_loop(CPUARMState *env)
345 {
346 int trapnr;
347@@ -474,10 +518,8 @@
348 }
349 }
350
351- if (n == ARM_NR_cacheflush) {
352- arm_cache_flush(env->regs[0], env->regs[1]);
353- } else if (n == ARM_NR_semihosting
354- || n == ARM_NR_thumb_semihosting) {
355+ if (n == ARM_NR_semihosting
356+ || n == ARM_NR_thumb_semihosting) {
357 env->regs[0] = do_arm_semihosting (env);
358 } else if (n == 0 || n >= ARM_SYSCALL_BASE
359 || (env->thumb && n == ARM_THUMB_SYSCALL)) {
360@@ -488,14 +530,34 @@
361 n -= ARM_SYSCALL_BASE;
362 env->eabi = 0;
363 }
364- env->regs[0] = do_syscall(env,
365- n,
366- env->regs[0],
367- env->regs[1],
368- env->regs[2],
369- env->regs[3],
370- env->regs[4],
371- env->regs[5]);
372+ if ( n > ARM_NR_BASE) {
373+ switch (n)
374+ {
375+ case ARM_NR_cacheflush:
376+ arm_cache_flush(env->regs[0], env->regs[1]);
377+ break;
378+#ifdef USE_NPTL
379+ case ARM_NR_set_tls:
380+ cpu_set_tls(env, env->regs[0]);
381+ env->regs[0] = 0;
382+ break;
383+#endif
384+ default:
385+ printf ("Error: Bad syscall: %x\n", n);
386+ goto error;
387+ }
388+ }
389+ else
390+ {
391+ env->regs[0] = do_syscall(env,
392+ n,
393+ env->regs[0],
394+ env->regs[1],
395+ env->regs[2],
396+ env->regs[3],
397+ env->regs[4],
398+ env->regs[5]);
399+ }
400 } else {
401 goto error;
402 }
403@@ -534,6 +596,10 @@
404 }
405 }
406 break;
407+ case EXCP_KERNEL_TRAP:
408+ if (do_kernel_trap(env))
409+ goto error;
410+ break;
411 default:
412 error:
413 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
414@@ -2402,6 +2468,10 @@
415 ts->heap_base = info->brk;
416 /* This will be filled in on the first SYS_HEAPINFO call. */
417 ts->heap_limit = 0;
418+ /* Register the magic kernel code page. The cpu will generate a
419+ special exception when it tries to execute code here. We can't
420+ put real code here because it may be in use by the host kernel. */
421+ page_set_flags(0xffff0000, 0xffff0fff, 0);
422 #endif
423
424 if (gdbstub_port) {
425Index: qemu/linux-user/qemu.h
426===================================================================
427--- qemu.orig/linux-user/qemu.h 2008-01-02 15:48:21.000000000 +0000
428+++ qemu/linux-user/qemu.h 2008-04-09 23:05:55.000000000 +0100
429@@ -107,6 +107,9 @@
430 uint32_t heap_base;
431 uint32_t heap_limit;
432 #endif
433+#ifdef USE_NPTL
434+ uint32_t *child_tidptr;
435+#endif
436 int used; /* non zero if used */
437 struct image_info *info;
438 uint8_t stack[0];
439Index: qemu/linux-user/syscall.c
440===================================================================
441--- qemu.orig/linux-user/syscall.c 2008-04-09 23:02:38.000000000 +0100
442+++ qemu/linux-user/syscall.c 2008-04-09 23:05:55.000000000 +0100
443@@ -71,9 +71,18 @@
444 #include <linux/kd.h>
445
446 #include "qemu.h"
447+#include "qemu_spinlock.h"
448
449 //#define DEBUG
450
451+#ifdef USE_NPTL
452+#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
453+ CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
454+#else
455+/* XXX: Hardcode the above values. */
456+#define CLONE_NPTL_FLAGS2 0
457+#endif
458+
459 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
460 || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
461 /* 16 bit uid wrappers emulation */
462@@ -2702,9 +2711,19 @@
463 thread/process */
464 #define NEW_STACK_SIZE 8192
465
466+#ifdef USE_NPTL
467+static spinlock_t nptl_lock = SPIN_LOCK_UNLOCKED;
468+#endif
469+
470 static int clone_func(void *arg)
471 {
472 CPUState *env = arg;
473+#ifdef HAVE_NPTL
474+ /* Wait until the parent has finshed initializing the tls state. */
475+ while (!spin_trylock(&nptl_lock))
476+ usleep(1);
477+ spin_unlock(&nptl_lock);
478+#endif
479 cpu_loop(env);
480 /* never exits */
481 return 0;
482@@ -2712,13 +2731,22 @@
483
484 /* do_fork() Must return host values and target errnos (unlike most
485 do_*() functions). */
486-int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp)
487+int do_fork(CPUState *env, unsigned int flags, unsigned long newsp,
488+ uint32_t *parent_tidptr, void *newtls,
489+ uint32_t *child_tidptr)
490 {
491 int ret;
492 TaskState *ts;
493 uint8_t *new_stack;
494 CPUState *new_env;
495
496+#ifdef USE_NPTL
497+ unsigned int nptl_flags;
498+
499+ if (flags & CLONE_PARENT_SETTID)
500+ *parent_tidptr = gettid();
501+#endif
502+
503 if (flags & CLONE_VM) {
504 ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE);
505 memset(ts, 0, sizeof(TaskState));
506@@ -2784,16 +2812,67 @@
507 #error unsupported target CPU
508 #endif
509 new_env->opaque = ts;
510+#ifdef USE_NPTL
511+ nptl_flags = flags;
512+ flags &= ~CLONE_NPTL_FLAGS2;
513+
514+ if (nptl_flags & CLONE_CHILD_CLEARTID) {
515+ ts->child_tidptr = child_tidptr;
516+ }
517+
518+ if (nptl_flags & CLONE_SETTLS)
519+ cpu_set_tls (new_env, newtls);
520+
521+ /* Grab the global cpu lock so that the thread setup appears
522+ atomic. */
523+ if (nptl_flags & CLONE_CHILD_SETTID)
524+ spin_lock(&nptl_lock);
525+
526+#else
527+ if (flags & CLONE_NPTL_FLAGS2)
528+ return -EINVAL;
529+#endif
530+
531+ if (CLONE_VFORK & flags)
532+ flags ^= CLONE_VM;
533 #ifdef __ia64__
534 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
535 #else
536 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
537 #endif
538+#ifdef USE_NPTL
539+ if (ret != -1) {
540+ if (nptl_flags & CLONE_CHILD_SETTID)
541+ *child_tidptr = ret;
542+ }
543+
544+ /* Allow the child to continue. */
545+ if (nptl_flags & CLONE_CHILD_SETTID)
546+ spin_unlock(&nptl_lock);
547+#endif
548 } else {
549 /* if no CLONE_VM, we consider it is a fork */
550- if ((flags & ~CSIGNAL) != 0)
551+ if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
552 return -EINVAL;
553 ret = fork();
554+#ifdef USE_NPTL
555+ /* There is a race condition here. The parent process could
556+ theoretically read the TID in the child process before the child
557+ tid is set. This would require using either ptrace
558+ (not implemented) or having *_tidptr to point at a shared memory
559+ mapping. We can't repeat the spinlock hack used above because
560+ the child process gets its own copy of the lock. */
561+ if (ret == 0) {
562+ /* Child Process. */
563+ if (flags & CLONE_CHILD_SETTID)
564+ *child_tidptr = gettid();
565+ ts = (TaskState *)env->opaque;
566+ if (flags & CLONE_CHILD_CLEARTID)
567+ ts->child_tidptr = child_tidptr;
568+ if (flags & CLONE_SETTLS)
569+ cpu_set_tls (env, newtls);
570+ }
571+#endif
572 }
573 return ret;
574 }
575@@ -3118,7 +3197,7 @@
576 ret = do_brk(arg1);
577 break;
578 case TARGET_NR_fork:
579- ret = get_errno(do_fork(cpu_env, SIGCHLD, 0));
580+ ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, NULL, NULL, NULL));
581 break;
582 #ifdef TARGET_NR_waitpid
583 case TARGET_NR_waitpid:
584@@ -4481,7 +4560,8 @@
585 ret = get_errno(fsync(arg1));
586 break;
587 case TARGET_NR_clone:
588- ret = get_errno(do_fork(cpu_env, arg1, arg2));
589+ ret = get_errno(do_fork(cpu_env, arg1, arg2, (uint32_t *)arg3,
590+ (void *)arg4, (uint32_t *)arg5));
591 break;
592 #ifdef __NR_exit_group
593 /* new thread calls */
594@@ -4928,7 +5008,8 @@
595 #endif
596 #ifdef TARGET_NR_vfork
597 case TARGET_NR_vfork:
598- ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0));
599+ ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0,
600+ NULL, NULL, NULL));
601 break;
602 #endif
603 #ifdef TARGET_NR_ugetrlimit
604Index: qemu/qemu_spinlock.h
605===================================================================
606--- /dev/null 1970-01-01 00:00:00.000000000 +0000
607+++ qemu/qemu_spinlock.h 2008-04-09 23:05:55.000000000 +0100
608@@ -0,0 +1,181 @@
609+/*
610+ * Atomic operation helper include
611+ *
612+ * Copyright (c) 2005 Fabrice Bellard
613+ *
614+ * This library is free software; you can redistribute it and/or
615+ * modify it under the terms of the GNU Lesser General Public
616+ * License as published by the Free Software Foundation; either
617+ * version 2 of the License, or (at your option) any later version.
618+ *
619+ * This library is distributed in the hope that it will be useful,
620+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
621+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
622+ * Lesser General Public License for more details.
623+ *
624+ * You should have received a copy of the GNU Lesser General Public
625+ * License along with this library; if not, write to the Free Software
626+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
627+ */
628+#ifndef QEMU_SPINLOCK_H
629+#define QEMU_SPINLOCK_H
630+
631+#ifdef __powerpc__
632+static inline int testandset (int *p)
633+{
634+ int ret;
635+ __asm__ __volatile__ (
636+ "0: lwarx %0,0,%1\n"
637+ " xor. %0,%3,%0\n"
638+ " bne 1f\n"
639+ " stwcx. %2,0,%1\n"
640+ " bne- 0b\n"
641+ "1: "
642+ : "=&r" (ret)
643+ : "r" (p), "r" (1), "r" (0)
644+ : "cr0", "memory");
645+ return ret;
646+}
647+#endif
648+
649+#ifdef __i386__
650+static inline int testandset (int *p)
651+{
652+ long int readval = 0;
653+
654+ __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
655+ : "+m" (*p), "+a" (readval)
656+ : "r" (1)
657+ : "cc");
658+ return readval;
659+}
660+#endif
661+
662+#ifdef __x86_64__
663+static inline int testandset (int *p)
664+{
665+ long int readval = 0;
666+
667+ __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
668+ : "+m" (*p), "+a" (readval)
669+ : "r" (1)
670+ : "cc");
671+ return readval;
672+}
673+#endif
674+
675+#ifdef __s390__
676+static inline int testandset (int *p)
677+{
678+ int ret;
679+
680+ __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
681+ " jl 0b"
682+ : "=&d" (ret)
683+ : "r" (1), "a" (p), "0" (*p)
684+ : "cc", "memory" );
685+ return ret;
686+}
687+#endif
688+
689+#ifdef __alpha__
690+static inline int testandset (int *p)
691+{
692+ int ret;
693+ unsigned long one;
694+
695+ __asm__ __volatile__ ("0: mov 1,%2\n"
696+ " ldl_l %0,%1\n"
697+ " stl_c %2,%1\n"
698+ " beq %2,1f\n"
699+ ".subsection 2\n"
700+ "1: br 0b\n"
701+ ".previous"
702+ : "=r" (ret), "=m" (*p), "=r" (one)
703+ : "m" (*p));
704+ return ret;
705+}
706+#endif
707+
708+#ifdef __sparc__
709+static inline int testandset (int *p)
710+{
711+ int ret;
712+
713+ __asm__ __volatile__("ldstub [%1], %0"
714+ : "=r" (ret)
715+ : "r" (p)
716+ : "memory");
717+
718+ return (ret ? 1 : 0);
719+}
720+#endif
721+
722+#ifdef __arm__
723+static inline int testandset (int *spinlock)
724+{
725+ register unsigned int ret;
726+ __asm__ __volatile__("swp %0, %1, [%2]"
727+ : "=r"(ret)
728+ : "0"(1), "r"(spinlock));
729+
730+ return ret;
731+}
732+#endif
733+
734+#ifdef __mc68000
735+static inline int testandset (int *p)
736+{
737+ char ret;
738+ __asm__ __volatile__("tas %1; sne %0"
739+ : "=r" (ret)
740+ : "m" (p)
741+ : "cc","memory");
742+ return ret;
743+}
744+#endif
745+
746+#ifdef __ia64
747+#include <ia64intrin.h>
748+
749+static inline int testandset (int *p)
750+{
751+ return __sync_lock_test_and_set (p, 1);
752+}
753+#endif
754+
755+typedef int spinlock_t;
756+
757+#define SPIN_LOCK_UNLOCKED 0
758+
759+#if defined(CONFIG_USER_ONLY)
760+static inline void spin_lock(spinlock_t *lock)
761+{
762+ while (testandset(lock));
763+}
764+
765+static inline void spin_unlock(spinlock_t *lock)
766+{
767+ *lock = 0;
768+}
769+
770+static inline int spin_trylock(spinlock_t *lock)
771+{
772+ return !testandset(lock);
773+}
774+#else
775+static inline void spin_lock(spinlock_t *lock)
776+{
777+}
778+
779+static inline void spin_unlock(spinlock_t *lock)
780+{
781+}
782+
783+static inline int spin_trylock(spinlock_t *lock)
784+{
785+ return 1;
786+}
787+#endif
788+
789+#endif
790Index: qemu/target-arm/cpu.h
791===================================================================
792--- qemu.orig/target-arm/cpu.h 2007-11-27 12:09:57.000000000 +0000
793+++ qemu/target-arm/cpu.h 2008-04-09 23:05:55.000000000 +0100
794@@ -38,6 +38,7 @@
795 #define EXCP_FIQ 6
796 #define EXCP_BKPT 7
797 #define EXCP_EXCEPTION_EXIT 8 /* Return from v7M exception. */
798+#define EXCP_KERNEL_TRAP 9 /* Jumped to kernel code page. */
799
800 #define ARMV7M_EXCP_RESET 1
801 #define ARMV7M_EXCP_NMI 2
802@@ -222,6 +223,15 @@
803 void cpu_lock(void);
804 void cpu_unlock(void);
805
806+void cpu_lock(void);
807+void cpu_unlock(void);
808+#if defined(USE_NPTL)
809+static inline void cpu_set_tls(CPUARMState *env, void *newtls)
810+{
811+ env->cp15.c13_tls2 = (uint32_t)(long)newtls;
812+}
813+#endif
814+
815 #define CPSR_M (0x1f)
816 #define CPSR_T (1 << 5)
817 #define CPSR_F (1 << 6)
818Index: qemu/target-arm/op.c
819===================================================================
820--- qemu.orig/target-arm/op.c 2008-04-09 22:40:01.000000000 +0100
821+++ qemu/target-arm/op.c 2008-04-09 23:05:55.000000000 +0100
822@@ -994,6 +994,12 @@
823 cpu_loop_exit();
824 }
825
826+void OPPROTO op_kernel_trap(void)
827+{
828+ env->exception_index = EXCP_KERNEL_TRAP;
829+ cpu_loop_exit();
830+}
831+
832 /* VFP support. We follow the convention used for VFP instrunctions:
833 Single precition routines have a "s" suffix, double precision a
834 "d" suffix. */
835Index: qemu/target-arm/translate.c
836===================================================================
837--- qemu.orig/target-arm/translate.c 2008-04-09 22:40:01.000000000 +0100
838+++ qemu/target-arm/translate.c 2008-04-09 23:05:55.000000000 +0100
839@@ -7496,7 +7496,14 @@
840 gen_op_exception_exit();
841 }
842 #endif
843-
844+#ifdef CONFIG_USER_ONLY
845+ /* Intercept jump to the magic kernel page. */
846+ if (dc->pc > 0xffff0000) {
847+ gen_op_kernel_trap();
848+ dc->is_jmp = DISAS_UPDATE;
849+ break;
850+ }
851+#endif
852 if (env->nb_breakpoints > 0) {
853 for(j = 0; j < env->nb_breakpoints; j++) {
854 if (env->breakpoints[j] == dc->pc) {
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/qemu-amd64-32b-mapping-0.9.0.patch b/meta/packages/qemu/qemu-0.9.1+svn/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+svn/qemu-amd64-32b-mapping-0.9.0.patch
@@ -0,0 +1,37 @@
1---
2 linux-user/mmap.c | 8 ++++++--
3 1 file changed, 6 insertions(+), 2 deletions(-)
4
5Index: qemu/linux-user/mmap.c
6===================================================================
7--- qemu.orig/linux-user/mmap.c 2007-12-03 15:40:25.000000000 +0000
8+++ qemu/linux-user/mmap.c 2007-12-03 16:37:21.000000000 +0000
9@@ -29,6 +29,10 @@
10
11 //#define DEBUG_MMAP
12
13+#ifndef MAP_32BIT
14+#define MAP_32BIT 0
15+#endif
16+
17 /* NOTE: all the constants are the HOST ones, but addresses are target. */
18 int target_mprotect(abi_ulong start, abi_ulong len, int prot)
19 {
20@@ -251,7 +255,7 @@ abi_long target_mmap(abi_ulong start, ab
21 especially important if qemu_host_page_size >
22 qemu_real_host_page_size */
23 p = mmap(g2h(mmap_start),
24- host_len, prot, flags | MAP_FIXED, fd, host_offset);
25+ host_len, prot, flags | MAP_FIXED | MAP_32BIT, fd, host_offset);
26 if (p == MAP_FAILED)
27 return -1;
28 /* update start so that it points to the file position at 'offset' */
29@@ -406,7 +410,7 @@ abi_long target_mremap(abi_ulong old_add
30 unsigned long host_addr;
31
32 /* XXX: use 5 args syscall */
33- host_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags);
34+ host_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags | MAP_32BIT);
35 if (host_addr == -1)
36 return -1;
37 new_addr = h2g(host_addr);
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/qemu-n800-support.patch b/meta/packages/qemu/qemu-0.9.1+svn/qemu-n800-support.patch
new file mode 100644
index 0000000000..b1b6649efc
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/qemu-n800-support.patch
@@ -0,0 +1,13970 @@
1diff --git a/Makefile b/Makefile
2index c36a978..cb0cf7b 100644
3--- a/Makefile
4+++ b/Makefile
5@@ -51,7 +51,8 @@ OBJS+=block.o
6
7 OBJS+=irq.o
8 OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o
9-OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o
10+OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o twl92230.o
11+OBJS+=tmp105.o
12 OBJS+=scsi-disk.o cdrom.o
13 OBJS+=scsi-generic.o
14 OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o usb-serial.o
15diff --git a/Makefile.target b/Makefile.target
16index d1deda1..48f31bc 100644
17--- a/Makefile.target
18+++ b/Makefile.target
19@@ -593,7 +593,9 @@ OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
20 OBJS+= pflash_cfi01.o gumstix.o
21 OBJS+= spitz.o ide.o serial.o nand.o ecc.o
22 OBJS+= omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o
23+OBJS+= omap2.o omap_dss.o
24 OBJS+= palm.o tsc210x.o
25+OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o
26 OBJS+= mst_fpga.o mainstone.o
27 CPPFLAGS += -DHAS_AUDIO
28 endif
29diff --git a/console.h b/console.h
30index b8a5c6d..b45974e 100644
31--- a/console.h
32+++ b/console.h
33@@ -32,6 +32,12 @@ void kbd_put_keycode(int keycode);
34 void kbd_mouse_event(int dx, int dy, int dz, int buttons_state);
35 int kbd_mouse_is_absolute(void);
36
37+struct mouse_transform_info_s {
38+ int x;
39+ int y;
40+ int a[7];
41+};
42+
43 void do_info_mice(void);
44 void do_mouse_set(int index);
45
46diff --git a/cpu-all.h b/cpu-all.h
47index 7a7e655..c7c9611 100644
48--- a/cpu-all.h
49+++ b/cpu-all.h
50@@ -810,7 +810,7 @@ extern uint8_t *phys_ram_dirty;
51 /* physical memory access */
52 #define TLB_INVALID_MASK (1 << 3)
53 #define IO_MEM_SHIFT 4
54-#define IO_MEM_NB_ENTRIES (1 << (TARGET_PAGE_BITS - IO_MEM_SHIFT))
55+#define IO_MEM_NB_ENTRIES (16 << (TARGET_PAGE_BITS - IO_MEM_SHIFT))
56
57 #define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */
58 #define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */
59diff --git a/exec.c b/exec.c
60index e9a5918..c69f742 100644
61--- a/exec.c
62+++ b/exec.c
63@@ -1658,7 +1658,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
64 {
65 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
66 /* IO memory case */
67- address = vaddr | pd;
68+ address = vaddr | (pd & ~TARGET_PAGE_MASK);
69 addend = paddr;
70 } else {
71 /* standard memory */
72@@ -1692,7 +1692,9 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
73 } else {
74 te->addr_read = -1;
75 }
76- if (prot & PAGE_EXEC) {
77+ if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
78+ te->addr_code = pd;
79+ } else if (prot & PAGE_EXEC) {
80 te->addr_code = address;
81 } else {
82 te->addr_code = -1;
83@@ -2487,7 +2489,9 @@ int cpu_register_io_memory(int io_index,
84 if (io_index <= 0) {
85 if (io_mem_nb >= IO_MEM_NB_ENTRIES)
86 return -1;
87- io_index = io_mem_nb++;
88+ do io_index = io_mem_nb++;
89+ while (((io_index << IO_MEM_SHIFT) & ~TARGET_PAGE_MASK)
90+ <= IO_MEM_NOTDIRTY);
91 } else {
92 if (io_index >= IO_MEM_NB_ENTRIES)
93 return -1;
94diff --git a/hw/arm-misc.h b/hw/arm-misc.h
95index 7914ff1..a1e0061 100644
96--- a/hw/arm-misc.h
97+++ b/hw/arm-misc.h
98@@ -21,10 +21,7 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
99 const char *kernel_filename, const char *cpu_model);
100
101 /* arm_boot.c */
102-
103-void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
104- const char *kernel_cmdline, const char *initrd_filename,
105- int board_id, target_phys_addr_t loader_start);
106+void arm_load_kernel(CPUState *env, struct arm_boot_info *info);
107
108 /* armv7m_nvic.c */
109 int system_clock_scale;
110diff --git a/hw/arm_boot.c b/hw/arm_boot.c
111index 8335e69..20b1512 100644
112--- a/hw/arm_boot.c
113+++ b/hw/arm_boot.c
114@@ -47,21 +47,18 @@ static void main_cpu_reset(void *opaque)
115 CPUState *env = opaque;
116
117 cpu_reset(env);
118- if (env->kernel_filename)
119- arm_load_kernel(env, env->ram_size, env->kernel_filename,
120- env->kernel_cmdline, env->initrd_filename,
121- env->board_id, env->loader_start);
122+ if (env->boot_info)
123+ arm_load_kernel(env, env->boot_info);
124
125 /* TODO: Reset secondary CPUs. */
126 }
127
128-static void set_kernel_args(uint32_t ram_size, int initrd_size,
129- const char *kernel_cmdline,
130- target_phys_addr_t loader_start)
131+static void set_kernel_args(struct arm_boot_info *info,
132+ int initrd_size, void *base)
133 {
134 uint32_t *p;
135
136- p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR);
137+ p = (uint32_t *)(base + KERNEL_ARGS_ADDR);
138 /* ATAG_CORE */
139 stl_raw(p++, 5);
140 stl_raw(p++, 0x54410001);
141@@ -69,46 +66,55 @@ static void set_kernel_args(uint32_t ram_size, int initrd_size,
142 stl_raw(p++, 0x1000);
143 stl_raw(p++, 0);
144 /* ATAG_MEM */
145+ /* TODO: multiple chips */
146 stl_raw(p++, 4);
147 stl_raw(p++, 0x54410002);
148- stl_raw(p++, ram_size);
149- stl_raw(p++, loader_start);
150+ stl_raw(p++, info->ram_size);
151+ stl_raw(p++, info->loader_start);
152 if (initrd_size) {
153 /* ATAG_INITRD2 */
154 stl_raw(p++, 4);
155 stl_raw(p++, 0x54420005);
156- stl_raw(p++, loader_start + INITRD_LOAD_ADDR);
157+ stl_raw(p++, info->loader_start + INITRD_LOAD_ADDR);
158 stl_raw(p++, initrd_size);
159 }
160- if (kernel_cmdline && *kernel_cmdline) {
161+ if (info->kernel_cmdline && *info->kernel_cmdline) {
162 /* ATAG_CMDLINE */
163 int cmdline_size;
164
165- cmdline_size = strlen(kernel_cmdline);
166- memcpy (p + 2, kernel_cmdline, cmdline_size + 1);
167+ cmdline_size = strlen(info->kernel_cmdline);
168+ memcpy(p + 2, info->kernel_cmdline, cmdline_size + 1);
169 cmdline_size = (cmdline_size >> 2) + 1;
170 stl_raw(p++, cmdline_size + 2);
171 stl_raw(p++, 0x54410009);
172 p += cmdline_size;
173 }
174+ if (info->atag_board) {
175+ /* ATAG_BOARD */
176+ int atag_board_len;
177+
178+ atag_board_len = (info->atag_board(info, p + 2) + 3) >> 2;
179+ stl_raw(p++, 2 + atag_board_len);
180+ stl_raw(p++, 0x414f4d50);
181+ p += atag_board_len;
182+ }
183 /* ATAG_END */
184 stl_raw(p++, 0);
185 stl_raw(p++, 0);
186 }
187
188-static void set_kernel_args_old(uint32_t ram_size, int initrd_size,
189- const char *kernel_cmdline,
190- target_phys_addr_t loader_start)
191+static void set_kernel_args_old(struct arm_boot_info *info,
192+ int initrd_size, void *base)
193 {
194 uint32_t *p;
195 unsigned char *s;
196
197 /* see linux/include/asm-arm/setup.h */
198- p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR);
199+ p = (uint32_t *)(base + KERNEL_ARGS_ADDR);
200 /* page_size */
201 stl_raw(p++, 4096);
202 /* nr_pages */
203- stl_raw(p++, ram_size / 4096);
204+ stl_raw(p++, info->ram_size / 4096);
205 /* ramdisk_size */
206 stl_raw(p++, 0);
207 #define FLAG_READONLY 1
208@@ -142,7 +148,7 @@ static void set_kernel_args_old(uint32_t ram_size, int initrd_size,
209 stl_raw(p++, 0);
210 /* initrd_start */
211 if (initrd_size)
212- stl_raw(p++, loader_start + INITRD_LOAD_ADDR);
213+ stl_raw(p++, info->loader_start + INITRD_LOAD_ADDR);
214 else
215 stl_raw(p++, 0);
216 /* initrd_size */
217@@ -159,17 +165,15 @@ static void set_kernel_args_old(uint32_t ram_size, int initrd_size,
218 stl_raw(p++, 0);
219 /* zero unused fields */
220 memset(p, 0, 256 + 1024 -
221- (p - ((uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR))));
222- s = phys_ram_base + KERNEL_ARGS_ADDR + 256 + 1024;
223- if (kernel_cmdline)
224- strcpy (s, kernel_cmdline);
225+ (p - ((uint32_t *)(base + KERNEL_ARGS_ADDR))));
226+ s = base + KERNEL_ARGS_ADDR + 256 + 1024;
227+ if (info->kernel_cmdline)
228+ strcpy (s, info->kernel_cmdline);
229 else
230 stb_raw(s, 0);
231 }
232
233-void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
234- const char *kernel_cmdline, const char *initrd_filename,
235- int board_id, target_phys_addr_t loader_start)
236+void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
237 {
238 int kernel_size;
239 int initrd_size;
240@@ -177,36 +181,41 @@ void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
241 int is_linux = 0;
242 uint64_t elf_entry;
243 target_ulong entry;
244+ uint32_t pd;
245+ void *loader_phys;
246
247 /* Load the kernel. */
248- if (!kernel_filename) {
249+ if (!info->kernel_filename) {
250 fprintf(stderr, "Kernel image must be specified\n");
251 exit(1);
252 }
253
254- if (!env->kernel_filename) {
255- env->ram_size = ram_size;
256- env->kernel_filename = kernel_filename;
257- env->kernel_cmdline = kernel_cmdline;
258- env->initrd_filename = initrd_filename;
259- env->board_id = board_id;
260- env->loader_start = loader_start;
261+ if (!env->boot_info) {
262+ if (info->nb_cpus == 0)
263+ info->nb_cpus = 1;
264+ env->boot_info = info;
265 qemu_register_reset(main_cpu_reset, env);
266 }
267+
268+ pd = cpu_get_physical_page_desc(info->loader_start);
269+ loader_phys = phys_ram_base + (pd & TARGET_PAGE_MASK) +
270+ (info->loader_start & ~TARGET_PAGE_MASK);
271+
272 /* Assume that raw images are linux kernels, and ELF images are not. */
273- kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL);
274+ kernel_size = load_elf(info->kernel_filename, 0, &elf_entry, NULL, NULL);
275 entry = elf_entry;
276 if (kernel_size < 0) {
277- kernel_size = load_uboot(kernel_filename, &entry, &is_linux);
278+ kernel_size = load_uboot(info->kernel_filename, &entry, &is_linux);
279 }
280 if (kernel_size < 0) {
281- kernel_size = load_image(kernel_filename,
282- phys_ram_base + KERNEL_LOAD_ADDR);
283- entry = loader_start + KERNEL_LOAD_ADDR;
284+ kernel_size = load_image(info->kernel_filename,
285+ loader_phys + KERNEL_LOAD_ADDR);
286+ entry = info->loader_start + KERNEL_LOAD_ADDR;
287 is_linux = 1;
288 }
289 if (kernel_size < 0) {
290- fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
291+ fprintf(stderr, "qemu: could not load kernel '%s'\n",
292+ info->kernel_filename);
293 exit(1);
294 }
295 if (!is_linux) {
296@@ -214,30 +223,29 @@ void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
297 env->regs[15] = entry & 0xfffffffe;
298 env->thumb = entry & 1;
299 } else {
300- if (initrd_filename) {
301- initrd_size = load_image(initrd_filename,
302- phys_ram_base + INITRD_LOAD_ADDR);
303+ if (info->initrd_filename) {
304+ initrd_size = load_image(info->initrd_filename,
305+ loader_phys + INITRD_LOAD_ADDR);
306 if (initrd_size < 0) {
307 fprintf(stderr, "qemu: could not load initrd '%s'\n",
308- initrd_filename);
309+ info->initrd_filename);
310 exit(1);
311 }
312 } else {
313 initrd_size = 0;
314 }
315- bootloader[1] |= board_id & 0xff;
316- bootloader[2] |= (board_id >> 8) & 0xff;
317- bootloader[5] = loader_start + KERNEL_ARGS_ADDR;
318+ bootloader[1] |= info->board_id & 0xff;
319+ bootloader[2] |= (info->board_id >> 8) & 0xff;
320+ bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR;
321 bootloader[6] = entry;
322 for (n = 0; n < sizeof(bootloader) / 4; n++)
323- stl_raw(phys_ram_base + (n * 4), bootloader[n]);
324- for (n = 0; n < sizeof(smpboot) / 4; n++)
325- stl_raw(phys_ram_base + ram_size + (n * 4), smpboot[n]);
326+ stl_raw(loader_phys + (n * 4), bootloader[n]);
327+ if (info->nb_cpus > 1)
328+ for (n = 0; n < sizeof(smpboot) / 4; n++)
329+ stl_raw(loader_phys + info->ram_size + (n * 4), smpboot[n]);
330 if (old_param)
331- set_kernel_args_old(ram_size, initrd_size,
332- kernel_cmdline, loader_start);
333+ set_kernel_args_old(info, initrd_size, loader_phys);
334 else
335- set_kernel_args(ram_size, initrd_size,
336- kernel_cmdline, loader_start);
337+ set_kernel_args(info, initrd_size, loader_phys);
338 }
339 }
340diff --git a/hw/blizzard.c b/hw/blizzard.c
341new file mode 100644
342index 0000000..9046b5d
343--- /dev/null
344+++ b/hw/blizzard.c
345@@ -0,0 +1,1001 @@
346+/*
347+ * Epson S1D13744/S1D13745 (Blizzard/Hailstorm/Tornado) LCD/TV controller.
348+ *
349+ * Copyright (C) 2008 Nokia Corporation
350+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
351+ *
352+ * This program is free software; you can redistribute it and/or
353+ * modify it under the terms of the GNU General Public License as
354+ * published by the Free Software Foundation; either version 2 of
355+ * the License, or (at your option) any later version.
356+ *
357+ * This program is distributed in the hope that it will be useful,
358+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
359+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
360+ * GNU General Public License for more details.
361+ *
362+ * You should have received a copy of the GNU General Public License
363+ * along with this program; if not, write to the Free Software
364+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
365+ * MA 02111-1307 USA
366+ */
367+
368+#include "qemu-common.h"
369+#include "sysemu.h"
370+#include "console.h"
371+#include "devices.h"
372+#include "vga_int.h"
373+#include "pixel_ops.h"
374+
375+typedef void (*blizzard_fn_t)(uint8_t *, const uint8_t *, unsigned int);
376+
377+struct blizzard_s {
378+ uint8_t reg;
379+ uint32_t addr;
380+ int swallow;
381+
382+ int pll;
383+ int pll_range;
384+ int pll_ctrl;
385+ uint8_t pll_mode;
386+ uint8_t clksel;
387+ int memenable;
388+ int memrefresh;
389+ uint8_t timing[3];
390+ int priority;
391+
392+ uint8_t lcd_config;
393+ int x;
394+ int y;
395+ int skipx;
396+ int skipy;
397+ uint8_t hndp;
398+ uint8_t vndp;
399+ uint8_t hsync;
400+ uint8_t vsync;
401+ uint8_t pclk;
402+ uint8_t u;
403+ uint8_t v;
404+ uint8_t yrc[2];
405+ int ix[2];
406+ int iy[2];
407+ int ox[2];
408+ int oy[2];
409+
410+ int enable;
411+ int blank;
412+ int bpp;
413+ int invalidate;
414+ int mx[2];
415+ int my[2];
416+ uint8_t mode;
417+ uint8_t effect;
418+ uint8_t iformat;
419+ uint8_t source;
420+ DisplayState *state;
421+ blizzard_fn_t *line_fn_tab[2];
422+ void *fb;
423+
424+ uint8_t hssi_config[3];
425+ uint8_t tv_config;
426+ uint8_t tv_timing[4];
427+ uint8_t vbi;
428+ uint8_t tv_x;
429+ uint8_t tv_y;
430+ uint8_t tv_test;
431+ uint8_t tv_filter_config;
432+ uint8_t tv_filter_idx;
433+ uint8_t tv_filter_coeff[0x20];
434+ uint8_t border_r;
435+ uint8_t border_g;
436+ uint8_t border_b;
437+ uint8_t gamma_config;
438+ uint8_t gamma_idx;
439+ uint8_t gamma_lut[0x100];
440+ uint8_t matrix_ena;
441+ uint8_t matrix_coeff[0x12];
442+ uint8_t matrix_r;
443+ uint8_t matrix_g;
444+ uint8_t matrix_b;
445+ uint8_t pm;
446+ uint8_t status;
447+ uint8_t rgbgpio_dir;
448+ uint8_t rgbgpio;
449+ uint8_t gpio_dir;
450+ uint8_t gpio;
451+ uint8_t gpio_edge[2];
452+ uint8_t gpio_irq;
453+ uint8_t gpio_pdown;
454+
455+ struct {
456+ int x;
457+ int y;
458+ int dx;
459+ int dy;
460+ int len;
461+ int buflen;
462+ void *buf;
463+ void *data;
464+ uint16_t *ptr;
465+ int angle;
466+ int pitch;
467+ blizzard_fn_t line_fn;
468+ } data;
469+};
470+
471+/* Bytes(!) per pixel */
472+static const int blizzard_iformat_bpp[0x10] = {
473+ 0,
474+ 2, /* RGB 5:6:5*/
475+ 3, /* RGB 6:6:6 mode 1 */
476+ 3, /* RGB 8:8:8 mode 1 */
477+ 0, 0,
478+ 4, /* RGB 6:6:6 mode 2 */
479+ 4, /* RGB 8:8:8 mode 2 */
480+ 0, /* YUV 4:2:2 */
481+ 0, /* YUV 4:2:0 */
482+ 0, 0, 0, 0, 0, 0,
483+};
484+
485+static inline void blizzard_rgb2yuv(int r, int g, int b,
486+ int *y, int *u, int *v)
487+{
488+ *y = 0x10 + ((0x838 * r + 0x1022 * g + 0x322 * b) >> 13);
489+ *u = 0x80 + ((0xe0e * b - 0x04c1 * r - 0x94e * g) >> 13);
490+ *v = 0x80 + ((0xe0e * r - 0x0bc7 * g - 0x247 * b) >> 13);
491+}
492+
493+static void blizzard_window(struct blizzard_s *s)
494+{
495+ uint8_t *src, *dst;
496+ int bypp[2];
497+ int bypl[3];
498+ int y;
499+ blizzard_fn_t fn = s->data.line_fn;
500+
501+ if (!fn)
502+ return;
503+ if (s->mx[0] > s->data.x)
504+ s->mx[0] = s->data.x;
505+ if (s->my[0] > s->data.y)
506+ s->my[0] = s->data.y;
507+ if (s->mx[1] < s->data.x + s->data.dx)
508+ s->mx[1] = s->data.x + s->data.dx;
509+ if (s->my[1] < s->data.y + s->data.dy)
510+ s->my[1] = s->data.y + s->data.dy;
511+
512+ bypp[0] = s->bpp;
513+ bypp[1] = (s->state->depth + 7) >> 3;
514+ bypl[0] = bypp[0] * s->data.pitch;
515+ bypl[1] = bypp[1] * s->x;
516+ bypl[2] = bypp[0] * s->data.dx;
517+
518+ src = s->data.data;
519+ dst = s->fb + bypl[1] * s->data.y + bypp[1] * s->data.x;
520+ for (y = s->data.dy; y > 0; y --, src += bypl[0], dst += bypl[1])
521+ fn(dst, src, bypl[2]);
522+}
523+
524+static int blizzard_transfer_setup(struct blizzard_s *s)
525+{
526+ if (s->source > 3 || !s->bpp ||
527+ s->ix[1] < s->ix[0] || s->iy[1] < s->iy[0])
528+ return 0;
529+
530+ s->data.angle = s->effect & 3;
531+ s->data.line_fn = s->line_fn_tab[!!s->data.angle][s->iformat];
532+ s->data.x = s->ix[0];
533+ s->data.y = s->iy[0];
534+ s->data.dx = s->ix[1] - s->ix[0] + 1;
535+ s->data.dy = s->iy[1] - s->iy[0] + 1;
536+ s->data.len = s->bpp * s->data.dx * s->data.dy;
537+ s->data.pitch = s->data.dx;
538+ if (s->data.len > s->data.buflen) {
539+ s->data.buf = realloc(s->data.buf, s->data.len);
540+ s->data.buflen = s->data.len;
541+ }
542+ s->data.ptr = s->data.buf;
543+ s->data.data = s->data.buf;
544+ s->data.len /= 2;
545+ return 1;
546+}
547+
548+static void blizzard_reset(struct blizzard_s *s)
549+{
550+ s->reg = 0;
551+ s->swallow = 0;
552+
553+ s->pll = 9;
554+ s->pll_range = 1;
555+ s->pll_ctrl = 0x14;
556+ s->pll_mode = 0x32;
557+ s->clksel = 0x00;
558+ s->memenable = 0;
559+ s->memrefresh = 0x25c;
560+ s->timing[0] = 0x3f;
561+ s->timing[1] = 0x13;
562+ s->timing[2] = 0x21;
563+ s->priority = 0;
564+
565+ s->lcd_config = 0x74;
566+ s->x = 8;
567+ s->y = 1;
568+ s->skipx = 0;
569+ s->skipy = 0;
570+ s->hndp = 3;
571+ s->vndp = 2;
572+ s->hsync = 1;
573+ s->vsync = 1;
574+ s->pclk = 0x80;
575+
576+ s->ix[0] = 0;
577+ s->ix[1] = 0;
578+ s->iy[0] = 0;
579+ s->iy[1] = 0;
580+ s->ox[0] = 0;
581+ s->ox[1] = 0;
582+ s->oy[0] = 0;
583+ s->oy[1] = 0;
584+
585+ s->yrc[0] = 0x00;
586+ s->yrc[1] = 0x30;
587+ s->u = 0;
588+ s->v = 0;
589+
590+ s->iformat = 3;
591+ s->source = 0;
592+ s->bpp = blizzard_iformat_bpp[s->iformat];
593+
594+ s->hssi_config[0] = 0x00;
595+ s->hssi_config[1] = 0x00;
596+ s->hssi_config[2] = 0x01;
597+ s->tv_config = 0x00;
598+ s->tv_timing[0] = 0x00;
599+ s->tv_timing[1] = 0x00;
600+ s->tv_timing[2] = 0x00;
601+ s->tv_timing[3] = 0x00;
602+ s->vbi = 0x10;
603+ s->tv_x = 0x14;
604+ s->tv_y = 0x03;
605+ s->tv_test = 0x00;
606+ s->tv_filter_config = 0x80;
607+ s->tv_filter_idx = 0x00;
608+ s->border_r = 0x10;
609+ s->border_g = 0x80;
610+ s->border_b = 0x80;
611+ s->gamma_config = 0x00;
612+ s->gamma_idx = 0x00;
613+ s->matrix_ena = 0x00;
614+ memset(&s->matrix_coeff, 0, sizeof(s->matrix_coeff));
615+ s->matrix_r = 0x00;
616+ s->matrix_g = 0x00;
617+ s->matrix_b = 0x00;
618+ s->pm = 0x02;
619+ s->status = 0x00;
620+ s->rgbgpio_dir = 0x00;
621+ s->gpio_dir = 0x00;
622+ s->gpio_edge[0] = 0x00;
623+ s->gpio_edge[1] = 0x00;
624+ s->gpio_irq = 0x00;
625+ s->gpio_pdown = 0xff;
626+}
627+
628+static inline void blizzard_invalidate_display(void *opaque) {
629+ struct blizzard_s *s = (struct blizzard_s *) opaque;
630+
631+ s->invalidate = 1;
632+}
633+
634+static uint16_t blizzard_reg_read(void *opaque, uint8_t reg)
635+{
636+ struct blizzard_s *s = (struct blizzard_s *) opaque;
637+
638+ switch (reg) {
639+ case 0x00: /* Revision Code */
640+ return 0xa5;
641+
642+ case 0x02: /* Configuration Readback */
643+ return 0x83; /* Macrovision OK, CNF[2:0] = 3 */
644+
645+ case 0x04: /* PLL M-Divider */
646+ return (s->pll - 1) | (1 << 7);
647+ case 0x06: /* PLL Lock Range Control */
648+ return s->pll_range;
649+ case 0x08: /* PLL Lock Synthesis Control 0 */
650+ return s->pll_ctrl & 0xff;
651+ case 0x0a: /* PLL Lock Synthesis Control 1 */
652+ return s->pll_ctrl >> 8;
653+ case 0x0c: /* PLL Mode Control 0 */
654+ return s->pll_mode;
655+
656+ case 0x0e: /* Clock-Source Select */
657+ return s->clksel;
658+
659+ case 0x10: /* Memory Controller Activate */
660+ case 0x14: /* Memory Controller Bank 0 Status Flag */
661+ return s->memenable;
662+
663+ case 0x18: /* Auto-Refresh Interval Setting 0 */
664+ return s->memrefresh & 0xff;
665+ case 0x1a: /* Auto-Refresh Interval Setting 1 */
666+ return s->memrefresh >> 8;
667+
668+ case 0x1c: /* Power-On Sequence Timing Control */
669+ return s->timing[0];
670+ case 0x1e: /* Timing Control 0 */
671+ return s->timing[1];
672+ case 0x20: /* Timing Control 1 */
673+ return s->timing[2];
674+
675+ case 0x24: /* Arbitration Priority Control */
676+ return s->priority;
677+
678+ case 0x28: /* LCD Panel Configuration */
679+ return s->lcd_config;
680+
681+ case 0x2a: /* LCD Horizontal Display Width */
682+ return s->x >> 3;
683+ case 0x2c: /* LCD Horizontal Non-display Period */
684+ return s->hndp;
685+ case 0x2e: /* LCD Vertical Display Height 0 */
686+ return s->y & 0xff;
687+ case 0x30: /* LCD Vertical Display Height 1 */
688+ return s->y >> 8;
689+ case 0x32: /* LCD Vertical Non-display Period */
690+ return s->vndp;
691+ case 0x34: /* LCD HS Pulse-width */
692+ return s->hsync;
693+ case 0x36: /* LCd HS Pulse Start Position */
694+ return s->skipx >> 3;
695+ case 0x38: /* LCD VS Pulse-width */
696+ return s->vsync;
697+ case 0x3a: /* LCD VS Pulse Start Position */
698+ return s->skipy;
699+
700+ case 0x3c: /* PCLK Polarity */
701+ return s->pclk;
702+
703+ case 0x3e: /* High-speed Serial Interface Tx Configuration Port 0 */
704+ return s->hssi_config[0];
705+ case 0x40: /* High-speed Serial Interface Tx Configuration Port 1 */
706+ return s->hssi_config[1];
707+ case 0x42: /* High-speed Serial Interface Tx Mode */
708+ return s->hssi_config[2];
709+ case 0x44: /* TV Display Configuration */
710+ return s->tv_config;
711+ case 0x46 ... 0x4c: /* TV Vertical Blanking Interval Data bits */
712+ return s->tv_timing[(reg - 0x46) >> 1];
713+ case 0x4e: /* VBI: Closed Caption / XDS Control / Status */
714+ return s->vbi;
715+ case 0x50: /* TV Horizontal Start Position */
716+ return s->tv_x;
717+ case 0x52: /* TV Vertical Start Position */
718+ return s->tv_y;
719+ case 0x54: /* TV Test Pattern Setting */
720+ return s->tv_test;
721+ case 0x56: /* TV Filter Setting */
722+ return s->tv_filter_config;
723+ case 0x58: /* TV Filter Coefficient Index */
724+ return s->tv_filter_idx;
725+ case 0x5a: /* TV Filter Coefficient Data */
726+ if (s->tv_filter_idx < 0x20)
727+ return s->tv_filter_coeff[s->tv_filter_idx ++];
728+ return 0;
729+
730+ case 0x60: /* Input YUV/RGB Translate Mode 0 */
731+ return s->yrc[0];
732+ case 0x62: /* Input YUV/RGB Translate Mode 1 */
733+ return s->yrc[1];
734+ case 0x64: /* U Data Fix */
735+ return s->u;
736+ case 0x66: /* V Data Fix */
737+ return s->v;
738+
739+ case 0x68: /* Display Mode */
740+ return s->mode;
741+
742+ case 0x6a: /* Special Effects */
743+ return s->effect;
744+
745+ case 0x6c: /* Input Window X Start Position 0 */
746+ return s->ix[0] & 0xff;
747+ case 0x6e: /* Input Window X Start Position 1 */
748+ return s->ix[0] >> 3;
749+ case 0x70: /* Input Window Y Start Position 0 */
750+ return s->ix[0] & 0xff;
751+ case 0x72: /* Input Window Y Start Position 1 */
752+ return s->ix[0] >> 3;
753+ case 0x74: /* Input Window X End Position 0 */
754+ return s->ix[1] & 0xff;
755+ case 0x76: /* Input Window X End Position 1 */
756+ return s->ix[1] >> 3;
757+ case 0x78: /* Input Window Y End Position 0 */
758+ return s->ix[1] & 0xff;
759+ case 0x7a: /* Input Window Y End Position 1 */
760+ return s->ix[1] >> 3;
761+ case 0x7c: /* Output Window X Start Position 0 */
762+ return s->ox[0] & 0xff;
763+ case 0x7e: /* Output Window X Start Position 1 */
764+ return s->ox[0] >> 3;
765+ case 0x80: /* Output Window Y Start Position 0 */
766+ return s->oy[0] & 0xff;
767+ case 0x82: /* Output Window Y Start Position 1 */
768+ return s->oy[0] >> 3;
769+ case 0x84: /* Output Window X End Position 0 */
770+ return s->ox[1] & 0xff;
771+ case 0x86: /* Output Window X End Position 1 */
772+ return s->ox[1] >> 3;
773+ case 0x88: /* Output Window Y End Position 0 */
774+ return s->oy[1] & 0xff;
775+ case 0x8a: /* Output Window Y End Position 1 */
776+ return s->oy[1] >> 3;
777+
778+ case 0x8c: /* Input Data Format */
779+ return s->iformat;
780+ case 0x8e: /* Data Source Select */
781+ return s->source;
782+ case 0x90: /* Display Memory Data Port */
783+ return 0;
784+
785+ case 0xa8: /* Border Color 0 */
786+ return s->border_r;
787+ case 0xaa: /* Border Color 1 */
788+ return s->border_g;
789+ case 0xac: /* Border Color 2 */
790+ return s->border_b;
791+
792+ case 0xb4: /* Gamma Correction Enable */
793+ return s->gamma_config;
794+ case 0xb6: /* Gamma Correction Table Index */
795+ return s->gamma_idx;
796+ case 0xb8: /* Gamma Correction Table Data */
797+ return s->gamma_lut[s->gamma_idx ++];
798+
799+ case 0xba: /* 3x3 Matrix Enable */
800+ return s->matrix_ena;
801+ case 0xbc ... 0xde: /* Coefficient Registers */
802+ return s->matrix_coeff[(reg - 0xbc) >> 1];
803+ case 0xe0: /* 3x3 Matrix Red Offset */
804+ return s->matrix_r;
805+ case 0xe2: /* 3x3 Matrix Green Offset */
806+ return s->matrix_g;
807+ case 0xe4: /* 3x3 Matrix Blue Offset */
808+ return s->matrix_b;
809+
810+ case 0xe6: /* Power-save */
811+ return s->pm;
812+ case 0xe8: /* Non-display Period Control / Status */
813+ return s->status | (1 << 5);
814+ case 0xea: /* RGB Interface Control */
815+ return s->rgbgpio_dir;
816+ case 0xec: /* RGB Interface Status */
817+ return s->rgbgpio;
818+ case 0xee: /* General-purpose IO Pins Configuration */
819+ return s->gpio_dir;
820+ case 0xf0: /* General-purpose IO Pins Status / Control */
821+ return s->gpio;
822+ case 0xf2: /* GPIO Positive Edge Interrupt Trigger */
823+ return s->gpio_edge[0];
824+ case 0xf4: /* GPIO Negative Edge Interrupt Trigger */
825+ return s->gpio_edge[1];
826+ case 0xf6: /* GPIO Interrupt Status */
827+ return s->gpio_irq;
828+ case 0xf8: /* GPIO Pull-down Control */
829+ return s->gpio_pdown;
830+
831+ default:
832+ fprintf(stderr, "%s: unknown register %02x\n", __FUNCTION__, reg);
833+ return 0;
834+ }
835+}
836+
837+static void blizzard_reg_write(void *opaque, uint8_t reg, uint16_t value)
838+{
839+ struct blizzard_s *s = (struct blizzard_s *) opaque;
840+
841+ switch (reg) {
842+ case 0x04: /* PLL M-Divider */
843+ s->pll = (value & 0x3f) + 1;
844+ break;
845+ case 0x06: /* PLL Lock Range Control */
846+ s->pll_range = value & 3;
847+ break;
848+ case 0x08: /* PLL Lock Synthesis Control 0 */
849+ s->pll_ctrl &= 0xf00;
850+ s->pll_ctrl |= (value << 0) & 0x0ff;
851+ break;
852+ case 0x0a: /* PLL Lock Synthesis Control 1 */
853+ s->pll_ctrl &= 0x0ff;
854+ s->pll_ctrl |= (value << 8) & 0xf00;
855+ break;
856+ case 0x0c: /* PLL Mode Control 0 */
857+ s->pll_mode = value & 0x77;
858+ if ((value & 3) == 0 || (value & 3) == 3)
859+ fprintf(stderr, "%s: wrong PLL Control bits (%i)\n",
860+ __FUNCTION__, value & 3);
861+ break;
862+
863+ case 0x0e: /* Clock-Source Select */
864+ s->clksel = value & 0xff;
865+ break;
866+
867+ case 0x10: /* Memory Controller Activate */
868+ s->memenable = value & 1;
869+ break;
870+ case 0x14: /* Memory Controller Bank 0 Status Flag */
871+ break;
872+
873+ case 0x18: /* Auto-Refresh Interval Setting 0 */
874+ s->memrefresh &= 0xf00;
875+ s->memrefresh |= (value << 0) & 0x0ff;
876+ break;
877+ case 0x1a: /* Auto-Refresh Interval Setting 1 */
878+ s->memrefresh &= 0x0ff;
879+ s->memrefresh |= (value << 8) & 0xf00;
880+ break;
881+
882+ case 0x1c: /* Power-On Sequence Timing Control */
883+ s->timing[0] = value & 0x7f;
884+ break;
885+ case 0x1e: /* Timing Control 0 */
886+ s->timing[1] = value & 0x17;
887+ break;
888+ case 0x20: /* Timing Control 1 */
889+ s->timing[2] = value & 0x35;
890+ break;
891+
892+ case 0x24: /* Arbitration Priority Control */
893+ s->priority = value & 1;
894+ break;
895+
896+ case 0x28: /* LCD Panel Configuration */
897+ s->lcd_config = value & 0xff;
898+ if (value & (1 << 7))
899+ fprintf(stderr, "%s: data swap not supported!\n", __FUNCTION__);
900+ break;
901+
902+ case 0x2a: /* LCD Horizontal Display Width */
903+ s->x = value << 3;
904+ break;
905+ case 0x2c: /* LCD Horizontal Non-display Period */
906+ s->hndp = value & 0xff;
907+ break;
908+ case 0x2e: /* LCD Vertical Display Height 0 */
909+ s->y &= 0x300;
910+ s->y |= (value << 0) & 0x0ff;
911+ break;
912+ case 0x30: /* LCD Vertical Display Height 1 */
913+ s->y &= 0x0ff;
914+ s->y |= (value << 8) & 0x300;
915+ break;
916+ case 0x32: /* LCD Vertical Non-display Period */
917+ s->vndp = value & 0xff;
918+ break;
919+ case 0x34: /* LCD HS Pulse-width */
920+ s->hsync = value & 0xff;
921+ break;
922+ case 0x36: /* LCD HS Pulse Start Position */
923+ s->skipx = value & 0xff;
924+ break;
925+ case 0x38: /* LCD VS Pulse-width */
926+ s->vsync = value & 0xbf;
927+ break;
928+ case 0x3a: /* LCD VS Pulse Start Position */
929+ s->skipy = value & 0xff;
930+ break;
931+
932+ case 0x3c: /* PCLK Polarity */
933+ s->pclk = value & 0x82;
934+ /* Affects calculation of s->hndp, s->hsync and s->skipx. */
935+ break;
936+
937+ case 0x3e: /* High-speed Serial Interface Tx Configuration Port 0 */
938+ s->hssi_config[0] = value;
939+ break;
940+ case 0x40: /* High-speed Serial Interface Tx Configuration Port 1 */
941+ s->hssi_config[1] = value;
942+ if (((value >> 4) & 3) == 3)
943+ fprintf(stderr, "%s: Illegal active-data-links value\n",
944+ __FUNCTION__);
945+ break;
946+ case 0x42: /* High-speed Serial Interface Tx Mode */
947+ s->hssi_config[2] = value & 0xbd;
948+ break;
949+
950+ case 0x44: /* TV Display Configuration */
951+ s->tv_config = value & 0xfe;
952+ break;
953+ case 0x46 ... 0x4c: /* TV Vertical Blanking Interval Data bits 0 */
954+ s->tv_timing[(reg - 0x46) >> 1] = value;
955+ break;
956+ case 0x4e: /* VBI: Closed Caption / XDS Control / Status */
957+ s->vbi = value;
958+ break;
959+ case 0x50: /* TV Horizontal Start Position */
960+ s->tv_x = value;
961+ break;
962+ case 0x52: /* TV Vertical Start Position */
963+ s->tv_y = value & 0x7f;
964+ break;
965+ case 0x54: /* TV Test Pattern Setting */
966+ s->tv_test = value;
967+ break;
968+ case 0x56: /* TV Filter Setting */
969+ s->tv_filter_config = value & 0xbf;
970+ break;
971+ case 0x58: /* TV Filter Coefficient Index */
972+ s->tv_filter_idx = value & 0x1f;
973+ break;
974+ case 0x5a: /* TV Filter Coefficient Data */
975+ if (s->tv_filter_idx < 0x20)
976+ s->tv_filter_coeff[s->tv_filter_idx ++] = value;
977+ break;
978+
979+ case 0x60: /* Input YUV/RGB Translate Mode 0 */
980+ s->yrc[0] = value & 0xb0;
981+ break;
982+ case 0x62: /* Input YUV/RGB Translate Mode 1 */
983+ s->yrc[1] = value & 0x30;
984+ break;
985+ case 0x64: /* U Data Fix */
986+ s->u = value & 0xff;
987+ break;
988+ case 0x66: /* V Data Fix */
989+ s->v = value & 0xff;
990+ break;
991+
992+ case 0x68: /* Display Mode */
993+ if ((s->mode ^ value) & 3)
994+ s->invalidate = 1;
995+ s->mode = value & 0xb7;
996+ s->enable = value & 1;
997+ s->blank = (value >> 1) & 1;
998+ if (value & (1 << 4))
999+ fprintf(stderr, "%s: Macrovision enable attempt!\n", __FUNCTION__);
1000+ break;
1001+
1002+ case 0x6a: /* Special Effects */
1003+ s->effect = value & 0xfb;
1004+ break;
1005+
1006+ case 0x6c: /* Input Window X Start Position 0 */
1007+ s->ix[0] &= 0x300;
1008+ s->ix[0] |= (value << 0) & 0x0ff;
1009+ break;
1010+ case 0x6e: /* Input Window X Start Position 1 */
1011+ s->ix[0] &= 0x0ff;
1012+ s->ix[0] |= (value << 8) & 0x300;
1013+ break;
1014+ case 0x70: /* Input Window Y Start Position 0 */
1015+ s->iy[0] &= 0x300;
1016+ s->iy[0] |= (value << 0) & 0x0ff;
1017+ break;
1018+ case 0x72: /* Input Window Y Start Position 1 */
1019+ s->iy[0] &= 0x0ff;
1020+ s->iy[0] |= (value << 8) & 0x300;
1021+ break;
1022+ case 0x74: /* Input Window X End Position 0 */
1023+ s->ix[1] &= 0x300;
1024+ s->ix[1] |= (value << 0) & 0x0ff;
1025+ break;
1026+ case 0x76: /* Input Window X End Position 1 */
1027+ s->ix[1] &= 0x0ff;
1028+ s->ix[1] |= (value << 8) & 0x300;
1029+ break;
1030+ case 0x78: /* Input Window Y End Position 0 */
1031+ s->iy[1] &= 0x300;
1032+ s->iy[1] |= (value << 0) & 0x0ff;
1033+ break;
1034+ case 0x7a: /* Input Window Y End Position 1 */
1035+ s->iy[1] &= 0x0ff;
1036+ s->iy[1] |= (value << 8) & 0x300;
1037+ break;
1038+ case 0x7c: /* Output Window X Start Position 0 */
1039+ s->ox[0] &= 0x300;
1040+ s->ox[0] |= (value << 0) & 0x0ff;
1041+ break;
1042+ case 0x7e: /* Output Window X Start Position 1 */
1043+ s->ox[0] &= 0x0ff;
1044+ s->ox[0] |= (value << 8) & 0x300;
1045+ break;
1046+ case 0x80: /* Output Window Y Start Position 0 */
1047+ s->oy[0] &= 0x300;
1048+ s->oy[0] |= (value << 0) & 0x0ff;
1049+ break;
1050+ case 0x82: /* Output Window Y Start Position 1 */
1051+ s->oy[0] &= 0x0ff;
1052+ s->oy[0] |= (value << 8) & 0x300;
1053+ break;
1054+ case 0x84: /* Output Window X End Position 0 */
1055+ s->ox[1] &= 0x300;
1056+ s->ox[1] |= (value << 0) & 0x0ff;
1057+ break;
1058+ case 0x86: /* Output Window X End Position 1 */
1059+ s->ox[1] &= 0x0ff;
1060+ s->ox[1] |= (value << 8) & 0x300;
1061+ break;
1062+ case 0x88: /* Output Window Y End Position 0 */
1063+ s->oy[1] &= 0x300;
1064+ s->oy[1] |= (value << 0) & 0x0ff;
1065+ break;
1066+ case 0x8a: /* Output Window Y End Position 1 */
1067+ s->oy[1] &= 0x0ff;
1068+ s->oy[1] |= (value << 8) & 0x300;
1069+ break;
1070+
1071+ case 0x8c: /* Input Data Format */
1072+ s->iformat = value & 0xf;
1073+ s->bpp = blizzard_iformat_bpp[s->iformat];
1074+ if (!s->bpp)
1075+ fprintf(stderr, "%s: Illegal or unsupported input format %x\n",
1076+ __FUNCTION__, s->iformat);
1077+ break;
1078+ case 0x8e: /* Data Source Select */
1079+ s->source = value & 7;
1080+ /* Currently all windows will be "destructive overlays". */
1081+ if ((!(s->effect & (1 << 3)) && (s->ix[0] != s->ox[0] ||
1082+ s->iy[0] != s->oy[0] ||
1083+ s->ix[1] != s->ox[1] ||
1084+ s->iy[1] != s->oy[1])) ||
1085+ !((s->ix[1] - s->ix[0]) & (s->iy[1] - s->iy[0]) &
1086+ (s->ox[1] - s->ox[0]) & (s->oy[1] - s->oy[0]) & 1))
1087+ fprintf(stderr, "%s: Illegal input/output window positions\n",
1088+ __FUNCTION__);
1089+
1090+ blizzard_transfer_setup(s);
1091+ break;
1092+
1093+ case 0x90: /* Display Memory Data Port */
1094+ if (!s->data.len && !blizzard_transfer_setup(s))
1095+ break;
1096+
1097+ *s->data.ptr ++ = value;
1098+ if (-- s->data.len == 0)
1099+ blizzard_window(s);
1100+ break;
1101+
1102+ case 0xa8: /* Border Color 0 */
1103+ s->border_r = value;
1104+ break;
1105+ case 0xaa: /* Border Color 1 */
1106+ s->border_g = value;
1107+ break;
1108+ case 0xac: /* Border Color 2 */
1109+ s->border_b = value;
1110+ break;
1111+
1112+ case 0xb4: /* Gamma Correction Enable */
1113+ s->gamma_config = value & 0x87;
1114+ break;
1115+ case 0xb6: /* Gamma Correction Table Index */
1116+ s->gamma_idx = value;
1117+ break;
1118+ case 0xb8: /* Gamma Correction Table Data */
1119+ s->gamma_lut[s->gamma_idx ++] = value;
1120+ break;
1121+
1122+ case 0xba: /* 3x3 Matrix Enable */
1123+ s->matrix_ena = value & 1;
1124+ break;
1125+ case 0xbc ... 0xde: /* Coefficient Registers */
1126+ s->matrix_coeff[(reg - 0xbc) >> 1] = value & ((reg & 2) ? 0x80 : 0xff);
1127+ break;
1128+ case 0xe0: /* 3x3 Matrix Red Offset */
1129+ s->matrix_r = value;
1130+ break;
1131+ case 0xe2: /* 3x3 Matrix Green Offset */
1132+ s->matrix_g = value;
1133+ break;
1134+ case 0xe4: /* 3x3 Matrix Blue Offset */
1135+ s->matrix_b = value;
1136+ break;
1137+
1138+ case 0xe6: /* Power-save */
1139+ s->pm = value & 0x83;
1140+ if (value & s->mode & 1)
1141+ fprintf(stderr, "%s: The display must be disabled before entering "
1142+ "Standby Mode\n", __FUNCTION__);
1143+ break;
1144+ case 0xe8: /* Non-display Period Control / Status */
1145+ s->status = value & 0x1b;
1146+ break;
1147+ case 0xea: /* RGB Interface Control */
1148+ s->rgbgpio_dir = value & 0x8f;
1149+ break;
1150+ case 0xec: /* RGB Interface Status */
1151+ s->rgbgpio = value & 0xcf;
1152+ break;
1153+ case 0xee: /* General-purpose IO Pins Configuration */
1154+ s->gpio_dir = value;
1155+ break;
1156+ case 0xf0: /* General-purpose IO Pins Status / Control */
1157+ s->gpio = value;
1158+ break;
1159+ case 0xf2: /* GPIO Positive Edge Interrupt Trigger */
1160+ s->gpio_edge[0] = value;
1161+ break;
1162+ case 0xf4: /* GPIO Negative Edge Interrupt Trigger */
1163+ s->gpio_edge[1] = value;
1164+ break;
1165+ case 0xf6: /* GPIO Interrupt Status */
1166+ s->gpio_irq &= value;
1167+ break;
1168+ case 0xf8: /* GPIO Pull-down Control */
1169+ s->gpio_pdown = value;
1170+ break;
1171+
1172+ default:
1173+ fprintf(stderr, "%s: unknown register %02x\n", __FUNCTION__, reg);
1174+ break;
1175+ }
1176+}
1177+
1178+uint16_t s1d13745_read(void *opaque, int dc)
1179+{
1180+ struct blizzard_s *s = (struct blizzard_s *) opaque;
1181+ uint16_t value = blizzard_reg_read(s, s->reg);
1182+
1183+ if (s->swallow -- > 0)
1184+ return 0;
1185+ if (dc)
1186+ s->reg ++;
1187+
1188+ return value;
1189+}
1190+
1191+void s1d13745_write(void *opaque, int dc, uint16_t value)
1192+{
1193+ struct blizzard_s *s = (struct blizzard_s *) opaque;
1194+
1195+ if (s->swallow -- > 0)
1196+ return;
1197+ if (dc) {
1198+ blizzard_reg_write(s, s->reg, value);
1199+
1200+ if (s->reg != 0x90 && s->reg != 0x5a && s->reg != 0xb8)
1201+ s->reg += 2;
1202+ } else
1203+ s->reg = value & 0xff;
1204+}
1205+
1206+void s1d13745_write_block(void *opaque, int dc,
1207+ void *buf, size_t len, int pitch)
1208+{
1209+ struct blizzard_s *s = (struct blizzard_s *) opaque;
1210+
1211+ while (len > 0) {
1212+ if (s->reg == 0x90 && dc &&
1213+ (s->data.len || blizzard_transfer_setup(s)) &&
1214+ len >= (s->data.len << 1)) {
1215+ len -= s->data.len << 1;
1216+ s->data.len = 0;
1217+ s->data.data = buf;
1218+ if (pitch)
1219+ s->data.pitch = pitch;
1220+ blizzard_window(s);
1221+ s->data.data = s->data.buf;
1222+ continue;
1223+ }
1224+
1225+ s1d13745_write(opaque, dc, *(uint16_t *) buf);
1226+ len -= 2;
1227+ buf += 2;
1228+ }
1229+
1230+ return;
1231+}
1232+
1233+static void blizzard_update_display(void *opaque)
1234+{
1235+ struct blizzard_s *s = (struct blizzard_s *) opaque;
1236+ int y, bypp, bypl, bwidth;
1237+ uint8_t *src, *dst;
1238+
1239+ if (!s->enable)
1240+ return;
1241+
1242+ if (s->x != s->state->width || s->y != s->state->height) {
1243+ s->invalidate = 1;
1244+ dpy_resize(s->state, s->x, s->y);
1245+ }
1246+
1247+ if (s->invalidate) {
1248+ s->invalidate = 0;
1249+
1250+ if (s->blank) {
1251+ bypp = (s->state->depth + 7) >> 3;
1252+ memset(s->state->data, 0, bypp * s->x * s->y);
1253+ return;
1254+ }
1255+
1256+ s->mx[0] = 0;
1257+ s->mx[1] = s->x;
1258+ s->my[0] = 0;
1259+ s->my[1] = s->y;
1260+ }
1261+
1262+ if (s->mx[1] <= s->mx[0])
1263+ return;
1264+
1265+ bypp = (s->state->depth + 7) >> 3;
1266+ bypl = bypp * s->x;
1267+ bwidth = bypp * (s->mx[1] - s->mx[0]);
1268+ y = s->my[0];
1269+ src = s->fb + bypl * y + bypp * s->mx[0];
1270+ dst = s->state->data + bypl * y + bypp * s->mx[0];
1271+ for (; y < s->my[1]; y ++, src += bypl, dst += bypl)
1272+ memcpy(dst, src, bwidth);
1273+
1274+ dpy_update(s->state, s->mx[0], s->my[0],
1275+ s->mx[1] - s->mx[0], y - s->my[0]);
1276+
1277+ s->mx[0] = s->x;
1278+ s->mx[1] = 0;
1279+ s->my[0] = s->y;
1280+ s->my[1] = 0;
1281+}
1282+
1283+static void blizzard_screen_dump(void *opaque, const char *filename) {
1284+ struct blizzard_s *s = (struct blizzard_s *) opaque;
1285+
1286+ blizzard_update_display(opaque);
1287+ if (s && s->state->data)
1288+ ppm_save(filename, s->state->data, s->x, s->y, s->state->linesize);
1289+}
1290+
1291+#define DEPTH 8
1292+#include "blizzard_template.h"
1293+#define DEPTH 15
1294+#include "blizzard_template.h"
1295+#define DEPTH 16
1296+#include "blizzard_template.h"
1297+#define DEPTH 24
1298+#include "blizzard_template.h"
1299+#define DEPTH 32
1300+#include "blizzard_template.h"
1301+
1302+void *s1d13745_init(qemu_irq gpio_int, DisplayState *ds)
1303+{
1304+ struct blizzard_s *s = (struct blizzard_s *) qemu_mallocz(sizeof(*s));
1305+
1306+ s->state = ds;
1307+ s->fb = qemu_malloc(0x180000);
1308+
1309+ switch (s->state->depth) {
1310+ case 0:
1311+ s->line_fn_tab[0] = s->line_fn_tab[1] =
1312+ qemu_mallocz(sizeof(blizzard_fn_t) * 0x10);
1313+ break;
1314+ case 8:
1315+ s->line_fn_tab[0] = blizzard_draw_fn_8;
1316+ s->line_fn_tab[1] = blizzard_draw_fn_r_8;
1317+ break;
1318+ case 15:
1319+ s->line_fn_tab[0] = blizzard_draw_fn_15;
1320+ s->line_fn_tab[1] = blizzard_draw_fn_r_15;
1321+ break;
1322+ case 16:
1323+ s->line_fn_tab[0] = blizzard_draw_fn_16;
1324+ s->line_fn_tab[1] = blizzard_draw_fn_r_16;
1325+ break;
1326+ case 24:
1327+ s->line_fn_tab[0] = blizzard_draw_fn_24;
1328+ s->line_fn_tab[1] = blizzard_draw_fn_r_24;
1329+ break;
1330+ case 32:
1331+ s->line_fn_tab[0] = blizzard_draw_fn_32;
1332+ s->line_fn_tab[1] = blizzard_draw_fn_r_32;
1333+ break;
1334+ default:
1335+ fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
1336+ exit(1);
1337+ }
1338+
1339+ blizzard_reset(s);
1340+
1341+ graphic_console_init(s->state, blizzard_update_display,
1342+ blizzard_invalidate_display, blizzard_screen_dump,
1343+ NULL, s);
1344+
1345+ return s;
1346+}
1347diff --git a/hw/blizzard_template.h b/hw/blizzard_template.h
1348new file mode 100644
1349index 0000000..8c6451d
1350--- /dev/null
1351+++ b/hw/blizzard_template.h
1352@@ -0,0 +1,138 @@
1353+/*
1354+ * QEMU Epson S1D13744/S1D13745 templates
1355+ *
1356+ * Copyright (C) 2008 Nokia Corporation
1357+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
1358+ *
1359+ * This program is free software; you can redistribute it and/or
1360+ * modify it under the terms of the GNU General Public License as
1361+ * published by the Free Software Foundation; either version 2 of
1362+ * the License, or (at your option) any later version.
1363+ *
1364+ * This program is distributed in the hope that it will be useful,
1365+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1366+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1367+ * GNU General Public License for more details.
1368+ *
1369+ * You should have received a copy of the GNU General Public License
1370+ * along with this program; if not, write to the Free Software
1371+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
1372+ * MA 02111-1307 USA
1373+ */
1374+
1375+#define SKIP_PIXEL(to) to += deststep
1376+#if DEPTH == 8
1377+# define PIXEL_TYPE uint8_t
1378+# define COPY_PIXEL(to, from) *to = from; SKIP_PIXEL(to)
1379+# define COPY_PIXEL1(to, from) *to ++ = from
1380+#elif DEPTH == 15 || DEPTH == 16
1381+# define PIXEL_TYPE uint16_t
1382+# define COPY_PIXEL(to, from) *to = from; SKIP_PIXEL(to)
1383+# define COPY_PIXEL1(to, from) *to ++ = from
1384+#elif DEPTH == 24
1385+# define PIXEL_TYPE uint8_t
1386+# define COPY_PIXEL(to, from) \
1387+ to[0] = from; to[1] = (from) >> 8; to[2] = (from) >> 16; SKIP_PIXEL(to)
1388+# define COPY_PIXEL1(to, from) \
1389+ *to ++ = from; *to ++ = (from) >> 8; *to ++ = (from) >> 16
1390+#elif DEPTH == 32
1391+# define PIXEL_TYPE uint32_t
1392+# define COPY_PIXEL(to, from) *to = from; SKIP_PIXEL(to)
1393+# define COPY_PIXEL1(to, from) *to ++ = from
1394+#else
1395+# error unknown bit depth
1396+#endif
1397+
1398+#ifdef WORDS_BIGENDIAN
1399+# define SWAP_WORDS 1
1400+#endif
1401+
1402+static void glue(blizzard_draw_line16_, DEPTH)(PIXEL_TYPE *dest,
1403+ const uint16_t *src, unsigned int width)
1404+{
1405+#if !defined(SWAP_WORDS) && DEPTH == 16
1406+ memcpy(dest, src, width << 1);
1407+#else
1408+ uint16_t data;
1409+ unsigned int r, g, b;
1410+ const uint16_t *end = (void *) src + width;
1411+ while (src < end) {
1412+ data = lduw_raw(src ++);
1413+ b = (data & 0x1f) << 3;
1414+ data >>= 5;
1415+ g = (data & 0x3f) << 2;
1416+ data >>= 6;
1417+ r = (data & 0x1f) << 3;
1418+ data >>= 5;
1419+ COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b));
1420+ }
1421+#endif
1422+}
1423+
1424+static void glue(blizzard_draw_line24mode1_, DEPTH)(PIXEL_TYPE *dest,
1425+ const uint8_t *src, unsigned int width)
1426+{
1427+ /* TODO: check if SDL 24-bit planes are not in the same format and
1428+ * if so, use memcpy */
1429+ unsigned int r[2], g[2], b[2];
1430+ const uint8_t *end = src + width;
1431+ while (src < end) {
1432+ g[0] = *src ++;
1433+ r[0] = *src ++;
1434+ r[1] = *src ++;
1435+ b[0] = *src ++;
1436+ COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[0], g[0], b[0]));
1437+ b[1] = *src ++;
1438+ g[1] = *src ++;
1439+ COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[1], g[1], b[1]));
1440+ }
1441+}
1442+
1443+static void glue(blizzard_draw_line24mode2_, DEPTH)(PIXEL_TYPE *dest,
1444+ const uint8_t *src, unsigned int width)
1445+{
1446+ unsigned int r, g, b;
1447+ const uint8_t *end = src + width;
1448+ while (src < end) {
1449+ r = *src ++;
1450+ src ++;
1451+ b = *src ++;
1452+ g = *src ++;
1453+ COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b));
1454+ }
1455+}
1456+
1457+/* No rotation */
1458+static blizzard_fn_t glue(blizzard_draw_fn_, DEPTH)[0x10] = {
1459+ NULL,
1460+ /* RGB 5:6:5*/
1461+ (blizzard_fn_t) glue(blizzard_draw_line16_, DEPTH),
1462+ /* RGB 6:6:6 mode 1 */
1463+ (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH),
1464+ /* RGB 8:8:8 mode 1 */
1465+ (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH),
1466+ NULL, NULL,
1467+ /* RGB 6:6:6 mode 2 */
1468+ (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH),
1469+ /* RGB 8:8:8 mode 2 */
1470+ (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH),
1471+ /* YUV 4:2:2 */
1472+ NULL,
1473+ /* YUV 4:2:0 */
1474+ NULL,
1475+ NULL, NULL, NULL, NULL, NULL, NULL,
1476+};
1477+
1478+/* 90deg, 180deg and 270deg rotation */
1479+static blizzard_fn_t glue(blizzard_draw_fn_r_, DEPTH)[0x10] = {
1480+ /* TODO */
1481+ [0 ... 0xf] = NULL,
1482+};
1483+
1484+#undef DEPTH
1485+#undef SKIP_PIXEL
1486+#undef COPY_PIXEL
1487+#undef COPY_PIXEL1
1488+#undef PIXEL_TYPE
1489+
1490+#undef SWAP_WORDS
1491diff --git a/hw/boards.h b/hw/boards.h
1492index affcaa6..408d1e8 100644
1493--- a/hw/boards.h
1494+++ b/hw/boards.h
1495@@ -80,6 +80,9 @@ extern QEMUMachine terrierpda_machine;
1496 /* palm.c */
1497 extern QEMUMachine palmte_machine;
1498
1499+/* nseries.c */
1500+extern QEMUMachine n800_machine;
1501+
1502 /* gumstix.c */
1503 extern QEMUMachine connex_machine;
1504 extern QEMUMachine verdex_machine;
1505diff --git a/hw/cbus.c b/hw/cbus.c
1506new file mode 100644
1507index 0000000..001b007
1508--- /dev/null
1509+++ b/hw/cbus.c
1510@@ -0,0 +1,565 @@
1511+/*
1512+ * CBUS three-pin bus and the Retu / Betty / Tahvo / Vilma / Avilma /
1513+ * Hinku / Vinku / Ahne / Pihi chips used in various Nokia platforms.
1514+ *
1515+ * Copyright (C) 2008 Nokia Corporation
1516+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
1517+ *
1518+ * This program is free software; you can redistribute it and/or
1519+ * modify it under the terms of the GNU General Public License as
1520+ * published by the Free Software Foundation; either version 2 of
1521+ * the License, or (at your option) any later version.
1522+ *
1523+ * This program is distributed in the hope that it will be useful,
1524+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1525+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1526+ * GNU General Public License for more details.
1527+ *
1528+ * You should have received a copy of the GNU General Public License
1529+ * along with this program; if not, write to the Free Software
1530+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
1531+ * MA 02111-1307 USA
1532+ */
1533+
1534+#include "qemu-common.h"
1535+#include "irq.h"
1536+#include "devices.h"
1537+#include "sysemu.h"
1538+
1539+//#define DEBUG
1540+
1541+struct cbus_slave_s;
1542+struct cbus_priv_s {
1543+ struct cbus_s cbus;
1544+
1545+ int sel;
1546+ int dat;
1547+ int clk;
1548+ int bit;
1549+ int dir;
1550+ uint16_t val;
1551+ qemu_irq dat_out;
1552+
1553+ int addr;
1554+ int reg;
1555+ int rw;
1556+ enum {
1557+ cbus_address,
1558+ cbus_value,
1559+ } cycle;
1560+
1561+ struct cbus_slave_s *slave[8];
1562+};
1563+
1564+struct cbus_slave_s {
1565+ void *opaque;
1566+ void (*io)(void *opaque, int rw, int reg, uint16_t *val);
1567+ int addr;
1568+};
1569+
1570+static void cbus_io(struct cbus_priv_s *s)
1571+{
1572+ if (s->slave[s->addr])
1573+ s->slave[s->addr]->io(s->slave[s->addr]->opaque,
1574+ s->rw, s->reg, &s->val);
1575+ else
1576+ cpu_abort(cpu_single_env, "%s: bad slave address %i\n",
1577+ __FUNCTION__, s->addr);
1578+}
1579+
1580+static void cbus_cycle(struct cbus_priv_s *s)
1581+{
1582+ switch (s->cycle) {
1583+ case cbus_address:
1584+ s->addr = (s->val >> 6) & 7;
1585+ s->rw = (s->val >> 5) & 1;
1586+ s->reg = (s->val >> 0) & 0x1f;
1587+
1588+ s->cycle = cbus_value;
1589+ s->bit = 15;
1590+ s->dir = !s->rw;
1591+ s->val = 0;
1592+
1593+ if (s->rw)
1594+ cbus_io(s);
1595+ break;
1596+
1597+ case cbus_value:
1598+ if (!s->rw)
1599+ cbus_io(s);
1600+
1601+ s->cycle = cbus_address;
1602+ s->bit = 8;
1603+ s->dir = 1;
1604+ s->val = 0;
1605+ break;
1606+ }
1607+}
1608+
1609+static void cbus_clk(void *opaque, int line, int level)
1610+{
1611+ struct cbus_priv_s *s = (struct cbus_priv_s *) opaque;
1612+
1613+ if (!s->sel && level && !s->clk) {
1614+ if (s->dir)
1615+ s->val |= s->dat << (s->bit --);
1616+ else
1617+ qemu_set_irq(s->dat_out, (s->val >> (s->bit --)) & 1);
1618+
1619+ if (s->bit < 0)
1620+ cbus_cycle(s);
1621+ }
1622+
1623+ s->clk = level;
1624+}
1625+
1626+static void cbus_dat(void *opaque, int line, int level)
1627+{
1628+ struct cbus_priv_s *s = (struct cbus_priv_s *) opaque;
1629+
1630+ s->dat = level;
1631+}
1632+
1633+static void cbus_sel(void *opaque, int line, int level)
1634+{
1635+ struct cbus_priv_s *s = (struct cbus_priv_s *) opaque;
1636+
1637+ if (!level) {
1638+ s->dir = 1;
1639+ s->bit = 8;
1640+ s->val = 0;
1641+ }
1642+
1643+ s->sel = level;
1644+}
1645+
1646+struct cbus_s *cbus_init(qemu_irq dat)
1647+{
1648+ struct cbus_priv_s *s = (struct cbus_priv_s *) qemu_mallocz(sizeof(*s));
1649+
1650+ s->dat_out = dat;
1651+ s->cbus.clk = qemu_allocate_irqs(cbus_clk, s, 1)[0];
1652+ s->cbus.dat = qemu_allocate_irqs(cbus_dat, s, 1)[0];
1653+ s->cbus.sel = qemu_allocate_irqs(cbus_sel, s, 1)[0];
1654+
1655+ s->sel = 1;
1656+ s->clk = 0;
1657+ s->dat = 0;
1658+
1659+ return &s->cbus;
1660+}
1661+
1662+void cbus_attach(struct cbus_s *bus, void *slave_opaque)
1663+{
1664+ struct cbus_slave_s *slave = (struct cbus_slave_s *) slave_opaque;
1665+ struct cbus_priv_s *s = (struct cbus_priv_s *) bus;
1666+
1667+ s->slave[slave->addr] = slave;
1668+}
1669+
1670+/* Retu/Vilma */
1671+struct cbus_retu_s {
1672+ uint16_t irqst;
1673+ uint16_t irqen;
1674+ uint16_t cc[2];
1675+ int channel;
1676+ uint16_t result[16];
1677+ uint16_t sample;
1678+
1679+ struct {
1680+ uint16_t cal;
1681+ } rtc;
1682+
1683+ int is_vilma;
1684+ qemu_irq irq;
1685+ struct cbus_slave_s cbus;
1686+};
1687+
1688+static void retu_interrupt_update(struct cbus_retu_s *s)
1689+{
1690+ qemu_set_irq(s->irq, s->irqst & ~s->irqen);
1691+}
1692+
1693+#define RETU_REG_ASICR 0x00 /* (RO) ASIC ID & revision */
1694+#define RETU_REG_IDR 0x01 /* (T) Interrupt ID */
1695+#define RETU_REG_IMR 0x02 /* (RW) Interrupt mask */
1696+#define RETU_REG_RTCDSR 0x03 /* (RW) RTC seconds register */
1697+#define RETU_REG_RTCHMR 0x04 /* (RO) RTC hours and minutes reg */
1698+#define RETU_REG_RTCHMAR 0x05 /* (RW) RTC hours and minutes set reg */
1699+#define RETU_REG_RTCCALR 0x06 /* (RW) RTC calibration register */
1700+#define RETU_REG_ADCR 0x08 /* (RW) ADC result register */
1701+#define RETU_REG_ADCSCR 0x09 /* (RW) ADC sample control register */
1702+#define RETU_REG_AFCR 0x0a /* (RW) AFC register */
1703+#define RETU_REG_ANTIFR 0x0b /* (RW) AntiF register */
1704+#define RETU_REG_CALIBR 0x0c /* (RW) CalibR register*/
1705+#define RETU_REG_CCR1 0x0d /* (RW) Common control register 1 */
1706+#define RETU_REG_CCR2 0x0e /* (RW) Common control register 2 */
1707+#define RETU_REG_RCTRL_CLR 0x0f /* (T) Regulator clear register */
1708+#define RETU_REG_RCTRL_SET 0x10 /* (T) Regulator set register */
1709+#define RETU_REG_TXCR 0x11 /* (RW) TxC register */
1710+#define RETU_REG_STATUS 0x16 /* (RO) Status register */
1711+#define RETU_REG_WATCHDOG 0x17 /* (RW) Watchdog register */
1712+#define RETU_REG_AUDTXR 0x18 /* (RW) Audio Codec Tx register */
1713+#define RETU_REG_AUDPAR 0x19 /* (RW) AudioPA register */
1714+#define RETU_REG_AUDRXR1 0x1a /* (RW) Audio receive register 1 */
1715+#define RETU_REG_AUDRXR2 0x1b /* (RW) Autio receive register 2 */
1716+#define RETU_REG_SGR1 0x1c /* (RW) */
1717+#define RETU_REG_SCR1 0x1d /* (RW) */
1718+#define RETU_REG_SGR2 0x1e /* (RW) */
1719+#define RETU_REG_SCR2 0x1f /* (RW) */
1720+
1721+/* Retu Interrupt sources */
1722+enum {
1723+ retu_int_pwr = 0, /* Power */
1724+ retu_int_char = 1, /* Charger */
1725+ retu_int_rtcs = 2, /* Seconds */
1726+ retu_int_rtcm = 3, /* Minutes */
1727+ retu_int_rtcd = 4, /* Days */
1728+ retu_int_rtca = 5, /* Alarm */
1729+ retu_int_hook = 6, /* Hook */
1730+ retu_int_head = 7, /* Headset */
1731+ retu_int_adcs = 8, /* ADC sample */
1732+};
1733+
1734+/* Retu ADC channel wiring */
1735+enum {
1736+ retu_adc_bsi = 1, /* BSI */
1737+ retu_adc_batt_temp = 2, /* Battery temperature */
1738+ retu_adc_chg_volt = 3, /* Charger voltage */
1739+ retu_adc_head_det = 4, /* Headset detection */
1740+ retu_adc_hook_det = 5, /* Hook detection */
1741+ retu_adc_rf_gp = 6, /* RF GP */
1742+ retu_adc_tx_det = 7, /* Wideband Tx detection */
1743+ retu_adc_batt_volt = 8, /* Battery voltage */
1744+ retu_adc_sens = 10, /* Light sensor */
1745+ retu_adc_sens_temp = 11, /* Light sensor temperature */
1746+ retu_adc_bbatt_volt = 12, /* Backup battery voltage */
1747+ retu_adc_self_temp = 13, /* RETU temperature */
1748+};
1749+
1750+static inline uint16_t retu_read(struct cbus_retu_s *s, int reg)
1751+{
1752+#ifdef DEBUG
1753+ printf("RETU read at %02x\n", reg);
1754+#endif
1755+
1756+ switch (reg) {
1757+ case RETU_REG_ASICR:
1758+ return 0x0015 | (s->is_vilma << 7);
1759+
1760+ case RETU_REG_IDR:
1761+ return s->irqst;
1762+
1763+ case RETU_REG_IMR:
1764+ return s->irqen;
1765+
1766+ case RETU_REG_RTCDSR:
1767+ case RETU_REG_RTCHMR:
1768+ case RETU_REG_RTCHMAR:
1769+ /* TODO */
1770+ return 0x0000;
1771+
1772+ case RETU_REG_RTCCALR:
1773+ return s->rtc.cal;
1774+
1775+ case RETU_REG_ADCR:
1776+ return (s->channel << 10) | s->result[s->channel];
1777+ case RETU_REG_ADCSCR:
1778+ return s->sample;
1779+
1780+ case RETU_REG_AFCR:
1781+ case RETU_REG_ANTIFR:
1782+ case RETU_REG_CALIBR:
1783+ /* TODO */
1784+ return 0x0000;
1785+
1786+ case RETU_REG_CCR1:
1787+ return s->cc[0];
1788+ case RETU_REG_CCR2:
1789+ return s->cc[1];
1790+
1791+ case RETU_REG_RCTRL_CLR:
1792+ case RETU_REG_RCTRL_SET:
1793+ case RETU_REG_TXCR:
1794+ case RETU_REG_STATUS:
1795+ case RETU_REG_WATCHDOG:
1796+ case RETU_REG_AUDTXR:
1797+ case RETU_REG_AUDPAR:
1798+ case RETU_REG_AUDRXR1:
1799+ case RETU_REG_AUDRXR2:
1800+ case RETU_REG_SGR1:
1801+ case RETU_REG_SCR1:
1802+ case RETU_REG_SGR2:
1803+ case RETU_REG_SCR2:
1804+ /* TODO */
1805+ return 0x0000;
1806+
1807+ default:
1808+ cpu_abort(cpu_single_env, "%s: bad register %02x\n",
1809+ __FUNCTION__, reg);
1810+ }
1811+}
1812+
1813+static inline void retu_write(struct cbus_retu_s *s, int reg, uint16_t val)
1814+{
1815+#ifdef DEBUG
1816+ printf("RETU write of %04x at %02x\n", val, reg);
1817+#endif
1818+
1819+ switch (reg) {
1820+ case RETU_REG_IDR:
1821+ s->irqst ^= val;
1822+ retu_interrupt_update(s);
1823+ break;
1824+
1825+ case RETU_REG_IMR:
1826+ s->irqen = val;
1827+ retu_interrupt_update(s);
1828+ break;
1829+
1830+ case RETU_REG_RTCDSR:
1831+ case RETU_REG_RTCHMAR:
1832+ /* TODO */
1833+ break;
1834+
1835+ case RETU_REG_RTCCALR:
1836+ s->rtc.cal = val;
1837+ break;
1838+
1839+ case RETU_REG_ADCR:
1840+ s->channel = (val >> 10) & 0xf;
1841+ s->irqst |= 1 << retu_int_adcs;
1842+ retu_interrupt_update(s);
1843+ break;
1844+ case RETU_REG_ADCSCR:
1845+ s->sample &= ~val;
1846+ break;
1847+
1848+ case RETU_REG_AFCR:
1849+ case RETU_REG_ANTIFR:
1850+ case RETU_REG_CALIBR:
1851+
1852+ case RETU_REG_CCR1:
1853+ s->cc[0] = val;
1854+ break;
1855+ case RETU_REG_CCR2:
1856+ s->cc[1] = val;
1857+
1858+ break;
1859+ case RETU_REG_RCTRL_CLR:
1860+ case RETU_REG_RCTRL_SET:
1861+ case RETU_REG_STATUS:
1862+ /* TODO */
1863+ break;
1864+
1865+ case RETU_REG_WATCHDOG:
1866+ if (val == 0 && (s->cc[0] & 2))
1867+ qemu_system_shutdown_request();
1868+ break;
1869+
1870+ case RETU_REG_TXCR:
1871+ case RETU_REG_AUDTXR:
1872+ case RETU_REG_AUDPAR:
1873+ case RETU_REG_AUDRXR1:
1874+ case RETU_REG_AUDRXR2:
1875+ case RETU_REG_SGR1:
1876+ case RETU_REG_SCR1:
1877+ case RETU_REG_SGR2:
1878+ case RETU_REG_SCR2:
1879+ /* TODO */
1880+ break;
1881+
1882+ default:
1883+ cpu_abort(cpu_single_env, "%s: bad register %02x\n",
1884+ __FUNCTION__, reg);
1885+ }
1886+}
1887+
1888+static void retu_io(void *opaque, int rw, int reg, uint16_t *val)
1889+{
1890+ struct cbus_retu_s *s = (struct cbus_retu_s *) opaque;
1891+
1892+ if (rw)
1893+ *val = retu_read(s, reg);
1894+ else
1895+ retu_write(s, reg, *val);
1896+}
1897+
1898+void *retu_init(qemu_irq irq, int vilma)
1899+{
1900+ struct cbus_retu_s *s = (struct cbus_retu_s *) qemu_mallocz(sizeof(*s));
1901+
1902+ s->irq = irq;
1903+ s->irqen = 0xffff;
1904+ s->irqst = 0x0000;
1905+ s->is_vilma = !!vilma;
1906+ s->rtc.cal = 0x01;
1907+ s->result[retu_adc_bsi] = 0x100;
1908+ s->result[retu_adc_batt_temp] = 0x100;
1909+ s->result[retu_adc_chg_volt] = 0x200;
1910+ s->result[retu_adc_batt_volt] = 0x240;
1911+ s->result[retu_adc_sens] = 0x100;
1912+ s->result[retu_adc_sens_temp] = 0x100;
1913+ s->result[retu_adc_bbatt_volt] = 0x200;
1914+ s->result[retu_adc_self_temp] = 0x100;
1915+
1916+ s->cbus.opaque = s;
1917+ s->cbus.io = retu_io;
1918+ s->cbus.addr = 1;
1919+
1920+ return &s->cbus;
1921+}
1922+
1923+/* Tahvo/Betty */
1924+struct cbus_tahvo_s {
1925+ uint16_t irqst;
1926+ uint16_t irqen;
1927+ uint8_t charger;
1928+ uint8_t backlight;
1929+ uint16_t usbr;
1930+ uint16_t power;
1931+
1932+ int is_betty;
1933+ qemu_irq irq;
1934+ struct cbus_slave_s cbus;
1935+};
1936+
1937+static void tahvo_interrupt_update(struct cbus_tahvo_s *s)
1938+{
1939+ qemu_set_irq(s->irq, s->irqst & ~s->irqen);
1940+}
1941+
1942+#define TAHVO_REG_ASICR 0x00 /* (RO) ASIC ID & revision */
1943+#define TAHVO_REG_IDR 0x01 /* (T) Interrupt ID */
1944+#define TAHVO_REG_IDSR 0x02 /* (RO) Interrupt status */
1945+#define TAHVO_REG_IMR 0x03 /* (RW) Interrupt mask */
1946+#define TAHVO_REG_CHAPWMR 0x04 /* (RW) Charger PWM */
1947+#define TAHVO_REG_LEDPWMR 0x05 /* (RW) LED PWM */
1948+#define TAHVO_REG_USBR 0x06 /* (RW) USB control */
1949+#define TAHVO_REG_RCR 0x07 /* (RW) Some kind of power management */
1950+#define TAHVO_REG_CCR1 0x08 /* (RW) Common control register 1 */
1951+#define TAHVO_REG_CCR2 0x09 /* (RW) Common control register 2 */
1952+#define TAHVO_REG_TESTR1 0x0a /* (RW) Test register 1 */
1953+#define TAHVO_REG_TESTR2 0x0b /* (RW) Test register 2 */
1954+#define TAHVO_REG_NOPR 0x0c /* (RW) Number of periods */
1955+#define TAHVO_REG_FRR 0x0d /* (RO) FR */
1956+
1957+static inline uint16_t tahvo_read(struct cbus_tahvo_s *s, int reg)
1958+{
1959+#ifdef DEBUG
1960+ printf("TAHVO read at %02x\n", reg);
1961+#endif
1962+
1963+ switch (reg) {
1964+ case TAHVO_REG_ASICR:
1965+ return 0x0021 | (s->is_betty ? 0x0b00 : 0x0300);
1966+
1967+ case TAHVO_REG_IDR:
1968+ case TAHVO_REG_IDSR: /* XXX: what does this do? */
1969+ return s->irqst;
1970+
1971+ case TAHVO_REG_IMR:
1972+ return s->irqen;
1973+
1974+ case TAHVO_REG_CHAPWMR:
1975+ return s->charger;
1976+
1977+ case TAHVO_REG_LEDPWMR:
1978+ return s->backlight;
1979+
1980+ case TAHVO_REG_USBR:
1981+ return s->usbr;
1982+
1983+ case TAHVO_REG_RCR:
1984+ return s->power;
1985+
1986+ case TAHVO_REG_CCR1:
1987+ case TAHVO_REG_CCR2:
1988+ case TAHVO_REG_TESTR1:
1989+ case TAHVO_REG_TESTR2:
1990+ case TAHVO_REG_NOPR:
1991+ case TAHVO_REG_FRR:
1992+ return 0x0000;
1993+
1994+ default:
1995+ cpu_abort(cpu_single_env, "%s: bad register %02x\n",
1996+ __FUNCTION__, reg);
1997+ }
1998+}
1999+
2000+static inline void tahvo_write(struct cbus_tahvo_s *s, int reg, uint16_t val)
2001+{
2002+#ifdef DEBUG
2003+ printf("TAHVO write of %04x at %02x\n", val, reg);
2004+#endif
2005+
2006+ switch (reg) {
2007+ case TAHVO_REG_IDR:
2008+ s->irqst ^= val;
2009+ tahvo_interrupt_update(s);
2010+ break;
2011+
2012+ case TAHVO_REG_IMR:
2013+ s->irqen = val;
2014+ tahvo_interrupt_update(s);
2015+ break;
2016+
2017+ case TAHVO_REG_CHAPWMR:
2018+ s->charger = val;
2019+ break;
2020+
2021+ case TAHVO_REG_LEDPWMR:
2022+ if (s->backlight != (val & 0x7f)) {
2023+ s->backlight = val & 0x7f;
2024+ printf("%s: LCD backlight now at %i / 127\n",
2025+ __FUNCTION__, s->backlight);
2026+ }
2027+ break;
2028+
2029+ case TAHVO_REG_USBR:
2030+ s->usbr = val;
2031+ break;
2032+
2033+ case TAHVO_REG_RCR:
2034+ s->power = val;
2035+ break;
2036+
2037+ case TAHVO_REG_CCR1:
2038+ case TAHVO_REG_CCR2:
2039+ case TAHVO_REG_TESTR1:
2040+ case TAHVO_REG_TESTR2:
2041+ case TAHVO_REG_NOPR:
2042+ case TAHVO_REG_FRR:
2043+ break;
2044+
2045+ default:
2046+ cpu_abort(cpu_single_env, "%s: bad register %02x\n",
2047+ __FUNCTION__, reg);
2048+ }
2049+}
2050+
2051+static void tahvo_io(void *opaque, int rw, int reg, uint16_t *val)
2052+{
2053+ struct cbus_tahvo_s *s = (struct cbus_tahvo_s *) opaque;
2054+
2055+ if (rw)
2056+ *val = tahvo_read(s, reg);
2057+ else
2058+ tahvo_write(s, reg, *val);
2059+}
2060+
2061+void *tahvo_init(qemu_irq irq, int betty)
2062+{
2063+ struct cbus_tahvo_s *s = (struct cbus_tahvo_s *) qemu_mallocz(sizeof(*s));
2064+
2065+ s->irq = irq;
2066+ s->irqen = 0xffff;
2067+ s->irqst = 0x0000;
2068+ s->is_betty = !!betty;
2069+
2070+ s->cbus.opaque = s;
2071+ s->cbus.io = tahvo_io;
2072+ s->cbus.addr = 2;
2073+
2074+ return &s->cbus;
2075+}
2076diff --git a/hw/devices.h b/hw/devices.h
2077index 07c673b..6f1d27b 100644
2078--- a/hw/devices.h
2079+++ b/hw/devices.h
2080@@ -16,7 +16,38 @@ uint32_t ads7846_read(void *opaque);
2081 void ads7846_write(void *opaque, uint32_t value);
2082 struct ads7846_state_s *ads7846_init(qemu_irq penirq);
2083
2084+/* tsc210x.c */
2085+struct uwire_slave_s;
2086+struct mouse_transform_info_s;
2087+struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio);
2088+struct uwire_slave_s *tsc2301_init(qemu_irq penirq, qemu_irq kbirq,
2089+ qemu_irq dav, AudioState *audio);
2090+struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip);
2091+uint32_t tsc210x_txrx(void *opaque, uint32_t value);
2092+void tsc210x_set_transform(struct uwire_slave_s *chip,
2093+ struct mouse_transform_info_s *info);
2094+void tsc210x_key_event(struct uwire_slave_s *chip, int key, int down);
2095+
2096 /* stellaris_input.c */
2097 void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
2098
2099+/* blizzard.c */
2100+void *s1d13745_init(qemu_irq gpio_int, DisplayState *ds);
2101+void s1d13745_write(void *opaque, int dc, uint16_t value);
2102+void s1d13745_write_block(void *opaque, int dc,
2103+ void *buf, size_t len, int pitch);
2104+uint16_t s1d13745_read(void *opaque, int dc);
2105+
2106+/* cbus.c */
2107+struct cbus_s {
2108+ qemu_irq clk;
2109+ qemu_irq dat;
2110+ qemu_irq sel;
2111+};
2112+struct cbus_s *cbus_init(qemu_irq dat_out);
2113+void cbus_attach(struct cbus_s *bus, void *slave_opaque);
2114+
2115+void *retu_init(qemu_irq irq, int vilma);
2116+void *tahvo_init(qemu_irq irq, int betty);
2117+
2118 #endif
2119diff --git a/hw/flash.h b/hw/flash.h
2120index 42d25fe..c000d33 100644
2121--- a/hw/flash.h
2122+++ b/hw/flash.h
2123@@ -34,6 +34,11 @@ uint8_t nand_getio(struct nand_flash_s *s);
2124 #define NAND_MFR_HYNIX 0xad
2125 #define NAND_MFR_MICRON 0x2c
2126
2127+/* onenand.c */
2128+void onenand_base_update(void *opaque, target_phys_addr_t new);
2129+void onenand_base_unmap(void *opaque);
2130+void *onenand_init(uint32_t id, int regshift, qemu_irq irq);
2131+
2132 /* ecc.c */
2133 struct ecc_state_s {
2134 uint8_t cp; /* Column parity */
2135diff --git a/hw/i2c.h b/hw/i2c.h
2136index 2897036..fae46b7 100644
2137--- a/hw/i2c.h
2138+++ b/hw/i2c.h
2139@@ -71,4 +71,14 @@ uint32_t wm8750_adc_dat(void *opaque);
2140 /* ssd0303.c */
2141 void ssd0303_init(DisplayState *ds, i2c_bus *bus, int address);
2142
2143+/* twl92230.c */
2144+i2c_slave *twl92230_init(i2c_bus *bus, qemu_irq irq);
2145+qemu_irq *twl92230_gpio_in_get(i2c_slave *i2c);
2146+void twl92230_gpio_out_set(i2c_slave *i2c, int line, qemu_irq handler);
2147+
2148+/* tmp105.c */
2149+struct i2c_slave *tmp105_init(i2c_bus *bus, qemu_irq alarm);
2150+void tmp105_reset(i2c_slave *i2c);
2151+void tmp105_set(i2c_slave *i2c, int temp);
2152+
2153 #endif
2154diff --git a/hw/integratorcp.c b/hw/integratorcp.c
2155index 549cc25..f6e6364 100644
2156--- a/hw/integratorcp.c
2157+++ b/hw/integratorcp.c
2158@@ -469,6 +469,11 @@ static void icp_control_init(uint32_t base)
2159
2160 /* Board init. */
2161
2162+static struct arm_boot_info integrator_binfo = {
2163+ .loader_start = 0x0,
2164+ .board_id = 0x113,
2165+};
2166+
2167 static void integratorcp_init(int ram_size, int vga_ram_size,
2168 const char *boot_device, DisplayState *ds,
2169 const char *kernel_filename, const char *kernel_cmdline,
2170@@ -527,8 +532,11 @@ static void integratorcp_init(int ram_size, int vga_ram_size,
2171 }
2172 pl110_init(ds, 0xc0000000, pic[22], 0);
2173
2174- arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline,
2175- initrd_filename, 0x113, 0x0);
2176+ integrator_binfo.ram_size = ram_size;
2177+ integrator_binfo.kernel_filename = kernel_filename;
2178+ integrator_binfo.kernel_cmdline = kernel_cmdline;
2179+ integrator_binfo.initrd_filename = initrd_filename;
2180+ arm_load_kernel(env, &integrator_binfo);
2181 }
2182
2183 QEMUMachine integratorcp_machine = {
2184diff --git a/hw/mainstone.c b/hw/mainstone.c
2185index 5856791..9564fc3 100644
2186--- a/hw/mainstone.c
2187+++ b/hw/mainstone.c
2188@@ -59,12 +59,17 @@ static struct keymap map[0xE0] = {
2189
2190 enum mainstone_model_e { mainstone };
2191
2192+static struct arm_boot_info mainstone_binfo = {
2193+ .loader_start = PXA2XX_SDRAM_BASE,
2194+ .ram_size = 0x04000000,
2195+};
2196+
2197 static void mainstone_common_init(int ram_size, int vga_ram_size,
2198 DisplayState *ds, const char *kernel_filename,
2199 const char *kernel_cmdline, const char *initrd_filename,
2200 const char *cpu_model, enum mainstone_model_e model, int arm_id)
2201 {
2202- uint32_t mainstone_ram = 0x04000000;
2203+ uint32_t mainstone_ram = mainstone_binfo.ram_size;
2204 uint32_t mainstone_rom = 0x00800000;
2205 uint32_t mainstone_flash = 0x02000000;
2206 uint32_t sector_len = 256 * 1024;
2207@@ -90,7 +95,7 @@ static void mainstone_common_init(int ram_size, int vga_ram_size,
2208 qemu_ram_alloc(mainstone_rom) | IO_MEM_ROM);
2209
2210 /* Setup initial (reset) machine state */
2211- cpu->env->regs[15] = PXA2XX_SDRAM_BASE;
2212+ cpu->env->regs[15] = mainstone_binfo.loader_start;
2213
2214 /* There are two 32MiB flash devices on the board */
2215 for (i = 0; i < 2; i ++) {
2216@@ -121,8 +126,11 @@ static void mainstone_common_init(int ram_size, int vga_ram_size,
2217
2218 smc91c111_init(&nd_table[0], MST_ETH_PHYS, mst_irq[ETHERNET_IRQ]);
2219
2220- arm_load_kernel(cpu->env, mainstone_ram, kernel_filename, kernel_cmdline,
2221- initrd_filename, arm_id, PXA2XX_SDRAM_BASE);
2222+ mainstone_binfo.kernel_filename = kernel_filename;
2223+ mainstone_binfo.kernel_cmdline = kernel_cmdline;
2224+ mainstone_binfo.initrd_filename = initrd_filename;
2225+ mainstone_binfo.board_id = arm_id;
2226+ arm_load_kernel(cpu->env, &mainstone_binfo);
2227 }
2228
2229 static void mainstone_init(int ram_size, int vga_ram_size,
2230diff --git a/hw/max7310.c b/hw/max7310.c
2231index 75e56c7..397950a 100644
2232--- a/hw/max7310.c
2233+++ b/hw/max7310.c
2234@@ -134,8 +134,8 @@ static void max7310_event(i2c_slave *i2c, enum i2c_event event)
2235 s->i2c_command_byte = 1;
2236 break;
2237 case I2C_FINISH:
2238- if (s->len == 1)
2239 #ifdef VERBOSE
2240+ if (s->len == 1)
2241 printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len);
2242 #endif
2243 break;
2244diff --git a/hw/nseries.c b/hw/nseries.c
2245new file mode 100644
2246index 0000000..0425d46
2247--- /dev/null
2248+++ b/hw/nseries.c
2249@@ -0,0 +1,870 @@
2250+/*
2251+ * Nokia N-series internet tablets.
2252+ *
2253+ * Copyright (C) 2007 Nokia Corporation
2254+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
2255+ *
2256+ * This program is free software; you can redistribute it and/or
2257+ * modify it under the terms of the GNU General Public License as
2258+ * published by the Free Software Foundation; either version 2 of
2259+ * the License, or (at your option) any later version.
2260+ *
2261+ * This program is distributed in the hope that it will be useful,
2262+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2263+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2264+ * GNU General Public License for more details.
2265+ *
2266+ * You should have received a copy of the GNU General Public License
2267+ * along with this program; if not, write to the Free Software
2268+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
2269+ * MA 02111-1307 USA
2270+ */
2271+
2272+#include "qemu-common.h"
2273+#include "sysemu.h"
2274+#include "omap.h"
2275+#include "arm-misc.h"
2276+#include "irq.h"
2277+#include "console.h"
2278+#include "boards.h"
2279+#include "i2c.h"
2280+#include "devices.h"
2281+#include "flash.h"
2282+#include "hw.h"
2283+
2284+/* Nokia N800 support */
2285+struct n800_s {
2286+ struct omap_mpu_state_s *cpu;
2287+
2288+ struct rfbi_chip_s blizzard;
2289+ struct uwire_slave_s *ts;
2290+ i2c_bus *i2c;
2291+
2292+ int keymap[0x80];
2293+};
2294+
2295+#define N800_MMC2_WP_GPIO 8
2296+#define N800_CAM_TURN_GPIO 12
2297+#define N800_BLIZZARD_POWERDOWN_GPIO 15
2298+#define N800_MMC1_WP_GPIO 23
2299+#define N800_ONENAND_GPIO 26
2300+#define N800_BT_WKUP_GPIO 61
2301+#define N800_STI_GPIO 62
2302+#define N800_CBUS_SEL_GPIO 64
2303+#define N800_CBUS_CLK_GPIO 65
2304+#define N800_CBUS_DAT_GPIO 66
2305+#define N800_WLAN_IRQ_GPIO 87
2306+#define N800_BT_RESET_GPIO 92
2307+#define N800_TEA5761_CS_GPIO 93
2308+#define N800_UNKNOWN_GPIO 94
2309+#define N800_CAM_ACT_GPIO 95
2310+#define N800_MMC_CS_GPIO 96
2311+#define N800_WLAN_PWR_GPIO 97
2312+#define N800_BT_HOST_WKUP_GPIO 98
2313+#define N800_TSC_TS_GPIO 103
2314+#define N800_HEADPHONE_GPIO 107
2315+#define N800_RETU_GPIO 108
2316+#define N800_TSC_KP_IRQ_GPIO 109
2317+#define N800_BAT_COVER_GPIO 110
2318+#define N800_TAHVO_GPIO 111
2319+#define N800_TSC_RESET_GPIO 119
2320+#define N800_TMP105_GPIO 125
2321+
2322+#define XLDR_LL_UART 1
2323+
2324+#define N800_TMP105_ADDR 0x48
2325+#define N800_MENELAUS_ADDR 0x72
2326+
2327+static void n800_mmc_cs_cb(void *opaque, int line, int level)
2328+{
2329+ /* TODO: this seems to actually be connected to the menelaus, to
2330+ * which also both MMC slots connect. */
2331+ omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
2332+
2333+ printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);
2334+}
2335+
2336+static void n800_gpio_setup(struct n800_s *s)
2337+{
2338+ qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->cpu->mmc, 1);
2339+ omap2_gpio_out_set(s->cpu->gpif, N800_MMC_CS_GPIO, mmc_cs[0]);
2340+
2341+ qemu_irq_lower(omap2_gpio_in_get(s->cpu->gpif, N800_BAT_COVER_GPIO)[0]);
2342+}
2343+
2344+static void n800_nand_setup(struct n800_s *s)
2345+{
2346+ /* Either ec40xx or ec48xx are OK for the ID */
2347+ omap_gpmc_attach(s->cpu->gpmc, 0, 0, onenand_base_update,
2348+ onenand_base_unmap,
2349+ onenand_init(0xec4800, 1,
2350+ omap2_gpio_in_get(s->cpu->gpif,
2351+ N800_ONENAND_GPIO)[0]));
2352+}
2353+
2354+static void n800_i2c_setup(struct n800_s *s)
2355+{
2356+ qemu_irq tmp_irq = omap2_gpio_in_get(s->cpu->gpif, N800_TMP105_GPIO)[0];
2357+
2358+ /* Attach the CPU on one end of our I2C bus. */
2359+ s->i2c = omap_i2c_bus(s->cpu->i2c[0]);
2360+
2361+ /* Attach a menelaus PM chip */
2362+ i2c_set_slave_address(
2363+ twl92230_init(s->i2c,
2364+ s->cpu->irq[0][OMAP_INT_24XX_SYS_NIRQ]),
2365+ N800_MENELAUS_ADDR);
2366+
2367+ /* Attach a TMP105 PM chip (A0 wired to ground) */
2368+ i2c_set_slave_address(tmp105_init(s->i2c, tmp_irq), N800_TMP105_ADDR);
2369+}
2370+
2371+/* Touchscreen and keypad controller */
2372+static void n800_key_event(void *opaque, int keycode)
2373+{
2374+ struct n800_s *s = (struct n800_s *) opaque;
2375+ int code = s->keymap[keycode & 0x7f];
2376+
2377+ if (code == -1)
2378+ return;
2379+
2380+ tsc210x_key_event(s->ts, code, !(keycode & 0x80));
2381+}
2382+
2383+static const int n800_keys[16] = {
2384+ -1,
2385+ 72, /* Up */
2386+ 63, /* Home (F5) */
2387+ -1,
2388+ 75, /* Left */
2389+ 28, /* Enter */
2390+ 77, /* Right */
2391+ -1,
2392+ 1, /* Cycle (ESC) */
2393+ 80, /* Down */
2394+ 62, /* Menu (F4) */
2395+ -1,
2396+ 66, /* Zoom- (F8) */
2397+ 64, /* FS (F6) */
2398+ 65, /* Zoom+ (F7) */
2399+ -1,
2400+};
2401+
2402+static struct mouse_transform_info_s n800_pointercal = {
2403+ .x = 800,
2404+ .y = 480,
2405+ .a = { 14560, -68, -3455208, -39, -9621, 35152972, 65536 },
2406+};
2407+
2408+static void n800_tsc_setup(struct n800_s *s)
2409+{
2410+ int i;
2411+
2412+ /* XXX: are the three pins inverted inside the chip between the
2413+ * tsc and the cpu (N4111)? */
2414+ qemu_irq penirq = 0; /* NC */
2415+ qemu_irq kbirq = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_KP_IRQ_GPIO)[0];
2416+ qemu_irq dav = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_TS_GPIO)[0];
2417+
2418+ s->ts = tsc2301_init(penirq, kbirq, dav, 0);
2419+
2420+ for (i = 0; i < 0x80; i ++)
2421+ s->keymap[i] = -1;
2422+ for (i = 0; i < 0x10; i ++)
2423+ if (n800_keys[i] >= 0)
2424+ s->keymap[n800_keys[i]] = i;
2425+
2426+ qemu_add_kbd_event_handler(n800_key_event, s);
2427+
2428+ tsc210x_set_transform(s->ts, &n800_pointercal);
2429+}
2430+
2431+/* LCD MIPI DBI-C controller (URAL) */
2432+struct mipid_s {
2433+ int resp[4];
2434+ int param[4];
2435+ int p;
2436+ int pm;
2437+ int cmd;
2438+
2439+ int sleep;
2440+ int booster;
2441+ int te;
2442+ int selfcheck;
2443+ int partial;
2444+ int normal;
2445+ int vscr;
2446+ int invert;
2447+ int onoff;
2448+ int gamma;
2449+ uint32_t id;
2450+};
2451+
2452+static void mipid_reset(struct mipid_s *s)
2453+{
2454+ if (!s->sleep)
2455+ fprintf(stderr, "%s: Display off\n", __FUNCTION__);
2456+
2457+ s->pm = 0;
2458+ s->cmd = 0;
2459+
2460+ s->sleep = 1;
2461+ s->booster = 0;
2462+ s->selfcheck =
2463+ (1 << 7) | /* Register loading OK. */
2464+ (1 << 5) | /* The chip is attached. */
2465+ (1 << 4); /* Display glass still in one piece. */
2466+ s->te = 0;
2467+ s->partial = 0;
2468+ s->normal = 1;
2469+ s->vscr = 0;
2470+ s->invert = 0;
2471+ s->onoff = 1;
2472+ s->gamma = 0;
2473+}
2474+
2475+static uint32_t mipid_txrx(void *opaque, uint32_t cmd)
2476+{
2477+ struct mipid_s *s = (struct mipid_s *) opaque;
2478+ uint8_t ret;
2479+
2480+ if (s->p >= sizeof(s->resp) / sizeof(*s->resp))
2481+ ret = 0;
2482+ else
2483+ ret = s->resp[s->p ++];
2484+ if (s->pm --> 0)
2485+ s->param[s->pm] = cmd;
2486+ else
2487+ s->cmd = cmd;
2488+
2489+ switch (s->cmd) {
2490+ case 0x00: /* NOP */
2491+ break;
2492+
2493+ case 0x01: /* SWRESET */
2494+ mipid_reset(s);
2495+ break;
2496+
2497+ case 0x02: /* BSTROFF */
2498+ s->booster = 0;
2499+ break;
2500+ case 0x03: /* BSTRON */
2501+ s->booster = 1;
2502+ break;
2503+
2504+ case 0x04: /* RDDID */
2505+ s->p = 0;
2506+ s->resp[0] = (s->id >> 16) & 0xff;
2507+ s->resp[1] = (s->id >> 8) & 0xff;
2508+ s->resp[2] = (s->id >> 0) & 0xff;
2509+ break;
2510+
2511+ case 0x06: /* RD_RED */
2512+ case 0x07: /* RD_GREEN */
2513+ /* XXX the bootloader sometimes issues RD_BLUE meaning RDDID so
2514+ * for the bootloader one needs to change this. */
2515+ case 0x08: /* RD_BLUE */
2516+ s->p = 0;
2517+ /* TODO: return first pixel components */
2518+ s->resp[0] = 0x01;
2519+ break;
2520+
2521+ case 0x09: /* RDDST */
2522+ s->p = 0;
2523+ s->resp[0] = s->booster << 7;
2524+ s->resp[1] = (5 << 4) | (s->partial << 2) |
2525+ (s->sleep << 1) | s->normal;
2526+ s->resp[2] = (s->vscr << 7) | (s->invert << 5) |
2527+ (s->onoff << 2) | (s->te << 1) | (s->gamma >> 2);
2528+ s->resp[3] = s->gamma << 6;
2529+ break;
2530+
2531+ case 0x0a: /* RDDPM */
2532+ s->p = 0;
2533+ s->resp[0] = (s->onoff << 2) | (s->normal << 3) | (s->sleep << 4) |
2534+ (s->partial << 5) | (s->sleep << 6) | (s->booster << 7);
2535+ break;
2536+ case 0x0b: /* RDDMADCTR */
2537+ s->p = 0;
2538+ s->resp[0] = 0;
2539+ break;
2540+ case 0x0c: /* RDDCOLMOD */
2541+ s->p = 0;
2542+ s->resp[0] = 5; /* 65K colours */
2543+ break;
2544+ case 0x0d: /* RDDIM */
2545+ s->p = 0;
2546+ s->resp[0] = (s->invert << 5) | (s->vscr << 7) | s->gamma;
2547+ break;
2548+ case 0x0e: /* RDDSM */
2549+ s->p = 0;
2550+ s->resp[0] = s->te << 7;
2551+ break;
2552+ case 0x0f: /* RDDSDR */
2553+ s->p = 0;
2554+ s->resp[0] = s->selfcheck;
2555+ break;
2556+
2557+ case 0x10: /* SLPIN */
2558+ s->sleep = 1;
2559+ break;
2560+ case 0x11: /* SLPOUT */
2561+ s->sleep = 0;
2562+ s->selfcheck ^= 1 << 6; /* POFF self-diagnosis Ok */
2563+ break;
2564+
2565+ case 0x12: /* PTLON */
2566+ s->partial = 1;
2567+ s->normal = 0;
2568+ s->vscr = 0;
2569+ break;
2570+ case 0x13: /* NORON */
2571+ s->partial = 0;
2572+ s->normal = 1;
2573+ s->vscr = 0;
2574+ break;
2575+
2576+ case 0x20: /* INVOFF */
2577+ s->invert = 0;
2578+ break;
2579+ case 0x21: /* INVON */
2580+ s->invert = 1;
2581+ break;
2582+
2583+ case 0x22: /* APOFF */
2584+ case 0x23: /* APON */
2585+ goto bad_cmd;
2586+
2587+ case 0x25: /* WRCNTR */
2588+ if (s->pm < 0)
2589+ s->pm = 1;
2590+ goto bad_cmd;
2591+
2592+ case 0x26: /* GAMSET */
2593+ if (!s->pm)
2594+ s->gamma = ffs(s->param[0] & 0xf) - 1;
2595+ else if (s->pm < 0)
2596+ s->pm = 1;
2597+ break;
2598+
2599+ case 0x28: /* DISPOFF */
2600+ s->onoff = 0;
2601+ fprintf(stderr, "%s: Display off\n", __FUNCTION__);
2602+ break;
2603+ case 0x29: /* DISPON */
2604+ s->onoff = 1;
2605+ fprintf(stderr, "%s: Display on\n", __FUNCTION__);
2606+ break;
2607+
2608+ case 0x2a: /* CASET */
2609+ case 0x2b: /* RASET */
2610+ case 0x2c: /* RAMWR */
2611+ case 0x2d: /* RGBSET */
2612+ case 0x2e: /* RAMRD */
2613+ case 0x30: /* PTLAR */
2614+ case 0x33: /* SCRLAR */
2615+ goto bad_cmd;
2616+
2617+ case 0x34: /* TEOFF */
2618+ s->te = 0;
2619+ break;
2620+ case 0x35: /* TEON */
2621+ if (!s->pm)
2622+ s->te = 1;
2623+ else if (s->pm < 0)
2624+ s->pm = 1;
2625+ break;
2626+
2627+ case 0x36: /* MADCTR */
2628+ goto bad_cmd;
2629+
2630+ case 0x37: /* VSCSAD */
2631+ s->partial = 0;
2632+ s->normal = 0;
2633+ s->vscr = 1;
2634+ break;
2635+
2636+ case 0x38: /* IDMOFF */
2637+ case 0x39: /* IDMON */
2638+ case 0x3a: /* COLMOD */
2639+ goto bad_cmd;
2640+
2641+ case 0xb0: /* CLKINT / DISCTL */
2642+ case 0xb1: /* CLKEXT */
2643+ if (s->pm < 0)
2644+ s->pm = 2;
2645+ break;
2646+
2647+ case 0xb4: /* FRMSEL */
2648+ break;
2649+
2650+ case 0xb5: /* FRM8SEL */
2651+ case 0xb6: /* TMPRNG / INIESC */
2652+ case 0xb7: /* TMPHIS / NOP2 */
2653+ case 0xb8: /* TMPREAD / MADCTL */
2654+ case 0xba: /* DISTCTR */
2655+ case 0xbb: /* EPVOL */
2656+ goto bad_cmd;
2657+
2658+ case 0xbd: /* Unknown */
2659+ s->p = 0;
2660+ s->resp[0] = 0;
2661+ s->resp[1] = 1;
2662+ break;
2663+
2664+ case 0xc2: /* IFMOD */
2665+ if (s->pm < 0)
2666+ s->pm = 2;
2667+ break;
2668+
2669+ case 0xc6: /* PWRCTL */
2670+ case 0xc7: /* PPWRCTL */
2671+ case 0xd0: /* EPWROUT */
2672+ case 0xd1: /* EPWRIN */
2673+ case 0xd4: /* RDEV */
2674+ case 0xd5: /* RDRR */
2675+ goto bad_cmd;
2676+
2677+ case 0xda: /* RDID1 */
2678+ s->p = 0;
2679+ s->resp[0] = (s->id >> 16) & 0xff;
2680+ break;
2681+ case 0xdb: /* RDID2 */
2682+ s->p = 0;
2683+ s->resp[0] = (s->id >> 8) & 0xff;
2684+ break;
2685+ case 0xdc: /* RDID3 */
2686+ s->p = 0;
2687+ s->resp[0] = (s->id >> 0) & 0xff;
2688+ break;
2689+
2690+ default:
2691+ bad_cmd:
2692+ fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, s->cmd);
2693+ break;
2694+ }
2695+
2696+ return ret;
2697+}
2698+
2699+static void *mipid_init(void)
2700+{
2701+ struct mipid_s *s = (struct mipid_s *) qemu_mallocz(sizeof(*s));
2702+
2703+ s->id = 0x838f03;
2704+ mipid_reset(s);
2705+
2706+ return s;
2707+}
2708+
2709+static void n800_spi_setup(struct n800_s *s)
2710+{
2711+ void *tsc2301 = s->ts->opaque;
2712+ void *mipid = mipid_init();
2713+
2714+ omap_mcspi_attach(s->cpu->mcspi[0], tsc210x_txrx, tsc2301, 0);
2715+ omap_mcspi_attach(s->cpu->mcspi[0], mipid_txrx, mipid, 1);
2716+}
2717+
2718+/* This task is normally performed by the bootloader. If we're loading
2719+ * a kernel directly, we need to enable the Blizzard ourselves. */
2720+static void n800_dss_init(struct rfbi_chip_s *chip)
2721+{
2722+ chip->write(chip->opaque, 0, 0x2a); /* LCD Width register */
2723+ chip->write(chip->opaque, 1, 0x64);
2724+ chip->write(chip->opaque, 0, 0x2c); /* LCD HNDP register */
2725+ chip->write(chip->opaque, 1, 0x1e);
2726+ chip->write(chip->opaque, 0, 0x2e); /* LCD Height 0 register */
2727+ chip->write(chip->opaque, 1, 0xe0);
2728+ chip->write(chip->opaque, 0, 0x30); /* LCD Height 1 register */
2729+ chip->write(chip->opaque, 1, 0x01);
2730+ chip->write(chip->opaque, 0, 0x32); /* LCD VNDP register */
2731+ chip->write(chip->opaque, 1, 0x06);
2732+ chip->write(chip->opaque, 0, 0x68); /* Display Mode register */
2733+ chip->write(chip->opaque, 1, 1); /* Enable bit */
2734+}
2735+
2736+static void n800_dss_setup(struct n800_s *s, DisplayState *ds)
2737+{
2738+ s->blizzard.opaque = s1d13745_init(0, ds);
2739+ s->blizzard.block = s1d13745_write_block;
2740+ s->blizzard.write = s1d13745_write;
2741+ s->blizzard.read = s1d13745_read;
2742+
2743+ omap_rfbi_attach(s->cpu->dss, 0, &s->blizzard);
2744+}
2745+
2746+static void n800_cbus_setup(struct n800_s *s)
2747+{
2748+ qemu_irq dat_out = omap2_gpio_in_get(s->cpu->gpif, N800_CBUS_DAT_GPIO)[0];
2749+ qemu_irq retu_irq = omap2_gpio_in_get(s->cpu->gpif, N800_RETU_GPIO)[0];
2750+ qemu_irq tahvo_irq = omap2_gpio_in_get(s->cpu->gpif, N800_TAHVO_GPIO)[0];
2751+
2752+ struct cbus_s *cbus = cbus_init(dat_out);
2753+
2754+ omap2_gpio_out_set(s->cpu->gpif, N800_CBUS_CLK_GPIO, cbus->clk);
2755+ omap2_gpio_out_set(s->cpu->gpif, N800_CBUS_DAT_GPIO, cbus->dat);
2756+ omap2_gpio_out_set(s->cpu->gpif, N800_CBUS_SEL_GPIO, cbus->sel);
2757+
2758+ cbus_attach(cbus, retu_init(retu_irq, 1));
2759+ cbus_attach(cbus, tahvo_init(tahvo_irq, 1));
2760+}
2761+
2762+/* This task is normally performed by the bootloader. If we're loading
2763+ * a kernel directly, we need to set up GPMC mappings ourselves. */
2764+static void n800_gpmc_init(struct n800_s *s)
2765+{
2766+ uint32_t config7 =
2767+ (0xf << 8) | /* MASKADDRESS */
2768+ (1 << 6) | /* CSVALID */
2769+ (4 << 0); /* BASEADDRESS */
2770+
2771+ cpu_physical_memory_write(0x6800a078, /* GPMC_CONFIG7_0 */
2772+ (void *) &config7, sizeof(config7));
2773+}
2774+
2775+#if 0
2776+static uint32_t n800_pinout[104] = {
2777+ 0x080f00d8, 0x00d40808, 0x03080808, 0x080800d0,
2778+ 0x00dc0808, 0x0b0f0f00, 0x080800b4, 0x00c00808,
2779+ 0x08080808, 0x180800c4, 0x00b80000, 0x08080808,
2780+ 0x080800bc, 0x00cc0808, 0x08081818, 0x18180128,
2781+ 0x01241800, 0x18181818, 0x000000f0, 0x01300000,
2782+ 0x00001b0b, 0x1b0f0138, 0x00e0181b, 0x1b031b0b,
2783+ 0x180f0078, 0x00740018, 0x0f0f0f1a, 0x00000080,
2784+ 0x007c0000, 0x00000000, 0x00000088, 0x00840000,
2785+ 0x00000000, 0x00000094, 0x00980300, 0x0f180003,
2786+ 0x0000008c, 0x00900f0f, 0x0f0f1b00, 0x0f00009c,
2787+ 0x01140000, 0x1b1b0f18, 0x0818013c, 0x01400008,
2788+ 0x00001818, 0x000b0110, 0x010c1800, 0x0b030b0f,
2789+ 0x181800f4, 0x00f81818, 0x00000018, 0x000000fc,
2790+ 0x00401808, 0x00000000, 0x0f1b0030, 0x003c0008,
2791+ 0x00000000, 0x00000038, 0x00340000, 0x00000000,
2792+ 0x1a080070, 0x00641a1a, 0x08080808, 0x08080060,
2793+ 0x005c0808, 0x08080808, 0x08080058, 0x00540808,
2794+ 0x08080808, 0x0808006c, 0x00680808, 0x08080808,
2795+ 0x000000a8, 0x00b00000, 0x08080808, 0x000000a0,
2796+ 0x00a40000, 0x00000000, 0x08ff0050, 0x004c0808,
2797+ 0xffffffff, 0xffff0048, 0x0044ffff, 0xffffffff,
2798+ 0x000000ac, 0x01040800, 0x08080b0f, 0x18180100,
2799+ 0x01081818, 0x0b0b1808, 0x1a0300e4, 0x012c0b1a,
2800+ 0x02020018, 0x0b000134, 0x011c0800, 0x0b1b1b00,
2801+ 0x0f0000c8, 0x00ec181b, 0x000f0f02, 0x00180118,
2802+ 0x01200000, 0x0f0b1b1b, 0x0f0200e8, 0x0000020b,
2803+};
2804+#endif
2805+
2806+/* Setup sequence done by the bootloader */
2807+static void n800_boot_init(void *opaque)
2808+{
2809+ struct n800_s *s = (struct n800_s *) opaque;
2810+ uint32_t buf;
2811+
2812+ /* PRCM setup */
2813+#define omap_writel(addr, val) \
2814+ buf = (val); \
2815+ cpu_physical_memory_write(addr, (void *) &buf, sizeof(buf))
2816+
2817+ omap_writel(0x48008060, 0x41); /* PRCM_CLKSRC_CTRL */
2818+ omap_writel(0x48008070, 1); /* PRCM_CLKOUT_CTRL */
2819+ omap_writel(0x48008078, 0); /* PRCM_CLKEMUL_CTRL */
2820+ omap_writel(0x48008090, 0); /* PRCM_VOLTSETUP */
2821+ omap_writel(0x48008094, 0); /* PRCM_CLKSSETUP */
2822+ omap_writel(0x48008098, 0); /* PRCM_POLCTRL */
2823+ omap_writel(0x48008140, 2); /* CM_CLKSEL_MPU */
2824+ omap_writel(0x48008148, 0); /* CM_CLKSTCTRL_MPU */
2825+ omap_writel(0x48008158, 1); /* RM_RSTST_MPU */
2826+ omap_writel(0x480081c8, 0x15); /* PM_WKDEP_MPU */
2827+ omap_writel(0x480081d4, 0x1d4); /* PM_EVGENCTRL_MPU */
2828+ omap_writel(0x480081d8, 0); /* PM_EVEGENONTIM_MPU */
2829+ omap_writel(0x480081dc, 0); /* PM_EVEGENOFFTIM_MPU */
2830+ omap_writel(0x480081e0, 0xc); /* PM_PWSTCTRL_MPU */
2831+ omap_writel(0x48008200, 0x047e7ff7); /* CM_FCLKEN1_CORE */
2832+ omap_writel(0x48008204, 0x00000004); /* CM_FCLKEN2_CORE */
2833+ omap_writel(0x48008210, 0x047e7ff1); /* CM_ICLKEN1_CORE */
2834+ omap_writel(0x48008214, 0x00000004); /* CM_ICLKEN2_CORE */
2835+ omap_writel(0x4800821c, 0x00000000); /* CM_ICLKEN4_CORE */
2836+ omap_writel(0x48008230, 0); /* CM_AUTOIDLE1_CORE */
2837+ omap_writel(0x48008234, 0); /* CM_AUTOIDLE2_CORE */
2838+ omap_writel(0x48008238, 7); /* CM_AUTOIDLE3_CORE */
2839+ omap_writel(0x4800823c, 0); /* CM_AUTOIDLE4_CORE */
2840+ omap_writel(0x48008240, 0x04360626); /* CM_CLKSEL1_CORE */
2841+ omap_writel(0x48008244, 0x00000014); /* CM_CLKSEL2_CORE */
2842+ omap_writel(0x48008248, 0); /* CM_CLKSTCTRL_CORE */
2843+ omap_writel(0x48008300, 0x00000000); /* CM_FCLKEN_GFX */
2844+ omap_writel(0x48008310, 0x00000000); /* CM_ICLKEN_GFX */
2845+ omap_writel(0x48008340, 0x00000001); /* CM_CLKSEL_GFX */
2846+ omap_writel(0x48008400, 0x00000004); /* CM_FCLKEN_WKUP */
2847+ omap_writel(0x48008410, 0x00000004); /* CM_ICLKEN_WKUP */
2848+ omap_writel(0x48008440, 0x00000000); /* CM_CLKSEL_WKUP */
2849+ omap_writel(0x48008500, 0x000000cf); /* CM_CLKEN_PLL */
2850+ omap_writel(0x48008530, 0x0000000c); /* CM_AUTOIDLE_PLL */
2851+ omap_writel(0x48008540, /* CM_CLKSEL1_PLL */
2852+ (0x78 << 12) | (6 << 8));
2853+ omap_writel(0x48008544, 2); /* CM_CLKSEL2_PLL */
2854+
2855+ /* GPMC setup */
2856+ n800_gpmc_init(s);
2857+
2858+ /* Video setup */
2859+ n800_dss_init(&s->blizzard);
2860+
2861+ /* CPU setup */
2862+ s->cpu->env->regs[15] = s->cpu->env->boot_info->loader_start;
2863+}
2864+
2865+#define OMAP_TAG_NOKIA_BT 0x4e01
2866+#define OMAP_TAG_WLAN_CX3110X 0x4e02
2867+#define OMAP_TAG_CBUS 0x4e03
2868+#define OMAP_TAG_EM_ASIC_BB5 0x4e04
2869+
2870+static int n800_atag_setup(struct arm_boot_info *info, void *p)
2871+{
2872+ uint8_t *b;
2873+ uint16_t *w;
2874+ uint32_t *l;
2875+
2876+ w = p;
2877+
2878+ stw_raw(w ++, OMAP_TAG_UART); /* u16 tag */
2879+ stw_raw(w ++, 4); /* u16 len */
2880+ stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
2881+ w ++;
2882+
2883+ stw_raw(w ++, OMAP_TAG_EM_ASIC_BB5); /* u16 tag */
2884+ stw_raw(w ++, 4); /* u16 len */
2885+ stw_raw(w ++, N800_RETU_GPIO); /* s16 retu_irq_gpio */
2886+ stw_raw(w ++, N800_TAHVO_GPIO); /* s16 tahvo_irq_gpio */
2887+
2888+ stw_raw(w ++, OMAP_TAG_CBUS); /* u16 tag */
2889+ stw_raw(w ++, 8); /* u16 len */
2890+ stw_raw(w ++, N800_CBUS_CLK_GPIO); /* s16 clk_gpio */
2891+ stw_raw(w ++, N800_CBUS_DAT_GPIO); /* s16 dat_gpio */
2892+ stw_raw(w ++, N800_CBUS_SEL_GPIO); /* s16 sel_gpio */
2893+ w ++;
2894+
2895+ stw_raw(w ++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */
2896+ stw_raw(w ++, 20); /* u16 len */
2897+ strcpy((void *) w, "bat_cover"); /* char name[12] */
2898+ w += 6;
2899+ stw_raw(w ++, N800_BAT_COVER_GPIO); /* u16 gpio */
2900+ stw_raw(w ++, 0x01);
2901+ stw_raw(w ++, 0);
2902+ stw_raw(w ++, 0);
2903+
2904+ stw_raw(w ++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */
2905+ stw_raw(w ++, 20); /* u16 len */
2906+ strcpy((void *) w, "cam_act"); /* char name[12] */
2907+ w += 6;
2908+ stw_raw(w ++, N800_CAM_ACT_GPIO); /* u16 gpio */
2909+ stw_raw(w ++, 0x20);
2910+ stw_raw(w ++, 0);
2911+ stw_raw(w ++, 0);
2912+
2913+ stw_raw(w ++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */
2914+ stw_raw(w ++, 20); /* u16 len */
2915+ strcpy((void *) w, "cam_turn"); /* char name[12] */
2916+ w += 6;
2917+ stw_raw(w ++, N800_CAM_TURN_GPIO); /* u16 gpio */
2918+ stw_raw(w ++, 0x21);
2919+ stw_raw(w ++, 0);
2920+ stw_raw(w ++, 0);
2921+
2922+ stw_raw(w ++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */
2923+ stw_raw(w ++, 20); /* u16 len */
2924+ strcpy((void *) w, "headphone"); /* char name[12] */
2925+ w += 6;
2926+ stw_raw(w ++, N800_HEADPHONE_GPIO); /* u16 gpio */
2927+ stw_raw(w ++, 0x11);
2928+ stw_raw(w ++, 0);
2929+ stw_raw(w ++, 0);
2930+
2931+ stw_raw(w ++, OMAP_TAG_NOKIA_BT); /* u16 tag */
2932+ stw_raw(w ++, 12); /* u16 len */
2933+ b = (void *) w;
2934+ stb_raw(b ++, 0x01); /* u8 chip_type (CSR) */
2935+ stb_raw(b ++, N800_BT_WKUP_GPIO); /* u8 bt_wakeup_gpio */
2936+ stb_raw(b ++, N800_BT_HOST_WKUP_GPIO); /* u8 host_wakeup_gpio */
2937+ stb_raw(b ++, N800_BT_RESET_GPIO); /* u8 reset_gpio */
2938+ stb_raw(b ++, 1); /* u8 bt_uart */
2939+ memset(b, 0, 6); /* u8 bd_addr[6] */
2940+ b += 6;
2941+ stb_raw(b ++, 0x02); /* u8 bt_sysclk (38.4) */
2942+ w = (void *) b;
2943+
2944+ stw_raw(w ++, OMAP_TAG_WLAN_CX3110X); /* u16 tag */
2945+ stw_raw(w ++, 8); /* u16 len */
2946+ stw_raw(w ++, 0x25); /* u8 chip_type */
2947+ stw_raw(w ++, N800_WLAN_PWR_GPIO); /* s16 power_gpio */
2948+ stw_raw(w ++, N800_WLAN_IRQ_GPIO); /* s16 irq_gpio */
2949+ stw_raw(w ++, -1); /* s16 spi_cs_gpio */
2950+
2951+ stw_raw(w ++, OMAP_TAG_MMC); /* u16 tag */
2952+ stw_raw(w ++, 16); /* u16 len */
2953+ stw_raw(w ++, 0xf); /* unsigned flags */
2954+ stw_raw(w ++, -1); /* s16 power_pin */
2955+ stw_raw(w ++, -1); /* s16 switch_pin */
2956+ stw_raw(w ++, -1); /* s16 wp_pin */
2957+ stw_raw(w ++, 0); /* unsigned flags */
2958+ stw_raw(w ++, 0); /* s16 power_pin */
2959+ stw_raw(w ++, 0); /* s16 switch_pin */
2960+ stw_raw(w ++, 0); /* s16 wp_pin */
2961+
2962+ stw_raw(w ++, OMAP_TAG_TEA5761); /* u16 tag */
2963+ stw_raw(w ++, 4); /* u16 len */
2964+ stw_raw(w ++, N800_TEA5761_CS_GPIO); /* u16 enable_gpio */
2965+ w ++;
2966+
2967+ stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */
2968+ stw_raw(w ++, 28); /* u16 len */
2969+ strcpy((void *) w, "bootloader"); /* char name[16] */
2970+ l = (void *) (w + 8);
2971+ stl_raw(l ++, 0x00020000); /* unsigned int size */
2972+ stl_raw(l ++, 0x00000000); /* unsigned int offset */
2973+ stl_raw(l ++, 0x3); /* unsigned int mask_flags */
2974+ w = (void *) l;
2975+
2976+ stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */
2977+ stw_raw(w ++, 28); /* u16 len */
2978+ strcpy((void *) w, "config"); /* char name[16] */
2979+ l = (void *) (w + 8);
2980+ stl_raw(l ++, 0x00060000); /* unsigned int size */
2981+ stl_raw(l ++, 0x00020000); /* unsigned int offset */
2982+ stl_raw(l ++, 0x0); /* unsigned int mask_flags */
2983+ w = (void *) l;
2984+
2985+ stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */
2986+ stw_raw(w ++, 28); /* u16 len */
2987+ strcpy((void *) w, "kernel"); /* char name[16] */
2988+ l = (void *) (w + 8);
2989+ stl_raw(l ++, 0x00200000); /* unsigned int size */
2990+ stl_raw(l ++, 0x00080000); /* unsigned int offset */
2991+ stl_raw(l ++, 0x0); /* unsigned int mask_flags */
2992+ w = (void *) l;
2993+
2994+ stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */
2995+ stw_raw(w ++, 28); /* u16 len */
2996+ strcpy((void *) w, "initfs"); /* char name[16] */
2997+ l = (void *) (w + 8);
2998+ stl_raw(l ++, 0x00200000); /* unsigned int size */
2999+ stl_raw(l ++, 0x00280000); /* unsigned int offset */
3000+ stl_raw(l ++, 0x3); /* unsigned int mask_flags */
3001+ w = (void *) l;
3002+
3003+ stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */
3004+ stw_raw(w ++, 28); /* u16 len */
3005+ strcpy((void *) w, "rootfs"); /* char name[16] */
3006+ l = (void *) (w + 8);
3007+ stl_raw(l ++, 0x0fb80000); /* unsigned int size */
3008+ stl_raw(l ++, 0x00480000); /* unsigned int offset */
3009+ stl_raw(l ++, 0x3); /* unsigned int mask_flags */
3010+ w = (void *) l;
3011+
3012+ stw_raw(w ++, OMAP_TAG_BOOT_REASON); /* u16 tag */
3013+ stw_raw(w ++, 12); /* u16 len */
3014+#if 0
3015+ strcpy((void *) w, "por"); /* char reason_str[12] */
3016+ strcpy((void *) w, "charger"); /* char reason_str[12] */
3017+ strcpy((void *) w, "32wd_to"); /* char reason_str[12] */
3018+ strcpy((void *) w, "sw_rst"); /* char reason_str[12] */
3019+ strcpy((void *) w, "mbus"); /* char reason_str[12] */
3020+ strcpy((void *) w, "unknown"); /* char reason_str[12] */
3021+ strcpy((void *) w, "swdg_to"); /* char reason_str[12] */
3022+ strcpy((void *) w, "sec_vio"); /* char reason_str[12] */
3023+ strcpy((void *) w, "pwr_key"); /* char reason_str[12] */
3024+ strcpy((void *) w, "rtc_alarm"); /* char reason_str[12] */
3025+#else
3026+ strcpy((void *) w, "pwr_key"); /* char reason_str[12] */
3027+#endif
3028+ w += 6;
3029+
3030+ stw_raw(w ++, OMAP_TAG_VERSION_STR); /* u16 tag */
3031+ stw_raw(w ++, 24); /* u16 len */
3032+ strcpy((void *) w, "product"); /* char component[12] */
3033+ w += 6;
3034+ strcpy((void *) w, "RX-34"); /* char version[12] */
3035+ w += 6;
3036+
3037+ stw_raw(w ++, OMAP_TAG_VERSION_STR); /* u16 tag */
3038+ stw_raw(w ++, 24); /* u16 len */
3039+ strcpy((void *) w, "hw-build"); /* char component[12] */
3040+ w += 6;
3041+ strcpy((void *) w, "QEMU"); /* char version[12] */
3042+ w += 6;
3043+
3044+ stw_raw(w ++, OMAP_TAG_VERSION_STR); /* u16 tag */
3045+ stw_raw(w ++, 24); /* u16 len */
3046+ strcpy((void *) w, "nolo"); /* char component[12] */
3047+ w += 6;
3048+ strcpy((void *) w, "1.1.6-qemu"); /* char version[12] */
3049+ w += 6;
3050+
3051+ stw_raw(w ++, OMAP_TAG_LCD); /* u16 tag */
3052+ stw_raw(w ++, 36); /* u16 len */
3053+ strcpy((void *) w, "QEMU LCD panel"); /* char panel_name[16] */
3054+ w += 8;
3055+ strcpy((void *) w, "blizzard"); /* char ctrl_name[16] */
3056+ w += 8;
3057+ stw_raw(w ++, 5); /* TODO s16 nreset_gpio */
3058+ stw_raw(w ++, 16); /* u8 data_lines */
3059+
3060+ return (void *) w - p;
3061+}
3062+
3063+static struct arm_boot_info n800_binfo = {
3064+ .loader_start = OMAP2_Q2_BASE,
3065+ /* Actually two chips of 0x4000000 bytes each */
3066+ .ram_size = 0x08000000,
3067+ .board_id = 0x4f7,
3068+ .atag_board = n800_atag_setup,
3069+};
3070+
3071+static void n800_init(int ram_size, int vga_ram_size,
3072+ const char *boot_device, DisplayState *ds,
3073+ const char *kernel_filename, const char *kernel_cmdline,
3074+ const char *initrd_filename, const char *cpu_model)
3075+{
3076+ struct n800_s *s = (struct n800_s *) qemu_mallocz(sizeof(*s));
3077+ int sdram_size = n800_binfo.ram_size;
3078+ int onenandram_size = 0x00010000;
3079+
3080+ if (ram_size < sdram_size + onenandram_size + OMAP242X_SRAM_SIZE) {
3081+ fprintf(stderr, "This architecture uses %i bytes of memory\n",
3082+ sdram_size + onenandram_size + OMAP242X_SRAM_SIZE);
3083+ exit(1);
3084+ }
3085+
3086+ s->cpu = omap2420_mpu_init(sdram_size, NULL, cpu_model);
3087+
3088+ n800_gpio_setup(s);
3089+ n800_nand_setup(s);
3090+ n800_i2c_setup(s);
3091+ n800_tsc_setup(s);
3092+ n800_spi_setup(s);
3093+ n800_dss_setup(s, ds);
3094+ n800_cbus_setup(s);
3095+
3096+ /* Setup initial (reset) machine state */
3097+
3098+ /* Start at the OneNAND bootloader. */
3099+ s->cpu->env->regs[15] = 0;
3100+
3101+ if (kernel_filename) {
3102+ /* Or at the linux loader. */
3103+ n800_binfo.kernel_filename = kernel_filename;
3104+ n800_binfo.kernel_cmdline = kernel_cmdline;
3105+ n800_binfo.initrd_filename = initrd_filename;
3106+ arm_load_kernel(s->cpu->env, &n800_binfo);
3107+
3108+ qemu_register_reset(n800_boot_init, s);
3109+ n800_boot_init(s);
3110+ }
3111+
3112+ dpy_resize(ds, 800, 480);
3113+}
3114+
3115+QEMUMachine n800_machine = {
3116+ "n800",
3117+ "Nokia N800 aka. RX-34 tablet (OMAP2420)",
3118+ n800_init,
3119+};
3120diff --git a/hw/omap.h b/hw/omap.h
3121index ecfd54d..de838c9 100644
3122--- a/hw/omap.h
3123+++ b/hw/omap.h
3124@@ -22,6 +22,7 @@
3125 # define hw_omap_h "omap.h"
3126
3127 # define OMAP_EMIFS_BASE 0x00000000
3128+# define OMAP2_Q0_BASE 0x00000000
3129 # define OMAP_CS0_BASE 0x00000000
3130 # define OMAP_CS1_BASE 0x04000000
3131 # define OMAP_CS2_BASE 0x08000000
3132@@ -29,18 +30,26 @@
3133 # define OMAP_EMIFF_BASE 0x10000000
3134 # define OMAP_IMIF_BASE 0x20000000
3135 # define OMAP_LOCALBUS_BASE 0x30000000
3136+# define OMAP2_Q1_BASE 0x40000000
3137+# define OMAP2_L4_BASE 0x48000000
3138+# define OMAP2_SRAM_BASE 0x40200000
3139+# define OMAP2_L3_BASE 0x68000000
3140+# define OMAP2_Q2_BASE 0x80000000
3141+# define OMAP2_Q3_BASE 0xc0000000
3142 # define OMAP_MPUI_BASE 0xe1000000
3143
3144 # define OMAP730_SRAM_SIZE 0x00032000
3145 # define OMAP15XX_SRAM_SIZE 0x00030000
3146 # define OMAP16XX_SRAM_SIZE 0x00004000
3147 # define OMAP1611_SRAM_SIZE 0x0003e800
3148+# define OMAP242X_SRAM_SIZE 0x000a0000
3149+# define OMAP243X_SRAM_SIZE 0x00010000
3150 # define OMAP_CS0_SIZE 0x04000000
3151 # define OMAP_CS1_SIZE 0x04000000
3152 # define OMAP_CS2_SIZE 0x04000000
3153 # define OMAP_CS3_SIZE 0x04000000
3154
3155-/* omap1_clk.c */
3156+/* omap_clk.c */
3157 struct omap_mpu_state_s;
3158 typedef struct clk *omap_clk;
3159 omap_clk omap_findclk(struct omap_mpu_state_s *mpu, const char *name);
3160@@ -55,14 +64,41 @@ int64_t omap_clk_getrate(omap_clk clk);
3161 void omap_clk_reparent(omap_clk clk, omap_clk parent);
3162
3163 /* omap[123].c */
3164+struct omap_l4_s;
3165+struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num);
3166+
3167+struct omap_target_agent_s;
3168+struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, int cs);
3169+target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
3170+ int iotype);
3171+
3172 struct omap_intr_handler_s;
3173 struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
3174- unsigned long size, unsigned char nbanks,
3175+ unsigned long size, unsigned char nbanks, qemu_irq **pins,
3176 qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk);
3177-
3178-struct omap_target_agent_s;
3179-static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
3180- int region, int iotype) { return 0; }
3181+struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
3182+ int size, int nbanks, qemu_irq **pins,
3183+ qemu_irq parent_irq, qemu_irq parent_fiq,
3184+ omap_clk fclk, omap_clk iclk);
3185+void omap_inth_reset(struct omap_intr_handler_s *s);
3186+
3187+struct omap_prcm_s;
3188+struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
3189+ qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
3190+ struct omap_mpu_state_s *mpu);
3191+
3192+struct omap_sysctl_s;
3193+struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
3194+ omap_clk iclk, struct omap_mpu_state_s *mpu);
3195+
3196+struct omap_sdrc_s;
3197+struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base);
3198+
3199+struct omap_gpmc_s;
3200+struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq);
3201+void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
3202+ void (*base_upd)(void *opaque, target_phys_addr_t new),
3203+ void (*unmap)(void *opaque), void *opaque);
3204
3205 /*
3206 * Common IRQ numbers for level 1 interrupt handler
3207@@ -295,10 +331,20 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
3208 * OMAP-24xx common IRQ numbers
3209 */
3210 # define OMAP_INT_24XX_SYS_NIRQ 7
3211+# define OMAP_INT_24XX_L3_IRQ 10
3212+# define OMAP_INT_24XX_PRCM_MPU_IRQ 11
3213 # define OMAP_INT_24XX_SDMA_IRQ0 12
3214 # define OMAP_INT_24XX_SDMA_IRQ1 13
3215 # define OMAP_INT_24XX_SDMA_IRQ2 14
3216 # define OMAP_INT_24XX_SDMA_IRQ3 15
3217+# define OMAP_INT_243X_MCBSP2_IRQ 16
3218+# define OMAP_INT_243X_MCBSP3_IRQ 17
3219+# define OMAP_INT_243X_MCBSP4_IRQ 18
3220+# define OMAP_INT_243X_MCBSP5_IRQ 19
3221+# define OMAP_INT_24XX_GPMC_IRQ 20
3222+# define OMAP_INT_24XX_GUFFAW_IRQ 21
3223+# define OMAP_INT_24XX_IVA_IRQ 22
3224+# define OMAP_INT_24XX_EAC_IRQ 23
3225 # define OMAP_INT_24XX_CAM_IRQ 24
3226 # define OMAP_INT_24XX_DSS_IRQ 25
3227 # define OMAP_INT_24XX_MAIL_U0_MPU 26
3228@@ -308,8 +354,10 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
3229 # define OMAP_INT_24XX_GPIO_BANK2 30
3230 # define OMAP_INT_24XX_GPIO_BANK3 31
3231 # define OMAP_INT_24XX_GPIO_BANK4 32
3232-# define OMAP_INT_24XX_GPIO_BANK5 33
3233+# define OMAP_INT_243X_GPIO_BANK5 33
3234 # define OMAP_INT_24XX_MAIL_U3_MPU 34
3235+# define OMAP_INT_24XX_WDT3 35
3236+# define OMAP_INT_24XX_WDT4 36
3237 # define OMAP_INT_24XX_GPTIMER1 37
3238 # define OMAP_INT_24XX_GPTIMER2 38
3239 # define OMAP_INT_24XX_GPTIMER3 39
3240@@ -322,10 +370,24 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
3241 # define OMAP_INT_24XX_GPTIMER10 46
3242 # define OMAP_INT_24XX_GPTIMER11 47
3243 # define OMAP_INT_24XX_GPTIMER12 48
3244+# define OMAP_INT_24XX_PKA_IRQ 50
3245+# define OMAP_INT_24XX_SHA1MD5_IRQ 51
3246+# define OMAP_INT_24XX_RNG_IRQ 52
3247+# define OMAP_INT_24XX_MG_IRQ 53
3248+# define OMAP_INT_24XX_I2C1_IRQ 56
3249+# define OMAP_INT_24XX_I2C2_IRQ 57
3250 # define OMAP_INT_24XX_MCBSP1_IRQ_TX 59
3251 # define OMAP_INT_24XX_MCBSP1_IRQ_RX 60
3252 # define OMAP_INT_24XX_MCBSP2_IRQ_TX 62
3253 # define OMAP_INT_24XX_MCBSP2_IRQ_RX 63
3254+# define OMAP_INT_243X_MCBSP1_IRQ 64
3255+# define OMAP_INT_24XX_MCSPI1_IRQ 65
3256+# define OMAP_INT_24XX_MCSPI2_IRQ 66
3257+# define OMAP_INT_24XX_SSI1_IRQ0 67
3258+# define OMAP_INT_24XX_SSI1_IRQ1 68
3259+# define OMAP_INT_24XX_SSI2_IRQ0 69
3260+# define OMAP_INT_24XX_SSI2_IRQ1 70
3261+# define OMAP_INT_24XX_SSI_GDD_IRQ 71
3262 # define OMAP_INT_24XX_UART1_IRQ 72
3263 # define OMAP_INT_24XX_UART2_IRQ 73
3264 # define OMAP_INT_24XX_UART3_IRQ 74
3265@@ -335,10 +397,15 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
3266 # define OMAP_INT_24XX_USB_IRQ_HGEN 78
3267 # define OMAP_INT_24XX_USB_IRQ_HSOF 79
3268 # define OMAP_INT_24XX_USB_IRQ_OTG 80
3269+# define OMAP_INT_24XX_VLYNQ_IRQ 81
3270 # define OMAP_INT_24XX_MMC_IRQ 83
3271+# define OMAP_INT_24XX_MS_IRQ 84
3272+# define OMAP_INT_24XX_FAC_IRQ 85
3273+# define OMAP_INT_24XX_MCSPI3_IRQ 91
3274 # define OMAP_INT_243X_HS_USB_MC 92
3275 # define OMAP_INT_243X_HS_USB_DMA 93
3276 # define OMAP_INT_243X_CARKIT 94
3277+# define OMAP_INT_34XX_GPTIMER12 95
3278
3279 /* omap_dma.c */
3280 enum omap_dma_model {
3281@@ -352,6 +419,9 @@ struct omap_dma_s;
3282 struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
3283 qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
3284 enum omap_dma_model model);
3285+struct omap_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
3286+ struct omap_mpu_state_s *mpu, int fifo,
3287+ int chans, omap_clk iclk, omap_clk fclk);
3288 void omap_dma_reset(struct omap_dma_s *s);
3289
3290 struct dma_irq_map {
3291@@ -367,7 +437,7 @@ enum omap_dma_port {
3292 tipb,
3293 local, /* omap16xx: ocp_t2 */
3294 tipb_mpui,
3295- omap_dma_port_last,
3296+ __omap_dma_port_last,
3297 };
3298
3299 typedef enum {
3300@@ -488,11 +558,83 @@ struct omap_dma_lcd_channel_s {
3301 # define OMAP_DMA_MMC2_RX 55
3302 # define OMAP_DMA_CRYPTO_DES_OUT 56
3303
3304+/*
3305+ * DMA request numbers for the OMAP2
3306+ */
3307+# define OMAP24XX_DMA_NO_DEVICE 0
3308+# define OMAP24XX_DMA_XTI_DMA 1 /* Not in OMAP2420 */
3309+# define OMAP24XX_DMA_EXT_DMAREQ0 2
3310+# define OMAP24XX_DMA_EXT_DMAREQ1 3
3311+# define OMAP24XX_DMA_GPMC 4
3312+# define OMAP24XX_DMA_GFX 5 /* Not in OMAP2420 */
3313+# define OMAP24XX_DMA_DSS 6
3314+# define OMAP24XX_DMA_VLYNQ_TX 7 /* Not in OMAP2420 */
3315+# define OMAP24XX_DMA_CWT 8 /* Not in OMAP2420 */
3316+# define OMAP24XX_DMA_AES_TX 9 /* Not in OMAP2420 */
3317+# define OMAP24XX_DMA_AES_RX 10 /* Not in OMAP2420 */
3318+# define OMAP24XX_DMA_DES_TX 11 /* Not in OMAP2420 */
3319+# define OMAP24XX_DMA_DES_RX 12 /* Not in OMAP2420 */
3320+# define OMAP24XX_DMA_SHA1MD5_RX 13 /* Not in OMAP2420 */
3321+# define OMAP24XX_DMA_EXT_DMAREQ2 14
3322+# define OMAP24XX_DMA_EXT_DMAREQ3 15
3323+# define OMAP24XX_DMA_EXT_DMAREQ4 16
3324+# define OMAP24XX_DMA_EAC_AC_RD 17
3325+# define OMAP24XX_DMA_EAC_AC_WR 18
3326+# define OMAP24XX_DMA_EAC_MD_UL_RD 19
3327+# define OMAP24XX_DMA_EAC_MD_UL_WR 20
3328+# define OMAP24XX_DMA_EAC_MD_DL_RD 21
3329+# define OMAP24XX_DMA_EAC_MD_DL_WR 22
3330+# define OMAP24XX_DMA_EAC_BT_UL_RD 23
3331+# define OMAP24XX_DMA_EAC_BT_UL_WR 24
3332+# define OMAP24XX_DMA_EAC_BT_DL_RD 25
3333+# define OMAP24XX_DMA_EAC_BT_DL_WR 26
3334+# define OMAP24XX_DMA_I2C1_TX 27
3335+# define OMAP24XX_DMA_I2C1_RX 28
3336+# define OMAP24XX_DMA_I2C2_TX 29
3337+# define OMAP24XX_DMA_I2C2_RX 30
3338+# define OMAP24XX_DMA_MCBSP1_TX 31
3339+# define OMAP24XX_DMA_MCBSP1_RX 32
3340+# define OMAP24XX_DMA_MCBSP2_TX 33
3341+# define OMAP24XX_DMA_MCBSP2_RX 34
3342+# define OMAP24XX_DMA_SPI1_TX0 35
3343+# define OMAP24XX_DMA_SPI1_RX0 36
3344+# define OMAP24XX_DMA_SPI1_TX1 37
3345+# define OMAP24XX_DMA_SPI1_RX1 38
3346+# define OMAP24XX_DMA_SPI1_TX2 39
3347+# define OMAP24XX_DMA_SPI1_RX2 40
3348+# define OMAP24XX_DMA_SPI1_TX3 41
3349+# define OMAP24XX_DMA_SPI1_RX3 42
3350+# define OMAP24XX_DMA_SPI2_TX0 43
3351+# define OMAP24XX_DMA_SPI2_RX0 44
3352+# define OMAP24XX_DMA_SPI2_TX1 45
3353+# define OMAP24XX_DMA_SPI2_RX1 46
3354+
3355+# define OMAP24XX_DMA_UART1_TX 49
3356+# define OMAP24XX_DMA_UART1_RX 50
3357+# define OMAP24XX_DMA_UART2_TX 51
3358+# define OMAP24XX_DMA_UART2_RX 52
3359+# define OMAP24XX_DMA_UART3_TX 53
3360+# define OMAP24XX_DMA_UART3_RX 54
3361+# define OMAP24XX_DMA_USB_W2FC_TX0 55
3362+# define OMAP24XX_DMA_USB_W2FC_RX0 56
3363+# define OMAP24XX_DMA_USB_W2FC_TX1 57
3364+# define OMAP24XX_DMA_USB_W2FC_RX1 58
3365+# define OMAP24XX_DMA_USB_W2FC_TX2 59
3366+# define OMAP24XX_DMA_USB_W2FC_RX2 60
3367+# define OMAP24XX_DMA_MMC1_TX 61
3368+# define OMAP24XX_DMA_MMC1_RX 62
3369+# define OMAP24XX_DMA_MS 63 /* Not in OMAP2420 */
3370+# define OMAP24XX_DMA_EXT_DMAREQ5 64
3371+
3372 /* omap[123].c */
3373 struct omap_mpu_timer_s;
3374 struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
3375 qemu_irq irq, omap_clk clk);
3376
3377+struct omap_gp_timer_s;
3378+struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
3379+ qemu_irq irq, omap_clk fclk, omap_clk iclk);
3380+
3381 struct omap_watchdog_timer_s;
3382 struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
3383 qemu_irq irq, omap_clk clk);
3384@@ -501,13 +643,21 @@ struct omap_32khz_timer_s;
3385 struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
3386 qemu_irq irq, omap_clk clk);
3387
3388+void omap_synctimer_init(struct omap_target_agent_s *ta,
3389+ struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk);
3390+
3391 struct omap_tipb_bridge_s;
3392 struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base,
3393 qemu_irq abort_irq, omap_clk clk);
3394
3395 struct omap_uart_s;
3396 struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
3397- qemu_irq irq, omap_clk clk, CharDriverState *chr);
3398+ qemu_irq irq, omap_clk fclk, omap_clk iclk,
3399+ qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr);
3400+struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
3401+ qemu_irq irq, omap_clk fclk, omap_clk iclk,
3402+ qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr);
3403+void omap_uart_reset(struct omap_uart_s *s);
3404
3405 struct omap_mpuio_s;
3406 struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base,
3407@@ -523,6 +673,12 @@ struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
3408 qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
3409 void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
3410
3411+struct omap_gpif_s;
3412+struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
3413+ qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules);
3414+qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start);
3415+void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler);
3416+
3417 struct uwire_slave_s {
3418 uint16_t (*receive)(void *opaque);
3419 void (*send)(void *opaque, uint16_t data);
3420@@ -534,6 +690,13 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
3421 void omap_uwire_attach(struct omap_uwire_s *s,
3422 struct uwire_slave_s *slave, int chipselect);
3423
3424+struct omap_mcspi_s;
3425+struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
3426+ qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk);
3427+void omap_mcspi_attach(struct omap_mcspi_s *s,
3428+ uint32_t (*txrx)(void *opaque, uint32_t), void *opaque,
3429+ int chipselect);
3430+
3431 struct omap_rtc_s;
3432 struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
3433 qemu_irq *irq, omap_clk clk);
3434@@ -570,6 +733,9 @@ void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave);
3435 struct omap_lpg_s;
3436 struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk);
3437
3438+void omap_tap_init(struct omap_target_agent_s *ta,
3439+ struct omap_mpu_state_s *mpu);
3440+
3441 /* omap_lcdc.c */
3442 struct omap_lcd_panel_s;
3443 void omap_lcdc_reset(struct omap_lcd_panel_s *s);
3444@@ -577,13 +743,33 @@ struct omap_lcd_panel_s *omap_lcdc_init(target_phys_addr_t base, qemu_irq irq,
3445 struct omap_dma_lcd_channel_s *dma, DisplayState *ds,
3446 ram_addr_t imif_base, ram_addr_t emiff_base, omap_clk clk);
3447
3448+/* omap_dss.c */
3449+struct rfbi_chip_s {
3450+ void *opaque;
3451+ void (*write)(void *opaque, int dc, uint16_t value);
3452+ void (*block)(void *opaque, int dc, void *buf, size_t len, int pitch);
3453+ uint16_t (*read)(void *opaque, int dc);
3454+};
3455+struct omap_dss_s;
3456+void omap_dss_reset(struct omap_dss_s *s);
3457+struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
3458+ target_phys_addr_t l3_base, DisplayState *ds,
3459+ qemu_irq irq, qemu_irq drq,
3460+ omap_clk fck1, omap_clk fck2, omap_clk ck54m,
3461+ omap_clk ick1, omap_clk ick2);
3462+void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip);
3463+
3464 /* omap_mmc.c */
3465 struct omap_mmc_s;
3466 struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
3467 BlockDriverState *bd,
3468 qemu_irq irq, qemu_irq dma[], omap_clk clk);
3469+struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
3470+ BlockDriverState *bd, qemu_irq irq, qemu_irq dma[],
3471+ omap_clk fclk, omap_clk iclk);
3472 void omap_mmc_reset(struct omap_mmc_s *s);
3473 void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover);
3474+void omap_mmc_enable(struct omap_mmc_s *s, int enable);
3475
3476 /* omap_i2c.c */
3477 struct omap_i2c_s;
3478@@ -596,14 +782,37 @@ i2c_bus *omap_i2c_bus(struct omap_i2c_s *s);
3479
3480 # define cpu_is_omap310(cpu) (cpu->mpu_model == omap310)
3481 # define cpu_is_omap1510(cpu) (cpu->mpu_model == omap1510)
3482+# define cpu_is_omap1610(cpu) (cpu->mpu_model == omap1610)
3483+# define cpu_is_omap1710(cpu) (cpu->mpu_model == omap1710)
3484+# define cpu_is_omap2410(cpu) (cpu->mpu_model == omap2410)
3485+# define cpu_is_omap2420(cpu) (cpu->mpu_model == omap2420)
3486+# define cpu_is_omap2430(cpu) (cpu->mpu_model == omap2430)
3487+# define cpu_is_omap3430(cpu) (cpu->mpu_model == omap3430)
3488+
3489 # define cpu_is_omap15xx(cpu) \
3490 (cpu_is_omap310(cpu) || cpu_is_omap1510(cpu))
3491-# define cpu_class_omap1(cpu) 1
3492+# define cpu_is_omap16xx(cpu) \
3493+ (cpu_is_omap1610(cpu) || cpu_is_omap1710(cpu))
3494+# define cpu_is_omap24xx(cpu) \
3495+ (cpu_is_omap2410(cpu) || cpu_is_omap2420(cpu) || cpu_is_omap2430(cpu))
3496+
3497+# define cpu_class_omap1(cpu) \
3498+ (cpu_is_omap15xx(cpu) || cpu_is_omap16xx(cpu))
3499+# define cpu_class_omap2(cpu) cpu_is_omap24xx(cpu)
3500+# define cpu_class_omap3(cpu) cpu_is_omap3430(cpu)
3501
3502 struct omap_mpu_state_s {
3503- enum omap1_mpu_model {
3504+ enum omap_mpu_model {
3505 omap310,
3506 omap1510,
3507+ omap1610,
3508+ omap1710,
3509+ omap2410,
3510+ omap2420,
3511+ omap2422,
3512+ omap2423,
3513+ omap2430,
3514+ omap3430,
3515 } mpu_model;
3516
3517 CPUState *env;
3518@@ -620,7 +829,7 @@ struct omap_mpu_state_s {
3519 target_phys_addr_t offset, uint32_t value);
3520 int (*addr_valid)(struct omap_mpu_state_s *s,
3521 target_phys_addr_t addr);
3522- } port[omap_dma_port_last];
3523+ } port[__omap_dma_port_last];
3524
3525 unsigned long sdram_size;
3526 unsigned long sram_size;
3527@@ -656,7 +865,7 @@ struct omap_mpu_state_s {
3528 omap_clk clk;
3529 } pwt;
3530
3531- struct omap_i2c_s *i2c;
3532+ struct omap_i2c_s *i2c[2];
3533
3534 struct omap_rtc_s *rtc;
3535
3536@@ -722,7 +931,38 @@ struct omap_mpu_state_s {
3537 uint16_t dsp_idlect2;
3538 uint16_t dsp_rstct2;
3539 } clkm;
3540-} *omap310_mpu_init(unsigned long sdram_size,
3541+
3542+ /* OMAP2-only peripherals */
3543+ struct omap_l4_s *l4;
3544+
3545+ struct omap_gp_timer_s *gptimer[12];
3546+
3547+ target_phys_addr_t tap_base;
3548+
3549+ struct omap_synctimer_s {
3550+ target_phys_addr_t base;
3551+ uint32_t val;
3552+ uint16_t readh;
3553+ } synctimer;
3554+
3555+ struct omap_prcm_s *prcm;
3556+ struct omap_sdrc_s *sdrc;
3557+ struct omap_gpmc_s *gpmc;
3558+ struct omap_sysctl_s *sysc;
3559+
3560+ struct omap_gpif_s *gpif;
3561+
3562+ struct omap_mcspi_s *mcspi[2];
3563+
3564+ struct omap_dss_s *dss;
3565+};
3566+
3567+/* omap1.c */
3568+struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
3569+ DisplayState *ds, const char *core);
3570+
3571+/* omap2.c */
3572+struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
3573 DisplayState *ds, const char *core);
3574
3575 # if TARGET_PHYS_ADDR_BITS == 32
3576@@ -743,24 +983,46 @@ uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr);
3577 void omap_badwidth_write32(void *opaque, target_phys_addr_t addr,
3578 uint32_t value);
3579
3580+void omap_mpu_wakeup(void *opaque, int irq, int req);
3581+
3582 # define OMAP_BAD_REG(paddr) \
3583- printf("%s: Bad register " OMAP_FMT_plx "\n", __FUNCTION__, paddr)
3584+ fprintf(stderr, "%s: Bad register " OMAP_FMT_plx "\n", \
3585+ __FUNCTION__, paddr)
3586 # define OMAP_RO_REG(paddr) \
3587- printf("%s: Read-only register " OMAP_FMT_plx "\n", \
3588+ fprintf(stderr, "%s: Read-only register " OMAP_FMT_plx "\n", \
3589 __FUNCTION__, paddr)
3590
3591+/* OMAP-specific Linux bootloader tags for the ATAG_BOARD area
3592+ (Board-specifc tags are not here) */
3593+#define OMAP_TAG_CLOCK 0x4f01
3594+#define OMAP_TAG_MMC 0x4f02
3595+#define OMAP_TAG_SERIAL_CONSOLE 0x4f03
3596+#define OMAP_TAG_USB 0x4f04
3597+#define OMAP_TAG_LCD 0x4f05
3598+#define OMAP_TAG_GPIO_SWITCH 0x4f06
3599+#define OMAP_TAG_UART 0x4f07
3600+#define OMAP_TAG_FBMEM 0x4f08
3601+#define OMAP_TAG_STI_CONSOLE 0x4f09
3602+#define OMAP_TAG_CAMERA_SENSOR 0x4f0a
3603+#define OMAP_TAG_PARTITION 0x4f0b
3604+#define OMAP_TAG_TEA5761 0x4f10
3605+#define OMAP_TAG_TMP105 0x4f11
3606+#define OMAP_TAG_BOOT_REASON 0x4f80
3607+#define OMAP_TAG_FLASH_PART_STR 0x4f81
3608+#define OMAP_TAG_VERSION_STR 0x4f82
3609+
3610 # define TCMI_VERBOSE 1
3611 //# define MEM_VERBOSE 1
3612
3613 # ifdef TCMI_VERBOSE
3614 # define OMAP_8B_REG(paddr) \
3615- printf("%s: 8-bit register " OMAP_FMT_plx "\n", \
3616+ fprintf(stderr, "%s: 8-bit register " OMAP_FMT_plx "\n", \
3617 __FUNCTION__, paddr)
3618 # define OMAP_16B_REG(paddr) \
3619- printf("%s: 16-bit register " OMAP_FMT_plx "\n", \
3620+ fprintf(stderr, "%s: 16-bit register " OMAP_FMT_plx "\n", \
3621 __FUNCTION__, paddr)
3622 # define OMAP_32B_REG(paddr) \
3623- printf("%s: 32-bit register " OMAP_FMT_plx "\n", \
3624+ fprintf(stderr, "%s: 32-bit register " OMAP_FMT_plx "\n", \
3625 __FUNCTION__, paddr)
3626 # else
3627 # define OMAP_8B_REG(paddr)
3628@@ -863,10 +1125,4 @@ inline static int debug_register_io_memory(int io_index,
3629 # define cpu_register_io_memory debug_register_io_memory
3630 # endif
3631
3632-/* Not really omap specific, but is the only thing that uses the
3633- uwire interface. */
3634-/* tsc210x.c */
3635-struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio);
3636-struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip);
3637-
3638 #endif /* hw_omap_h */
3639diff --git a/hw/omap1.c b/hw/omap1.c
3640index 3888e80..d81cbce 100644
3641--- a/hw/omap1.c
3642+++ b/hw/omap1.c
3643@@ -23,10 +23,11 @@
3644 #include "omap.h"
3645 #include "sysemu.h"
3646 #include "qemu-timer.h"
3647+#include "qemu-char.h"
3648 /* We use pc-style serial ports. */
3649 #include "pc.h"
3650
3651-/* Should signal the TCMI */
3652+/* Should signal the TCMI/GPMC */
3653 uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr)
3654 {
3655 uint8_t ret;
3656@@ -86,6 +87,7 @@ struct omap_intr_handler_bank_s {
3657 uint32_t mask;
3658 uint32_t fiq;
3659 uint32_t sens_edge;
3660+ uint32_t swi;
3661 unsigned char priority[32];
3662 };
3663
3664@@ -94,11 +96,14 @@ struct omap_intr_handler_s {
3665 qemu_irq parent_intr[2];
3666 target_phys_addr_t base;
3667 unsigned char nbanks;
3668+ int level_only;
3669
3670 /* state */
3671 uint32_t new_agr[2];
3672 int sir_intr[2];
3673- struct omap_intr_handler_bank_s banks[];
3674+ int autoidle;
3675+ uint32_t mask;
3676+ struct omap_intr_handler_bank_s bank[];
3677 };
3678
3679 static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq)
3680@@ -113,11 +118,11 @@ static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq)
3681 * If all interrupts have the same priority, the default order is IRQ_N,
3682 * IRQ_N-1,...,IRQ_0. */
3683 for (j = 0; j < s->nbanks; ++j) {
3684- level = s->banks[j].irqs & ~s->banks[j].mask &
3685- (is_fiq ? s->banks[j].fiq : ~s->banks[j].fiq);
3686+ level = s->bank[j].irqs & ~s->bank[j].mask &
3687+ (is_fiq ? s->bank[j].fiq : ~s->bank[j].fiq);
3688 for (f = ffs(level), i = f - 1, level >>= f - 1; f; i += f,
3689 level >>= f) {
3690- p = s->banks[j].priority[i];
3691+ p = s->bank[j].priority[i];
3692 if (p <= p_intr) {
3693 p_intr = p;
3694 sir_intr = 32 * j + i;
3695@@ -134,10 +139,10 @@ static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
3696 uint32_t has_intr = 0;
3697
3698 for (i = 0; i < s->nbanks; ++i)
3699- has_intr |= s->banks[i].irqs & ~s->banks[i].mask &
3700- (is_fiq ? s->banks[i].fiq : ~s->banks[i].fiq);
3701+ has_intr |= s->bank[i].irqs & ~s->bank[i].mask &
3702+ (is_fiq ? s->bank[i].fiq : ~s->bank[i].fiq);
3703
3704- if (s->new_agr[is_fiq] && has_intr) {
3705+ if (s->new_agr[is_fiq] & has_intr & s->mask) {
3706 s->new_agr[is_fiq] = 0;
3707 omap_inth_sir_update(s, is_fiq);
3708 qemu_set_irq(s->parent_intr[is_fiq], 1);
3709@@ -152,13 +157,13 @@ static void omap_set_intr(void *opaque, int irq, int req)
3710 struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
3711 uint32_t rise;
3712
3713- struct omap_intr_handler_bank_s *bank = &ih->banks[irq >> 5];
3714+ struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
3715 int n = irq & 31;
3716
3717 if (req) {
3718 rise = ~bank->irqs & (1 << n);
3719 if (~bank->sens_edge & (1 << n))
3720- rise &= ~bank->inputs & (1 << n);
3721+ rise &= ~bank->inputs;
3722
3723 bank->inputs |= (1 << n);
3724 if (rise) {
3725@@ -173,13 +178,33 @@ static void omap_set_intr(void *opaque, int irq, int req)
3726 }
3727 }
3728
3729+/* Simplified version with no edge detection */
3730+static void omap_set_intr_noedge(void *opaque, int irq, int req)
3731+{
3732+ struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
3733+ uint32_t rise;
3734+
3735+ struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
3736+ int n = irq & 31;
3737+
3738+ if (req) {
3739+ rise = ~bank->inputs & (1 << n);
3740+ if (rise) {
3741+ bank->irqs |= bank->inputs |= rise;
3742+ omap_inth_update(ih, 0);
3743+ omap_inth_update(ih, 1);
3744+ }
3745+ } else
3746+ bank->irqs = (bank->inputs &= ~(1 << n)) | bank->swi;
3747+}
3748+
3749 static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr)
3750 {
3751 struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
3752 int i, offset = addr - s->base;
3753 int bank_no = offset >> 8;
3754 int line_no;
3755- struct omap_intr_handler_bank_s *bank = &s->banks[bank_no];
3756+ struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
3757 offset &= 0xff;
3758
3759 switch (offset) {
3760@@ -194,7 +219,7 @@ static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr)
3761 if (bank_no != 0)
3762 break;
3763 line_no = s->sir_intr[(offset - 0x10) >> 2];
3764- bank = &s->banks[line_no >> 5];
3765+ bank = &s->bank[line_no >> 5];
3766 i = line_no & 31;
3767 if (((bank->sens_edge >> i) & 1) == INT_FALLING_EDGE)
3768 bank->irqs &= ~(1 << i);
3769@@ -256,7 +281,7 @@ static void omap_inth_write(void *opaque, target_phys_addr_t addr,
3770 struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
3771 int i, offset = addr - s->base;
3772 int bank_no = offset >> 8;
3773- struct omap_intr_handler_bank_s *bank = &s->banks[bank_no];
3774+ struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
3775 offset &= 0xff;
3776
3777 switch (offset) {
3778@@ -360,25 +385,31 @@ void omap_inth_reset(struct omap_intr_handler_s *s)
3779 int i;
3780
3781 for (i = 0; i < s->nbanks; ++i){
3782- s->banks[i].irqs = 0x00000000;
3783- s->banks[i].mask = 0xffffffff;
3784- s->banks[i].sens_edge = 0x00000000;
3785- s->banks[i].fiq = 0x00000000;
3786- s->banks[i].inputs = 0x00000000;
3787- memset(s->banks[i].priority, 0, sizeof(s->banks[i].priority));
3788+ s->bank[i].irqs = 0x00000000;
3789+ s->bank[i].mask = 0xffffffff;
3790+ s->bank[i].sens_edge = 0x00000000;
3791+ s->bank[i].fiq = 0x00000000;
3792+ s->bank[i].inputs = 0x00000000;
3793+ s->bank[i].swi = 0x00000000;
3794+ memset(s->bank[i].priority, 0, sizeof(s->bank[i].priority));
3795+
3796+ if (s->level_only)
3797+ s->bank[i].sens_edge = 0xffffffff;
3798 }
3799
3800 s->new_agr[0] = ~0;
3801 s->new_agr[1] = ~0;
3802 s->sir_intr[0] = 0;
3803 s->sir_intr[1] = 0;
3804+ s->autoidle = 0;
3805+ s->mask = ~0;
3806
3807 qemu_set_irq(s->parent_intr[0], 0);
3808 qemu_set_irq(s->parent_intr[1], 0);
3809 }
3810
3811 struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
3812- unsigned long size, unsigned char nbanks,
3813+ unsigned long size, unsigned char nbanks, qemu_irq **pins,
3814 qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk)
3815 {
3816 int iomemtype;
3817@@ -391,6 +422,8 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
3818 s->base = base;
3819 s->nbanks = nbanks;
3820 s->pins = qemu_allocate_irqs(omap_set_intr, s, nbanks * 32);
3821+ if (pins)
3822+ *pins = s->pins;
3823
3824 omap_inth_reset(s);
3825
3826@@ -401,6 +434,227 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
3827 return s;
3828 }
3829
3830+static uint32_t omap2_inth_read(void *opaque, target_phys_addr_t addr)
3831+{
3832+ struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
3833+ int offset = addr - s->base;
3834+ int bank_no, line_no;
3835+ struct omap_intr_handler_bank_s *bank = 0;
3836+
3837+ if ((offset & 0xf80) == 0x80) {
3838+ bank_no = (offset & 0x60) >> 5;
3839+ if (bank_no < s->nbanks) {
3840+ offset &= ~0x60;
3841+ bank = &s->bank[bank_no];
3842+ }
3843+ }
3844+
3845+ switch (offset) {
3846+ case 0x00: /* INTC_REVISION */
3847+ return 0x21;
3848+
3849+ case 0x10: /* INTC_SYSCONFIG */
3850+ return (s->autoidle >> 2) & 1;
3851+
3852+ case 0x14: /* INTC_SYSSTATUS */
3853+ return 1; /* RESETDONE */
3854+
3855+ case 0x40: /* INTC_SIR_IRQ */
3856+ return s->sir_intr[0];
3857+
3858+ case 0x44: /* INTC_SIR_FIQ */
3859+ return s->sir_intr[1];
3860+
3861+ case 0x48: /* INTC_CONTROL */
3862+ return (!s->mask) << 2; /* GLOBALMASK */
3863+
3864+ case 0x4c: /* INTC_PROTECTION */
3865+ return 0;
3866+
3867+ case 0x50: /* INTC_IDLE */
3868+ return s->autoidle & 3;
3869+
3870+ /* Per-bank registers */
3871+ case 0x80: /* INTC_ITR */
3872+ return bank->inputs;
3873+
3874+ case 0x84: /* INTC_MIR */
3875+ return bank->mask;
3876+
3877+ case 0x88: /* INTC_MIR_CLEAR */
3878+ case 0x8c: /* INTC_MIR_SET */
3879+ return 0;
3880+
3881+ case 0x90: /* INTC_ISR_SET */
3882+ return bank->swi;
3883+
3884+ case 0x94: /* INTC_ISR_CLEAR */
3885+ return 0;
3886+
3887+ case 0x98: /* INTC_PENDING_IRQ */
3888+ return bank->irqs & ~bank->mask & ~bank->fiq;
3889+
3890+ case 0x9c: /* INTC_PENDING_FIQ */
3891+ return bank->irqs & ~bank->mask & bank->fiq;
3892+
3893+ /* Per-line registers */
3894+ case 0x100 ... 0x300: /* INTC_ILR */
3895+ bank_no = (offset - 0x100) >> 7;
3896+ if (bank_no > s->nbanks)
3897+ break;
3898+ bank = &s->bank[bank_no];
3899+ line_no = (offset & 0x7f) >> 2;
3900+ return (bank->priority[line_no] << 2) |
3901+ ((bank->fiq >> line_no) & 1);
3902+ }
3903+ OMAP_BAD_REG(addr);
3904+ return 0;
3905+}
3906+
3907+static void omap2_inth_write(void *opaque, target_phys_addr_t addr,
3908+ uint32_t value)
3909+{
3910+ struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
3911+ int offset = addr - s->base;
3912+ int bank_no, line_no;
3913+ struct omap_intr_handler_bank_s *bank = 0;
3914+
3915+ if ((offset & 0xf80) == 0x80) {
3916+ bank_no = (offset & 0x60) >> 5;
3917+ if (bank_no < s->nbanks) {
3918+ offset &= ~0x60;
3919+ bank = &s->bank[bank_no];
3920+ }
3921+ }
3922+
3923+ switch (offset) {
3924+ case 0x10: /* INTC_SYSCONFIG */
3925+ s->autoidle &= 4;
3926+ s->autoidle |= (value & 1) << 2;
3927+ if (value & 2) /* SOFTRESET */
3928+ omap_inth_reset(s);
3929+ return;
3930+
3931+ case 0x48: /* INTC_CONTROL */
3932+ s->mask = (value & 4) ? 0 : ~0; /* GLOBALMASK */
3933+ if (value & 2) { /* NEWFIQAGR */
3934+ qemu_set_irq(s->parent_intr[1], 0);
3935+ s->new_agr[1] = ~0;
3936+ omap_inth_update(s, 1);
3937+ }
3938+ if (value & 1) { /* NEWIRQAGR */
3939+ qemu_set_irq(s->parent_intr[0], 0);
3940+ s->new_agr[0] = ~0;
3941+ omap_inth_update(s, 0);
3942+ }
3943+ return;
3944+
3945+ case 0x4c: /* INTC_PROTECTION */
3946+ /* TODO: Make a bitmap (or sizeof(char)map) of access privileges
3947+ * for every register, see Chapter 3 and 4 for privileged mode. */
3948+ if (value & 1)
3949+ fprintf(stderr, "%s: protection mode enable attempt\n",
3950+ __FUNCTION__);
3951+ return;
3952+
3953+ case 0x50: /* INTC_IDLE */
3954+ s->autoidle &= ~3;
3955+ s->autoidle |= value & 3;
3956+ return;
3957+
3958+ /* Per-bank registers */
3959+ case 0x84: /* INTC_MIR */
3960+ bank->mask = value;
3961+ omap_inth_update(s, 0);
3962+ omap_inth_update(s, 1);
3963+ return;
3964+
3965+ case 0x88: /* INTC_MIR_CLEAR */
3966+ bank->mask &= ~value;
3967+ omap_inth_update(s, 0);
3968+ omap_inth_update(s, 1);
3969+ return;
3970+
3971+ case 0x8c: /* INTC_MIR_SET */
3972+ bank->mask |= value;
3973+ return;
3974+
3975+ case 0x90: /* INTC_ISR_SET */
3976+ bank->irqs |= bank->swi |= value;
3977+ omap_inth_update(s, 0);
3978+ omap_inth_update(s, 1);
3979+ return;
3980+
3981+ case 0x94: /* INTC_ISR_CLEAR */
3982+ bank->swi &= ~value;
3983+ bank->irqs = bank->swi & bank->inputs;
3984+ return;
3985+
3986+ /* Per-line registers */
3987+ case 0x100 ... 0x300: /* INTC_ILR */
3988+ bank_no = (offset - 0x100) >> 7;
3989+ if (bank_no > s->nbanks)
3990+ break;
3991+ bank = &s->bank[bank_no];
3992+ line_no = (offset & 0x7f) >> 2;
3993+ bank->priority[line_no] = (value >> 2) & 0x3f;
3994+ bank->fiq &= ~(1 << line_no);
3995+ bank->fiq |= (value & 1) << line_no;
3996+ return;
3997+
3998+ case 0x00: /* INTC_REVISION */
3999+ case 0x14: /* INTC_SYSSTATUS */
4000+ case 0x40: /* INTC_SIR_IRQ */
4001+ case 0x44: /* INTC_SIR_FIQ */
4002+ case 0x80: /* INTC_ITR */
4003+ case 0x98: /* INTC_PENDING_IRQ */
4004+ case 0x9c: /* INTC_PENDING_FIQ */
4005+ OMAP_RO_REG(addr);
4006+ return;
4007+ }
4008+ OMAP_BAD_REG(addr);
4009+}
4010+
4011+static CPUReadMemoryFunc *omap2_inth_readfn[] = {
4012+ omap_badwidth_read32,
4013+ omap_badwidth_read32,
4014+ omap2_inth_read,
4015+};
4016+
4017+static CPUWriteMemoryFunc *omap2_inth_writefn[] = {
4018+ omap2_inth_write,
4019+ omap2_inth_write,
4020+ omap2_inth_write,
4021+};
4022+
4023+struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
4024+ int size, int nbanks, qemu_irq **pins,
4025+ qemu_irq parent_irq, qemu_irq parent_fiq,
4026+ omap_clk fclk, omap_clk iclk)
4027+{
4028+ int iomemtype;
4029+ struct omap_intr_handler_s *s = (struct omap_intr_handler_s *)
4030+ qemu_mallocz(sizeof(struct omap_intr_handler_s) +
4031+ sizeof(struct omap_intr_handler_bank_s) * nbanks);
4032+
4033+ s->parent_intr[0] = parent_irq;
4034+ s->parent_intr[1] = parent_fiq;
4035+ s->base = base;
4036+ s->nbanks = nbanks;
4037+ s->level_only = 1;
4038+ s->pins = qemu_allocate_irqs(omap_set_intr_noedge, s, nbanks * 32);
4039+ if (pins)
4040+ *pins = s->pins;
4041+
4042+ omap_inth_reset(s);
4043+
4044+ iomemtype = cpu_register_io_memory(0, omap2_inth_readfn,
4045+ omap2_inth_writefn, s);
4046+ cpu_register_physical_memory(s->base, size, iomemtype);
4047+
4048+ return s;
4049+}
4050+
4051 /* MPU OS timers */
4052 struct omap_mpu_timer_s {
4053 qemu_irq irq;
4054@@ -1289,6 +1543,8 @@ static uint32_t omap_id_read(void *opaque, target_phys_addr_t addr)
4055 return 0x03310315;
4056 case omap1510:
4057 return 0x03310115;
4058+ default:
4059+ cpu_abort(cpu_single_env, "%s: bad mpu model\n", __FUNCTION__);
4060 }
4061 break;
4062
4063@@ -1298,6 +1554,8 @@ static uint32_t omap_id_read(void *opaque, target_phys_addr_t addr)
4064 return 0xfb57402f;
4065 case omap1510:
4066 return 0xfb47002f;
4067+ default:
4068+ cpu_abort(cpu_single_env, "%s: bad mpu model\n", __FUNCTION__);
4069 }
4070 break;
4071 }
4072@@ -1722,19 +1980,116 @@ static void omap_dpll_init(struct dpll_ctl_s *s, target_phys_addr_t base,
4073 /* UARTs */
4074 struct omap_uart_s {
4075 SerialState *serial; /* TODO */
4076+ struct omap_target_agent_s *ta;
4077+ target_phys_addr_t base;
4078+
4079+ uint8_t eblr;
4080+ uint8_t syscontrol;
4081+ uint8_t wkup;
4082+ uint8_t cfps;
4083 };
4084
4085-static void omap_uart_reset(struct omap_uart_s *s)
4086+void omap_uart_reset(struct omap_uart_s *s)
4087 {
4088+ s->eblr = 0x00;
4089+ s->syscontrol = 0;
4090+ s->wkup = 0x3f;
4091+ s->cfps = 0x69;
4092 }
4093
4094 struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
4095- qemu_irq irq, omap_clk clk, CharDriverState *chr)
4096+ qemu_irq irq, omap_clk fclk, omap_clk iclk,
4097+ qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr)
4098 {
4099 struct omap_uart_s *s = (struct omap_uart_s *)
4100 qemu_mallocz(sizeof(struct omap_uart_s));
4101- if (chr)
4102- s->serial = serial_mm_init(base, 2, irq, chr, 1);
4103+
4104+ s->serial = serial_mm_init(base, 2, irq, chr ?: qemu_chr_open("null"), 1);
4105+
4106+ return s;
4107+}
4108+
4109+static uint32_t omap_uart_read(void *opaque, target_phys_addr_t addr)
4110+{
4111+ struct omap_uart_s *s = (struct omap_uart_s *) opaque;
4112+ int offset = addr - s->base;
4113+
4114+ switch (offset) {
4115+ case 0x48: /* EBLR */
4116+ return s->eblr;
4117+ case 0x50: /* MVR */
4118+ return 0x30;
4119+ case 0x54: /* SYSC */
4120+ return s->syscontrol;
4121+ case 0x58: /* SYSS */
4122+ return 1;
4123+ case 0x5c: /* WER */
4124+ return s->wkup;
4125+ case 0x60: /* CFPS */
4126+ return s->cfps;
4127+ }
4128+
4129+ OMAP_BAD_REG(addr);
4130+ return 0;
4131+}
4132+
4133+static void omap_uart_write(void *opaque, target_phys_addr_t addr,
4134+ uint32_t value)
4135+{
4136+ struct omap_uart_s *s = (struct omap_uart_s *) opaque;
4137+ int offset = addr - s->base;
4138+
4139+ switch (offset) {
4140+ case 0x48: /* EBLR */
4141+ s->eblr = value & 0xff;
4142+ break;
4143+ case 0x50: /* MVR */
4144+ case 0x58: /* SYSS */
4145+ OMAP_RO_REG(addr);
4146+ break;
4147+ case 0x54: /* SYSC */
4148+ s->syscontrol = value & 0x1d;
4149+ if (value & 2)
4150+ omap_uart_reset(s);
4151+ break;
4152+ case 0x5c: /* WER */
4153+ s->wkup = value & 0x7f;
4154+ break;
4155+ case 0x60: /* CFPS */
4156+ s->cfps = value & 0xff;
4157+ break;
4158+ default:
4159+ OMAP_BAD_REG(addr);
4160+ }
4161+}
4162+
4163+static CPUReadMemoryFunc *omap_uart_readfn[] = {
4164+ omap_uart_read,
4165+ omap_uart_read,
4166+ omap_badwidth_read8,
4167+};
4168+
4169+static CPUWriteMemoryFunc *omap_uart_writefn[] = {
4170+ omap_uart_write,
4171+ omap_uart_write,
4172+ omap_badwidth_write8,
4173+};
4174+
4175+struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
4176+ qemu_irq irq, omap_clk fclk, omap_clk iclk,
4177+ qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr)
4178+{
4179+ target_phys_addr_t base = omap_l4_attach(ta, 0, 0);
4180+ struct omap_uart_s *s = omap_uart_init(base, irq,
4181+ fclk, iclk, txdma, rxdma, chr);
4182+ int iomemtype = cpu_register_io_memory(0, omap_uart_readfn,
4183+ omap_uart_writefn, s);
4184+
4185+ s->ta = ta;
4186+ s->base = base;
4187+
4188+ cpu_register_physical_memory(s->base + 0x20, 0x100, iomemtype);
4189+
4190 return s;
4191 }
4192
4193@@ -2778,9 +3133,11 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
4194 void omap_uwire_attach(struct omap_uwire_s *s,
4195 struct uwire_slave_s *slave, int chipselect)
4196 {
4197- if (chipselect < 0 || chipselect > 3)
4198- cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n", __FUNCTION__,
4199- chipselect);
4200+ if (chipselect < 0 || chipselect > 3) {
4201+ fprintf(stderr, "%s: Bad chipselect %i\n",
4202+ __FUNCTION__, chipselect);
4203+ exit(-1);
4204+ }
4205
4206 s->chip[chipselect] = slave;
4207 }
4208@@ -4123,7 +4481,7 @@ static void omap_setup_mpui_io(struct omap_mpu_state_s *mpu)
4209 }
4210
4211 /* General chip reset */
4212-static void omap_mpu_reset(void *opaque)
4213+static void omap1_mpu_reset(void *opaque)
4214 {
4215 struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
4216
4217@@ -4153,7 +4511,7 @@ static void omap_mpu_reset(void *opaque)
4218 omap_uwire_reset(mpu->microwire);
4219 omap_pwl_reset(mpu);
4220 omap_pwt_reset(mpu);
4221- omap_i2c_reset(mpu->i2c);
4222+ omap_i2c_reset(mpu->i2c[0]);
4223 omap_rtc_reset(mpu->rtc);
4224 omap_mcbsp_reset(mpu->mcbsp1);
4225 omap_mcbsp_reset(mpu->mcbsp2);
4226@@ -4205,7 +4563,7 @@ static void omap_setup_dsp_mapping(const struct omap_map_s *map)
4227 }
4228 }
4229
4230-static void omap_mpu_wakeup(void *opaque, int irq, int req)
4231+void omap_mpu_wakeup(void *opaque, int irq, int req)
4232 {
4233 struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
4234
4235@@ -4213,7 +4571,7 @@ static void omap_mpu_wakeup(void *opaque, int irq, int req)
4236 cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
4237 }
4238
4239-static const struct dma_irq_map omap_dma_irq_map[] = {
4240+static const struct dma_irq_map omap1_dma_irq_map[] = {
4241 { 0, OMAP_INT_DMA_CH0_6 },
4242 { 0, OMAP_INT_DMA_CH1_7 },
4243 { 0, OMAP_INT_DMA_CH2_8 },
4244@@ -4307,17 +4665,16 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
4245 omap_clkm_init(0xfffece00, 0xe1008000, s);
4246
4247 cpu_irq = arm_pic_init_cpu(s->env);
4248- s->ih[0] = omap_inth_init(0xfffecb00, 0x100, 1,
4249+ s->ih[0] = omap_inth_init(0xfffecb00, 0x100, 1, &s->irq[0],
4250 cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ],
4251 omap_findclk(s, "arminth_ck"));
4252- s->ih[1] = omap_inth_init(0xfffe0000, 0x800, 1,
4253+ s->ih[1] = omap_inth_init(0xfffe0000, 0x800, 1, &s->irq[1],
4254 s->ih[0]->pins[OMAP_INT_15XX_IH2_IRQ], NULL,
4255 omap_findclk(s, "arminth_ck"));
4256- s->irq[0] = s->ih[0]->pins;
4257- s->irq[1] = s->ih[1]->pins;
4258
4259 for (i = 0; i < 6; i ++)
4260- dma_irqs[i] = s->irq[omap_dma_irq_map[i].ih][omap_dma_irq_map[i].intr];
4261+ dma_irqs[i] =
4262+ s->irq[omap1_dma_irq_map[i].ih][omap1_dma_irq_map[i].intr];
4263 s->dma = omap_dma_init(0xfffed800, dma_irqs, s->irq[0][OMAP_INT_DMA_LCD],
4264 s, omap_findclk(s, "dma_ck"), omap_dma_3_1);
4265
4266@@ -4367,12 +4724,18 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
4267
4268 s->uart[0] = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1],
4269 omap_findclk(s, "uart1_ck"),
4270+ omap_findclk(s, "uart1_ck"),
4271+ s->drq[OMAP_DMA_UART1_TX], s->drq[OMAP_DMA_UART1_RX],
4272 serial_hds[0]);
4273 s->uart[1] = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2],
4274 omap_findclk(s, "uart2_ck"),
4275+ omap_findclk(s, "uart2_ck"),
4276+ s->drq[OMAP_DMA_UART2_TX], s->drq[OMAP_DMA_UART2_RX],
4277 serial_hds[0] ? serial_hds[1] : 0);
4278 s->uart[2] = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3],
4279 omap_findclk(s, "uart3_ck"),
4280+ omap_findclk(s, "uart3_ck"),
4281+ s->drq[OMAP_DMA_UART3_TX], s->drq[OMAP_DMA_UART3_RX],
4282 serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0);
4283
4284 omap_dpll_init(&s->dpll[0], 0xfffecf00, omap_findclk(s, "dpll1"));
4285@@ -4401,7 +4764,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
4286 omap_pwl_init(0xfffb5800, s, omap_findclk(s, "armxor_ck"));
4287 omap_pwt_init(0xfffb6000, s, omap_findclk(s, "armxor_ck"));
4288
4289- s->i2c = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C],
4290+ s->i2c[0] = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C],
4291 &s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck"));
4292
4293 s->rtc = omap_rtc_init(0xfffb4800, &s->irq[1][OMAP_INT_RTC_TIMER],
4294@@ -4435,7 +4798,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
4295 omap_setup_dsp_mapping(omap15xx_dsp_mm);
4296 omap_setup_mpui_io(s);
4297
4298- qemu_register_reset(omap_mpu_reset, s);
4299+ qemu_register_reset(omap1_mpu_reset, s);
4300
4301 return s;
4302 }
4303diff --git a/hw/omap2.c b/hw/omap2.c
4304new file mode 100644
4305index 0000000..1e51197
4306--- /dev/null
4307+++ b/hw/omap2.c
4308@@ -0,0 +1,3872 @@
4309+/*
4310+ * TI OMAP processors emulation.
4311+ *
4312+ * Copyright (C) 2007-2008 Nokia Corporation
4313+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
4314+ *
4315+ * This program is free software; you can redistribute it and/or
4316+ * modify it under the terms of the GNU General Public License as
4317+ * published by the Free Software Foundation; either version 2 of
4318+ * the License, or (at your option) any later version.
4319+ *
4320+ * This program is distributed in the hope that it will be useful,
4321+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4322+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4323+ * GNU General Public License for more details.
4324+ *
4325+ * You should have received a copy of the GNU General Public License
4326+ * along with this program; if not, write to the Free Software
4327+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
4328+ * MA 02111-1307 USA
4329+ */
4330+#include "hw.h"
4331+#include "arm-misc.h"
4332+#include "omap.h"
4333+#include "sysemu.h"
4334+#include "qemu-timer.h"
4335+#include "qemu-char.h"
4336+#include "flash.h"
4337+/* We use pc-style serial ports. */
4338+#include "pc.h"
4339+
4340+/* GP timers */
4341+struct omap_gp_timer_s {
4342+ qemu_irq irq;
4343+ qemu_irq wkup;
4344+ qemu_irq in;
4345+ qemu_irq out;
4346+ omap_clk clk;
4347+ target_phys_addr_t base;
4348+ QEMUTimer *timer;
4349+ QEMUTimer *match;
4350+ struct omap_target_agent_s *ta;
4351+
4352+ int in_val;
4353+ int out_val;
4354+ int64_t time;
4355+ int64_t rate;
4356+ int64_t ticks_per_sec;
4357+
4358+ int16_t config;
4359+ int status;
4360+ int it_ena;
4361+ int wu_ena;
4362+ int enable;
4363+ int inout;
4364+ int capt2;
4365+ int pt;
4366+ enum {
4367+ gpt_trigger_none, gpt_trigger_overflow, gpt_trigger_both
4368+ } trigger;
4369+ enum {
4370+ gpt_capture_none, gpt_capture_rising,
4371+ gpt_capture_falling, gpt_capture_both
4372+ } capture;
4373+ int scpwm;
4374+ int ce;
4375+ int pre;
4376+ int ptv;
4377+ int ar;
4378+ int st;
4379+ int posted;
4380+ uint32_t val;
4381+ uint32_t load_val;
4382+ uint32_t capture_val[2];
4383+ uint32_t match_val;
4384+ int capt_num;
4385+
4386+ uint16_t writeh; /* LSB */
4387+ uint16_t readh; /* MSB */
4388+};
4389+
4390+#define GPT_TCAR_IT (1 << 2)
4391+#define GPT_OVF_IT (1 << 1)
4392+#define GPT_MAT_IT (1 << 0)
4393+
4394+static inline void omap_gp_timer_intr(struct omap_gp_timer_s *timer, int it)
4395+{
4396+ if (timer->it_ena & it) {
4397+ if (!timer->status)
4398+ qemu_irq_raise(timer->irq);
4399+
4400+ timer->status |= it;
4401+ /* Or are the status bits set even when masked?
4402+ * i.e. is masking applied before or after the status register? */
4403+ }
4404+
4405+ if (timer->wu_ena & it)
4406+ qemu_irq_pulse(timer->wkup);
4407+}
4408+
4409+static inline void omap_gp_timer_out(struct omap_gp_timer_s *timer, int level)
4410+{
4411+ if (!timer->inout && timer->out_val != level) {
4412+ timer->out_val = level;
4413+ qemu_set_irq(timer->out, level);
4414+ }
4415+}
4416+
4417+static inline uint32_t omap_gp_timer_read(struct omap_gp_timer_s *timer)
4418+{
4419+ uint64_t distance;
4420+
4421+ if (timer->st && timer->rate) {
4422+ distance = qemu_get_clock(vm_clock) - timer->time;
4423+ distance = muldiv64(distance, timer->rate, timer->ticks_per_sec);
4424+
4425+ if (distance >= 0xffffffff - timer->val)
4426+ return 0xffffffff;
4427+ else
4428+ return timer->val + distance;
4429+ } else
4430+ return timer->val;
4431+}
4432+
4433+static inline void omap_gp_timer_sync(struct omap_gp_timer_s *timer)
4434+{
4435+ if (timer->st) {
4436+ timer->val = omap_gp_timer_read(timer);
4437+ timer->time = qemu_get_clock(vm_clock);
4438+ }
4439+}
4440+
4441+static inline void omap_gp_timer_update(struct omap_gp_timer_s *timer)
4442+{
4443+ int64_t expires, matches;
4444+
4445+ if (timer->st && timer->rate) {
4446+ expires = muldiv64(0x100000000ll - timer->val,
4447+ timer->ticks_per_sec, timer->rate);
4448+ qemu_mod_timer(timer->timer, timer->time + expires);
4449+
4450+ if (timer->ce && timer->match_val >= timer->val) {
4451+ matches = muldiv64(timer->match_val - timer->val,
4452+ timer->ticks_per_sec, timer->rate);
4453+ qemu_mod_timer(timer->match, timer->time + matches);
4454+ } else
4455+ qemu_del_timer(timer->match);
4456+ } else {
4457+ qemu_del_timer(timer->timer);
4458+ qemu_del_timer(timer->match);
4459+ omap_gp_timer_out(timer, timer->scpwm);
4460+ }
4461+}
4462+
4463+static inline void omap_gp_timer_trigger(struct omap_gp_timer_s *timer)
4464+{
4465+ if (timer->pt)
4466+ /* TODO in overflow-and-match mode if the first event to
4467+ * occurs is the match, don't toggle. */
4468+ omap_gp_timer_out(timer, !timer->out_val);
4469+ else
4470+ /* TODO inverted pulse on timer->out_val == 1? */
4471+ qemu_irq_pulse(timer->out);
4472+}
4473+
4474+static void omap_gp_timer_tick(void *opaque)
4475+{
4476+ struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
4477+
4478+ if (!timer->ar) {
4479+ timer->st = 0;
4480+ timer->val = 0;
4481+ } else {
4482+ timer->val = timer->load_val;
4483+ timer->time = qemu_get_clock(vm_clock);
4484+ }
4485+
4486+ if (timer->trigger == gpt_trigger_overflow ||
4487+ timer->trigger == gpt_trigger_both)
4488+ omap_gp_timer_trigger(timer);
4489+
4490+ omap_gp_timer_intr(timer, GPT_OVF_IT);
4491+ omap_gp_timer_update(timer);
4492+}
4493+
4494+static void omap_gp_timer_match(void *opaque)
4495+{
4496+ struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
4497+
4498+ if (timer->trigger == gpt_trigger_both)
4499+ omap_gp_timer_trigger(timer);
4500+
4501+ omap_gp_timer_intr(timer, GPT_MAT_IT);
4502+}
4503+
4504+static void omap_gp_timer_input(void *opaque, int line, int on)
4505+{
4506+ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
4507+ int trigger;
4508+
4509+ switch (s->capture) {
4510+ default:
4511+ case gpt_capture_none:
4512+ trigger = 0;
4513+ break;
4514+ case gpt_capture_rising:
4515+ trigger = !s->in_val && on;
4516+ break;
4517+ case gpt_capture_falling:
4518+ trigger = s->in_val && !on;
4519+ break;
4520+ case gpt_capture_both:
4521+ trigger = (s->in_val == !on);
4522+ break;
4523+ }
4524+ s->in_val = on;
4525+
4526+ if (s->inout && trigger && s->capt_num < 2) {
4527+ s->capture_val[s->capt_num] = omap_gp_timer_read(s);
4528+
4529+ if (s->capt2 == s->capt_num ++)
4530+ omap_gp_timer_intr(s, GPT_TCAR_IT);
4531+ }
4532+}
4533+
4534+static void omap_gp_timer_clk_update(void *opaque, int line, int on)
4535+{
4536+ struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
4537+
4538+ omap_gp_timer_sync(timer);
4539+ timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
4540+ omap_gp_timer_update(timer);
4541+}
4542+
4543+static void omap_gp_timer_clk_setup(struct omap_gp_timer_s *timer)
4544+{
4545+ omap_clk_adduser(timer->clk,
4546+ qemu_allocate_irqs(omap_gp_timer_clk_update, timer, 1)[0]);
4547+ timer->rate = omap_clk_getrate(timer->clk);
4548+}
4549+
4550+static void omap_gp_timer_reset(struct omap_gp_timer_s *s)
4551+{
4552+ s->config = 0x000;
4553+ s->status = 0;
4554+ s->it_ena = 0;
4555+ s->wu_ena = 0;
4556+ s->inout = 0;
4557+ s->capt2 = 0;
4558+ s->capt_num = 0;
4559+ s->pt = 0;
4560+ s->trigger = gpt_trigger_none;
4561+ s->capture = gpt_capture_none;
4562+ s->scpwm = 0;
4563+ s->ce = 0;
4564+ s->pre = 0;
4565+ s->ptv = 0;
4566+ s->ar = 0;
4567+ s->st = 0;
4568+ s->posted = 1;
4569+ s->val = 0x00000000;
4570+ s->load_val = 0x00000000;
4571+ s->capture_val[0] = 0x00000000;
4572+ s->capture_val[1] = 0x00000000;
4573+ s->match_val = 0x00000000;
4574+ omap_gp_timer_update(s);
4575+}
4576+
4577+static uint32_t omap_gp_timer_readw(void *opaque, target_phys_addr_t addr)
4578+{
4579+ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
4580+ int offset = addr - s->base;
4581+
4582+ switch (offset) {
4583+ case 0x00: /* TIDR */
4584+ return 0x21;
4585+
4586+ case 0x10: /* TIOCP_CFG */
4587+ return s->config;
4588+
4589+ case 0x14: /* TISTAT */
4590+ /* ??? When's this bit reset? */
4591+ return 1; /* RESETDONE */
4592+
4593+ case 0x18: /* TISR */
4594+ return s->status;
4595+
4596+ case 0x1c: /* TIER */
4597+ return s->it_ena;
4598+
4599+ case 0x20: /* TWER */
4600+ return s->wu_ena;
4601+
4602+ case 0x24: /* TCLR */
4603+ return (s->inout << 14) |
4604+ (s->capt2 << 13) |
4605+ (s->pt << 12) |
4606+ (s->trigger << 10) |
4607+ (s->capture << 8) |
4608+ (s->scpwm << 7) |
4609+ (s->ce << 6) |
4610+ (s->pre << 5) |
4611+ (s->ptv << 2) |
4612+ (s->ar << 1) |
4613+ (s->st << 0);
4614+
4615+ case 0x28: /* TCRR */
4616+ return omap_gp_timer_read(s);
4617+
4618+ case 0x2c: /* TLDR */
4619+ return s->load_val;
4620+
4621+ case 0x30: /* TTGR */
4622+ return 0xffffffff;
4623+
4624+ case 0x34: /* TWPS */
4625+ return 0x00000000; /* No posted writes pending. */
4626+
4627+ case 0x38: /* TMAR */
4628+ return s->match_val;
4629+
4630+ case 0x3c: /* TCAR1 */
4631+ return s->capture_val[0];
4632+
4633+ case 0x40: /* TSICR */
4634+ return s->posted << 2;
4635+
4636+ case 0x44: /* TCAR2 */
4637+ return s->capture_val[1];
4638+ }
4639+
4640+ OMAP_BAD_REG(addr);
4641+ return 0;
4642+}
4643+
4644+static uint32_t omap_gp_timer_readh(void *opaque, target_phys_addr_t addr)
4645+{
4646+ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
4647+ uint32_t ret;
4648+
4649+ if (addr & 2)
4650+ return s->readh;
4651+ else {
4652+ ret = omap_gp_timer_readw(opaque, addr);
4653+ s->readh = ret >> 16;
4654+ return ret & 0xffff;
4655+ }
4656+}
4657+
4658+static CPUReadMemoryFunc *omap_gp_timer_readfn[] = {
4659+ omap_badwidth_read32,
4660+ omap_gp_timer_readh,
4661+ omap_gp_timer_readw,
4662+};
4663+
4664+static void omap_gp_timer_write(void *opaque, target_phys_addr_t addr,
4665+ uint32_t value)
4666+{
4667+ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
4668+ int offset = addr - s->base;
4669+
4670+ switch (offset) {
4671+ case 0x00: /* TIDR */
4672+ case 0x14: /* TISTAT */
4673+ case 0x34: /* TWPS */
4674+ case 0x3c: /* TCAR1 */
4675+ case 0x44: /* TCAR2 */
4676+ OMAP_RO_REG(addr);
4677+ break;
4678+
4679+ case 0x10: /* TIOCP_CFG */
4680+ s->config = value & 0x33d;
4681+ if (((value >> 3) & 3) == 3) /* IDLEMODE */
4682+ fprintf(stderr, "%s: illegal IDLEMODE value in TIOCP_CFG\n",
4683+ __FUNCTION__);
4684+ if (value & 2) /* SOFTRESET */
4685+ omap_gp_timer_reset(s);
4686+ break;
4687+
4688+ case 0x18: /* TISR */
4689+ if (value & GPT_TCAR_IT)
4690+ s->capt_num = 0;
4691+ if (s->status && !(s->status &= ~value))
4692+ qemu_irq_lower(s->irq);
4693+ break;
4694+
4695+ case 0x1c: /* TIER */
4696+ s->it_ena = value & 7;
4697+ break;
4698+
4699+ case 0x20: /* TWER */
4700+ s->wu_ena = value & 7;
4701+ break;
4702+
4703+ case 0x24: /* TCLR */
4704+ omap_gp_timer_sync(s);
4705+ s->inout = (value >> 14) & 1;
4706+ s->capt2 = (value >> 13) & 1;
4707+ s->pt = (value >> 12) & 1;
4708+ s->trigger = (value >> 10) & 3;
4709+ if (s->capture == gpt_capture_none &&
4710+ ((value >> 8) & 3) != gpt_capture_none)
4711+ s->capt_num = 0;
4712+ s->capture = (value >> 8) & 3;
4713+ s->scpwm = (value >> 7) & 1;
4714+ s->ce = (value >> 6) & 1;
4715+ s->pre = (value >> 5) & 1;
4716+ s->ptv = (value >> 2) & 7;
4717+ s->ar = (value >> 1) & 1;
4718+ s->st = (value >> 0) & 1;
4719+ if (s->inout && s->trigger != gpt_trigger_none)
4720+ fprintf(stderr, "%s: GP timer pin must be an output "
4721+ "for this trigger mode\n", __FUNCTION__);
4722+ if (!s->inout && s->capture != gpt_capture_none)
4723+ fprintf(stderr, "%s: GP timer pin must be an input "
4724+ "for this capture mode\n", __FUNCTION__);
4725+ if (s->trigger == gpt_trigger_none)
4726+ omap_gp_timer_out(s, s->scpwm);
4727+ /* TODO: make sure this doesn't overflow 32-bits */
4728+ s->ticks_per_sec = ticks_per_sec << (s->pre ? s->ptv + 1 : 0);
4729+ omap_gp_timer_update(s);
4730+ break;
4731+
4732+ case 0x28: /* TCRR */
4733+ s->time = qemu_get_clock(vm_clock);
4734+ s->val = value;
4735+ omap_gp_timer_update(s);
4736+ break;
4737+
4738+ case 0x2c: /* TLDR */
4739+ s->load_val = value;
4740+ break;
4741+
4742+ case 0x30: /* TTGR */
4743+ s->time = qemu_get_clock(vm_clock);
4744+ s->val = s->load_val;
4745+ omap_gp_timer_update(s);
4746+ break;
4747+
4748+ case 0x38: /* TMAR */
4749+ omap_gp_timer_sync(s);
4750+ s->match_val = value;
4751+ omap_gp_timer_update(s);
4752+ break;
4753+
4754+ case 0x40: /* TSICR */
4755+ s->posted = (value >> 2) & 1;
4756+ if (value & 2) /* How much exactly are we supposed to reset? */
4757+ omap_gp_timer_reset(s);
4758+ break;
4759+
4760+ default:
4761+ OMAP_BAD_REG(addr);
4762+ }
4763+}
4764+
4765+static void omap_gp_timer_writeh(void *opaque, target_phys_addr_t addr,
4766+ uint32_t value)
4767+{
4768+ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
4769+
4770+ if (addr & 2)
4771+ return omap_gp_timer_write(opaque, addr, (value << 16) | s->writeh);
4772+ else
4773+ s->writeh = (uint16_t) value;
4774+}
4775+
4776+static CPUWriteMemoryFunc *omap_gp_timer_writefn[] = {
4777+ omap_badwidth_write32,
4778+ omap_gp_timer_writeh,
4779+ omap_gp_timer_write,
4780+};
4781+
4782+struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
4783+ qemu_irq irq, omap_clk fclk, omap_clk iclk)
4784+{
4785+ int iomemtype;
4786+ struct omap_gp_timer_s *s = (struct omap_gp_timer_s *)
4787+ qemu_mallocz(sizeof(struct omap_gp_timer_s));
4788+
4789+ s->ta = ta;
4790+ s->irq = irq;
4791+ s->clk = fclk;
4792+ s->timer = qemu_new_timer(vm_clock, omap_gp_timer_tick, s);
4793+ s->match = qemu_new_timer(vm_clock, omap_gp_timer_match, s);
4794+ s->in = qemu_allocate_irqs(omap_gp_timer_input, s, 1)[0];
4795+ omap_gp_timer_reset(s);
4796+ omap_gp_timer_clk_setup(s);
4797+
4798+ iomemtype = cpu_register_io_memory(0, omap_gp_timer_readfn,
4799+ omap_gp_timer_writefn, s);
4800+ s->base = omap_l4_attach(ta, 0, iomemtype);
4801+
4802+ return s;
4803+}
4804+
4805+/* 32-kHz Sync Timer of the OMAP2 */
4806+static uint32_t omap_synctimer_read(struct omap_synctimer_s *s) {
4807+ return muldiv64(qemu_get_clock(vm_clock), 0x8000, ticks_per_sec);
4808+}
4809+
4810+static void omap_synctimer_reset(struct omap_synctimer_s *s)
4811+{
4812+ s->val = omap_synctimer_read(s);
4813+}
4814+
4815+static uint32_t omap_synctimer_readw(void *opaque, target_phys_addr_t addr)
4816+{
4817+ struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
4818+ int offset = addr - s->base;
4819+
4820+ switch (offset) {
4821+ case 0x00: /* 32KSYNCNT_REV */
4822+ return 0x21;
4823+
4824+ case 0x10: /* CR */
4825+ return omap_synctimer_read(s) - s->val;
4826+ }
4827+
4828+ OMAP_BAD_REG(addr);
4829+ return 0;
4830+}
4831+
4832+static uint32_t omap_synctimer_readh(void *opaque, target_phys_addr_t addr)
4833+{
4834+ struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
4835+ uint32_t ret;
4836+
4837+ if (addr & 2)
4838+ return s->readh;
4839+ else {
4840+ ret = omap_synctimer_readw(opaque, addr);
4841+ s->readh = ret >> 16;
4842+ return ret & 0xffff;
4843+ }
4844+}
4845+
4846+static CPUReadMemoryFunc *omap_synctimer_readfn[] = {
4847+ omap_badwidth_read32,
4848+ omap_synctimer_readh,
4849+ omap_synctimer_readw,
4850+};
4851+
4852+static void omap_synctimer_write(void *opaque, target_phys_addr_t addr,
4853+ uint32_t value)
4854+{
4855+ OMAP_BAD_REG(addr);
4856+}
4857+
4858+static CPUWriteMemoryFunc *omap_synctimer_writefn[] = {
4859+ omap_badwidth_write32,
4860+ omap_synctimer_write,
4861+ omap_synctimer_write,
4862+};
4863+
4864+void omap_synctimer_init(struct omap_target_agent_s *ta,
4865+ struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk)
4866+{
4867+ struct omap_synctimer_s *s = &mpu->synctimer;
4868+
4869+ omap_synctimer_reset(s);
4870+ s->base = omap_l4_attach(ta, 0, cpu_register_io_memory(0,
4871+ omap_synctimer_readfn, omap_synctimer_writefn, s));
4872+}
4873+
4874+/* General-Purpose Interface of OMAP2 */
4875+struct omap2_gpio_s {
4876+ target_phys_addr_t base;
4877+ qemu_irq irq[2];
4878+ qemu_irq wkup;
4879+ qemu_irq *in;
4880+ qemu_irq handler[32];
4881+
4882+ uint8_t config[2];
4883+ uint32_t inputs;
4884+ uint32_t outputs;
4885+ uint32_t dir;
4886+ uint32_t level[2];
4887+ uint32_t edge[2];
4888+ uint32_t mask[2];
4889+ uint32_t wumask;
4890+ uint32_t ints[2];
4891+ uint32_t debounce;
4892+ uint8_t delay;
4893+};
4894+
4895+static inline void omap_gpio_module_int_update(struct omap2_gpio_s *s,
4896+ int line)
4897+{
4898+ qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
4899+}
4900+
4901+static void omap_gpio_module_wake(struct omap2_gpio_s *s, int line)
4902+{
4903+ if (!(s->config[0] & (1 << 2))) /* ENAWAKEUP */
4904+ return;
4905+ if (!(s->config[0] & (3 << 3))) /* Force Idle */
4906+ return;
4907+ if (!(s->wumask & (1 << line)))
4908+ return;
4909+
4910+ qemu_irq_raise(s->wkup);
4911+}
4912+
4913+static inline void omap_gpio_module_out_update(struct omap2_gpio_s *s,
4914+ uint32_t diff)
4915+{
4916+ int ln;
4917+
4918+ s->outputs ^= diff;
4919+ diff &= ~s->dir;
4920+ while ((ln = ffs(diff))) {
4921+ ln --;
4922+ qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1);
4923+ diff &= ~(1 << ln);
4924+ }
4925+}
4926+
4927+static void omap_gpio_module_level_update(struct omap2_gpio_s *s, int line)
4928+{
4929+ s->ints[line] |= s->dir &
4930+ ((s->inputs & s->level[1]) | (~s->inputs & s->level[0]));
4931+ omap_gpio_module_int_update(s, line);
4932+}
4933+
4934+static inline void omap_gpio_module_int(struct omap2_gpio_s *s, int line)
4935+{
4936+ s->ints[0] |= 1 << line;
4937+ omap_gpio_module_int_update(s, 0);
4938+ s->ints[1] |= 1 << line;
4939+ omap_gpio_module_int_update(s, 1);
4940+ omap_gpio_module_wake(s, line);
4941+}
4942+
4943+static void omap_gpio_module_set(void *opaque, int line, int level)
4944+{
4945+ struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
4946+
4947+ if (level) {
4948+ if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
4949+ omap_gpio_module_int(s, line);
4950+ s->inputs |= 1 << line;
4951+ } else {
4952+ if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0]))
4953+ omap_gpio_module_int(s, line);
4954+ s->inputs &= ~(1 << line);
4955+ }
4956+}
4957+
4958+static void omap_gpio_module_reset(struct omap2_gpio_s *s)
4959+{
4960+ s->config[0] = 0;
4961+ s->config[1] = 2;
4962+ s->ints[0] = 0;
4963+ s->ints[1] = 0;
4964+ s->mask[0] = 0;
4965+ s->mask[1] = 0;
4966+ s->wumask = 0;
4967+ s->dir = ~0;
4968+ s->level[0] = 0;
4969+ s->level[1] = 0;
4970+ s->edge[0] = 0;
4971+ s->edge[1] = 0;
4972+ s->debounce = 0;
4973+ s->delay = 0;
4974+}
4975+
4976+static uint32_t omap_gpio_module_read(void *opaque, target_phys_addr_t addr)
4977+{
4978+ struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
4979+ int offset = addr - s->base;
4980+
4981+ switch (offset) {
4982+ case 0x00: /* GPIO_REVISION */
4983+ return 0x18;
4984+
4985+ case 0x10: /* GPIO_SYSCONFIG */
4986+ return s->config[0];
4987+
4988+ case 0x14: /* GPIO_SYSSTATUS */
4989+ return 0x01;
4990+
4991+ case 0x18: /* GPIO_IRQSTATUS1 */
4992+ return s->ints[0];
4993+
4994+ case 0x1c: /* GPIO_IRQENABLE1 */
4995+ case 0x60: /* GPIO_CLEARIRQENABLE1 */
4996+ case 0x64: /* GPIO_SETIRQENABLE1 */
4997+ return s->mask[0];
4998+
4999+ case 0x20: /* GPIO_WAKEUPENABLE */
5000+ case 0x80: /* GPIO_CLEARWKUENA */
5001+ case 0x84: /* GPIO_SETWKUENA */
5002+ return s->wumask;
5003+
5004+ case 0x28: /* GPIO_IRQSTATUS2 */
5005+ return s->ints[1];
5006+
5007+ case 0x2c: /* GPIO_IRQENABLE2 */
5008+ case 0x70: /* GPIO_CLEARIRQENABLE2 */
5009+ case 0x74: /* GPIO_SETIREQNEABLE2 */
5010+ return s->mask[1];
5011+
5012+ case 0x30: /* GPIO_CTRL */
5013+ return s->config[1];
5014+
5015+ case 0x34: /* GPIO_OE */
5016+ return s->dir;
5017+
5018+ case 0x38: /* GPIO_DATAIN */
5019+ return s->inputs;
5020+
5021+ case 0x3c: /* GPIO_DATAOUT */
5022+ case 0x90: /* GPIO_CLEARDATAOUT */
5023+ case 0x94: /* GPIO_SETDATAOUT */
5024+ return s->outputs;
5025+
5026+ case 0x40: /* GPIO_LEVELDETECT0 */
5027+ return s->level[0];
5028+
5029+ case 0x44: /* GPIO_LEVELDETECT1 */
5030+ return s->level[1];
5031+
5032+ case 0x48: /* GPIO_RISINGDETECT */
5033+ return s->edge[0];
5034+
5035+ case 0x4c: /* GPIO_FALLINGDETECT */
5036+ return s->edge[1];
5037+
5038+ case 0x50: /* GPIO_DEBOUNCENABLE */
5039+ return s->debounce;
5040+
5041+ case 0x54: /* GPIO_DEBOUNCINGTIME */
5042+ return s->delay;
5043+ }
5044+
5045+ OMAP_BAD_REG(addr);
5046+ return 0;
5047+}
5048+
5049+static void omap_gpio_module_write(void *opaque, target_phys_addr_t addr,
5050+ uint32_t value)
5051+{
5052+ struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
5053+ int offset = addr - s->base;
5054+ uint32_t diff;
5055+ int ln;
5056+
5057+ switch (offset) {
5058+ case 0x00: /* GPIO_REVISION */
5059+ case 0x14: /* GPIO_SYSSTATUS */
5060+ case 0x38: /* GPIO_DATAIN */
5061+ OMAP_RO_REG(addr);
5062+ break;
5063+
5064+ case 0x10: /* GPIO_SYSCONFIG */
5065+ if (((value >> 3) & 3) == 3)
5066+ fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__);
5067+ if (value & 2)
5068+ omap_gpio_module_reset(s);
5069+ s->config[0] = value & 0x1d;
5070+ break;
5071+
5072+ case 0x18: /* GPIO_IRQSTATUS1 */
5073+ if (s->ints[0] & value) {
5074+ s->ints[0] &= ~value;
5075+ omap_gpio_module_level_update(s, 0);
5076+ }
5077+ break;
5078+
5079+ case 0x1c: /* GPIO_IRQENABLE1 */
5080+ s->mask[0] = value;
5081+ omap_gpio_module_int_update(s, 0);
5082+ break;
5083+
5084+ case 0x20: /* GPIO_WAKEUPENABLE */
5085+ s->wumask = value;
5086+ break;
5087+
5088+ case 0x28: /* GPIO_IRQSTATUS2 */
5089+ if (s->ints[1] & value) {
5090+ s->ints[1] &= ~value;
5091+ omap_gpio_module_level_update(s, 1);
5092+ }
5093+ break;
5094+
5095+ case 0x2c: /* GPIO_IRQENABLE2 */
5096+ s->mask[1] = value;
5097+ omap_gpio_module_int_update(s, 1);
5098+ break;
5099+
5100+ case 0x30: /* GPIO_CTRL */
5101+ s->config[1] = value & 7;
5102+ break;
5103+
5104+ case 0x34: /* GPIO_OE */
5105+ diff = s->outputs & (s->dir ^ value);
5106+ s->dir = value;
5107+
5108+ value = s->outputs & ~s->dir;
5109+ while ((ln = ffs(diff))) {
5110+ diff &= ~(1 <<-- ln);
5111+ qemu_set_irq(s->handler[ln], (value >> ln) & 1);
5112+ }
5113+
5114+ omap_gpio_module_level_update(s, 0);
5115+ omap_gpio_module_level_update(s, 1);
5116+ break;
5117+
5118+ case 0x3c: /* GPIO_DATAOUT */
5119+ omap_gpio_module_out_update(s, s->outputs ^ value);
5120+ break;
5121+
5122+ case 0x40: /* GPIO_LEVELDETECT0 */
5123+ s->level[0] = value;
5124+ omap_gpio_module_level_update(s, 0);
5125+ omap_gpio_module_level_update(s, 1);
5126+ break;
5127+
5128+ case 0x44: /* GPIO_LEVELDETECT1 */
5129+ s->level[1] = value;
5130+ omap_gpio_module_level_update(s, 0);
5131+ omap_gpio_module_level_update(s, 1);
5132+ break;
5133+
5134+ case 0x48: /* GPIO_RISINGDETECT */
5135+ s->edge[0] = value;
5136+ break;
5137+
5138+ case 0x4c: /* GPIO_FALLINGDETECT */
5139+ s->edge[1] = value;
5140+ break;
5141+
5142+ case 0x50: /* GPIO_DEBOUNCENABLE */
5143+ s->debounce = value;
5144+ break;
5145+
5146+ case 0x54: /* GPIO_DEBOUNCINGTIME */
5147+ s->delay = value;
5148+ break;
5149+
5150+ case 0x60: /* GPIO_CLEARIRQENABLE1 */
5151+ s->mask[0] &= ~value;
5152+ omap_gpio_module_int_update(s, 0);
5153+ break;
5154+
5155+ case 0x64: /* GPIO_SETIRQENABLE1 */
5156+ s->mask[0] |= value;
5157+ omap_gpio_module_int_update(s, 0);
5158+ break;
5159+
5160+ case 0x70: /* GPIO_CLEARIRQENABLE2 */
5161+ s->mask[1] &= ~value;
5162+ omap_gpio_module_int_update(s, 1);
5163+ break;
5164+
5165+ case 0x74: /* GPIO_SETIREQNEABLE2 */
5166+ s->mask[1] |= value;
5167+ omap_gpio_module_int_update(s, 1);
5168+ break;
5169+
5170+ case 0x80: /* GPIO_CLEARWKUENA */
5171+ s->wumask &= ~value;
5172+ break;
5173+
5174+ case 0x84: /* GPIO_SETWKUENA */
5175+ s->wumask |= value;
5176+ break;
5177+
5178+ case 0x90: /* GPIO_CLEARDATAOUT */
5179+ omap_gpio_module_out_update(s, s->outputs & value);
5180+ break;
5181+
5182+ case 0x94: /* GPIO_SETDATAOUT */
5183+ omap_gpio_module_out_update(s, ~s->outputs & value);
5184+ break;
5185+
5186+ default:
5187+ OMAP_BAD_REG(addr);
5188+ return;
5189+ }
5190+}
5191+
5192+static uint32_t omap_gpio_module_readp(void *opaque, target_phys_addr_t addr)
5193+{
5194+ return omap_gpio_module_readp(opaque, addr) >> ((addr & 3) << 3);
5195+}
5196+
5197+static void omap_gpio_module_writep(void *opaque, target_phys_addr_t addr,
5198+ uint32_t value)
5199+{
5200+ struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
5201+ int offset = addr - s->base;
5202+ uint32_t cur = 0;
5203+ uint32_t mask = 0xffff;
5204+
5205+ switch (offset & ~3) {
5206+ case 0x00: /* GPIO_REVISION */
5207+ case 0x14: /* GPIO_SYSSTATUS */
5208+ case 0x38: /* GPIO_DATAIN */
5209+ OMAP_RO_REG(addr);
5210+ break;
5211+
5212+ case 0x10: /* GPIO_SYSCONFIG */
5213+ case 0x1c: /* GPIO_IRQENABLE1 */
5214+ case 0x20: /* GPIO_WAKEUPENABLE */
5215+ case 0x2c: /* GPIO_IRQENABLE2 */
5216+ case 0x30: /* GPIO_CTRL */
5217+ case 0x34: /* GPIO_OE */
5218+ case 0x3c: /* GPIO_DATAOUT */
5219+ case 0x40: /* GPIO_LEVELDETECT0 */
5220+ case 0x44: /* GPIO_LEVELDETECT1 */
5221+ case 0x48: /* GPIO_RISINGDETECT */
5222+ case 0x4c: /* GPIO_FALLINGDETECT */
5223+ case 0x50: /* GPIO_DEBOUNCENABLE */
5224+ case 0x54: /* GPIO_DEBOUNCINGTIME */
5225+ cur = omap_gpio_module_read(opaque, addr & ~3) &
5226+ ~(mask << ((addr & 3) << 3));
5227+
5228+ /* Fall through. */
5229+ case 0x18: /* GPIO_IRQSTATUS1 */
5230+ case 0x28: /* GPIO_IRQSTATUS2 */
5231+ case 0x60: /* GPIO_CLEARIRQENABLE1 */
5232+ case 0x64: /* GPIO_SETIRQENABLE1 */
5233+ case 0x70: /* GPIO_CLEARIRQENABLE2 */
5234+ case 0x74: /* GPIO_SETIREQNEABLE2 */
5235+ case 0x80: /* GPIO_CLEARWKUENA */
5236+ case 0x84: /* GPIO_SETWKUENA */
5237+ case 0x90: /* GPIO_CLEARDATAOUT */
5238+ case 0x94: /* GPIO_SETDATAOUT */
5239+ value <<= (addr & 3) << 3;
5240+ omap_gpio_module_write(opaque, addr, cur | value);
5241+ break;
5242+
5243+ default:
5244+ OMAP_BAD_REG(addr);
5245+ return;
5246+ }
5247+}
5248+
5249+static CPUReadMemoryFunc *omap_gpio_module_readfn[] = {
5250+ omap_gpio_module_readp,
5251+ omap_gpio_module_readp,
5252+ omap_gpio_module_read,
5253+};
5254+
5255+static CPUWriteMemoryFunc *omap_gpio_module_writefn[] = {
5256+ omap_gpio_module_writep,
5257+ omap_gpio_module_writep,
5258+ omap_gpio_module_write,
5259+};
5260+
5261+static void omap_gpio_module_init(struct omap2_gpio_s *s,
5262+ struct omap_target_agent_s *ta, int region,
5263+ qemu_irq mpu, qemu_irq dsp, qemu_irq wkup,
5264+ omap_clk fclk, omap_clk iclk)
5265+{
5266+ int iomemtype;
5267+
5268+ s->irq[0] = mpu;
5269+ s->irq[1] = dsp;
5270+ s->wkup = wkup;
5271+ s->in = qemu_allocate_irqs(omap_gpio_module_set, s, 32);
5272+
5273+ iomemtype = cpu_register_io_memory(0, omap_gpio_module_readfn,
5274+ omap_gpio_module_writefn, s);
5275+ s->base = omap_l4_attach(ta, region, iomemtype);
5276+}
5277+
5278+struct omap_gpif_s {
5279+ struct omap2_gpio_s module[5];
5280+ int modules;
5281+
5282+ target_phys_addr_t topbase;
5283+ int autoidle;
5284+ int gpo;
5285+};
5286+
5287+static void omap_gpif_reset(struct omap_gpif_s *s)
5288+{
5289+ int i;
5290+
5291+ for (i = 0; i < s->modules; i ++)
5292+ omap_gpio_module_reset(s->module + i);
5293+
5294+ s->autoidle = 0;
5295+ s->gpo = 0;
5296+}
5297+
5298+static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
5299+{
5300+ struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
5301+ int offset = addr - s->topbase;
5302+
5303+ switch (offset) {
5304+ case 0x00: /* IPGENERICOCPSPL_REVISION */
5305+ return 0x18;
5306+
5307+ case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */
5308+ return s->autoidle;
5309+
5310+ case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */
5311+ return 0x01;
5312+
5313+ case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */
5314+ return 0x00;
5315+
5316+ case 0x40: /* IPGENERICOCPSPL_GPO */
5317+ return s->gpo;
5318+
5319+ case 0x50: /* IPGENERICOCPSPL_GPI */
5320+ return 0x00;
5321+ }
5322+
5323+ OMAP_BAD_REG(addr);
5324+ return 0;
5325+}
5326+
5327+static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
5328+ uint32_t value)
5329+{
5330+ struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
5331+ int offset = addr - s->topbase;
5332+
5333+ switch (offset) {
5334+ case 0x00: /* IPGENERICOCPSPL_REVISION */
5335+ case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */
5336+ case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */
5337+ case 0x50: /* IPGENERICOCPSPL_GPI */
5338+ OMAP_RO_REG(addr);
5339+ break;
5340+
5341+ case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */
5342+ if (value & (1 << 1)) /* SOFTRESET */
5343+ omap_gpif_reset(s);
5344+ s->autoidle = value & 1;
5345+ break;
5346+
5347+ case 0x40: /* IPGENERICOCPSPL_GPO */
5348+ s->gpo = value & 1;
5349+ break;
5350+
5351+ default:
5352+ OMAP_BAD_REG(addr);
5353+ return;
5354+ }
5355+}
5356+
5357+static CPUReadMemoryFunc *omap_gpif_top_readfn[] = {
5358+ omap_gpif_top_read,
5359+ omap_gpif_top_read,
5360+ omap_gpif_top_read,
5361+};
5362+
5363+static CPUWriteMemoryFunc *omap_gpif_top_writefn[] = {
5364+ omap_gpif_top_write,
5365+ omap_gpif_top_write,
5366+ omap_gpif_top_write,
5367+};
5368+
5369+struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
5370+ qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules)
5371+{
5372+ int iomemtype, i;
5373+ struct omap_gpif_s *s = (struct omap_gpif_s *)
5374+ qemu_mallocz(sizeof(struct omap_gpif_s));
5375+ int region[4] = { 0, 2, 4, 5 };
5376+
5377+ s->modules = modules;
5378+ for (i = 0; i < modules; i ++)
5379+ omap_gpio_module_init(s->module + i, ta, region[i],
5380+ irq[i], 0, 0, fclk[i], iclk);
5381+
5382+ omap_gpif_reset(s);
5383+
5384+ iomemtype = cpu_register_io_memory(0, omap_gpif_top_readfn,
5385+ omap_gpif_top_writefn, s);
5386+ s->topbase = omap_l4_attach(ta, 1, iomemtype);
5387+
5388+ return s;
5389+}
5390+
5391+qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start)
5392+{
5393+ if (start >= s->modules * 32 || start < 0)
5394+ cpu_abort(cpu_single_env, "%s: No GPIO line %i\n",
5395+ __FUNCTION__, start);
5396+ return s->module[start >> 5].in + (start & 31);
5397+}
5398+
5399+void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler)
5400+{
5401+ if (line >= s->modules * 32 || line < 0)
5402+ cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line);
5403+ s->module[line >> 5].handler[line & 31] = handler;
5404+}
5405+
5406+/* Multichannel SPI */
5407+struct omap_mcspi_s {
5408+ target_phys_addr_t base;
5409+ qemu_irq irq;
5410+ int chnum;
5411+
5412+ uint32_t sysconfig;
5413+ uint32_t systest;
5414+ uint32_t irqst;
5415+ uint32_t irqen;
5416+ uint32_t wken;
5417+ uint32_t control;
5418+
5419+ struct omap_mcspi_ch_s {
5420+ qemu_irq txdrq;
5421+ qemu_irq rxdrq;
5422+ uint32_t (*txrx)(void *opaque, uint32_t);
5423+ void *opaque;
5424+
5425+ uint32_t tx;
5426+ uint32_t rx;
5427+
5428+ uint32_t config;
5429+ uint32_t status;
5430+ uint32_t control;
5431+ } ch[4];
5432+};
5433+
5434+static inline void omap_mcspi_interrupt_update(struct omap_mcspi_s *s)
5435+{
5436+ qemu_set_irq(s->irq, s->irqst & s->irqen);
5437+}
5438+
5439+static inline void omap_mcspi_dmarequest_update(struct omap_mcspi_ch_s *ch)
5440+{
5441+ qemu_set_irq(ch->txdrq,
5442+ (ch->control & 1) && /* EN */
5443+ (ch->config & (1 << 14)) && /* DMAW */
5444+ (ch->status & (1 << 1)) && /* TXS */
5445+ ((ch->config >> 12) & 3) != 1); /* TRM */
5446+ qemu_set_irq(ch->rxdrq,
5447+ (ch->control & 1) && /* EN */
5448+ (ch->config & (1 << 15)) && /* DMAW */
5449+ (ch->status & (1 << 0)) && /* RXS */
5450+ ((ch->config >> 12) & 3) != 2); /* TRM */
5451+}
5452+
5453+static void omap_mcspi_transfer_run(struct omap_mcspi_s *s, int chnum)
5454+{
5455+ struct omap_mcspi_ch_s *ch = s->ch + chnum;
5456+
5457+ if (!(ch->control & 1)) /* EN */
5458+ return;
5459+ if ((ch->status & (1 << 0)) && /* RXS */
5460+ ((ch->config >> 12) & 3) != 2 && /* TRM */
5461+ !(ch->config & (1 << 19))) /* TURBO */
5462+ goto intr_update;
5463+ if ((ch->status & (1 << 1)) && /* TXS */
5464+ ((ch->config >> 12) & 3) != 1) /* TRM */
5465+ goto intr_update;
5466+
5467+ if (!(s->control & 1) || /* SINGLE */
5468+ (ch->config & (1 << 20))) { /* FORCE */
5469+ if (ch->txrx)
5470+ ch->rx = ch->txrx(ch->opaque, ch->tx);
5471+ }
5472+
5473+ ch->tx = 0;
5474+ ch->status |= 1 << 2; /* EOT */
5475+ ch->status |= 1 << 1; /* TXS */
5476+ if (((ch->config >> 12) & 3) != 2) /* TRM */
5477+ ch->status |= 1 << 0; /* RXS */
5478+
5479+intr_update:
5480+ if ((ch->status & (1 << 0)) && /* RXS */
5481+ ((ch->config >> 12) & 3) != 2 && /* TRM */
5482+ !(ch->config & (1 << 19))) /* TURBO */
5483+ s->irqst |= 1 << (2 + 4 * chnum); /* RX_FULL */
5484+ if ((ch->status & (1 << 1)) && /* TXS */
5485+ ((ch->config >> 12) & 3) != 1) /* TRM */
5486+ s->irqst |= 1 << (0 + 4 * chnum); /* TX_EMPTY */
5487+ omap_mcspi_interrupt_update(s);
5488+ omap_mcspi_dmarequest_update(ch);
5489+}
5490+
5491+static void omap_mcspi_reset(struct omap_mcspi_s *s)
5492+{
5493+ int ch;
5494+
5495+ s->sysconfig = 0;
5496+ s->systest = 0;
5497+ s->irqst = 0;
5498+ s->irqen = 0;
5499+ s->wken = 0;
5500+ s->control = 4;
5501+
5502+ for (ch = 0; ch < 4; ch ++) {
5503+ s->ch[ch].config = 0x060000;
5504+ s->ch[ch].status = 2; /* TXS */
5505+ s->ch[ch].control = 0;
5506+
5507+ omap_mcspi_dmarequest_update(s->ch + ch);
5508+ }
5509+
5510+ omap_mcspi_interrupt_update(s);
5511+}
5512+
5513+static uint32_t omap_mcspi_read(void *opaque, target_phys_addr_t addr)
5514+{
5515+ struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
5516+ int offset = addr - s->base;
5517+ int ch = 0;
5518+ uint32_t ret;
5519+
5520+ switch (offset) {
5521+ case 0x00: /* MCSPI_REVISION */
5522+ return 0x91;
5523+
5524+ case 0x10: /* MCSPI_SYSCONFIG */
5525+ return s->sysconfig;
5526+
5527+ case 0x14: /* MCSPI_SYSSTATUS */
5528+ return 1; /* RESETDONE */
5529+
5530+ case 0x18: /* MCSPI_IRQSTATUS */
5531+ return s->irqst;
5532+
5533+ case 0x1c: /* MCSPI_IRQENABLE */
5534+ return s->irqen;
5535+
5536+ case 0x20: /* MCSPI_WAKEUPENABLE */
5537+ return s->wken;
5538+
5539+ case 0x24: /* MCSPI_SYST */
5540+ return s->systest;
5541+
5542+ case 0x28: /* MCSPI_MODULCTRL */
5543+ return s->control;
5544+
5545+ case 0x68: ch ++;
5546+ case 0x54: ch ++;
5547+ case 0x40: ch ++;
5548+ case 0x2c: /* MCSPI_CHCONF */
5549+ return s->ch[ch].config;
5550+
5551+ case 0x6c: ch ++;
5552+ case 0x58: ch ++;
5553+ case 0x44: ch ++;
5554+ case 0x30: /* MCSPI_CHSTAT */
5555+ return s->ch[ch].status;
5556+
5557+ case 0x70: ch ++;
5558+ case 0x5c: ch ++;
5559+ case 0x48: ch ++;
5560+ case 0x34: /* MCSPI_CHCTRL */
5561+ return s->ch[ch].control;
5562+
5563+ case 0x74: ch ++;
5564+ case 0x60: ch ++;
5565+ case 0x4c: ch ++;
5566+ case 0x38: /* MCSPI_TX */
5567+ return s->ch[ch].tx;
5568+
5569+ case 0x78: ch ++;
5570+ case 0x64: ch ++;
5571+ case 0x50: ch ++;
5572+ case 0x3c: /* MCSPI_RX */
5573+ s->ch[ch].status &= ~(1 << 0); /* RXS */
5574+ ret = s->ch[ch].rx;
5575+ omap_mcspi_transfer_run(s, ch);
5576+ return ret;
5577+ }
5578+
5579+ OMAP_BAD_REG(addr);
5580+ return 0;
5581+}
5582+
5583+static void omap_mcspi_write(void *opaque, target_phys_addr_t addr,
5584+ uint32_t value)
5585+{
5586+ struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
5587+ int offset = addr - s->base;
5588+ int ch = 0;
5589+
5590+ switch (offset) {
5591+ case 0x00: /* MCSPI_REVISION */
5592+ case 0x14: /* MCSPI_SYSSTATUS */
5593+ case 0x30: /* MCSPI_CHSTAT0 */
5594+ case 0x3c: /* MCSPI_RX0 */
5595+ case 0x44: /* MCSPI_CHSTAT1 */
5596+ case 0x50: /* MCSPI_RX1 */
5597+ case 0x58: /* MCSPI_CHSTAT2 */
5598+ case 0x64: /* MCSPI_RX2 */
5599+ case 0x6c: /* MCSPI_CHSTAT3 */
5600+ case 0x78: /* MCSPI_RX3 */
5601+ OMAP_RO_REG(addr);
5602+ return;
5603+
5604+ case 0x10: /* MCSPI_SYSCONFIG */
5605+ if (value & (1 << 1)) /* SOFTRESET */
5606+ omap_mcspi_reset(s);
5607+ s->sysconfig = value & 0x31d;
5608+ break;
5609+
5610+ case 0x18: /* MCSPI_IRQSTATUS */
5611+ if (!((s->control & (1 << 3)) && (s->systest & (1 << 11)))) {
5612+ s->irqst &= ~value;
5613+ omap_mcspi_interrupt_update(s);
5614+ }
5615+ break;
5616+
5617+ case 0x1c: /* MCSPI_IRQENABLE */
5618+ s->irqen = value & 0x1777f;
5619+ omap_mcspi_interrupt_update(s);
5620+ break;
5621+
5622+ case 0x20: /* MCSPI_WAKEUPENABLE */
5623+ s->wken = value & 1;
5624+ break;
5625+
5626+ case 0x24: /* MCSPI_SYST */
5627+ if (s->control & (1 << 3)) /* SYSTEM_TEST */
5628+ if (value & (1 << 11)) { /* SSB */
5629+ s->irqst |= 0x1777f;
5630+ omap_mcspi_interrupt_update(s);
5631+ }
5632+ s->systest = value & 0xfff;
5633+ break;
5634+
5635+ case 0x28: /* MCSPI_MODULCTRL */
5636+ if (value & (1 << 3)) /* SYSTEM_TEST */
5637+ if (s->systest & (1 << 11)) { /* SSB */
5638+ s->irqst |= 0x1777f;
5639+ omap_mcspi_interrupt_update(s);
5640+ }
5641+ s->control = value & 0xf;
5642+ break;
5643+
5644+ case 0x68: ch ++;
5645+ case 0x54: ch ++;
5646+ case 0x40: ch ++;
5647+ case 0x2c: /* MCSPI_CHCONF */
5648+ if ((value ^ s->ch[ch].config) & (3 << 14)) /* DMAR | DMAW */
5649+ omap_mcspi_dmarequest_update(s->ch + ch);
5650+ if (((value >> 12) & 3) == 3) /* TRM */
5651+ fprintf(stderr, "%s: invalid TRM value (3)\n", __FUNCTION__);
5652+ if (((value >> 7) & 0x1f) < 3) /* WL */
5653+ fprintf(stderr, "%s: invalid WL value (%i)\n",
5654+ __FUNCTION__, (value >> 7) & 0x1f);
5655+ s->ch[ch].config = value & 0x7fffff;
5656+ break;
5657+
5658+ case 0x70: ch ++;
5659+ case 0x5c: ch ++;
5660+ case 0x48: ch ++;
5661+ case 0x34: /* MCSPI_CHCTRL */
5662+ if (value & ~s->ch[ch].control & 1) { /* EN */
5663+ s->ch[ch].control |= 1;
5664+ omap_mcspi_transfer_run(s, ch);
5665+ } else
5666+ s->ch[ch].control = value & 1;
5667+ break;
5668+
5669+ case 0x74: ch ++;
5670+ case 0x60: ch ++;
5671+ case 0x4c: ch ++;
5672+ case 0x38: /* MCSPI_TX */
5673+ s->ch[ch].tx = value;
5674+ s->ch[ch].status &= ~(1 << 1); /* TXS */
5675+ omap_mcspi_transfer_run(s, ch);
5676+ break;
5677+
5678+ default:
5679+ OMAP_BAD_REG(addr);
5680+ return;
5681+ }
5682+}
5683+
5684+static CPUReadMemoryFunc *omap_mcspi_readfn[] = {
5685+ omap_badwidth_read32,
5686+ omap_badwidth_read32,
5687+ omap_mcspi_read,
5688+};
5689+
5690+static CPUWriteMemoryFunc *omap_mcspi_writefn[] = {
5691+ omap_badwidth_write32,
5692+ omap_badwidth_write32,
5693+ omap_mcspi_write,
5694+};
5695+
5696+struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
5697+ qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
5698+{
5699+ int iomemtype;
5700+ struct omap_mcspi_s *s = (struct omap_mcspi_s *)
5701+ qemu_mallocz(sizeof(struct omap_mcspi_s));
5702+ struct omap_mcspi_ch_s *ch = s->ch;
5703+
5704+ s->irq = irq;
5705+ s->chnum = chnum;
5706+ while (chnum --) {
5707+ ch->txdrq = *drq ++;
5708+ ch->rxdrq = *drq ++;
5709+ ch ++;
5710+ }
5711+ omap_mcspi_reset(s);
5712+
5713+ iomemtype = cpu_register_io_memory(0, omap_mcspi_readfn,
5714+ omap_mcspi_writefn, s);
5715+ s->base = omap_l4_attach(ta, 0, iomemtype);
5716+
5717+ return s;
5718+}
5719+
5720+void omap_mcspi_attach(struct omap_mcspi_s *s,
5721+ uint32_t (*txrx)(void *opaque, uint32_t), void *opaque,
5722+ int chipselect)
5723+{
5724+ if (chipselect < 0 || chipselect >= s->chnum)
5725+ cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n",
5726+ __FUNCTION__, chipselect);
5727+
5728+ s->ch[chipselect].txrx = txrx;
5729+ s->ch[chipselect].opaque = opaque;
5730+}
5731+
5732+/* L4 Interconnect */
5733+struct omap_target_agent_s {
5734+ struct omap_l4_s *bus;
5735+ int regions;
5736+ struct omap_l4_region_s *start;
5737+ target_phys_addr_t base;
5738+ uint32_t component;
5739+ uint32_t control;
5740+ uint32_t status;
5741+};
5742+
5743+struct omap_l4_s {
5744+ target_phys_addr_t base;
5745+ int ta_num;
5746+ struct omap_target_agent_s ta[0];
5747+};
5748+
5749+struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num)
5750+{
5751+ struct omap_l4_s *bus = qemu_mallocz(
5752+ sizeof(*bus) + ta_num * sizeof(*bus->ta));
5753+
5754+ bus->ta_num = ta_num;
5755+ bus->base = base;
5756+
5757+ return bus;
5758+}
5759+
5760+static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr)
5761+{
5762+ struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
5763+ target_phys_addr_t reg = addr - s->base;
5764+
5765+ switch (reg) {
5766+ case 0x00: /* COMPONENT */
5767+ return s->component;
5768+
5769+ case 0x20: /* AGENT_CONTROL */
5770+ return s->control;
5771+
5772+ case 0x28: /* AGENT_STATUS */
5773+ return s->status;
5774+ }
5775+
5776+ OMAP_BAD_REG(addr);
5777+ return 0;
5778+}
5779+
5780+static void omap_l4ta_write(void *opaque, target_phys_addr_t addr,
5781+ uint32_t value)
5782+{
5783+ struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
5784+ target_phys_addr_t reg = addr - s->base;
5785+
5786+ switch (reg) {
5787+ case 0x00: /* COMPONENT */
5788+ case 0x28: /* AGENT_STATUS */
5789+ OMAP_RO_REG(addr);
5790+ break;
5791+
5792+ case 0x20: /* AGENT_CONTROL */
5793+ s->control = value & 0x01000700;
5794+ if (value & 1) /* OCP_RESET */
5795+ s->status &= ~1; /* REQ_TIMEOUT */
5796+ break;
5797+
5798+ default:
5799+ OMAP_BAD_REG(addr);
5800+ }
5801+}
5802+
5803+static CPUReadMemoryFunc *omap_l4ta_readfn[] = {
5804+ omap_badwidth_read16,
5805+ omap_l4ta_read,
5806+ omap_badwidth_read16,
5807+};
5808+
5809+static CPUWriteMemoryFunc *omap_l4ta_writefn[] = {
5810+ omap_badwidth_write32,
5811+ omap_badwidth_write32,
5812+ omap_l4ta_write,
5813+};
5814+
5815+#define L4TA(n) (n)
5816+#define L4TAO(n) ((n) + 39)
5817+
5818+static struct omap_l4_region_s {
5819+ target_phys_addr_t offset;
5820+ size_t size;
5821+ int access;
5822+} omap_l4_region[125] = {
5823+ [ 1] = { 0x40800, 0x800, 32 }, /* Initiator agent */
5824+ [ 2] = { 0x41000, 0x1000, 32 }, /* Link agent */
5825+ [ 0] = { 0x40000, 0x800, 32 }, /* Address and protection */
5826+ [ 3] = { 0x00000, 0x1000, 32 | 16 | 8 }, /* System Control and Pinout */
5827+ [ 4] = { 0x01000, 0x1000, 32 | 16 | 8 }, /* L4TAO1 */
5828+ [ 5] = { 0x04000, 0x1000, 32 | 16 }, /* 32K Timer */
5829+ [ 6] = { 0x05000, 0x1000, 32 | 16 | 8 }, /* L4TAO2 */
5830+ [ 7] = { 0x08000, 0x800, 32 }, /* PRCM Region A */
5831+ [ 8] = { 0x08800, 0x800, 32 }, /* PRCM Region B */
5832+ [ 9] = { 0x09000, 0x1000, 32 | 16 | 8 }, /* L4TAO */
5833+ [ 10] = { 0x12000, 0x1000, 32 | 16 | 8 }, /* Test (BCM) */
5834+ [ 11] = { 0x13000, 0x1000, 32 | 16 | 8 }, /* L4TA1 */
5835+ [ 12] = { 0x14000, 0x1000, 32 }, /* Test/emulation (TAP) */
5836+ [ 13] = { 0x15000, 0x1000, 32 | 16 | 8 }, /* L4TA2 */
5837+ [ 14] = { 0x18000, 0x1000, 32 | 16 | 8 }, /* GPIO1 */
5838+ [ 16] = { 0x1a000, 0x1000, 32 | 16 | 8 }, /* GPIO2 */
5839+ [ 18] = { 0x1c000, 0x1000, 32 | 16 | 8 }, /* GPIO3 */
5840+ [ 19] = { 0x1e000, 0x1000, 32 | 16 | 8 }, /* GPIO4 */
5841+ [ 15] = { 0x19000, 0x1000, 32 | 16 | 8 }, /* Quad GPIO TOP */
5842+ [ 17] = { 0x1b000, 0x1000, 32 | 16 | 8 }, /* L4TA3 */
5843+ [ 20] = { 0x20000, 0x1000, 32 | 16 | 8 }, /* WD Timer 1 (Secure) */
5844+ [ 22] = { 0x22000, 0x1000, 32 | 16 | 8 }, /* WD Timer 2 (OMAP) */
5845+ [ 21] = { 0x21000, 0x1000, 32 | 16 | 8 }, /* Dual WD timer TOP */
5846+ [ 23] = { 0x23000, 0x1000, 32 | 16 | 8 }, /* L4TA4 */
5847+ [ 24] = { 0x28000, 0x1000, 32 | 16 | 8 }, /* GP Timer 1 */
5848+ [ 25] = { 0x29000, 0x1000, 32 | 16 | 8 }, /* L4TA7 */
5849+ [ 26] = { 0x48000, 0x2000, 32 | 16 | 8 }, /* Emulation (ARM11ETB) */
5850+ [ 27] = { 0x4a000, 0x1000, 32 | 16 | 8 }, /* L4TA9 */
5851+ [ 28] = { 0x50000, 0x400, 32 | 16 | 8 }, /* Display top */
5852+ [ 29] = { 0x50400, 0x400, 32 | 16 | 8 }, /* Display control */
5853+ [ 30] = { 0x50800, 0x400, 32 | 16 | 8 }, /* Display RFBI */
5854+ [ 31] = { 0x50c00, 0x400, 32 | 16 | 8 }, /* Display encoder */
5855+ [ 32] = { 0x51000, 0x1000, 32 | 16 | 8 }, /* L4TA10 */
5856+ [ 33] = { 0x52000, 0x400, 32 | 16 | 8 }, /* Camera top */
5857+ [ 34] = { 0x52400, 0x400, 32 | 16 | 8 }, /* Camera core */
5858+ [ 35] = { 0x52800, 0x400, 32 | 16 | 8 }, /* Camera DMA */
5859+ [ 36] = { 0x52c00, 0x400, 32 | 16 | 8 }, /* Camera MMU */
5860+ [ 37] = { 0x53000, 0x1000, 32 | 16 | 8 }, /* L4TA11 */
5861+ [ 38] = { 0x56000, 0x1000, 32 | 16 | 8 }, /* sDMA */
5862+ [ 39] = { 0x57000, 0x1000, 32 | 16 | 8 }, /* L4TA12 */
5863+ [ 40] = { 0x58000, 0x1000, 32 | 16 | 8 }, /* SSI top */
5864+ [ 41] = { 0x59000, 0x1000, 32 | 16 | 8 }, /* SSI GDD */
5865+ [ 42] = { 0x5a000, 0x1000, 32 | 16 | 8 }, /* SSI Port1 */
5866+ [ 43] = { 0x5b000, 0x1000, 32 | 16 | 8 }, /* SSI Port2 */
5867+ [ 44] = { 0x5c000, 0x1000, 32 | 16 | 8 }, /* L4TA13 */
5868+ [ 45] = { 0x5e000, 0x1000, 32 | 16 | 8 }, /* USB OTG */
5869+ [ 46] = { 0x5f000, 0x1000, 32 | 16 | 8 }, /* L4TAO4 */
5870+ [ 47] = { 0x60000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER1SDRC) */
5871+ [ 48] = { 0x61000, 0x1000, 32 | 16 | 8 }, /* L4TA14 */
5872+ [ 49] = { 0x62000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER2GPMC) */
5873+ [ 50] = { 0x63000, 0x1000, 32 | 16 | 8 }, /* L4TA15 */
5874+ [ 51] = { 0x64000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER3OCM) */
5875+ [ 52] = { 0x65000, 0x1000, 32 | 16 | 8 }, /* L4TA16 */
5876+ [ 53] = { 0x66000, 0x300, 32 | 16 | 8 }, /* Emulation (WIN_TRACER4L4) */
5877+ [ 54] = { 0x67000, 0x1000, 32 | 16 | 8 }, /* L4TA17 */
5878+ [ 55] = { 0x68000, 0x1000, 32 | 16 | 8 }, /* Emulation (XTI) */
5879+ [ 56] = { 0x69000, 0x1000, 32 | 16 | 8 }, /* L4TA18 */
5880+ [ 57] = { 0x6a000, 0x1000, 16 | 8 }, /* UART1 */
5881+ [ 58] = { 0x6b000, 0x1000, 32 | 16 | 8 }, /* L4TA19 */
5882+ [ 59] = { 0x6c000, 0x1000, 16 | 8 }, /* UART2 */
5883+ [ 60] = { 0x6d000, 0x1000, 32 | 16 | 8 }, /* L4TA20 */
5884+ [ 61] = { 0x6e000, 0x1000, 16 | 8 }, /* UART3 */
5885+ [ 62] = { 0x6f000, 0x1000, 32 | 16 | 8 }, /* L4TA21 */
5886+ [ 63] = { 0x70000, 0x1000, 16 }, /* I2C1 */
5887+ [ 64] = { 0x71000, 0x1000, 32 | 16 | 8 }, /* L4TAO5 */
5888+ [ 65] = { 0x72000, 0x1000, 16 }, /* I2C2 */
5889+ [ 66] = { 0x73000, 0x1000, 32 | 16 | 8 }, /* L4TAO6 */
5890+ [ 67] = { 0x74000, 0x1000, 16 }, /* McBSP1 */
5891+ [ 68] = { 0x75000, 0x1000, 32 | 16 | 8 }, /* L4TAO7 */
5892+ [ 69] = { 0x76000, 0x1000, 16 }, /* McBSP2 */
5893+ [ 70] = { 0x77000, 0x1000, 32 | 16 | 8 }, /* L4TAO8 */
5894+ [ 71] = { 0x24000, 0x1000, 32 | 16 | 8 }, /* WD Timer 3 (DSP) */
5895+ [ 72] = { 0x25000, 0x1000, 32 | 16 | 8 }, /* L4TA5 */
5896+ [ 73] = { 0x26000, 0x1000, 32 | 16 | 8 }, /* WD Timer 4 (IVA) */
5897+ [ 74] = { 0x27000, 0x1000, 32 | 16 | 8 }, /* L4TA6 */
5898+ [ 75] = { 0x2a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 2 */
5899+ [ 76] = { 0x2b000, 0x1000, 32 | 16 | 8 }, /* L4TA8 */
5900+ [ 77] = { 0x78000, 0x1000, 32 | 16 | 8 }, /* GP Timer 3 */
5901+ [ 78] = { 0x79000, 0x1000, 32 | 16 | 8 }, /* L4TA22 */
5902+ [ 79] = { 0x7a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 4 */
5903+ [ 80] = { 0x7b000, 0x1000, 32 | 16 | 8 }, /* L4TA23 */
5904+ [ 81] = { 0x7c000, 0x1000, 32 | 16 | 8 }, /* GP Timer 5 */
5905+ [ 82] = { 0x7d000, 0x1000, 32 | 16 | 8 }, /* L4TA24 */
5906+ [ 83] = { 0x7e000, 0x1000, 32 | 16 | 8 }, /* GP Timer 6 */
5907+ [ 84] = { 0x7f000, 0x1000, 32 | 16 | 8 }, /* L4TA25 */
5908+ [ 85] = { 0x80000, 0x1000, 32 | 16 | 8 }, /* GP Timer 7 */
5909+ [ 86] = { 0x81000, 0x1000, 32 | 16 | 8 }, /* L4TA26 */
5910+ [ 87] = { 0x82000, 0x1000, 32 | 16 | 8 }, /* GP Timer 8 */
5911+ [ 88] = { 0x83000, 0x1000, 32 | 16 | 8 }, /* L4TA27 */
5912+ [ 89] = { 0x84000, 0x1000, 32 | 16 | 8 }, /* GP Timer 9 */
5913+ [ 90] = { 0x85000, 0x1000, 32 | 16 | 8 }, /* L4TA28 */
5914+ [ 91] = { 0x86000, 0x1000, 32 | 16 | 8 }, /* GP Timer 10 */
5915+ [ 92] = { 0x87000, 0x1000, 32 | 16 | 8 }, /* L4TA29 */
5916+ [ 93] = { 0x88000, 0x1000, 32 | 16 | 8 }, /* GP Timer 11 */
5917+ [ 94] = { 0x89000, 0x1000, 32 | 16 | 8 }, /* L4TA30 */
5918+ [ 95] = { 0x8a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 12 */
5919+ [ 96] = { 0x8b000, 0x1000, 32 | 16 | 8 }, /* L4TA31 */
5920+ [ 97] = { 0x90000, 0x1000, 16 }, /* EAC */
5921+ [ 98] = { 0x91000, 0x1000, 32 | 16 | 8 }, /* L4TA32 */
5922+ [ 99] = { 0x92000, 0x1000, 16 }, /* FAC */
5923+ [100] = { 0x93000, 0x1000, 32 | 16 | 8 }, /* L4TA33 */
5924+ [101] = { 0x94000, 0x1000, 32 | 16 | 8 }, /* IPC (MAILBOX) */
5925+ [102] = { 0x95000, 0x1000, 32 | 16 | 8 }, /* L4TA34 */
5926+ [103] = { 0x98000, 0x1000, 32 | 16 | 8 }, /* SPI1 */
5927+ [104] = { 0x99000, 0x1000, 32 | 16 | 8 }, /* L4TA35 */
5928+ [105] = { 0x9a000, 0x1000, 32 | 16 | 8 }, /* SPI2 */
5929+ [106] = { 0x9b000, 0x1000, 32 | 16 | 8 }, /* L4TA36 */
5930+ [107] = { 0x9c000, 0x1000, 16 | 8 }, /* MMC SDIO */
5931+ [108] = { 0x9d000, 0x1000, 32 | 16 | 8 }, /* L4TAO9 */
5932+ [109] = { 0x9e000, 0x1000, 32 | 16 | 8 }, /* MS_PRO */
5933+ [110] = { 0x9f000, 0x1000, 32 | 16 | 8 }, /* L4TAO10 */
5934+ [111] = { 0xa0000, 0x1000, 32 }, /* RNG */
5935+ [112] = { 0xa1000, 0x1000, 32 | 16 | 8 }, /* L4TAO11 */
5936+ [113] = { 0xa2000, 0x1000, 32 }, /* DES3DES */
5937+ [114] = { 0xa3000, 0x1000, 32 | 16 | 8 }, /* L4TAO12 */
5938+ [115] = { 0xa4000, 0x1000, 32 }, /* SHA1MD5 */
5939+ [116] = { 0xa5000, 0x1000, 32 | 16 | 8 }, /* L4TAO13 */
5940+ [117] = { 0xa6000, 0x1000, 32 }, /* AES */
5941+ [118] = { 0xa7000, 0x1000, 32 | 16 | 8 }, /* L4TA37 */
5942+ [119] = { 0xa8000, 0x2000, 32 }, /* PKA */
5943+ [120] = { 0xaa000, 0x1000, 32 | 16 | 8 }, /* L4TA38 */
5944+ [121] = { 0xb0000, 0x1000, 32 }, /* MG */
5945+ [122] = { 0xb1000, 0x1000, 32 | 16 | 8 },
5946+ [123] = { 0xb2000, 0x1000, 32 }, /* HDQ/1-Wire */
5947+ [124] = { 0xb3000, 0x1000, 32 | 16 | 8 }, /* L4TA39 */
5948+};
5949+
5950+static struct omap_l4_agent_info_s {
5951+ int ta;
5952+ int region;
5953+ int regions;
5954+ int ta_region;
5955+} omap_l4_agent_info[54] = {
5956+ { 0, 0, 3, 2 }, /* L4IA initiatior agent */
5957+ { L4TAO(1), 3, 2, 1 }, /* Control and pinout module */
5958+ { L4TAO(2), 5, 2, 1 }, /* 32K timer */
5959+ { L4TAO(3), 7, 3, 2 }, /* PRCM */
5960+ { L4TA(1), 10, 2, 1 }, /* BCM */
5961+ { L4TA(2), 12, 2, 1 }, /* Test JTAG */
5962+ { L4TA(3), 14, 6, 3 }, /* Quad GPIO */
5963+ { L4TA(4), 20, 4, 3 }, /* WD timer 1/2 */
5964+ { L4TA(7), 24, 2, 1 }, /* GP timer 1 */
5965+ { L4TA(9), 26, 2, 1 }, /* ATM11 ETB */
5966+ { L4TA(10), 28, 5, 4 }, /* Display subsystem */
5967+ { L4TA(11), 33, 5, 4 }, /* Camera subsystem */
5968+ { L4TA(12), 38, 2, 1 }, /* sDMA */
5969+ { L4TA(13), 40, 5, 4 }, /* SSI */
5970+ { L4TAO(4), 45, 2, 1 }, /* USB */
5971+ { L4TA(14), 47, 2, 1 }, /* Win Tracer1 */
5972+ { L4TA(15), 49, 2, 1 }, /* Win Tracer2 */
5973+ { L4TA(16), 51, 2, 1 }, /* Win Tracer3 */
5974+ { L4TA(17), 53, 2, 1 }, /* Win Tracer4 */
5975+ { L4TA(18), 55, 2, 1 }, /* XTI */
5976+ { L4TA(19), 57, 2, 1 }, /* UART1 */
5977+ { L4TA(20), 59, 2, 1 }, /* UART2 */
5978+ { L4TA(21), 61, 2, 1 }, /* UART3 */
5979+ { L4TAO(5), 63, 2, 1 }, /* I2C1 */
5980+ { L4TAO(6), 65, 2, 1 }, /* I2C2 */
5981+ { L4TAO(7), 67, 2, 1 }, /* McBSP1 */
5982+ { L4TAO(8), 69, 2, 1 }, /* McBSP2 */
5983+ { L4TA(5), 71, 2, 1 }, /* WD Timer 3 (DSP) */
5984+ { L4TA(6), 73, 2, 1 }, /* WD Timer 4 (IVA) */
5985+ { L4TA(8), 75, 2, 1 }, /* GP Timer 2 */
5986+ { L4TA(22), 77, 2, 1 }, /* GP Timer 3 */
5987+ { L4TA(23), 79, 2, 1 }, /* GP Timer 4 */
5988+ { L4TA(24), 81, 2, 1 }, /* GP Timer 5 */
5989+ { L4TA(25), 83, 2, 1 }, /* GP Timer 6 */
5990+ { L4TA(26), 85, 2, 1 }, /* GP Timer 7 */
5991+ { L4TA(27), 87, 2, 1 }, /* GP Timer 8 */
5992+ { L4TA(28), 89, 2, 1 }, /* GP Timer 9 */
5993+ { L4TA(29), 91, 2, 1 }, /* GP Timer 10 */
5994+ { L4TA(30), 93, 2, 1 }, /* GP Timer 11 */
5995+ { L4TA(31), 95, 2, 1 }, /* GP Timer 12 */
5996+ { L4TA(32), 97, 2, 1 }, /* EAC */
5997+ { L4TA(33), 99, 2, 1 }, /* FAC */
5998+ { L4TA(34), 101, 2, 1 }, /* IPC */
5999+ { L4TA(35), 103, 2, 1 }, /* SPI1 */
6000+ { L4TA(36), 105, 2, 1 }, /* SPI2 */
6001+ { L4TAO(9), 107, 2, 1 }, /* MMC SDIO */
6002+ { L4TAO(10), 109, 2, 1 },
6003+ { L4TAO(11), 111, 2, 1 }, /* RNG */
6004+ { L4TAO(12), 113, 2, 1 }, /* DES3DES */
6005+ { L4TAO(13), 115, 2, 1 }, /* SHA1MD5 */
6006+ { L4TA(37), 117, 2, 1 }, /* AES */
6007+ { L4TA(38), 119, 2, 1 }, /* PKA */
6008+ { -1, 121, 2, 1 },
6009+ { L4TA(39), 123, 2, 1 }, /* HDQ/1-Wire */
6010+};
6011+
6012+#define omap_l4ta(bus, cs) omap_l4ta_get(bus, L4TA(cs))
6013+#define omap_l4tao(bus, cs) omap_l4ta_get(bus, L4TAO(cs))
6014+
6015+struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, int cs)
6016+{
6017+ int i, iomemtype;
6018+ struct omap_target_agent_s *ta = 0;
6019+ struct omap_l4_agent_info_s *info = 0;
6020+
6021+ for (i = 0; i < bus->ta_num; i ++)
6022+ if (omap_l4_agent_info[i].ta == cs) {
6023+ ta = &bus->ta[i];
6024+ info = &omap_l4_agent_info[i];
6025+ break;
6026+ }
6027+ if (!ta) {
6028+ fprintf(stderr, "%s: bad target agent (%i)\n", __FUNCTION__, cs);
6029+ exit(-1);
6030+ }
6031+
6032+ ta->bus = bus;
6033+ ta->start = &omap_l4_region[info->region];
6034+ ta->regions = info->regions;
6035+ ta->base = bus->base + ta->start[info->ta_region].offset;
6036+
6037+ ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
6038+ ta->status = 0x00000000;
6039+ ta->control = 0x00000200; /* XXX 01000200 for L4TAO */
6040+
6041+ iomemtype = cpu_register_io_memory(0, omap_l4ta_readfn,
6042+ omap_l4ta_writefn, ta);
6043+ cpu_register_physical_memory(ta->base, 0x200, iomemtype);
6044+
6045+ return ta;
6046+}
6047+
6048+target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
6049+ int iotype)
6050+{
6051+ target_phys_addr_t base;
6052+ size_t size;
6053+
6054+ if (region < 0 || region >= ta->regions) {
6055+ fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region);
6056+ exit(-1);
6057+ }
6058+
6059+ base = ta->bus->base + ta->start[region].offset;
6060+ size = ta->start[region].size;
6061+ if (iotype)
6062+ cpu_register_physical_memory(base, size, iotype);
6063+
6064+ return base;
6065+}
6066+
6067+/* TEST-Chip-level TAP */
6068+static uint32_t omap_tap_read(void *opaque, target_phys_addr_t addr)
6069+{
6070+ struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
6071+ target_phys_addr_t reg = addr - s->tap_base;
6072+
6073+ switch (reg) {
6074+ case 0x204: /* IDCODE_reg */
6075+ switch (s->mpu_model) {
6076+ case omap2420:
6077+ case omap2422:
6078+ case omap2423:
6079+ return 0x5b5d902f; /* ES 2.2 */
6080+ case omap2430:
6081+ return 0x5b68a02f; /* ES 2.2 */
6082+ case omap3430:
6083+ return 0x1b7ae02f; /* ES 2 */
6084+ default:
6085+ cpu_abort(cpu_single_env, "%s: Bad mpu model\n", __FUNCTION__);
6086+ }
6087+
6088+ case 0x208: /* PRODUCTION_ID_reg for OMAP2 */
6089+ case 0x210: /* PRODUCTION_ID_reg for OMAP3 */
6090+ switch (s->mpu_model) {
6091+ case omap2420:
6092+ return 0x000200f0; /* POP ESHS2.1.1 in N91/93/95, ES2 in N800 */
6093+ case omap2422:
6094+ return 0x000400f0;
6095+ case omap2423:
6096+ return 0x000800f0;
6097+ case omap2430:
6098+ return 0x000000f0;
6099+ case omap3430:
6100+ return 0x000000f0;
6101+ default:
6102+ cpu_abort(cpu_single_env, "%s: Bad mpu model\n", __FUNCTION__);
6103+ }
6104+
6105+ case 0x218: /* DIE_ID_reg */
6106+ return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
6107+ case 0x21c: /* DIE_ID_reg */
6108+ return ( 5 << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
6109+ case 0x220: /* DIE_ID_reg */
6110+ return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
6111+ case 0x224: /* DIE_ID_reg */
6112+ return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
6113+ }
6114+
6115+ OMAP_BAD_REG(addr);
6116+ return 0;
6117+}
6118+
6119+static void omap_tap_write(void *opaque, target_phys_addr_t addr,
6120+ uint32_t value)
6121+{
6122+ OMAP_BAD_REG(addr);
6123+}
6124+
6125+static CPUReadMemoryFunc *omap_tap_readfn[] = {
6126+ omap_badwidth_read32,
6127+ omap_badwidth_read32,
6128+ omap_tap_read,
6129+};
6130+
6131+static CPUWriteMemoryFunc *omap_tap_writefn[] = {
6132+ omap_badwidth_write32,
6133+ omap_badwidth_write32,
6134+ omap_tap_write,
6135+};
6136+
6137+void omap_tap_init(struct omap_target_agent_s *ta,
6138+ struct omap_mpu_state_s *mpu)
6139+{
6140+ mpu->tap_base = omap_l4_attach(ta, 0, cpu_register_io_memory(0,
6141+ omap_tap_readfn, omap_tap_writefn, mpu));
6142+}
6143+
6144+/* Power, Reset, and Clock Management */
6145+struct omap_prcm_s {
6146+ target_phys_addr_t base;
6147+ qemu_irq irq[3];
6148+ struct omap_mpu_state_s *mpu;
6149+
6150+ uint32_t irqst[3];
6151+ uint32_t irqen[3];
6152+
6153+ uint32_t sysconfig;
6154+ uint32_t voltctrl;
6155+ uint32_t scratch[20];
6156+
6157+ uint32_t clksrc[1];
6158+ uint32_t clkout[1];
6159+ uint32_t clkemul[1];
6160+ uint32_t clkpol[1];
6161+ uint32_t clksel[8];
6162+ uint32_t clken[12];
6163+ uint32_t clkctrl[4];
6164+ uint32_t clkidle[7];
6165+ uint32_t setuptime[2];
6166+
6167+ uint32_t wkup[3];
6168+ uint32_t wken[3];
6169+ uint32_t wkst[3];
6170+ uint32_t rst[4];
6171+ uint32_t rstctrl[1];
6172+ uint32_t power[4];
6173+ uint32_t rsttime_wkup;
6174+
6175+ uint32_t ev;
6176+ uint32_t evtime[2];
6177+};
6178+
6179+static void omap_prcm_int_update(struct omap_prcm_s *s, int dom)
6180+{
6181+ qemu_set_irq(s->irq[dom], s->irqst[dom] & s->irqen[dom]);
6182+ /* XXX or is the mask applied before PRCM_IRQSTATUS_* ? */
6183+}
6184+
6185+static uint32_t omap_prcm_read(void *opaque, target_phys_addr_t addr)
6186+{
6187+ struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
6188+ int offset = addr - s->base;
6189+
6190+ switch (offset) {
6191+ case 0x000: /* PRCM_REVISION */
6192+ return 0x10;
6193+
6194+ case 0x010: /* PRCM_SYSCONFIG */
6195+ return s->sysconfig;
6196+
6197+ case 0x018: /* PRCM_IRQSTATUS_MPU */
6198+ return s->irqst[0];
6199+
6200+ case 0x01c: /* PRCM_IRQENABLE_MPU */
6201+ return s->irqen[0];
6202+
6203+ case 0x050: /* PRCM_VOLTCTRL */
6204+ return s->voltctrl;
6205+ case 0x054: /* PRCM_VOLTST */
6206+ return s->voltctrl & 3;
6207+
6208+ case 0x060: /* PRCM_CLKSRC_CTRL */
6209+ return s->clksrc[0];
6210+ case 0x070: /* PRCM_CLKOUT_CTRL */
6211+ return s->clkout[0];
6212+ case 0x078: /* PRCM_CLKEMUL_CTRL */
6213+ return s->clkemul[0];
6214+ case 0x080: /* PRCM_CLKCFG_CTRL */
6215+ case 0x084: /* PRCM_CLKCFG_STATUS */
6216+ return 0;
6217+
6218+ case 0x090: /* PRCM_VOLTSETUP */
6219+ return s->setuptime[0];
6220+
6221+ case 0x094: /* PRCM_CLKSSETUP */
6222+ return s->setuptime[1];
6223+
6224+ case 0x098: /* PRCM_POLCTRL */
6225+ return s->clkpol[0];
6226+
6227+ case 0x0b0: /* GENERAL_PURPOSE1 */
6228+ case 0x0b4: /* GENERAL_PURPOSE2 */
6229+ case 0x0b8: /* GENERAL_PURPOSE3 */
6230+ case 0x0bc: /* GENERAL_PURPOSE4 */
6231+ case 0x0c0: /* GENERAL_PURPOSE5 */
6232+ case 0x0c4: /* GENERAL_PURPOSE6 */
6233+ case 0x0c8: /* GENERAL_PURPOSE7 */
6234+ case 0x0cc: /* GENERAL_PURPOSE8 */
6235+ case 0x0d0: /* GENERAL_PURPOSE9 */
6236+ case 0x0d4: /* GENERAL_PURPOSE10 */
6237+ case 0x0d8: /* GENERAL_PURPOSE11 */
6238+ case 0x0dc: /* GENERAL_PURPOSE12 */
6239+ case 0x0e0: /* GENERAL_PURPOSE13 */
6240+ case 0x0e4: /* GENERAL_PURPOSE14 */
6241+ case 0x0e8: /* GENERAL_PURPOSE15 */
6242+ case 0x0ec: /* GENERAL_PURPOSE16 */
6243+ case 0x0f0: /* GENERAL_PURPOSE17 */
6244+ case 0x0f4: /* GENERAL_PURPOSE18 */
6245+ case 0x0f8: /* GENERAL_PURPOSE19 */
6246+ case 0x0fc: /* GENERAL_PURPOSE20 */
6247+ return s->scratch[(offset - 0xb0) >> 2];
6248+
6249+ case 0x140: /* CM_CLKSEL_MPU */
6250+ return s->clksel[0];
6251+ case 0x148: /* CM_CLKSTCTRL_MPU */
6252+ return s->clkctrl[0];
6253+
6254+ case 0x158: /* RM_RSTST_MPU */
6255+ return s->rst[0];
6256+ case 0x1c8: /* PM_WKDEP_MPU */
6257+ return s->wkup[0];
6258+ case 0x1d4: /* PM_EVGENCTRL_MPU */
6259+ return s->ev;
6260+ case 0x1d8: /* PM_EVEGENONTIM_MPU */
6261+ return s->evtime[0];
6262+ case 0x1dc: /* PM_EVEGENOFFTIM_MPU */
6263+ return s->evtime[1];
6264+ case 0x1e0: /* PM_PWSTCTRL_MPU */
6265+ return s->power[0];
6266+ case 0x1e4: /* PM_PWSTST_MPU */
6267+ return 0;
6268+
6269+ case 0x200: /* CM_FCLKEN1_CORE */
6270+ return s->clken[0];
6271+ case 0x204: /* CM_FCLKEN2_CORE */
6272+ return s->clken[1];
6273+ case 0x210: /* CM_ICLKEN1_CORE */
6274+ return s->clken[2];
6275+ case 0x214: /* CM_ICLKEN2_CORE */
6276+ return s->clken[3];
6277+ case 0x21c: /* CM_ICLKEN4_CORE */
6278+ return s->clken[4];
6279+
6280+ case 0x220: /* CM_IDLEST1_CORE */
6281+ /* TODO: check the actual iclk status */
6282+ return 0x7ffffff9;
6283+ case 0x224: /* CM_IDLEST2_CORE */
6284+ /* TODO: check the actual iclk status */
6285+ return 0x00000007;
6286+ case 0x22c: /* CM_IDLEST4_CORE */
6287+ /* TODO: check the actual iclk status */
6288+ return 0x0000001f;
6289+
6290+ case 0x230: /* CM_AUTOIDLE1_CORE */
6291+ return s->clkidle[0];
6292+ case 0x234: /* CM_AUTOIDLE2_CORE */
6293+ return s->clkidle[1];
6294+ case 0x238: /* CM_AUTOIDLE3_CORE */
6295+ return s->clkidle[2];
6296+ case 0x23c: /* CM_AUTOIDLE4_CORE */
6297+ return s->clkidle[3];
6298+
6299+ case 0x240: /* CM_CLKSEL1_CORE */
6300+ return s->clksel[1];
6301+ case 0x244: /* CM_CLKSEL2_CORE */
6302+ return s->clksel[2];
6303+
6304+ case 0x248: /* CM_CLKSTCTRL_CORE */
6305+ return s->clkctrl[1];
6306+
6307+ case 0x2a0: /* PM_WKEN1_CORE */
6308+ return s->wken[0];
6309+ case 0x2a4: /* PM_WKEN2_CORE */
6310+ return s->wken[1];
6311+
6312+ case 0x2b0: /* PM_WKST1_CORE */
6313+ return s->wkst[0];
6314+ case 0x2b4: /* PM_WKST2_CORE */
6315+ return s->wkst[1];
6316+ case 0x2c8: /* PM_WKDEP_CORE */
6317+ return 0x1e;
6318+
6319+ case 0x2e0: /* PM_PWSTCTRL_CORE */
6320+ return s->power[1];
6321+ case 0x2e4: /* PM_PWSTST_CORE */
6322+ return 0x000030 | (s->power[1] & 0xfc00);
6323+
6324+ case 0x300: /* CM_FCLKEN_GFX */
6325+ return s->clken[5];
6326+ case 0x310: /* CM_ICLKEN_GFX */
6327+ return s->clken[6];
6328+ case 0x320: /* CM_IDLEST_GFX */
6329+ /* TODO: check the actual iclk status */
6330+ return 0x00000001;
6331+ case 0x340: /* CM_CLKSEL_GFX */
6332+ return s->clksel[3];
6333+ case 0x348: /* CM_CLKSTCTRL_GFX */
6334+ return s->clkctrl[2];
6335+ case 0x350: /* RM_RSTCTRL_GFX */
6336+ return s->rstctrl[0];
6337+ case 0x358: /* RM_RSTST_GFX */
6338+ return s->rst[1];
6339+ case 0x3c8: /* PM_WKDEP_GFX */
6340+ return s->wkup[1];
6341+
6342+ case 0x3e0: /* PM_PWSTCTRL_GFX */
6343+ return s->power[2];
6344+ case 0x3e4: /* PM_PWSTST_GFX */
6345+ return s->power[2] & 3;
6346+
6347+ case 0x400: /* CM_FCLKEN_WKUP */
6348+ return s->clken[7];
6349+ case 0x410: /* CM_ICLKEN_WKUP */
6350+ return s->clken[8];
6351+ case 0x420: /* CM_IDLEST_WKUP */
6352+ /* TODO: check the actual iclk status */
6353+ return 0x0000003f;
6354+ case 0x430: /* CM_AUTOIDLE_WKUP */
6355+ return s->clkidle[4];
6356+ case 0x440: /* CM_CLKSEL_WKUP */
6357+ return s->clksel[4];
6358+ case 0x450: /* RM_RSTCTRL_WKUP */
6359+ return 0;
6360+ case 0x454: /* RM_RSTTIME_WKUP */
6361+ return s->rsttime_wkup;
6362+ case 0x458: /* RM_RSTST_WKUP */
6363+ return s->rst[2];
6364+ case 0x4a0: /* PM_WKEN_WKUP */
6365+ return s->wken[2];
6366+ case 0x4b0: /* PM_WKST_WKUP */
6367+ return s->wkst[2];
6368+
6369+ case 0x500: /* CM_CLKEN_PLL */
6370+ return s->clken[9];
6371+ case 0x520: /* CM_IDLEST_CKGEN */
6372+ /* Core uses 32-kHz clock */
6373+ if (!(s->clksel[6] & 3))
6374+ return 0x00000377;
6375+ /* DPLL not in lock mode, core uses ref_clk */
6376+ if ((s->clken[9] & 3) != 3)
6377+ return 0x00000375;
6378+ /* Core uses DPLL */
6379+ return 0x00000376;
6380+ case 0x530: /* CM_AUTOIDLE_PLL */
6381+ return s->clkidle[5];
6382+ case 0x540: /* CM_CLKSEL1_PLL */
6383+ return s->clksel[5];
6384+ case 0x544: /* CM_CLKSEL2_PLL */
6385+ return s->clksel[6];
6386+
6387+ case 0x800: /* CM_FCLKEN_DSP */
6388+ return s->clken[10];
6389+ case 0x810: /* CM_ICLKEN_DSP */
6390+ return s->clken[11];
6391+ case 0x820: /* CM_IDLEST_DSP */
6392+ /* TODO: check the actual iclk status */
6393+ return 0x00000103;
6394+ case 0x830: /* CM_AUTOIDLE_DSP */
6395+ return s->clkidle[6];
6396+ case 0x840: /* CM_CLKSEL_DSP */
6397+ return s->clksel[7];
6398+ case 0x848: /* CM_CLKSTCTRL_DSP */
6399+ return s->clkctrl[3];
6400+ case 0x850: /* RM_RSTCTRL_DSP */
6401+ return 0;
6402+ case 0x858: /* RM_RSTST_DSP */
6403+ return s->rst[3];
6404+ case 0x8c8: /* PM_WKDEP_DSP */
6405+ return s->wkup[2];
6406+ case 0x8e0: /* PM_PWSTCTRL_DSP */
6407+ return s->power[3];
6408+ case 0x8e4: /* PM_PWSTST_DSP */
6409+ return 0x008030 | (s->power[3] & 0x3003);
6410+
6411+ case 0x8f0: /* PRCM_IRQSTATUS_DSP */
6412+ return s->irqst[1];
6413+ case 0x8f4: /* PRCM_IRQENABLE_DSP */
6414+ return s->irqen[1];
6415+
6416+ case 0x8f8: /* PRCM_IRQSTATUS_IVA */
6417+ return s->irqst[2];
6418+ case 0x8fc: /* PRCM_IRQENABLE_IVA */
6419+ return s->irqen[2];
6420+ }
6421+
6422+ OMAP_BAD_REG(addr);
6423+ return 0;
6424+}
6425+
6426+static void omap_prcm_write(void *opaque, target_phys_addr_t addr,
6427+ uint32_t value)
6428+{
6429+ struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
6430+ int offset = addr - s->base;
6431+
6432+ switch (offset) {
6433+ case 0x000: /* PRCM_REVISION */
6434+ case 0x054: /* PRCM_VOLTST */
6435+ case 0x084: /* PRCM_CLKCFG_STATUS */
6436+ case 0x1e4: /* PM_PWSTST_MPU */
6437+ case 0x220: /* CM_IDLEST1_CORE */
6438+ case 0x224: /* CM_IDLEST2_CORE */
6439+ case 0x22c: /* CM_IDLEST4_CORE */
6440+ case 0x2c8: /* PM_WKDEP_CORE */
6441+ case 0x2e4: /* PM_PWSTST_CORE */
6442+ case 0x320: /* CM_IDLEST_GFX */
6443+ case 0x3e4: /* PM_PWSTST_GFX */
6444+ case 0x420: /* CM_IDLEST_WKUP */
6445+ case 0x520: /* CM_IDLEST_CKGEN */
6446+ case 0x820: /* CM_IDLEST_DSP */
6447+ case 0x8e4: /* PM_PWSTST_DSP */
6448+ OMAP_RO_REG(addr);
6449+ return;
6450+
6451+ case 0x010: /* PRCM_SYSCONFIG */
6452+ s->sysconfig = value & 1;
6453+ break;
6454+
6455+ case 0x018: /* PRCM_IRQSTATUS_MPU */
6456+ s->irqst[0] &= ~value;
6457+ omap_prcm_int_update(s, 0);
6458+ break;
6459+ case 0x01c: /* PRCM_IRQENABLE_MPU */
6460+ s->irqen[0] = value & 0x3f;
6461+ omap_prcm_int_update(s, 0);
6462+ break;
6463+
6464+ case 0x050: /* PRCM_VOLTCTRL */
6465+ s->voltctrl = value & 0xf1c3;
6466+ break;
6467+
6468+ case 0x060: /* PRCM_CLKSRC_CTRL */
6469+ s->clksrc[0] = value & 0xdb;
6470+ /* TODO update clocks */
6471+ break;
6472+
6473+ case 0x070: /* PRCM_CLKOUT_CTRL */
6474+ s->clkout[0] = value & 0xbbbb;
6475+ /* TODO update clocks */
6476+ break;
6477+
6478+ case 0x078: /* PRCM_CLKEMUL_CTRL */
6479+ s->clkemul[0] = value & 1;
6480+ /* TODO update clocks */
6481+ break;
6482+
6483+ case 0x080: /* PRCM_CLKCFG_CTRL */
6484+ break;
6485+
6486+ case 0x090: /* PRCM_VOLTSETUP */
6487+ s->setuptime[0] = value & 0xffff;
6488+ break;
6489+ case 0x094: /* PRCM_CLKSSETUP */
6490+ s->setuptime[1] = value & 0xffff;
6491+ break;
6492+
6493+ case 0x098: /* PRCM_POLCTRL */
6494+ s->clkpol[0] = value & 0x701;
6495+ break;
6496+
6497+ case 0x0b0: /* GENERAL_PURPOSE1 */
6498+ case 0x0b4: /* GENERAL_PURPOSE2 */
6499+ case 0x0b8: /* GENERAL_PURPOSE3 */
6500+ case 0x0bc: /* GENERAL_PURPOSE4 */
6501+ case 0x0c0: /* GENERAL_PURPOSE5 */
6502+ case 0x0c4: /* GENERAL_PURPOSE6 */
6503+ case 0x0c8: /* GENERAL_PURPOSE7 */
6504+ case 0x0cc: /* GENERAL_PURPOSE8 */
6505+ case 0x0d0: /* GENERAL_PURPOSE9 */
6506+ case 0x0d4: /* GENERAL_PURPOSE10 */
6507+ case 0x0d8: /* GENERAL_PURPOSE11 */
6508+ case 0x0dc: /* GENERAL_PURPOSE12 */
6509+ case 0x0e0: /* GENERAL_PURPOSE13 */
6510+ case 0x0e4: /* GENERAL_PURPOSE14 */
6511+ case 0x0e8: /* GENERAL_PURPOSE15 */
6512+ case 0x0ec: /* GENERAL_PURPOSE16 */
6513+ case 0x0f0: /* GENERAL_PURPOSE17 */
6514+ case 0x0f4: /* GENERAL_PURPOSE18 */
6515+ case 0x0f8: /* GENERAL_PURPOSE19 */
6516+ case 0x0fc: /* GENERAL_PURPOSE20 */
6517+ s->scratch[(offset - 0xb0) >> 2] = value;
6518+ break;
6519+
6520+ case 0x140: /* CM_CLKSEL_MPU */
6521+ s->clksel[0] = value & 0x1f;
6522+ /* TODO update clocks */
6523+ break;
6524+ case 0x148: /* CM_CLKSTCTRL_MPU */
6525+ s->clkctrl[0] = value & 0x1f;
6526+ break;
6527+
6528+ case 0x158: /* RM_RSTST_MPU */
6529+ s->rst[0] &= ~value;
6530+ break;
6531+ case 0x1c8: /* PM_WKDEP_MPU */
6532+ s->wkup[0] = value & 0x15;
6533+ break;
6534+
6535+ case 0x1d4: /* PM_EVGENCTRL_MPU */
6536+ s->ev = value & 0x1f;
6537+ break;
6538+ case 0x1d8: /* PM_EVEGENONTIM_MPU */
6539+ s->evtime[0] = value;
6540+ break;
6541+ case 0x1dc: /* PM_EVEGENOFFTIM_MPU */
6542+ s->evtime[1] = value;
6543+ break;
6544+
6545+ case 0x1e0: /* PM_PWSTCTRL_MPU */
6546+ s->power[0] = value & 0xc0f;
6547+ break;
6548+
6549+ case 0x200: /* CM_FCLKEN1_CORE */
6550+ s->clken[0] = value & 0xbfffffff;
6551+ /* TODO update clocks */
6552+ break;
6553+ case 0x204: /* CM_FCLKEN2_CORE */
6554+ s->clken[1] = value & 0x00000007;
6555+ /* TODO update clocks */
6556+ break;
6557+ case 0x210: /* CM_ICLKEN1_CORE */
6558+ s->clken[2] = value & 0xfffffff9;
6559+ /* TODO update clocks */
6560+ break;
6561+ case 0x214: /* CM_ICLKEN2_CORE */
6562+ s->clken[3] = value & 0x00000007;
6563+ /* TODO update clocks */
6564+ break;
6565+ case 0x21c: /* CM_ICLKEN4_CORE */
6566+ s->clken[4] = value & 0x0000001f;
6567+ /* TODO update clocks */
6568+ break;
6569+
6570+ case 0x230: /* CM_AUTOIDLE1_CORE */
6571+ s->clkidle[0] = value & 0xfffffff9;
6572+ /* TODO update clocks */
6573+ break;
6574+ case 0x234: /* CM_AUTOIDLE2_CORE */
6575+ s->clkidle[1] = value & 0x00000007;
6576+ /* TODO update clocks */
6577+ break;
6578+ case 0x238: /* CM_AUTOIDLE3_CORE */
6579+ s->clkidle[2] = value & 0x00000007;
6580+ /* TODO update clocks */
6581+ break;
6582+ case 0x23c: /* CM_AUTOIDLE4_CORE */
6583+ s->clkidle[3] = value & 0x0000001f;
6584+ /* TODO update clocks */
6585+ break;
6586+
6587+ case 0x240: /* CM_CLKSEL1_CORE */
6588+ s->clksel[1] = value & 0x0fffbf7f;
6589+ /* TODO update clocks */
6590+ break;
6591+
6592+ case 0x244: /* CM_CLKSEL2_CORE */
6593+ s->clksel[2] = value & 0x00fffffc;
6594+ /* TODO update clocks */
6595+ break;
6596+
6597+ case 0x248: /* CM_CLKSTCTRL_CORE */
6598+ s->clkctrl[1] = value & 0x7;
6599+ break;
6600+
6601+ case 0x2a0: /* PM_WKEN1_CORE */
6602+ s->wken[0] = value & 0x04667ff8;
6603+ break;
6604+ case 0x2a4: /* PM_WKEN2_CORE */
6605+ s->wken[1] = value & 0x00000005;
6606+ break;
6607+
6608+ case 0x2b0: /* PM_WKST1_CORE */
6609+ s->wkst[0] &= ~value;
6610+ break;
6611+ case 0x2b4: /* PM_WKST2_CORE */
6612+ s->wkst[1] &= ~value;
6613+ break;
6614+
6615+ case 0x2e0: /* PM_PWSTCTRL_CORE */
6616+ s->power[1] = (value & 0x00fc3f) | (1 << 2);
6617+ break;
6618+
6619+ case 0x300: /* CM_FCLKEN_GFX */
6620+ s->clken[5] = value & 6;
6621+ /* TODO update clocks */
6622+ break;
6623+ case 0x310: /* CM_ICLKEN_GFX */
6624+ s->clken[6] = value & 1;
6625+ /* TODO update clocks */
6626+ break;
6627+ case 0x340: /* CM_CLKSEL_GFX */
6628+ s->clksel[3] = value & 7;
6629+ /* TODO update clocks */
6630+ break;
6631+ case 0x348: /* CM_CLKSTCTRL_GFX */
6632+ s->clkctrl[2] = value & 1;
6633+ break;
6634+ case 0x350: /* RM_RSTCTRL_GFX */
6635+ s->rstctrl[0] = value & 1;
6636+ /* TODO: reset */
6637+ break;
6638+ case 0x358: /* RM_RSTST_GFX */
6639+ s->rst[1] &= ~value;
6640+ break;
6641+ case 0x3c8: /* PM_WKDEP_GFX */
6642+ s->wkup[1] = value & 0x13;
6643+ break;
6644+ case 0x3e0: /* PM_PWSTCTRL_GFX */
6645+ s->power[2] = (value & 0x00c0f) | (3 << 2);
6646+ break;
6647+
6648+ case 0x400: /* CM_FCLKEN_WKUP */
6649+ s->clken[7] = value & 0xd;
6650+ /* TODO update clocks */
6651+ break;
6652+ case 0x410: /* CM_ICLKEN_WKUP */
6653+ s->clken[8] = value & 0x3f;
6654+ /* TODO update clocks */
6655+ break;
6656+ case 0x430: /* CM_AUTOIDLE_WKUP */
6657+ s->clkidle[4] = value & 0x0000003f;
6658+ /* TODO update clocks */
6659+ break;
6660+ case 0x440: /* CM_CLKSEL_WKUP */
6661+ s->clksel[4] = value & 3;
6662+ /* TODO update clocks */
6663+ break;
6664+ case 0x450: /* RM_RSTCTRL_WKUP */
6665+ /* TODO: reset */
6666+ if (value & 2)
6667+ qemu_system_reset_request();
6668+ break;
6669+ case 0x454: /* RM_RSTTIME_WKUP */
6670+ s->rsttime_wkup = value & 0x1fff;
6671+ break;
6672+ case 0x458: /* RM_RSTST_WKUP */
6673+ s->rst[2] &= ~value;
6674+ break;
6675+ case 0x4a0: /* PM_WKEN_WKUP */
6676+ s->wken[2] = value & 0x00000005;
6677+ break;
6678+ case 0x4b0: /* PM_WKST_WKUP */
6679+ s->wkst[2] &= ~value;
6680+ break;
6681+
6682+ case 0x500: /* CM_CLKEN_PLL */
6683+ s->clken[9] = value & 0xcf;
6684+ /* TODO update clocks */
6685+ break;
6686+ case 0x530: /* CM_AUTOIDLE_PLL */
6687+ s->clkidle[5] = value & 0x000000cf;
6688+ /* TODO update clocks */
6689+ break;
6690+ case 0x540: /* CM_CLKSEL1_PLL */
6691+ s->clksel[5] = value & 0x03bfff28;
6692+ /* TODO update clocks */
6693+ break;
6694+ case 0x544: /* CM_CLKSEL2_PLL */
6695+ s->clksel[6] = value & 3;
6696+ /* TODO update clocks */
6697+ break;
6698+
6699+ case 0x800: /* CM_FCLKEN_DSP */
6700+ s->clken[10] = value & 0x501;
6701+ /* TODO update clocks */
6702+ break;
6703+ case 0x810: /* CM_ICLKEN_DSP */
6704+ s->clken[11] = value & 0x2;
6705+ /* TODO update clocks */
6706+ break;
6707+ case 0x830: /* CM_AUTOIDLE_DSP */
6708+ s->clkidle[6] = value & 0x2;
6709+ /* TODO update clocks */
6710+ break;
6711+ case 0x840: /* CM_CLKSEL_DSP */
6712+ s->clksel[7] = value & 0x3fff;
6713+ /* TODO update clocks */
6714+ break;
6715+ case 0x848: /* CM_CLKSTCTRL_DSP */
6716+ s->clkctrl[3] = value & 0x101;
6717+ break;
6718+ case 0x850: /* RM_RSTCTRL_DSP */
6719+ /* TODO: reset */
6720+ break;
6721+ case 0x858: /* RM_RSTST_DSP */
6722+ s->rst[3] &= ~value;
6723+ break;
6724+ case 0x8c8: /* PM_WKDEP_DSP */
6725+ s->wkup[2] = value & 0x13;
6726+ break;
6727+ case 0x8e0: /* PM_PWSTCTRL_DSP */
6728+ s->power[3] = (value & 0x03017) | (3 << 2);
6729+ break;
6730+
6731+ case 0x8f0: /* PRCM_IRQSTATUS_DSP */
6732+ s->irqst[1] &= ~value;
6733+ omap_prcm_int_update(s, 1);
6734+ break;
6735+ case 0x8f4: /* PRCM_IRQENABLE_DSP */
6736+ s->irqen[1] = value & 0x7;
6737+ omap_prcm_int_update(s, 1);
6738+ break;
6739+
6740+ case 0x8f8: /* PRCM_IRQSTATUS_IVA */
6741+ s->irqst[2] &= ~value;
6742+ omap_prcm_int_update(s, 2);
6743+ break;
6744+ case 0x8fc: /* PRCM_IRQENABLE_IVA */
6745+ s->irqen[2] = value & 0x7;
6746+ omap_prcm_int_update(s, 2);
6747+ break;
6748+
6749+ default:
6750+ OMAP_BAD_REG(addr);
6751+ return;
6752+ }
6753+}
6754+
6755+static CPUReadMemoryFunc *omap_prcm_readfn[] = {
6756+ omap_badwidth_read32,
6757+ omap_badwidth_read32,
6758+ omap_prcm_read,
6759+};
6760+
6761+static CPUWriteMemoryFunc *omap_prcm_writefn[] = {
6762+ omap_badwidth_write32,
6763+ omap_badwidth_write32,
6764+ omap_prcm_write,
6765+};
6766+
6767+static void omap_prcm_reset(struct omap_prcm_s *s)
6768+{
6769+ s->sysconfig = 0;
6770+ s->irqst[0] = 0;
6771+ s->irqst[1] = 0;
6772+ s->irqst[2] = 0;
6773+ s->irqen[0] = 0;
6774+ s->irqen[1] = 0;
6775+ s->irqen[2] = 0;
6776+ s->voltctrl = 0x1040;
6777+ s->ev = 0x14;
6778+ s->evtime[0] = 0;
6779+ s->evtime[1] = 0;
6780+ s->clkctrl[0] = 0;
6781+ s->clkctrl[1] = 0;
6782+ s->clkctrl[2] = 0;
6783+ s->clkctrl[3] = 0;
6784+ s->clken[1] = 7;
6785+ s->clken[3] = 7;
6786+ s->clken[4] = 0;
6787+ s->clken[5] = 0;
6788+ s->clken[6] = 0;
6789+ s->clken[7] = 0xc;
6790+ s->clken[8] = 0x3e;
6791+ s->clken[9] = 0x0d;
6792+ s->clken[10] = 0;
6793+ s->clken[11] = 0;
6794+ s->clkidle[0] = 0;
6795+ s->clkidle[2] = 7;
6796+ s->clkidle[3] = 0;
6797+ s->clkidle[4] = 0;
6798+ s->clkidle[5] = 0x0c;
6799+ s->clkidle[6] = 0;
6800+ s->clksel[0] = 0x01;
6801+ s->clksel[1] = 0x02100121;
6802+ s->clksel[2] = 0x00000000;
6803+ s->clksel[3] = 0x01;
6804+ s->clksel[4] = 0;
6805+ s->clksel[7] = 0x0121;
6806+ s->wkup[0] = 0x15;
6807+ s->wkup[1] = 0x13;
6808+ s->wkup[2] = 0x13;
6809+ s->wken[0] = 0x04667ff8;
6810+ s->wken[1] = 0x00000005;
6811+ s->wken[2] = 5;
6812+ s->wkst[0] = 0;
6813+ s->wkst[1] = 0;
6814+ s->wkst[2] = 0;
6815+ s->power[0] = 0x00c;
6816+ s->power[1] = 4;
6817+ s->power[2] = 0x0000c;
6818+ s->power[3] = 0x14;
6819+ s->rstctrl[0] = 1;
6820+ s->rst[3] = 1;
6821+}
6822+
6823+static void omap_prcm_coldreset(struct omap_prcm_s *s)
6824+{
6825+ s->setuptime[0] = 0;
6826+ s->setuptime[1] = 0;
6827+ memset(&s->scratch, 0, sizeof(s->scratch));
6828+ s->rst[0] = 0x01;
6829+ s->rst[1] = 0x00;
6830+ s->rst[2] = 0x01;
6831+ s->clken[0] = 0;
6832+ s->clken[2] = 0;
6833+ s->clkidle[1] = 0;
6834+ s->clksel[5] = 0;
6835+ s->clksel[6] = 2;
6836+ s->clksrc[0] = 0x43;
6837+ s->clkout[0] = 0x0303;
6838+ s->clkemul[0] = 0;
6839+ s->clkpol[0] = 0x100;
6840+ s->rsttime_wkup = 0x1002;
6841+
6842+ omap_prcm_reset(s);
6843+}
6844+
6845+struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
6846+ qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
6847+ struct omap_mpu_state_s *mpu)
6848+{
6849+ int iomemtype;
6850+ struct omap_prcm_s *s = (struct omap_prcm_s *)
6851+ qemu_mallocz(sizeof(struct omap_prcm_s));
6852+
6853+ s->irq[0] = mpu_int;
6854+ s->irq[1] = dsp_int;
6855+ s->irq[2] = iva_int;
6856+ s->mpu = mpu;
6857+ omap_prcm_coldreset(s);
6858+
6859+ iomemtype = cpu_register_io_memory(0, omap_prcm_readfn,
6860+ omap_prcm_writefn, s);
6861+ s->base = omap_l4_attach(ta, 0, iomemtype);
6862+ omap_l4_attach(ta, 1, iomemtype);
6863+
6864+ return s;
6865+}
6866+
6867+/* System and Pinout control */
6868+struct omap_sysctl_s {
6869+ target_phys_addr_t base;
6870+ struct omap_mpu_state_s *mpu;
6871+
6872+ uint32_t sysconfig;
6873+ uint32_t devconfig;
6874+ uint32_t psaconfig;
6875+ uint32_t padconf[0x45];
6876+ uint8_t obs;
6877+ uint32_t msuspendmux[5];
6878+};
6879+
6880+static uint32_t omap_sysctl_read(void *opaque, target_phys_addr_t addr)
6881+{
6882+ struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
6883+ int offset = addr - s->base;
6884+
6885+ switch (offset) {
6886+ case 0x000: /* CONTROL_REVISION */
6887+ return 0x20;
6888+
6889+ case 0x010: /* CONTROL_SYSCONFIG */
6890+ return s->sysconfig;
6891+
6892+ case 0x030 ... 0x140: /* CONTROL_PADCONF - only used in the POP */
6893+ return s->padconf[(offset - 0x30) >> 2];
6894+
6895+ case 0x270: /* CONTROL_DEBOBS */
6896+ return s->obs;
6897+
6898+ case 0x274: /* CONTROL_DEVCONF */
6899+ return s->devconfig;
6900+
6901+ case 0x28c: /* CONTROL_EMU_SUPPORT */
6902+ return 0;
6903+
6904+ case 0x290: /* CONTROL_MSUSPENDMUX_0 */
6905+ return s->msuspendmux[0];
6906+ case 0x294: /* CONTROL_MSUSPENDMUX_1 */
6907+ return s->msuspendmux[1];
6908+ case 0x298: /* CONTROL_MSUSPENDMUX_2 */
6909+ return s->msuspendmux[2];
6910+ case 0x29c: /* CONTROL_MSUSPENDMUX_3 */
6911+ return s->msuspendmux[3];
6912+ case 0x2a0: /* CONTROL_MSUSPENDMUX_4 */
6913+ return s->msuspendmux[4];
6914+ case 0x2a4: /* CONTROL_MSUSPENDMUX_5 */
6915+ return 0;
6916+
6917+ case 0x2b8: /* CONTROL_PSA_CTRL */
6918+ return s->psaconfig;
6919+ case 0x2bc: /* CONTROL_PSA_CMD */
6920+ case 0x2c0: /* CONTROL_PSA_VALUE */
6921+ return 0;
6922+
6923+ case 0x2b0: /* CONTROL_SEC_CTRL */
6924+ return 0x800000f1;
6925+ case 0x2d0: /* CONTROL_SEC_EMU */
6926+ return 0x80000015;
6927+ case 0x2d4: /* CONTROL_SEC_TAP */
6928+ return 0x8000007f;
6929+ case 0x2b4: /* CONTROL_SEC_TEST */
6930+ case 0x2f0: /* CONTROL_SEC_STATUS */
6931+ case 0x2f4: /* CONTROL_SEC_ERR_STATUS */
6932+ /* Secure mode is not present on general-pusrpose device. Outside
6933+ * secure mode these values cannot be read or written. */
6934+ return 0;
6935+
6936+ case 0x2d8: /* CONTROL_OCM_RAM_PERM */
6937+ return 0xff;
6938+ case 0x2dc: /* CONTROL_OCM_PUB_RAM_ADD */
6939+ case 0x2e0: /* CONTROL_EXT_SEC_RAM_START_ADD */
6940+ case 0x2e4: /* CONTROL_EXT_SEC_RAM_STOP_ADD */
6941+ /* No secure mode so no Extended Secure RAM present. */
6942+ return 0;
6943+
6944+ case 0x2f8: /* CONTROL_STATUS */
6945+ /* Device Type => General-purpose */
6946+ return 0x0300;
6947+ case 0x2fc: /* CONTROL_GENERAL_PURPOSE_STATUS */
6948+
6949+ case 0x300: /* CONTROL_RPUB_KEY_H_0 */
6950+ case 0x304: /* CONTROL_RPUB_KEY_H_1 */
6951+ case 0x308: /* CONTROL_RPUB_KEY_H_2 */
6952+ case 0x30c: /* CONTROL_RPUB_KEY_H_3 */
6953+ return 0xdecafbad;
6954+
6955+ case 0x310: /* CONTROL_RAND_KEY_0 */
6956+ case 0x314: /* CONTROL_RAND_KEY_1 */
6957+ case 0x318: /* CONTROL_RAND_KEY_2 */
6958+ case 0x31c: /* CONTROL_RAND_KEY_3 */
6959+ case 0x320: /* CONTROL_CUST_KEY_0 */
6960+ case 0x324: /* CONTROL_CUST_KEY_1 */
6961+ case 0x330: /* CONTROL_TEST_KEY_0 */
6962+ case 0x334: /* CONTROL_TEST_KEY_1 */
6963+ case 0x338: /* CONTROL_TEST_KEY_2 */
6964+ case 0x33c: /* CONTROL_TEST_KEY_3 */
6965+ case 0x340: /* CONTROL_TEST_KEY_4 */
6966+ case 0x344: /* CONTROL_TEST_KEY_5 */
6967+ case 0x348: /* CONTROL_TEST_KEY_6 */
6968+ case 0x34c: /* CONTROL_TEST_KEY_7 */
6969+ case 0x350: /* CONTROL_TEST_KEY_8 */
6970+ case 0x354: /* CONTROL_TEST_KEY_9 */
6971+ /* Can only be accessed in secure mode and when C_FieldAccEnable
6972+ * bit is set in CONTROL_SEC_CTRL.
6973+ * TODO: otherwise an interconnect access error is generated. */
6974+ return 0;
6975+ }
6976+
6977+ OMAP_BAD_REG(addr);
6978+ return 0;
6979+}
6980+
6981+static void omap_sysctl_write(void *opaque, target_phys_addr_t addr,
6982+ uint32_t value)
6983+{
6984+ struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
6985+ int offset = addr - s->base;
6986+
6987+ switch (offset) {
6988+ case 0x000: /* CONTROL_REVISION */
6989+ case 0x2a4: /* CONTROL_MSUSPENDMUX_5 */
6990+ case 0x2c0: /* CONTROL_PSA_VALUE */
6991+ case 0x2f8: /* CONTROL_STATUS */
6992+ case 0x2fc: /* CONTROL_GENERAL_PURPOSE_STATUS */
6993+ case 0x300: /* CONTROL_RPUB_KEY_H_0 */
6994+ case 0x304: /* CONTROL_RPUB_KEY_H_1 */
6995+ case 0x308: /* CONTROL_RPUB_KEY_H_2 */
6996+ case 0x30c: /* CONTROL_RPUB_KEY_H_3 */
6997+ case 0x310: /* CONTROL_RAND_KEY_0 */
6998+ case 0x314: /* CONTROL_RAND_KEY_1 */
6999+ case 0x318: /* CONTROL_RAND_KEY_2 */
7000+ case 0x31c: /* CONTROL_RAND_KEY_3 */
7001+ case 0x320: /* CONTROL_CUST_KEY_0 */
7002+ case 0x324: /* CONTROL_CUST_KEY_1 */
7003+ case 0x330: /* CONTROL_TEST_KEY_0 */
7004+ case 0x334: /* CONTROL_TEST_KEY_1 */
7005+ case 0x338: /* CONTROL_TEST_KEY_2 */
7006+ case 0x33c: /* CONTROL_TEST_KEY_3 */
7007+ case 0x340: /* CONTROL_TEST_KEY_4 */
7008+ case 0x344: /* CONTROL_TEST_KEY_5 */
7009+ case 0x348: /* CONTROL_TEST_KEY_6 */
7010+ case 0x34c: /* CONTROL_TEST_KEY_7 */
7011+ case 0x350: /* CONTROL_TEST_KEY_8 */
7012+ case 0x354: /* CONTROL_TEST_KEY_9 */
7013+ OMAP_RO_REG(addr);
7014+ return;
7015+
7016+ case 0x010: /* CONTROL_SYSCONFIG */
7017+ s->sysconfig = value & 0x1e;
7018+ break;
7019+
7020+ case 0x030 ... 0x140: /* CONTROL_PADCONF - only used in the POP */
7021+ /* XXX: should check constant bits */
7022+ s->padconf[(offset - 0x30) >> 2] = value & 0x1f1f1f1f;
7023+ break;
7024+
7025+ case 0x270: /* CONTROL_DEBOBS */
7026+ s->obs = value & 0xff;
7027+ break;
7028+
7029+ case 0x274: /* CONTROL_DEVCONF */
7030+ s->devconfig = value & 0xffffc7ff;
7031+ break;
7032+
7033+ case 0x28c: /* CONTROL_EMU_SUPPORT */
7034+ break;
7035+
7036+ case 0x290: /* CONTROL_MSUSPENDMUX_0 */
7037+ s->msuspendmux[0] = value & 0x3fffffff;
7038+ break;
7039+ case 0x294: /* CONTROL_MSUSPENDMUX_1 */
7040+ s->msuspendmux[1] = value & 0x3fffffff;
7041+ break;
7042+ case 0x298: /* CONTROL_MSUSPENDMUX_2 */
7043+ s->msuspendmux[2] = value & 0x3fffffff;
7044+ break;
7045+ case 0x29c: /* CONTROL_MSUSPENDMUX_3 */
7046+ s->msuspendmux[3] = value & 0x3fffffff;
7047+ break;
7048+ case 0x2a0: /* CONTROL_MSUSPENDMUX_4 */
7049+ s->msuspendmux[4] = value & 0x3fffffff;
7050+ break;
7051+
7052+ case 0x2b8: /* CONTROL_PSA_CTRL */
7053+ s->psaconfig = value & 0x1c;
7054+ s->psaconfig |= (value & 0x20) ? 2 : 1;
7055+ break;
7056+ case 0x2bc: /* CONTROL_PSA_CMD */
7057+ break;
7058+
7059+ case 0x2b0: /* CONTROL_SEC_CTRL */
7060+ case 0x2b4: /* CONTROL_SEC_TEST */
7061+ case 0x2d0: /* CONTROL_SEC_EMU */
7062+ case 0x2d4: /* CONTROL_SEC_TAP */
7063+ case 0x2d8: /* CONTROL_OCM_RAM_PERM */
7064+ case 0x2dc: /* CONTROL_OCM_PUB_RAM_ADD */
7065+ case 0x2e0: /* CONTROL_EXT_SEC_RAM_START_ADD */
7066+ case 0x2e4: /* CONTROL_EXT_SEC_RAM_STOP_ADD */
7067+ case 0x2f0: /* CONTROL_SEC_STATUS */
7068+ case 0x2f4: /* CONTROL_SEC_ERR_STATUS */
7069+ break;
7070+
7071+ default:
7072+ OMAP_BAD_REG(addr);
7073+ return;
7074+ }
7075+}
7076+
7077+static CPUReadMemoryFunc *omap_sysctl_readfn[] = {
7078+ omap_badwidth_read32, /* TODO */
7079+ omap_badwidth_read32, /* TODO */
7080+ omap_sysctl_read,
7081+};
7082+
7083+static CPUWriteMemoryFunc *omap_sysctl_writefn[] = {
7084+ omap_badwidth_write32, /* TODO */
7085+ omap_badwidth_write32, /* TODO */
7086+ omap_sysctl_write,
7087+};
7088+
7089+static void omap_sysctl_reset(struct omap_sysctl_s *s)
7090+{
7091+ /* (power-on reset) */
7092+ s->sysconfig = 0;
7093+ s->obs = 0;
7094+ s->devconfig = 0x0c000000;
7095+ s->msuspendmux[0] = 0x00000000;
7096+ s->msuspendmux[1] = 0x00000000;
7097+ s->msuspendmux[2] = 0x00000000;
7098+ s->msuspendmux[3] = 0x00000000;
7099+ s->msuspendmux[4] = 0x00000000;
7100+ s->psaconfig = 1;
7101+
7102+ s->padconf[0x00] = 0x000f0f0f;
7103+ s->padconf[0x01] = 0x00000000;
7104+ s->padconf[0x02] = 0x00000000;
7105+ s->padconf[0x03] = 0x00000000;
7106+ s->padconf[0x04] = 0x00000000;
7107+ s->padconf[0x05] = 0x00000000;
7108+ s->padconf[0x06] = 0x00000000;
7109+ s->padconf[0x07] = 0x00000000;
7110+ s->padconf[0x08] = 0x08080800;
7111+ s->padconf[0x09] = 0x08080808;
7112+ s->padconf[0x0a] = 0x08080808;
7113+ s->padconf[0x0b] = 0x08080808;
7114+ s->padconf[0x0c] = 0x08080808;
7115+ s->padconf[0x0d] = 0x08080800;
7116+ s->padconf[0x0e] = 0x08080808;
7117+ s->padconf[0x0f] = 0x08080808;
7118+ s->padconf[0x10] = 0x18181808; /* | 0x07070700 if SBoot3 */
7119+ s->padconf[0x11] = 0x18181818; /* | 0x07070707 if SBoot3 */
7120+ s->padconf[0x12] = 0x18181818; /* | 0x07070707 if SBoot3 */
7121+ s->padconf[0x13] = 0x18181818; /* | 0x07070707 if SBoot3 */
7122+ s->padconf[0x14] = 0x18181818; /* | 0x00070707 if SBoot3 */
7123+ s->padconf[0x15] = 0x18181818;
7124+ s->padconf[0x16] = 0x18181818; /* | 0x07000000 if SBoot3 */
7125+ s->padconf[0x17] = 0x1f001f00;
7126+ s->padconf[0x18] = 0x1f1f1f1f;
7127+ s->padconf[0x19] = 0x00000000;
7128+ s->padconf[0x1a] = 0x1f180000;
7129+ s->padconf[0x1b] = 0x00001f1f;
7130+ s->padconf[0x1c] = 0x1f001f00;
7131+ s->padconf[0x1d] = 0x00000000;
7132+ s->padconf[0x1e] = 0x00000000;
7133+ s->padconf[0x1f] = 0x08000000;
7134+ s->padconf[0x20] = 0x08080808;
7135+ s->padconf[0x21] = 0x08080808;
7136+ s->padconf[0x22] = 0x0f080808;
7137+ s->padconf[0x23] = 0x0f0f0f0f;
7138+ s->padconf[0x24] = 0x000f0f0f;
7139+ s->padconf[0x25] = 0x1f1f1f0f;
7140+ s->padconf[0x26] = 0x080f0f1f;
7141+ s->padconf[0x27] = 0x070f1808;
7142+ s->padconf[0x28] = 0x0f070707;
7143+ s->padconf[0x29] = 0x000f0f1f;
7144+ s->padconf[0x2a] = 0x0f0f0f1f;
7145+ s->padconf[0x2b] = 0x08000000;
7146+ s->padconf[0x2c] = 0x0000001f;
7147+ s->padconf[0x2d] = 0x0f0f1f00;
7148+ s->padconf[0x2e] = 0x1f1f0f0f;
7149+ s->padconf[0x2f] = 0x0f1f1f1f;
7150+ s->padconf[0x30] = 0x0f0f0f0f;
7151+ s->padconf[0x31] = 0x0f1f0f1f;
7152+ s->padconf[0x32] = 0x0f0f0f0f;
7153+ s->padconf[0x33] = 0x0f1f0f1f;
7154+ s->padconf[0x34] = 0x1f1f0f0f;
7155+ s->padconf[0x35] = 0x0f0f1f1f;
7156+ s->padconf[0x36] = 0x0f0f1f0f;
7157+ s->padconf[0x37] = 0x0f0f0f0f;
7158+ s->padconf[0x38] = 0x1f18180f;
7159+ s->padconf[0x39] = 0x1f1f1f1f;
7160+ s->padconf[0x3a] = 0x00001f1f;
7161+ s->padconf[0x3b] = 0x00000000;
7162+ s->padconf[0x3c] = 0x00000000;
7163+ s->padconf[0x3d] = 0x0f0f0f0f;
7164+ s->padconf[0x3e] = 0x18000f0f;
7165+ s->padconf[0x3f] = 0x00070000;
7166+ s->padconf[0x40] = 0x00000707;
7167+ s->padconf[0x41] = 0x0f1f0700;
7168+ s->padconf[0x42] = 0x1f1f070f;
7169+ s->padconf[0x43] = 0x0008081f;
7170+ s->padconf[0x44] = 0x00000800;
7171+}
7172+
7173+struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
7174+ omap_clk iclk, struct omap_mpu_state_s *mpu)
7175+{
7176+ int iomemtype;
7177+ struct omap_sysctl_s *s = (struct omap_sysctl_s *)
7178+ qemu_mallocz(sizeof(struct omap_sysctl_s));
7179+
7180+ s->mpu = mpu;
7181+ omap_sysctl_reset(s);
7182+
7183+ iomemtype = cpu_register_io_memory(0, omap_sysctl_readfn,
7184+ omap_sysctl_writefn, s);
7185+ s->base = omap_l4_attach(ta, 0, iomemtype);
7186+ omap_l4_attach(ta, 0, iomemtype);
7187+
7188+ return s;
7189+}
7190+
7191+/* SDRAM Controller Subsystem */
7192+struct omap_sdrc_s {
7193+ target_phys_addr_t base;
7194+
7195+ uint8_t config;
7196+};
7197+
7198+static void omap_sdrc_reset(struct omap_sdrc_s *s)
7199+{
7200+ s->config = 0x10;
7201+}
7202+
7203+static uint32_t omap_sdrc_read(void *opaque, target_phys_addr_t addr)
7204+{
7205+ struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
7206+ int offset = addr - s->base;
7207+
7208+ switch (offset) {
7209+ case 0x00: /* SDRC_REVISION */
7210+ return 0x20;
7211+
7212+ case 0x10: /* SDRC_SYSCONFIG */
7213+ return s->config;
7214+
7215+ case 0x14: /* SDRC_SYSSTATUS */
7216+ return 1; /* RESETDONE */
7217+
7218+ case 0x40: /* SDRC_CS_CFG */
7219+ case 0x44: /* SDRC_SHARING */
7220+ case 0x48: /* SDRC_ERR_ADDR */
7221+ case 0x4c: /* SDRC_ERR_TYPE */
7222+ case 0x60: /* SDRC_DLLA_SCTRL */
7223+ case 0x64: /* SDRC_DLLA_STATUS */
7224+ case 0x68: /* SDRC_DLLB_CTRL */
7225+ case 0x6c: /* SDRC_DLLB_STATUS */
7226+ case 0x70: /* SDRC_POWER */
7227+ case 0x80: /* SDRC_MCFG_0 */
7228+ case 0x84: /* SDRC_MR_0 */
7229+ case 0x88: /* SDRC_EMR1_0 */
7230+ case 0x8c: /* SDRC_EMR2_0 */
7231+ case 0x90: /* SDRC_EMR3_0 */
7232+ case 0x94: /* SDRC_DCDL1_CTRL */
7233+ case 0x98: /* SDRC_DCDL2_CTRL */
7234+ case 0x9c: /* SDRC_ACTIM_CTRLA_0 */
7235+ case 0xa0: /* SDRC_ACTIM_CTRLB_0 */
7236+ case 0xa4: /* SDRC_RFR_CTRL_0 */
7237+ case 0xa8: /* SDRC_MANUAL_0 */
7238+ case 0xb0: /* SDRC_MCFG_1 */
7239+ case 0xb4: /* SDRC_MR_1 */
7240+ case 0xb8: /* SDRC_EMR1_1 */
7241+ case 0xbc: /* SDRC_EMR2_1 */
7242+ case 0xc0: /* SDRC_EMR3_1 */
7243+ case 0xc4: /* SDRC_ACTIM_CTRLA_1 */
7244+ case 0xc8: /* SDRC_ACTIM_CTRLB_1 */
7245+ case 0xd4: /* SDRC_RFR_CTRL_1 */
7246+ case 0xd8: /* SDRC_MANUAL_1 */
7247+ return 0x00;
7248+ }
7249+
7250+ OMAP_BAD_REG(addr);
7251+ return 0;
7252+}
7253+
7254+static void omap_sdrc_write(void *opaque, target_phys_addr_t addr,
7255+ uint32_t value)
7256+{
7257+ struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
7258+ int offset = addr - s->base;
7259+
7260+ switch (offset) {
7261+ case 0x00: /* SDRC_REVISION */
7262+ case 0x14: /* SDRC_SYSSTATUS */
7263+ case 0x48: /* SDRC_ERR_ADDR */
7264+ case 0x64: /* SDRC_DLLA_STATUS */
7265+ case 0x6c: /* SDRC_DLLB_STATUS */
7266+ OMAP_RO_REG(addr);
7267+ return;
7268+
7269+ case 0x10: /* SDRC_SYSCONFIG */
7270+ if ((value >> 3) != 0x2)
7271+ fprintf(stderr, "%s: bad SDRAM idle mode %i\n",
7272+ __FUNCTION__, value >> 3);
7273+ if (value & 2)
7274+ omap_sdrc_reset(s);
7275+ s->config = value & 0x18;
7276+ break;
7277+
7278+ case 0x40: /* SDRC_CS_CFG */
7279+ case 0x44: /* SDRC_SHARING */
7280+ case 0x4c: /* SDRC_ERR_TYPE */
7281+ case 0x60: /* SDRC_DLLA_SCTRL */
7282+ case 0x68: /* SDRC_DLLB_CTRL */
7283+ case 0x70: /* SDRC_POWER */
7284+ case 0x80: /* SDRC_MCFG_0 */
7285+ case 0x84: /* SDRC_MR_0 */
7286+ case 0x88: /* SDRC_EMR1_0 */
7287+ case 0x8c: /* SDRC_EMR2_0 */
7288+ case 0x90: /* SDRC_EMR3_0 */
7289+ case 0x94: /* SDRC_DCDL1_CTRL */
7290+ case 0x98: /* SDRC_DCDL2_CTRL */
7291+ case 0x9c: /* SDRC_ACTIM_CTRLA_0 */
7292+ case 0xa0: /* SDRC_ACTIM_CTRLB_0 */
7293+ case 0xa4: /* SDRC_RFR_CTRL_0 */
7294+ case 0xa8: /* SDRC_MANUAL_0 */
7295+ case 0xb0: /* SDRC_MCFG_1 */
7296+ case 0xb4: /* SDRC_MR_1 */
7297+ case 0xb8: /* SDRC_EMR1_1 */
7298+ case 0xbc: /* SDRC_EMR2_1 */
7299+ case 0xc0: /* SDRC_EMR3_1 */
7300+ case 0xc4: /* SDRC_ACTIM_CTRLA_1 */
7301+ case 0xc8: /* SDRC_ACTIM_CTRLB_1 */
7302+ case 0xd4: /* SDRC_RFR_CTRL_1 */
7303+ case 0xd8: /* SDRC_MANUAL_1 */
7304+ break;
7305+
7306+ default:
7307+ OMAP_BAD_REG(addr);
7308+ return;
7309+ }
7310+}
7311+
7312+static CPUReadMemoryFunc *omap_sdrc_readfn[] = {
7313+ omap_badwidth_read32,
7314+ omap_badwidth_read32,
7315+ omap_sdrc_read,
7316+};
7317+
7318+static CPUWriteMemoryFunc *omap_sdrc_writefn[] = {
7319+ omap_badwidth_write32,
7320+ omap_badwidth_write32,
7321+ omap_sdrc_write,
7322+};
7323+
7324+struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base)
7325+{
7326+ int iomemtype;
7327+ struct omap_sdrc_s *s = (struct omap_sdrc_s *)
7328+ qemu_mallocz(sizeof(struct omap_sdrc_s));
7329+
7330+ s->base = base;
7331+ omap_sdrc_reset(s);
7332+
7333+ iomemtype = cpu_register_io_memory(0, omap_sdrc_readfn,
7334+ omap_sdrc_writefn, s);
7335+ cpu_register_physical_memory(s->base, 0x1000, iomemtype);
7336+
7337+ return s;
7338+}
7339+
7340+/* General-Purpose Memory Controller */
7341+struct omap_gpmc_s {
7342+ target_phys_addr_t base;
7343+ qemu_irq irq;
7344+
7345+ uint8_t sysconfig;
7346+ uint16_t irqst;
7347+ uint16_t irqen;
7348+ uint16_t timeout;
7349+ uint16_t config;
7350+ uint32_t prefconfig[2];
7351+ int prefcontrol;
7352+ int preffifo;
7353+ int prefcount;
7354+ struct omap_gpmc_cs_file_s {
7355+ uint32_t config[7];
7356+ target_phys_addr_t base;
7357+ size_t size;
7358+ int iomemtype;
7359+ void (*base_update)(void *opaque, target_phys_addr_t new);
7360+ void (*unmap)(void *opaque);
7361+ void *opaque;
7362+ } cs_file[8];
7363+ int ecc_cs;
7364+ int ecc_ptr;
7365+ uint32_t ecc_cfg;
7366+ struct ecc_state_s ecc[9];
7367+};
7368+
7369+static void omap_gpmc_int_update(struct omap_gpmc_s *s)
7370+{
7371+ qemu_set_irq(s->irq, s->irqen & s->irqst);
7372+}
7373+
7374+static void omap_gpmc_cs_map(struct omap_gpmc_cs_file_s *f, int base, int mask)
7375+{
7376+ /* TODO: check for overlapping regions and report access errors */
7377+ if ((mask != 0x8 && mask != 0xc && mask != 0xe && mask != 0xf) ||
7378+ (base < 0 || base >= 0x40) ||
7379+ (base & 0x0f & ~mask)) {
7380+ fprintf(stderr, "%s: wrong cs address mapping/decoding!\n",
7381+ __FUNCTION__);
7382+ return;
7383+ }
7384+
7385+ if (!f->opaque)
7386+ return;
7387+
7388+ f->base = base << 24;
7389+ f->size = (0x0fffffff & ~(mask << 24)) + 1;
7390+ /* TODO: rather than setting the size of the mapping (which should be
7391+ * constant), the mask should cause wrapping of the address space, so
7392+ * that the same memory becomes accessible at every <i>size</i> bytes
7393+ * starting from <i>base</i>. */
7394+ if (f->iomemtype)
7395+ cpu_register_physical_memory(f->base, f->size, f->iomemtype);
7396+
7397+ if (f->base_update)
7398+ f->base_update(f->opaque, f->base);
7399+}
7400+
7401+static void omap_gpmc_cs_unmap(struct omap_gpmc_cs_file_s *f)
7402+{
7403+ if (f->size) {
7404+ if (f->unmap)
7405+ f->unmap(f->opaque);
7406+ if (f->iomemtype)
7407+ cpu_register_physical_memory(f->base, f->size, IO_MEM_UNASSIGNED);
7408+ f->base = 0;
7409+ f->size = 0;
7410+ }
7411+}
7412+
7413+static void omap_gpmc_reset(struct omap_gpmc_s *s)
7414+{
7415+ int i;
7416+
7417+ s->sysconfig = 0;
7418+ s->irqst = 0;
7419+ s->irqen = 0;
7420+ omap_gpmc_int_update(s);
7421+ s->timeout = 0;
7422+ s->config = 0xa00;
7423+ s->prefconfig[0] = 0x00004000;
7424+ s->prefconfig[1] = 0x00000000;
7425+ s->prefcontrol = 0;
7426+ s->preffifo = 0;
7427+ s->prefcount = 0;
7428+ for (i = 0; i < 8; i ++) {
7429+ if (s->cs_file[i].config[6] & (1 << 6)) /* CSVALID */
7430+ omap_gpmc_cs_unmap(s->cs_file + i);
7431+ s->cs_file[i].config[0] = i ? 1 << 12 : 0;
7432+ s->cs_file[i].config[1] = 0x101001;
7433+ s->cs_file[i].config[2] = 0x020201;
7434+ s->cs_file[i].config[3] = 0x10031003;
7435+ s->cs_file[i].config[4] = 0x10f1111;
7436+ s->cs_file[i].config[5] = 0;
7437+ s->cs_file[i].config[6] = 0xf00 | (i ? 0 : 1 << 6);
7438+ if (s->cs_file[i].config[6] & (1 << 6)) /* CSVALID */
7439+ omap_gpmc_cs_map(&s->cs_file[i],
7440+ s->cs_file[i].config[6] & 0x1f, /* MASKADDR */
7441+ (s->cs_file[i].config[6] >> 8 & 0xf)); /* BASEADDR */
7442+ }
7443+ omap_gpmc_cs_map(s->cs_file, 0, 0xf);
7444+ s->ecc_cs = 0;
7445+ s->ecc_ptr = 0;
7446+ s->ecc_cfg = 0x3fcff000;
7447+ for (i = 0; i < 9; i ++)
7448+ ecc_reset(&s->ecc[i]);
7449+}
7450+
7451+static uint32_t omap_gpmc_read(void *opaque, target_phys_addr_t addr)
7452+{
7453+ struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
7454+ int offset = addr - s->base;
7455+ int cs;
7456+ struct omap_gpmc_cs_file_s *f;
7457+
7458+ switch (offset) {
7459+ case 0x000: /* GPMC_REVISION */
7460+ return 0x20;
7461+
7462+ case 0x010: /* GPMC_SYSCONFIG */
7463+ return s->sysconfig;
7464+
7465+ case 0x014: /* GPMC_SYSSTATUS */
7466+ return 1; /* RESETDONE */
7467+
7468+ case 0x018: /* GPMC_IRQSTATUS */
7469+ return s->irqst;
7470+
7471+ case 0x01c: /* GPMC_IRQENABLE */
7472+ return s->irqen;
7473+
7474+ case 0x040: /* GPMC_TIMEOUT_CONTROL */
7475+ return s->timeout;
7476+
7477+ case 0x044: /* GPMC_ERR_ADDRESS */
7478+ case 0x048: /* GPMC_ERR_TYPE */
7479+ return 0;
7480+
7481+ case 0x050: /* GPMC_CONFIG */
7482+ return s->config;
7483+
7484+ case 0x054: /* GPMC_STATUS */
7485+ return 0x001;
7486+
7487+ case 0x060 ... 0x1d4:
7488+ cs = (offset - 0x060) / 0x30;
7489+ offset -= cs * 0x30;
7490+ f = s->cs_file + cs;
7491+ switch (offset - cs * 0x30) {
7492+ case 0x60: /* GPMC_CONFIG1 */
7493+ return f->config[0];
7494+ case 0x64: /* GPMC_CONFIG2 */
7495+ return f->config[1];
7496+ case 0x68: /* GPMC_CONFIG3 */
7497+ return f->config[2];
7498+ case 0x6c: /* GPMC_CONFIG4 */
7499+ return f->config[3];
7500+ case 0x70: /* GPMC_CONFIG5 */
7501+ return f->config[4];
7502+ case 0x74: /* GPMC_CONFIG6 */
7503+ return f->config[5];
7504+ case 0x78: /* GPMC_CONFIG7 */
7505+ return f->config[6];
7506+ case 0x84: /* GPMC_NAND_DATA */
7507+ return 0;
7508+ }
7509+ break;
7510+
7511+ case 0x1e0: /* GPMC_PREFETCH_CONFIG1 */
7512+ return s->prefconfig[0];
7513+ case 0x1e4: /* GPMC_PREFETCH_CONFIG2 */
7514+ return s->prefconfig[1];
7515+ case 0x1ec: /* GPMC_PREFETCH_CONTROL */
7516+ return s->prefcontrol;
7517+ case 0x1f0: /* GPMC_PREFETCH_STATUS */
7518+ return (s->preffifo << 24) |
7519+ ((s->preffifo >
7520+ ((s->prefconfig[0] >> 8) & 0x7f) ? 1 : 0) << 16) |
7521+ s->prefcount;
7522+
7523+ case 0x1f4: /* GPMC_ECC_CONFIG */
7524+ return s->ecc_cs;
7525+ case 0x1f8: /* GPMC_ECC_CONTROL */
7526+ return s->ecc_ptr;
7527+ case 0x1fc: /* GPMC_ECC_SIZE_CONFIG */
7528+ return s->ecc_cfg;
7529+ case 0x200 ... 0x220: /* GPMC_ECC_RESULT */
7530+ cs = (offset & 0x1f) >> 2;
7531+ /* TODO: check correctness */
7532+ return
7533+ ((s->ecc[cs].cp & 0x07) << 0) |
7534+ ((s->ecc[cs].cp & 0x38) << 13) |
7535+ ((s->ecc[cs].lp[0] & 0x1ff) << 3) |
7536+ ((s->ecc[cs].lp[1] & 0x1ff) << 19);
7537+
7538+ case 0x230: /* GPMC_TESTMODE_CTRL */
7539+ return 0;
7540+ case 0x234: /* GPMC_PSA_LSB */
7541+ case 0x238: /* GPMC_PSA_MSB */
7542+ return 0x00000000;
7543+ }
7544+
7545+ OMAP_BAD_REG(addr);
7546+ return 0;
7547+}
7548+
7549+static void omap_gpmc_write(void *opaque, target_phys_addr_t addr,
7550+ uint32_t value)
7551+{
7552+ struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
7553+ int offset = addr - s->base;
7554+ int cs;
7555+ struct omap_gpmc_cs_file_s *f;
7556+
7557+ switch (offset) {
7558+ case 0x000: /* GPMC_REVISION */
7559+ case 0x014: /* GPMC_SYSSTATUS */
7560+ case 0x054: /* GPMC_STATUS */
7561+ case 0x1f0: /* GPMC_PREFETCH_STATUS */
7562+ case 0x200 ... 0x220: /* GPMC_ECC_RESULT */
7563+ case 0x234: /* GPMC_PSA_LSB */
7564+ case 0x238: /* GPMC_PSA_MSB */
7565+ OMAP_RO_REG(addr);
7566+ break;
7567+
7568+ case 0x010: /* GPMC_SYSCONFIG */
7569+ if ((value >> 3) == 0x3)
7570+ fprintf(stderr, "%s: bad SDRAM idle mode %i\n",
7571+ __FUNCTION__, value >> 3);
7572+ if (value & 2)
7573+ omap_gpmc_reset(s);
7574+ s->sysconfig = value & 0x19;
7575+ break;
7576+
7577+ case 0x018: /* GPMC_IRQSTATUS */
7578+ s->irqen = ~value;
7579+ omap_gpmc_int_update(s);
7580+ break;
7581+
7582+ case 0x01c: /* GPMC_IRQENABLE */
7583+ s->irqen = value & 0xf03;
7584+ omap_gpmc_int_update(s);
7585+ break;
7586+
7587+ case 0x040: /* GPMC_TIMEOUT_CONTROL */
7588+ s->timeout = value & 0x1ff1;
7589+ break;
7590+
7591+ case 0x044: /* GPMC_ERR_ADDRESS */
7592+ case 0x048: /* GPMC_ERR_TYPE */
7593+ break;
7594+
7595+ case 0x050: /* GPMC_CONFIG */
7596+ s->config = value & 0xf13;
7597+ break;
7598+
7599+ case 0x060 ... 0x1d4:
7600+ cs = (offset - 0x060) / 0x30;
7601+ offset -= cs * 0x30;
7602+ f = s->cs_file + cs;
7603+ switch (offset - cs * 0x30) {
7604+ case 0x60: /* GPMC_CONFIG1 */
7605+ f->config[0] = value & 0xffef3e13;
7606+ break;
7607+ case 0x64: /* GPMC_CONFIG2 */
7608+ f->config[1] = value & 0x001f1f8f;
7609+ break;
7610+ case 0x68: /* GPMC_CONFIG3 */
7611+ f->config[2] = value & 0x001f1f8f;
7612+ break;
7613+ case 0x6c: /* GPMC_CONFIG4 */
7614+ f->config[3] = value & 0x1f8f1f8f;
7615+ break;
7616+ case 0x70: /* GPMC_CONFIG5 */
7617+ f->config[4] = value & 0x0f1f1f1f;
7618+ break;
7619+ case 0x74: /* GPMC_CONFIG6 */
7620+ f->config[5] = value & 0x00000fcf;
7621+ break;
7622+ case 0x78: /* GPMC_CONFIG7 */
7623+ if ((f->config[6] ^ value) & 0xf7f) {
7624+ if (f->config[6] & (1 << 6)) /* CSVALID */
7625+ omap_gpmc_cs_unmap(f);
7626+ if (value & (1 << 6)) /* CSVALID */
7627+ omap_gpmc_cs_map(f, value & 0x1f, /* MASKADDR */
7628+ (value >> 8 & 0xf)); /* BASEADDR */
7629+ }
7630+ f->config[6] = value & 0x00000f7f;
7631+ break;
7632+ case 0x7c: /* GPMC_NAND_COMMAND */
7633+ case 0x80: /* GPMC_NAND_ADDRESS */
7634+ case 0x84: /* GPMC_NAND_DATA */
7635+ break;
7636+
7637+ default:
7638+ goto bad_reg;
7639+ }
7640+ break;
7641+
7642+ case 0x1e0: /* GPMC_PREFETCH_CONFIG1 */
7643+ s->prefconfig[0] = value & 0x7f8f7fbf;
7644+ /* TODO: update interrupts, fifos, dmas */
7645+ break;
7646+
7647+ case 0x1e4: /* GPMC_PREFETCH_CONFIG2 */
7648+ s->prefconfig[1] = value & 0x3fff;
7649+ break;
7650+
7651+ case 0x1ec: /* GPMC_PREFETCH_CONTROL */
7652+ s->prefcontrol = value & 1;
7653+ if (s->prefcontrol) {
7654+ if (s->prefconfig[0] & 1)
7655+ s->preffifo = 0x40;
7656+ else
7657+ s->preffifo = 0x00;
7658+ }
7659+ /* TODO: start */
7660+ break;
7661+
7662+ case 0x1f4: /* GPMC_ECC_CONFIG */
7663+ s->ecc_cs = 0x8f;
7664+ break;
7665+ case 0x1f8: /* GPMC_ECC_CONTROL */
7666+ if (value & (1 << 8))
7667+ for (cs = 0; cs < 9; cs ++)
7668+ ecc_reset(&s->ecc[cs]);
7669+ s->ecc_ptr = value & 0xf;
7670+ if (s->ecc_ptr == 0 || s->ecc_ptr > 9) {
7671+ s->ecc_ptr = 0;
7672+ s->ecc_cs &= ~1;
7673+ }
7674+ break;
7675+ case 0x1fc: /* GPMC_ECC_SIZE_CONFIG */
7676+ s->ecc_cfg = value & 0x3fcff1ff;
7677+ break;
7678+ case 0x230: /* GPMC_TESTMODE_CTRL */
7679+ if (value & 7)
7680+ fprintf(stderr, "%s: test mode enable attempt\n", __FUNCTION__);
7681+ break;
7682+
7683+ default:
7684+ bad_reg:
7685+ OMAP_BAD_REG(addr);
7686+ return;
7687+ }
7688+}
7689+
7690+static CPUReadMemoryFunc *omap_gpmc_readfn[] = {
7691+ omap_badwidth_read32, /* TODO */
7692+ omap_badwidth_read32, /* TODO */
7693+ omap_gpmc_read,
7694+};
7695+
7696+static CPUWriteMemoryFunc *omap_gpmc_writefn[] = {
7697+ omap_badwidth_write32, /* TODO */
7698+ omap_badwidth_write32, /* TODO */
7699+ omap_gpmc_write,
7700+};
7701+
7702+struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq)
7703+{
7704+ int iomemtype;
7705+ struct omap_gpmc_s *s = (struct omap_gpmc_s *)
7706+ qemu_mallocz(sizeof(struct omap_gpmc_s));
7707+
7708+ s->base = base;
7709+ omap_gpmc_reset(s);
7710+
7711+ iomemtype = cpu_register_io_memory(0, omap_gpmc_readfn,
7712+ omap_gpmc_writefn, s);
7713+ cpu_register_physical_memory(s->base, 0x1000, iomemtype);
7714+
7715+ return s;
7716+}
7717+
7718+void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
7719+ void (*base_upd)(void *opaque, target_phys_addr_t new),
7720+ void (*unmap)(void *opaque), void *opaque)
7721+{
7722+ struct omap_gpmc_cs_file_s *f;
7723+
7724+ if (cs < 0 || cs >= 8) {
7725+ fprintf(stderr, "%s: bad chip-select %i\n", __FUNCTION__, cs);
7726+ exit(-1);
7727+ }
7728+ f = &s->cs_file[cs];
7729+
7730+ f->iomemtype = iomemtype;
7731+ f->base_update = base_upd;
7732+ f->unmap = unmap;
7733+ f->opaque = opaque;
7734+
7735+ if (f->config[6] & (1 << 6)) /* CSVALID */
7736+ omap_gpmc_cs_map(f, f->config[6] & 0x1f, /* MASKADDR */
7737+ (f->config[6] >> 8 & 0xf)); /* BASEADDR */
7738+}
7739+
7740+/* General chip reset */
7741+static void omap2_mpu_reset(void *opaque)
7742+{
7743+ struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
7744+
7745+ omap_inth_reset(mpu->ih[0]);
7746+ omap_dma_reset(mpu->dma);
7747+ omap_prcm_reset(mpu->prcm);
7748+ omap_sysctl_reset(mpu->sysc);
7749+ omap_gp_timer_reset(mpu->gptimer[0]);
7750+ omap_gp_timer_reset(mpu->gptimer[1]);
7751+ omap_gp_timer_reset(mpu->gptimer[2]);
7752+ omap_gp_timer_reset(mpu->gptimer[3]);
7753+ omap_gp_timer_reset(mpu->gptimer[4]);
7754+ omap_gp_timer_reset(mpu->gptimer[5]);
7755+ omap_gp_timer_reset(mpu->gptimer[6]);
7756+ omap_gp_timer_reset(mpu->gptimer[7]);
7757+ omap_gp_timer_reset(mpu->gptimer[8]);
7758+ omap_gp_timer_reset(mpu->gptimer[9]);
7759+ omap_gp_timer_reset(mpu->gptimer[10]);
7760+ omap_gp_timer_reset(mpu->gptimer[11]);
7761+ omap_synctimer_reset(&mpu->synctimer);
7762+ omap_sdrc_reset(mpu->sdrc);
7763+ omap_gpmc_reset(mpu->gpmc);
7764+ omap_dss_reset(mpu->dss);
7765+#if 0
7766+ omap_wd_timer_reset(mpu->wdt);
7767+ omap_ulpd_pm_reset(mpu);
7768+ omap_pin_cfg_reset(mpu);
7769+ omap_mpui_reset(mpu);
7770+ omap_tipb_bridge_reset(mpu->private_tipb);
7771+ omap_tipb_bridge_reset(mpu->public_tipb);
7772+ omap_dpll_reset(&mpu->dpll[0]);
7773+ omap_dpll_reset(&mpu->dpll[1]);
7774+ omap_dpll_reset(&mpu->dpll[2]);
7775+#endif
7776+ omap_uart_reset(mpu->uart[0]);
7777+ omap_uart_reset(mpu->uart[1]);
7778+ omap_uart_reset(mpu->uart[2]);
7779+ omap_mmc_reset(mpu->mmc);
7780+ omap_gpif_reset(mpu->gpif);
7781+ omap_mcspi_reset(mpu->mcspi[0]);
7782+ omap_mcspi_reset(mpu->mcspi[1]);
7783+#if 0
7784+ omap_pwl_reset(mpu);
7785+ omap_pwt_reset(mpu);
7786+#endif
7787+ omap_i2c_reset(mpu->i2c[0]);
7788+ omap_i2c_reset(mpu->i2c[1]);
7789+#if 0
7790+ omap_rtc_reset(mpu->rtc);
7791+ omap_mcbsp_reset(mpu->mcbsp1);
7792+ omap_mcbsp_reset(mpu->mcbsp2);
7793+ omap_mcbsp_reset(mpu->mcbsp3);
7794+ omap_lpg_reset(mpu->led[0]);
7795+ omap_lpg_reset(mpu->led[1]);
7796+ omap_clkm_reset(mpu);
7797+#endif
7798+ cpu_reset(mpu->env);
7799+}
7800+
7801+static int omap2_validate_addr(struct omap_mpu_state_s *s,
7802+ target_phys_addr_t addr)
7803+{
7804+ return 1;
7805+}
7806+
7807+static const struct dma_irq_map omap2_dma_irq_map[] = {
7808+ { 0, OMAP_INT_24XX_SDMA_IRQ0 },
7809+ { 0, OMAP_INT_24XX_SDMA_IRQ1 },
7810+ { 0, OMAP_INT_24XX_SDMA_IRQ2 },
7811+ { 0, OMAP_INT_24XX_SDMA_IRQ3 },
7812+};
7813+
7814+struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
7815+ DisplayState *ds, const char *core)
7816+{
7817+ struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
7818+ qemu_mallocz(sizeof(struct omap_mpu_state_s));
7819+ ram_addr_t sram_base, q3_base;
7820+ qemu_irq *cpu_irq;
7821+ qemu_irq dma_irqs[4];
7822+ omap_clk gpio_clks[4];
7823+ int sdindex;
7824+ int i;
7825+
7826+ /* Core */
7827+ s->mpu_model = omap2420;
7828+ s->env = cpu_init(core ?: "arm1136-r2");
7829+ if (!s->env) {
7830+ fprintf(stderr, "Unable to find CPU definition\n");
7831+ exit(1);
7832+ }
7833+ s->sdram_size = sdram_size;
7834+ s->sram_size = OMAP242X_SRAM_SIZE;
7835+
7836+ s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
7837+
7838+ /* Clocks */
7839+ omap_clk_init(s);
7840+
7841+ /* Memory-mapped stuff */
7842+ cpu_register_physical_memory(OMAP2_Q2_BASE, s->sdram_size,
7843+ (q3_base = qemu_ram_alloc(s->sdram_size)) | IO_MEM_RAM);
7844+ cpu_register_physical_memory(OMAP2_SRAM_BASE, s->sram_size,
7845+ (sram_base = qemu_ram_alloc(s->sram_size)) | IO_MEM_RAM);
7846+
7847+ s->l4 = omap_l4_init(OMAP2_L4_BASE, 54);
7848+
7849+ /* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
7850+ cpu_irq = arm_pic_init_cpu(s->env);
7851+ s->ih[0] = omap2_inth_init(0x480fe000, 0x1000, 3, &s->irq[0],
7852+ cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ],
7853+ omap_findclk(s, "mpu_intc_fclk"),
7854+ omap_findclk(s, "mpu_intc_iclk"));
7855+
7856+ s->prcm = omap_prcm_init(omap_l4tao(s->l4, 3),
7857+ s->irq[0][OMAP_INT_24XX_PRCM_MPU_IRQ], NULL, NULL, s);
7858+
7859+ s->sysc = omap_sysctl_init(omap_l4tao(s->l4, 1),
7860+ omap_findclk(s, "omapctrl_iclk"), s);
7861+
7862+ for (i = 0; i < 4; i ++)
7863+ dma_irqs[i] =
7864+ s->irq[omap2_dma_irq_map[i].ih][omap2_dma_irq_map[i].intr];
7865+ s->dma = omap_dma4_init(0x48056000, dma_irqs, s, 256, 32,
7866+ omap_findclk(s, "sdma_iclk"),
7867+ omap_findclk(s, "sdma_fclk"));
7868+ s->port->addr_valid = omap2_validate_addr;
7869+
7870+ s->uart[0] = omap2_uart_init(omap_l4ta(s->l4, 19),
7871+ s->irq[0][OMAP_INT_24XX_UART1_IRQ],
7872+ omap_findclk(s, "uart1_fclk"),
7873+ omap_findclk(s, "uart1_iclk"),
7874+ s->drq[OMAP24XX_DMA_UART1_TX],
7875+ s->drq[OMAP24XX_DMA_UART1_RX], serial_hds[0]);
7876+ s->uart[1] = omap2_uart_init(omap_l4ta(s->l4, 20),
7877+ s->irq[0][OMAP_INT_24XX_UART2_IRQ],
7878+ omap_findclk(s, "uart2_fclk"),
7879+ omap_findclk(s, "uart2_iclk"),
7880+ s->drq[OMAP24XX_DMA_UART2_TX],
7881+ s->drq[OMAP24XX_DMA_UART2_RX],
7882+ serial_hds[0] ? serial_hds[1] : 0);
7883+ s->uart[2] = omap2_uart_init(omap_l4ta(s->l4, 21),
7884+ s->irq[0][OMAP_INT_24XX_UART3_IRQ],
7885+ omap_findclk(s, "uart3_fclk"),
7886+ omap_findclk(s, "uart3_iclk"),
7887+ s->drq[OMAP24XX_DMA_UART3_TX],
7888+ s->drq[OMAP24XX_DMA_UART3_RX],
7889+ serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0);
7890+
7891+ s->gptimer[0] = omap_gp_timer_init(omap_l4ta(s->l4, 7),
7892+ s->irq[0][OMAP_INT_24XX_GPTIMER1],
7893+ omap_findclk(s, "wu_gpt1_clk"),
7894+ omap_findclk(s, "wu_l4_iclk"));
7895+ s->gptimer[1] = omap_gp_timer_init(omap_l4ta(s->l4, 8),
7896+ s->irq[0][OMAP_INT_24XX_GPTIMER2],
7897+ omap_findclk(s, "core_gpt2_clk"),
7898+ omap_findclk(s, "core_l4_iclk"));
7899+ s->gptimer[2] = omap_gp_timer_init(omap_l4ta(s->l4, 22),
7900+ s->irq[0][OMAP_INT_24XX_GPTIMER3],
7901+ omap_findclk(s, "core_gpt3_clk"),
7902+ omap_findclk(s, "core_l4_iclk"));
7903+ s->gptimer[3] = omap_gp_timer_init(omap_l4ta(s->l4, 23),
7904+ s->irq[0][OMAP_INT_24XX_GPTIMER4],
7905+ omap_findclk(s, "core_gpt4_clk"),
7906+ omap_findclk(s, "core_l4_iclk"));
7907+ s->gptimer[4] = omap_gp_timer_init(omap_l4ta(s->l4, 24),
7908+ s->irq[0][OMAP_INT_24XX_GPTIMER5],
7909+ omap_findclk(s, "core_gpt5_clk"),
7910+ omap_findclk(s, "core_l4_iclk"));
7911+ s->gptimer[5] = omap_gp_timer_init(omap_l4ta(s->l4, 25),
7912+ s->irq[0][OMAP_INT_24XX_GPTIMER6],
7913+ omap_findclk(s, "core_gpt6_clk"),
7914+ omap_findclk(s, "core_l4_iclk"));
7915+ s->gptimer[6] = omap_gp_timer_init(omap_l4ta(s->l4, 26),
7916+ s->irq[0][OMAP_INT_24XX_GPTIMER7],
7917+ omap_findclk(s, "core_gpt7_clk"),
7918+ omap_findclk(s, "core_l4_iclk"));
7919+ s->gptimer[7] = omap_gp_timer_init(omap_l4ta(s->l4, 27),
7920+ s->irq[0][OMAP_INT_24XX_GPTIMER8],
7921+ omap_findclk(s, "core_gpt8_clk"),
7922+ omap_findclk(s, "core_l4_iclk"));
7923+ s->gptimer[8] = omap_gp_timer_init(omap_l4ta(s->l4, 28),
7924+ s->irq[0][OMAP_INT_24XX_GPTIMER9],
7925+ omap_findclk(s, "core_gpt9_clk"),
7926+ omap_findclk(s, "core_l4_iclk"));
7927+ s->gptimer[9] = omap_gp_timer_init(omap_l4ta(s->l4, 29),
7928+ s->irq[0][OMAP_INT_24XX_GPTIMER10],
7929+ omap_findclk(s, "core_gpt10_clk"),
7930+ omap_findclk(s, "core_l4_iclk"));
7931+ s->gptimer[10] = omap_gp_timer_init(omap_l4ta(s->l4, 30),
7932+ s->irq[0][OMAP_INT_24XX_GPTIMER11],
7933+ omap_findclk(s, "core_gpt11_clk"),
7934+ omap_findclk(s, "core_l4_iclk"));
7935+ s->gptimer[11] = omap_gp_timer_init(omap_l4ta(s->l4, 31),
7936+ s->irq[0][OMAP_INT_24XX_GPTIMER12],
7937+ omap_findclk(s, "core_gpt12_clk"),
7938+ omap_findclk(s, "core_l4_iclk"));
7939+
7940+ omap_tap_init(omap_l4ta(s->l4, 2), s);
7941+
7942+ omap_synctimer_init(omap_l4tao(s->l4, 2), s,
7943+ omap_findclk(s, "clk32-kHz"),
7944+ omap_findclk(s, "core_l4_iclk"));
7945+
7946+ s->i2c[0] = omap2_i2c_init(omap_l4tao(s->l4, 5),
7947+ s->irq[0][OMAP_INT_24XX_I2C1_IRQ],
7948+ &s->drq[OMAP24XX_DMA_I2C1_TX],
7949+ omap_findclk(s, "i2c1.fclk"),
7950+ omap_findclk(s, "i2c1.iclk"));
7951+ s->i2c[1] = omap2_i2c_init(omap_l4tao(s->l4, 6),
7952+ s->irq[0][OMAP_INT_24XX_I2C2_IRQ],
7953+ &s->drq[OMAP24XX_DMA_I2C2_TX],
7954+ omap_findclk(s, "i2c2.fclk"),
7955+ omap_findclk(s, "i2c2.iclk"));
7956+
7957+ gpio_clks[0] = omap_findclk(s, "gpio1_dbclk");
7958+ gpio_clks[1] = omap_findclk(s, "gpio2_dbclk");
7959+ gpio_clks[2] = omap_findclk(s, "gpio3_dbclk");
7960+ gpio_clks[3] = omap_findclk(s, "gpio4_dbclk");
7961+ s->gpif = omap2_gpio_init(omap_l4ta(s->l4, 3),
7962+ &s->irq[0][OMAP_INT_24XX_GPIO_BANK1],
7963+ gpio_clks, omap_findclk(s, "gpio_iclk"), 4);
7964+
7965+ s->sdrc = omap_sdrc_init(0x68009000);
7966+ s->gpmc = omap_gpmc_init(0x6800a000, s->irq[0][OMAP_INT_24XX_GPMC_IRQ]);
7967+
7968+ sdindex = drive_get_index(IF_SD, 0, 0);
7969+ if (sdindex == -1) {
7970+ fprintf(stderr, "qemu: missing SecureDigital device\n");
7971+ exit(1);
7972+ }
7973+ s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), drives_table[sdindex].bdrv,
7974+ s->irq[0][OMAP_INT_24XX_MMC_IRQ],
7975+ &s->drq[OMAP24XX_DMA_MMC1_TX],
7976+ omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
7977+
7978+ s->mcspi[0] = omap_mcspi_init(omap_l4ta(s->l4, 35), 4,
7979+ s->irq[0][OMAP_INT_24XX_MCSPI1_IRQ],
7980+ &s->drq[OMAP24XX_DMA_SPI1_TX0],
7981+ omap_findclk(s, "spi1_fclk"),
7982+ omap_findclk(s, "spi1_iclk"));
7983+ s->mcspi[1] = omap_mcspi_init(omap_l4ta(s->l4, 36), 2,
7984+ s->irq[0][OMAP_INT_24XX_MCSPI2_IRQ],
7985+ &s->drq[OMAP24XX_DMA_SPI2_TX0],
7986+ omap_findclk(s, "spi2_fclk"),
7987+ omap_findclk(s, "spi2_iclk"));
7988+
7989+ s->dss = omap_dss_init(omap_l4ta(s->l4, 10), 0x68000800, ds,
7990+ /* XXX wire M_IRQ_25, D_L2_IRQ_30 and I_IRQ_13 together */
7991+ s->irq[0][OMAP_INT_24XX_DSS_IRQ], s->drq[OMAP24XX_DMA_DSS],
7992+ omap_findclk(s, "dss_clk1"), omap_findclk(s, "dss_clk2"),
7993+ omap_findclk(s, "dss_54m_clk"),
7994+ omap_findclk(s, "dss_l3_iclk"),
7995+ omap_findclk(s, "dss_l4_iclk"));
7996+
7997+ /* Register mappings not currenlty implemented:
7998+ * SystemControlMod 48000000 - 48000fff
7999+ * SystemControlL4 48001000 - 48001fff
8000+ * 32kHz Timer Mod 48004000 - 48004fff
8001+ * 32kHz Timer L4 48005000 - 48005fff
8002+ * PRCM ModA 48008000 - 480087ff
8003+ * PRCM ModB 48008800 - 48008fff
8004+ * PRCM L4 48009000 - 48009fff
8005+ * TEST-BCM Mod 48012000 - 48012fff
8006+ * TEST-BCM L4 48013000 - 48013fff
8007+ * TEST-TAP Mod 48014000 - 48014fff
8008+ * TEST-TAP L4 48015000 - 48015fff
8009+ * GPIO1 Mod 48018000 - 48018fff
8010+ * GPIO Top 48019000 - 48019fff
8011+ * GPIO2 Mod 4801a000 - 4801afff
8012+ * GPIO L4 4801b000 - 4801bfff
8013+ * GPIO3 Mod 4801c000 - 4801cfff
8014+ * GPIO4 Mod 4801e000 - 4801efff
8015+ * WDTIMER1 Mod 48020000 - 48010fff
8016+ * WDTIMER Top 48021000 - 48011fff
8017+ * WDTIMER2 Mod 48022000 - 48012fff
8018+ * WDTIMER L4 48023000 - 48013fff
8019+ * WDTIMER3 Mod 48024000 - 48014fff
8020+ * WDTIMER3 L4 48025000 - 48015fff
8021+ * WDTIMER4 Mod 48026000 - 48016fff
8022+ * WDTIMER4 L4 48027000 - 48017fff
8023+ * GPTIMER1 Mod 48028000 - 48018fff
8024+ * GPTIMER1 L4 48029000 - 48019fff
8025+ * GPTIMER2 Mod 4802a000 - 4801afff
8026+ * GPTIMER2 L4 4802b000 - 4801bfff
8027+ * L4-Config AP 48040000 - 480407ff
8028+ * L4-Config IP 48040800 - 48040fff
8029+ * L4-Config LA 48041000 - 48041fff
8030+ * ARM11ETB Mod 48048000 - 48049fff
8031+ * ARM11ETB L4 4804a000 - 4804afff
8032+ * DISPLAY Top 48050000 - 480503ff
8033+ * DISPLAY DISPC 48050400 - 480507ff
8034+ * DISPLAY RFBI 48050800 - 48050bff
8035+ * DISPLAY VENC 48050c00 - 48050fff
8036+ * DISPLAY L4 48051000 - 48051fff
8037+ * CAMERA Top 48052000 - 480523ff
8038+ * CAMERA core 48052400 - 480527ff
8039+ * CAMERA DMA 48052800 - 48052bff
8040+ * CAMERA MMU 48052c00 - 48052fff
8041+ * CAMERA L4 48053000 - 48053fff
8042+ * SDMA Mod 48056000 - 48056fff
8043+ * SDMA L4 48057000 - 48057fff
8044+ * SSI Top 48058000 - 48058fff
8045+ * SSI GDD 48059000 - 48059fff
8046+ * SSI Port1 4805a000 - 4805afff
8047+ * SSI Port2 4805b000 - 4805bfff
8048+ * SSI L4 4805c000 - 4805cfff
8049+ * USB Mod 4805e000 - 480fefff
8050+ * USB L4 4805f000 - 480fffff
8051+ * WIN_TRACER1 Mod 48060000 - 48060fff
8052+ * WIN_TRACER1 L4 48061000 - 48061fff
8053+ * WIN_TRACER2 Mod 48062000 - 48062fff
8054+ * WIN_TRACER2 L4 48063000 - 48063fff
8055+ * WIN_TRACER3 Mod 48064000 - 48064fff
8056+ * WIN_TRACER3 L4 48065000 - 48065fff
8057+ * WIN_TRACER4 Top 48066000 - 480660ff
8058+ * WIN_TRACER4 ETT 48066100 - 480661ff
8059+ * WIN_TRACER4 WT 48066200 - 480662ff
8060+ * WIN_TRACER4 L4 48067000 - 48067fff
8061+ * XTI Mod 48068000 - 48068fff
8062+ * XTI L4 48069000 - 48069fff
8063+ * UART1 Mod 4806a000 - 4806afff
8064+ * UART1 L4 4806b000 - 4806bfff
8065+ * UART2 Mod 4806c000 - 4806cfff
8066+ * UART2 L4 4806d000 - 4806dfff
8067+ * UART3 Mod 4806e000 - 4806efff
8068+ * UART3 L4 4806f000 - 4806ffff
8069+ * I2C1 Mod 48070000 - 48070fff
8070+ * I2C1 L4 48071000 - 48071fff
8071+ * I2C2 Mod 48072000 - 48072fff
8072+ * I2C2 L4 48073000 - 48073fff
8073+ * McBSP1 Mod 48074000 - 48074fff
8074+ * McBSP1 L4 48075000 - 48075fff
8075+ * McBSP2 Mod 48076000 - 48076fff
8076+ * McBSP2 L4 48077000 - 48077fff
8077+ * GPTIMER3 Mod 48078000 - 48078fff
8078+ * GPTIMER3 L4 48079000 - 48079fff
8079+ * GPTIMER4 Mod 4807a000 - 4807afff
8080+ * GPTIMER4 L4 4807b000 - 4807bfff
8081+ * GPTIMER5 Mod 4807c000 - 4807cfff
8082+ * GPTIMER5 L4 4807d000 - 4807dfff
8083+ * GPTIMER6 Mod 4807e000 - 4807efff
8084+ * GPTIMER6 L4 4807f000 - 4807ffff
8085+ * GPTIMER7 Mod 48080000 - 48080fff
8086+ * GPTIMER7 L4 48081000 - 48081fff
8087+ * GPTIMER8 Mod 48082000 - 48082fff
8088+ * GPTIMER8 L4 48083000 - 48083fff
8089+ * GPTIMER9 Mod 48084000 - 48084fff
8090+ * GPTIMER9 L4 48085000 - 48085fff
8091+ * GPTIMER10 Mod 48086000 - 48086fff
8092+ * GPTIMER10 L4 48087000 - 48087fff
8093+ * GPTIMER11 Mod 48088000 - 48088fff
8094+ * GPTIMER11 L4 48089000 - 48089fff
8095+ * GPTIMER12 Mod 4808a000 - 4808afff
8096+ * GPTIMER12 L4 4808b000 - 4808bfff
8097+ * EAC Mod 48090000 - 48090fff
8098+ * EAC L4 48091000 - 48091fff
8099+ * FAC Mod 48092000 - 48092fff
8100+ * FAC L4 48093000 - 48093fff
8101+ * MAILBOX Mod 48094000 - 48094fff
8102+ * MAILBOX L4 48095000 - 48095fff
8103+ * SPI1 Mod 48098000 - 48098fff
8104+ * SPI1 L4 48099000 - 48099fff
8105+ * SPI2 Mod 4809a000 - 4809afff
8106+ * SPI2 L4 4809b000 - 4809bfff
8107+ * MMC/SDIO Mod 4809c000 - 4809cfff
8108+ * MMC/SDIO L4 4809d000 - 4809dfff
8109+ * MS_PRO Mod 4809e000 - 4809efff
8110+ * MS_PRO L4 4809f000 - 4809ffff
8111+ * RNG Mod 480a0000 - 480a0fff
8112+ * RNG L4 480a1000 - 480a1fff
8113+ * DES3DES Mod 480a2000 - 480a2fff
8114+ * DES3DES L4 480a3000 - 480a3fff
8115+ * SHA1MD5 Mod 480a4000 - 480a4fff
8116+ * SHA1MD5 L4 480a5000 - 480a5fff
8117+ * AES Mod 480a6000 - 480a6fff
8118+ * AES L4 480a7000 - 480a7fff
8119+ * PKA Mod 480a8000 - 480a9fff
8120+ * PKA L4 480aa000 - 480aafff
8121+ * MG Mod 480b0000 - 480b0fff
8122+ * MG L4 480b1000 - 480b1fff
8123+ * HDQ/1-wire Mod 480b2000 - 480b2fff
8124+ * HDQ/1-wire L4 480b3000 - 480b3fff
8125+ * MPU interrupt 480fe000 - 480fefff
8126+ * IVA RAM 5c000000 - 5c01ffff
8127+ * IVA ROM 5c020000 - 5c027fff
8128+ * IMG_BUF_A 5c040000 - 5c040fff
8129+ * IMG_BUF_B 5c042000 - 5c042fff
8130+ * VLCDS 5c048000 - 5c0487ff
8131+ * IMX_COEF 5c049000 - 5c04afff
8132+ * IMX_CMD 5c051000 - 5c051fff
8133+ * VLCDQ 5c053000 - 5c0533ff
8134+ * VLCDH 5c054000 - 5c054fff
8135+ * SEQ_CMD 5c055000 - 5c055fff
8136+ * IMX_REG 5c056000 - 5c0560ff
8137+ * VLCD_REG 5c056100 - 5c0561ff
8138+ * SEQ_REG 5c056200 - 5c0562ff
8139+ * IMG_BUF_REG 5c056300 - 5c0563ff
8140+ * SEQIRQ_REG 5c056400 - 5c0564ff
8141+ * OCP_REG 5c060000 - 5c060fff
8142+ * SYSC_REG 5c070000 - 5c070fff
8143+ * MMU_REG 5d000000 - 5d000fff
8144+ * sDMA R 68000400 - 680005ff
8145+ * sDMA W 68000600 - 680007ff
8146+ * Display Control 68000800 - 680009ff
8147+ * DSP subsystem 68000a00 - 68000bff
8148+ * MPU subsystem 68000c00 - 68000dff
8149+ * IVA subsystem 68001000 - 680011ff
8150+ * USB 68001200 - 680013ff
8151+ * Camera 68001400 - 680015ff
8152+ * VLYNQ (firewall) 68001800 - 68001bff
8153+ * VLYNQ 68001e00 - 68001fff
8154+ * SSI 68002000 - 680021ff
8155+ * L4 68002400 - 680025ff
8156+ * DSP (firewall) 68002800 - 68002bff
8157+ * DSP subsystem 68002e00 - 68002fff
8158+ * IVA (firewall) 68003000 - 680033ff
8159+ * IVA 68003600 - 680037ff
8160+ * GFX 68003a00 - 68003bff
8161+ * CMDWR emulation 68003c00 - 68003dff
8162+ * SMS 68004000 - 680041ff
8163+ * OCM 68004200 - 680043ff
8164+ * GPMC 68004400 - 680045ff
8165+ * RAM (firewall) 68005000 - 680053ff
8166+ * RAM (err login) 68005400 - 680057ff
8167+ * ROM (firewall) 68005800 - 68005bff
8168+ * ROM (err login) 68005c00 - 68005fff
8169+ * GPMC (firewall) 68006000 - 680063ff
8170+ * GPMC (err login) 68006400 - 680067ff
8171+ * SMS (err login) 68006c00 - 68006fff
8172+ * SMS registers 68008000 - 68008fff
8173+ * SDRC registers 68009000 - 68009fff
8174+ * GPMC registers 6800a000 6800afff
8175+ */
8176+
8177+ qemu_register_reset(omap2_mpu_reset, s);
8178+
8179+ return s;
8180+}
8181diff --git a/hw/omap_clk.c b/hw/omap_clk.c
8182index 37daec2..da03e15 100644
8183--- a/hw/omap_clk.c
8184+++ b/hw/omap_clk.c
8185@@ -34,6 +34,9 @@ struct clk {
8186 #define CLOCK_IN_OMAP730 (1 << 11)
8187 #define CLOCK_IN_OMAP1510 (1 << 12)
8188 #define CLOCK_IN_OMAP16XX (1 << 13)
8189+#define CLOCK_IN_OMAP242X (1 << 14)
8190+#define CLOCK_IN_OMAP243X (1 << 15)
8191+#define CLOCK_IN_OMAP343X (1 << 16)
8192 uint32_t flags;
8193 int id;
8194
8195@@ -55,7 +58,8 @@ static struct clk xtal_osc12m = {
8196 static struct clk xtal_osc32k = {
8197 .name = "xtal_osc_32k",
8198 .rate = 32768,
8199- .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310,
8200+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 |
8201+ CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8202 };
8203
8204 static struct clk ck_ref = {
8205@@ -502,11 +506,441 @@ static struct clk i2c_ick = {
8206 static struct clk clk32k = {
8207 .name = "clk32-kHz",
8208 .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
8209- ALWAYS_ENABLED,
8210- .parent = &xtal_osc32k,
8211+ CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
8212+ .parent = &xtal_osc32k,
8213+};
8214+
8215+static struct clk apll_96m = {
8216+ .name = "apll_96m",
8217+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
8218+ .rate = 96000000,
8219+ /*.parent = sys.xtalin */
8220+};
8221+
8222+static struct clk apll_54m = {
8223+ .name = "apll_54m",
8224+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
8225+ .rate = 54000000,
8226+ /*.parent = sys.xtalin */
8227+};
8228+
8229+static struct clk sys_clk = {
8230+ .name = "sys_clk",
8231+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
8232+ .rate = 32768,
8233+ /*.parent = sys.xtalin */
8234+};
8235+
8236+static struct clk sleep_clk = {
8237+ .name = "sleep_clk",
8238+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
8239+ .rate = 32768,
8240+ /*.parent = sys.xtalin */
8241+};
8242+
8243+static struct clk dpll_ck = {
8244+ .name = "dpll",
8245+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
8246+ /*.parent = sys.xtalin */
8247+};
8248+
8249+static struct clk dpll_x2_ck = {
8250+ .name = "dpll_x2",
8251+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
8252+ /*.parent = sys.xtalin */
8253+};
8254+
8255+static struct clk wdt1_sys_clk = {
8256+ .name = "wdt1_sys_clk",
8257+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
8258+ .rate = 32768,
8259+ /*.parent = sys.xtalin */
8260+};
8261+
8262+static struct clk func_96m_clk = {
8263+ .name = "func_96m_clk",
8264+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8265+ .divisor = 1,
8266+ .parent = &apll_96m,
8267+};
8268+
8269+static struct clk func_48m_clk = {
8270+ .name = "func_48m_clk",
8271+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8272+ .divisor = 2,
8273+ .parent = &apll_96m,
8274+};
8275+
8276+static struct clk func_12m_clk = {
8277+ .name = "func_12m_clk",
8278+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8279+ .divisor = 8,
8280+ .parent = &apll_96m,
8281+};
8282+
8283+static struct clk func_54m_clk = {
8284+ .name = "func_54m_clk",
8285+ .flags = CLOCK_IN_OMAP242X,
8286+ .divisor = 1,
8287+ .parent = &apll_54m,
8288+};
8289+
8290+static struct clk sys_clkout = {
8291+ .name = "clkout",
8292+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8293+ .parent = &sys_clk,
8294+};
8295+
8296+static struct clk sys_clkout2 = {
8297+ .name = "clkout2",
8298+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8299+ .parent = &sys_clk,
8300+};
8301+
8302+static struct clk core_clk = {
8303+ .name = "core_clk",
8304+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8305+ .parent = &dpll_ck,
8306+};
8307+
8308+static struct clk l3_clk = {
8309+ .name = "l3_clk",
8310+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8311+ .parent = &core_clk,
8312+};
8313+
8314+static struct clk core_l4_iclk = {
8315+ .name = "core_l4_iclk",
8316+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8317+ .parent = &l3_clk,
8318+};
8319+
8320+static struct clk wu_l4_iclk = {
8321+ .name = "wu_l4_iclk",
8322+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8323+ .parent = &l3_clk,
8324+};
8325+
8326+static struct clk core_l3_iclk = {
8327+ .name = "core_l3_iclk",
8328+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8329+ .parent = &core_clk,
8330+};
8331+
8332+static struct clk core_l4_usb_clk = {
8333+ .name = "core_l4_usb_clk",
8334+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8335+ .parent = &l3_clk,
8336+};
8337+
8338+static struct clk wu_gpt1_clk = {
8339+ .name = "wu_gpt1_clk",
8340+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8341+ .parent = &sys_clk,
8342+};
8343+
8344+static struct clk wu_32k_clk = {
8345+ .name = "wu_32k_clk",
8346+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8347+ .parent = &sys_clk,
8348+};
8349+
8350+static struct clk uart1_fclk = {
8351+ .name = "uart1_fclk",
8352+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8353+ .parent = &func_48m_clk,
8354+};
8355+
8356+static struct clk uart1_iclk = {
8357+ .name = "uart1_iclk",
8358+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8359+ .parent = &core_l4_iclk,
8360+};
8361+
8362+static struct clk uart2_fclk = {
8363+ .name = "uart2_fclk",
8364+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8365+ .parent = &func_48m_clk,
8366+};
8367+
8368+static struct clk uart2_iclk = {
8369+ .name = "uart2_iclk",
8370+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8371+ .parent = &core_l4_iclk,
8372+};
8373+
8374+static struct clk uart3_fclk = {
8375+ .name = "uart3_fclk",
8376+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8377+ .parent = &func_48m_clk,
8378+};
8379+
8380+static struct clk uart3_iclk = {
8381+ .name = "uart3_iclk",
8382+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8383+ .parent = &core_l4_iclk,
8384+};
8385+
8386+static struct clk mpu_fclk = {
8387+ .name = "mpu_fclk",
8388+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8389+ .parent = &core_clk,
8390+};
8391+
8392+static struct clk mpu_iclk = {
8393+ .name = "mpu_iclk",
8394+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8395+ .parent = &core_clk,
8396+};
8397+
8398+static struct clk int_m_fclk = {
8399+ .name = "int_m_fclk",
8400+ .alias = "mpu_intc_fclk",
8401+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8402+ .parent = &core_clk,
8403+};
8404+
8405+static struct clk int_m_iclk = {
8406+ .name = "int_m_iclk",
8407+ .alias = "mpu_intc_iclk",
8408+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8409+ .parent = &core_clk,
8410+};
8411+
8412+static struct clk core_gpt2_clk = {
8413+ .name = "core_gpt2_clk",
8414+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8415+ .parent = &sys_clk,
8416+};
8417+
8418+static struct clk core_gpt3_clk = {
8419+ .name = "core_gpt3_clk",
8420+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8421+ .parent = &sys_clk,
8422+};
8423+
8424+static struct clk core_gpt4_clk = {
8425+ .name = "core_gpt4_clk",
8426+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8427+ .parent = &sys_clk,
8428+};
8429+
8430+static struct clk core_gpt5_clk = {
8431+ .name = "core_gpt5_clk",
8432+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8433+ .parent = &sys_clk,
8434+};
8435+
8436+static struct clk core_gpt6_clk = {
8437+ .name = "core_gpt6_clk",
8438+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8439+ .parent = &sys_clk,
8440+};
8441+
8442+static struct clk core_gpt7_clk = {
8443+ .name = "core_gpt7_clk",
8444+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8445+ .parent = &sys_clk,
8446+};
8447+
8448+static struct clk core_gpt8_clk = {
8449+ .name = "core_gpt8_clk",
8450+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8451+ .parent = &sys_clk,
8452+};
8453+
8454+static struct clk core_gpt9_clk = {
8455+ .name = "core_gpt9_clk",
8456+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8457+ .parent = &sys_clk,
8458+};
8459+
8460+static struct clk core_gpt10_clk = {
8461+ .name = "core_gpt10_clk",
8462+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8463+ .parent = &sys_clk,
8464+};
8465+
8466+static struct clk core_gpt11_clk = {
8467+ .name = "core_gpt11_clk",
8468+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8469+ .parent = &sys_clk,
8470+};
8471+
8472+static struct clk core_gpt12_clk = {
8473+ .name = "core_gpt12_clk",
8474+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8475+ .parent = &sys_clk,
8476+};
8477+
8478+static struct clk mcbsp1_clk = {
8479+ .name = "mcbsp1_cg",
8480+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8481+ .divisor = 2,
8482+ .parent = &func_96m_clk,
8483+};
8484+
8485+static struct clk mcbsp2_clk = {
8486+ .name = "mcbsp2_cg",
8487+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8488+ .divisor = 2,
8489+ .parent = &func_96m_clk,
8490+};
8491+
8492+static struct clk emul_clk = {
8493+ .name = "emul_ck",
8494+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8495+ .parent = &func_54m_clk,
8496+};
8497+
8498+static struct clk sdma_fclk = {
8499+ .name = "sdma_fclk",
8500+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8501+ .parent = &l3_clk,
8502+};
8503+
8504+static struct clk sdma_iclk = {
8505+ .name = "sdma_iclk",
8506+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8507+ .parent = &core_l3_iclk, /* core_l4_iclk for the configuration port */
8508+};
8509+
8510+static struct clk i2c1_fclk = {
8511+ .name = "i2c1.fclk",
8512+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8513+ .parent = &func_12m_clk,
8514+ .divisor = 1,
8515+};
8516+
8517+static struct clk i2c1_iclk = {
8518+ .name = "i2c1.iclk",
8519+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8520+ .parent = &core_l4_iclk,
8521+};
8522+
8523+static struct clk i2c2_fclk = {
8524+ .name = "i2c2.fclk",
8525+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8526+ .parent = &func_12m_clk,
8527+ .divisor = 1,
8528+};
8529+
8530+static struct clk i2c2_iclk = {
8531+ .name = "i2c2.iclk",
8532+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8533+ .parent = &core_l4_iclk,
8534+};
8535+
8536+static struct clk gpio_dbclk[4] = {
8537+ {
8538+ .name = "gpio1_dbclk",
8539+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8540+ .parent = &wu_32k_clk,
8541+ }, {
8542+ .name = "gpio2_dbclk",
8543+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8544+ .parent = &wu_32k_clk,
8545+ }, {
8546+ .name = "gpio3_dbclk",
8547+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8548+ .parent = &wu_32k_clk,
8549+ }, {
8550+ .name = "gpio4_dbclk",
8551+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8552+ .parent = &wu_32k_clk,
8553+ },
8554+};
8555+
8556+static struct clk gpio_iclk = {
8557+ .name = "gpio_iclk",
8558+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8559+ .parent = &wu_l4_iclk,
8560+};
8561+
8562+static struct clk mmc_fck = {
8563+ .name = "mmc_fclk",
8564+ .flags = CLOCK_IN_OMAP242X,
8565+ .parent = &func_96m_clk,
8566+};
8567+
8568+static struct clk mmc_ick = {
8569+ .name = "mmc_iclk",
8570+ .flags = CLOCK_IN_OMAP242X,
8571+ .parent = &core_l4_iclk,
8572+};
8573+
8574+static struct clk spi_fclk[3] = {
8575+ {
8576+ .name = "spi1_fclk",
8577+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8578+ .parent = &func_48m_clk,
8579+ }, {
8580+ .name = "spi2_fclk",
8581+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8582+ .parent = &func_48m_clk,
8583+ }, {
8584+ .name = "spi3_fclk",
8585+ .flags = CLOCK_IN_OMAP243X,
8586+ .parent = &func_48m_clk,
8587+ },
8588+};
8589+
8590+static struct clk dss_clk[2] = {
8591+ {
8592+ .name = "dss_clk1",
8593+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8594+ .parent = &core_clk,
8595+ }, {
8596+ .name = "dss_clk2",
8597+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8598+ .parent = &sys_clk,
8599+ },
8600+};
8601+
8602+static struct clk dss_54m_clk = {
8603+ .name = "dss_54m_clk",
8604+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8605+ .parent = &func_54m_clk,
8606+};
8607+
8608+static struct clk dss_l3_iclk = {
8609+ .name = "dss_l3_iclk",
8610+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8611+ .parent = &core_l3_iclk,
8612+};
8613+
8614+static struct clk dss_l4_iclk = {
8615+ .name = "dss_l4_iclk",
8616+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8617+ .parent = &core_l4_iclk,
8618+};
8619+
8620+static struct clk spi_iclk[3] = {
8621+ {
8622+ .name = "spi1_iclk",
8623+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8624+ .parent = &core_l4_iclk,
8625+ }, {
8626+ .name = "spi2_iclk",
8627+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8628+ .parent = &core_l4_iclk,
8629+ }, {
8630+ .name = "spi3_iclk",
8631+ .flags = CLOCK_IN_OMAP243X,
8632+ .parent = &core_l4_iclk,
8633+ },
8634+};
8635+
8636+static struct clk omapctrl_clk = {
8637+ .name = "omapctrl_iclk",
8638+ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
8639+ /* XXX Should be in WKUP domain */
8640+ .parent = &core_l4_iclk,
8641 };
8642
8643 static struct clk *onchip_clks[] = {
8644+ /* OMAP 1 */
8645+
8646 /* non-ULPD clocks */
8647 &xtal_osc12m,
8648 &xtal_osc32k,
8649@@ -572,6 +1006,80 @@ static struct clk *onchip_clks[] = {
8650 /* Virtual clocks */
8651 &i2c_fck,
8652 &i2c_ick,
8653+
8654+ /* OMAP 2 */
8655+
8656+ &apll_96m,
8657+ &apll_54m,
8658+ &sys_clk,
8659+ &sleep_clk,
8660+ &dpll_ck,
8661+ &dpll_x2_ck,
8662+ &wdt1_sys_clk,
8663+ &func_96m_clk,
8664+ &func_48m_clk,
8665+ &func_12m_clk,
8666+ &func_54m_clk,
8667+ &sys_clkout,
8668+ &sys_clkout2,
8669+ &core_clk,
8670+ &l3_clk,
8671+ &core_l4_iclk,
8672+ &wu_l4_iclk,
8673+ &core_l3_iclk,
8674+ &core_l4_usb_clk,
8675+ &wu_gpt1_clk,
8676+ &wu_32k_clk,
8677+ &uart1_fclk,
8678+ &uart1_iclk,
8679+ &uart2_fclk,
8680+ &uart2_iclk,
8681+ &uart3_fclk,
8682+ &uart3_iclk,
8683+ &mpu_fclk,
8684+ &mpu_iclk,
8685+ &int_m_fclk,
8686+ &int_m_iclk,
8687+ &core_gpt2_clk,
8688+ &core_gpt3_clk,
8689+ &core_gpt4_clk,
8690+ &core_gpt5_clk,
8691+ &core_gpt6_clk,
8692+ &core_gpt7_clk,
8693+ &core_gpt8_clk,
8694+ &core_gpt9_clk,
8695+ &core_gpt10_clk,
8696+ &core_gpt11_clk,
8697+ &core_gpt12_clk,
8698+ &mcbsp1_clk,
8699+ &mcbsp2_clk,
8700+ &emul_clk,
8701+ &sdma_fclk,
8702+ &sdma_iclk,
8703+ &i2c1_fclk,
8704+ &i2c1_iclk,
8705+ &i2c2_fclk,
8706+ &i2c2_iclk,
8707+ &gpio_dbclk[0],
8708+ &gpio_dbclk[1],
8709+ &gpio_dbclk[2],
8710+ &gpio_dbclk[3],
8711+ &gpio_iclk,
8712+ &mmc_fck,
8713+ &mmc_ick,
8714+ &spi_fclk[0],
8715+ &spi_iclk[0],
8716+ &spi_fclk[1],
8717+ &spi_iclk[1],
8718+ &spi_fclk[2],
8719+ &spi_iclk[2],
8720+ &dss_clk[0],
8721+ &dss_clk[1],
8722+ &dss_54m_clk,
8723+ &dss_l3_iclk,
8724+ &dss_l4_iclk,
8725+ &omapctrl_clk,
8726+
8727 0
8728 };
8729
8730@@ -727,6 +1235,12 @@ void omap_clk_init(struct omap_mpu_state_s *mpu)
8731 flag = CLOCK_IN_OMAP310;
8732 else if (cpu_is_omap1510(mpu))
8733 flag = CLOCK_IN_OMAP1510;
8734+ else if (cpu_is_omap2410(mpu) || cpu_is_omap2420(mpu))
8735+ flag = CLOCK_IN_OMAP242X;
8736+ else if (cpu_is_omap2430(mpu))
8737+ flag = CLOCK_IN_OMAP243X;
8738+ else if (cpu_is_omap3430(mpu))
8739+ flag = CLOCK_IN_OMAP243X;
8740 else
8741 return;
8742
8743diff --git a/hw/omap_dma.c b/hw/omap_dma.c
8744index 1835826..6c0bd82 100644
8745--- a/hw/omap_dma.c
8746+++ b/hw/omap_dma.c
8747@@ -28,12 +28,15 @@ struct omap_dma_channel_s {
8748 /* transfer data */
8749 int burst[2];
8750 int pack[2];
8751+ int endian[2];
8752+ int endian_lock[2];
8753+ int translate[2];
8754 enum omap_dma_port port[2];
8755 target_phys_addr_t addr[2];
8756 omap_dma_addressing_t mode[2];
8757- uint16_t elements;
8758+ uint32_t elements;
8759 uint16_t frames;
8760- int16_t frame_index[2];
8761+ int32_t frame_index[2];
8762 int16_t element_index[2];
8763 int data_type;
8764
8765@@ -41,6 +44,7 @@ struct omap_dma_channel_s {
8766 int transparent_copy;
8767 int constant_fill;
8768 uint32_t color;
8769+ int prefetch;
8770
8771 /* auto init and linked channel data */
8772 int end_prog;
8773@@ -52,11 +56,13 @@ struct omap_dma_channel_s {
8774 /* interruption data */
8775 int interrupts;
8776 int status;
8777+ int cstatus;
8778
8779 /* state data */
8780 int active;
8781 int enable;
8782 int sync;
8783+ int src_sync;
8784 int pending_request;
8785 int waiting_end_prog;
8786 uint16_t cpc;
8787@@ -75,16 +81,21 @@ struct omap_dma_channel_s {
8788 target_phys_addr_t src, dest;
8789 int frame;
8790 int element;
8791+ int pck_element;
8792 int frame_delta[2];
8793 int elem_delta[2];
8794 int frames;
8795 int elements;
8796+ int pck_elements;
8797 } active_set;
8798
8799 /* unused parameters */
8800+ int write_mode;
8801 int priority;
8802 int interleave_disabled;
8803 int type;
8804+ int suspend;
8805+ int buf_disable;
8806 };
8807
8808 struct omap_dma_s {
8809@@ -93,15 +104,21 @@ struct omap_dma_s {
8810 target_phys_addr_t base;
8811 omap_clk clk;
8812 int64_t delay;
8813- uint32_t drq;
8814+ uint64_t drq;
8815+ qemu_irq irq[4];
8816+ void (*intr_update)(struct omap_dma_s *s);
8817 enum omap_dma_model model;
8818 int omap_3_1_mapping_disabled;
8819
8820- uint16_t gcr;
8821+ uint32_t gcr;
8822+ uint32_t ocp;
8823+ uint32_t caps[5];
8824+ uint32_t irqen[4];
8825+ uint32_t irqstat[4];
8826 int run_count;
8827
8828 int chans;
8829- struct omap_dma_channel_s ch[16];
8830+ struct omap_dma_channel_s ch[32];
8831 struct omap_dma_lcd_channel_s lcd_ch;
8832 };
8833
8834@@ -113,23 +130,13 @@ struct omap_dma_s {
8835 #define LAST_FRAME_INTR (1 << 4)
8836 #define END_BLOCK_INTR (1 << 5)
8837 #define SYNC (1 << 6)
8838+#define END_PKT_INTR (1 << 7)
8839+#define TRANS_ERR_INTR (1 << 8)
8840+#define MISALIGN_INTR (1 << 11)
8841
8842-static void omap_dma_interrupts_update(struct omap_dma_s *s)
8843+static inline void omap_dma_interrupts_update(struct omap_dma_s *s)
8844 {
8845- struct omap_dma_channel_s *ch = s->ch;
8846- int i;
8847-
8848- if (s->omap_3_1_mapping_disabled) {
8849- for (i = 0; i < s->chans; i ++, ch ++)
8850- if (ch->status)
8851- qemu_irq_raise(ch->irq);
8852- } else {
8853- /* First three interrupts are shared between two channels each. */
8854- for (i = 0; i < 6; i ++, ch ++) {
8855- if (ch->status || (ch->sibling && ch->sibling->status))
8856- qemu_irq_raise(ch->irq);
8857- }
8858- }
8859+ return s->intr_update(s);
8860 }
8861
8862 static void omap_dma_channel_load(struct omap_dma_s *s,
8863@@ -148,8 +155,10 @@ static void omap_dma_channel_load(struct omap_dma_s *s,
8864 a->dest = ch->addr[1];
8865 a->frames = ch->frames;
8866 a->elements = ch->elements;
8867+ a->pck_elements = ch->frame_index[!ch->src_sync];
8868 a->frame = 0;
8869 a->element = 0;
8870+ a->pck_element = 0;
8871
8872 if (unlikely(!ch->elements || !ch->frames)) {
8873 printf("%s: bad DMA request\n", __FUNCTION__);
8874@@ -202,16 +211,15 @@ static void omap_dma_deactivate_channel(struct omap_dma_s *s,
8875 /* Update cpc */
8876 ch->cpc = ch->active_set.dest & 0xffff;
8877
8878- if (ch->pending_request && !ch->waiting_end_prog) {
8879+ if (ch->pending_request && !ch->waiting_end_prog && ch->enable) {
8880 /* Don't deactivate the channel */
8881 ch->pending_request = 0;
8882- if (ch->enable)
8883- return;
8884+ return;
8885 }
8886
8887 /* Don't deactive the channel if it is synchronized and the DMA request is
8888 active */
8889- if (ch->sync && (s->drq & (1 << ch->sync)) && ch->enable)
8890+ if (ch->sync && ch->enable && (s->drq & (1 << ch->sync)))
8891 return;
8892
8893 if (ch->active) {
8894@@ -231,6 +239,9 @@ static void omap_dma_enable_channel(struct omap_dma_s *s,
8895 ch->enable = 1;
8896 ch->waiting_end_prog = 0;
8897 omap_dma_channel_load(s, ch);
8898+ /* TODO: theoretically if ch->sync && ch->prefetch &&
8899+ * !s->drq[ch->sync], we should also activate and fetch from source
8900+ * and then stall until signalled. */
8901 if ((!ch->sync) || (s->drq & (1 << ch->sync)))
8902 omap_dma_activate_channel(s, ch);
8903 }
8904@@ -259,16 +270,47 @@ static void omap_dma_channel_end_prog(struct omap_dma_s *s,
8905 }
8906 }
8907
8908+static void omap_dma_interrupts_3_1_update(struct omap_dma_s *s)
8909+{
8910+ struct omap_dma_channel_s *ch = s->ch;
8911+
8912+ /* First three interrupts are shared between two channels each. */
8913+ if (ch[0].status | ch[6].status)
8914+ qemu_irq_raise(ch[0].irq);
8915+ if (ch[1].status | ch[7].status)
8916+ qemu_irq_raise(ch[1].irq);
8917+ if (ch[2].status | ch[8].status)
8918+ qemu_irq_raise(ch[2].irq);
8919+ if (ch[3].status)
8920+ qemu_irq_raise(ch[3].irq);
8921+ if (ch[4].status)
8922+ qemu_irq_raise(ch[4].irq);
8923+ if (ch[5].status)
8924+ qemu_irq_raise(ch[5].irq);
8925+}
8926+
8927+static void omap_dma_interrupts_3_2_update(struct omap_dma_s *s)
8928+{
8929+ struct omap_dma_channel_s *ch = s->ch;
8930+ int i;
8931+
8932+ for (i = s->chans; i; ch ++, i --)
8933+ if (ch->status)
8934+ qemu_irq_raise(ch->irq);
8935+}
8936+
8937 static void omap_dma_enable_3_1_mapping(struct omap_dma_s *s)
8938 {
8939 s->omap_3_1_mapping_disabled = 0;
8940 s->chans = 9;
8941+ s->intr_update = omap_dma_interrupts_3_1_update;
8942 }
8943
8944 static void omap_dma_disable_3_1_mapping(struct omap_dma_s *s)
8945 {
8946 s->omap_3_1_mapping_disabled = 1;
8947 s->chans = 16;
8948+ s->intr_update = omap_dma_interrupts_3_2_update;
8949 }
8950
8951 static void omap_dma_process_request(struct omap_dma_s *s, int request)
8952@@ -358,6 +400,22 @@ static void omap_dma_channel_run(struct omap_dma_s *s)
8953 if (ch->interrupts & HALF_FRAME_INTR)
8954 ch->status |= HALF_FRAME_INTR;
8955
8956+ if (ch->fs && ch->bs) {
8957+ a->pck_element ++;
8958+ /* Check if a full packet has beed transferred. */
8959+ if (a->pck_element == a->pck_elements) {
8960+ a->pck_element = 0;
8961+
8962+ /* Set the END_PKT interrupt */
8963+ if ((ch->interrupts & END_PKT_INTR) && !ch->src_sync)
8964+ ch->status |= END_PKT_INTR;
8965+
8966+ /* If the channel is packet-synchronized, deactivate it */
8967+ if (ch->sync)
8968+ omap_dma_deactivate_channel(s, ch);
8969+ }
8970+ }
8971+
8972 if (a->element == a->elements) {
8973 /* End of Frame */
8974 a->element = 0;
8975@@ -366,7 +424,7 @@ static void omap_dma_channel_run(struct omap_dma_s *s)
8976 a->frame ++;
8977
8978 /* If the channel is frame synchronized, deactivate it */
8979- if (ch->sync && ch->fs)
8980+ if (ch->sync && ch->fs && !ch->bs)
8981 omap_dma_deactivate_channel(s, ch);
8982
8983 /* If the channel is async, update cpc */
8984@@ -414,50 +472,62 @@ void omap_dma_reset(struct omap_dma_s *s)
8985 int i;
8986
8987 qemu_del_timer(s->tm);
8988- s->gcr = 0x0004;
8989+ if (s->model < omap_dma_4)
8990+ s->gcr = 0x0004;
8991+ else
8992+ s->gcr = 0x00010010;
8993+ s->ocp = 0x00000000;
8994+ memset(&s->irqstat, 0, sizeof(s->irqstat));
8995+ memset(&s->irqen, 0, sizeof(s->irqen));
8996 s->drq = 0x00000000;
8997 s->run_count = 0;
8998 s->lcd_ch.src = emiff;
8999 s->lcd_ch.condition = 0;
9000 s->lcd_ch.interrupts = 0;
9001 s->lcd_ch.dual = 0;
9002- omap_dma_enable_3_1_mapping(s);
9003+ if (s->model < omap_dma_4)
9004+ omap_dma_enable_3_1_mapping(s);
9005 for (i = 0; i < s->chans; i ++) {
9006+ s->ch[i].suspend = 0;
9007+ s->ch[i].prefetch = 0;
9008+ s->ch[i].buf_disable = 0;
9009+ s->ch[i].src_sync = 0;
9010 memset(&s->ch[i].burst, 0, sizeof(s->ch[i].burst));
9011 memset(&s->ch[i].port, 0, sizeof(s->ch[i].port));
9012 memset(&s->ch[i].mode, 0, sizeof(s->ch[i].mode));
9013- memset(&s->ch[i].elements, 0, sizeof(s->ch[i].elements));
9014- memset(&s->ch[i].frames, 0, sizeof(s->ch[i].frames));
9015 memset(&s->ch[i].frame_index, 0, sizeof(s->ch[i].frame_index));
9016 memset(&s->ch[i].element_index, 0, sizeof(s->ch[i].element_index));
9017- memset(&s->ch[i].data_type, 0, sizeof(s->ch[i].data_type));
9018- memset(&s->ch[i].transparent_copy, 0,
9019- sizeof(s->ch[i].transparent_copy));
9020- memset(&s->ch[i].constant_fill, 0, sizeof(s->ch[i].constant_fill));
9021- memset(&s->ch[i].color, 0, sizeof(s->ch[i].color));
9022- memset(&s->ch[i].end_prog, 0, sizeof(s->ch[i].end_prog));
9023- memset(&s->ch[i].repeat, 0, sizeof(s->ch[i].repeat));
9024- memset(&s->ch[i].auto_init, 0, sizeof(s->ch[i].auto_init));
9025- memset(&s->ch[i].link_enabled, 0, sizeof(s->ch[i].link_enabled));
9026- memset(&s->ch[i].link_next_ch, 0, sizeof(s->ch[i].link_next_ch));
9027- s->ch[i].interrupts = 0x0003;
9028- memset(&s->ch[i].status, 0, sizeof(s->ch[i].status));
9029- memset(&s->ch[i].active, 0, sizeof(s->ch[i].active));
9030- memset(&s->ch[i].enable, 0, sizeof(s->ch[i].enable));
9031- memset(&s->ch[i].sync, 0, sizeof(s->ch[i].sync));
9032- memset(&s->ch[i].pending_request, 0, sizeof(s->ch[i].pending_request));
9033- memset(&s->ch[i].waiting_end_prog, 0,
9034- sizeof(s->ch[i].waiting_end_prog));
9035- memset(&s->ch[i].cpc, 0, sizeof(s->ch[i].cpc));
9036- memset(&s->ch[i].fs, 0, sizeof(s->ch[i].fs));
9037- memset(&s->ch[i].bs, 0, sizeof(s->ch[i].bs));
9038- memset(&s->ch[i].omap_3_1_compatible_disable, 0,
9039- sizeof(s->ch[i].omap_3_1_compatible_disable));
9040+ memset(&s->ch[i].endian, 0, sizeof(s->ch[i].endian));
9041+ memset(&s->ch[i].endian_lock, 0, sizeof(s->ch[i].endian_lock));
9042+ memset(&s->ch[i].translate, 0, sizeof(s->ch[i].translate));
9043+ s->ch[i].write_mode = 0;
9044+ s->ch[i].data_type = 0;
9045+ s->ch[i].transparent_copy = 0;
9046+ s->ch[i].constant_fill = 0;
9047+ s->ch[i].color = 0x00000000;
9048+ s->ch[i].end_prog = 0;
9049+ s->ch[i].repeat = 0;
9050+ s->ch[i].auto_init = 0;
9051+ s->ch[i].link_enabled = 0;
9052+ if (s->model < omap_dma_4)
9053+ s->ch[i].interrupts = 0x0003;
9054+ else
9055+ s->ch[i].interrupts = 0x0000;
9056+ s->ch[i].status = 0;
9057+ s->ch[i].cstatus = 0;
9058+ s->ch[i].active = 0;
9059+ s->ch[i].enable = 0;
9060+ s->ch[i].sync = 0;
9061+ s->ch[i].pending_request = 0;
9062+ s->ch[i].waiting_end_prog = 0;
9063+ s->ch[i].cpc = 0x0000;
9064+ s->ch[i].fs = 0;
9065+ s->ch[i].bs = 0;
9066+ s->ch[i].omap_3_1_compatible_disable = 0;
9067 memset(&s->ch[i].active_set, 0, sizeof(s->ch[i].active_set));
9068- memset(&s->ch[i].priority, 0, sizeof(s->ch[i].priority));
9069- memset(&s->ch[i].interleave_disabled, 0,
9070- sizeof(s->ch[i].interleave_disabled));
9071- memset(&s->ch[i].type, 0, sizeof(s->ch[i].type));
9072+ s->ch[i].priority = 0;
9073+ s->ch[i].interleave_disabled = 0;
9074+ s->ch[i].type = 0;
9075 }
9076 }
9077
9078@@ -476,7 +546,7 @@ static int omap_dma_ch_reg_read(struct omap_dma_s *s,
9079 break;
9080
9081 case 0x02: /* SYS_DMA_CCR_CH0 */
9082- if (s->model == omap_dma_3_1)
9083+ if (s->model <= omap_dma_3_1)
9084 *value = 0 << 10; /* FIFO_FLUSH reads as 0 */
9085 else
9086 *value = ch->omap_3_1_compatible_disable << 10;
9087@@ -596,11 +666,11 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s,
9088 ch->burst[0] = (value & 0x0180) >> 7;
9089 ch->pack[0] = (value & 0x0040) >> 6;
9090 ch->port[0] = (enum omap_dma_port) ((value & 0x003c) >> 2);
9091- ch->data_type = (1 << (value & 3));
9092- if (ch->port[0] >= omap_dma_port_last)
9093+ ch->data_type = 1 << (value & 3);
9094+ if (ch->port[0] >= __omap_dma_port_last)
9095 printf("%s: invalid DMA port %i\n", __FUNCTION__,
9096 ch->port[0]);
9097- if (ch->port[1] >= omap_dma_port_last)
9098+ if (ch->port[1] >= __omap_dma_port_last)
9099 printf("%s: invalid DMA port %i\n", __FUNCTION__,
9100 ch->port[1]);
9101 if ((value & 3) == 3)
9102@@ -611,7 +681,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s,
9103 ch->mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14);
9104 ch->mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12);
9105 ch->end_prog = (value & 0x0800) >> 11;
9106- if (s->model > omap_dma_3_1)
9107+ if (s->model >= omap_dma_3_2)
9108 ch->omap_3_1_compatible_disable = (value >> 10) & 0x1;
9109 ch->repeat = (value & 0x0200) >> 9;
9110 ch->auto_init = (value & 0x0100) >> 8;
9111@@ -630,7 +700,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s,
9112 break;
9113
9114 case 0x04: /* SYS_DMA_CICR_CH0 */
9115- ch->interrupts = value;
9116+ ch->interrupts = value & 0x3f;
9117 break;
9118
9119 case 0x06: /* SYS_DMA_CSR_CH0 */
9120@@ -696,7 +766,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s,
9121 break;
9122
9123 case 0x24: /* DMA_CCR2 */
9124- ch->bs = (value >> 2) & 0x1;
9125+ ch->bs = (value >> 2) & 0x1;
9126 ch->transparent_copy = (value >> 1) & 0x1;
9127 ch->constant_fill = value & 0x1;
9128 break;
9129@@ -1126,48 +1196,29 @@ static int omap_dma_sys_read(struct omap_dma_s *s, int offset,
9130 break;
9131
9132 case 0x44e: /* DMA_CAPS_0_U */
9133- *ret = (1 << 3) | /* Constant Fill Capacity */
9134- (1 << 2); /* Transparent BLT Capacity */
9135+ *ret = (s->caps[0] >> 16) & 0xffff;
9136 break;
9137-
9138 case 0x450: /* DMA_CAPS_0_L */
9139- case 0x452: /* DMA_CAPS_1_U */
9140- *ret = 0;
9141+ *ret = (s->caps[0] >> 0) & 0xffff;
9142 break;
9143
9144+ case 0x452: /* DMA_CAPS_1_U */
9145+ *ret = (s->caps[1] >> 16) & 0xffff;
9146+ break;
9147 case 0x454: /* DMA_CAPS_1_L */
9148- *ret = (1 << 1); /* 1-bit palletized capability */
9149+ *ret = (s->caps[1] >> 0) & 0xffff;
9150 break;
9151
9152 case 0x456: /* DMA_CAPS_2 */
9153- *ret = (1 << 8) | /* SSDIC */
9154- (1 << 7) | /* DDIAC */
9155- (1 << 6) | /* DSIAC */
9156- (1 << 5) | /* DPIAC */
9157- (1 << 4) | /* DCAC */
9158- (1 << 3) | /* SDIAC */
9159- (1 << 2) | /* SSIAC */
9160- (1 << 1) | /* SPIAC */
9161- 1; /* SCAC */
9162+ *ret = s->caps[2];
9163 break;
9164
9165 case 0x458: /* DMA_CAPS_3 */
9166- *ret = (1 << 5) | /* CCC */
9167- (1 << 4) | /* IC */
9168- (1 << 3) | /* ARC */
9169- (1 << 2) | /* AEC */
9170- (1 << 1) | /* FSC */
9171- 1; /* ESC */
9172+ *ret = s->caps[3];
9173 break;
9174
9175 case 0x45a: /* DMA_CAPS_4 */
9176- *ret = (1 << 6) | /* SSC */
9177- (1 << 5) | /* BIC */
9178- (1 << 4) | /* LFIC */
9179- (1 << 3) | /* FIC */
9180- (1 << 2) | /* HFIC */
9181- (1 << 1) | /* EDIC */
9182- 1; /* TOIC */
9183+ *ret = s->caps[4];
9184 break;
9185
9186 case 0x460: /* DMA_PCh2_SR */
9187@@ -1193,7 +1244,7 @@ static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
9188
9189 switch (offset) {
9190 case 0x300 ... 0x3fe:
9191- if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
9192+ if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
9193 if (omap_dma_3_1_lcd_read(&s->lcd_ch, offset, &ret))
9194 break;
9195 return ret;
9196@@ -1207,7 +1258,7 @@ static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
9197 return ret;
9198
9199 case 0x404 ... 0x4fe:
9200- if (s->model == omap_dma_3_1)
9201+ if (s->model <= omap_dma_3_1)
9202 break;
9203 /* Fall through. */
9204 case 0x400:
9205@@ -1236,7 +1287,7 @@ static void omap_dma_write(void *opaque, target_phys_addr_t addr,
9206
9207 switch (offset) {
9208 case 0x300 ... 0x3fe:
9209- if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
9210+ if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
9211 if (omap_dma_3_1_lcd_write(&s->lcd_ch, offset, value))
9212 break;
9213 return;
9214@@ -1250,7 +1301,7 @@ static void omap_dma_write(void *opaque, target_phys_addr_t addr,
9215 return;
9216
9217 case 0x404 ... 0x4fe:
9218- if (s->model == omap_dma_3_1)
9219+ if (s->model <= omap_dma_3_1)
9220 break;
9221 case 0x400:
9222 /* Fall through. */
9223@@ -1285,7 +1336,7 @@ static CPUWriteMemoryFunc *omap_dma_writefn[] = {
9224 static void omap_dma_request(void *opaque, int drq, int req)
9225 {
9226 struct omap_dma_s *s = (struct omap_dma_s *) opaque;
9227- /* The request pins are level triggered. */
9228+ /* The request pins are level triggered in QEMU. */
9229 if (req) {
9230 if (~s->drq & (1 << drq)) {
9231 s->drq |= 1 << drq;
9232@@ -1310,6 +1361,52 @@ static void omap_dma_clk_update(void *opaque, int line, int on)
9233 }
9234 }
9235
9236+static void omap_dma_setcaps(struct omap_dma_s *s)
9237+{
9238+ switch (s->model) {
9239+ default:
9240+ case omap_dma_3_1:
9241+ break;
9242+ case omap_dma_3_2:
9243+ case omap_dma_4:
9244+ /* XXX Only available for sDMA */
9245+ s->caps[0] =
9246+ (1 << 19) | /* Constant Fill Capability */
9247+ (1 << 18); /* Transparent BLT Capability */
9248+ s->caps[1] =
9249+ (1 << 1); /* 1-bit palettized capability (DMA 3.2 only) */
9250+ s->caps[2] =
9251+ (1 << 8) | /* SEPARATE_SRC_AND_DST_INDEX_CPBLTY */
9252+ (1 << 7) | /* DST_DOUBLE_INDEX_ADRS_CPBLTY */
9253+ (1 << 6) | /* DST_SINGLE_INDEX_ADRS_CPBLTY */
9254+ (1 << 5) | /* DST_POST_INCRMNT_ADRS_CPBLTY */
9255+ (1 << 4) | /* DST_CONST_ADRS_CPBLTY */
9256+ (1 << 3) | /* SRC_DOUBLE_INDEX_ADRS_CPBLTY */
9257+ (1 << 2) | /* SRC_SINGLE_INDEX_ADRS_CPBLTY */
9258+ (1 << 1) | /* SRC_POST_INCRMNT_ADRS_CPBLTY */
9259+ (1 << 0); /* SRC_CONST_ADRS_CPBLTY */
9260+ s->caps[3] =
9261+ (1 << 6) | /* BLOCK_SYNCHR_CPBLTY (DMA 4 only) */
9262+ (1 << 7) | /* PKT_SYNCHR_CPBLTY (DMA 4 only) */
9263+ (1 << 5) | /* CHANNEL_CHAINING_CPBLTY */
9264+ (1 << 4) | /* LCh_INTERLEAVE_CPBLTY */
9265+ (1 << 3) | /* AUTOINIT_REPEAT_CPBLTY (DMA 3.2 only) */
9266+ (1 << 2) | /* AUTOINIT_ENDPROG_CPBLTY (DMA 3.2 only) */
9267+ (1 << 1) | /* FRAME_SYNCHR_CPBLTY */
9268+ (1 << 0); /* ELMNT_SYNCHR_CPBLTY */
9269+ s->caps[4] =
9270+ (1 << 7) | /* PKT_INTERRUPT_CPBLTY (DMA 4 only) */
9271+ (1 << 6) | /* SYNC_STATUS_CPBLTY */
9272+ (1 << 5) | /* BLOCK_INTERRUPT_CPBLTY */
9273+ (1 << 4) | /* LAST_FRAME_INTERRUPT_CPBLTY */
9274+ (1 << 3) | /* FRAME_INTERRUPT_CPBLTY */
9275+ (1 << 2) | /* HALF_FRAME_INTERRUPT_CPBLTY */
9276+ (1 << 1) | /* EVENT_DROP_INTERRUPT_CPBLTY */
9277+ (1 << 0); /* TIMEOUT_INTERRUPT_CPBLTY (DMA 3.2 only) */
9278+ break;
9279+ }
9280+}
9281+
9282 struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
9283 qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
9284 enum omap_dma_model model)
9285@@ -1318,7 +1415,7 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
9286 struct omap_dma_s *s = (struct omap_dma_s *)
9287 qemu_mallocz(sizeof(struct omap_dma_s));
9288
9289- if (model == omap_dma_3_1) {
9290+ if (model <= omap_dma_3_1) {
9291 num_irqs = 6;
9292 memsize = 0x800;
9293 } else {
9294@@ -1331,6 +1428,7 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
9295 s->clk = clk;
9296 s->lcd_ch.irq = lcd_irq;
9297 s->lcd_ch.mpu = mpu;
9298+ omap_dma_setcaps(s);
9299 while (num_irqs --)
9300 s->ch[num_irqs].irq = irqs[num_irqs];
9301 for (i = 0; i < 3; i ++) {
9302@@ -1350,6 +1448,393 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
9303 return s;
9304 }
9305
9306+static void omap_dma_interrupts_4_update(struct omap_dma_s *s)
9307+{
9308+ struct omap_dma_channel_s *ch = s->ch;
9309+ uint32_t bmp, bit;
9310+
9311+ for (bmp = 0, bit = 1; bit; ch ++, bit <<= 1)
9312+ if (ch->status) {
9313+ bmp |= bit;
9314+ ch->cstatus |= ch->status;
9315+ ch->status = 0;
9316+ }
9317+ if ((s->irqstat[0] |= s->irqen[0] & bmp))
9318+ qemu_irq_raise(s->irq[0]);
9319+ if ((s->irqstat[1] |= s->irqen[1] & bmp))
9320+ qemu_irq_raise(s->irq[1]);
9321+ if ((s->irqstat[2] |= s->irqen[2] & bmp))
9322+ qemu_irq_raise(s->irq[2]);
9323+ if ((s->irqstat[3] |= s->irqen[3] & bmp))
9324+ qemu_irq_raise(s->irq[3]);
9325+}
9326+
9327+static uint32_t omap_dma4_read(void *opaque, target_phys_addr_t addr)
9328+{
9329+ struct omap_dma_s *s = (struct omap_dma_s *) opaque;
9330+ int irqn = 0, chnum, offset = addr - s->base;
9331+ struct omap_dma_channel_s *ch;
9332+
9333+ switch (offset) {
9334+ case 0x00: /* DMA4_REVISION */
9335+ return 0x40;
9336+
9337+ case 0x14: /* DMA4_IRQSTATUS_L3 */
9338+ irqn ++;
9339+ case 0x10: /* DMA4_IRQSTATUS_L2 */
9340+ irqn ++;
9341+ case 0x0c: /* DMA4_IRQSTATUS_L1 */
9342+ irqn ++;
9343+ case 0x08: /* DMA4_IRQSTATUS_L0 */
9344+ return s->irqstat[irqn];
9345+
9346+ case 0x24: /* DMA4_IRQENABLE_L3 */
9347+ irqn ++;
9348+ case 0x20: /* DMA4_IRQENABLE_L2 */
9349+ irqn ++;
9350+ case 0x1c: /* DMA4_IRQENABLE_L1 */
9351+ irqn ++;
9352+ case 0x18: /* DMA4_IRQENABLE_L0 */
9353+ return s->irqen[irqn];
9354+
9355+ case 0x28: /* DMA4_SYSSTATUS */
9356+ return 1; /* RESETDONE */
9357+
9358+ case 0x2c: /* DMA4_OCP_SYSCONFIG */
9359+ return s->ocp;
9360+
9361+ case 0x64: /* DMA4_CAPS_0 */
9362+ return s->caps[0];
9363+ case 0x6c: /* DMA4_CAPS_2 */
9364+ return s->caps[2];
9365+ case 0x70: /* DMA4_CAPS_3 */
9366+ return s->caps[3];
9367+ case 0x74: /* DMA4_CAPS_4 */
9368+ return s->caps[4];
9369+
9370+ case 0x78: /* DMA4_GCR */
9371+ return s->gcr;
9372+
9373+ case 0x80 ... 0xfff:
9374+ offset -= 0x80;
9375+ chnum = offset / 0x60;
9376+ ch = s->ch + chnum;
9377+ offset -= chnum * 0x60;
9378+ break;
9379+
9380+ default:
9381+ OMAP_BAD_REG(addr);
9382+ return 0;
9383+ }
9384+
9385+ /* Per-channel registers */
9386+ switch (offset) {
9387+ case 0x00: /* DMA4_CCR */
9388+ return (ch->buf_disable << 25) |
9389+ (ch->src_sync << 24) |
9390+ (ch->prefetch << 23) |
9391+ ((ch->sync & 0x60) << 14) |
9392+ (ch->bs << 18) |
9393+ (ch->transparent_copy << 17) |
9394+ (ch->constant_fill << 16) |
9395+ (ch->mode[1] << 14) |
9396+ (ch->mode[0] << 12) |
9397+ (0 << 10) | (0 << 9) |
9398+ (ch->suspend << 8) |
9399+ (ch->enable << 7) |
9400+ (ch->priority << 6) |
9401+ (ch->fs << 5) | (ch->sync & 0x1f);
9402+
9403+ case 0x04: /* DMA4_CLNK_CTRL */
9404+ return (ch->link_enabled << 15) | ch->link_next_ch;
9405+
9406+ case 0x08: /* DMA4_CICR */
9407+ return ch->interrupts;
9408+
9409+ case 0x0c: /* DMA4_CSR */
9410+ return ch->cstatus;
9411+
9412+ case 0x10: /* DMA4_CSDP */
9413+ return (ch->endian[0] << 21) |
9414+ (ch->endian_lock[0] << 20) |
9415+ (ch->endian[1] << 19) |
9416+ (ch->endian_lock[1] << 18) |
9417+ (ch->write_mode << 16) |
9418+ (ch->burst[1] << 14) |
9419+ (ch->pack[1] << 13) |
9420+ (ch->translate[1] << 9) |
9421+ (ch->burst[0] << 7) |
9422+ (ch->pack[0] << 6) |
9423+ (ch->translate[0] << 2) |
9424+ (ch->data_type >> 1);
9425+
9426+ case 0x14: /* DMA4_CEN */
9427+ return ch->elements;
9428+
9429+ case 0x18: /* DMA4_CFN */
9430+ return ch->frames;
9431+
9432+ case 0x1c: /* DMA4_CSSA */
9433+ return ch->addr[0];
9434+
9435+ case 0x20: /* DMA4_CDSA */
9436+ return ch->addr[1];
9437+
9438+ case 0x24: /* DMA4_CSEI */
9439+ return ch->element_index[0];
9440+
9441+ case 0x28: /* DMA4_CSFI */
9442+ return ch->frame_index[0];
9443+
9444+ case 0x2c: /* DMA4_CDEI */
9445+ return ch->element_index[1];
9446+
9447+ case 0x30: /* DMA4_CDFI */
9448+ return ch->frame_index[1];
9449+
9450+ case 0x34: /* DMA4_CSAC */
9451+ return ch->active_set.src & 0xffff;
9452+
9453+ case 0x38: /* DMA4_CDAC */
9454+ return ch->active_set.dest & 0xffff;
9455+
9456+ case 0x3c: /* DMA4_CCEN */
9457+ return ch->active_set.element;
9458+
9459+ case 0x40: /* DMA4_CCFN */
9460+ return ch->active_set.frame;
9461+
9462+ case 0x44: /* DMA4_COLOR */
9463+ /* XXX only in sDMA */
9464+ return ch->color;
9465+
9466+ default:
9467+ OMAP_BAD_REG(addr);
9468+ return 0;
9469+ }
9470+}
9471+
9472+static void omap_dma4_write(void *opaque, target_phys_addr_t addr,
9473+ uint32_t value)
9474+{
9475+ struct omap_dma_s *s = (struct omap_dma_s *) opaque;
9476+ int chnum, irqn = 0, offset = addr - s->base;
9477+ struct omap_dma_channel_s *ch;
9478+
9479+ switch (offset) {
9480+ case 0x14: /* DMA4_IRQSTATUS_L3 */
9481+ irqn ++;
9482+ case 0x10: /* DMA4_IRQSTATUS_L2 */
9483+ irqn ++;
9484+ case 0x0c: /* DMA4_IRQSTATUS_L1 */
9485+ irqn ++;
9486+ case 0x08: /* DMA4_IRQSTATUS_L0 */
9487+ s->irqstat[irqn] &= ~value;
9488+ if (!s->irqstat[irqn])
9489+ qemu_irq_lower(s->irq[irqn]);
9490+ return;
9491+
9492+ case 0x24: /* DMA4_IRQENABLE_L3 */
9493+ irqn ++;
9494+ case 0x20: /* DMA4_IRQENABLE_L2 */
9495+ irqn ++;
9496+ case 0x1c: /* DMA4_IRQENABLE_L1 */
9497+ irqn ++;
9498+ case 0x18: /* DMA4_IRQENABLE_L0 */
9499+ s->irqen[irqn] = value;
9500+ return;
9501+
9502+ case 0x2c: /* DMA4_OCP_SYSCONFIG */
9503+ if (value & 2) /* SOFTRESET */
9504+ omap_dma_reset(s);
9505+ s->ocp = value & 0x3321;
9506+ if (((s->ocp >> 12) & 3) == 3) /* MIDLEMODE */
9507+ fprintf(stderr, "%s: invalid DMA power mode\n", __FUNCTION__);
9508+ return;
9509+
9510+ case 0x78: /* DMA4_GCR */
9511+ s->gcr = value & 0x00ff00ff;
9512+ if ((value & 0xff) == 0x00) /* MAX_CHANNEL_FIFO_DEPTH */
9513+ fprintf(stderr, "%s: wrong FIFO depth in GCR\n", __FUNCTION__);
9514+ return;
9515+
9516+ case 0x80 ... 0xfff:
9517+ offset -= 0x80;
9518+ chnum = offset / 0x60;
9519+ ch = s->ch + chnum;
9520+ offset -= chnum * 0x60;
9521+ break;
9522+
9523+ case 0x00: /* DMA4_REVISION */
9524+ case 0x28: /* DMA4_SYSSTATUS */
9525+ case 0x64: /* DMA4_CAPS_0 */
9526+ case 0x6c: /* DMA4_CAPS_2 */
9527+ case 0x70: /* DMA4_CAPS_3 */
9528+ case 0x74: /* DMA4_CAPS_4 */
9529+ OMAP_RO_REG(addr);
9530+ return;
9531+
9532+ default:
9533+ OMAP_BAD_REG(addr);
9534+ return;
9535+ }
9536+
9537+ /* Per-channel registers */
9538+ switch (offset) {
9539+ case 0x00: /* DMA4_CCR */
9540+ ch->buf_disable = (value >> 25) & 1;
9541+ ch->src_sync = (value >> 24) & 1; /* XXX For CamDMA must be 1 */
9542+ if (ch->buf_disable && !ch->src_sync)
9543+ fprintf(stderr, "%s: Buffering disable is not allowed in "
9544+ "destination synchronised mode\n", __FUNCTION__);
9545+ ch->prefetch = (value >> 23) & 1;
9546+ ch->bs = (value >> 18) & 1;
9547+ ch->transparent_copy = (value >> 17) & 1;
9548+ ch->constant_fill = (value >> 16) & 1;
9549+ ch->mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14);
9550+ ch->mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12);
9551+ ch->suspend = (value & 0x0100) >> 8;
9552+ ch->priority = (value & 0x0040) >> 6;
9553+ ch->fs = (value & 0x0020) >> 5;
9554+ if (ch->fs && ch->bs && ch->mode[0] && ch->mode[1])
9555+ fprintf(stderr, "%s: For a packet transfer at least one port "
9556+ "must be constant-addressed\n", __FUNCTION__);
9557+ ch->sync = (value & 0x001f) | ((value >> 14) & 0x0060);
9558+ /* XXX must be 0x01 for CamDMA */
9559+
9560+ if (value & 0x0080)
9561+ omap_dma_enable_channel(s, ch);
9562+ else
9563+ omap_dma_disable_channel(s, ch);
9564+
9565+ break;
9566+
9567+ case 0x04: /* DMA4_CLNK_CTRL */
9568+ ch->link_enabled = (value >> 15) & 0x1;
9569+ ch->link_next_ch = value & 0x1f;
9570+ break;
9571+
9572+ case 0x08: /* DMA4_CICR */
9573+ ch->interrupts = value & 0x09be;
9574+ break;
9575+
9576+ case 0x0c: /* DMA4_CSR */
9577+ ch->cstatus &= ~value;
9578+ break;
9579+
9580+ case 0x10: /* DMA4_CSDP */
9581+ ch->endian[0] =(value >> 21) & 1;
9582+ ch->endian_lock[0] =(value >> 20) & 1;
9583+ ch->endian[1] =(value >> 19) & 1;
9584+ ch->endian_lock[1] =(value >> 18) & 1;
9585+ if (ch->endian[0] != ch->endian[1])
9586+ fprintf(stderr, "%s: DMA endianned conversion enable attempt\n",
9587+ __FUNCTION__);
9588+ ch->write_mode = (value >> 16) & 3;
9589+ ch->burst[1] = (value & 0xc000) >> 14;
9590+ ch->pack[1] = (value & 0x2000) >> 13;
9591+ ch->translate[1] = (value & 0x1e00) >> 9;
9592+ ch->burst[0] = (value & 0x0180) >> 7;
9593+ ch->pack[0] = (value & 0x0040) >> 6;
9594+ ch->translate[0] = (value & 0x003c) >> 2;
9595+ if (ch->translate[0] | ch->translate[1])
9596+ fprintf(stderr, "%s: bad MReqAddressTranslate sideband signal\n",
9597+ __FUNCTION__);
9598+ ch->data_type = 1 << (value & 3);
9599+ if ((value & 3) == 3)
9600+ printf("%s: bad data_type for DMA channel\n", __FUNCTION__);
9601+ break;
9602+
9603+ case 0x14: /* DMA4_CEN */
9604+ ch->elements = value & 0xffffff;
9605+ break;
9606+
9607+ case 0x18: /* DMA4_CFN */
9608+ ch->frames = value & 0xffff;
9609+ break;
9610+
9611+ case 0x1c: /* DMA4_CSSA */
9612+ ch->addr[0] = (target_phys_addr_t) (uint32_t) value;
9613+ break;
9614+
9615+ case 0x20: /* DMA4_CDSA */
9616+ ch->addr[1] = (target_phys_addr_t) (uint32_t) value;
9617+ break;
9618+
9619+ case 0x24: /* DMA4_CSEI */
9620+ ch->element_index[0] = (int16_t) value;
9621+ break;
9622+
9623+ case 0x28: /* DMA4_CSFI */
9624+ ch->frame_index[0] = (int32_t) value;
9625+ break;
9626+
9627+ case 0x2c: /* DMA4_CDEI */
9628+ ch->element_index[1] = (int16_t) value;
9629+ break;
9630+
9631+ case 0x30: /* DMA4_CDFI */
9632+ ch->frame_index[1] = (int32_t) value;
9633+ break;
9634+
9635+ case 0x44: /* DMA4_COLOR */
9636+ /* XXX only in sDMA */
9637+ ch->color = value;
9638+ break;
9639+
9640+ case 0x34: /* DMA4_CSAC */
9641+ case 0x38: /* DMA4_CDAC */
9642+ case 0x3c: /* DMA4_CCEN */
9643+ case 0x40: /* DMA4_CCFN */
9644+ OMAP_RO_REG(addr);
9645+ break;
9646+
9647+ default:
9648+ OMAP_BAD_REG(addr);
9649+ }
9650+}
9651+
9652+static CPUReadMemoryFunc *omap_dma4_readfn[] = {
9653+ omap_badwidth_read16,
9654+ omap_dma4_read,
9655+ omap_dma4_read,
9656+};
9657+
9658+static CPUWriteMemoryFunc *omap_dma4_writefn[] = {
9659+ omap_badwidth_write16,
9660+ omap_dma4_write,
9661+ omap_dma4_write,
9662+};
9663+
9664+struct omap_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
9665+ struct omap_mpu_state_s *mpu, int fifo,
9666+ int chans, omap_clk iclk, omap_clk fclk)
9667+{
9668+ int iomemtype;
9669+ struct omap_dma_s *s = (struct omap_dma_s *)
9670+ qemu_mallocz(sizeof(struct omap_dma_s));
9671+
9672+ s->base = base;
9673+ s->model = omap_dma_4;
9674+ s->chans = chans;
9675+ s->mpu = mpu;
9676+ s->clk = fclk;
9677+ memcpy(&s->irq, irqs, sizeof(s->irq));
9678+ s->intr_update = omap_dma_interrupts_4_update;
9679+ omap_dma_setcaps(s);
9680+ s->tm = qemu_new_timer(vm_clock, (QEMUTimerCB *) omap_dma_channel_run, s);
9681+ omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
9682+ mpu->drq = qemu_allocate_irqs(omap_dma_request, s, 64);
9683+ omap_dma_reset(s);
9684+ omap_dma_clk_update(s, 0, 1);
9685+
9686+ iomemtype = cpu_register_io_memory(0, omap_dma4_readfn,
9687+ omap_dma4_writefn, s);
9688+ cpu_register_physical_memory(s->base, 0x1000, iomemtype);
9689+
9690+ return s;
9691+}
9692+
9693 struct omap_dma_lcd_channel_s *omap_dma_get_lcdch(struct omap_dma_s *s)
9694 {
9695 return &s->lcd_ch;
9696diff --git a/hw/omap_dss.c b/hw/omap_dss.c
9697new file mode 100644
9698index 0000000..1c16802
9699--- /dev/null
9700+++ b/hw/omap_dss.c
9701@@ -0,0 +1,1088 @@
9702+/*
9703+ * OMAP2 Display Subsystem.
9704+ *
9705+ * Copyright (C) 2008 Nokia Corporation
9706+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
9707+ *
9708+ * This program is free software; you can redistribute it and/or
9709+ * modify it under the terms of the GNU General Public License as
9710+ * published by the Free Software Foundation; either version 2 of
9711+ * the License, or (at your option) any later version.
9712+ *
9713+ * This program is distributed in the hope that it will be useful,
9714+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9715+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9716+ * GNU General Public License for more details.
9717+ *
9718+ * You should have received a copy of the GNU General Public License
9719+ * along with this program; if not, write to the Free Software
9720+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
9721+ * MA 02111-1307 USA
9722+ */
9723+#include "hw.h"
9724+#include "console.h"
9725+#include "omap.h"
9726+
9727+struct omap_dss_s {
9728+ target_phys_addr_t diss_base;
9729+ target_phys_addr_t disc_base;
9730+ target_phys_addr_t rfbi_base;
9731+ target_phys_addr_t venc_base;
9732+ target_phys_addr_t im3_base;
9733+ qemu_irq irq;
9734+ qemu_irq drq;
9735+ DisplayState *state;
9736+
9737+ int autoidle;
9738+ int control;
9739+ int enable;
9740+
9741+ struct omap_dss_panel_s {
9742+ int enable;
9743+ int nx;
9744+ int ny;
9745+
9746+ int x;
9747+ int y;
9748+ } dig, lcd;
9749+
9750+ struct {
9751+ uint32_t idlemode;
9752+ uint32_t irqst;
9753+ uint32_t irqen;
9754+ uint32_t control;
9755+ uint32_t config;
9756+ uint32_t capable;
9757+ uint32_t timing[3];
9758+ int line;
9759+ uint32_t bg[2];
9760+ uint32_t trans[2];
9761+
9762+ struct omap_dss_plane_s {
9763+ int enable;
9764+ int bpp;
9765+ int posx;
9766+ int posy;
9767+ int nx;
9768+ int ny;
9769+
9770+ target_phys_addr_t addr[3];
9771+
9772+ uint32_t attr;
9773+ uint32_t tresh;
9774+ int rowinc;
9775+ int colinc;
9776+ int wininc;
9777+ } l[3];
9778+
9779+ int invalidate;
9780+ uint16_t palette[256];
9781+ } dispc;
9782+
9783+ struct {
9784+ int idlemode;
9785+ uint32_t control;
9786+ int enable;
9787+ int pixels;
9788+ int busy;
9789+ int skiplines;
9790+ uint16_t rxbuf;
9791+ uint32_t config[2];
9792+ uint32_t time[4];
9793+ uint32_t data[6];
9794+ uint16_t vsync;
9795+ uint16_t hsync;
9796+ struct rfbi_chip_s *chip[2];
9797+ } rfbi;
9798+};
9799+
9800+static void omap_dispc_interrupt_update(struct omap_dss_s *s)
9801+{
9802+ qemu_set_irq(s->irq, s->dispc.irqst & s->dispc.irqen);
9803+}
9804+
9805+static void omap_rfbi_reset(struct omap_dss_s *s)
9806+{
9807+ s->rfbi.idlemode = 0;
9808+ s->rfbi.control = 2;
9809+ s->rfbi.enable = 0;
9810+ s->rfbi.pixels = 0;
9811+ s->rfbi.skiplines = 0;
9812+ s->rfbi.busy = 0;
9813+ s->rfbi.config[0] = 0x00310000;
9814+ s->rfbi.config[1] = 0x00310000;
9815+ s->rfbi.time[0] = 0;
9816+ s->rfbi.time[1] = 0;
9817+ s->rfbi.time[2] = 0;
9818+ s->rfbi.time[3] = 0;
9819+ s->rfbi.data[0] = 0;
9820+ s->rfbi.data[1] = 0;
9821+ s->rfbi.data[2] = 0;
9822+ s->rfbi.data[3] = 0;
9823+ s->rfbi.data[4] = 0;
9824+ s->rfbi.data[5] = 0;
9825+ s->rfbi.vsync = 0;
9826+ s->rfbi.hsync = 0;
9827+}
9828+
9829+void omap_dss_reset(struct omap_dss_s *s)
9830+{
9831+ s->autoidle = 0;
9832+ s->control = 0;
9833+ s->enable = 0;
9834+
9835+ s->dig.enable = 0;
9836+ s->dig.nx = 1;
9837+ s->dig.ny = 1;
9838+
9839+ s->lcd.enable = 0;
9840+ s->lcd.nx = 1;
9841+ s->lcd.ny = 1;
9842+
9843+ s->dispc.idlemode = 0;
9844+ s->dispc.irqst = 0;
9845+ s->dispc.irqen = 0;
9846+ s->dispc.control = 0;
9847+ s->dispc.config = 0;
9848+ s->dispc.capable = 0x161;
9849+ s->dispc.timing[0] = 0;
9850+ s->dispc.timing[1] = 0;
9851+ s->dispc.timing[2] = 0;
9852+ s->dispc.line = 0;
9853+ s->dispc.bg[0] = 0;
9854+ s->dispc.bg[1] = 0;
9855+ s->dispc.trans[0] = 0;
9856+ s->dispc.trans[1] = 0;
9857+
9858+ s->dispc.l[0].enable = 0;
9859+ s->dispc.l[0].bpp = 0;
9860+ s->dispc.l[0].addr[0] = 0;
9861+ s->dispc.l[0].addr[1] = 0;
9862+ s->dispc.l[0].addr[2] = 0;
9863+ s->dispc.l[0].posx = 0;
9864+ s->dispc.l[0].posy = 0;
9865+ s->dispc.l[0].nx = 1;
9866+ s->dispc.l[0].ny = 1;
9867+ s->dispc.l[0].attr = 0;
9868+ s->dispc.l[0].tresh = 0;
9869+ s->dispc.l[0].rowinc = 1;
9870+ s->dispc.l[0].colinc = 1;
9871+ s->dispc.l[0].wininc = 0;
9872+
9873+ omap_rfbi_reset(s);
9874+ omap_dispc_interrupt_update(s);
9875+}
9876+
9877+static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr)
9878+{
9879+ struct omap_dss_s *s = (struct omap_dss_s *) opaque;
9880+ int offset = addr - s->diss_base;
9881+
9882+ switch (offset) {
9883+ case 0x00: /* DSS_REVISIONNUMBER */
9884+ return 0x20;
9885+
9886+ case 0x10: /* DSS_SYSCONFIG */
9887+ return s->autoidle;
9888+
9889+ case 0x14: /* DSS_SYSSTATUS */
9890+ return 1; /* RESETDONE */
9891+
9892+ case 0x40: /* DSS_CONTROL */
9893+ return s->control;
9894+
9895+ case 0x50: /* DSS_PSA_LCD_REG_1 */
9896+ case 0x54: /* DSS_PSA_LCD_REG_2 */
9897+ case 0x58: /* DSS_PSA_VIDEO_REG */
9898+ /* TODO: fake some values when appropriate s->control bits are set */
9899+ return 0;
9900+
9901+ case 0x5c: /* DSS_STATUS */
9902+ return 1 + (s->control & 1);
9903+
9904+ default:
9905+ break;
9906+ }
9907+ OMAP_BAD_REG(addr);
9908+ return 0;
9909+}
9910+
9911+static void omap_diss_write(void *opaque, target_phys_addr_t addr,
9912+ uint32_t value)
9913+{
9914+ struct omap_dss_s *s = (struct omap_dss_s *) opaque;
9915+ int offset = addr - s->diss_base;
9916+
9917+ switch (offset) {
9918+ case 0x00: /* DSS_REVISIONNUMBER */
9919+ case 0x14: /* DSS_SYSSTATUS */
9920+ case 0x50: /* DSS_PSA_LCD_REG_1 */
9921+ case 0x54: /* DSS_PSA_LCD_REG_2 */
9922+ case 0x58: /* DSS_PSA_VIDEO_REG */
9923+ case 0x5c: /* DSS_STATUS */
9924+ OMAP_RO_REG(addr);
9925+ break;
9926+
9927+ case 0x10: /* DSS_SYSCONFIG */
9928+ if (value & 2) /* SOFTRESET */
9929+ omap_dss_reset(s);
9930+ s->autoidle = value & 1;
9931+ break;
9932+
9933+ case 0x40: /* DSS_CONTROL */
9934+ s->control = value & 0x3dd;
9935+ break;
9936+
9937+ default:
9938+ OMAP_BAD_REG(addr);
9939+ }
9940+}
9941+
9942+static CPUReadMemoryFunc *omap_diss1_readfn[] = {
9943+ omap_badwidth_read32,
9944+ omap_badwidth_read32,
9945+ omap_diss_read,
9946+};
9947+
9948+static CPUWriteMemoryFunc *omap_diss1_writefn[] = {
9949+ omap_badwidth_write32,
9950+ omap_badwidth_write32,
9951+ omap_diss_write,
9952+};
9953+
9954+static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr)
9955+{
9956+ struct omap_dss_s *s = (struct omap_dss_s *) opaque;
9957+ int offset = addr - s->disc_base;
9958+
9959+ switch (offset) {
9960+ case 0x000: /* DISPC_REVISION */
9961+ return 0x20;
9962+
9963+ case 0x010: /* DISPC_SYSCONFIG */
9964+ return s->dispc.idlemode;
9965+
9966+ case 0x014: /* DISPC_SYSSTATUS */
9967+ return 1; /* RESETDONE */
9968+
9969+ case 0x018: /* DISPC_IRQSTATUS */
9970+ return s->dispc.irqst;
9971+
9972+ case 0x01c: /* DISPC_IRQENABLE */
9973+ return s->dispc.irqen;
9974+
9975+ case 0x040: /* DISPC_CONTROL */
9976+ return s->dispc.control;
9977+
9978+ case 0x044: /* DISPC_CONFIG */
9979+ return s->dispc.config;
9980+
9981+ case 0x048: /* DISPC_CAPABLE */
9982+ return s->dispc.capable;
9983+
9984+ case 0x04c: /* DISPC_DEFAULT_COLOR0 */
9985+ return s->dispc.bg[0];
9986+ case 0x050: /* DISPC_DEFAULT_COLOR1 */
9987+ return s->dispc.bg[1];
9988+ case 0x054: /* DISPC_TRANS_COLOR0 */
9989+ return s->dispc.trans[0];
9990+ case 0x058: /* DISPC_TRANS_COLOR1 */
9991+ return s->dispc.trans[1];
9992+
9993+ case 0x05c: /* DISPC_LINE_STATUS */
9994+ return 0x7ff;
9995+ case 0x060: /* DISPC_LINE_NUMBER */
9996+ return s->dispc.line;
9997+
9998+ case 0x064: /* DISPC_TIMING_H */
9999+ return s->dispc.timing[0];
10000+ case 0x068: /* DISPC_TIMING_V */
10001+ return s->dispc.timing[1];
10002+ case 0x06c: /* DISPC_POL_FREQ */
10003+ return s->dispc.timing[2];
10004+ case 0x070: /* DISPC_DIVISOR */
10005+ return s->dispc.timing[3];
10006+
10007+ case 0x078: /* DISPC_SIZE_DIG */
10008+ return ((s->dig.ny - 1) << 16) | (s->dig.nx - 1);
10009+ case 0x07c: /* DISPC_SIZE_LCD */
10010+ return ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1);
10011+
10012+ case 0x080: /* DISPC_GFX_BA0 */
10013+ return s->dispc.l[0].addr[0];
10014+ case 0x084: /* DISPC_GFX_BA1 */
10015+ return s->dispc.l[0].addr[1];
10016+ case 0x088: /* DISPC_GFX_POSITION */
10017+ return (s->dispc.l[0].posy << 16) | s->dispc.l[0].posx;
10018+ case 0x08c: /* DISPC_GFX_SIZE */
10019+ return ((s->dispc.l[0].ny - 1) << 16) | (s->dispc.l[0].nx - 1);
10020+ case 0x0a0: /* DISPC_GFX_ATTRIBUTES */
10021+ return s->dispc.l[0].attr;
10022+ case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */
10023+ return s->dispc.l[0].tresh;
10024+ case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */
10025+ return 256;
10026+ case 0x0ac: /* DISPC_GFX_ROW_INC */
10027+ return s->dispc.l[0].rowinc;
10028+ case 0x0b0: /* DISPC_GFX_PIXEL_INC */
10029+ return s->dispc.l[0].colinc;
10030+ case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */
10031+ return s->dispc.l[0].wininc;
10032+ case 0x0b8: /* DISPC_GFX_TABLE_BA */
10033+ return s->dispc.l[0].addr[2];
10034+
10035+ case 0x0bc: /* DISPC_VID1_BA0 */
10036+ case 0x0c0: /* DISPC_VID1_BA1 */
10037+ case 0x0c4: /* DISPC_VID1_POSITION */
10038+ case 0x0c8: /* DISPC_VID1_SIZE */
10039+ case 0x0cc: /* DISPC_VID1_ATTRIBUTES */
10040+ case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */
10041+ case 0x0d4: /* DISPC_VID1_FIFO_SIZE_STATUS */
10042+ case 0x0d8: /* DISPC_VID1_ROW_INC */
10043+ case 0x0dc: /* DISPC_VID1_PIXEL_INC */
10044+ case 0x0e0: /* DISPC_VID1_FIR */
10045+ case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */
10046+ case 0x0e8: /* DISPC_VID1_ACCU0 */
10047+ case 0x0ec: /* DISPC_VID1_ACCU1 */
10048+ case 0x0f0 ... 0x140: /* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */
10049+ case 0x14c: /* DISPC_VID2_BA0 */
10050+ case 0x150: /* DISPC_VID2_BA1 */
10051+ case 0x154: /* DISPC_VID2_POSITION */
10052+ case 0x158: /* DISPC_VID2_SIZE */
10053+ case 0x15c: /* DISPC_VID2_ATTRIBUTES */
10054+ case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */
10055+ case 0x164: /* DISPC_VID2_FIFO_SIZE_STATUS */
10056+ case 0x168: /* DISPC_VID2_ROW_INC */
10057+ case 0x16c: /* DISPC_VID2_PIXEL_INC */
10058+ case 0x170: /* DISPC_VID2_FIR */
10059+ case 0x174: /* DISPC_VID2_PICTURE_SIZE */
10060+ case 0x178: /* DISPC_VID2_ACCU0 */
10061+ case 0x17c: /* DISPC_VID2_ACCU1 */
10062+ case 0x180 ... 0x1d0: /* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */
10063+ case 0x1d4: /* DISPC_DATA_CYCLE1 */
10064+ case 0x1d8: /* DISPC_DATA_CYCLE2 */
10065+ case 0x1dc: /* DISPC_DATA_CYCLE3 */
10066+ return 0;
10067+
10068+ default:
10069+ break;
10070+ }
10071+ OMAP_BAD_REG(addr);
10072+ return 0;
10073+}
10074+
10075+static void omap_disc_write(void *opaque, target_phys_addr_t addr,
10076+ uint32_t value)
10077+{
10078+ struct omap_dss_s *s = (struct omap_dss_s *) opaque;
10079+ int offset = addr - s->disc_base;
10080+
10081+ switch (offset) {
10082+ case 0x010: /* DISPC_SYSCONFIG */
10083+ if (value & 2) /* SOFTRESET */
10084+ omap_dss_reset(s);
10085+ s->dispc.idlemode = value & 0x301b;
10086+ break;
10087+
10088+ case 0x018: /* DISPC_IRQSTATUS */
10089+ s->dispc.irqst &= ~value;
10090+ omap_dispc_interrupt_update(s);
10091+ break;
10092+
10093+ case 0x01c: /* DISPC_IRQENABLE */
10094+ s->dispc.irqen = value & 0xffff;
10095+ omap_dispc_interrupt_update(s);
10096+ break;
10097+
10098+ case 0x040: /* DISPC_CONTROL */
10099+ s->dispc.control = value & 0x07ff9fff;
10100+ s->dig.enable = (value >> 1) & 1;
10101+ s->lcd.enable = (value >> 0) & 1;
10102+ if (value & (1 << 12)) /* OVERLAY_OPTIMIZATION */
10103+ if (~((s->dispc.l[1].attr | s->dispc.l[2].attr) & 1))
10104+ fprintf(stderr, "%s: Overlay Optimization when no overlay "
10105+ "region effectively exists leads to "
10106+ "unpredictable behaviour!\n", __FUNCTION__);
10107+ if (value & (1 << 6)) { /* GODIGITAL */
10108+ //// Shadows:
10109+ //// s->dispc.config
10110+ //// s->dispc.capable
10111+ //// s->dispc.bg[0]
10112+ //// s->dispc.bg[1]
10113+ //// s->dispc.trans[0]
10114+ //// s->dispc.trans[1]
10115+ //// s->dispc.line
10116+ //// s->dispc.timing[0]
10117+ //// s->dispc.timing[1]
10118+ //// s->dispc.timing[2]
10119+ //// s->dispc.timing[3]
10120+ //// s->lcd.nx
10121+ //// s->lcd.ny
10122+ //// s->dig.nx
10123+ //// s->dig.ny
10124+ //// s->dispc.l[0].addr[0]
10125+ //// s->dispc.l[0].addr[1]
10126+ //// s->dispc.l[0].addr[2]
10127+ //// s->dispc.l[0].posx
10128+ //// s->dispc.l[0].posy
10129+ //// s->dispc.l[0].nx
10130+ //// s->dispc.l[0].ny
10131+ //// s->dispc.l[0].tresh
10132+ //// s->dispc.l[0].rowinc
10133+ //// s->dispc.l[0].colinc
10134+ //// s->dispc.l[0].wininc
10135+ }
10136+ if (value & (1 << 5)) { /* GOLCD */
10137+ }
10138+ s->dispc.invalidate = 1;
10139+ break;
10140+
10141+ case 0x044: /* DISPC_CONFIG */
10142+ s->dispc.config = value & 0x3fff;
10143+ //// bits 2:1 (LOADMODE) reset to 0 after set to 1 and palette loaded
10144+ //// bits 2:1 (LOADMODE) reset to 2 after set to 3 and palette loaded
10145+ s->dispc.invalidate = 1;
10146+ break;
10147+
10148+ case 0x048: /* DISPC_CAPABLE */
10149+ s->dispc.capable = value & 0x3ff;
10150+ break;
10151+
10152+ case 0x04c: /* DISPC_DEFAULT_COLOR0 */
10153+ s->dispc.bg[0] = value & 0xffffff;
10154+ s->dispc.invalidate = 1;
10155+ break;
10156+ case 0x050: /* DISPC_DEFAULT_COLOR1 */
10157+ s->dispc.bg[1] = value & 0xffffff;
10158+ s->dispc.invalidate = 1;
10159+ break;
10160+ case 0x054: /* DISPC_TRANS_COLOR0 */
10161+ s->dispc.trans[0] = value & 0xffffff;
10162+ s->dispc.invalidate = 1;
10163+ break;
10164+ case 0x058: /* DISPC_TRANS_COLOR1 */
10165+ s->dispc.trans[1] = value & 0xffffff;
10166+ s->dispc.invalidate = 1;
10167+ break;
10168+
10169+ case 0x060: /* DISPC_LINE_NUMBER */
10170+ s->dispc.line = value & 0x7ff;
10171+ break;
10172+
10173+ case 0x064: /* DISPC_TIMING_H */
10174+ s->dispc.timing[0] = value & 0x0ff0ff3f;
10175+ break;
10176+ case 0x068: /* DISPC_TIMING_V */
10177+ s->dispc.timing[1] = value & 0x0ff0ff3f;
10178+ break;
10179+ case 0x06c: /* DISPC_POL_FREQ */
10180+ s->dispc.timing[2] = value & 0x0003ffff;
10181+ break;
10182+ case 0x070: /* DISPC_DIVISOR */
10183+ s->dispc.timing[3] = value & 0x00ff00ff;
10184+ break;
10185+
10186+ case 0x078: /* DISPC_SIZE_DIG */
10187+ s->dig.nx = ((value >> 0) & 0x7ff) + 1; /* PPL */
10188+ s->dig.ny = ((value >> 16) & 0x7ff) + 1; /* LPP */
10189+ s->dispc.invalidate = 1;
10190+ break;
10191+ case 0x07c: /* DISPC_SIZE_LCD */
10192+ s->lcd.nx = ((value >> 0) & 0x7ff) + 1; /* PPL */
10193+ s->lcd.ny = ((value >> 16) & 0x7ff) + 1; /* LPP */
10194+ s->dispc.invalidate = 1;
10195+ break;
10196+ case 0x080: /* DISPC_GFX_BA0 */
10197+ s->dispc.l[0].addr[0] = (target_phys_addr_t) value;
10198+ s->dispc.invalidate = 1;
10199+ break;
10200+ case 0x084: /* DISPC_GFX_BA1 */
10201+ s->dispc.l[0].addr[1] = (target_phys_addr_t) value;
10202+ s->dispc.invalidate = 1;
10203+ break;
10204+ case 0x088: /* DISPC_GFX_POSITION */
10205+ s->dispc.l[0].posx = ((value >> 0) & 0x7ff); /* GFXPOSX */
10206+ s->dispc.l[0].posy = ((value >> 16) & 0x7ff); /* GFXPOSY */
10207+ s->dispc.invalidate = 1;
10208+ break;
10209+ case 0x08c: /* DISPC_GFX_SIZE */
10210+ s->dispc.l[0].nx = ((value >> 0) & 0x7ff) + 1; /* GFXSIZEX */
10211+ s->dispc.l[0].ny = ((value >> 16) & 0x7ff) + 1; /* GFXSIZEY */
10212+ s->dispc.invalidate = 1;
10213+ break;
10214+ case 0x0a0: /* DISPC_GFX_ATTRIBUTES */
10215+ s->dispc.l[0].attr = value & 0x7ff;
10216+ if (value & (3 << 9))
10217+ fprintf(stderr, "%s: Big-endian pixel format not supported\n",
10218+ __FUNCTION__);
10219+ s->dispc.l[0].enable = value & 1;
10220+ s->dispc.l[0].bpp = (value >> 1) & 0xf;
10221+ s->dispc.invalidate = 1;
10222+ break;
10223+ case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */
10224+ s->dispc.l[0].tresh = value & 0x01ff01ff;
10225+ break;
10226+ case 0x0ac: /* DISPC_GFX_ROW_INC */
10227+ s->dispc.l[0].rowinc = value;
10228+ s->dispc.invalidate = 1;
10229+ break;
10230+ case 0x0b0: /* DISPC_GFX_PIXEL_INC */
10231+ s->dispc.l[0].colinc = value;
10232+ s->dispc.invalidate = 1;
10233+ break;
10234+ case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */
10235+ s->dispc.l[0].wininc = value;
10236+ break;
10237+ case 0x0b8: /* DISPC_GFX_TABLE_BA */
10238+ s->dispc.l[0].addr[2] = (target_phys_addr_t) value;
10239+ s->dispc.invalidate = 1;
10240+ break;
10241+
10242+ case 0x0bc: /* DISPC_VID1_BA0 */
10243+ case 0x0c0: /* DISPC_VID1_BA1 */
10244+ case 0x0c4: /* DISPC_VID1_POSITION */
10245+ case 0x0c8: /* DISPC_VID1_SIZE */
10246+ case 0x0cc: /* DISPC_VID1_ATTRIBUTES */
10247+ case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */
10248+ case 0x0d8: /* DISPC_VID1_ROW_INC */
10249+ case 0x0dc: /* DISPC_VID1_PIXEL_INC */
10250+ case 0x0e0: /* DISPC_VID1_FIR */
10251+ case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */
10252+ case 0x0e8: /* DISPC_VID1_ACCU0 */
10253+ case 0x0ec: /* DISPC_VID1_ACCU1 */
10254+ case 0x0f0 ... 0x140: /* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */
10255+ case 0x14c: /* DISPC_VID2_BA0 */
10256+ case 0x150: /* DISPC_VID2_BA1 */
10257+ case 0x154: /* DISPC_VID2_POSITION */
10258+ case 0x158: /* DISPC_VID2_SIZE */
10259+ case 0x15c: /* DISPC_VID2_ATTRIBUTES */
10260+ case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */
10261+ case 0x168: /* DISPC_VID2_ROW_INC */
10262+ case 0x16c: /* DISPC_VID2_PIXEL_INC */
10263+ case 0x170: /* DISPC_VID2_FIR */
10264+ case 0x174: /* DISPC_VID2_PICTURE_SIZE */
10265+ case 0x178: /* DISPC_VID2_ACCU0 */
10266+ case 0x17c: /* DISPC_VID2_ACCU1 */
10267+ case 0x180 ... 0x1d0: /* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */
10268+ case 0x1d4: /* DISPC_DATA_CYCLE1 */
10269+ case 0x1d8: /* DISPC_DATA_CYCLE2 */
10270+ case 0x1dc: /* DISPC_DATA_CYCLE3 */
10271+ break;
10272+
10273+ default:
10274+ OMAP_BAD_REG(addr);
10275+ }
10276+}
10277+
10278+static CPUReadMemoryFunc *omap_disc1_readfn[] = {
10279+ omap_badwidth_read32,
10280+ omap_badwidth_read32,
10281+ omap_disc_read,
10282+};
10283+
10284+static CPUWriteMemoryFunc *omap_disc1_writefn[] = {
10285+ omap_badwidth_write32,
10286+ omap_badwidth_write32,
10287+ omap_disc_write,
10288+};
10289+
10290+static void *omap_rfbi_get_buffer(struct omap_dss_s *s)
10291+{
10292+ target_phys_addr_t fb;
10293+ uint32_t pd;
10294+
10295+ /* TODO */
10296+ fb = s->dispc.l[0].addr[0];
10297+
10298+ pd = cpu_get_physical_page_desc(fb);
10299+ if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
10300+ /* TODO */
10301+ cpu_abort(cpu_single_env, "%s: framebuffer outside RAM!\n",
10302+ __FUNCTION__);
10303+ else
10304+ return phys_ram_base +
10305+ (pd & TARGET_PAGE_MASK) +
10306+ (fb & ~TARGET_PAGE_MASK);
10307+}
10308+
10309+static void omap_rfbi_transfer_stop(struct omap_dss_s *s)
10310+{
10311+ if (!s->rfbi.busy)
10312+ return;
10313+
10314+ /* TODO: in non-Bypass mode we probably need to just deassert the DRQ. */
10315+
10316+ s->rfbi.busy = 0;
10317+}
10318+
10319+static void omap_rfbi_transfer_start(struct omap_dss_s *s)
10320+{
10321+ void *data;
10322+ size_t len;
10323+ int pitch;
10324+
10325+ if (!s->rfbi.enable || s->rfbi.busy)
10326+ return;
10327+
10328+ if (s->rfbi.control & (1 << 1)) { /* BYPASS */
10329+ /* TODO: in non-Bypass mode we probably need to just assert the
10330+ * DRQ and wait for DMA to write the pixels. */
10331+ fprintf(stderr, "%s: Bypass mode unimplemented\n", __FUNCTION__);
10332+ return;
10333+ }
10334+
10335+ if (!(s->dispc.control & (1 << 11))) /* RFBIMODE */
10336+ return;
10337+ /* TODO: check that LCD output is enabled in DISPC. */
10338+
10339+ s->rfbi.busy = 1;
10340+
10341+ data = omap_rfbi_get_buffer(s);
10342+
10343+ /* TODO bpp */
10344+ len = s->rfbi.pixels * 2;
10345+ s->rfbi.pixels = 0;
10346+
10347+ /* TODO: negative values */
10348+ pitch = s->dispc.l[0].nx + (s->dispc.l[0].rowinc - 1) / 2;
10349+
10350+ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
10351+ s->rfbi.chip[0]->block(s->rfbi.chip[0]->opaque, 1, data, len, pitch);
10352+ if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
10353+ s->rfbi.chip[1]->block(s->rfbi.chip[1]->opaque, 1, data, len, pitch);
10354+
10355+ omap_rfbi_transfer_stop(s);
10356+
10357+ /* TODO */
10358+ s->dispc.irqst |= 1; /* FRAMEDONE */
10359+ omap_dispc_interrupt_update(s);
10360+}
10361+
10362+static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr)
10363+{
10364+ struct omap_dss_s *s = (struct omap_dss_s *) opaque;
10365+ int offset = addr - s->rfbi_base;
10366+
10367+ switch (offset) {
10368+ case 0x00: /* RFBI_REVISION */
10369+ return 0x10;
10370+
10371+ case 0x10: /* RFBI_SYSCONFIG */
10372+ return s->rfbi.idlemode;
10373+
10374+ case 0x14: /* RFBI_SYSSTATUS */
10375+ return 1 | (s->rfbi.busy << 8); /* RESETDONE */
10376+
10377+ case 0x40: /* RFBI_CONTROL */
10378+ return s->rfbi.control;
10379+
10380+ case 0x44: /* RFBI_PIXELCNT */
10381+ return s->rfbi.pixels;
10382+
10383+ case 0x48: /* RFBI_LINE_NUMBER */
10384+ return s->rfbi.skiplines;
10385+
10386+ case 0x58: /* RFBI_READ */
10387+ case 0x5c: /* RFBI_STATUS */
10388+ return s->rfbi.rxbuf;
10389+
10390+ case 0x60: /* RFBI_CONFIG0 */
10391+ return s->rfbi.config[0];
10392+ case 0x64: /* RFBI_ONOFF_TIME0 */
10393+ return s->rfbi.time[0];
10394+ case 0x68: /* RFBI_CYCLE_TIME0 */
10395+ return s->rfbi.time[1];
10396+ case 0x6c: /* RFBI_DATA_CYCLE1_0 */
10397+ return s->rfbi.data[0];
10398+ case 0x70: /* RFBI_DATA_CYCLE2_0 */
10399+ return s->rfbi.data[1];
10400+ case 0x74: /* RFBI_DATA_CYCLE3_0 */
10401+ return s->rfbi.data[2];
10402+
10403+ case 0x78: /* RFBI_CONFIG1 */
10404+ return s->rfbi.config[1];
10405+ case 0x7c: /* RFBI_ONOFF_TIME1 */
10406+ return s->rfbi.time[2];
10407+ case 0x80: /* RFBI_CYCLE_TIME1 */
10408+ return s->rfbi.time[3];
10409+ case 0x84: /* RFBI_DATA_CYCLE1_1 */
10410+ return s->rfbi.data[3];
10411+ case 0x88: /* RFBI_DATA_CYCLE2_1 */
10412+ return s->rfbi.data[4];
10413+ case 0x8c: /* RFBI_DATA_CYCLE3_1 */
10414+ return s->rfbi.data[5];
10415+
10416+ case 0x90: /* RFBI_VSYNC_WIDTH */
10417+ return s->rfbi.vsync;
10418+ case 0x94: /* RFBI_HSYNC_WIDTH */
10419+ return s->rfbi.hsync;
10420+ }
10421+ OMAP_BAD_REG(addr);
10422+ return 0;
10423+}
10424+
10425+static void omap_rfbi_write(void *opaque, target_phys_addr_t addr,
10426+ uint32_t value)
10427+{
10428+ struct omap_dss_s *s = (struct omap_dss_s *) opaque;
10429+ int offset = addr - s->rfbi_base;
10430+
10431+ switch (offset) {
10432+ case 0x10: /* RFBI_SYSCONFIG */
10433+ if (value & 2) /* SOFTRESET */
10434+ omap_rfbi_reset(s);
10435+ s->rfbi.idlemode = value & 0x19;
10436+ break;
10437+
10438+ case 0x40: /* RFBI_CONTROL */
10439+ s->rfbi.control = value & 0xf;
10440+ s->rfbi.enable = value & 1;
10441+ if (value & (1 << 4) && /* ITE */
10442+ !(s->rfbi.config[0] & s->rfbi.config[1] & 0xc))
10443+ omap_rfbi_transfer_start(s);
10444+ break;
10445+
10446+ case 0x44: /* RFBI_PIXELCNT */
10447+ s->rfbi.pixels = value;
10448+ break;
10449+
10450+ case 0x48: /* RFBI_LINE_NUMBER */
10451+ s->rfbi.skiplines = value & 0x7ff;
10452+ break;
10453+
10454+ case 0x4c: /* RFBI_CMD */
10455+ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
10456+ s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 0, value & 0xffff);
10457+ if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
10458+ s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 0, value & 0xffff);
10459+ break;
10460+ case 0x50: /* RFBI_PARAM */
10461+ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
10462+ s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
10463+ if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
10464+ s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
10465+ break;
10466+ case 0x54: /* RFBI_DATA */
10467+ /* TODO: take into account the format set up in s->rfbi.config[?] and
10468+ * s->rfbi.data[?], but special-case the most usual scenario so that
10469+ * speed doesn't suffer. */
10470+ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) {
10471+ s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
10472+ s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value >> 16);
10473+ }
10474+ if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) {
10475+ s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
10476+ s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value >> 16);
10477+ }
10478+ if (!-- s->rfbi.pixels)
10479+ omap_rfbi_transfer_stop(s);
10480+ break;
10481+ case 0x58: /* RFBI_READ */
10482+ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
10483+ s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
10484+ else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
10485+ s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
10486+ if (!-- s->rfbi.pixels)
10487+ omap_rfbi_transfer_stop(s);
10488+ break;
10489+
10490+ case 0x5c: /* RFBI_STATUS */
10491+ if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
10492+ s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
10493+ else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
10494+ s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
10495+ if (!-- s->rfbi.pixels)
10496+ omap_rfbi_transfer_stop(s);
10497+ break;
10498+
10499+ case 0x60: /* RFBI_CONFIG0 */
10500+ s->rfbi.config[0] = value & 0x003f1fff;
10501+ break;
10502+
10503+ case 0x64: /* RFBI_ONOFF_TIME0 */
10504+ s->rfbi.time[0] = value & 0x3fffffff;
10505+ break;
10506+ case 0x68: /* RFBI_CYCLE_TIME0 */
10507+ s->rfbi.time[1] = value & 0x0fffffff;
10508+ break;
10509+ case 0x6c: /* RFBI_DATA_CYCLE1_0 */
10510+ s->rfbi.data[0] = value & 0x0f1f0f1f;
10511+ break;
10512+ case 0x70: /* RFBI_DATA_CYCLE2_0 */
10513+ s->rfbi.data[1] = value & 0x0f1f0f1f;
10514+ break;
10515+ case 0x74: /* RFBI_DATA_CYCLE3_0 */
10516+ s->rfbi.data[2] = value & 0x0f1f0f1f;
10517+ break;
10518+ case 0x78: /* RFBI_CONFIG1 */
10519+ s->rfbi.config[1] = value & 0x003f1fff;
10520+ break;
10521+
10522+ case 0x7c: /* RFBI_ONOFF_TIME1 */
10523+ s->rfbi.time[2] = value & 0x3fffffff;
10524+ break;
10525+ case 0x80: /* RFBI_CYCLE_TIME1 */
10526+ s->rfbi.time[3] = value & 0x0fffffff;
10527+ break;
10528+ case 0x84: /* RFBI_DATA_CYCLE1_1 */
10529+ s->rfbi.data[3] = value & 0x0f1f0f1f;
10530+ break;
10531+ case 0x88: /* RFBI_DATA_CYCLE2_1 */
10532+ s->rfbi.data[4] = value & 0x0f1f0f1f;
10533+ break;
10534+ case 0x8c: /* RFBI_DATA_CYCLE3_1 */
10535+ s->rfbi.data[5] = value & 0x0f1f0f1f;
10536+ break;
10537+
10538+ case 0x90: /* RFBI_VSYNC_WIDTH */
10539+ s->rfbi.vsync = value & 0xffff;
10540+ break;
10541+ case 0x94: /* RFBI_HSYNC_WIDTH */
10542+ s->rfbi.hsync = value & 0xffff;
10543+ break;
10544+
10545+ default:
10546+ OMAP_BAD_REG(addr);
10547+ }
10548+}
10549+
10550+static CPUReadMemoryFunc *omap_rfbi1_readfn[] = {
10551+ omap_badwidth_read32,
10552+ omap_badwidth_read32,
10553+ omap_rfbi_read,
10554+};
10555+
10556+static CPUWriteMemoryFunc *omap_rfbi1_writefn[] = {
10557+ omap_badwidth_write32,
10558+ omap_badwidth_write32,
10559+ omap_rfbi_write,
10560+};
10561+
10562+static uint32_t omap_venc_read(void *opaque, target_phys_addr_t addr)
10563+{
10564+ struct omap_dss_s *s = (struct omap_dss_s *) opaque;
10565+ int offset = addr - s->venc_base;
10566+
10567+ switch (offset) {
10568+ case 0x00: /* REV_ID */
10569+ case 0x04: /* STATUS */
10570+ case 0x08: /* F_CONTROL */
10571+ case 0x10: /* VIDOUT_CTRL */
10572+ case 0x14: /* SYNC_CTRL */
10573+ case 0x1c: /* LLEN */
10574+ case 0x20: /* FLENS */
10575+ case 0x24: /* HFLTR_CTRL */
10576+ case 0x28: /* CC_CARR_WSS_CARR */
10577+ case 0x2c: /* C_PHASE */
10578+ case 0x30: /* GAIN_U */
10579+ case 0x34: /* GAIN_V */
10580+ case 0x38: /* GAIN_Y */
10581+ case 0x3c: /* BLACK_LEVEL */
10582+ case 0x40: /* BLANK_LEVEL */
10583+ case 0x44: /* X_COLOR */
10584+ case 0x48: /* M_CONTROL */
10585+ case 0x4c: /* BSTAMP_WSS_DATA */
10586+ case 0x50: /* S_CARR */
10587+ case 0x54: /* LINE21 */
10588+ case 0x58: /* LN_SEL */
10589+ case 0x5c: /* L21__WC_CTL */
10590+ case 0x60: /* HTRIGGER_VTRIGGER */
10591+ case 0x64: /* SAVID__EAVID */
10592+ case 0x68: /* FLEN__FAL */
10593+ case 0x6c: /* LAL__PHASE_RESET */
10594+ case 0x70: /* HS_INT_START_STOP_X */
10595+ case 0x74: /* HS_EXT_START_STOP_X */
10596+ case 0x78: /* VS_INT_START_X */
10597+ case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */
10598+ case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */
10599+ case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */
10600+ case 0x88: /* VS_EXT_STOP_Y */
10601+ case 0x90: /* AVID_START_STOP_X */
10602+ case 0x94: /* AVID_START_STOP_Y */
10603+ case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */
10604+ case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */
10605+ case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
10606+ case 0xb0: /* TVDETGP_INT_START_STOP_X */
10607+ case 0xb4: /* TVDETGP_INT_START_STOP_Y */
10608+ case 0xb8: /* GEN_CTRL */
10609+ case 0xc4: /* DAC_TST__DAC_A */
10610+ case 0xc8: /* DAC_B__DAC_C */
10611+ return 0;
10612+
10613+ default:
10614+ break;
10615+ }
10616+ OMAP_BAD_REG(addr);
10617+ return 0;
10618+}
10619+
10620+static void omap_venc_write(void *opaque, target_phys_addr_t addr,
10621+ uint32_t value)
10622+{
10623+ struct omap_dss_s *s = (struct omap_dss_s *) opaque;
10624+ int offset = addr - s->venc_base;
10625+
10626+ switch (offset) {
10627+ case 0x08: /* F_CONTROL */
10628+ case 0x10: /* VIDOUT_CTRL */
10629+ case 0x14: /* SYNC_CTRL */
10630+ case 0x1c: /* LLEN */
10631+ case 0x20: /* FLENS */
10632+ case 0x24: /* HFLTR_CTRL */
10633+ case 0x28: /* CC_CARR_WSS_CARR */
10634+ case 0x2c: /* C_PHASE */
10635+ case 0x30: /* GAIN_U */
10636+ case 0x34: /* GAIN_V */
10637+ case 0x38: /* GAIN_Y */
10638+ case 0x3c: /* BLACK_LEVEL */
10639+ case 0x40: /* BLANK_LEVEL */
10640+ case 0x44: /* X_COLOR */
10641+ case 0x48: /* M_CONTROL */
10642+ case 0x4c: /* BSTAMP_WSS_DATA */
10643+ case 0x50: /* S_CARR */
10644+ case 0x54: /* LINE21 */
10645+ case 0x58: /* LN_SEL */
10646+ case 0x5c: /* L21__WC_CTL */
10647+ case 0x60: /* HTRIGGER_VTRIGGER */
10648+ case 0x64: /* SAVID__EAVID */
10649+ case 0x68: /* FLEN__FAL */
10650+ case 0x6c: /* LAL__PHASE_RESET */
10651+ case 0x70: /* HS_INT_START_STOP_X */
10652+ case 0x74: /* HS_EXT_START_STOP_X */
10653+ case 0x78: /* VS_INT_START_X */
10654+ case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */
10655+ case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */
10656+ case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */
10657+ case 0x88: /* VS_EXT_STOP_Y */
10658+ case 0x90: /* AVID_START_STOP_X */
10659+ case 0x94: /* AVID_START_STOP_Y */
10660+ case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */
10661+ case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */
10662+ case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
10663+ case 0xb0: /* TVDETGP_INT_START_STOP_X */
10664+ case 0xb4: /* TVDETGP_INT_START_STOP_Y */
10665+ case 0xb8: /* GEN_CTRL */
10666+ case 0xc4: /* DAC_TST__DAC_A */
10667+ case 0xc8: /* DAC_B__DAC_C */
10668+ break;
10669+
10670+ default:
10671+ OMAP_BAD_REG(addr);
10672+ }
10673+}
10674+
10675+static CPUReadMemoryFunc *omap_venc1_readfn[] = {
10676+ omap_badwidth_read32,
10677+ omap_badwidth_read32,
10678+ omap_venc_read,
10679+};
10680+
10681+static CPUWriteMemoryFunc *omap_venc1_writefn[] = {
10682+ omap_badwidth_write32,
10683+ omap_badwidth_write32,
10684+ omap_venc_write,
10685+};
10686+
10687+static uint32_t omap_im3_read(void *opaque, target_phys_addr_t addr)
10688+{
10689+ struct omap_dss_s *s = (struct omap_dss_s *) opaque;
10690+ int offset = addr - s->im3_base;
10691+
10692+ switch (offset) {
10693+ case 0x0a8: /* SBIMERRLOGA */
10694+ case 0x0b0: /* SBIMERRLOG */
10695+ case 0x190: /* SBIMSTATE */
10696+ case 0x198: /* SBTMSTATE_L */
10697+ case 0x19c: /* SBTMSTATE_H */
10698+ case 0x1a8: /* SBIMCONFIG_L */
10699+ case 0x1ac: /* SBIMCONFIG_H */
10700+ case 0x1f8: /* SBID_L */
10701+ case 0x1fc: /* SBID_H */
10702+ return 0;
10703+
10704+ default:
10705+ break;
10706+ }
10707+ OMAP_BAD_REG(addr);
10708+ return 0;
10709+}
10710+
10711+static void omap_im3_write(void *opaque, target_phys_addr_t addr,
10712+ uint32_t value)
10713+{
10714+ struct omap_dss_s *s = (struct omap_dss_s *) opaque;
10715+ int offset = addr - s->im3_base;
10716+
10717+ switch (offset) {
10718+ case 0x0b0: /* SBIMERRLOG */
10719+ case 0x190: /* SBIMSTATE */
10720+ case 0x198: /* SBTMSTATE_L */
10721+ case 0x19c: /* SBTMSTATE_H */
10722+ case 0x1a8: /* SBIMCONFIG_L */
10723+ case 0x1ac: /* SBIMCONFIG_H */
10724+ break;
10725+
10726+ default:
10727+ OMAP_BAD_REG(addr);
10728+ }
10729+}
10730+
10731+static CPUReadMemoryFunc *omap_im3_readfn[] = {
10732+ omap_badwidth_read32,
10733+ omap_badwidth_read32,
10734+ omap_im3_read,
10735+};
10736+
10737+static CPUWriteMemoryFunc *omap_im3_writefn[] = {
10738+ omap_badwidth_write32,
10739+ omap_badwidth_write32,
10740+ omap_im3_write,
10741+};
10742+
10743+struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
10744+ target_phys_addr_t l3_base, DisplayState *ds,
10745+ qemu_irq irq, qemu_irq drq,
10746+ omap_clk fck1, omap_clk fck2, omap_clk ck54m,
10747+ omap_clk ick1, omap_clk ick2)
10748+{
10749+ int iomemtype[5];
10750+ struct omap_dss_s *s = (struct omap_dss_s *)
10751+ qemu_mallocz(sizeof(struct omap_dss_s));
10752+
10753+ s->irq = irq;
10754+ s->drq = drq;
10755+ s->state = ds;
10756+ omap_dss_reset(s);
10757+
10758+ iomemtype[0] = cpu_register_io_memory(0, omap_diss1_readfn,
10759+ omap_diss1_writefn, s);
10760+ iomemtype[1] = cpu_register_io_memory(0, omap_disc1_readfn,
10761+ omap_disc1_writefn, s);
10762+ iomemtype[2] = cpu_register_io_memory(0, omap_rfbi1_readfn,
10763+ omap_rfbi1_writefn, s);
10764+ iomemtype[3] = cpu_register_io_memory(0, omap_venc1_readfn,
10765+ omap_venc1_writefn, s);
10766+ iomemtype[4] = cpu_register_io_memory(0, omap_im3_readfn,
10767+ omap_im3_writefn, s);
10768+ s->diss_base = omap_l4_attach(ta, 0, iomemtype[0]);
10769+ s->disc_base = omap_l4_attach(ta, 1, iomemtype[1]);
10770+ s->rfbi_base = omap_l4_attach(ta, 2, iomemtype[2]);
10771+ s->venc_base = omap_l4_attach(ta, 3, iomemtype[3]);
10772+ s->im3_base = l3_base;
10773+ cpu_register_physical_memory(s->im3_base, 0x1000, iomemtype[4]);
10774+
10775+#if 0
10776+ if (ds)
10777+ graphic_console_init(ds, omap_update_display,
10778+ omap_invalidate_display, omap_screen_dump, s);
10779+#endif
10780+
10781+ return s;
10782+}
10783+
10784+void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip)
10785+{
10786+ if (cs < 0 || cs > 1)
10787+ cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
10788+ s->rfbi.chip[cs] = chip;
10789+}
10790diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c
10791index de63309..9915676 100644
10792--- a/hw/omap_i2c.c
10793+++ b/hw/omap_i2c.c
10794@@ -150,6 +150,8 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s)
10795 }
10796 if (ack && s->count_cur)
10797 s->stat |= 1 << 4; /* XRDY */
10798+ else
10799+ s->stat &= ~(1 << 4); /* XRDY */
10800 if (!s->count_cur) {
10801 s->stat |= 1 << 2; /* ARDY */
10802 s->control &= ~(1 << 10); /* MST */
10803@@ -161,6 +163,8 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s)
10804 }
10805 if (s->rxlen)
10806 s->stat |= 1 << 3; /* RRDY */
10807+ else
10808+ s->stat &= ~(1 << 3); /* RRDY */
10809 }
10810 if (!s->count_cur) {
10811 if ((s->control >> 1) & 1) { /* STP */
10812@@ -321,7 +325,8 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
10813 return;
10814 }
10815
10816- s->stat &= ~(value & 0x3f);
10817+ /* RRDY and XRDY are reset by hardware. (in all versions???) */
10818+ s->stat &= ~(value & 0x27);
10819 omap_i2c_interrupts_update(s);
10820 break;
10821
10822@@ -376,11 +381,13 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
10823 break;
10824 }
10825 if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */
10826- printf("%s: I^2C slave mode not supported\n", __FUNCTION__);
10827+ fprintf(stderr, "%s: I^2C slave mode not supported\n",
10828+ __FUNCTION__);
10829 break;
10830 }
10831 if ((value & (1 << 15)) && value & (1 << 8)) { /* XA */
10832- printf("%s: 10-bit addressing mode not supported\n", __FUNCTION__);
10833+ fprintf(stderr, "%s: 10-bit addressing mode not supported\n",
10834+ __FUNCTION__);
10835 break;
10836 }
10837 if ((value & (1 << 15)) && value & (1 << 0)) { /* STT */
10838@@ -427,7 +434,7 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
10839 omap_i2c_interrupts_update(s);
10840 }
10841 if (value & (1 << 15)) /* ST_EN */
10842- printf("%s: System Test not supported\n", __FUNCTION__);
10843+ fprintf(stderr, "%s: System Test not supported\n", __FUNCTION__);
10844 break;
10845
10846 default:
10847diff --git a/hw/omap_mmc.c b/hw/omap_mmc.c
10848index 6fbbb84..e46289a 100644
10849--- a/hw/omap_mmc.c
10850+++ b/hw/omap_mmc.c
10851@@ -26,19 +26,24 @@ struct omap_mmc_s {
10852 target_phys_addr_t base;
10853 qemu_irq irq;
10854 qemu_irq *dma;
10855+ qemu_irq coverswitch;
10856 omap_clk clk;
10857 SDState *card;
10858 uint16_t last_cmd;
10859 uint16_t sdio;
10860 uint16_t rsp[8];
10861 uint32_t arg;
10862+ int lines;
10863 int dw;
10864 int mode;
10865 int enable;
10866+ int be;
10867+ int rev;
10868 uint16_t status;
10869 uint16_t mask;
10870 uint8_t cto;
10871 uint16_t dto;
10872+ int clkdiv;
10873 uint16_t fifo[32];
10874 int fifo_start;
10875 int fifo_len;
10876@@ -53,6 +58,11 @@ struct omap_mmc_s {
10877
10878 int ddir;
10879 int transfer;
10880+
10881+ int cdet_wakeup;
10882+ int cdet_enable;
10883+ int cdet_state;
10884+ qemu_irq cdet;
10885 };
10886
10887 static void omap_mmc_interrupts_update(struct omap_mmc_s *s)
10888@@ -107,6 +117,11 @@ static void omap_mmc_command(struct omap_mmc_s *host, int cmd, int dir,
10889 struct sd_request_s request;
10890 uint8_t response[16];
10891
10892+ if (init && cmd == 0) {
10893+ host->status |= 0x0001;
10894+ return;
10895+ }
10896+
10897 if (resptype == sd_r1 && busy)
10898 resptype = sd_r1b;
10899
10900@@ -265,6 +280,34 @@ static void omap_mmc_update(void *opaque)
10901 omap_mmc_interrupts_update(s);
10902 }
10903
10904+void omap_mmc_reset(struct omap_mmc_s *host)
10905+{
10906+ host->last_cmd = 0;
10907+ memset(host->rsp, 0, sizeof(host->rsp));
10908+ host->arg = 0;
10909+ host->dw = 0;
10910+ host->mode = 0;
10911+ host->enable = 0;
10912+ host->status = 0;
10913+ host->mask = 0;
10914+ host->cto = 0;
10915+ host->dto = 0;
10916+ host->fifo_len = 0;
10917+ host->blen = 0;
10918+ host->blen_counter = 0;
10919+ host->nblk = 0;
10920+ host->nblk_counter = 0;
10921+ host->tx_dma = 0;
10922+ host->rx_dma = 0;
10923+ host->ae_level = 0x00;
10924+ host->af_level = 0x1f;
10925+ host->transfer = 0;
10926+ host->cdet_wakeup = 0;
10927+ host->cdet_enable = 0;
10928+ qemu_set_irq(host->coverswitch, host->cdet_state);
10929+ host->clkdiv = 0;
10930+}
10931+
10932 static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
10933 {
10934 uint16_t i;
10935@@ -282,7 +325,8 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
10936 return s->arg >> 16;
10937
10938 case 0x0c: /* MMC_CON */
10939- return (s->dw << 15) | (s->mode << 12) | (s->enable << 11);
10940+ return (s->dw << 15) | (s->mode << 12) | (s->enable << 11) |
10941+ (s->be << 10) | s->clkdiv;
10942
10943 case 0x10: /* MMC_STAT */
10944 return s->status;
10945@@ -324,12 +368,12 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
10946 case 0x30: /* MMC_SPI */
10947 return 0x0000;
10948 case 0x34: /* MMC_SDIO */
10949- return s->sdio;
10950+ return (s->cdet_wakeup << 2) | (s->cdet_enable) | s->sdio;
10951 case 0x38: /* MMC_SYST */
10952 return 0x0000;
10953
10954 case 0x3c: /* MMC_REV */
10955- return 0x0001;
10956+ return s->rev;
10957
10958 case 0x40: /* MMC_RSP0 */
10959 case 0x44: /* MMC_RSP1 */
10960@@ -340,6 +384,13 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
10961 case 0x58: /* MMC_RSP6 */
10962 case 0x5c: /* MMC_RSP7 */
10963 return s->rsp[(offset - 0x40) >> 2];
10964+
10965+ /* OMAP2-specific */
10966+ case 0x60: /* MMC_IOSR */
10967+ case 0x64: /* MMC_SYSC */
10968+ return 0;
10969+ case 0x68: /* MMC_SYSS */
10970+ return 1; /* RSTD */
10971 }
10972
10973 OMAP_BAD_REG(offset);
10974@@ -383,10 +434,16 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
10975 s->dw = (value >> 15) & 1;
10976 s->mode = (value >> 12) & 3;
10977 s->enable = (value >> 11) & 1;
10978+ s->be = (value >> 10) & 1;
10979+ s->clkdiv = (value >> 0) & (s->rev >= 2 ? 0x3ff : 0xff);
10980 if (s->mode != 0)
10981 printf("SD mode %i unimplemented!\n", s->mode);
10982- if (s->dw != 0)
10983+ if (s->be != 0)
10984+ printf("SD FIFO byte sex unimplemented!\n");
10985+ if (s->dw != 0 && s->lines < 4)
10986 printf("4-bit SD bus enabled\n");
10987+ if (!s->enable)
10988+ omap_mmc_reset(s);
10989 break;
10990
10991 case 0x10: /* MMC_STAT */
10992@@ -395,13 +452,13 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
10993 break;
10994
10995 case 0x14: /* MMC_IE */
10996- s->mask = value;
10997+ s->mask = value & 0x7fff;
10998 omap_mmc_interrupts_update(s);
10999 break;
11000
11001 case 0x18: /* MMC_CTO */
11002 s->cto = value & 0xff;
11003- if (s->cto > 0xfd)
11004+ if (s->cto > 0xfd && s->rev <= 1)
11005 printf("MMC: CTO of 0xff and 0xfe cannot be used!\n");
11006 break;
11007
11008@@ -446,10 +503,12 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
11009 break;
11010
11011 /* SPI, SDIO and TEST modes unimplemented */
11012- case 0x30: /* MMC_SPI */
11013+ case 0x30: /* MMC_SPI (OMAP1 only) */
11014 break;
11015 case 0x34: /* MMC_SDIO */
11016- s->sdio = value & 0x2020;
11017+ s->sdio = value & (s->rev >= 2 ? 0xfbf3 : 0x2020);
11018+ s->cdet_wakeup = (value >> 9) & 1;
11019+ s->cdet_enable = (value >> 2) & 1;
11020 break;
11021 case 0x38: /* MMC_SYST */
11022 break;
11023@@ -466,6 +525,19 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
11024 OMAP_RO_REG(offset);
11025 break;
11026
11027+ /* OMAP2-specific */
11028+ case 0x60: /* MMC_IOSR */
11029+ if (value & 0xf)
11030+ printf("MMC: SDIO bits used!\n");
11031+ break;
11032+ case 0x64: /* MMC_SYSC */
11033+ if (value & (1 << 2)) /* SRTS */
11034+ omap_mmc_reset(s);
11035+ break;
11036+ case 0x68: /* MMC_SYSS */
11037+ OMAP_RO_REG(offset);
11038+ break;
11039+
11040 default:
11041 OMAP_BAD_REG(offset);
11042 }
11043@@ -483,28 +555,21 @@ static CPUWriteMemoryFunc *omap_mmc_writefn[] = {
11044 omap_badwidth_write16,
11045 };
11046
11047-void omap_mmc_reset(struct omap_mmc_s *host)
11048+static void omap_mmc_cover_cb(void *opaque, int line, int level)
11049 {
11050- host->last_cmd = 0;
11051- memset(host->rsp, 0, sizeof(host->rsp));
11052- host->arg = 0;
11053- host->dw = 0;
11054- host->mode = 0;
11055- host->enable = 0;
11056- host->status = 0;
11057- host->mask = 0;
11058- host->cto = 0;
11059- host->dto = 0;
11060- host->fifo_len = 0;
11061- host->blen = 0;
11062- host->blen_counter = 0;
11063- host->nblk = 0;
11064- host->nblk_counter = 0;
11065- host->tx_dma = 0;
11066- host->rx_dma = 0;
11067- host->ae_level = 0x00;
11068- host->af_level = 0x1f;
11069- host->transfer = 0;
11070+ struct omap_mmc_s *host = (struct omap_mmc_s *) opaque;
11071+
11072+ if (!host->cdet_state && level) {
11073+ host->status |= 0x0002;
11074+ omap_mmc_interrupts_update(host);
11075+ if (host->cdet_wakeup)
11076+ /* TODO: Assert wake-up */;
11077+ }
11078+
11079+ if (host->cdet_state != level) {
11080+ qemu_set_irq(host->coverswitch, level);
11081+ host->cdet_state = level;
11082+ }
11083 }
11084
11085 struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
11086@@ -519,6 +584,10 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
11087 s->base = base;
11088 s->dma = dma;
11089 s->clk = clk;
11090+ s->lines = 1; /* TODO: needs to be settable per-board */
11091+ s->rev = 1;
11092+
11093+ omap_mmc_reset(s);
11094
11095 iomemtype = cpu_register_io_memory(0, omap_mmc_readfn,
11096 omap_mmc_writefn, s);
11097@@ -530,7 +599,46 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
11098 return s;
11099 }
11100
11101+struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
11102+ BlockDriverState *bd, qemu_irq irq, qemu_irq dma[],
11103+ omap_clk fclk, omap_clk iclk)
11104+{
11105+ int iomemtype;
11106+ struct omap_mmc_s *s = (struct omap_mmc_s *)
11107+ qemu_mallocz(sizeof(struct omap_mmc_s));
11108+
11109+ s->irq = irq;
11110+ s->dma = dma;
11111+ s->clk = fclk;
11112+ s->lines = 4;
11113+ s->rev = 2;
11114+
11115+ omap_mmc_reset(s);
11116+
11117+ iomemtype = cpu_register_io_memory(0, omap_mmc_readfn,
11118+ omap_mmc_writefn, s);
11119+ s->base = omap_l4_attach(ta, 0, iomemtype);
11120+
11121+ /* Instantiate the storage */
11122+ s->card = sd_init(bd, 0);
11123+
11124+ s->cdet = qemu_allocate_irqs(omap_mmc_cover_cb, s, 1)[0];
11125+ sd_set_cb(s->card, 0, s->cdet);
11126+
11127+ return s;
11128+}
11129+
11130 void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover)
11131 {
11132- sd_set_cb(s->card, ro, cover);
11133+ if (s->cdet) {
11134+ sd_set_cb(s->card, ro, s->cdet);
11135+ s->coverswitch = cover;
11136+ qemu_set_irq(cover, s->cdet_state);
11137+ } else
11138+ sd_set_cb(s->card, ro, cover);
11139+}
11140+
11141+void omap_mmc_enable(struct omap_mmc_s *s, int enable)
11142+{
11143+ sd_enable(s->card, enable);
11144 }
11145diff --git a/hw/onenand.c b/hw/onenand.c
11146new file mode 100644
11147index 0000000..549d392
11148--- /dev/null
11149+++ b/hw/onenand.c
11150@@ -0,0 +1,642 @@
11151+/*
11152+ * OneNAND flash memories emulation.
11153+ *
11154+ * Copyright (C) 2008 Nokia Corporation
11155+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
11156+ *
11157+ * This program is free software; you can redistribute it and/or
11158+ * modify it under the terms of the GNU General Public License as
11159+ * published by the Free Software Foundation; either version 2 of
11160+ * the License, or (at your option) any later version.
11161+ *
11162+ * This program is distributed in the hope that it will be useful,
11163+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11164+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11165+ * GNU General Public License for more details.
11166+ *
11167+ * You should have received a copy of the GNU General Public License
11168+ * along with this program; if not, write to the Free Software
11169+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
11170+ * MA 02111-1307 USA
11171+ */
11172+
11173+#include "qemu-common.h"
11174+#include "flash.h"
11175+#include "irq.h"
11176+#include "sysemu.h"
11177+#include "block.h"
11178+
11179+/* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
11180+#define PAGE_SHIFT 11
11181+
11182+/* Fixed */
11183+#define BLOCK_SHIFT (PAGE_SHIFT + 6)
11184+
11185+struct onenand_s {
11186+ uint32_t id;
11187+ int shift;
11188+ target_phys_addr_t base;
11189+ qemu_irq intr;
11190+ qemu_irq rdy;
11191+ BlockDriverState *bdrv;
11192+ BlockDriverState *bdrv_cur;
11193+ uint8_t *image;
11194+ uint8_t *otp;
11195+ uint8_t *current;
11196+ ram_addr_t ram;
11197+ uint8_t *boot[2];
11198+ uint8_t *data[2][2];
11199+ int iomemtype;
11200+ int cycle;
11201+ int otpmode;
11202+
11203+ uint16_t addr[8];
11204+ uint16_t unladdr[8];
11205+ int bufaddr;
11206+ int count;
11207+ uint16_t command;
11208+ uint16_t config[2];
11209+ uint16_t status;
11210+ uint16_t intstatus;
11211+ uint16_t wpstatus;
11212+
11213+ struct ecc_state_s ecc;
11214+
11215+ int density_mask;
11216+ int secs;
11217+ int secs_cur;
11218+ int blocks;
11219+ uint8_t *blockwp;
11220+};
11221+
11222+enum {
11223+ ONEN_BUF_BLOCK = 0,
11224+ ONEN_BUF_BLOCK2 = 1,
11225+ ONEN_BUF_DEST_BLOCK = 2,
11226+ ONEN_BUF_DEST_PAGE = 3,
11227+ ONEN_BUF_PAGE = 7,
11228+};
11229+
11230+enum {
11231+ ONEN_ERR_CMD = 1 << 10,
11232+ ONEN_ERR_ERASE = 1 << 11,
11233+ ONEN_ERR_PROG = 1 << 12,
11234+ ONEN_ERR_LOAD = 1 << 13,
11235+};
11236+
11237+enum {
11238+ ONEN_INT_RESET = 1 << 4,
11239+ ONEN_INT_ERASE = 1 << 5,
11240+ ONEN_INT_PROG = 1 << 6,
11241+ ONEN_INT_LOAD = 1 << 7,
11242+ ONEN_INT = 1 << 15,
11243+};
11244+
11245+enum {
11246+ ONEN_LOCK_LOCKTIGHTEN = 1 << 0,
11247+ ONEN_LOCK_LOCKED = 1 << 1,
11248+ ONEN_LOCK_UNLOCKED = 1 << 2,
11249+};
11250+
11251+void onenand_base_update(void *opaque, target_phys_addr_t new)
11252+{
11253+ struct onenand_s *s = (struct onenand_s *) opaque;
11254+
11255+ s->base = new;
11256+
11257+ /* XXX: We should use IO_MEM_ROMD but we broke it earlier...
11258+ * Both 0x0000 ... 0x01ff and 0x8000 ... 0x800f can be used to
11259+ * write boot commands. Also take note of the BWPS bit. */
11260+ cpu_register_physical_memory(s->base + (0x0000 << s->shift),
11261+ 0x0200 << s->shift, s->iomemtype);
11262+ cpu_register_physical_memory(s->base + (0x0200 << s->shift),
11263+ 0xbe00 << s->shift,
11264+ (s->ram +(0x0200 << s->shift)) | IO_MEM_RAM);
11265+ if (s->iomemtype)
11266+ cpu_register_physical_memory(s->base + (0xc000 << s->shift),
11267+ 0x4000 << s->shift, s->iomemtype);
11268+}
11269+
11270+void onenand_base_unmap(void *opaque)
11271+{
11272+ struct onenand_s *s = (struct onenand_s *) opaque;
11273+
11274+ cpu_register_physical_memory(s->base,
11275+ 0x10000 << s->shift, IO_MEM_UNASSIGNED);
11276+}
11277+
11278+static void onenand_intr_update(struct onenand_s *s)
11279+{
11280+ qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1);
11281+}
11282+
11283+/* Hot reset (Reset OneNAND command) or warm reset (RP pin low) */
11284+static void onenand_reset(struct onenand_s *s, int cold)
11285+{
11286+ memset(&s->addr, 0, sizeof(s->addr));
11287+ s->command = 0;
11288+ s->count = 1;
11289+ s->bufaddr = 0;
11290+ s->config[0] = 0x40c0;
11291+ s->config[1] = 0x0000;
11292+ onenand_intr_update(s);
11293+ qemu_irq_raise(s->rdy);
11294+ s->status = 0x0000;
11295+ s->intstatus = cold ? 0x8080 : 0x8010;
11296+ s->unladdr[0] = 0;
11297+ s->unladdr[1] = 0;
11298+ s->wpstatus = 0x0002;
11299+ s->cycle = 0;
11300+ s->otpmode = 0;
11301+ s->bdrv_cur = s->bdrv;
11302+ s->current = s->image;
11303+ s->secs_cur = s->secs;
11304+
11305+ if (cold) {
11306+ /* Lock the whole flash */
11307+ memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks);
11308+
11309+ if (s->bdrv && bdrv_read(s->bdrv, 0, s->boot[0], 8) < 0)
11310+ cpu_abort(cpu_single_env, "%s: Loading the BootRAM failed.\n",
11311+ __FUNCTION__);
11312+ }
11313+}
11314+
11315+static inline int onenand_load_main(struct onenand_s *s, int sec, int secn,
11316+ void *dest)
11317+{
11318+ if (s->bdrv_cur)
11319+ return bdrv_read(s->bdrv_cur, sec, dest, secn) < 0;
11320+ else if (sec + secn > s->secs_cur)
11321+ return 1;
11322+
11323+ memcpy(dest, s->current + (sec << 9), secn << 9);
11324+
11325+ return 0;
11326+}
11327+
11328+static inline int onenand_prog_main(struct onenand_s *s, int sec, int secn,
11329+ void *src)
11330+{
11331+ if (s->bdrv_cur)
11332+ return bdrv_write(s->bdrv_cur, sec, src, secn) < 0;
11333+ else if (sec + secn > s->secs_cur)
11334+ return 1;
11335+
11336+ memcpy(s->current + (sec << 9), src, secn << 9);
11337+
11338+ return 0;
11339+}
11340+
11341+static inline int onenand_load_spare(struct onenand_s *s, int sec, int secn,
11342+ void *dest)
11343+{
11344+ uint8_t buf[512];
11345+
11346+ if (s->bdrv_cur) {
11347+ if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0)
11348+ return 1;
11349+ memcpy(dest, buf + ((sec & 31) << 4), secn << 4);
11350+ } else if (sec + secn > s->secs_cur)
11351+ return 1;
11352+ else
11353+ memcpy(dest, s->current + (s->secs_cur << 9) + (sec << 4), secn << 4);
11354+
11355+ return 0;
11356+}
11357+
11358+static inline int onenand_prog_spare(struct onenand_s *s, int sec, int secn,
11359+ void *src)
11360+{
11361+ uint8_t buf[512];
11362+
11363+ if (s->bdrv_cur) {
11364+ if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0)
11365+ return 1;
11366+ memcpy(buf + ((sec & 31) << 4), src, secn << 4);
11367+ return bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0;
11368+ } else if (sec + secn > s->secs_cur)
11369+ return 1;
11370+
11371+ memcpy(s->current + (s->secs_cur << 9) + (sec << 4), src, secn << 4);
11372+
11373+ return 0;
11374+}
11375+
11376+static inline int onenand_erase(struct onenand_s *s, int sec, int num)
11377+{
11378+ /* TODO: optimise */
11379+ uint8_t buf[512];
11380+
11381+ memset(buf, 0xff, sizeof(buf));
11382+ for (; num > 0; num --, sec ++) {
11383+ if (onenand_prog_main(s, sec, 1, buf))
11384+ return 1;
11385+ if (onenand_prog_spare(s, sec, 1, buf))
11386+ return 1;
11387+ }
11388+
11389+ return 0;
11390+}
11391+
11392+static void onenand_command(struct onenand_s *s, int cmd)
11393+{
11394+ int b;
11395+ int sec;
11396+ void *buf;
11397+#define SETADDR(block, page) \
11398+ sec = (s->addr[page] & 3) + \
11399+ ((((s->addr[page] >> 2) & 0x3f) + \
11400+ (((s->addr[block] & 0xfff) | \
11401+ (s->addr[block] >> 15 ? \
11402+ s->density_mask : 0)) << 6)) << (PAGE_SHIFT - 9));
11403+#define SETBUF_M() \
11404+ buf = (s->bufaddr & 8) ? \
11405+ s->data[(s->bufaddr >> 2) & 1][0] : s->boot[0]; \
11406+ buf += (s->bufaddr & 3) << 9;
11407+#define SETBUF_S() \
11408+ buf = (s->bufaddr & 8) ? \
11409+ s->data[(s->bufaddr >> 2) & 1][1] : s->boot[1]; \
11410+ buf += (s->bufaddr & 3) << 4;
11411+
11412+ switch (cmd) {
11413+ case 0x00: /* Load single/multiple sector data unit into buffer */
11414+ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
11415+
11416+ SETBUF_M()
11417+ if (onenand_load_main(s, sec, s->count, buf))
11418+ s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
11419+
11420+#if 0
11421+ SETBUF_S()
11422+ if (onenand_load_spare(s, sec, s->count, buf))
11423+ s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
11424+#endif
11425+
11426+ /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
11427+ * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
11428+ * then we need two split the read/write into two chunks.
11429+ */
11430+ s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
11431+ break;
11432+ case 0x13: /* Load single/multiple spare sector into buffer */
11433+ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
11434+
11435+ SETBUF_S()
11436+ if (onenand_load_spare(s, sec, s->count, buf))
11437+ s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
11438+
11439+ /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
11440+ * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
11441+ * then we need two split the read/write into two chunks.
11442+ */
11443+ s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
11444+ break;
11445+ case 0x80: /* Program single/multiple sector data unit from buffer */
11446+ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
11447+
11448+ SETBUF_M()
11449+ if (onenand_prog_main(s, sec, s->count, buf))
11450+ s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
11451+
11452+#if 0
11453+ SETBUF_S()
11454+ if (onenand_prog_spare(s, sec, s->count, buf))
11455+ s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
11456+#endif
11457+
11458+ /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
11459+ * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
11460+ * then we need two split the read/write into two chunks.
11461+ */
11462+ s->intstatus |= ONEN_INT | ONEN_INT_PROG;
11463+ break;
11464+ case 0x1a: /* Program single/multiple spare area sector from buffer */
11465+ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
11466+
11467+ SETBUF_S()
11468+ if (onenand_prog_spare(s, sec, s->count, buf))
11469+ s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
11470+
11471+ /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
11472+ * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
11473+ * then we need two split the read/write into two chunks.
11474+ */
11475+ s->intstatus |= ONEN_INT | ONEN_INT_PROG;
11476+ break;
11477+ case 0x1b: /* Copy-back program */
11478+ SETBUF_S()
11479+
11480+ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
11481+ if (onenand_load_main(s, sec, s->count, buf))
11482+ s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
11483+
11484+ SETADDR(ONEN_BUF_DEST_BLOCK, ONEN_BUF_DEST_PAGE)
11485+ if (onenand_prog_main(s, sec, s->count, buf))
11486+ s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
11487+
11488+ /* TODO: spare areas */
11489+
11490+ s->intstatus |= ONEN_INT | ONEN_INT_PROG;
11491+ break;
11492+
11493+ case 0x23: /* Unlock NAND array block(s) */
11494+ s->intstatus |= ONEN_INT;
11495+
11496+ /* XXX the previous (?) area should be locked automatically */
11497+ for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
11498+ if (b >= s->blocks) {
11499+ s->status |= ONEN_ERR_CMD;
11500+ break;
11501+ }
11502+ if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
11503+ break;
11504+
11505+ s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED;
11506+ }
11507+ break;
11508+ case 0x2a: /* Lock NAND array block(s) */
11509+ s->intstatus |= ONEN_INT;
11510+
11511+ for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
11512+ if (b >= s->blocks) {
11513+ s->status |= ONEN_ERR_CMD;
11514+ break;
11515+ }
11516+ if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
11517+ break;
11518+
11519+ s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKED;
11520+ }
11521+ break;
11522+ case 0x2c: /* Lock-tight NAND array block(s) */
11523+ s->intstatus |= ONEN_INT;
11524+
11525+ for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
11526+ if (b >= s->blocks) {
11527+ s->status |= ONEN_ERR_CMD;
11528+ break;
11529+ }
11530+ if (s->blockwp[b] == ONEN_LOCK_UNLOCKED)
11531+ continue;
11532+
11533+ s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKTIGHTEN;
11534+ }
11535+ break;
11536+
11537+ case 0x71: /* Erase-Verify-Read */
11538+ s->intstatus |= ONEN_INT;
11539+ break;
11540+ case 0x95: /* Multi-block erase */
11541+ qemu_irq_pulse(s->intr);
11542+ /* Fall through. */
11543+ case 0x94: /* Block erase */
11544+ sec = ((s->addr[ONEN_BUF_BLOCK] & 0xfff) |
11545+ (s->addr[ONEN_BUF_BLOCK] >> 15 ? s->density_mask : 0))
11546+ << (BLOCK_SHIFT - 9);
11547+ if (onenand_erase(s, sec, 1 << (BLOCK_SHIFT - 9)))
11548+ s->status |= ONEN_ERR_CMD | ONEN_ERR_ERASE;
11549+
11550+ s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
11551+ break;
11552+ case 0xb0: /* Erase suspend */
11553+ break;
11554+ case 0x30: /* Erase resume */
11555+ s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
11556+ break;
11557+
11558+ case 0xf0: /* Reset NAND Flash core */
11559+ onenand_reset(s, 0);
11560+ break;
11561+ case 0xf3: /* Reset OneNAND */
11562+ onenand_reset(s, 0);
11563+ break;
11564+
11565+ case 0x65: /* OTP Access */
11566+ s->intstatus |= ONEN_INT;
11567+ s->bdrv_cur = 0;
11568+ s->current = s->otp;
11569+ s->secs_cur = 1 << (BLOCK_SHIFT - 9);
11570+ s->addr[ONEN_BUF_BLOCK] = 0;
11571+ s->otpmode = 1;
11572+ break;
11573+
11574+ default:
11575+ s->status |= ONEN_ERR_CMD;
11576+ s->intstatus |= ONEN_INT;
11577+ fprintf(stderr, "%s: unknown OneNAND command %x\n",
11578+ __FUNCTION__, cmd);
11579+ }
11580+
11581+ onenand_intr_update(s);
11582+}
11583+
11584+static uint32_t onenand_read(void *opaque, target_phys_addr_t addr)
11585+{
11586+ struct onenand_s *s = (struct onenand_s *) opaque;
11587+ int offset = (addr - s->base) >> s->shift;
11588+
11589+ switch (offset) {
11590+ case 0x0000 ... 0xc000:
11591+ return lduw_le_p(s->boot[0] + (addr - s->base));
11592+
11593+ case 0xf000: /* Manufacturer ID */
11594+ return (s->id >> 16) & 0xff;
11595+ case 0xf001: /* Device ID */
11596+ return (s->id >> 8) & 0xff;
11597+ /* TODO: get the following values from a real chip! */
11598+ case 0xf002: /* Version ID */
11599+ return (s->id >> 0) & 0xff;
11600+ case 0xf003: /* Data Buffer size */
11601+ return 1 << PAGE_SHIFT;
11602+ case 0xf004: /* Boot Buffer size */
11603+ return 0x200;
11604+ case 0xf005: /* Amount of buffers */
11605+ return 1 | (2 << 8);
11606+ case 0xf006: /* Technology */
11607+ return 0;
11608+
11609+ case 0xf100 ... 0xf107: /* Start addresses */
11610+ return s->addr[offset - 0xf100];
11611+
11612+ case 0xf200: /* Start buffer */
11613+ return (s->bufaddr << 8) | ((s->count - 1) & (1 << (PAGE_SHIFT - 10)));
11614+
11615+ case 0xf220: /* Command */
11616+ return s->command;
11617+ case 0xf221: /* System Configuration 1 */
11618+ return s->config[0] & 0xffe0;
11619+ case 0xf222: /* System Configuration 2 */
11620+ return s->config[1];
11621+
11622+ case 0xf240: /* Controller Status */
11623+ return s->status;
11624+ case 0xf241: /* Interrupt */
11625+ return s->intstatus;
11626+ case 0xf24c: /* Unlock Start Block Address */
11627+ return s->unladdr[0];
11628+ case 0xf24d: /* Unlock End Block Address */
11629+ return s->unladdr[1];
11630+ case 0xf24e: /* Write Protection Status */
11631+ return s->wpstatus;
11632+
11633+ case 0xff00: /* ECC Status */
11634+ return 0x00;
11635+ case 0xff01: /* ECC Result of main area data */
11636+ case 0xff02: /* ECC Result of spare area data */
11637+ case 0xff03: /* ECC Result of main area data */
11638+ case 0xff04: /* ECC Result of spare area data */
11639+ cpu_abort(cpu_single_env, "%s: imeplement ECC\n", __FUNCTION__);
11640+ return 0x0000;
11641+ }
11642+
11643+ fprintf(stderr, "%s: unknown OneNAND register %x\n",
11644+ __FUNCTION__, offset);
11645+ return 0;
11646+}
11647+
11648+static void onenand_write(void *opaque, target_phys_addr_t addr,
11649+ uint32_t value)
11650+{
11651+ struct onenand_s *s = (struct onenand_s *) opaque;
11652+ int offset = (addr - s->base) >> s->shift;
11653+ int sec;
11654+
11655+ switch (offset) {
11656+ case 0x0000 ... 0x01ff:
11657+ case 0x8000 ... 0x800f:
11658+ if (s->cycle) {
11659+ s->cycle = 0;
11660+
11661+ if (value == 0x0000) {
11662+ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
11663+ onenand_load_main(s, sec,
11664+ 1 << (PAGE_SHIFT - 9), s->data[0][0]);
11665+ s->addr[ONEN_BUF_PAGE] += 4;
11666+ s->addr[ONEN_BUF_PAGE] &= 0xff;
11667+ }
11668+ break;
11669+ }
11670+
11671+ switch (value) {
11672+ case 0x00f0: /* Reset OneNAND */
11673+ onenand_reset(s, 0);
11674+ break;
11675+
11676+ case 0x00e0: /* Load Data into Buffer */
11677+ s->cycle = 1;
11678+ break;
11679+
11680+ case 0x0090: /* Read Identification Data */
11681+ memset(s->boot[0], 0, 3 << s->shift);
11682+ s->boot[0][0 << s->shift] = (s->id >> 16) & 0xff;
11683+ s->boot[0][1 << s->shift] = (s->id >> 8) & 0xff;
11684+ s->boot[0][2 << s->shift] = s->wpstatus & 0xff;
11685+ break;
11686+
11687+ default:
11688+ fprintf(stderr, "%s: unknown OneNAND boot command %x\n",
11689+ __FUNCTION__, value);
11690+ }
11691+ break;
11692+
11693+ case 0xf100 ... 0xf107: /* Start addresses */
11694+ s->addr[offset - 0xf100] = value;
11695+ break;
11696+
11697+ case 0xf200: /* Start buffer */
11698+ s->bufaddr = (value >> 8) & 0xf;
11699+ if (PAGE_SHIFT == 11)
11700+ s->count = (value & 3) ?: 4;
11701+ else if (PAGE_SHIFT == 10)
11702+ s->count = (value & 1) ?: 2;
11703+ break;
11704+
11705+ case 0xf220: /* Command */
11706+ if (s->intstatus & (1 << 15))
11707+ break;
11708+ s->command = value;
11709+ onenand_command(s, s->command);
11710+ break;
11711+ case 0xf221: /* System Configuration 1 */
11712+ s->config[0] = value;
11713+ onenand_intr_update(s);
11714+ qemu_set_irq(s->rdy, (s->config[0] >> 7) & 1);
11715+ break;
11716+ case 0xf222: /* System Configuration 2 */
11717+ s->config[1] = value;
11718+ break;
11719+
11720+ case 0xf241: /* Interrupt */
11721+ s->intstatus &= value;
11722+ if ((1 << 15) & ~s->intstatus)
11723+ s->status &= ~(ONEN_ERR_CMD | ONEN_ERR_ERASE |
11724+ ONEN_ERR_PROG | ONEN_ERR_LOAD);
11725+ onenand_intr_update(s);
11726+ break;
11727+ case 0xf24c: /* Unlock Start Block Address */
11728+ s->unladdr[0] = value & (s->blocks - 1);
11729+ /* For some reason we have to set the end address to by default
11730+ * be same as start because the software forgets to write anything
11731+ * in there. */
11732+ s->unladdr[1] = value & (s->blocks - 1);
11733+ break;
11734+ case 0xf24d: /* Unlock End Block Address */
11735+ s->unladdr[1] = value & (s->blocks - 1);
11736+ break;
11737+
11738+ default:
11739+ fprintf(stderr, "%s: unknown OneNAND register %x\n",
11740+ __FUNCTION__, offset);
11741+ }
11742+}
11743+
11744+static CPUReadMemoryFunc *onenand_readfn[] = {
11745+ onenand_read, /* TODO */
11746+ onenand_read,
11747+ onenand_read,
11748+};
11749+
11750+static CPUWriteMemoryFunc *onenand_writefn[] = {
11751+ onenand_write, /* TODO */
11752+ onenand_write,
11753+ onenand_write,
11754+};
11755+
11756+void *onenand_init(uint32_t id, int regshift, qemu_irq irq)
11757+{
11758+ struct onenand_s *s = (struct onenand_s *) qemu_mallocz(sizeof(*s));
11759+ int bdrv_index = drive_get_index(IF_MTD, 0, 0);
11760+ uint32_t size = 1 << (24 + ((id >> 12) & 7));
11761+ void *ram;
11762+
11763+ s->shift = regshift;
11764+ s->intr = irq;
11765+ s->rdy = 0;
11766+ s->id = id;
11767+ s->blocks = size >> BLOCK_SHIFT;
11768+ s->secs = size >> 9;
11769+ s->blockwp = qemu_malloc(s->blocks);
11770+ s->density_mask = (id & (1 << 11)) ? (1 << (6 + ((id >> 12) & 7))) : 0;
11771+ s->iomemtype = cpu_register_io_memory(0, onenand_readfn,
11772+ onenand_writefn, s);
11773+ if (bdrv_index == -1)
11774+ s->image = memset(qemu_malloc(size + (size >> 5)),
11775+ 0xff, size + (size >> 5));
11776+ else
11777+ s->bdrv = drives_table[bdrv_index].bdrv;
11778+ s->otp = memset(qemu_malloc((64 + 2) << PAGE_SHIFT),
11779+ 0xff, (64 + 2) << PAGE_SHIFT);
11780+ s->ram = qemu_ram_alloc(0xc000 << s->shift);
11781+ ram = phys_ram_base + s->ram;
11782+ s->boot[0] = ram + (0x0000 << s->shift);
11783+ s->boot[1] = ram + (0x8000 << s->shift);
11784+ s->data[0][0] = ram + ((0x0200 + (0 << (PAGE_SHIFT - 1))) << s->shift);
11785+ s->data[0][1] = ram + ((0x8010 + (0 << (PAGE_SHIFT - 6))) << s->shift);
11786+ s->data[1][0] = ram + ((0x0200 + (1 << (PAGE_SHIFT - 1))) << s->shift);
11787+ s->data[1][1] = ram + ((0x8010 + (1 << (PAGE_SHIFT - 6))) << s->shift);
11788+
11789+ onenand_reset(s, 1);
11790+
11791+ return s;
11792+}
11793diff --git a/hw/palm.c b/hw/palm.c
11794index 9400ea7..8b767e2 100644
11795--- a/hw/palm.c
11796+++ b/hw/palm.c
11797@@ -25,6 +25,7 @@
11798 #include "omap.h"
11799 #include "boards.h"
11800 #include "arm-misc.h"
11801+#include "devices.h"
11802
11803 static uint32_t static_readb(void *opaque, target_phys_addr_t offset)
11804 {
11805@@ -32,12 +33,14 @@ static uint32_t static_readb(void *opaque, target_phys_addr_t offset)
11806 return *val >> ((offset & 3) << 3);
11807 }
11808
11809-static uint32_t static_readh(void *opaque, target_phys_addr_t offset) {
11810+static uint32_t static_readh(void *opaque, target_phys_addr_t offset)
11811+{
11812 uint32_t *val = (uint32_t *) opaque;
11813 return *val >> ((offset & 1) << 3);
11814 }
11815
11816-static uint32_t static_readw(void *opaque, target_phys_addr_t offset) {
11817+static uint32_t static_readw(void *opaque, target_phys_addr_t offset)
11818+{
11819 uint32_t *val = (uint32_t *) opaque;
11820 return *val >> ((offset & 0) << 3);
11821 }
11822@@ -183,6 +186,12 @@ static void palmte_gpio_setup(struct omap_mpu_state_s *cpu)
11823 qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[11]);
11824 }
11825
11826+static struct arm_boot_info palmte_binfo = {
11827+ .loader_start = OMAP_EMIFF_BASE,
11828+ .ram_size = 0x02000000,
11829+ .board_id = 0x331,
11830+};
11831+
11832 static void palmte_init(int ram_size, int vga_ram_size,
11833 const char *boot_device, DisplayState *ds,
11834 const char *kernel_filename, const char *kernel_cmdline,
11835@@ -190,7 +199,7 @@ static void palmte_init(int ram_size, int vga_ram_size,
11836 {
11837 struct omap_mpu_state_s *cpu;
11838 int flash_size = 0x00800000;
11839- int sdram_size = 0x02000000;
11840+ int sdram_size = palmte_binfo.ram_size;
11841 int io;
11842 static uint32_t cs0val = 0xffffffff;
11843 static uint32_t cs1val = 0x0000e1a0;
11844@@ -250,10 +259,12 @@ static void palmte_init(int ram_size, int vga_ram_size,
11845 /* Load the kernel. */
11846 if (kernel_filename) {
11847 /* Start at bootloader. */
11848- cpu->env->regs[15] = OMAP_EMIFF_BASE;
11849+ cpu->env->regs[15] = palmte_binfo.loader_start;
11850
11851- arm_load_kernel(cpu->env, sdram_size, kernel_filename, kernel_cmdline,
11852- initrd_filename, 0x331, OMAP_EMIFF_BASE);
11853+ palmte_binfo.kernel_filename = kernel_filename;
11854+ palmte_binfo.kernel_cmdline = kernel_cmdline;
11855+ palmte_binfo.initrd_filename = initrd_filename;
11856+ arm_load_kernel(cpu->env, &palmte_binfo);
11857 }
11858
11859 dpy_resize(ds, 320, 320);
11860diff --git a/hw/realview.c b/hw/realview.c
11861index 29579d8..acf3b9e 100644
11862--- a/hw/realview.c
11863+++ b/hw/realview.c
11864@@ -18,6 +18,11 @@
11865
11866 /* Board init. */
11867
11868+static struct arm_boot_info realview_binfo = {
11869+ .loader_start = 0x0,
11870+ .board_id = 0x33b,
11871+};
11872+
11873 static void realview_init(int ram_size, int vga_ram_size,
11874 const char *boot_device, DisplayState *ds,
11875 const char *kernel_filename, const char *kernel_cmdline,
11876@@ -177,8 +182,12 @@ static void realview_init(int ram_size, int vga_ram_size,
11877 /* 0x68000000 PCI mem 1. */
11878 /* 0x6c000000 PCI mem 2. */
11879
11880- arm_load_kernel(first_cpu, ram_size, kernel_filename, kernel_cmdline,
11881- initrd_filename, 0x33b, 0x0);
11882+ realview_binfo.ram_size = ram_size;
11883+ realview_binfo.kernel_filename = kernel_filename;
11884+ realview_binfo.kernel_cmdline = kernel_cmdline;
11885+ realview_binfo.initrd_filename = initrd_filename;
11886+ realview_binfo.nb_cpus = ncpu;
11887+ arm_load_kernel(first_cpu, &realview_binfo);
11888
11889 /* ??? Hack to map an additional page of ram for the secondary CPU
11890 startup code. I guess this works on real hardware because the
11891diff --git a/hw/sd.c b/hw/sd.c
11892index 1f71d85..de7dd89 100644
11893--- a/hw/sd.c
11894+++ b/hw/sd.c
11895@@ -37,7 +37,7 @@
11896
11897 #ifdef DEBUG_SD
11898 #define DPRINTF(fmt, args...) \
11899-do { printf("SD: " fmt , ##args); } while (0)
11900+do { fprintf(stderr, "SD: " fmt , ##args); } while (0)
11901 #else
11902 #define DPRINTF(fmt, args...) do {} while(0)
11903 #endif
11904@@ -99,6 +99,8 @@ struct SDState {
11905 qemu_irq inserted_cb;
11906 BlockDriverState *bdrv;
11907 uint8_t *buf;
11908+
11909+ int enable;
11910 };
11911
11912 static void sd_set_status(SDState *sd)
11913@@ -530,7 +532,7 @@ static void sd_lock_command(SDState *sd)
11914 sd->card_status &= ~CARD_IS_LOCKED;
11915 sd->pwd_len = 0;
11916 /* Erasing the entire card here! */
11917- printf("SD: Card force-erased by CMD42\n");
11918+ fprintf(stderr, "SD: Card force-erased by CMD42\n");
11919 return;
11920 }
11921
11922@@ -1076,7 +1078,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
11923 return sd_r1;
11924
11925 case 56: /* CMD56: GEN_CMD */
11926- printf("SD: GEN_CMD 0x%08x\n", req.arg);
11927+ fprintf(stderr, "SD: GEN_CMD 0x%08x\n", req.arg);
11928
11929 switch (sd->state) {
11930 case sd_transfer_state:
11931@@ -1096,18 +1098,18 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
11932 bad_cmd:
11933 sd->card_status |= ILLEGAL_COMMAND;
11934
11935- printf("SD: Unknown CMD%i\n", req.cmd);
11936+ fprintf(stderr, "SD: Unknown CMD%i\n", req.cmd);
11937 return sd_r0;
11938
11939 unimplemented_cmd:
11940 /* Commands that are recognised but not yet implemented in SPI mode. */
11941 sd->card_status |= ILLEGAL_COMMAND;
11942- printf ("SD: CMD%i not implemented in SPI mode\n", req.cmd);
11943+ fprintf(stderr, "SD: CMD%i not implemented in SPI mode\n", req.cmd);
11944 return sd_r0;
11945 }
11946
11947 sd->card_status |= ILLEGAL_COMMAND;
11948- printf("SD: CMD%i in a wrong state\n", req.cmd);
11949+ fprintf(stderr, "SD: CMD%i in a wrong state\n", req.cmd);
11950 return sd_r0;
11951 }
11952
11953@@ -1217,7 +1219,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
11954 return sd_normal_command(sd, req);
11955 }
11956
11957- printf("SD: ACMD%i in a wrong state\n", req.cmd);
11958+ fprintf(stderr, "SD: ACMD%i in a wrong state\n", req.cmd);
11959 return sd_r0;
11960 }
11961
11962@@ -1227,7 +1229,7 @@ int sd_do_command(SDState *sd, struct sd_request_s *req,
11963 sd_rsp_type_t rtype;
11964 int rsplen;
11965
11966- if (!bdrv_is_inserted(sd->bdrv)) {
11967+ if (!bdrv_is_inserted(sd->bdrv) || !sd->enable) {
11968 return 0;
11969 }
11970
11971@@ -1247,7 +1249,7 @@ int sd_do_command(SDState *sd, struct sd_request_s *req,
11972 sd_cmd_class[req->cmd] == 7 ||
11973 req->cmd == 16 || req->cmd == 55))) {
11974 sd->card_status |= ILLEGAL_COMMAND;
11975- printf("SD: Card is locked\n");
11976+ fprintf(stderr, "SD: Card is locked\n");
11977 return 0;
11978 }
11979
11980@@ -1321,7 +1323,7 @@ static void sd_blk_read(SDState *sd, uint32_t addr, uint32_t len)
11981 uint32_t end = addr + len;
11982
11983 if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) == -1) {
11984- printf("sd_blk_read: read error on host side\n");
11985+ fprintf(stderr, "sd_blk_read: read error on host side\n");
11986 return;
11987 }
11988
11989@@ -1329,7 +1331,7 @@ static void sd_blk_read(SDState *sd, uint32_t addr, uint32_t len)
11990 memcpy(sd->data, sd->buf + (addr & 511), 512 - (addr & 511));
11991
11992 if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) == -1) {
11993- printf("sd_blk_read: read error on host side\n");
11994+ fprintf(stderr, "sd_blk_read: read error on host side\n");
11995 return;
11996 }
11997 memcpy(sd->data + 512 - (addr & 511), sd->buf, end & 511);
11998@@ -1343,28 +1345,28 @@ static void sd_blk_write(SDState *sd, uint32_t addr, uint32_t len)
11999
12000 if ((addr & 511) || len < 512)
12001 if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) == -1) {
12002- printf("sd_blk_write: read error on host side\n");
12003+ fprintf(stderr, "sd_blk_write: read error on host side\n");
12004 return;
12005 }
12006
12007 if (end > (addr & ~511) + 512) {
12008 memcpy(sd->buf + (addr & 511), sd->data, 512 - (addr & 511));
12009 if (bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) == -1) {
12010- printf("sd_blk_write: write error on host side\n");
12011+ fprintf(stderr, "sd_blk_write: write error on host side\n");
12012 return;
12013 }
12014
12015 if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) == -1) {
12016- printf("sd_blk_write: read error on host side\n");
12017+ fprintf(stderr, "sd_blk_write: read error on host side\n");
12018 return;
12019 }
12020 memcpy(sd->buf, sd->data + 512 - (addr & 511), end & 511);
12021 if (bdrv_write(sd->bdrv, end >> 9, sd->buf, 1) == -1)
12022- printf("sd_blk_write: write error on host side\n");
12023+ fprintf(stderr, "sd_blk_write: write error on host side\n");
12024 } else {
12025 memcpy(sd->buf + (addr & 511), sd->data, len);
12026 if (!sd->bdrv || bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) == -1)
12027- printf("sd_blk_write: write error on host side\n");
12028+ fprintf(stderr, "sd_blk_write: write error on host side\n");
12029 }
12030 }
12031
12032@@ -1377,11 +1379,11 @@ void sd_write_data(SDState *sd, uint8_t value)
12033 {
12034 int i;
12035
12036- if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv))
12037+ if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable)
12038 return;
12039
12040 if (sd->state != sd_receivingdata_state) {
12041- printf("sd_write_data: not in Receiving-Data state\n");
12042+ fprintf(stderr, "sd_write_data: not in Receiving-Data state\n");
12043 return;
12044 }
12045
12046@@ -1489,7 +1491,7 @@ void sd_write_data(SDState *sd, uint8_t value)
12047 break;
12048
12049 default:
12050- printf("sd_write_data: unknown command\n");
12051+ fprintf(stderr, "sd_write_data: unknown command\n");
12052 break;
12053 }
12054 }
12055@@ -1499,11 +1501,11 @@ uint8_t sd_read_data(SDState *sd)
12056 /* TODO: Append CRCs */
12057 uint8_t ret;
12058
12059- if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv))
12060+ if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable)
12061 return 0x00;
12062
12063 if (sd->state != sd_sendingdata_state) {
12064- printf("sd_read_data: not in Sending-Data state\n");
12065+ fprintf(stderr, "sd_read_data: not in Sending-Data state\n");
12066 return 0x00;
12067 }
12068
12069@@ -1603,7 +1605,7 @@ uint8_t sd_read_data(SDState *sd)
12070 break;
12071
12072 default:
12073- printf("sd_read_data: unknown command\n");
12074+ fprintf(stderr, "sd_read_data: unknown command\n");
12075 return 0x00;
12076 }
12077
12078@@ -1614,3 +1616,8 @@ int sd_data_ready(SDState *sd)
12079 {
12080 return sd->state == sd_sendingdata_state;
12081 }
12082+
12083+void sd_enable(SDState *sd, int enable)
12084+{
12085+ sd->enable = enable;
12086+}
12087diff --git a/hw/sd.h b/hw/sd.h
12088index 85f110f..cb7bc9c 100644
12089--- a/hw/sd.h
12090+++ b/hw/sd.h
12091@@ -74,6 +74,7 @@ void sd_write_data(SDState *sd, uint8_t value);
12092 uint8_t sd_read_data(SDState *sd);
12093 void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert);
12094 int sd_data_ready(SDState *sd);
12095+void sd_enable(SDState *sd, int enable);
12096
12097 /* ssi-sd.c */
12098 int ssi_sd_xfer(void *opaque, int val);
12099diff --git a/hw/spitz.c b/hw/spitz.c
12100index 159c633..b059f9a 100644
12101--- a/hw/spitz.c
12102+++ b/hw/spitz.c
12103@@ -1180,12 +1180,17 @@ static void sl_bootparam_write(uint32_t ptr)
12104 /* Board init. */
12105 enum spitz_model_e { spitz, akita, borzoi, terrier };
12106
12107+static struct arm_boot_info spitz_binfo = {
12108+ .loader_start = PXA2XX_SDRAM_BASE,
12109+ .ram_size = 0x04000000,
12110+};
12111+
12112 static void spitz_common_init(int ram_size, int vga_ram_size,
12113 DisplayState *ds, const char *kernel_filename,
12114 const char *kernel_cmdline, const char *initrd_filename,
12115 const char *cpu_model, enum spitz_model_e model, int arm_id)
12116 {
12117- uint32_t spitz_ram = 0x04000000;
12118+ uint32_t spitz_ram = spitz_binfo.ram_size;
12119 uint32_t spitz_rom = 0x00800000;
12120 struct pxa2xx_state_s *cpu;
12121 struct scoop_info_s *scp;
12122@@ -1230,10 +1235,13 @@ static void spitz_common_init(int ram_size, int vga_ram_size,
12123 spitz_microdrive_attach(cpu);
12124
12125 /* Setup initial (reset) machine state */
12126- cpu->env->regs[15] = PXA2XX_SDRAM_BASE;
12127+ cpu->env->regs[15] = spitz_binfo.loader_start;
12128
12129- arm_load_kernel(cpu->env, spitz_ram, kernel_filename, kernel_cmdline,
12130- initrd_filename, arm_id, PXA2XX_SDRAM_BASE);
12131+ spitz_binfo.kernel_filename = kernel_filename;
12132+ spitz_binfo.kernel_cmdline = kernel_cmdline;
12133+ spitz_binfo.initrd_filename = initrd_filename;
12134+ spitz_binfo.board_id = arm_id;
12135+ arm_load_kernel(cpu->env, &spitz_binfo);
12136 sl_bootparam_write(SL_PXA_PARAM_BASE - PXA2XX_SDRAM_BASE);
12137 }
12138
12139diff --git a/hw/tmp105.c b/hw/tmp105.c
12140new file mode 100644
12141index 0000000..d9a3900
12142--- /dev/null
12143+++ b/hw/tmp105.c
12144@@ -0,0 +1,249 @@
12145+/*
12146+ * Texas Instruments TMP105 temperature sensor.
12147+ *
12148+ * Copyright (C) 2008 Nokia Corporation
12149+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
12150+ *
12151+ * This program is free software; you can redistribute it and/or
12152+ * modify it under the terms of the GNU General Public License as
12153+ * published by the Free Software Foundation; either version 2 of
12154+ * the License, or (at your option) any later version.
12155+ *
12156+ * This program is distributed in the hope that it will be useful,
12157+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12158+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12159+ * GNU General Public License for more details.
12160+ *
12161+ * You should have received a copy of the GNU General Public License
12162+ * along with this program; if not, write to the Free Software
12163+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
12164+ * MA 02111-1307 USA
12165+ */
12166+
12167+#include "hw.h"
12168+#include "i2c.h"
12169+
12170+struct tmp105_s {
12171+ i2c_slave i2c;
12172+ int len;
12173+ uint8_t buf[2];
12174+ qemu_irq pin;
12175+
12176+ uint8_t pointer;
12177+ uint8_t config;
12178+ int16_t temperature;
12179+ int16_t limit[2];
12180+ int faults;
12181+ int alarm;
12182+};
12183+
12184+static void tmp105_interrupt_update(struct tmp105_s *s)
12185+{
12186+ qemu_set_irq(s->pin, s->alarm ^ ((~s->config >> 2) & 1)); /* POL */
12187+}
12188+
12189+static void tmp105_alarm_update(struct tmp105_s *s)
12190+{
12191+ if ((s->config >> 0) & 1) { /* SD */
12192+ if ((s->config >> 7) & 1) /* OS */
12193+ s->config &= ~(1 << 7); /* OS */
12194+ else
12195+ return;
12196+ }
12197+
12198+ if ((s->config >> 1) & 1) { /* TM */
12199+ if (s->temperature >= s->limit[1])
12200+ s->alarm = 1;
12201+ else if (s->temperature < s->limit[0])
12202+ s->alarm = 1;
12203+ } else {
12204+ if (s->temperature >= s->limit[1])
12205+ s->alarm = 1;
12206+ else if (s->temperature < s->limit[0])
12207+ s->alarm = 0;
12208+ }
12209+
12210+ tmp105_interrupt_update(s);
12211+}
12212+
12213+/* Units are 0.001 centigrades relative to 0 C. */
12214+void tmp105_set(i2c_slave *i2c, int temp)
12215+{
12216+ struct tmp105_s *s = (struct tmp105_s *) i2c;
12217+
12218+ if (temp >= 128000 || temp < -128000) {
12219+ fprintf(stderr, "%s: values is out of range (%i.%03i C)\n",
12220+ __FUNCTION__, temp / 1000, temp % 1000);
12221+ exit(-1);
12222+ }
12223+
12224+ s->temperature = ((int16_t) (temp * 0x800 / 128000)) << 4;
12225+
12226+ tmp105_alarm_update(s);
12227+}
12228+
12229+static const int tmp105_faultq[4] = { 1, 2, 4, 6 };
12230+
12231+static void tmp105_read(struct tmp105_s *s)
12232+{
12233+ s->len = 0;
12234+
12235+ if ((s->config >> 1) & 1) { /* TM */
12236+ s->alarm = 0;
12237+ tmp105_interrupt_update(s);
12238+ }
12239+
12240+ switch (s->pointer & 3) {
12241+ case 0: /* Temperature */
12242+ s->buf[s->len ++] = (((uint16_t) s->temperature) >> 8);
12243+ s->buf[s->len ++] = (((uint16_t) s->temperature) >> 0) &
12244+ (0xf0 << ((~s->config >> 5) & 3)); /* R */
12245+ break;
12246+
12247+ case 1: /* Configuration */
12248+ s->buf[s->len ++] = s->config;
12249+ break;
12250+
12251+ case 2: /* T_LOW */
12252+ s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 8;
12253+ s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 0;
12254+ break;
12255+
12256+ case 3: /* T_HIGH */
12257+ s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 8;
12258+ s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 0;
12259+ break;
12260+ }
12261+}
12262+
12263+static void tmp105_write(struct tmp105_s *s)
12264+{
12265+ switch (s->pointer & 3) {
12266+ case 0: /* Temperature */
12267+ break;
12268+
12269+ case 1: /* Configuration */
12270+ if (s->buf[0] & ~s->config & (1 << 0)) /* SD */
12271+ printf("%s: TMP105 shutdown\n", __FUNCTION__);
12272+ s->config = s->buf[0];
12273+ s->faults = tmp105_faultq[(s->config >> 3) & 3]; /* F */
12274+ tmp105_alarm_update(s);
12275+ break;
12276+
12277+ case 2: /* T_LOW */
12278+ case 3: /* T_HIGH */
12279+ if (s->len >= 3)
12280+ s->limit[s->pointer & 1] = (int16_t)
12281+ ((((uint16_t) s->buf[0]) << 8) | s->buf[1]);
12282+ tmp105_alarm_update(s);
12283+ break;
12284+ }
12285+}
12286+
12287+static int tmp105_rx(i2c_slave *i2c)
12288+{
12289+ struct tmp105_s *s = (struct tmp105_s *) i2c;
12290+
12291+ if (s->len < 2)
12292+ return s->buf[s->len ++];
12293+ else
12294+ return 0xff;
12295+}
12296+
12297+static int tmp105_tx(i2c_slave *i2c, uint8_t data)
12298+{
12299+ struct tmp105_s *s = (struct tmp105_s *) i2c;
12300+
12301+ if (!s->len ++)
12302+ s->pointer = data;
12303+ else {
12304+ if (s->len <= 2)
12305+ s->buf[s->len - 1] = data;
12306+ tmp105_write(s);
12307+ }
12308+
12309+ return 0;
12310+}
12311+
12312+static void tmp105_event(i2c_slave *i2c, enum i2c_event event)
12313+{
12314+ struct tmp105_s *s = (struct tmp105_s *) i2c;
12315+
12316+ if (event == I2C_START_RECV)
12317+ tmp105_read(s);
12318+
12319+ s->len = 0;
12320+}
12321+
12322+static void tmp105_save(QEMUFile *f, void *opaque)
12323+{
12324+ struct tmp105_s *s = (struct tmp105_s *) opaque;
12325+
12326+ qemu_put_byte(f, s->len);
12327+ qemu_put_8s(f, &s->buf[0]);
12328+ qemu_put_8s(f, &s->buf[1]);
12329+
12330+ qemu_put_8s(f, &s->pointer);
12331+ qemu_put_8s(f, &s->config);
12332+ qemu_put_be16s(f, &s->temperature);
12333+ qemu_put_be16s(f, &s->limit[0]);
12334+ qemu_put_be16s(f, &s->limit[1]);
12335+ qemu_put_byte(f, s->alarm);
12336+ s->faults = tmp105_faultq[(s->config >> 3) & 3]; /* F */
12337+
12338+ i2c_slave_save(f, &s->i2c);
12339+}
12340+
12341+static int tmp105_load(QEMUFile *f, void *opaque, int version_id)
12342+{
12343+ struct tmp105_s *s = (struct tmp105_s *) opaque;
12344+
12345+ s->len = qemu_get_byte(f);
12346+ qemu_get_8s(f, &s->buf[0]);
12347+ qemu_get_8s(f, &s->buf[1]);
12348+
12349+ qemu_get_8s(f, &s->pointer);
12350+ qemu_get_8s(f, &s->config);
12351+ qemu_get_be16s(f, &s->temperature);
12352+ qemu_get_be16s(f, &s->limit[0]);
12353+ qemu_get_be16s(f, &s->limit[1]);
12354+ s->alarm = qemu_get_byte(f);
12355+
12356+ tmp105_interrupt_update(s);
12357+
12358+ i2c_slave_load(f, &s->i2c);
12359+ return 0;
12360+}
12361+
12362+void tmp105_reset(i2c_slave *i2c)
12363+{
12364+ struct tmp105_s *s = (struct tmp105_s *) i2c;
12365+
12366+ s->temperature = 0;
12367+ s->pointer = 0;
12368+ s->config = 0;
12369+ s->faults = tmp105_faultq[(s->config >> 3) & 3];
12370+ s->alarm = 0;
12371+
12372+ tmp105_interrupt_update(s);
12373+}
12374+
12375+static int tmp105_iid = 0;
12376+
12377+struct i2c_slave *tmp105_init(i2c_bus *bus, qemu_irq alarm)
12378+{
12379+ struct tmp105_s *s = (struct tmp105_s *)
12380+ i2c_slave_init(bus, 0, sizeof(struct tmp105_s));
12381+
12382+ s->i2c.event = tmp105_event;
12383+ s->i2c.recv = tmp105_rx;
12384+ s->i2c.send = tmp105_tx;
12385+ s->pin = alarm;
12386+
12387+ tmp105_reset(&s->i2c);
12388+
12389+ register_savevm("TMP105", tmp105_iid ++, 0,
12390+ tmp105_save, tmp105_load, s);
12391+
12392+ return &s->i2c;
12393+}
12394diff --git a/hw/tsc210x.c b/hw/tsc210x.c
12395index 96956a4..1654b8b 100644
12396--- a/hw/tsc210x.c
12397+++ b/hw/tsc210x.c
12398@@ -2,6 +2,7 @@
12399 * TI TSC2102 (touchscreen/sensors/audio controller) emulator.
12400 *
12401 * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
12402+ * Copyright (C) 2008 Nokia Corporation
12403 *
12404 * This program is free software; you can redistribute it and/or
12405 * modify it under the terms of the GNU General Public License as
12406@@ -35,12 +36,15 @@
12407
12408 struct tsc210x_state_s {
12409 qemu_irq pint;
12410+ qemu_irq kbint;
12411+ qemu_irq davint;
12412 QEMUTimer *timer;
12413 QEMUSoundCard card;
12414 struct uwire_slave_s chip;
12415 struct i2s_codec_s codec;
12416 uint8_t in_fifo[16384];
12417 uint8_t out_fifo[16384];
12418+ uint16_t model;
12419
12420 int x, y;
12421 int pressure;
12422@@ -64,7 +68,7 @@ struct tsc210x_state_s {
12423 uint16_t audio_ctrl1;
12424 uint16_t audio_ctrl2;
12425 uint16_t audio_ctrl3;
12426- uint16_t pll[2];
12427+ uint16_t pll[3];
12428 uint16_t volume;
12429 int64_t volume_change;
12430 int softstep;
12431@@ -78,6 +82,17 @@ struct tsc210x_state_s {
12432 int i2s_rx_rate;
12433 int i2s_tx_rate;
12434 AudioState *audio;
12435+
12436+ int tr[8];
12437+
12438+ struct {
12439+ uint16_t down;
12440+ uint16_t mask;
12441+ int scan;
12442+ int debounce;
12443+ int mode;
12444+ int intr;
12445+ } kb;
12446 };
12447
12448 static const int resolution[4] = { 12, 8, 10, 12 };
12449@@ -118,17 +133,10 @@ static const uint16_t mode_regs[16] = {
12450 0x0000, /* Y+, X- drivers */
12451 };
12452
12453-/*
12454- * Convert screen coordinates to arbitrary values that the
12455- * touchscreen in my Palm Tungsten E device returns.
12456- * This shouldn't really matter (because the guest system
12457- * should calibrate the touchscreen anyway), but let's
12458- * imitate some real hardware.
12459- */
12460-#define X_TRANSFORM(value) \
12461- ((3850 - ((int) (value) * (3850 - 250) / 32768)) << 4)
12462-#define Y_TRANSFORM(value) \
12463- ((150 + ((int) (value) * (3037 - 150) / 32768)) << 4)
12464+#define X_TRANSFORM(s) \
12465+ ((s->y * s->tr[0] - s->x * s->tr[1]) / s->tr[2] + s->tr[3])
12466+#define Y_TRANSFORM(s) \
12467+ ((s->y * s->tr[4] - s->x * s->tr[5]) / s->tr[6] + s->tr[7])
12468 #define Z1_TRANSFORM(s) \
12469 ((400 - ((s)->x >> 7) + ((s)->pressure << 10)) << 4)
12470 #define Z2_TRANSFORM(s) \
12471@@ -161,6 +169,7 @@ static void tsc210x_reset(struct tsc210x_state_s *s)
12472 s->audio_ctrl3 = 0x0000;
12473 s->pll[0] = 0x1004;
12474 s->pll[1] = 0x0000;
12475+ s->pll[2] = 0x1fff;
12476 s->volume = 0xffff;
12477 s->dac_power = 0x8540;
12478 s->softstep = 1;
12479@@ -190,7 +199,15 @@ static void tsc210x_reset(struct tsc210x_state_s *s)
12480 s->i2s_tx_rate = 0;
12481 s->i2s_rx_rate = 0;
12482
12483+ s->kb.scan = 1;
12484+ s->kb.debounce = 0;
12485+ s->kb.mask = 0x0000;
12486+ s->kb.mode = 3;
12487+ s->kb.intr = 0;
12488+
12489 qemu_set_irq(s->pint, !s->irq);
12490+ qemu_set_irq(s->davint, !s->dav);
12491+ qemu_irq_raise(s->kbint);
12492 }
12493
12494 struct tsc210x_rate_info_s {
12495@@ -344,13 +361,13 @@ static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg)
12496 switch (reg) {
12497 case 0x00: /* X */
12498 s->dav &= 0xfbff;
12499- return TSC_CUT_RESOLUTION(X_TRANSFORM(s->x), s->precision) +
12500+ return TSC_CUT_RESOLUTION(X_TRANSFORM(s), s->precision) +
12501 (s->noise & 3);
12502
12503 case 0x01: /* Y */
12504 s->noise ++;
12505 s->dav &= 0xfdff;
12506- return TSC_CUT_RESOLUTION(Y_TRANSFORM(s->y), s->precision) ^
12507+ return TSC_CUT_RESOLUTION(Y_TRANSFORM(s), s->precision) ^
12508 (s->noise & 3);
12509
12510 case 0x02: /* Z1 */
12511@@ -364,6 +381,14 @@ static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg)
12512 (s->noise & 3);
12513
12514 case 0x04: /* KPData */
12515+ if ((s->model & 0xff00) == 0x2300) {
12516+ if (s->kb.intr && (s->kb.mode & 2)) {
12517+ s->kb.intr = 0;
12518+ qemu_irq_raise(s->kbint);
12519+ }
12520+ return s->kb.down;
12521+ }
12522+
12523 return 0xffff;
12524
12525 case 0x05: /* BAT1 */
12526@@ -414,9 +439,19 @@ static uint16_t tsc2102_control_register_read(
12527 return (s->pressure << 15) | ((!s->busy) << 14) |
12528 (s->nextfunction << 10) | (s->nextprecision << 8) | s->filter;
12529
12530- case 0x01: /* Status */
12531- return (s->pin_func << 14) | ((!s->enabled) << 13) |
12532- (s->host_mode << 12) | ((!!s->dav) << 11) | s->dav;
12533+ case 0x01: /* Status / Keypad Control */
12534+ if ((s->model & 0xff00) == 0x2100)
12535+ return (s->pin_func << 14) | ((!s->enabled) << 13) |
12536+ (s->host_mode << 12) | ((!!s->dav) << 11) | s->dav;
12537+ else
12538+ return (s->kb.intr << 15) | ((s->kb.scan || !s->kb.down) << 14) |
12539+ (s->kb.debounce << 11);
12540+
12541+ case 0x02: /* DAC Control */
12542+ if ((s->model & 0xff00) == 0x2300)
12543+ return s->dac_power & 0x8000;
12544+ else
12545+ goto bad_reg;
12546
12547 case 0x03: /* Reference */
12548 return s->ref;
12549@@ -427,7 +462,18 @@ static uint16_t tsc2102_control_register_read(
12550 case 0x05: /* Configuration */
12551 return s->timing;
12552
12553+ case 0x06: /* Secondary configuration */
12554+ if ((s->model & 0xff00) == 0x2100)
12555+ goto bad_reg;
12556+ return ((!s->dav) << 15) | ((s->kb.mode & 1) << 14) | s->pll[2];
12557+
12558+ case 0x10: /* Keypad Mask */
12559+ if ((s->model & 0xff00) == 0x2100)
12560+ goto bad_reg;
12561+ return s->kb.mask;
12562+
12563 default:
12564+ bad_reg:
12565 #ifdef TSC_VERBOSE
12566 fprintf(stderr, "tsc2102_control_register_read: "
12567 "no such register: 0x%02x\n", reg);
12568@@ -556,10 +602,27 @@ static void tsc2102_control_register_write(
12569 s->filter = value & 0xff;
12570 return;
12571
12572- case 0x01: /* Status */
12573- s->pin_func = value >> 14;
12574+ case 0x01: /* Status / Keypad Control */
12575+ if ((s->model & 0xff00) == 0x2100)
12576+ s->pin_func = value >> 14;
12577+ else {
12578+ s->kb.scan = (value >> 14) & 1;
12579+ s->kb.debounce = (value >> 11) & 7;
12580+ if (s->kb.intr && s->kb.scan) {
12581+ s->kb.intr = 0;
12582+ qemu_irq_raise(s->kbint);
12583+ }
12584+ }
12585 return;
12586
12587+ case 0x02: /* DAC Control */
12588+ if ((s->model & 0xff00) == 0x2300) {
12589+ s->dac_power &= 0x7fff;
12590+ s->dac_power |= 0x8000 & value;
12591+ } else
12592+ goto bad_reg;
12593+ break;
12594+
12595 case 0x03: /* Reference */
12596 s->ref = value & 0x1f;
12597 return;
12598@@ -586,7 +649,21 @@ static void tsc2102_control_register_write(
12599 #endif
12600 return;
12601
12602+ case 0x06: /* Secondary configuration */
12603+ if ((s->model & 0xff00) == 0x2100)
12604+ goto bad_reg;
12605+ s->kb.mode = value >> 14;
12606+ s->pll[2] = value & 0x3ffff;
12607+ return;
12608+
12609+ case 0x10: /* Keypad Mask */
12610+ if ((s->model & 0xff00) == 0x2100)
12611+ goto bad_reg;
12612+ s->kb.mask = value;
12613+ return;
12614+
12615 default:
12616+ bad_reg:
12617 #ifdef TSC_VERBOSE
12618 fprintf(stderr, "tsc2102_control_register_write: "
12619 "no such register: 0x%02x\n", reg);
12620@@ -785,7 +862,7 @@ static void tsc210x_pin_update(struct tsc210x_state_s *s)
12621 return;
12622 }
12623
12624- if (!s->enabled || s->busy)
12625+ if (!s->enabled || s->busy || s->dav)
12626 return;
12627
12628 s->busy = 1;
12629@@ -805,6 +882,8 @@ static uint16_t tsc210x_read(struct tsc210x_state_s *s)
12630 switch (s->page) {
12631 case TSC_DATA_REGISTERS_PAGE:
12632 ret = tsc2102_data_register_read(s, s->offset);
12633+ if (!s->dav)
12634+ qemu_irq_raise(s->davint);
12635 break;
12636 case TSC_CONTROL_REGISTERS_PAGE:
12637 ret = tsc2102_control_register_read(s, s->offset);
12638@@ -859,6 +938,22 @@ static void tsc210x_write(struct tsc210x_state_s *s, uint16_t value)
12639 }
12640 }
12641
12642+uint32_t tsc210x_txrx(void *opaque, uint32_t value)
12643+{
12644+ struct tsc210x_state_s *s = opaque;
12645+ uint32_t ret = 0;
12646+
12647+ /* TODO: sequential reads etc - how do we make sure the host doesn't
12648+ * unintentionally read out a conversion result from a register while
12649+ * transmitting the command word of the next command? */
12650+ if (!value || (s->state && s->command))
12651+ ret = tsc210x_read(s);
12652+ if (value || (s->state && !s->command))
12653+ tsc210x_write(s, value);
12654+
12655+ return ret;
12656+}
12657+
12658 static void tsc210x_timer_tick(void *opaque)
12659 {
12660 struct tsc210x_state_s *s = opaque;
12661@@ -871,6 +966,7 @@ static void tsc210x_timer_tick(void *opaque)
12662 s->busy = 0;
12663 s->dav |= mode_regs[s->function];
12664 tsc210x_pin_update(s);
12665+ qemu_irq_lower(s->davint);
12666 }
12667
12668 static void tsc210x_touchscreen_event(void *opaque,
12669@@ -1001,6 +1097,7 @@ static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
12670
12671 s->busy = qemu_timer_pending(s->timer);
12672 qemu_set_irq(s->pint, !s->irq);
12673+ qemu_set_irq(s->davint, !s->dav);
12674
12675 return 0;
12676 }
12677@@ -1020,9 +1117,19 @@ struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio)
12678 s->precision = s->nextprecision = 0;
12679 s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s);
12680 s->pint = pint;
12681+ s->model = 0x2102;
12682 s->name = "tsc2102";
12683 s->audio = audio;
12684
12685+ s->tr[0] = 0;
12686+ s->tr[1] = 1;
12687+ s->tr[2] = 0;
12688+ s->tr[3] = 1;
12689+ s->tr[4] = 1;
12690+ s->tr[5] = 0;
12691+ s->tr[6] = 0;
12692+ s->tr[7] = 1;
12693+
12694 s->chip.opaque = s;
12695 s->chip.send = (void *) tsc210x_write;
12696 s->chip.receive = (void *) tsc210x_read;
12697@@ -1048,9 +1155,147 @@ struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio)
12698 return &s->chip;
12699 }
12700
12701+struct uwire_slave_s *tsc2301_init(qemu_irq penirq, qemu_irq kbirq,
12702+ qemu_irq dav, AudioState *audio)
12703+{
12704+ struct tsc210x_state_s *s;
12705+
12706+ s = (struct tsc210x_state_s *)
12707+ qemu_mallocz(sizeof(struct tsc210x_state_s));
12708+ memset(s, 0, sizeof(struct tsc210x_state_s));
12709+ s->x = 400;
12710+ s->y = 240;
12711+ s->pressure = 0;
12712+ s->precision = s->nextprecision = 0;
12713+ s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s);
12714+ s->pint = penirq;
12715+ s->kbint = kbirq;
12716+ s->davint = dav;
12717+ s->model = 0x2301;
12718+ s->name = "tsc2301";
12719+ s->audio = audio;
12720+
12721+ s->tr[0] = 0;
12722+ s->tr[1] = 1;
12723+ s->tr[2] = 0;
12724+ s->tr[3] = 1;
12725+ s->tr[4] = 1;
12726+ s->tr[5] = 0;
12727+ s->tr[6] = 0;
12728+ s->tr[7] = 1;
12729+
12730+ s->chip.opaque = s;
12731+ s->chip.send = (void *) tsc210x_write;
12732+ s->chip.receive = (void *) tsc210x_read;
12733+
12734+ s->codec.opaque = s;
12735+ s->codec.tx_swallow = (void *) tsc210x_i2s_swallow;
12736+ s->codec.set_rate = (void *) tsc210x_i2s_set_rate;
12737+ s->codec.in.fifo = s->in_fifo;
12738+ s->codec.out.fifo = s->out_fifo;
12739+
12740+ tsc210x_reset(s);
12741+
12742+ qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1,
12743+ "QEMU TSC2301-driven Touchscreen");
12744+
12745+ if (s->audio)
12746+ AUD_register_card(s->audio, s->name, &s->card);
12747+
12748+ qemu_register_reset((void *) tsc210x_reset, s);
12749+ register_savevm(s->name, tsc2102_iid ++, 0,
12750+ tsc210x_save, tsc210x_load, s);
12751+
12752+ return &s->chip;
12753+}
12754+
12755 struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip)
12756 {
12757 struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque;
12758
12759 return &s->codec;
12760 }
12761+
12762+/*
12763+ * Use tslib generated calibration data to generate ADC input values
12764+ * from the touchscreen. Assuming 12-bit precision was used during
12765+ * tslib calibration.
12766+ */
12767+void tsc210x_set_transform(struct uwire_slave_s *chip,
12768+ struct mouse_transform_info_s *info)
12769+{
12770+ struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque;
12771+#if 0
12772+ int64_t ltr[8];
12773+
12774+ ltr[0] = (int64_t) info->a[1] * info->y;
12775+ ltr[1] = (int64_t) info->a[4] * info->x;
12776+ ltr[2] = (int64_t) info->a[1] * info->a[3] -
12777+ (int64_t) info->a[4] * info->a[0];
12778+ ltr[3] = (int64_t) info->a[2] * info->a[4] -
12779+ (int64_t) info->a[5] * info->a[1];
12780+ ltr[4] = (int64_t) info->a[0] * info->y;
12781+ ltr[5] = (int64_t) info->a[3] * info->x;
12782+ ltr[6] = (int64_t) info->a[4] * info->a[0] -
12783+ (int64_t) info->a[1] * info->a[3];
12784+ ltr[7] = (int64_t) info->a[2] * info->a[3] -
12785+ (int64_t) info->a[5] * info->a[0];
12786+
12787+ /* Avoid integer overflow */
12788+ s->tr[0] = ltr[0] >> 11;
12789+ s->tr[1] = ltr[1] >> 11;
12790+ s->tr[2] = muldiv64(ltr[2], 1, info->a[6]);
12791+ s->tr[3] = muldiv64(ltr[3], 1 << 4, ltr[2]);
12792+ s->tr[4] = ltr[4] >> 11;
12793+ s->tr[5] = ltr[5] >> 11;
12794+ s->tr[6] = muldiv64(ltr[6], 1, info->a[6]);
12795+ s->tr[7] = muldiv64(ltr[7], 1 << 4, ltr[6]);
12796+#else
12797+
12798+ if (abs(info->a[0]) > abs(info->a[1])) {
12799+ s->tr[0] = 0;
12800+ s->tr[1] = -info->a[6] * info->x;
12801+ s->tr[2] = info->a[0];
12802+ s->tr[3] = -info->a[2] / info->a[0];
12803+ s->tr[4] = info->a[6] * info->y;
12804+ s->tr[5] = 0;
12805+ s->tr[6] = info->a[4];
12806+ s->tr[7] = -info->a[5] / info->a[4];
12807+ } else {
12808+ s->tr[0] = info->a[6] * info->y;
12809+ s->tr[1] = 0;
12810+ s->tr[2] = info->a[1];
12811+ s->tr[3] = -info->a[2] / info->a[1];
12812+ s->tr[4] = 0;
12813+ s->tr[5] = -info->a[6] * info->x;
12814+ s->tr[6] = info->a[3];
12815+ s->tr[7] = -info->a[5] / info->a[3];
12816+ }
12817+
12818+ s->tr[0] >>= 11;
12819+ s->tr[1] >>= 11;
12820+ s->tr[3] <<= 4;
12821+ s->tr[4] >>= 11;
12822+ s->tr[5] >>= 11;
12823+ s->tr[7] <<= 4;
12824+#endif
12825+}
12826+
12827+void tsc210x_key_event(struct uwire_slave_s *chip, int key, int down)
12828+{
12829+ struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque;
12830+
12831+ if (down)
12832+ s->kb.down |= 1 << key;
12833+ else
12834+ s->kb.down &= ~(1 << key);
12835+
12836+ if (down && (s->kb.down & ~s->kb.mask) && !s->kb.intr) {
12837+ s->kb.intr = 1;
12838+ qemu_irq_lower(s->kbint);
12839+ } else if (s->kb.intr && !(s->kb.down & ~s->kb.mask) &&
12840+ !(s->kb.mode & 1)) {
12841+ s->kb.intr = 0;
12842+ qemu_irq_raise(s->kbint);
12843+ }
12844+}
12845diff --git a/hw/twl92230.c b/hw/twl92230.c
12846new file mode 100644
12847index 0000000..11a5d1a
12848--- /dev/null
12849+++ b/hw/twl92230.c
12850@@ -0,0 +1,923 @@
12851+/*
12852+ * TI TWL92230C energy-management companion device for the OMAP24xx.
12853+ * Aka. Menelaus (N4200 MENELAUS1_V2.2)
12854+ *
12855+ * Copyright (C) 2008 Nokia Corporation
12856+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
12857+ *
12858+ * This program is free software; you can redistribute it and/or
12859+ * modify it under the terms of the GNU General Public License as
12860+ * published by the Free Software Foundation; either version 2 of
12861+ * the License, or (at your option) any later version.
12862+ *
12863+ * This program is distributed in the hope that it will be useful,
12864+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12865+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12866+ * GNU General Public License for more details.
12867+ *
12868+ * You should have received a copy of the GNU General Public License
12869+ * along with this program; if not, write to the Free Software
12870+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
12871+ * MA 02111-1307 USA
12872+ */
12873+
12874+#include "hw.h"
12875+#include "qemu-timer.h"
12876+#include "i2c.h"
12877+#include "sysemu.h"
12878+#include "console.h"
12879+
12880+#define VERBOSE 1
12881+
12882+struct menelaus_s {
12883+ i2c_slave i2c;
12884+ qemu_irq irq;
12885+
12886+ int firstbyte;
12887+ uint8_t reg;
12888+
12889+ uint8_t vcore[5];
12890+ uint8_t dcdc[3];
12891+ uint8_t ldo[8];
12892+ uint8_t sleep[2];
12893+ uint8_t osc;
12894+ uint8_t detect;
12895+ uint16_t mask;
12896+ uint16_t status;
12897+ uint8_t dir;
12898+ uint8_t inputs;
12899+ uint8_t outputs;
12900+ uint8_t bbsms;
12901+ uint8_t pull[4];
12902+ uint8_t mmc_ctrl[3];
12903+ uint8_t mmc_debounce;
12904+ struct {
12905+ uint8_t ctrl;
12906+ uint16_t comp;
12907+ QEMUTimer *hz;
12908+ int64_t next;
12909+ struct tm tm;
12910+ struct tm new;
12911+ struct tm alm;
12912+ time_t sec;
12913+ time_t alm_sec;
12914+ time_t next_comp;
12915+ struct tm *(*gettime)(const time_t *timep, struct tm *result);
12916+ } rtc;
12917+ qemu_irq handler[3];
12918+ qemu_irq *in;
12919+ int pwrbtn_state;
12920+ qemu_irq pwrbtn;
12921+};
12922+
12923+static inline void menelaus_update(struct menelaus_s *s)
12924+{
12925+ qemu_set_irq(s->irq, s->status & ~s->mask);
12926+}
12927+
12928+static inline void menelaus_rtc_start(struct menelaus_s *s)
12929+{
12930+ s->rtc.next =+ qemu_get_clock(rt_clock);
12931+ qemu_mod_timer(s->rtc.hz, s->rtc.next);
12932+}
12933+
12934+static inline void menelaus_rtc_stop(struct menelaus_s *s)
12935+{
12936+ qemu_del_timer(s->rtc.hz);
12937+ s->rtc.next =- qemu_get_clock(rt_clock);
12938+ if (s->rtc.next < 1)
12939+ s->rtc.next = 1;
12940+}
12941+
12942+static void menelaus_rtc_update(struct menelaus_s *s)
12943+{
12944+ s->rtc.gettime(&s->rtc.sec, &s->rtc.tm);
12945+}
12946+
12947+static void menelaus_alm_update(struct menelaus_s *s)
12948+{
12949+ if ((s->rtc.ctrl & 3) == 3)
12950+ s->rtc.alm_sec = mktime(&s->rtc.alm);
12951+}
12952+
12953+static void menelaus_rtc_hz(void *opaque)
12954+{
12955+ struct menelaus_s *s = (struct menelaus_s *) opaque;
12956+
12957+ s->rtc.sec ++;
12958+ s->rtc.next += 1000;
12959+ qemu_mod_timer(s->rtc.hz, s->rtc.next);
12960+ if ((s->rtc.ctrl >> 3) & 3) { /* EVERY */
12961+ menelaus_rtc_update(s);
12962+ if (((s->rtc.ctrl >> 3) & 3) == 1 && !s->rtc.tm.tm_sec)
12963+ s->status |= 1 << 8; /* RTCTMR */
12964+ else if (((s->rtc.ctrl >> 3) & 3) == 2 && !s->rtc.tm.tm_min)
12965+ s->status |= 1 << 8; /* RTCTMR */
12966+ else if (!s->rtc.tm.tm_hour)
12967+ s->status |= 1 << 8; /* RTCTMR */
12968+ } else
12969+ s->status |= 1 << 8; /* RTCTMR */
12970+ if ((s->rtc.ctrl >> 1) & 1) { /* RTC_AL_EN */
12971+ if (s->rtc.sec == s->rtc.alm_sec)
12972+ s->status |= 1 << 9; /* RTCALM */
12973+ /* TODO: wake-up */
12974+ }
12975+ if (s->rtc.next_comp >= s->rtc.sec) {
12976+ s->rtc.next -= muldiv64((int16_t) s->rtc.comp, 1000, 0x8000);
12977+ s->rtc.next_comp = s->rtc.sec + 3600;
12978+ }
12979+ menelaus_update(s);
12980+}
12981+
12982+void menelaus_reset(i2c_slave *i2c)
12983+{
12984+ struct menelaus_s *s = (struct menelaus_s *) i2c;
12985+ time_t ti;
12986+ s->reg = 0x00;
12987+
12988+ s->vcore[0] = 0x0c; /* XXX: X-loader needs 0x8c? check! */
12989+ s->vcore[1] = 0x05;
12990+ s->vcore[2] = 0x02;
12991+ s->vcore[3] = 0x0c;
12992+ s->vcore[4] = 0x03;
12993+ s->dcdc[0] = 0x33; /* Depends on wiring */
12994+ s->dcdc[1] = 0x03;
12995+ s->dcdc[2] = 0x00;
12996+ s->ldo[0] = 0x95;
12997+ s->ldo[1] = 0x7e;
12998+ s->ldo[2] = 0x00;
12999+ s->ldo[3] = 0x00; /* Depends on wiring */
13000+ s->ldo[4] = 0x03; /* Depends on wiring */
13001+ s->ldo[5] = 0x00;
13002+ s->ldo[6] = 0x00;
13003+ s->ldo[7] = 0x00;
13004+ s->sleep[0] = 0x00;
13005+ s->sleep[1] = 0x00;
13006+ s->osc = 0x01;
13007+ s->detect = 0x09;
13008+ s->mask = 0x0fff;
13009+ s->status = 0;
13010+ s->dir = 0x07;
13011+ s->outputs = 0x00;
13012+ s->bbsms = 0x00;
13013+ s->pull[0] = 0x00;
13014+ s->pull[1] = 0x00;
13015+ s->pull[2] = 0x00;
13016+ s->pull[3] = 0x00;
13017+ s->mmc_ctrl[0] = 0x03;
13018+ s->mmc_ctrl[1] = 0xc0;
13019+ s->mmc_ctrl[2] = 0x00;
13020+ s->mmc_debounce = 0x05;
13021+
13022+ time(&ti);
13023+ if (s->rtc.ctrl & 1)
13024+ menelaus_rtc_stop(s);
13025+ s->rtc.ctrl = 0x00;
13026+ s->rtc.comp = 0x0000;
13027+ s->rtc.next = 1000;
13028+ s->rtc.sec = ti;
13029+ s->rtc.next_comp = s->rtc.sec + 1800;
13030+ s->rtc.alm.tm_sec = 0x00;
13031+ s->rtc.alm.tm_min = 0x00;
13032+ s->rtc.alm.tm_hour = 0x00;
13033+ s->rtc.alm.tm_mday = 0x01;
13034+ s->rtc.alm.tm_mon = 0x00;
13035+ s->rtc.alm.tm_year = 2004;
13036+ menelaus_update(s);
13037+}
13038+
13039+static inline uint8_t to_bcd(int val)
13040+{
13041+ return ((val / 10) << 4) | (val % 10);
13042+}
13043+
13044+static inline int from_bcd(uint8_t val)
13045+{
13046+ return ((val >> 4) * 10) + (val & 0x0f);
13047+}
13048+
13049+static void menelaus_gpio_set(void *opaque, int line, int level)
13050+{
13051+ struct menelaus_s *s = (struct menelaus_s *) opaque;
13052+
13053+ /* No interrupt generated */
13054+ s->inputs &= ~(1 << line);
13055+ s->inputs |= level << line;
13056+}
13057+
13058+static void menelaus_pwrbtn_set(void *opaque, int line, int level)
13059+{
13060+ struct menelaus_s *s = (struct menelaus_s *) opaque;
13061+
13062+ if (!s->pwrbtn_state && level) {
13063+ s->status |= 1 << 11; /* PSHBTN */
13064+ menelaus_update(s);
13065+ }
13066+ s->pwrbtn_state = level;
13067+}
13068+
13069+#define MENELAUS_REV 0x01
13070+#define MENELAUS_VCORE_CTRL1 0x02
13071+#define MENELAUS_VCORE_CTRL2 0x03
13072+#define MENELAUS_VCORE_CTRL3 0x04
13073+#define MENELAUS_VCORE_CTRL4 0x05
13074+#define MENELAUS_VCORE_CTRL5 0x06
13075+#define MENELAUS_DCDC_CTRL1 0x07
13076+#define MENELAUS_DCDC_CTRL2 0x08
13077+#define MENELAUS_DCDC_CTRL3 0x09
13078+#define MENELAUS_LDO_CTRL1 0x0a
13079+#define MENELAUS_LDO_CTRL2 0x0b
13080+#define MENELAUS_LDO_CTRL3 0x0c
13081+#define MENELAUS_LDO_CTRL4 0x0d
13082+#define MENELAUS_LDO_CTRL5 0x0e
13083+#define MENELAUS_LDO_CTRL6 0x0f
13084+#define MENELAUS_LDO_CTRL7 0x10
13085+#define MENELAUS_LDO_CTRL8 0x11
13086+#define MENELAUS_SLEEP_CTRL1 0x12
13087+#define MENELAUS_SLEEP_CTRL2 0x13
13088+#define MENELAUS_DEVICE_OFF 0x14
13089+#define MENELAUS_OSC_CTRL 0x15
13090+#define MENELAUS_DETECT_CTRL 0x16
13091+#define MENELAUS_INT_MASK1 0x17
13092+#define MENELAUS_INT_MASK2 0x18
13093+#define MENELAUS_INT_STATUS1 0x19
13094+#define MENELAUS_INT_STATUS2 0x1a
13095+#define MENELAUS_INT_ACK1 0x1b
13096+#define MENELAUS_INT_ACK2 0x1c
13097+#define MENELAUS_GPIO_CTRL 0x1d
13098+#define MENELAUS_GPIO_IN 0x1e
13099+#define MENELAUS_GPIO_OUT 0x1f
13100+#define MENELAUS_BBSMS 0x20
13101+#define MENELAUS_RTC_CTRL 0x21
13102+#define MENELAUS_RTC_UPDATE 0x22
13103+#define MENELAUS_RTC_SEC 0x23
13104+#define MENELAUS_RTC_MIN 0x24
13105+#define MENELAUS_RTC_HR 0x25
13106+#define MENELAUS_RTC_DAY 0x26
13107+#define MENELAUS_RTC_MON 0x27
13108+#define MENELAUS_RTC_YR 0x28
13109+#define MENELAUS_RTC_WKDAY 0x29
13110+#define MENELAUS_RTC_AL_SEC 0x2a
13111+#define MENELAUS_RTC_AL_MIN 0x2b
13112+#define MENELAUS_RTC_AL_HR 0x2c
13113+#define MENELAUS_RTC_AL_DAY 0x2d
13114+#define MENELAUS_RTC_AL_MON 0x2e
13115+#define MENELAUS_RTC_AL_YR 0x2f
13116+#define MENELAUS_RTC_COMP_MSB 0x30
13117+#define MENELAUS_RTC_COMP_LSB 0x31
13118+#define MENELAUS_S1_PULL_EN 0x32
13119+#define MENELAUS_S1_PULL_DIR 0x33
13120+#define MENELAUS_S2_PULL_EN 0x34
13121+#define MENELAUS_S2_PULL_DIR 0x35
13122+#define MENELAUS_MCT_CTRL1 0x36
13123+#define MENELAUS_MCT_CTRL2 0x37
13124+#define MENELAUS_MCT_CTRL3 0x38
13125+#define MENELAUS_MCT_PIN_ST 0x39
13126+#define MENELAUS_DEBOUNCE1 0x3a
13127+
13128+static uint8_t menelaus_read(void *opaque, uint8_t addr)
13129+{
13130+ struct menelaus_s *s = (struct menelaus_s *) opaque;
13131+ int reg = 0;
13132+
13133+ switch (addr) {
13134+ case MENELAUS_REV:
13135+ return 0x22;
13136+
13137+ case MENELAUS_VCORE_CTRL5: reg ++;
13138+ case MENELAUS_VCORE_CTRL4: reg ++;
13139+ case MENELAUS_VCORE_CTRL3: reg ++;
13140+ case MENELAUS_VCORE_CTRL2: reg ++;
13141+ case MENELAUS_VCORE_CTRL1:
13142+ return s->vcore[reg];
13143+
13144+ case MENELAUS_DCDC_CTRL3: reg ++;
13145+ case MENELAUS_DCDC_CTRL2: reg ++;
13146+ case MENELAUS_DCDC_CTRL1:
13147+ return s->dcdc[reg];
13148+
13149+ case MENELAUS_LDO_CTRL8: reg ++;
13150+ case MENELAUS_LDO_CTRL7: reg ++;
13151+ case MENELAUS_LDO_CTRL6: reg ++;
13152+ case MENELAUS_LDO_CTRL5: reg ++;
13153+ case MENELAUS_LDO_CTRL4: reg ++;
13154+ case MENELAUS_LDO_CTRL3: reg ++;
13155+ case MENELAUS_LDO_CTRL2: reg ++;
13156+ case MENELAUS_LDO_CTRL1:
13157+ return s->ldo[reg];
13158+
13159+ case MENELAUS_SLEEP_CTRL2: reg ++;
13160+ case MENELAUS_SLEEP_CTRL1:
13161+ return s->sleep[reg];
13162+
13163+ case MENELAUS_DEVICE_OFF:
13164+ return 0;
13165+
13166+ case MENELAUS_OSC_CTRL:
13167+ return s->osc | (1 << 7); /* CLK32K_GOOD */
13168+
13169+ case MENELAUS_DETECT_CTRL:
13170+ return s->detect;
13171+
13172+ case MENELAUS_INT_MASK1:
13173+ return (s->mask >> 0) & 0xff;
13174+ case MENELAUS_INT_MASK2:
13175+ return (s->mask >> 8) & 0xff;
13176+
13177+ case MENELAUS_INT_STATUS1:
13178+ return (s->status >> 0) & 0xff;
13179+ case MENELAUS_INT_STATUS2:
13180+ return (s->status >> 8) & 0xff;
13181+
13182+ case MENELAUS_INT_ACK1:
13183+ case MENELAUS_INT_ACK2:
13184+ return 0;
13185+
13186+ case MENELAUS_GPIO_CTRL:
13187+ return s->dir;
13188+ case MENELAUS_GPIO_IN:
13189+ return s->inputs | (~s->dir & s->outputs);
13190+ case MENELAUS_GPIO_OUT:
13191+ return s->outputs;
13192+
13193+ case MENELAUS_BBSMS:
13194+ return s->bbsms;
13195+
13196+ case MENELAUS_RTC_CTRL:
13197+ return s->rtc.ctrl;
13198+ case MENELAUS_RTC_UPDATE:
13199+ return 0x00;
13200+ case MENELAUS_RTC_SEC:
13201+ menelaus_rtc_update(s);
13202+ return to_bcd(s->rtc.tm.tm_sec);
13203+ case MENELAUS_RTC_MIN:
13204+ menelaus_rtc_update(s);
13205+ return to_bcd(s->rtc.tm.tm_min);
13206+ case MENELAUS_RTC_HR:
13207+ menelaus_rtc_update(s);
13208+ if ((s->rtc.ctrl >> 2) & 1) /* MODE12_n24 */
13209+ return to_bcd((s->rtc.tm.tm_hour % 12) + 1) |
13210+ (!!(s->rtc.tm.tm_hour >= 12) << 7); /* PM_nAM */
13211+ else
13212+ return to_bcd(s->rtc.tm.tm_hour);
13213+ case MENELAUS_RTC_DAY:
13214+ menelaus_rtc_update(s);
13215+ return to_bcd(s->rtc.tm.tm_mday);
13216+ case MENELAUS_RTC_MON:
13217+ menelaus_rtc_update(s);
13218+ return to_bcd(s->rtc.tm.tm_mon + 1);
13219+ case MENELAUS_RTC_YR:
13220+ menelaus_rtc_update(s);
13221+ return to_bcd(s->rtc.tm.tm_year - 2000);
13222+ case MENELAUS_RTC_WKDAY:
13223+ menelaus_rtc_update(s);
13224+ return to_bcd(s->rtc.tm.tm_wday);
13225+ case MENELAUS_RTC_AL_SEC:
13226+ return to_bcd(s->rtc.alm.tm_sec);
13227+ case MENELAUS_RTC_AL_MIN:
13228+ return to_bcd(s->rtc.alm.tm_min);
13229+ case MENELAUS_RTC_AL_HR:
13230+ if ((s->rtc.ctrl >> 2) & 1) /* MODE12_n24 */
13231+ return to_bcd((s->rtc.alm.tm_hour % 12) + 1) |
13232+ (!!(s->rtc.alm.tm_hour >= 12) << 7);/* AL_PM_nAM */
13233+ else
13234+ return to_bcd(s->rtc.alm.tm_hour);
13235+ case MENELAUS_RTC_AL_DAY:
13236+ return to_bcd(s->rtc.alm.tm_mday);
13237+ case MENELAUS_RTC_AL_MON:
13238+ return to_bcd(s->rtc.alm.tm_mon + 1);
13239+ case MENELAUS_RTC_AL_YR:
13240+ return to_bcd(s->rtc.alm.tm_year - 2000);
13241+ case MENELAUS_RTC_COMP_MSB:
13242+ return (s->rtc.comp >> 8) & 0xff;
13243+ case MENELAUS_RTC_COMP_LSB:
13244+ return (s->rtc.comp >> 0) & 0xff;
13245+
13246+ case MENELAUS_S1_PULL_EN:
13247+ return s->pull[0];
13248+ case MENELAUS_S1_PULL_DIR:
13249+ return s->pull[1];
13250+ case MENELAUS_S2_PULL_EN:
13251+ return s->pull[2];
13252+ case MENELAUS_S2_PULL_DIR:
13253+ return s->pull[3];
13254+
13255+ case MENELAUS_MCT_CTRL3: reg ++;
13256+ case MENELAUS_MCT_CTRL2: reg ++;
13257+ case MENELAUS_MCT_CTRL1:
13258+ return s->mmc_ctrl[reg];
13259+ case MENELAUS_MCT_PIN_ST:
13260+ /* TODO: return the real Card Detect */
13261+ return 0;
13262+ case MENELAUS_DEBOUNCE1:
13263+ return s->mmc_debounce;
13264+
13265+ default:
13266+#ifdef VERBOSE
13267+ printf("%s: unknown register %02x\n", __FUNCTION__, addr);
13268+#endif
13269+ break;
13270+ }
13271+ return 0;
13272+}
13273+
13274+static void menelaus_write(void *opaque, uint8_t addr, uint8_t value)
13275+{
13276+ struct menelaus_s *s = (struct menelaus_s *) opaque;
13277+ int line;
13278+ int reg = 0;
13279+ struct tm tm;
13280+
13281+ switch (addr) {
13282+ case MENELAUS_VCORE_CTRL1:
13283+ s->vcore[0] = (value & 0xe) | MIN(value & 0x1f, 0x12);
13284+ break;
13285+ case MENELAUS_VCORE_CTRL2:
13286+ s->vcore[1] = value;
13287+ break;
13288+ case MENELAUS_VCORE_CTRL3:
13289+ s->vcore[2] = MIN(value & 0x1f, 0x12);
13290+ break;
13291+ case MENELAUS_VCORE_CTRL4:
13292+ s->vcore[3] = MIN(value & 0x1f, 0x12);
13293+ break;
13294+ case MENELAUS_VCORE_CTRL5:
13295+ s->vcore[4] = value & 3;
13296+ /* XXX
13297+ * auto set to 3 on M_Active, nRESWARM
13298+ * auto set to 0 on M_WaitOn, M_Backup
13299+ */
13300+ break;
13301+
13302+ case MENELAUS_DCDC_CTRL1:
13303+ s->dcdc[0] = value & 0x3f;
13304+ break;
13305+ case MENELAUS_DCDC_CTRL2:
13306+ s->dcdc[1] = value & 0x07;
13307+ /* XXX
13308+ * auto set to 3 on M_Active, nRESWARM
13309+ * auto set to 0 on M_WaitOn, M_Backup
13310+ */
13311+ break;
13312+ case MENELAUS_DCDC_CTRL3:
13313+ s->dcdc[2] = value & 0x07;
13314+ break;
13315+
13316+ case MENELAUS_LDO_CTRL1:
13317+ s->ldo[0] = value;
13318+ break;
13319+ case MENELAUS_LDO_CTRL2:
13320+ s->ldo[1] = value & 0x7f;
13321+ /* XXX
13322+ * auto set to 0x7e on M_WaitOn, M_Backup
13323+ */
13324+ break;
13325+ case MENELAUS_LDO_CTRL3:
13326+ s->ldo[2] = value & 3;
13327+ /* XXX
13328+ * auto set to 3 on M_Active, nRESWARM
13329+ * auto set to 0 on M_WaitOn, M_Backup
13330+ */
13331+ break;
13332+ case MENELAUS_LDO_CTRL4:
13333+ s->ldo[3] = value & 3;
13334+ /* XXX
13335+ * auto set to 3 on M_Active, nRESWARM
13336+ * auto set to 0 on M_WaitOn, M_Backup
13337+ */
13338+ break;
13339+ case MENELAUS_LDO_CTRL5:
13340+ s->ldo[4] = value & 3;
13341+ /* XXX
13342+ * auto set to 3 on M_Active, nRESWARM
13343+ * auto set to 0 on M_WaitOn, M_Backup
13344+ */
13345+ break;
13346+ case MENELAUS_LDO_CTRL6:
13347+ s->ldo[5] = value & 3;
13348+ break;
13349+ case MENELAUS_LDO_CTRL7:
13350+ s->ldo[6] = value & 3;
13351+ break;
13352+ case MENELAUS_LDO_CTRL8:
13353+ s->ldo[7] = value & 3;
13354+ break;
13355+
13356+ case MENELAUS_SLEEP_CTRL2: reg ++;
13357+ case MENELAUS_SLEEP_CTRL1:
13358+ s->sleep[reg] = value;
13359+ break;
13360+
13361+ case MENELAUS_DEVICE_OFF:
13362+ if (value & 1)
13363+ menelaus_reset(&s->i2c);
13364+ break;
13365+
13366+ case MENELAUS_OSC_CTRL:
13367+ s->osc = value & 7;
13368+ break;
13369+
13370+ case MENELAUS_DETECT_CTRL:
13371+ s->detect = value & 0x7f;
13372+ break;
13373+
13374+ case MENELAUS_INT_MASK1:
13375+ s->mask &= 0xf00;
13376+ s->mask |= value << 0;
13377+ menelaus_update(s);
13378+ break;
13379+ case MENELAUS_INT_MASK2:
13380+ s->mask &= 0x0ff;
13381+ s->mask |= value << 8;
13382+ menelaus_update(s);
13383+ break;
13384+
13385+ case MENELAUS_INT_ACK1:
13386+ s->status &= ~(((uint16_t) value) << 0);
13387+ menelaus_update(s);
13388+ break;
13389+ case MENELAUS_INT_ACK2:
13390+ s->status &= ~(((uint16_t) value) << 8);
13391+ menelaus_update(s);
13392+ break;
13393+
13394+ case MENELAUS_GPIO_CTRL:
13395+ for (line = 0; line < 3; line ++)
13396+ if (((s->dir ^ value) >> line) & 1)
13397+ if (s->handler[line])
13398+ qemu_set_irq(s->handler[line],
13399+ ((s->outputs & ~s->dir) >> line) & 1);
13400+ s->dir = value & 0x67;
13401+ break;
13402+ case MENELAUS_GPIO_OUT:
13403+ for (line = 0; line < 3; line ++)
13404+ if ((((s->outputs ^ value) & ~s->dir) >> line) & 1)
13405+ if (s->handler[line])
13406+ qemu_set_irq(s->handler[line], (s->outputs >> line) & 1);
13407+ s->outputs = value & 0x07;
13408+ break;
13409+
13410+ case MENELAUS_BBSMS:
13411+ s->bbsms = 0x0d;
13412+ break;
13413+
13414+ case MENELAUS_RTC_CTRL:
13415+ if ((s->rtc.ctrl ^ value) & 1) { /* RTC_EN */
13416+ if (value & 1)
13417+ menelaus_rtc_start(s);
13418+ else
13419+ menelaus_rtc_stop(s);
13420+ }
13421+ s->rtc.ctrl = value & 0x1f;
13422+ menelaus_alm_update(s);
13423+ break;
13424+ case MENELAUS_RTC_UPDATE:
13425+ menelaus_rtc_update(s);
13426+ memcpy(&tm, &s->rtc.tm, sizeof(tm));
13427+ switch (value & 0xf) {
13428+ case 0:
13429+ break;
13430+ case 1:
13431+ tm.tm_sec = s->rtc.new.tm_sec;
13432+ break;
13433+ case 2:
13434+ tm.tm_min = s->rtc.new.tm_min;
13435+ break;
13436+ case 3:
13437+ if (s->rtc.new.tm_hour > 23)
13438+ goto rtc_badness;
13439+ tm.tm_hour = s->rtc.new.tm_hour;
13440+ break;
13441+ case 4:
13442+ if (s->rtc.new.tm_mday < 1)
13443+ goto rtc_badness;
13444+ /* TODO check range */
13445+ tm.tm_mday = s->rtc.new.tm_mday;
13446+ break;
13447+ case 5:
13448+ if (s->rtc.new.tm_mon < 0 || s->rtc.new.tm_mon > 11)
13449+ goto rtc_badness;
13450+ tm.tm_mon = s->rtc.new.tm_mon;
13451+ break;
13452+ case 6:
13453+ tm.tm_year = s->rtc.new.tm_year;
13454+ break;
13455+ case 7:
13456+ /* TODO set .tm_mday instead */
13457+ tm.tm_wday = s->rtc.new.tm_wday;
13458+ break;
13459+ case 8:
13460+ if (s->rtc.new.tm_hour > 23)
13461+ goto rtc_badness;
13462+ if (s->rtc.new.tm_mday < 1)
13463+ goto rtc_badness;
13464+ if (s->rtc.new.tm_mon < 0 || s->rtc.new.tm_mon > 11)
13465+ goto rtc_badness;
13466+ tm.tm_sec = s->rtc.new.tm_sec;
13467+ tm.tm_min = s->rtc.new.tm_min;
13468+ tm.tm_hour = s->rtc.new.tm_hour;
13469+ tm.tm_mday = s->rtc.new.tm_mday;
13470+ tm.tm_mon = s->rtc.new.tm_mon;
13471+ tm.tm_year = s->rtc.new.tm_year;
13472+ break;
13473+ rtc_badness:
13474+ default:
13475+ fprintf(stderr, "%s: bad RTC_UPDATE value %02x\n",
13476+ __FUNCTION__, value);
13477+ s->status |= 1 << 10; /* RTCERR */
13478+ menelaus_update(s);
13479+ }
13480+ s->rtc.sec += difftime(mktime(&tm), mktime(&s->rtc.tm));
13481+ break;
13482+ case MENELAUS_RTC_SEC:
13483+ s->rtc.tm.tm_sec = from_bcd(value & 0x7f);
13484+ break;
13485+ case MENELAUS_RTC_MIN:
13486+ s->rtc.tm.tm_min = from_bcd(value & 0x7f);
13487+ break;
13488+ case MENELAUS_RTC_HR:
13489+ s->rtc.tm.tm_hour = (s->rtc.ctrl & (1 << 2)) ? /* MODE12_n24 */
13490+ MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) :
13491+ from_bcd(value & 0x3f);
13492+ break;
13493+ case MENELAUS_RTC_DAY:
13494+ s->rtc.tm.tm_mday = from_bcd(value);
13495+ break;
13496+ case MENELAUS_RTC_MON:
13497+ s->rtc.tm.tm_mon = MAX(1, from_bcd(value)) - 1;
13498+ break;
13499+ case MENELAUS_RTC_YR:
13500+ s->rtc.tm.tm_year = 2000 + from_bcd(value);
13501+ break;
13502+ case MENELAUS_RTC_WKDAY:
13503+ s->rtc.tm.tm_mday = from_bcd(value);
13504+ break;
13505+ case MENELAUS_RTC_AL_SEC:
13506+ s->rtc.alm.tm_sec = from_bcd(value & 0x7f);
13507+ menelaus_alm_update(s);
13508+ break;
13509+ case MENELAUS_RTC_AL_MIN:
13510+ s->rtc.alm.tm_min = from_bcd(value & 0x7f);
13511+ menelaus_alm_update(s);
13512+ break;
13513+ case MENELAUS_RTC_AL_HR:
13514+ s->rtc.alm.tm_hour = (s->rtc.ctrl & (1 << 2)) ? /* MODE12_n24 */
13515+ MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) :
13516+ from_bcd(value & 0x3f);
13517+ menelaus_alm_update(s);
13518+ break;
13519+ case MENELAUS_RTC_AL_DAY:
13520+ s->rtc.alm.tm_mday = from_bcd(value);
13521+ menelaus_alm_update(s);
13522+ break;
13523+ case MENELAUS_RTC_AL_MON:
13524+ s->rtc.alm.tm_mon = MAX(1, from_bcd(value)) - 1;
13525+ menelaus_alm_update(s);
13526+ break;
13527+ case MENELAUS_RTC_AL_YR:
13528+ s->rtc.alm.tm_year = 2000 + from_bcd(value);
13529+ menelaus_alm_update(s);
13530+ break;
13531+ case MENELAUS_RTC_COMP_MSB:
13532+ s->rtc.comp &= 0xff;
13533+ s->rtc.comp |= value << 8;
13534+ break;
13535+ case MENELAUS_RTC_COMP_LSB:
13536+ s->rtc.comp &= 0xff << 8;
13537+ s->rtc.comp |= value;
13538+ break;
13539+
13540+ case MENELAUS_S1_PULL_EN:
13541+ s->pull[0] = value;
13542+ break;
13543+ case MENELAUS_S1_PULL_DIR:
13544+ s->pull[1] = value & 0x1f;
13545+ break;
13546+ case MENELAUS_S2_PULL_EN:
13547+ s->pull[2] = value;
13548+ break;
13549+ case MENELAUS_S2_PULL_DIR:
13550+ s->pull[3] = value & 0x1f;
13551+ break;
13552+
13553+ case MENELAUS_MCT_CTRL1:
13554+ s->mmc_ctrl[0] = value & 0x7f;
13555+ break;
13556+ case MENELAUS_MCT_CTRL2:
13557+ s->mmc_ctrl[1] = value;
13558+ /* TODO update Card Detect interrupts */
13559+ break;
13560+ case MENELAUS_MCT_CTRL3:
13561+ s->mmc_ctrl[2] = value & 0xf;
13562+ break;
13563+ case MENELAUS_DEBOUNCE1:
13564+ s->mmc_debounce = value & 0x3f;
13565+ break;
13566+
13567+ default:
13568+#ifdef VERBOSE
13569+ printf("%s: unknown register %02x\n", __FUNCTION__, addr);
13570+#endif
13571+ }
13572+}
13573+
13574+static void menelaus_event(i2c_slave *i2c, enum i2c_event event)
13575+{
13576+ struct menelaus_s *s = (struct menelaus_s *) i2c;
13577+
13578+ if (event == I2C_START_SEND)
13579+ s->firstbyte = 1;
13580+}
13581+
13582+static int menelaus_tx(i2c_slave *i2c, uint8_t data)
13583+{
13584+ struct menelaus_s *s = (struct menelaus_s *) i2c;
13585+ /* Interpret register address byte */
13586+ if (s->firstbyte) {
13587+ s->reg = data;
13588+ s->firstbyte = 0;
13589+ } else
13590+ menelaus_write(s, s->reg ++, data);
13591+
13592+ return 0;
13593+}
13594+
13595+static int menelaus_rx(i2c_slave *i2c)
13596+{
13597+ struct menelaus_s *s = (struct menelaus_s *) i2c;
13598+
13599+ return menelaus_read(s, s->reg ++);
13600+}
13601+
13602+static void tm_put(QEMUFile *f, struct tm *tm) {
13603+ qemu_put_be16(f, tm->tm_sec);
13604+ qemu_put_be16(f, tm->tm_min);
13605+ qemu_put_be16(f, tm->tm_hour);
13606+ qemu_put_be16(f, tm->tm_mday);
13607+ qemu_put_be16(f, tm->tm_min);
13608+ qemu_put_be16(f, tm->tm_year);
13609+}
13610+
13611+static void tm_get(QEMUFile *f, struct tm *tm) {
13612+ tm->tm_sec = qemu_get_be16(f);
13613+ tm->tm_min = qemu_get_be16(f);
13614+ tm->tm_hour = qemu_get_be16(f);
13615+ tm->tm_mday = qemu_get_be16(f);
13616+ tm->tm_min = qemu_get_be16(f);
13617+ tm->tm_year = qemu_get_be16(f);
13618+}
13619+
13620+static void menelaus_save(QEMUFile *f, void *opaque)
13621+{
13622+ struct menelaus_s *s = (struct menelaus_s *) opaque;
13623+
13624+ qemu_put_be32(f, s->firstbyte);
13625+ qemu_put_8s(f, &s->reg);
13626+
13627+ qemu_put_8s(f, &s->vcore[0]);
13628+ qemu_put_8s(f, &s->vcore[1]);
13629+ qemu_put_8s(f, &s->vcore[2]);
13630+ qemu_put_8s(f, &s->vcore[3]);
13631+ qemu_put_8s(f, &s->vcore[4]);
13632+ qemu_put_8s(f, &s->dcdc[3]);
13633+ qemu_put_8s(f, &s->dcdc[3]);
13634+ qemu_put_8s(f, &s->dcdc[3]);
13635+ qemu_put_8s(f, &s->ldo[0]);
13636+ qemu_put_8s(f, &s->ldo[1]);
13637+ qemu_put_8s(f, &s->ldo[2]);
13638+ qemu_put_8s(f, &s->ldo[3]);
13639+ qemu_put_8s(f, &s->ldo[4]);
13640+ qemu_put_8s(f, &s->ldo[5]);
13641+ qemu_put_8s(f, &s->ldo[6]);
13642+ qemu_put_8s(f, &s->ldo[7]);
13643+ qemu_put_8s(f, &s->sleep[0]);
13644+ qemu_put_8s(f, &s->sleep[1]);
13645+ qemu_put_8s(f, &s->osc);
13646+ qemu_put_8s(f, &s->detect);
13647+ qemu_put_be16s(f, &s->mask);
13648+ qemu_put_be16s(f, &s->status);
13649+ qemu_put_8s(f, &s->dir);
13650+ qemu_put_8s(f, &s->inputs);
13651+ qemu_put_8s(f, &s->outputs);
13652+ qemu_put_8s(f, &s->bbsms);
13653+ qemu_put_8s(f, &s->pull[0]);
13654+ qemu_put_8s(f, &s->pull[1]);
13655+ qemu_put_8s(f, &s->pull[2]);
13656+ qemu_put_8s(f, &s->pull[3]);
13657+ qemu_put_8s(f, &s->mmc_ctrl[0]);
13658+ qemu_put_8s(f, &s->mmc_ctrl[1]);
13659+ qemu_put_8s(f, &s->mmc_ctrl[2]);
13660+ qemu_put_8s(f, &s->mmc_debounce);
13661+ qemu_put_8s(f, &s->rtc.ctrl);
13662+ qemu_put_be16s(f, &s->rtc.comp);
13663+ /* Should be <= 1000 */
13664+ qemu_put_be16(f, s->rtc.next - qemu_get_clock(rt_clock));
13665+ tm_put(f, &s->rtc.new);
13666+ tm_put(f, &s->rtc.alm);
13667+ qemu_put_byte(f, s->pwrbtn_state);
13668+
13669+ i2c_slave_save(f, &s->i2c);
13670+}
13671+
13672+static int menelaus_load(QEMUFile *f, void *opaque, int version_id)
13673+{
13674+ struct menelaus_s *s = (struct menelaus_s *) opaque;
13675+
13676+ s->firstbyte = qemu_get_be32(f);
13677+ qemu_get_8s(f, &s->reg);
13678+
13679+ if (s->rtc.ctrl & 1) /* RTC_EN */
13680+ menelaus_rtc_stop(s);
13681+ qemu_get_8s(f, &s->vcore[0]);
13682+ qemu_get_8s(f, &s->vcore[1]);
13683+ qemu_get_8s(f, &s->vcore[2]);
13684+ qemu_get_8s(f, &s->vcore[3]);
13685+ qemu_get_8s(f, &s->vcore[4]);
13686+ qemu_get_8s(f, &s->dcdc[3]);
13687+ qemu_get_8s(f, &s->dcdc[3]);
13688+ qemu_get_8s(f, &s->dcdc[3]);
13689+ qemu_get_8s(f, &s->ldo[0]);
13690+ qemu_get_8s(f, &s->ldo[1]);
13691+ qemu_get_8s(f, &s->ldo[2]);
13692+ qemu_get_8s(f, &s->ldo[3]);
13693+ qemu_get_8s(f, &s->ldo[4]);
13694+ qemu_get_8s(f, &s->ldo[5]);
13695+ qemu_get_8s(f, &s->ldo[6]);
13696+ qemu_get_8s(f, &s->ldo[7]);
13697+ qemu_get_8s(f, &s->sleep[0]);
13698+ qemu_get_8s(f, &s->sleep[1]);
13699+ qemu_get_8s(f, &s->osc);
13700+ qemu_get_8s(f, &s->detect);
13701+ qemu_get_be16s(f, &s->mask);
13702+ qemu_get_be16s(f, &s->status);
13703+ qemu_get_8s(f, &s->dir);
13704+ qemu_get_8s(f, &s->inputs);
13705+ qemu_get_8s(f, &s->outputs);
13706+ qemu_get_8s(f, &s->bbsms);
13707+ qemu_get_8s(f, &s->pull[0]);
13708+ qemu_get_8s(f, &s->pull[1]);
13709+ qemu_get_8s(f, &s->pull[2]);
13710+ qemu_get_8s(f, &s->pull[3]);
13711+ qemu_get_8s(f, &s->mmc_ctrl[0]);
13712+ qemu_get_8s(f, &s->mmc_ctrl[1]);
13713+ qemu_get_8s(f, &s->mmc_ctrl[2]);
13714+ qemu_get_8s(f, &s->mmc_debounce);
13715+ qemu_get_8s(f, &s->rtc.ctrl);
13716+ qemu_get_be16s(f, &s->rtc.comp);
13717+ s->rtc.next = qemu_get_be16(f);
13718+ tm_get(f, &s->rtc.new);
13719+ tm_get(f, &s->rtc.alm);
13720+ s->pwrbtn_state = qemu_get_byte(f);
13721+ menelaus_alm_update(s);
13722+ menelaus_update(s);
13723+ if (s->rtc.ctrl & 1) /* RTC_EN */
13724+ menelaus_rtc_start(s);
13725+
13726+ i2c_slave_load(f, &s->i2c);
13727+ return 0;
13728+}
13729+
13730+static int menelaus_iid = 0;
13731+
13732+i2c_slave *twl92230_init(i2c_bus *bus, qemu_irq irq)
13733+{
13734+ struct menelaus_s *s = (struct menelaus_s *)
13735+ i2c_slave_init(bus, 0, sizeof(struct menelaus_s));
13736+
13737+ s->i2c.event = menelaus_event;
13738+ s->i2c.recv = menelaus_rx;
13739+ s->i2c.send = menelaus_tx;
13740+
13741+ /* TODO: use the qemu gettime functions */
13742+ s->rtc.gettime = localtime_r;
13743+
13744+ s->irq = irq;
13745+ s->rtc.hz = qemu_new_timer(rt_clock, menelaus_rtc_hz, s);
13746+ s->in = qemu_allocate_irqs(menelaus_gpio_set, s, 3);
13747+ s->pwrbtn = qemu_allocate_irqs(menelaus_pwrbtn_set, s, 1)[0];
13748+
13749+ menelaus_reset(&s->i2c);
13750+
13751+ register_savevm("menelaus", menelaus_iid ++,
13752+ 0, menelaus_save, menelaus_load, s);
13753+
13754+ return &s->i2c;
13755+}
13756+
13757+qemu_irq *twl92230_gpio_in_get(i2c_slave *i2c)
13758+{
13759+ struct menelaus_s *s = (struct menelaus_s *) i2c;
13760+
13761+ return s->in;
13762+}
13763+
13764+void twl92230_gpio_out_set(i2c_slave *i2c, int line, qemu_irq handler)
13765+{
13766+ struct menelaus_s *s = (struct menelaus_s *) i2c;
13767+
13768+ if (line >= 3 || line < 0) {
13769+ fprintf(stderr, "%s: No GPO line %i\n", __FUNCTION__, line);
13770+ exit(-1);
13771+ }
13772+ s->handler[line] = handler;
13773+}
13774diff --git a/hw/versatilepb.c b/hw/versatilepb.c
13775index da6e4ec..ecc0037 100644
13776--- a/hw/versatilepb.c
13777+++ b/hw/versatilepb.c
13778@@ -157,6 +157,8 @@ static qemu_irq *vpb_sic_init(uint32_t base, qemu_irq *parent, int irq)
13779 peripherans and expansion busses. For now we emulate a subset of the
13780 PB peripherals and just change the board ID. */
13781
13782+static struct arm_boot_info versatile_binfo;
13783+
13784 static void versatile_init(int ram_size, int vga_ram_size,
13785 const char *boot_device, DisplayState *ds,
13786 const char *kernel_filename, const char *kernel_cmdline,
13787@@ -283,8 +285,12 @@ static void versatile_init(int ram_size, int vga_ram_size,
13788 /* 0x101f3000 UART2. */
13789 /* 0x101f4000 SSPI. */
13790
13791- arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline,
13792- initrd_filename, board_id, 0x0);
13793+ versatile_binfo.ram_size = ram_size;
13794+ versatile_binfo.kernel_filename = kernel_filename;
13795+ versatile_binfo.kernel_cmdline = kernel_cmdline;
13796+ versatile_binfo.initrd_filename = initrd_filename;
13797+ versatile_binfo.board_id = board_id;
13798+ arm_load_kernel(env, &versatile_binfo);
13799 }
13800
13801 static void vpb_init(int ram_size, int vga_ram_size,
13802diff --git a/softmmu_template.h b/softmmu_template.h
13803index 0a4bc7e..d480f34 100644
13804--- a/softmmu_template.h
13805+++ b/softmmu_template.h
13806@@ -51,12 +51,15 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
13807 int mmu_idx,
13808 void *retaddr);
13809 static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
13810- target_ulong tlb_addr)
13811+ target_ulong tlb_addr,
13812+ target_ulong tlb_io)
13813 {
13814 DATA_TYPE res;
13815 int index;
13816
13817- index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
13818+ index = (tlb_addr & ~TARGET_PAGE_MASK) >> IO_MEM_SHIFT;
13819+ if (index > 4)
13820+ index = (tlb_io >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
13821 #if SHIFT <= 2
13822 res = io_mem_read[index][SHIFT](io_mem_opaque[index], physaddr);
13823 #else
13824@@ -95,7 +98,9 @@ DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
13825 /* IO access */
13826 if ((addr & (DATA_SIZE - 1)) != 0)
13827 goto do_unaligned_access;
13828- res = glue(io_read, SUFFIX)(physaddr, tlb_addr);
13829+ res = glue(io_read, SUFFIX)(physaddr, tlb_addr,
13830+ env->tlb_table[mmu_idx]
13831+ [index].addr_code);
13832 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
13833 /* slow unaligned access (it spans two pages or IO) */
13834 do_unaligned_access:
13835@@ -147,7 +152,9 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
13836 /* IO access */
13837 if ((addr & (DATA_SIZE - 1)) != 0)
13838 goto do_unaligned_access;
13839- res = glue(io_read, SUFFIX)(physaddr, tlb_addr);
13840+ res = glue(io_read, SUFFIX)(physaddr, tlb_addr,
13841+ env->tlb_table[mmu_idx]
13842+ [index].addr_code);
13843 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
13844 do_unaligned_access:
13845 /* slow unaligned access (it spans two pages) */
13846@@ -186,11 +193,14 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
13847 static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
13848 DATA_TYPE val,
13849 target_ulong tlb_addr,
13850- void *retaddr)
13851+ void *retaddr,
13852+ target_ulong tlb_io)
13853 {
13854 int index;
13855
13856- index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
13857+ index = (tlb_addr & ~TARGET_PAGE_MASK) >> IO_MEM_SHIFT;
13858+ if (index > 4)
13859+ index = (tlb_io >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
13860 env->mem_write_vaddr = tlb_addr;
13861 env->mem_write_pc = (unsigned long)retaddr;
13862 #if SHIFT <= 2
13863@@ -228,7 +238,8 @@ void REGPARM glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
13864 if ((addr & (DATA_SIZE - 1)) != 0)
13865 goto do_unaligned_access;
13866 retaddr = GETPC();
13867- glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr);
13868+ glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr,
13869+ env->tlb_table[mmu_idx][index].addr_code);
13870 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
13871 do_unaligned_access:
13872 retaddr = GETPC();
13873@@ -278,7 +289,8 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
13874 /* IO access */
13875 if ((addr & (DATA_SIZE - 1)) != 0)
13876 goto do_unaligned_access;
13877- glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr);
13878+ glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr,
13879+ env->tlb_table[mmu_idx][index].addr_code);
13880 } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
13881 do_unaligned_access:
13882 /* XXX: not efficient, but simple */
13883diff --git a/target-arm/cpu.h b/target-arm/cpu.h
13884index b284a21..633b335 100644
13885--- a/target-arm/cpu.h
13886+++ b/target-arm/cpu.h
13887@@ -198,12 +198,16 @@ typedef struct CPUARMState {
13888 CPU_COMMON
13889
13890 /* These fields after the common ones so they are preserved on reset. */
13891- int ram_size;
13892- const char *kernel_filename;
13893- const char *kernel_cmdline;
13894- const char *initrd_filename;
13895- int board_id;
13896- target_phys_addr_t loader_start;
13897+ struct arm_boot_info {
13898+ int ram_size;
13899+ const char *kernel_filename;
13900+ const char *kernel_cmdline;
13901+ const char *initrd_filename;
13902+ target_phys_addr_t loader_start;
13903+ int nb_cpus;
13904+ int board_id;
13905+ int (*atag_board)(struct arm_boot_info *info, void *p);
13906+ } *boot_info;
13907 } CPUARMState;
13908
13909 CPUARMState *cpu_arm_init(const char *cpu_model);
13910@@ -377,6 +381,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
13911 #define ARM_CPUID_PXA270_C0 0x69054114
13912 #define ARM_CPUID_PXA270_C5 0x69054117
13913 #define ARM_CPUID_ARM1136 0x4117b363
13914+#define ARM_CPUID_ARM1136_R2 0x4107b362
13915 #define ARM_CPUID_ARM11MPCORE 0x410fb022
13916 #define ARM_CPUID_CORTEXA8 0x410fc080
13917 #define ARM_CPUID_CORTEXM3 0x410fc231
13918diff --git a/target-arm/helper.c b/target-arm/helper.c
13919index 86470db..0709129 100644
13920--- a/target-arm/helper.c
13921+++ b/target-arm/helper.c
13922@@ -53,6 +53,9 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
13923 env->cp15.c0_cachetype = 0x1dd20d2;
13924 env->cp15.c1_sys = 0x00090078;
13925 break;
13926+ case ARM_CPUID_ARM1136_R2:
13927+ /* TODO! */
13928+ env->GE = 0x5;
13929 case ARM_CPUID_ARM1136:
13930 set_feature(env, ARM_FEATURE_V6);
13931 set_feature(env, ARM_FEATURE_VFP);
13932@@ -198,6 +201,7 @@ static const struct arm_cpu_t arm_cpu_names[] = {
13933 { ARM_CPUID_ARM946, "arm946"},
13934 { ARM_CPUID_ARM1026, "arm1026"},
13935 { ARM_CPUID_ARM1136, "arm1136"},
13936+ { ARM_CPUID_ARM1136_R2, "arm1136-r2"},
13937 { ARM_CPUID_ARM11MPCORE, "arm11mpcore"},
13938 { ARM_CPUID_CORTEXM3, "cortex-m3"},
13939 { ARM_CPUID_CORTEXA8, "cortex-a8"},
13940@@ -1539,6 +1543,7 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
13941 case ARM_CPUID_ARM1026:
13942 return 1;
13943 case ARM_CPUID_ARM1136:
13944+ case ARM_CPUID_ARM1136_R2:
13945 return 7;
13946 case ARM_CPUID_ARM11MPCORE:
13947 return 1;
13948@@ -1721,6 +1726,10 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
13949 case 8: /* TI925T_status */
13950 return 0;
13951 }
13952+ /* TODO: Peripheral port remap register:
13953+ * On OMAP2 mcr p15, 0, rn, c15, c2, 4 sets up the interrupt
13954+ * controller base address at $rn & ~0xfff and map size of
13955+ * 0x200 << ($rn & 0xfff), when MMU is off. */
13956 goto bad_reg;
13957 }
13958 return 0;
13959diff --git a/vl.c b/vl.c
13960index d371af7..76d8def 100644
13961--- a/vl.c
13962+++ b/vl.c
13963@@ -8006,6 +8006,7 @@ static void register_machines(void)
13964 qemu_register_machine(&borzoipda_machine);
13965 qemu_register_machine(&terrierpda_machine);
13966 qemu_register_machine(&palmte_machine);
13967+ qemu_register_machine(&n800_machine);
13968 qemu_register_machine(&lm3s811evb_machine);
13969 qemu_register_machine(&lm3s6965evb_machine);
13970 qemu_register_machine(&connex_machine);
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/series b/meta/packages/qemu/qemu-0.9.1+svn/series
new file mode 100644
index 0000000000..126da88288
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/series
@@ -0,0 +1,25 @@
102_snapshot_use_tmpdir.patch -p0
205_non-fatal_if_linux_hd_missing.patch -p1
306_exit_segfault.patch -p0
410_signal_jobs.patch -p0
511_signal_sigaction.patch -p0
622_net_tuntap_stall.patch -p0
731_syscalls.patch -p0
832_syscall_sysctl.patch -p0
933_syscall_ppc_clone.patch -p0
1039_syscall_fadvise64.patch -p0
1141_arm_fpa_sigfpe.patch -p0
1252_ne2000_return.patch -p1
1361_safe_64bit_int.patch -p0
1463_sparc_build.patch -p0
1564_ppc_asm_constraints.patch -p1
1665_kfreebsd.patch -p0
1766_tls_ld.patch -p0
1891-oh-sdl-cursor.patch -p0
19qemu-0.9.0-nptl.patch -p1
20qemu-0.9.0-nptl-update.patch -p1
21qemu-amd64-32b-mapping-0.9.0.patch -p1
22workaround_bad_futex_headers.patch -p1
23fix_segfault.patch -p1
24no-strip.patch -p1
25qemu-n800-support.patch -p1
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/workaround_bad_futex_headers.patch b/meta/packages/qemu/qemu-0.9.1+svn/workaround_bad_futex_headers.patch
new file mode 100644
index 0000000000..cc122ebdba
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/workaround_bad_futex_headers.patch
@@ -0,0 +1,25 @@
1---
2 linux-user/syscall.c | 10 +++++++++-
3 1 file changed, 9 insertions(+), 1 deletion(-)
4
5Index: qemu/linux-user/syscall.c
6===================================================================
7--- qemu.orig/linux-user/syscall.c 2007-08-09 20:28:06.000000000 +0100
8+++ qemu/linux-user/syscall.c 2007-08-09 20:28:41.000000000 +0100
9@@ -61,7 +61,15 @@
10 #define tchars host_tchars /* same as target */
11 #define ltchars host_ltchars /* same as target */
12
13-#include <linux/futex.h>
14+#define FUTEX_WAIT 0
15+#define FUTEX_WAKE 1
16+#define FUTEX_FD 2
17+#define FUTEX_REQUEUE 3
18+#define FUTEX_CMP_REQUEUE 4
19+#define FUTEX_WAKE_OP 5
20+#define FUTEX_LOCK_PI 6
21+#define FUTEX_UNLOCK_PI 7
22+
23 #include <linux/termios.h>
24 #include <linux/unistd.h>
25 #include <linux/utsname.h>
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/writev_fix.patch b/meta/packages/qemu/qemu-0.9.1+svn/writev_fix.patch
new file mode 100644
index 0000000000..e0ed4af972
--- /dev/null
+++ b/meta/packages/qemu/qemu-0.9.1+svn/writev_fix.patch
@@ -0,0 +1,17 @@
1---
2 linux-user/syscall.c | 2 +-
3 1 file changed, 1 insertion(+), 1 deletion(-)
4
5Index: qemu-0.9.1/linux-user/syscall.c
6===================================================================
7--- qemu-0.9.1.orig/linux-user/syscall.c 2008-02-03 00:00:00.000000000 +0000
8+++ qemu-0.9.1/linux-user/syscall.c 2008-02-03 00:00:38.000000000 +0000
9@@ -1048,7 +1048,7 @@ static abi_long lock_iovec(int type, str
10 base = tswapl(target_vec[i].iov_base);
11 vec[i].iov_len = tswapl(target_vec[i].iov_len);
12 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
13- if (!vec[i].iov_base)
14+ if (!vec[i].iov_base && vec[i].iov_len)
15 goto fail;
16 }
17 unlock_user (target_vec, target_addr, 0);
diff --git a/meta/packages/qemu/qemu-native_svn.bb b/meta/packages/qemu/qemu-native_svn.bb
new file mode 100644
index 0000000000..1e3a4dbbfa
--- /dev/null
+++ b/meta/packages/qemu/qemu-native_svn.bb
@@ -0,0 +1,2 @@
1require qemu_svn.bb
2require qemu-native.inc
diff --git a/meta/packages/qemu/qemu-sdk_svn.bb b/meta/packages/qemu/qemu-sdk_svn.bb
new file mode 100644
index 0000000000..396f4ca82c
--- /dev/null
+++ b/meta/packages/qemu/qemu-sdk_svn.bb
@@ -0,0 +1,4 @@
1require qemu_svn.bb
2require qemu-sdk.inc
3
4EXTRA_OECONF += "--target-list=arm-linux-user,arm-softmmu"
diff --git a/meta/packages/qemu/qemu_svn.bb b/meta/packages/qemu/qemu_svn.bb
new file mode 100644
index 0000000000..0a55ba8736
--- /dev/null
+++ b/meta/packages/qemu/qemu_svn.bb
@@ -0,0 +1,46 @@
1LICENSE = "GPL"
2DEPENDS = "zlib"
3PV = "0.9.1+svnr${SRCREV}"
4PR = "r2"
5
6FILESPATH = "${FILE_DIRNAME}/qemu-0.9.1+svn/"
7
8SRC_URI = "\
9 svn://svn.savannah.nongnu.org/qemu;module=trunk \
10 file://02_snapshot_use_tmpdir.patch;patch=1;pnum=0 \
11 file://05_non-fatal_if_linux_hd_missing.patch;patch=1;pnum=1 \
12 file://06_exit_segfault.patch;patch=1;pnum=0 \
13 file://10_signal_jobs.patch;patch=1;pnum=0 \
14 file://11_signal_sigaction.patch;patch=1;pnum=0 \
15 file://22_net_tuntap_stall.patch;patch=1;pnum=0 \
16 file://31_syscalls.patch;patch=1;pnum=0 \
17 file://32_syscall_sysctl.patch;patch=1;pnum=0 \
18 file://33_syscall_ppc_clone.patch;patch=1;pnum=0 \
19 file://39_syscall_fadvise64.patch;patch=1;pnum=0 \
20 file://41_arm_fpa_sigfpe.patch;patch=1;pnum=0 \
21 file://52_ne2000_return.patch;patch=1;pnum=1 \
22 file://61_safe_64bit_int.patch;patch=1;pnum=0 \
23 file://63_sparc_build.patch;patch=1;pnum=0 \
24 file://64_ppc_asm_constraints.patch;patch=1;pnum=1 \
25 file://65_kfreebsd.patch;patch=1;pnum=0 \
26 file://66_tls_ld.patch;patch=1;pnum=0 \
27 file://91-oh-sdl-cursor.patch;patch=1;pnum=0 \
28 file://qemu-0.9.0-nptl.patch;patch=1 \
29 file://qemu-0.9.0-nptl-update.patch;patch=1 \
30 file://qemu-amd64-32b-mapping-0.9.0.patch;patch=1 \
31 file://workaround_bad_futex_headers.patch;patch=1 \
32 file://fix_segfault.patch;patch=1 \
33 file://no-strip.patch;patch=1 \
34 file://qemu-n800-support.patch;patch=1"
35
36S = "${WORKDIR}/trunk"
37
38#EXTRA_OECONF += "--disable-sdl"
39#EXTRA_OECONF += "--target-list=arm-linux-user,arm-softmmu"
40EXTRA_OECONF += "--disable-gfx-check"
41
42inherit autotools
43
44do_configure() {
45 ${S}/configure --prefix=${prefix} ${EXTRA_OECONF}
46}