Merge commit 'gnu/master' into test
[qemu] / hw / omap1.c
index 0c3b5cd..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"
@@ -95,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];
@@ -202,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];
@@ -280,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;
@@ -409,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)
@@ -420,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)
@@ -430,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;
 
@@ -452,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;
@@ -516,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;
 
@@ -628,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)
@@ -638,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);
@@ -651,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;
 }
 
@@ -660,7 +721,6 @@ 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;
@@ -757,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;
 
@@ -778,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;
@@ -836,7 +894,6 @@ 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);
@@ -844,7 +901,7 @@ struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
 
     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;
 }
@@ -861,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);
@@ -883,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;
@@ -963,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;
 }
@@ -1066,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;
 }
@@ -1082,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;
 
@@ -1113,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);
@@ -1146,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 */
@@ -1164,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)
@@ -1190,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 */
@@ -1203,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;
 
@@ -1223,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 */
@@ -1237,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"));
@@ -1303,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);
 }
 
@@ -1312,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];
@@ -1334,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];
@@ -1416,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 */
@@ -1454,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 */
@@ -1521,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);
 }
 
@@ -1549,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;
 
@@ -1560,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;
     }
@@ -1591,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 */
@@ -1631,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;
@@ -1677,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;
@@ -1698,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 */
@@ -1725,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;
@@ -1785,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;
 }
@@ -1799,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 */
@@ -1817,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;
     }
@@ -1834,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 */
@@ -1851,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:
@@ -1899,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);
 }
 
@@ -1908,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);
@@ -1922,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;
@@ -1975,18 +2010,17 @@ 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;
 
@@ -1996,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,
@@ -2017,17 +2086,19 @@ struct omap_uart_s *omap_uart_init(target_phys_addr_t 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"), 1);
+                               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 */
@@ -2036,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;
     }
 
@@ -2058,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;
@@ -2070,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:
@@ -2118,7 +2194,7 @@ struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
 
     s->ta = ta;
 
-    cpu_register_physical_memory(s->base + 0x20, 0x100, iomemtype);
+    cpu_register_physical_memory(base + 0x20, 0x100, iomemtype);
 
     return s;
 }
@@ -2126,18 +2202,20 @@ struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
 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"), 1);
+                               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;
 
@@ -2333,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] = {
@@ -2341,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;
@@ -2423,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;
 
@@ -2464,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;
@@ -2536,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;
@@ -2783,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;
@@ -2792,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]);
 
@@ -2807,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;
@@ -2827,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];
@@ -2984,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;
 }
@@ -3004,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;
@@ -3020,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 */
@@ -3155,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;
@@ -3163,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);
@@ -3364,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;
@@ -3392,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__);
 }
@@ -3535,8 +3600,8 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
 #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];
@@ -3554,8 +3619,8 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
 #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];
@@ -3762,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);
@@ -3775,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);
@@ -3784,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;
@@ -3810,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;
 };
@@ -4295,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];
@@ -4306,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;
 }
@@ -4331,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];
@@ -4340,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;
@@ -4473,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]);
 
@@ -4664,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 *)
@@ -4746,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);
@@ -4774,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],
@@ -4840,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;
 }