nand emulation fixes
[qemu] / hw / omap1.c
index b9176b3..52e9a63 100644 (file)
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 #include "hw.h"
 #include "arm-misc.h"
@@ -24,6 +23,7 @@
 #include "sysemu.h"
 #include "qemu-timer.h"
 #include "qemu-char.h"
+#include "soc_dma.h"
 /* We use pc-style serial ports.  */
 #include "pc.h"
 
@@ -94,9 +94,9 @@ struct omap_intr_handler_bank_s {
 struct omap_intr_handler_s {
     qemu_irq *pins;
     qemu_irq parent_intr[2];
-    target_phys_addr_t base;
     unsigned char nbanks;
     int level_only;
+    uint8_t revision;
 
     /* state */
     uint32_t new_agr[2];
@@ -201,7 +201,7 @@ static void omap_set_intr_noedge(void *opaque, int irq, int req)
 static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
-    int i, offset = addr - s->base;
+    int i, offset = addr;
     int bank_no = offset >> 8;
     int line_no;
     struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
@@ -279,7 +279,7 @@ static void omap_inth_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
-    int i, offset = addr - s->base;
+    int i, offset = addr;
     int bank_no = offset >> 8;
     struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
     offset &= 0xff;
@@ -408,6 +408,63 @@ void omap_inth_reset(struct omap_intr_handler_s *s)
     qemu_set_irq(s->parent_intr[1], 0);
 }
 
+static void omap_inth_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *)opaque;
+    int i, j;
+    
+    qemu_put_be32(f, s->new_agr[0]);
+    qemu_put_be32(f, s->new_agr[1]);
+    qemu_put_sbe32(f, s->sir_intr[0]);
+    qemu_put_sbe32(f, s->sir_intr[1]);
+    qemu_put_sbe32(f, s->autoidle);
+    qemu_put_be32(f, s->mask);
+    qemu_put_byte(f, s->nbanks);
+    for (i = 0; i < s->nbanks; i++) {
+        qemu_put_be32(f, s->bank[i].irqs);
+        qemu_put_be32(f, s->bank[i].inputs);
+        qemu_put_be32(f, s->bank[i].mask);
+        qemu_put_be32(f, s->bank[i].fiq);
+        qemu_put_be32(f, s->bank[i].sens_edge);
+        qemu_put_be32(f, s->bank[i].swi);
+        for (j = 0; j < 32; j++)
+            qemu_put_byte(f, s->bank[i].priority[j]);
+    }
+}
+
+static int omap_inth_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *)opaque;
+    int i, j;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    s->new_agr[0] = qemu_get_be32(f);
+    s->new_agr[1] = qemu_get_be32(f);
+    s->sir_intr[0] = qemu_get_sbe32(f);
+    s->sir_intr[1] = qemu_get_sbe32(f);
+    s->autoidle = qemu_get_sbe32(f);
+    s->mask = qemu_get_be32(f);
+    if (qemu_get_byte(f) != s->nbanks)
+        return -EINVAL;
+    for (i = 0; i < s->nbanks; i++) {
+        s->bank[i].irqs = qemu_get_be32(f);
+        s->bank[i].inputs = qemu_get_be32(f);
+        s->bank[i].mask = qemu_get_be32(f);
+        s->bank[i].fiq = qemu_get_be32(f);
+        s->bank[i].sens_edge = qemu_get_be32(f);
+        s->bank[i].swi = qemu_get_be32(f);
+        for (j = 0; j < 32; j++)
+            s->bank[i].priority[j] = qemu_get_byte(f);
+    }
+    
+    omap_inth_update(s, 0);
+    omap_inth_update(s, 1);
+    
+    return 0;
+}
+
 struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
                 unsigned long size, unsigned char nbanks, qemu_irq **pins,
                 qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk)
@@ -419,7 +476,6 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
 
     s->parent_intr[0] = parent_irq;
     s->parent_intr[1] = parent_fiq;
-    s->base = base;
     s->nbanks = nbanks;
     s->pins = qemu_allocate_irqs(omap_set_intr, s, nbanks * 32);
     if (pins)
@@ -429,15 +485,17 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
 
     iomemtype = cpu_register_io_memory(0, omap_inth_readfn,
                     omap_inth_writefn, s);
-    cpu_register_physical_memory(s->base, size, iomemtype);
+    cpu_register_physical_memory(base, size, iomemtype);
 
+    register_savevm("omap_inth", -1, 0,
+                    omap_inth_save_state, omap_inth_load_state, s);
     return s;
 }
 
 static uint32_t omap2_inth_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
-    int offset = addr - s->base;
+    int offset = addr;
     int bank_no, line_no;
     struct omap_intr_handler_bank_s *bank = 0;
 
@@ -451,7 +509,7 @@ static uint32_t omap2_inth_read(void *opaque, target_phys_addr_t addr)
 
     switch (offset) {
     case 0x00: /* INTC_REVISION */
-        return 0x21;
+        return s->revision;
 
     case 0x10: /* INTC_SYSCONFIG */
         return (s->autoidle >> 2) & 1;
@@ -515,7 +573,7 @@ static void omap2_inth_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
-    int offset = addr - s->base;
+    int offset = addr;
     int bank_no, line_no;
     struct omap_intr_handler_bank_s *bank = 0;
 
@@ -627,7 +685,9 @@ static CPUWriteMemoryFunc *omap2_inth_writefn[] = {
     omap2_inth_write,
 };
 
-struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
+struct omap_intr_handler_s *omap2_inth_init(
+                struct omap_mpu_state_s *mpu,
+                target_phys_addr_t base,
                 int size, int nbanks, qemu_irq **pins,
                 qemu_irq parent_irq, qemu_irq parent_fiq,
                 omap_clk fclk, omap_clk iclk)
@@ -637,9 +697,9 @@ struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
             qemu_mallocz(sizeof(struct omap_intr_handler_s) +
                             sizeof(struct omap_intr_handler_bank_s) * nbanks);
 
+    s->revision = cpu_class_omap3(mpu) ? 0x40 : 0x21;
     s->parent_intr[0] = parent_irq;
     s->parent_intr[1] = parent_fiq;
-    s->base = base;
     s->nbanks = nbanks;
     s->level_only = 1;
     s->pins = qemu_allocate_irqs(omap_set_intr_noedge, s, nbanks * 32);
@@ -650,8 +710,10 @@ struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
 
     iomemtype = cpu_register_io_memory(0, omap2_inth_readfn,
                     omap2_inth_writefn, s);
-    cpu_register_physical_memory(s->base, size, iomemtype);
+    cpu_register_physical_memory(base, size, iomemtype);
 
+    register_savevm("omap_inth", -1, 0,
+                    omap_inth_save_state, omap_inth_load_state, s);
     return s;
 }
 
@@ -659,10 +721,10 @@ struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
 struct omap_mpu_timer_s {
     qemu_irq irq;
     omap_clk clk;
-    target_phys_addr_t base;
     uint32_t val;
     int64_t time;
     QEMUTimer *timer;
+    QEMUBH *tick;
     int64_t rate;
     int it_ena;
 
@@ -696,7 +758,7 @@ static inline void omap_timer_update(struct omap_mpu_timer_s *timer)
 
     if (timer->enable && timer->st && timer->rate) {
         timer->val = timer->reset_val; /* Should skip this on clk enable */
-        expires = muldiv64(timer->val << (timer->ptv + 1),
+        expires = muldiv64((uint64_t) timer->val << (timer->ptv + 1),
                         ticks_per_sec, timer->rate);
 
         /* If timer expiry would be sooner than in about 1 ms and
@@ -707,21 +769,15 @@ static inline void omap_timer_update(struct omap_mpu_timer_s *timer)
          * ticks.  */
         if (expires > (ticks_per_sec >> 10) || timer->ar)
             qemu_mod_timer(timer->timer, timer->time + expires);
-        else {
-            timer->val = 0;
-            timer->st = 0;
-            if (timer->it_ena)
-                /* Edge-triggered irq */
-                qemu_irq_pulse(timer->irq);
-        }
+        else
+            qemu_bh_schedule(timer->tick);
     } else
         qemu_del_timer(timer->timer);
 }
 
-static void omap_timer_tick(void *opaque)
+static void omap_timer_fire(void *opaque)
 {
-    struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
-    omap_timer_sync(timer);
+    struct omap_mpu_timer_s *timer = opaque;
 
     if (!timer->ar) {
         timer->val = 0;
@@ -731,6 +787,14 @@ static void omap_timer_tick(void *opaque)
     if (timer->it_ena)
         /* Edge-triggered irq */
         qemu_irq_pulse(timer->irq);
+}
+
+static void omap_timer_tick(void *opaque)
+{
+    struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
+
+    omap_timer_sync(timer);
+    omap_timer_fire(timer);
     omap_timer_update(timer);
 }
 
@@ -753,9 +817,8 @@ static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer)
 static uint32_t omap_mpu_timer_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
-    int offset = addr - s->base;
 
-    switch (offset) {
+    switch (addr) {
     case 0x00: /* CNTL_TIMER */
         return (s->enable << 5) | (s->ptv << 2) | (s->ar << 1) | s->st;
 
@@ -774,9 +837,8 @@ static void omap_mpu_timer_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
-    int offset = addr - s->base;
 
-    switch (offset) {
+    switch (addr) {
     case 0x00: /* CNTL_TIMER */
         omap_timer_sync(s);
         s->enable = (value >> 5) & 1;
@@ -832,14 +894,14 @@ struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
 
     s->irq = irq;
     s->clk = clk;
-    s->base = base;
     s->timer = qemu_new_timer(vm_clock, omap_timer_tick, s);
+    s->tick = qemu_bh_new(omap_timer_fire, s);
     omap_mpu_timer_reset(s);
     omap_timer_clk_setup(s);
 
     iomemtype = cpu_register_io_memory(0, omap_mpu_timer_readfn,
                     omap_mpu_timer_writefn, s);
-    cpu_register_physical_memory(s->base, 0x100, iomemtype);
+    cpu_register_physical_memory(base, 0x100, iomemtype);
 
     return s;
 }
@@ -856,9 +918,8 @@ struct omap_watchdog_timer_s {
 static uint32_t omap_wd_timer_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
-    int offset = addr - s->timer.base;
 
-    switch (offset) {
+    switch (addr) {
     case 0x00: /* CNTL_TIMER */
         return (s->timer.ptv << 9) | (s->timer.ar << 8) |
                 (s->timer.st << 7) | (s->free << 1);
@@ -878,9 +939,8 @@ static void omap_wd_timer_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
-    int offset = addr - s->timer.base;
 
-    switch (offset) {
+    switch (addr) {
     case 0x00: /* CNTL_TIMER */
         omap_timer_sync(&s->timer);
         s->timer.ptv = (value >> 9) & 7;
@@ -958,14 +1018,13 @@ struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
 
     s->timer.irq = irq;
     s->timer.clk = clk;
-    s->timer.base = base;
     s->timer.timer = qemu_new_timer(vm_clock, omap_timer_tick, &s->timer);
     omap_wd_timer_reset(s);
     omap_timer_clk_setup(&s->timer);
 
     iomemtype = cpu_register_io_memory(0, omap_wd_timer_readfn,
                     omap_wd_timer_writefn, s);
-    cpu_register_physical_memory(s->timer.base, 0x100, iomemtype);
+    cpu_register_physical_memory(base, 0x100, iomemtype);
 
     return s;
 }
@@ -1061,14 +1120,13 @@ struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
 
     s->timer.irq = irq;
     s->timer.clk = clk;
-    s->timer.base = base;
     s->timer.timer = qemu_new_timer(vm_clock, omap_timer_tick, &s->timer);
     omap_os_timer_reset(s);
     omap_timer_clk_setup(&s->timer);
 
     iomemtype = cpu_register_io_memory(0, omap_os_timer_readfn,
                     omap_os_timer_writefn, s);
-    cpu_register_physical_memory(s->timer.base, 0x800, iomemtype);
+    cpu_register_physical_memory(base, 0x800, iomemtype);
 
     return s;
 }
@@ -1077,13 +1135,12 @@ struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
 static uint32_t omap_ulpd_pm_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    int offset = addr - s->ulpd_pm_base;
     uint16_t ret;
 
-    switch (offset) {
+    switch (addr) {
     case 0x14: /* IT_STATUS */
-        ret = s->ulpd_pm_regs[offset >> 2];
-        s->ulpd_pm_regs[offset >> 2] = 0;
+        ret = s->ulpd_pm_regs[addr >> 2];
+        s->ulpd_pm_regs[addr >> 2] = 0;
         qemu_irq_lower(s->irq[1][OMAP_INT_GAUGE_32K]);
         return ret;
 
@@ -1108,7 +1165,7 @@ static uint32_t omap_ulpd_pm_read(void *opaque, target_phys_addr_t addr)
     case 0x48: /* LOCL_TIME */
     case 0x4c: /* APLL_CTRL */
     case 0x50: /* POWER_CTRL */
-        return s->ulpd_pm_regs[offset >> 2];
+        return s->ulpd_pm_regs[addr >> 2];
     }
 
     OMAP_BAD_REG(addr);
@@ -1141,13 +1198,12 @@ static void omap_ulpd_pm_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    int offset = addr - s->ulpd_pm_base;
     int64_t now, ticks;
     int div, mult;
     static const int bypass_div[4] = { 1, 2, 4, 4 };
     uint16_t diff;
 
-    switch (offset) {
+    switch (addr) {
     case 0x00: /* COUNTER_32_LSB */
     case 0x04: /* COUNTER_32_MSB */
     case 0x08: /* COUNTER_HIGH_FREQ_LSB */
@@ -1159,7 +1215,7 @@ static void omap_ulpd_pm_write(void *opaque, target_phys_addr_t addr,
 
     case 0x10: /* GAUGING_CTRL */
         /* Bits 0 and 1 seem to be confused in the OMAP 310 TRM */
-        if ((s->ulpd_pm_regs[offset >> 2] ^ value) & 1) {
+        if ((s->ulpd_pm_regs[addr >> 2] ^ value) & 1) {
             now = qemu_get_clock(vm_clock);
 
             if (value & 1)
@@ -1185,7 +1241,7 @@ static void omap_ulpd_pm_write(void *opaque, target_phys_addr_t addr,
                 qemu_irq_raise(s->irq[1][OMAP_INT_GAUGE_32K]);
             }
         }
-        s->ulpd_pm_regs[offset >> 2] = value;
+        s->ulpd_pm_regs[addr >> 2] = value;
         break;
 
     case 0x18: /* Reserved */
@@ -1198,18 +1254,18 @@ static void omap_ulpd_pm_write(void *opaque, target_phys_addr_t addr,
     case 0x38: /* COUNTER_32_FIQ */
     case 0x48: /* LOCL_TIME */
     case 0x50: /* POWER_CTRL */
-        s->ulpd_pm_regs[offset >> 2] = value;
+        s->ulpd_pm_regs[addr >> 2] = value;
         break;
 
     case 0x30: /* CLOCK_CTRL */
-        diff = s->ulpd_pm_regs[offset >> 2] ^ value;
-        s->ulpd_pm_regs[offset >> 2] = value & 0x3f;
+        diff = s->ulpd_pm_regs[addr >> 2] ^ value;
+        s->ulpd_pm_regs[addr >> 2] = value & 0x3f;
         omap_ulpd_clk_update(s, diff, value);
         break;
 
     case 0x34: /* SOFT_REQ */
-        diff = s->ulpd_pm_regs[offset >> 2] ^ value;
-        s->ulpd_pm_regs[offset >> 2] = value & 0x1f;
+        diff = s->ulpd_pm_regs[addr >> 2] ^ value;
+        s->ulpd_pm_regs[addr >> 2] = value & 0x1f;
         omap_ulpd_req_update(s, diff, value);
         break;
 
@@ -1218,8 +1274,8 @@ static void omap_ulpd_pm_write(void *opaque, target_phys_addr_t addr,
          * omitted altogether, probably a typo.  */
         /* This register has identical semantics with DPLL(1:3) control
          * registers, see omap_dpll_write() */
-        diff = s->ulpd_pm_regs[offset >> 2] & value;
-        s->ulpd_pm_regs[offset >> 2] = value & 0x2fff;
+        diff = s->ulpd_pm_regs[addr >> 2] & value;
+        s->ulpd_pm_regs[addr >> 2] = value & 0x2fff;
         if (diff & (0x3ff << 2)) {
             if (value & (1 << 4)) {                    /* PLL_ENABLE */
                 div = ((value >> 5) & 3) + 1;          /* PLL_DIV */
@@ -1232,17 +1288,17 @@ static void omap_ulpd_pm_write(void *opaque, target_phys_addr_t addr,
         }
 
         /* Enter the desired mode.  */
-        s->ulpd_pm_regs[offset >> 2] =
-                (s->ulpd_pm_regs[offset >> 2] & 0xfffe) |
-                ((s->ulpd_pm_regs[offset >> 2] >> 4) & 1);
+        s->ulpd_pm_regs[addr >> 2] =
+                (s->ulpd_pm_regs[addr >> 2] & 0xfffe) |
+                ((s->ulpd_pm_regs[addr >> 2] >> 4) & 1);
 
         /* Act as if the lock is restored.  */
-        s->ulpd_pm_regs[offset >> 2] |= 2;
+        s->ulpd_pm_regs[addr >> 2] |= 2;
         break;
 
     case 0x4c: /* APLL_CTRL */
-        diff = s->ulpd_pm_regs[offset >> 2] & value;
-        s->ulpd_pm_regs[offset >> 2] = value & 0xf;
+        diff = s->ulpd_pm_regs[addr >> 2] & value;
+        s->ulpd_pm_regs[addr >> 2] = value & 0xf;
         if (diff & (1 << 0))                           /* APLL_NDPLL_SWITCH */
             omap_clk_reparent(omap_findclk(s, "ck_48m"), omap_findclk(s,
                                     (value & (1 << 0)) ? "apll" : "dpll4"));
@@ -1298,8 +1354,7 @@ static void omap_ulpd_pm_init(target_phys_addr_t base,
     int iomemtype = cpu_register_io_memory(0, omap_ulpd_pm_readfn,
                     omap_ulpd_pm_writefn, mpu);
 
-    mpu->ulpd_pm_base = base;
-    cpu_register_physical_memory(mpu->ulpd_pm_base, 0x800, iomemtype);
+    cpu_register_physical_memory(base, 0x800, iomemtype);
     omap_ulpd_pm_reset(mpu);
 }
 
@@ -1307,13 +1362,12 @@ static void omap_ulpd_pm_init(target_phys_addr_t base,
 static uint32_t omap_pin_cfg_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    int offset = addr - s->pin_cfg_base;
 
-    switch (offset) {
+    switch (addr) {
     case 0x00: /* FUNC_MUX_CTRL_0 */
     case 0x04: /* FUNC_MUX_CTRL_1 */
     case 0x08: /* FUNC_MUX_CTRL_2 */
-        return s->func_mux_ctrl[offset >> 2];
+        return s->func_mux_ctrl[addr >> 2];
 
     case 0x0c: /* COMP_MODE_CTRL_0 */
         return s->comp_mode_ctrl[0];
@@ -1329,13 +1383,13 @@ static uint32_t omap_pin_cfg_read(void *opaque, target_phys_addr_t addr)
     case 0x30: /* FUNC_MUX_CTRL_B */
     case 0x34: /* FUNC_MUX_CTRL_C */
     case 0x38: /* FUNC_MUX_CTRL_D */
-        return s->func_mux_ctrl[(offset >> 2) - 1];
+        return s->func_mux_ctrl[(addr >> 2) - 1];
 
     case 0x40: /* PULL_DWN_CTRL_0 */
     case 0x44: /* PULL_DWN_CTRL_1 */
     case 0x48: /* PULL_DWN_CTRL_2 */
     case 0x4c: /* PULL_DWN_CTRL_3 */
-        return s->pull_dwn_ctrl[(offset & 0xf) >> 2];
+        return s->pull_dwn_ctrl[(addr & 0xf) >> 2];
 
     case 0x50: /* GATE_INH_CTRL_0 */
         return s->gate_inh_ctrl[0];
@@ -1411,24 +1465,23 @@ static void omap_pin_cfg_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    int offset = addr - s->pin_cfg_base;
     uint32_t diff;
 
-    switch (offset) {
+    switch (addr) {
     case 0x00: /* FUNC_MUX_CTRL_0 */
-        diff = s->func_mux_ctrl[offset >> 2] ^ value;
-        s->func_mux_ctrl[offset >> 2] = value;
+        diff = s->func_mux_ctrl[addr >> 2] ^ value;
+        s->func_mux_ctrl[addr >> 2] = value;
         omap_pin_funcmux0_update(s, diff, value);
         return;
 
     case 0x04: /* FUNC_MUX_CTRL_1 */
-        diff = s->func_mux_ctrl[offset >> 2] ^ value;
-        s->func_mux_ctrl[offset >> 2] = value;
+        diff = s->func_mux_ctrl[addr >> 2] ^ value;
+        s->func_mux_ctrl[addr >> 2] = value;
         omap_pin_funcmux1_update(s, diff, value);
         return;
 
     case 0x08: /* FUNC_MUX_CTRL_2 */
-        s->func_mux_ctrl[offset >> 2] = value;
+        s->func_mux_ctrl[addr >> 2] = value;
         return;
 
     case 0x0c: /* COMP_MODE_CTRL_0 */
@@ -1449,14 +1502,14 @@ static void omap_pin_cfg_write(void *opaque, target_phys_addr_t addr,
     case 0x30: /* FUNC_MUX_CTRL_B */
     case 0x34: /* FUNC_MUX_CTRL_C */
     case 0x38: /* FUNC_MUX_CTRL_D */
-        s->func_mux_ctrl[(offset >> 2) - 1] = value;
+        s->func_mux_ctrl[(addr >> 2) - 1] = value;
         return;
 
     case 0x40: /* PULL_DWN_CTRL_0 */
     case 0x44: /* PULL_DWN_CTRL_1 */
     case 0x48: /* PULL_DWN_CTRL_2 */
     case 0x4c: /* PULL_DWN_CTRL_3 */
-        s->pull_dwn_ctrl[(offset & 0xf) >> 2] = value;
+        s->pull_dwn_ctrl[(addr & 0xf) >> 2] = value;
         return;
 
     case 0x50: /* GATE_INH_CTRL_0 */
@@ -1516,8 +1569,7 @@ static void omap_pin_cfg_init(target_phys_addr_t base,
     int iomemtype = cpu_register_io_memory(0, omap_pin_cfg_readfn,
                     omap_pin_cfg_writefn, mpu);
 
-    mpu->pin_cfg_base = base;
-    cpu_register_physical_memory(mpu->pin_cfg_base, 0x800, iomemtype);
+    cpu_register_physical_memory(base, 0x800, iomemtype);
     omap_pin_cfg_reset(mpu);
 }
 
@@ -1544,7 +1596,7 @@ static uint32_t omap_id_read(void *opaque, target_phys_addr_t addr)
         case omap1510:
             return 0x03310115;
         default:
-            cpu_abort(cpu_single_env, "%s: bad mpu model\n", __FUNCTION__);
+            hw_error("%s: bad mpu model\n", __FUNCTION__);
         }
         break;
 
@@ -1555,7 +1607,7 @@ static uint32_t omap_id_read(void *opaque, target_phys_addr_t addr)
         case omap1510:
             return 0xfb47002f;
         default:
-            cpu_abort(cpu_single_env, "%s: bad mpu model\n", __FUNCTION__);
+            hw_error("%s: bad mpu model\n", __FUNCTION__);
         }
         break;
     }
@@ -1586,19 +1638,18 @@ static void omap_id_init(struct omap_mpu_state_s *mpu)
 {
     int iomemtype = cpu_register_io_memory(0, omap_id_readfn,
                     omap_id_writefn, mpu);
-    cpu_register_physical_memory(0xfffe1800, 0x800, iomemtype);
-    cpu_register_physical_memory(0xfffed400, 0x100, iomemtype);
+    cpu_register_physical_memory_offset(0xfffe1800, 0x800, iomemtype, 0xfffe1800);
+    cpu_register_physical_memory_offset(0xfffed400, 0x100, iomemtype, 0xfffed400);
     if (!cpu_is_omap15xx(mpu))
-        cpu_register_physical_memory(0xfffe2000, 0x800, iomemtype);
+        cpu_register_physical_memory_offset(0xfffe2000, 0x800, iomemtype, 0xfffe2000);
 }
 
 /* MPUI Control (Dummy) */
 static uint32_t omap_mpui_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    int offset = addr - s->mpui_base;
 
-    switch (offset) {
+    switch (addr) {
     case 0x00: /* CTRL */
         return s->mpui_ctrl;
     case 0x04: /* DEBUG_ADDR */
@@ -1626,9 +1677,8 @@ static void omap_mpui_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    int offset = addr - s->mpui_base;
 
-    switch (offset) {
+    switch (addr) {
     case 0x00: /* CTRL */
         s->mpui_ctrl = value & 0x007fffff;
         break;
@@ -1672,15 +1722,13 @@ static void omap_mpui_init(target_phys_addr_t base,
     int iomemtype = cpu_register_io_memory(0, omap_mpui_readfn,
                     omap_mpui_writefn, mpu);
 
-    mpu->mpui_base = base;
-    cpu_register_physical_memory(mpu->mpui_base, 0x100, iomemtype);
+    cpu_register_physical_memory(base, 0x100, iomemtype);
 
     omap_mpui_reset(mpu);
 }
 
 /* TIPB Bridges */
 struct omap_tipb_bridge_s {
-    target_phys_addr_t base;
     qemu_irq abort;
 
     int width_intr;
@@ -1693,9 +1741,8 @@ struct omap_tipb_bridge_s {
 static uint32_t omap_tipb_bridge_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
-    int offset = addr - s->base;
 
-    switch (offset) {
+    switch (addr) {
     case 0x00: /* TIPB_CNTL */
         return s->control;
     case 0x04: /* TIPB_BUS_ALLOC */
@@ -1720,9 +1767,8 @@ static void omap_tipb_bridge_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
-    int offset = addr - s->base;
 
-    switch (offset) {
+    switch (addr) {
     case 0x00: /* TIPB_CNTL */
         s->control = value & 0xffff;
         break;
@@ -1780,12 +1826,11 @@ struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base,
             qemu_mallocz(sizeof(struct omap_tipb_bridge_s));
 
     s->abort = abort_irq;
-    s->base = base;
     omap_tipb_bridge_reset(s);
 
     iomemtype = cpu_register_io_memory(0, omap_tipb_bridge_readfn,
                     omap_tipb_bridge_writefn, s);
-    cpu_register_physical_memory(s->base, 0x100, iomemtype);
+    cpu_register_physical_memory(base, 0x100, iomemtype);
 
     return s;
 }
@@ -1794,10 +1839,9 @@ struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base,
 static uint32_t omap_tcmi_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    int offset = addr - s->tcmi_base;
     uint32_t ret;
 
-    switch (offset) {
+    switch (addr) {
     case 0x00: /* IMIF_PRIO */
     case 0x04: /* EMIFS_PRIO */
     case 0x08: /* EMIFF_PRIO */
@@ -1812,11 +1856,11 @@ static uint32_t omap_tcmi_read(void *opaque, target_phys_addr_t addr)
     case 0x30: /* TIMEOUT3 */
     case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */
     case 0x40: /* EMIFS_CFG_DYN_WAIT */
-        return s->tcmi_regs[offset >> 2];
+        return s->tcmi_regs[addr >> 2];
 
     case 0x20: /* EMIFF_SDRAM_CONFIG */
-        ret = s->tcmi_regs[offset >> 2];
-        s->tcmi_regs[offset >> 2] &= ~1; /* XXX: Clear SLRF on SDRAM access */
+        ret = s->tcmi_regs[addr >> 2];
+        s->tcmi_regs[addr >> 2] &= ~1; /* XXX: Clear SLRF on SDRAM access */
         /* XXX: We can try using the VGA_DIRTY flag for this */
         return ret;
     }
@@ -1829,9 +1873,8 @@ static void omap_tcmi_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    int offset = addr - s->tcmi_base;
 
-    switch (offset) {
+    switch (addr) {
     case 0x00: /* IMIF_PRIO */
     case 0x04: /* EMIFS_PRIO */
     case 0x08: /* EMIFF_PRIO */
@@ -1846,10 +1889,10 @@ static void omap_tcmi_write(void *opaque, target_phys_addr_t addr,
     case 0x30: /* TIMEOUT3 */
     case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */
     case 0x40: /* EMIFS_CFG_DYN_WAIT */
-        s->tcmi_regs[offset >> 2] = value;
+        s->tcmi_regs[addr >> 2] = value;
         break;
     case 0x0c: /* EMIFS_CONFIG */
-        s->tcmi_regs[offset >> 2] = (value & 0xf) | (1 << 4);
+        s->tcmi_regs[addr >> 2] = (value & 0xf) | (1 << 4);
         break;
 
     default:
@@ -1894,8 +1937,7 @@ static void omap_tcmi_init(target_phys_addr_t base,
     int iomemtype = cpu_register_io_memory(0, omap_tcmi_readfn,
                     omap_tcmi_writefn, mpu);
 
-    mpu->tcmi_base = base;
-    cpu_register_physical_memory(mpu->tcmi_base, 0x100, iomemtype);
+    cpu_register_physical_memory(base, 0x100, iomemtype);
     omap_tcmi_reset(mpu);
 }
 
@@ -1903,9 +1945,8 @@ static void omap_tcmi_init(target_phys_addr_t base,
 static uint32_t omap_dpll_read(void *opaque, target_phys_addr_t addr)
 {
     struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
-    int offset = addr - s->base;
 
-    if (offset == 0x00)        /* CTL_REG */
+    if (addr == 0x00)  /* CTL_REG */
         return s->mode;
 
     OMAP_BAD_REG(addr);
@@ -1917,11 +1958,10 @@ static void omap_dpll_write(void *opaque, target_phys_addr_t addr,
 {
     struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
     uint16_t diff;
-    int offset = addr - s->base;
     static const int bypass_div[4] = { 1, 2, 4, 4 };
     int div, mult;
 
-    if (offset == 0x00) {      /* CTL_REG */
+    if (addr == 0x00) {        /* CTL_REG */
         /* See omap_ulpd_pm_write() too */
         diff = s->mode & value;
         s->mode = value & 0x2fff;
@@ -1970,18 +2010,19 @@ static void omap_dpll_init(struct dpll_ctl_s *s, target_phys_addr_t base,
     int iomemtype = cpu_register_io_memory(0, omap_dpll_readfn,
                     omap_dpll_writefn, s);
 
-    s->base = base;
     s->dpll = clk;
     omap_dpll_reset(s);
 
-    cpu_register_physical_memory(s->base, 0x100, iomemtype);
+    cpu_register_physical_memory(base, 0x100, iomemtype);
 }
 
 /* UARTs */
 struct omap_uart_s {
+    target_phys_addr_t base;
     SerialState *serial; /* TODO */
     struct omap_target_agent_s *ta;
-    target_phys_addr_t base;
+    omap_clk fclk;
+    qemu_irq irq;
 
     uint8_t eblr;
     uint8_t syscontrol;
@@ -1989,14 +2030,49 @@ struct omap_uart_s {
     uint8_t cfps;
     uint8_t mdr[2];
     uint8_t scr;
+    uint8_t clksel;
 };
 
+static void omap_uart_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap_uart_s *s = (struct omap_uart_s *)opaque;
+    
+    qemu_put_byte(f, s->eblr);
+    qemu_put_byte(f, s->syscontrol);
+    qemu_put_byte(f, s->wkup);
+    qemu_put_byte(f, s->cfps);
+    qemu_put_byte(f, s->mdr[0]);
+    qemu_put_byte(f, s->mdr[1]);
+    qemu_put_byte(f, s->scr);
+    qemu_put_byte(f, s->clksel);
+}
+
+static int omap_uart_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap_uart_s *s = (struct omap_uart_s *)opaque;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    s->eblr = qemu_get_byte(f);
+    s->syscontrol = qemu_get_byte(f);
+    s->wkup = qemu_get_byte(f);
+    s->cfps = qemu_get_byte(f);
+    s->mdr[0] = qemu_get_byte(f);
+    s->mdr[1] = qemu_get_byte(f);
+    s->scr = qemu_get_byte(f);
+    s->clksel = qemu_get_byte(f);
+    
+    return  0;
+}
+
 void omap_uart_reset(struct omap_uart_s *s)
 {
     s->eblr = 0x00;
     s->syscontrol = 0;
     s->wkup = 0x3f;
     s->cfps = 0x69;
+    s->clksel = 0;
 }
 
 struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
@@ -2006,17 +2082,23 @@ struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
     struct omap_uart_s *s = (struct omap_uart_s *)
             qemu_mallocz(sizeof(struct omap_uart_s));
 
-    s->serial = serial_mm_init(base, 2, irq, chr ?: qemu_chr_open("null"), 1);
+    s->base = base;
+    s->fclk = fclk;
+    s->irq = irq;
+    s->serial = serial_mm_init(base, 2, irq, omap_clk_getrate(fclk)/16,
+                               chr ?: qemu_chr_open("null", "null", NULL), 1);
 
+    register_savevm("omap_uart", base >> 8, 0,
+                    omap_uart_save_state, omap_uart_load_state, s);
     return s;
 }
 
 static uint32_t omap_uart_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_uart_s *s = (struct omap_uart_s *) opaque;
-    int offset = addr - s->base;
 
-    switch (offset) {
+    addr &= 0xff;
+    switch (addr) {
     case 0x20: /* MDR1 */
         return s->mdr[0];
     case 0x24: /* MDR2 */
@@ -2025,17 +2107,19 @@ static uint32_t omap_uart_read(void *opaque, target_phys_addr_t addr)
         return s->scr;
     case 0x44: /* SSR */
         return 0x0;
-    case 0x48: /* EBLR */
+    case 0x48: /* EBLR (OMAP2) */
         return s->eblr;
+    case 0x4C: /* OSC_12M_SEL (OMAP1) */
+        return s->clksel;
     case 0x50: /* MVR */
         return 0x30;
-    case 0x54: /* SYSC */
+    case 0x54: /* SYSC (OMAP2) */
         return s->syscontrol;
-    case 0x58: /* SYSS */
+    case 0x58: /* SYSS (OMAP2) */
         return 1;
-    case 0x5c: /* WER */
+    case 0x5c: /* WER (OMAP2) */
         return s->wkup;
-    case 0x60: /* CFPS */
+    case 0x60: /* CFPS (OMAP2) */
         return s->cfps;
     }
 
@@ -2047,9 +2131,9 @@ static void omap_uart_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     struct omap_uart_s *s = (struct omap_uart_s *) opaque;
-    int offset = addr - s->base;
 
-    switch (offset) {
+    addr &= 0xff;
+    switch (addr) {
     case 0x20: /* MDR1 */
         s->mdr[0] = value & 0x7f;
         break;
@@ -2059,23 +2143,26 @@ static void omap_uart_write(void *opaque, target_phys_addr_t addr,
     case 0x40: /* SCR */
         s->scr = value & 0xff;
         break;
-    case 0x48: /* EBLR */
+    case 0x48: /* EBLR (OMAP2) */
         s->eblr = value & 0xff;
         break;
+    case 0x4C: /* OSC_12M_SEL (OMAP1) */
+        s->clksel = value & 1;
+        break;
     case 0x44: /* SSR */
     case 0x50: /* MVR */
-    case 0x58: /* SYSS */
+    case 0x58: /* SYSS (OMAP2) */
         OMAP_RO_REG(addr);
         break;
-    case 0x54: /* SYSC */
+    case 0x54: /* SYSC (OMAP2) */
         s->syscontrol = value & 0x1d;
         if (value & 2)
             omap_uart_reset(s);
         break;
-    case 0x5c: /* WER */
+    case 0x5c: /* WER (OMAP2) */
         s->wkup = value & 0x7f;
         break;
-    case 0x60: /* CFPS */
+    case 0x60: /* CFPS (OMAP2) */
         s->cfps = value & 0xff;
         break;
     default:
@@ -2106,20 +2193,29 @@ struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
                     omap_uart_writefn, s);
 
     s->ta = ta;
-    s->base = base;
 
-    cpu_register_physical_memory(s->base + 0x20, 0x100, iomemtype);
+    cpu_register_physical_memory(base + 0x20, 0x100, iomemtype);
 
     return s;
 }
 
+void omap_uart_attach(struct omap_uart_s *s, CharDriverState *chr)
+{
+    /* TODO: Should reuse or destroy current s->serial */
+    fprintf(stderr, "%s: WARNING - this function is broken, avoid using it\n",
+            __FUNCTION__);
+    s->serial = serial_mm_init(s->base, 2, s->irq,
+                               omap_clk_getrate(s->fclk) / 16,
+                               chr ?: qemu_chr_open("null", "null", NULL),
+                               1);
+}
+
 /* MPU Clock/Reset/Power Mode Control */
 static uint32_t omap_clkm_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    int offset = addr - s->clkm.mpu_base;
 
-    switch (offset) {
+    switch (addr) {
     case 0x00: /* ARM_CKCTL */
         return s->clkm.arm_ckctl;
 
@@ -2315,7 +2411,6 @@ static void omap_clkm_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    int offset = addr - s->clkm.mpu_base;
     uint16_t diff;
     omap_clk clk;
     static const char *clkschemename[8] = {
@@ -2323,7 +2418,7 @@ static void omap_clkm_write(void *opaque, target_phys_addr_t addr,
         "mix mode 1", "mix mode 2", "bypass mode", "mix mode 3", "mix mode 4",
     };
 
-    switch (offset) {
+    switch (addr) {
     case 0x00: /* ARM_CKCTL */
         diff = s->clkm.arm_ckctl ^ value;
         s->clkm.arm_ckctl = value & 0x7fff;
@@ -2405,9 +2500,8 @@ static CPUWriteMemoryFunc *omap_clkm_writefn[] = {
 static uint32_t omap_clkdsp_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    int offset = addr - s->clkm.dsp_base;
 
-    switch (offset) {
+    switch (addr) {
     case 0x04: /* DSP_IDLECT1 */
         return s->clkm.dsp_idlect1;
 
@@ -2446,10 +2540,9 @@ static void omap_clkdsp_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    int offset = addr - s->clkm.dsp_base;
     uint16_t diff;
 
-    switch (offset) {
+    switch (addr) {
     case 0x04: /* DSP_IDLECT1 */
         diff = s->clkm.dsp_idlect1 ^ value;
         s->clkm.dsp_idlect1 = value & 0x01f7;
@@ -2518,21 +2611,18 @@ static void omap_clkm_init(target_phys_addr_t mpu_base,
         cpu_register_io_memory(0, omap_clkdsp_readfn, omap_clkdsp_writefn, s),
     };
 
-    s->clkm.mpu_base = mpu_base;
-    s->clkm.dsp_base = dsp_base;
     s->clkm.arm_idlect1 = 0x03ff;
     s->clkm.arm_idlect2 = 0x0100;
     s->clkm.dsp_idlect1 = 0x0002;
     omap_clkm_reset(s);
     s->clkm.cold_start = 0x3a;
 
-    cpu_register_physical_memory(s->clkm.mpu_base, 0x100, iomemtype[0]);
-    cpu_register_physical_memory(s->clkm.dsp_base, 0x1000, iomemtype[1]);
+    cpu_register_physical_memory(mpu_base, 0x100, iomemtype[0]);
+    cpu_register_physical_memory(dsp_base, 0x1000, iomemtype[1]);
 }
 
 /* MPU I/O */
 struct omap_mpuio_s {
-    target_phys_addr_t base;
     qemu_irq irq;
     qemu_irq kbd_irq;
     qemu_irq *in;
@@ -2765,7 +2855,6 @@ struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base,
     struct omap_mpuio_s *s = (struct omap_mpuio_s *)
             qemu_mallocz(sizeof(struct omap_mpuio_s));
 
-    s->base = base;
     s->irq = gpio_int;
     s->kbd_irq = kbd_int;
     s->wakeup = wakeup;
@@ -2774,7 +2863,7 @@ struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base,
 
     iomemtype = cpu_register_io_memory(0, omap_mpuio_readfn,
                     omap_mpuio_writefn, s);
-    cpu_register_physical_memory(s->base, 0x800, iomemtype);
+    cpu_register_physical_memory(base, 0x800, iomemtype);
 
     omap_clk_adduser(clk, qemu_allocate_irqs(omap_mpuio_onoff, s, 1)[0]);
 
@@ -2789,15 +2878,14 @@ qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s)
 void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler)
 {
     if (line >= 16 || line < 0)
-        cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line);
+        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
     s->handler[line] = handler;
 }
 
 void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down)
 {
     if (row >= 5 || row < 0)
-        cpu_abort(cpu_single_env, "%s: No key %i-%i\n",
-                        __FUNCTION__, col, row);
+        hw_error("%s: No key %i-%i\n", __FUNCTION__, col, row);
 
     if (down)
         s->buttons[row] |= 1 << col;
@@ -2809,7 +2897,6 @@ void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down)
 
 /* General-Purpose I/O */
 struct omap_gpio_s {
-    target_phys_addr_t base;
     qemu_irq irq;
     qemu_irq *in;
     qemu_irq handler[16];
@@ -2966,14 +3053,13 @@ struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
     struct omap_gpio_s *s = (struct omap_gpio_s *)
             qemu_mallocz(sizeof(struct omap_gpio_s));
 
-    s->base = base;
     s->irq = irq;
     s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
     omap_gpio_reset(s);
 
     iomemtype = cpu_register_io_memory(0, omap_gpio_readfn,
                     omap_gpio_writefn, s);
-    cpu_register_physical_memory(s->base, 0x1000, iomemtype);
+    cpu_register_physical_memory(base, 0x1000, iomemtype);
 
     return s;
 }
@@ -2986,13 +3072,12 @@ qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
 void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
 {
     if (line >= 16 || line < 0)
-        cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line);
+        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
     s->handler[line] = handler;
 }
 
 /* MicroWire Interface */
 struct omap_uwire_s {
-    target_phys_addr_t base;
     qemu_irq txirq;
     qemu_irq rxirq;
     qemu_irq txdrq;
@@ -3002,13 +3087,13 @@ struct omap_uwire_s {
     uint16_t control;
     uint16_t setup[5];
 
-    struct uwire_slave_s *chip[4];
+    uWireSlave *chip[4];
 };
 
 static void omap_uwire_transfer_start(struct omap_uwire_s *s)
 {
     int chipselect = (s->control >> 10) & 3;           /* INDEX */
-    struct uwire_slave_s *slave = s->chip[chipselect];
+    uWireSlave *slave = s->chip[chipselect];
 
     if ((s->control >> 5) & 0x1f) {                    /* NB_BITS_WR */
         if (s->control & (1 << 12))                    /* CS_CMD */
@@ -3137,7 +3222,6 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
     struct omap_uwire_s *s = (struct omap_uwire_s *)
             qemu_mallocz(sizeof(struct omap_uwire_s));
 
-    s->base = base;
     s->txirq = irq[0];
     s->rxirq = irq[1];
     s->txdrq = dma;
@@ -3145,13 +3229,13 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
 
     iomemtype = cpu_register_io_memory(0, omap_uwire_readfn,
                     omap_uwire_writefn, s);
-    cpu_register_physical_memory(s->base, 0x800, iomemtype);
+    cpu_register_physical_memory(base, 0x800, iomemtype);
 
     return s;
 }
 
 void omap_uwire_attach(struct omap_uwire_s *s,
-                struct uwire_slave_s *slave, int chipselect)
+                uWireSlave *slave, int chipselect)
 {
     if (chipselect < 0 || chipselect > 3) {
         fprintf(stderr, "%s: Bad chipselect %i\n", __FUNCTION__, chipselect);
@@ -3346,7 +3430,6 @@ static void omap_pwt_init(target_phys_addr_t base, struct omap_mpu_state_s *s,
 
 /* Real-time Clock module */
 struct omap_rtc_s {
-    target_phys_addr_t base;
     qemu_irq irq;
     qemu_irq alarm;
     QEMUTimer *clk;
@@ -3374,7 +3457,7 @@ static void omap_rtc_interrupts_update(struct omap_rtc_s *s)
 
 static void omap_rtc_alarm_update(struct omap_rtc_s *s)
 {
-    s->alarm_ti = mktime(&s->alarm_tm);
+    s->alarm_ti = mktimegm(&s->alarm_tm);
     if (s->alarm_ti == -1)
         printf("%s: conversion failed\n", __FUNCTION__);
 }
@@ -3476,7 +3559,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
 
     switch (offset) {
     case 0x00: /* SECONDS_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("RTC SEC_REG <-- %02x\n", value);
 #endif
         s->ti -= s->current_tm.tm_sec;
@@ -3484,7 +3567,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
         return;
 
     case 0x04: /* MINUTES_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("RTC MIN_REG <-- %02x\n", value);
 #endif
         s->ti -= s->current_tm.tm_min * 60;
@@ -3492,7 +3575,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
         return;
 
     case 0x08: /* HOURS_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("RTC HRS_REG <-- %02x\n", value);
 #endif
         s->ti -= s->current_tm.tm_hour * 3600;
@@ -3504,7 +3587,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
         return;
 
     case 0x0c: /* DAYS_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("RTC DAY_REG <-- %02x\n", value);
 #endif
         s->ti -= s->current_tm.tm_mday * 86400;
@@ -3512,13 +3595,13 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
         return;
 
     case 0x10: /* MONTHS_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("RTC MTH_REG <-- %02x\n", value);
 #endif
         memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
         new_tm.tm_mon = omap_rtc_bin(value);
-        ti[0] = mktime(&s->current_tm);
-        ti[1] = mktime(&new_tm);
+        ti[0] = mktimegm(&s->current_tm);
+        ti[1] = mktimegm(&new_tm);
 
         if (ti[0] != -1 && ti[1] != -1) {
             s->ti -= ti[0];
@@ -3531,13 +3614,13 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
         return;
 
     case 0x14: /* YEARS_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("RTC YRS_REG <-- %02x\n", value);
 #endif
         memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
         new_tm.tm_year += omap_rtc_bin(value) - (new_tm.tm_year % 100);
-        ti[0] = mktime(&s->current_tm);
-        ti[1] = mktime(&new_tm);
+        ti[0] = mktimegm(&s->current_tm);
+        ti[1] = mktimegm(&new_tm);
 
         if (ti[0] != -1 && ti[1] != -1) {
             s->ti -= ti[0];
@@ -3553,7 +3636,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
         return;        /* Ignored */
 
     case 0x20: /* ALARM_SECONDS_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("ALM SEC_REG <-- %02x\n", value);
 #endif
         s->alarm_tm.tm_sec = omap_rtc_bin(value);
@@ -3561,7 +3644,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
         return;
 
     case 0x24: /* ALARM_MINUTES_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("ALM MIN_REG <-- %02x\n", value);
 #endif
         s->alarm_tm.tm_min = omap_rtc_bin(value);
@@ -3569,7 +3652,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
         return;
 
     case 0x28: /* ALARM_HOURS_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("ALM HRS_REG <-- %02x\n", value);
 #endif
         if (s->pm_am)
@@ -3582,7 +3665,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
         return;
 
     case 0x2c: /* ALARM_DAYS_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("ALM DAY_REG <-- %02x\n", value);
 #endif
         s->alarm_tm.tm_mday = omap_rtc_bin(value);
@@ -3590,7 +3673,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
         return;
 
     case 0x30: /* ALARM_MONTHS_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("ALM MON_REG <-- %02x\n", value);
 #endif
         s->alarm_tm.tm_mon = omap_rtc_bin(value);
@@ -3598,7 +3681,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
         return;
 
     case 0x34: /* ALARM_YEARS_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("ALM YRS_REG <-- %02x\n", value);
 #endif
         s->alarm_tm.tm_year = omap_rtc_bin(value);
@@ -3606,7 +3689,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
         return;
 
     case 0x40: /* RTC_CTRL_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("RTC CONTROL <-- %02x\n", value);
 #endif
         s->pm_am = (value >> 3) & 1;
@@ -3618,7 +3701,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
         return;
 
     case 0x44: /* RTC_STATUS_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("RTC STATUSL <-- %02x\n", value);
 #endif
         s->status &= ~((value & 0xc0) ^ 0x80);
@@ -3626,14 +3709,14 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
         return;
 
     case 0x48: /* RTC_INTERRUPTS_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("RTC INTRS <-- %02x\n", value);
 #endif
         s->interrupts = value;
         return;
 
     case 0x4c: /* RTC_COMP_LSB_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("RTC COMPLSB <-- %02x\n", value);
 #endif
         s->comp_reg &= 0xff00;
@@ -3641,7 +3724,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
         return;
 
     case 0x50: /* RTC_COMP_MSB_REG */
-#if ALMDEBUG
+#ifdef ALMDEBUG
         printf("RTC COMPMSB <-- %02x\n", value);
 #endif
         s->comp_reg &= 0x00ff;
@@ -3744,7 +3827,7 @@ static void omap_rtc_reset(struct omap_rtc_s *s)
     s->alarm_tm.tm_mday = 0x01;
     s->status = 1 << 7;
     qemu_get_timedate(&tm, 0);
-    s->ti = mktime(&tm);
+    s->ti = mktimegm(&tm);
 
     omap_rtc_alarm_update(s);
     omap_rtc_tick(s);
@@ -3757,7 +3840,6 @@ struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
     struct omap_rtc_s *s = (struct omap_rtc_s *)
             qemu_mallocz(sizeof(struct omap_rtc_s));
 
-    s->base = base;
     s->irq = irq[0];
     s->alarm = irq[1];
     s->clk = qemu_new_timer(rt_clock, omap_rtc_tick, s);
@@ -3766,14 +3848,13 @@ struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
 
     iomemtype = cpu_register_io_memory(0, omap_rtc_readfn,
                     omap_rtc_writefn, s);
-    cpu_register_physical_memory(s->base, 0x800, iomemtype);
+    cpu_register_physical_memory(base, 0x800, iomemtype);
 
     return s;
 }
 
 /* Multi-channel Buffered Serial Port interfaces */
 struct omap_mcbsp_s {
-    target_phys_addr_t base;
     qemu_irq txirq;
     qemu_irq rxirq;
     qemu_irq txdrq;
@@ -3792,7 +3873,7 @@ struct omap_mcbsp_s {
     int tx_req;
     int rx_req;
 
-    struct i2s_codec_s *codec;
+    I2SCodec *codec;
     QEMUTimer *source_timer;
     QEMUTimer *sink_timer;
 };
@@ -4277,7 +4358,6 @@ struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base,
     struct omap_mcbsp_s *s = (struct omap_mcbsp_s *)
             qemu_mallocz(sizeof(struct omap_mcbsp_s));
 
-    s->base = base;
     s->txirq = irq[0];
     s->rxirq = irq[1];
     s->txdrq = dma[0];
@@ -4288,7 +4368,7 @@ struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base,
 
     iomemtype = cpu_register_io_memory(0, omap_mcbsp_readfn,
                     omap_mcbsp_writefn, s);
-    cpu_register_physical_memory(s->base, 0x800, iomemtype);
+    cpu_register_physical_memory(base, 0x800, iomemtype);
 
     return s;
 }
@@ -4313,7 +4393,7 @@ static void omap_mcbsp_i2s_start(void *opaque, int line, int level)
     }
 }
 
-void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave)
+void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, I2SCodec *slave)
 {
     s->codec = slave;
     slave->rx_swallow = qemu_allocate_irqs(omap_mcbsp_i2s_swallow, s, 1)[0];
@@ -4322,7 +4402,6 @@ void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave)
 
 /* LED Pulse Generators */
 struct omap_lpg_s {
-    target_phys_addr_t base;
     QEMUTimer *tm;
 
     uint8_t control;
@@ -4455,14 +4534,13 @@ struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk)
     struct omap_lpg_s *s = (struct omap_lpg_s *)
             qemu_mallocz(sizeof(struct omap_lpg_s));
 
-    s->base = base;
     s->tm = qemu_new_timer(rt_clock, omap_lpg_tick, s);
 
     omap_lpg_reset(s);
 
     iomemtype = cpu_register_io_memory(0, omap_lpg_readfn,
                     omap_lpg_writefn, s);
-    cpu_register_physical_memory(s->base, 0x800, iomemtype);
+    cpu_register_physical_memory(base, 0x800, iomemtype);
 
     omap_clk_adduser(clk, qemu_allocate_irqs(omap_lpg_clk_update, s, 1)[0]);
 
@@ -4646,7 +4724,7 @@ static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s,
 }
 
 struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
-                DisplayState *ds, const char *core)
+                const char *core)
 {
     int i;
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
@@ -4703,6 +4781,12 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
     s->port[local    ].addr_valid = omap_validate_local_addr;
     s->port[tipb_mpui].addr_valid = omap_validate_tipb_mpui_addr;
 
+    /* Register SDRAM and SRAM DMA ports for fast transfers.  */
+    soc_dma_port_add_mem_ram(s->dma,
+                    emiff_base, OMAP_EMIFF_BASE, s->sdram_size);
+    soc_dma_port_add_mem_ram(s->dma,
+                    imif_base, OMAP_IMIF_BASE, s->sram_size);
+
     s->timer[0] = omap_mpu_timer_init(0xfffec500,
                     s->irq[0][OMAP_INT_TIMER1],
                     omap_findclk(s, "mputim_ck"));
@@ -4722,7 +4806,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
                     omap_findclk(s, "clk32-kHz"));
 
     s->lcd = omap_lcdc_init(0xfffec000, s->irq[0][OMAP_INT_LCD_CTRL],
-                    omap_dma_get_lcdch(s->dma), ds, imif_base, emiff_base,
+                    omap_dma_get_lcdch(s->dma), imif_base, emiff_base,
                     omap_findclk(s, "lcd_ck"));
 
     omap_ulpd_pm_init(0xfffe0800, s);
@@ -4750,7 +4834,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
                     omap_findclk(s, "uart2_ck"),
                     s->drq[OMAP_DMA_UART2_TX], s->drq[OMAP_DMA_UART2_RX],
                     serial_hds[0] ? serial_hds[1] : 0);
-    s->uart[2] = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3],
+    s->uart[2] = omap_uart_init(0xfffb9800, s->irq[0][OMAP_INT_UART3],
                     omap_findclk(s, "uart3_ck"),
                     omap_findclk(s, "uart3_ck"),
                     s->drq[OMAP_DMA_UART3_TX], s->drq[OMAP_DMA_UART3_RX],
@@ -4816,7 +4900,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
     omap_setup_dsp_mapping(omap15xx_dsp_mm);
     omap_setup_mpui_io(s);
 
-    qemu_register_reset(omap1_mpu_reset, s);
+    qemu_register_reset(omap1_mpu_reset, 0, s);
 
     return s;
 }