add savevm support in several modules
authorJuha Riihimäki <juhriihi@LX9900438.local>
Thu, 19 Mar 2009 08:40:38 +0000 (10:40 +0200)
committerJuha Riihimäki <juhriihi@LX9900438.local>
Thu, 19 Mar 2009 08:40:38 +0000 (10:40 +0200)
hw/omap1.c
hw/omap2.c
hw/omap3.c
hw/omap3_mmc.c
hw/omap_dma.c
hw/omap_dss.c
hw/omap_i2c.c
hw/sd.c
hw/soc_dma.c

index 9d065cd..0c9123b 100644 (file)
@@ -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)
@@ -430,6 +487,8 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
                     omap_inth_writefn, s);
     cpu_register_physical_memory(base, size, iomemtype);
 
+    register_savevm("omap_inth", -1, 0,
+                    omap_inth_save_state, omap_inth_load_state, s);
     return s;
 }
 
@@ -653,6 +712,8 @@ struct omap_intr_handler_s *omap2_inth_init(
                     omap2_inth_writefn, s);
     cpu_register_physical_memory(base, size, iomemtype);
 
+    register_savevm("omap_inth", -1, 0,
+                    omap_inth_save_state, omap_inth_load_state, s);
     return s;
 }
 
@@ -1972,6 +2033,39 @@ struct omap_uart_s {
     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;
@@ -1994,6 +2088,8 @@ struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
     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;
 }
 
index 00fe864..91abefe 100644 (file)
@@ -489,6 +489,89 @@ static CPUWriteMemoryFunc *omap_gp_timer_writefn[] = {
     omap_gp_timer_write,
 };
 
+static void omap_gp_timer_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *)opaque;
+    
+    qemu_put_timer(f, s->timer);
+    qemu_put_timer(f, s->match);
+    qemu_put_sbe32(f, s->in_val);
+    qemu_put_sbe32(f, s->out_val);
+    qemu_put_sbe64(f, s->time);
+    qemu_put_sbe64(f, s->rate);
+    qemu_put_sbe64(f, s->ticks_per_sec);
+    qemu_put_sbe16(f, s->config);
+    qemu_put_sbe32(f, s->status);
+    qemu_put_sbe32(f, s->it_ena);
+    qemu_put_sbe32(f, s->wu_ena);
+    qemu_put_sbe32(f, s->enable);
+    qemu_put_sbe32(f, s->inout);
+    qemu_put_sbe32(f, s->capt2);
+    qemu_put_sbe32(f, s->pt);
+    qemu_put_sbe32(f, s->trigger);
+    qemu_put_sbe32(f, s->capture);
+    qemu_put_sbe32(f, s->scpwm);
+    qemu_put_sbe32(f, s->ce);
+    qemu_put_sbe32(f, s->pre);
+    qemu_put_sbe32(f, s->ptv);
+    qemu_put_sbe32(f, s->ar);
+    qemu_put_sbe32(f, s->st);
+    qemu_put_sbe32(f, s->posted);
+    qemu_put_be32(f, s->val);
+    qemu_put_be32(f, s->load_val);
+    qemu_put_be32(f, s->capture_val[0]);
+    qemu_put_be32(f, s->capture_val[1]);
+    qemu_put_be32(f, s->match_val);
+    qemu_put_sbe32(f, s->capt_num);
+    qemu_put_be16(f, s->writeh);
+    qemu_put_be16(f, s->readh);
+}
+
+static int omap_gp_timer_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *)opaque;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    qemu_get_timer(f, s->timer);
+    qemu_get_timer(f, s->match);
+    s->in_val = qemu_get_sbe32(f);
+    s->out_val = qemu_get_sbe32(f);
+    s->time = qemu_get_sbe64(f);
+    s->rate = qemu_get_sbe64(f);
+    s->ticks_per_sec = qemu_get_sbe64(f);
+    s->config = qemu_get_sbe16(f);
+    s->status = qemu_get_sbe32(f);
+    s->it_ena = qemu_get_sbe32(f);
+    s->wu_ena = qemu_get_sbe32(f);
+    s->enable = qemu_get_sbe32(f);
+    s->inout = qemu_get_sbe32(f);
+    s->capt2 = qemu_get_sbe32(f);
+    s->pt = qemu_get_sbe32(f);
+    s->trigger = qemu_get_sbe32(f);
+    s->capture = qemu_get_sbe32(f);
+    s->scpwm = qemu_get_sbe32(f);
+    s->ce = qemu_get_sbe32(f);
+    s->pre = qemu_get_sbe32(f);
+    s->ptv = qemu_get_sbe32(f);
+    s->ar = qemu_get_sbe32(f);
+    s->st = qemu_get_sbe32(f);
+    s->posted = qemu_get_sbe32(f);
+    s->val = qemu_get_be32(f);
+    s->load_val = qemu_get_be32(f);
+    s->capture_val[0] = qemu_get_be32(f);
+    s->capture_val[1] = qemu_get_be32(f);
+    s->match_val = qemu_get_be32(f);
+    s->capt_num = qemu_get_sbe32(f);
+    s->writeh = qemu_get_be16(f);
+    s->readh = qemu_get_be16(f);
+    
+    omap_gp_timer_update(s);
+    
+    return 0;
+}
+
 struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
                 qemu_irq irq, omap_clk fclk, omap_clk iclk)
 {
@@ -509,6 +592,8 @@ struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
                     omap_gp_timer_writefn, s);
     omap_l4_attach(ta, 0, iomemtype);
 
+    register_savevm("omap_gp_timer", (ta->base >> 12) & 0xfffff, 0,
+                    omap_gp_timer_save_state, omap_gp_timer_load_state, s);
     return s;
 }
 
@@ -611,6 +696,31 @@ static CPUWriteMemoryFunc *omap3_synctimer_writefn[] = {
     omap3_synctimer_write,
 };
 
+static void omap_synctimer_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap_synctimer_s *s = (struct omap_synctimer_s *)opaque;
+    
+    qemu_put_be32(f, s->val);
+    qemu_put_be16(f, s->readh);
+    qemu_put_be32(f, s->sysconfig);
+}
+
+static int omap_synctimer_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap_synctimer_s *s = (struct omap_synctimer_s *)opaque;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    s->val = qemu_get_be32(f);
+    s->readh = qemu_get_be16(f);
+    s->sysconfig = qemu_get_be32(f);
+    
+    omap_synctimer_reset(s);
+    
+    return 0;
+}
+
 void omap_synctimer_init(struct omap_target_agent_s *ta,
                 struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk)
 {
@@ -623,6 +733,9 @@ void omap_synctimer_init(struct omap_target_agent_s *ta,
     else
         omap_l4_attach(ta, 0, l4_register_io_memory(0,
                     omap_synctimer_readfn, omap_synctimer_writefn, s));
+    
+    register_savevm("omap_synctimer", -1, 0,
+                    omap_synctimer_save_state, omap_synctimer_load_state, s);
 }
 
 /* General-Purpose Interface of OMAP2 */
@@ -1035,6 +1148,65 @@ struct omap_gpif_s {
     int gpo;
 };
 
+static void omap_gpif_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap_gpif_s *s = (struct omap_gpif_s *)opaque;
+    int i, j;
+    
+    qemu_put_sbe32(f, s->autoidle);
+    qemu_put_sbe32(f, s->gpo);
+    qemu_put_sbe32(f, s->modules);
+    for (i = 0; i < s->modules; i++) {
+        for (j = 0; j < 2; j++) {
+            qemu_put_byte(f, s->module[i].config[j]);
+            qemu_put_be32(f, s->module[i].level[j]);
+            qemu_put_be32(f, s->module[i].edge[j]);
+            qemu_put_be32(f, s->module[i].mask[j]);
+            qemu_put_be32(f, s->module[i].ints[j]);
+        }
+        qemu_put_be32(f, s->module[i].inputs);
+        qemu_put_be32(f, s->module[i].outputs);
+        qemu_put_be32(f, s->module[i].dir);
+        qemu_put_be32(f, s->module[i].wumask);
+        qemu_put_be32(f, s->module[i].debounce);
+        qemu_put_byte(f, s->module[i].delay);
+    }
+}
+
+static int omap_gpif_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap_gpif_s *s = (struct omap_gpif_s *)opaque;
+    int i, j;
+
+    if (version_id)
+        return -EINVAL;
+    
+    s->autoidle = qemu_get_sbe32(f);
+    s->gpo = qemu_get_sbe32(f);
+    if (qemu_get_sbe32(f) != s->modules)
+        return -EINVAL;
+    for (i = 0; i < s->modules; i++) {
+        for (j = 0; j < 2; j++) {
+            s->module[i].config[j] = qemu_get_byte(f);
+            s->module[i].level[j] = qemu_get_be32(f);
+            s->module[i].edge[j] = qemu_get_be32(f);
+            s->module[i].mask[j] = qemu_get_be32(f);
+            s->module[i].ints[j] = qemu_get_be32(f);
+        }
+        s->module[i].inputs = qemu_get_be32(f);
+        s->module[i].outputs = qemu_get_be32(f);
+        s->module[i].dir = qemu_get_be32(f);
+        s->module[i].wumask = qemu_get_be32(f);
+        s->module[i].debounce = qemu_get_be32(f);
+        s->module[i].delay = qemu_get_byte(f);
+
+        omap_gpio_module_level_update(&s->module[i], 0);
+        omap_gpio_module_level_update(&s->module[i], 1);
+    }
+    
+    return 0;
+}
+
 static void omap_gpif_reset(struct omap_gpif_s *s)
 {
     int i;
@@ -1143,6 +1315,9 @@ struct omap_gpif_s *omap3_gpif_init()
     struct omap_gpif_s *s = (struct omap_gpif_s *)
         qemu_mallocz(sizeof(struct omap_gpif_s));
     omap_gpif_reset(s);
+    
+    register_savevm("omap_gpif", -1, 0,
+                    omap_gpif_save_state, omap_gpif_load_state, s);
     return s;
 }
 
@@ -3987,6 +4162,53 @@ struct omap_sdrc_s {
     } cs[2];
 };
 
+static void omap_sdrc_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap_sdrc_s *s = (struct omap_sdrc_s *)opaque;
+    int i;
+    
+    qemu_put_byte(f, s->config);
+    qemu_put_be32(f, s->cscfg);
+    qemu_put_be32(f, s->sharing);
+    qemu_put_be32(f, s->dlla_ctrl);
+    qemu_put_be32(f, s->power_reg);
+    for (i = 0; i < 2; i++) {
+        qemu_put_be32(f, s->cs[i].mcfg);
+        qemu_put_be32(f, s->cs[i].mr);
+        qemu_put_be32(f, s->cs[i].emr2);
+        qemu_put_be32(f, s->cs[i].actim_ctrla);
+        qemu_put_be32(f, s->cs[i].actim_ctrlb);
+        qemu_put_be32(f, s->cs[i].rfr_ctrl);
+        qemu_put_be32(f, s->cs[i].manual);
+    }
+}
+
+static int omap_sdrc_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap_sdrc_s *s = (struct omap_sdrc_s *)opaque;
+    int i;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    s->config = qemu_get_byte(f);
+    s->cscfg = qemu_get_be32(f);
+    s->sharing = qemu_get_be32(f);
+    s->dlla_ctrl = qemu_get_be32(f);
+    s->power_reg = qemu_get_be32(f);
+    for (i = 0; i < 2; i++) {
+        s->cs[i].mcfg = qemu_get_be32(f);
+        s->cs[i].mr = qemu_get_be32(f);
+        s->cs[i].emr2 = qemu_get_be32(f);
+        s->cs[i].actim_ctrla = qemu_get_be32(f);
+        s->cs[i].actim_ctrlb = qemu_get_be32(f);
+        s->cs[i].rfr_ctrl = qemu_get_be32(f);
+        s->cs[i].manual = qemu_get_be32(f);
+    }
+    
+    return 0;
+}
+
 static void omap_sdrc_reset(struct omap_sdrc_s *s)
 {
     s->config    = 0x10;
@@ -4230,6 +4452,8 @@ struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base)
                     omap_sdrc_writefn, s);
     cpu_register_physical_memory(base, 0x1000, iomemtype);
 
+    register_savevm("omap_sdrc", -1, 0,
+                    omap_sdrc_save_state, omap_sdrc_load_state, s);
     return s;
 }
 
@@ -4345,6 +4569,76 @@ static void omap_gpmc_reset(struct omap_gpmc_s *s)
         ecc_reset(&s->ecc[i]);
 }
 
+static void omap_gpmc_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap_gpmc_s *s = (struct omap_gpmc_s *)opaque;
+    int i, j;
+    
+    qemu_put_byte(f, s->sysconfig);
+    qemu_put_be16(f, s->irqst);
+    qemu_put_be16(f, s->irqen);
+    qemu_put_be16(f, s->timeout);
+    qemu_put_be16(f, s->config);
+    qemu_put_be32(f, s->prefconfig[0]);
+    qemu_put_be32(f, s->prefconfig[1]);
+    qemu_put_sbe32(f, s->prefcontrol);
+    qemu_put_sbe32(f, s->preffifo);
+    qemu_put_sbe32(f, s->prefcount);
+    for (i = 0; i < 8; i++)
+        for (j = 0; j < 7; j++)
+            qemu_put_be32(f, s->cs_file[i].config[j]);
+    qemu_put_sbe32(f, s->ecc_cs);
+    qemu_put_sbe32(f, s->ecc_ptr);
+    qemu_put_be32(f, s->ecc_cfg);
+    for (i = 0; i < 9; i++) {
+        qemu_put_byte(f, s->ecc[i].cp);
+        qemu_put_be16(f, s->ecc[i].lp[0]);
+        qemu_put_be16(f, s->ecc[i].lp[1]);
+        qemu_put_be16(f, s->ecc[i].count);
+    }
+}
+
+static int omap_gpmc_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap_gpmc_s *s = (struct omap_gpmc_s *)opaque;
+    int i, j;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    s->sysconfig = qemu_get_byte(f);
+    s->irqst = qemu_get_be16(f);
+    s->irqen = qemu_get_be16(f);
+    s->timeout = qemu_get_be16(f);
+    s->config = qemu_get_be16(f);
+    s->prefconfig[0] = qemu_get_be32(f);
+    s->prefconfig[1] = qemu_get_be32(f);
+    s->prefcontrol = qemu_get_sbe32(f);
+    s->preffifo = qemu_get_sbe32(f);
+    s->prefcount = qemu_get_sbe32(f);
+    for (i = 0; i < 8; i++) {
+        for (j = 0; j < 7; j++)
+            s->cs_file[i].config[j] = qemu_get_be32(f);
+        if (s->cs_file[i].config[6] & (1 << 6)) /* CSVALID */
+            omap_gpmc_cs_map(&s->cs_file[i],
+                             s->cs_file[i].config[6] & 0x3f, /* MASKADDR */
+                             (s->cs_file[i].config[6] >> 8 & 0xf));    /* BASE */
+    }        
+    s->ecc_cs = qemu_get_sbe32(f);
+    s->ecc_ptr = qemu_get_sbe32(f);
+    s->ecc_cfg = qemu_get_be32(f);
+    for (i = 0; i < 9; i++) {
+        s->ecc[i].cp = qemu_get_byte(f);
+        s->ecc[i].lp[0] = qemu_get_be16(f);
+        s->ecc[i].lp[1] = qemu_get_be16(f);
+        s->ecc[i].count = qemu_get_be16(f);
+    }
+    
+    omap_gpmc_int_update(s);
+    
+    return 0;
+}
+
 static uint32_t omap_gpmc_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
@@ -4846,6 +5140,8 @@ struct omap_gpmc_s *omap_gpmc_init(struct omap_mpu_state_s *mpu,
                     omap_gpmc_writefn, s);
     cpu_register_physical_memory(base, 0x1000, iomemtype);
 
+    register_savevm("omap_gpmc", -1, 0,
+                    omap_gpmc_save_state, omap_gpmc_load_state, s);
     return s;
 }
 
index 918997a..6ffc65e 100644 (file)
@@ -225,11 +225,37 @@ static void omap3_l3ia_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
+static void omap3_l3ia_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap3_l3_initiator_agent_s *s =
+        (struct omap3_l3_initiator_agent_s *)opaque;
+
+    qemu_put_be32(f, s->control);
+    qemu_put_be32(f, s->status);
+}
+
+static int omap3_l3ia_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap3_l3_initiator_agent_s *s =
+        (struct omap3_l3_initiator_agent_s *)opaque;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    s->control = qemu_get_be32(f);
+    s->status = qemu_get_be32(f);
+    
+    return 0;
+}
+
 static void omap3_l3ia_init(struct omap3_l3_initiator_agent_s *s)
 {
     s->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
     s->control = 0x3e000000;
     s->status = 0;
+    
+    register_savevm("omap3_l3ia", (s->base >> 8) & 0xffff, 0,
+                    omap3_l3ia_save_state, omap3_l3ia_load_state, s);
 }
 
 static CPUReadMemoryFunc *omap3_l3ia_readfn[] = {
@@ -326,11 +352,37 @@ static void omap3_l3ta_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
+static void omap3_l3ta_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap_target_agent_s *s =
+        (struct omap_target_agent_s *)opaque;
+    
+    qemu_put_be32(f, s->control);
+    qemu_put_be32(f, s->status);
+}
+
+static int omap3_l3ta_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap_target_agent_s *s =
+        (struct omap_target_agent_s *)opaque;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    s->control = qemu_get_be32(f);
+    s->status = qemu_get_be32(f);
+    
+    return 0;
+}
+
 static void omap3_l3ta_init(struct omap_target_agent_s *s)
 {
     s->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
     s->control = 0x03000000;
     s->status = 0;
+
+    register_savevm("omap3_l3ta", (s->base >> 8) & 0xffff, 0,
+                    omap3_l3ta_save_state, omap3_l3ta_load_state, s);
 }
 
 static CPUReadMemoryFunc *omap3_l3ta_readfn[] = {
@@ -519,6 +571,42 @@ static void omap3_l3pm_write32(void *opaque, target_phys_addr_t addr,
     omap3_l3pm_write16(opaque, addr + 2, (value >> 16) & 0xffff);
 }
 
+static void omap3_l3pm_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap3_l3pm_s *s = (struct omap3_l3pm_s *)opaque;
+    int i;
+    
+    qemu_put_be32(f, s->error_log);
+    qemu_put_byte(f, s->control);
+    for (i = 0; i < 8; i++) {
+        qemu_put_be16(f, s->req_info_permission[i]);
+        qemu_put_be16(f, s->read_permission[i]);
+        qemu_put_be16(f, s->write_permission[i]);
+        if (i < 7)
+            qemu_put_be32(f, s->addr_match[i]);
+    }
+}
+
+static int omap3_l3pm_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap3_l3pm_s *s = (struct omap3_l3pm_s *)opaque;
+    int i;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    s->error_log = qemu_get_be32(f);
+    s->control = qemu_get_byte(f);
+    for (i = 0; i < 8; i++) {
+        s->req_info_permission[i] = qemu_get_be16(f);
+        s->read_permission[i] = qemu_get_be16(f);
+        s->write_permission[i] = qemu_get_be16(f);
+        if (i < 7)
+            s->addr_match[i] = qemu_get_be32(f);
+    }
+    return 0;
+}
+
 static void omap3_l3pm_init(struct omap3_l3pm_s *s)
 {
     int i;
@@ -577,6 +665,9 @@ static void omap3_l3pm_init(struct omap3_l3pm_s *s)
             exit(-1);
             break;
     }
+
+    register_savevm("omap3_l3pm", (s->base >> 8) & 0xffff, 0,
+                    omap3_l3pm_save_state, omap3_l3pm_load_state, s);
 }
 
 static CPUReadMemoryFunc *omap3_l3pm_readfn[] = {
@@ -1245,6 +1336,29 @@ static void omap3_l4ta_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
+static void omap3_l4ta_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap_target_agent_s *s = (struct omap_target_agent_s *)opaque;
+    
+    qemu_put_be32(f, s->control);
+    qemu_put_be32(f, s->control_h);
+    qemu_put_be32(f, s->status);
+}
+
+static int omap3_l4ta_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap_target_agent_s *s = (struct omap_target_agent_s *)opaque;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    s->control = qemu_get_be32(f);
+    s->control_h = qemu_get_be32(f);
+    s->status = qemu_get_be32(f);
+    
+    return 0;
+}
+
 static CPUReadMemoryFunc *omap3_l4ta_readfn[] = {
     omap_badwidth_read32,
     omap_badwidth_read32,
@@ -1300,6 +1414,9 @@ static struct omap_target_agent_s *omap3_l4ta_init(struct omap_l4_s *bus, int cs
                                       omap3_l4ta_writefn, ta);
     ta->base = omap_l4_attach(ta, i, iomemtype);
 
+    register_savevm("omap3_l4ta", ta->base >> 8, 0,
+                    omap3_l4ta_save_state, omap3_l4ta_load_state, ta);
+
     return ta;
 }
 
@@ -1570,9 +1687,10 @@ static uint32_t omap3_prm_read(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-static inline void omap3_prm_clksrc_ctrl_update(struct omap3_prm_s *s,
-                                                uint32_t value)
+static inline void omap3_prm_clksrc_ctrl_update(struct omap3_prm_s *s)
 {
+    uint32_t value = s->gr.prm_clksrc_ctrl;
+    
     if ((value & 0xd0) == 0x40)
         omap_clk_setrate(omap_findclk(s->omap, "omap3_sys_clk"), 1, 1);
     else if ((value & 0xd0) == 0x80)
@@ -1720,7 +1838,7 @@ static void omap3_prm_write(void *opaque, target_phys_addr_t addr,
         case 0x1264: s->gr.prm_sram_pcharge = value & 0xff; break;
         case 0x1270:
             s->gr.prm_clksrc_ctrl = value & 0xd8; /* set osc bypass mode */ 
-            omap3_prm_clksrc_ctrl_update(s, s->gr.prm_clksrc_ctrl);
+            omap3_prm_clksrc_ctrl_update(s);
             break;
         case 0x1280: OMAP_RO_REG(addr); break;
         case 0x1290: s->gr.prm_voltsetup1 = value; break;
@@ -1750,6 +1868,159 @@ static void omap3_prm_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
+static void omap3_prm_save_domain_state(QEMUFile *f,
+                                        struct omap3_prm_domain_s *s)
+{
+    qemu_put_be32(f, s->rm_rstctrl);
+    qemu_put_be32(f, s->rm_rstst);
+    qemu_put_be32(f, s->pm_wken);
+    qemu_put_be32(f, s->pm_mpugrpsel);
+    qemu_put_be32(f, s->pm_ivagrpsel);
+    qemu_put_be32(f, s->pm_wkst);
+    qemu_put_be32(f, s->pm_wkst3);
+    qemu_put_be32(f, s->pm_wkdep);
+    qemu_put_be32(f, s->pm_evgenctrl);
+    qemu_put_be32(f, s->pm_evgenontim);
+    qemu_put_be32(f, s->pm_evgenofftim);
+    qemu_put_be32(f, s->pm_pwstctrl);
+    qemu_put_be32(f, s->pm_pwstst);
+    qemu_put_be32(f, s->pm_prepwstst);
+    qemu_put_be32(f, s->pm_wken3);
+}
+
+static void omap3_prm_load_domain_state(QEMUFile *f,
+                                        struct omap3_prm_domain_s *s)
+{
+    s->rm_rstctrl = qemu_get_be32(f);
+    s->rm_rstst = qemu_get_be32(f);
+    s->pm_wken = qemu_get_be32(f);
+    s->pm_mpugrpsel = qemu_get_be32(f);
+    s->pm_ivagrpsel = qemu_get_be32(f);
+    s->pm_wkst = qemu_get_be32(f);
+    s->pm_wkst3 = qemu_get_be32(f);
+    s->pm_wkdep = qemu_get_be32(f);
+    s->pm_evgenctrl = qemu_get_be32(f);
+    s->pm_evgenontim = qemu_get_be32(f);
+    s->pm_evgenofftim = qemu_get_be32(f);
+    s->pm_pwstctrl = qemu_get_be32(f);
+    s->pm_pwstst = qemu_get_be32(f);
+    s->pm_prepwstst = qemu_get_be32(f);
+    s->pm_wken3 = qemu_get_be32(f);
+}
+
+static void omap3_prm_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap3_prm_s *s = (struct omap3_prm_s *)opaque;
+    
+    omap3_prm_save_domain_state(f, &s->iva2);
+    omap3_prm_save_domain_state(f, &s->mpu);
+    omap3_prm_save_domain_state(f, &s->core);
+    omap3_prm_save_domain_state(f, &s->sgx);
+    omap3_prm_save_domain_state(f, &s->wkup);
+    omap3_prm_save_domain_state(f, &s->dss);
+    omap3_prm_save_domain_state(f, &s->cam);
+    omap3_prm_save_domain_state(f, &s->per);
+    omap3_prm_save_domain_state(f, &s->emu);
+    omap3_prm_save_domain_state(f, &s->neon);
+    omap3_prm_save_domain_state(f, &s->usbhost);
+    
+    qemu_put_be32(f, s->prm_irqstatus_iva2);
+    qemu_put_be32(f, s->prm_irqenable_iva2);
+    qemu_put_be32(f, s->pm_iva2grpsel3_core);
+    qemu_put_be32(f, s->pm_mpugrpsel3_core);
+    
+    qemu_put_be32(f, s->ocp.prm_revision);
+    qemu_put_be32(f, s->ocp.prm_sysconfig);
+    qemu_put_be32(f, s->ocp.prm_irqstatus_mpu);
+    qemu_put_be32(f, s->ocp.prm_irqenable_mpu);
+    
+    qemu_put_be32(f, s->ccr.prm_clksel);
+    qemu_put_be32(f, s->ccr.prm_clkout_ctrl);
+    
+    qemu_put_be32(f, s->gr.prm_vc_smps_sa);
+    qemu_put_be32(f, s->gr.prm_vc_smps_vol_ra);
+    qemu_put_be32(f, s->gr.prm_vc_smps_cmd_ra);
+    qemu_put_be32(f, s->gr.prm_vc_cmd_val_0);
+    qemu_put_be32(f, s->gr.prm_vc_cmd_val_1);
+    qemu_put_be32(f, s->gr.prm_vc_hc_conf);
+    qemu_put_be32(f, s->gr.prm_vc_i2c_cfg);
+    qemu_put_be32(f, s->gr.prm_vc_bypass_val);
+    qemu_put_be32(f, s->gr.prm_rstctrl);
+    qemu_put_be32(f, s->gr.prm_rsttimer);
+    qemu_put_be32(f, s->gr.prm_rstst);
+    qemu_put_be32(f, s->gr.prm_voltctrl);
+    qemu_put_be32(f, s->gr.prm_sram_pcharge);
+    qemu_put_be32(f, s->gr.prm_clksrc_ctrl);
+    qemu_put_be32(f, s->gr.prm_obs);
+    qemu_put_be32(f, s->gr.prm_voltsetup1);
+    qemu_put_be32(f, s->gr.prm_voltoffset);
+    qemu_put_be32(f, s->gr.prm_clksetup);
+    qemu_put_be32(f, s->gr.prm_polctrl);
+    qemu_put_be32(f, s->gr.prm_voltsetup2);
+}
+
+static int omap3_prm_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap3_prm_s *s = (struct omap3_prm_s *)opaque;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    omap3_prm_load_domain_state(f, &s->iva2);
+    omap3_prm_load_domain_state(f, &s->mpu);
+    omap3_prm_load_domain_state(f, &s->core);
+    omap3_prm_load_domain_state(f, &s->sgx);
+    omap3_prm_load_domain_state(f, &s->wkup);
+    omap3_prm_load_domain_state(f, &s->dss);
+    omap3_prm_load_domain_state(f, &s->cam);
+    omap3_prm_load_domain_state(f, &s->per);
+    omap3_prm_load_domain_state(f, &s->emu);
+    omap3_prm_load_domain_state(f, &s->neon);
+    omap3_prm_load_domain_state(f, &s->usbhost);
+    
+    s->prm_irqstatus_iva2 = qemu_get_be32(f);
+    s->prm_irqenable_iva2 = qemu_get_be32(f);
+    s->pm_iva2grpsel3_core = qemu_get_be32(f);
+    s->pm_mpugrpsel3_core = qemu_get_be32(f);
+    
+    s->ocp.prm_revision = qemu_get_be32(f);
+    s->ocp.prm_sysconfig = qemu_get_be32(f);
+    s->ocp.prm_irqstatus_mpu = qemu_get_be32(f);
+    s->ocp.prm_irqenable_mpu = qemu_get_be32(f);
+    
+    s->ccr.prm_clksel = qemu_get_be32(f);
+    s->ccr.prm_clkout_ctrl = qemu_get_be32(f);
+    
+    s->gr.prm_vc_smps_sa = qemu_get_be32(f);
+    s->gr.prm_vc_smps_vol_ra = qemu_get_be32(f);
+    s->gr.prm_vc_smps_cmd_ra = qemu_get_be32(f);
+    s->gr.prm_vc_cmd_val_0 = qemu_get_be32(f);
+    s->gr.prm_vc_cmd_val_1 = qemu_get_be32(f);
+    s->gr.prm_vc_hc_conf = qemu_get_be32(f);
+    s->gr.prm_vc_i2c_cfg = qemu_get_be32(f);
+    s->gr.prm_vc_bypass_val = qemu_get_be32(f);
+    s->gr.prm_rstctrl = qemu_get_be32(f);
+    s->gr.prm_rsttimer = qemu_get_be32(f);
+    s->gr.prm_rstst = qemu_get_be32(f);
+    s->gr.prm_voltctrl = qemu_get_be32(f);
+    s->gr.prm_sram_pcharge = qemu_get_be32(f);
+    s->gr.prm_clksrc_ctrl = qemu_get_be32(f);
+    s->gr.prm_obs = qemu_get_be32(f);
+    s->gr.prm_voltsetup1 = qemu_get_be32(f);
+    s->gr.prm_voltoffset = qemu_get_be32(f);
+    s->gr.prm_clksetup = qemu_get_be32(f);
+    s->gr.prm_polctrl = qemu_get_be32(f);
+    s->gr.prm_voltsetup2 = qemu_get_be32(f);
+    
+    omap3_prm_int_update(s);
+    omap3_prm_clksrc_ctrl_update(s);
+    omap3_prm_clksel_update(s);
+    omap_clk_onoff(omap_findclk(s->omap, "omap3_sys_clkout1"),
+                   s->ccr.prm_clkout_ctrl & 0x80);
+    
+    return 0;
+}
+
 static CPUReadMemoryFunc *omap3_prm_readfn[] = {
     omap_badwidth_read32,
     omap_badwidth_read32,
@@ -1779,6 +2050,9 @@ struct omap3_prm_s *omap3_prm_init(struct omap_target_agent_s *ta,
     omap_l4_attach(ta, 0, iomemtype);
     omap_l4_attach(ta, 1, iomemtype);
 
+    register_savevm("omap3_prm", -1, 0,
+                    omap3_prm_save_state, omap3_prm_load_state, s);
+
     return s;
 }
 
@@ -2249,6 +2523,14 @@ static inline void omap3_cm_iclken1_core_update(struct omap3_cm_s *s)
     s->cm_idlest1_core = ~v;
 }
 
+static inline void omap3_cm_l3l4iclk_update(struct omap3_cm_s *s)
+{
+    omap_clk_setrate(omap_findclk(s->mpu, "omap3_l3_iclk"),
+                     s->cm_clksel_core & 0x3, 1);
+    omap_clk_setrate(omap_findclk(s->mpu, "omap3_l4_iclk"),
+                     (s->cm_clksel_core >> 2) & 0x3, 1);
+}
+
 static void omap3_cm_reset(struct omap3_cm_s *s)
 {
     s->cm_fclken_iva2 = 0x0;
@@ -2602,10 +2884,7 @@ static void omap3_cm_write(void *opaque,
         case 0xa40:
             s->cm_clksel_core = (value & 0xff) | 0x100;
             omap3_cm_gp10gp11_update(s);
-            omap_clk_setrate(omap_findclk(s->mpu, "omap3_l3_iclk"),
-                             s->cm_clksel_core & 0x3, 1);
-            omap_clk_setrate(omap_findclk(s->mpu, "omap3_l4_iclk"),
-                             (s->cm_clksel_core >> 2) & 0x3, 1);
+            omap3_cm_l3l4iclk_update(s);
             break;
         case 0xa48:
             s->cm_clkstctrl_core = value & 0xf;
@@ -2728,11 +3007,266 @@ static void omap3_cm_write(void *opaque,
         case 0x1444: s->cm_sleepdep_usbhost = value & 0x6; break;
         case 0x1448: s->cm_clkstctrl_usbhost = value & 0x3; break;
         /* unknown */
-        default: OMAP_BAD_REGV(addr, value); break;
+        default:
+            OMAP_BAD_REGV(addr, value);
+            break;
     }
 }
 
+static void omap3_cm_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap3_cm_s *s = (struct omap3_cm_s *)opaque;
+    
+    qemu_put_be32(f, s->cm_fclken_iva2);
+    qemu_put_be32(f, s->cm_clken_pll_iva2);
+    qemu_put_be32(f, s->cm_idlest_iva2);
+    qemu_put_be32(f, s->cm_idlest_pll_iva2);
+    qemu_put_be32(f, s->cm_autoidle_pll_iva2);
+    qemu_put_be32(f, s->cm_clksel1_pll_iva2);
+    qemu_put_be32(f, s->cm_clksel2_pll_iva2);
+    qemu_put_be32(f, s->cm_clkstctrl_iva2);
+    qemu_put_be32(f, s->cm_clkstst_iva2);
+    
+    qemu_put_be32(f, s->cm_revision);
+    qemu_put_be32(f, s->cm_sysconfig);
+    
+    qemu_put_be32(f, s->cm_clken_pll_mpu);
+    qemu_put_be32(f, s->cm_idlest_mpu);
+    qemu_put_be32(f, s->cm_idlest_pll_mpu);
+    qemu_put_be32(f, s->cm_autoidle_pll_mpu);
+    qemu_put_be32(f, s->cm_clksel1_pll_mpu);
+    qemu_put_be32(f, s->cm_clksel2_pll_mpu);
+    qemu_put_be32(f, s->cm_clkstctrl_mpu);
+    qemu_put_be32(f, s->cm_clkstst_mpu);
+    
+    qemu_put_be32(f, s->cm_fclken1_core);
+    qemu_put_be32(f, s->cm_fclken3_core);
+    qemu_put_be32(f, s->cm_iclken1_core);
+    qemu_put_be32(f, s->cm_iclken2_core);
+    qemu_put_be32(f, s->cm_iclken3_core);
+    qemu_put_be32(f, s->cm_idlest1_core);
+    qemu_put_be32(f, s->cm_idlest2_core);
+    qemu_put_be32(f, s->cm_idlest3_core);
+    qemu_put_be32(f, s->cm_autoidle1_core);
+    qemu_put_be32(f, s->cm_autoidle2_core);
+    qemu_put_be32(f, s->cm_autoidle3_core);
+    qemu_put_be32(f, s->cm_clksel_core);
+    qemu_put_be32(f, s->cm_clkstctrl_core);
+    qemu_put_be32(f, s->cm_clkstst_core);
+    
+    qemu_put_be32(f, s->cm_fclken_sgx);
+    qemu_put_be32(f, s->cm_iclken_sgx);
+    qemu_put_be32(f, s->cm_idlest_sgx);
+    qemu_put_be32(f, s->cm_clksel_sgx);
+    qemu_put_be32(f, s->cm_sleepdep_sgx);
+    qemu_put_be32(f, s->cm_clkstctrl_sgx);
+    qemu_put_be32(f, s->cm_clkstst_sgx);
+    
+    qemu_put_be32(f, s->cm_fclken_wkup);
+    qemu_put_be32(f, s->cm_iclken_wkup);
+    qemu_put_be32(f, s->cm_idlest_wkup);
+    qemu_put_be32(f, s->cm_autoidle_wkup);
+    qemu_put_be32(f, s->cm_clksel_wkup);
+    qemu_put_be32(f, s->cm_c48);
+    
+    qemu_put_be32(f, s->cm_clken_pll);
+    qemu_put_be32(f, s->cm_clken2_pll);
+    qemu_put_be32(f, s->cm_idlest_ckgen);
+    qemu_put_be32(f, s->cm_idlest2_ckgen);
+    qemu_put_be32(f, s->cm_autoidle_pll);
+    qemu_put_be32(f, s->cm_autoidle2_pll);
+    qemu_put_be32(f, s->cm_clksel1_pll);
+    qemu_put_be32(f, s->cm_clksel2_pll);
+    qemu_put_be32(f, s->cm_clksel3_pll);
+    qemu_put_be32(f, s->cm_clksel4_pll);
+    qemu_put_be32(f, s->cm_clksel5_pll);
+    qemu_put_be32(f, s->cm_clkout_ctrl);
+    
+    qemu_put_be32(f, s->cm_fclken_dss);
+    qemu_put_be32(f, s->cm_iclken_dss);
+    qemu_put_be32(f, s->cm_idlest_dss);
+    qemu_put_be32(f, s->cm_autoidle_dss);
+    qemu_put_be32(f, s->cm_clksel_dss);
+    qemu_put_be32(f, s->cm_sleepdep_dss);
+    qemu_put_be32(f, s->cm_clkstctrl_dss);
+    qemu_put_be32(f, s->cm_clkstst_dss);
+    
+    qemu_put_be32(f, s->cm_fclken_cam);
+    qemu_put_be32(f, s->cm_iclken_cam);
+    qemu_put_be32(f, s->cm_idlest_cam);
+    qemu_put_be32(f, s->cm_autoidle_cam);
+    qemu_put_be32(f, s->cm_clksel_cam);
+    qemu_put_be32(f, s->cm_sleepdep_cam);
+    qemu_put_be32(f, s->cm_clkstctrl_cam);
+    qemu_put_be32(f, s->cm_clkstst_cam);
+
+    qemu_put_be32(f, s->cm_fclken_per);
+    qemu_put_be32(f, s->cm_iclken_per);
+    qemu_put_be32(f, s->cm_idlest_per);
+    qemu_put_be32(f, s->cm_autoidle_per);
+    qemu_put_be32(f, s->cm_clksel_per);
+    qemu_put_be32(f, s->cm_sleepdep_per);
+    qemu_put_be32(f, s->cm_clkstctrl_per);
+    qemu_put_be32(f, s->cm_clkstst_per);
+    
+    qemu_put_be32(f, s->cm_clksel1_emu);
+    qemu_put_be32(f, s->cm_clkstctrl_emu);
+    qemu_put_be32(f, s->cm_clkstst_emu);
+    qemu_put_be32(f, s->cm_clksel2_emu);
+    qemu_put_be32(f, s->cm_clksel3_emu);
+    
+    qemu_put_be32(f, s->cm_polctrl);
+
+    qemu_put_be32(f, s->cm_idlest_neon);
+    qemu_put_be32(f, s->cm_clkstctrl_neon);
+
+    qemu_put_be32(f, s->cm_fclken_usbhost);
+    qemu_put_be32(f, s->cm_iclken_usbhost);
+    qemu_put_be32(f, s->cm_idlest_usbhost);
+    qemu_put_be32(f, s->cm_autoidle_usbhost);
+    qemu_put_be32(f, s->cm_sleepdep_usbhost);
+    qemu_put_be32(f, s->cm_clkstctrl_usbhost);
+    qemu_put_be32(f, s->cm_clkstst_usbhost);
+}
 
+static int omap3_cm_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap3_cm_s *s = (struct omap3_cm_s *)opaque;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    s->cm_fclken_iva2 = qemu_get_be32(f);
+    s->cm_clken_pll_iva2 = qemu_get_be32(f);
+    s->cm_idlest_iva2 = qemu_get_be32(f);
+    s->cm_idlest_pll_iva2 = qemu_get_be32(f);
+    s->cm_autoidle_pll_iva2 = qemu_get_be32(f);
+    s->cm_clksel1_pll_iva2 = qemu_get_be32(f);
+    s->cm_clksel2_pll_iva2 = qemu_get_be32(f);
+    s->cm_clkstctrl_iva2 = qemu_get_be32(f);
+    s->cm_clkstst_iva2 = qemu_get_be32(f);
+    
+    s->cm_revision = qemu_get_be32(f);
+    s->cm_sysconfig = qemu_get_be32(f);
+    
+    s->cm_clken_pll_mpu = qemu_get_be32(f);
+    s->cm_idlest_mpu = qemu_get_be32(f);
+    s->cm_idlest_pll_mpu = qemu_get_be32(f);
+    s->cm_autoidle_pll_mpu = qemu_get_be32(f);
+    s->cm_clksel1_pll_mpu = qemu_get_be32(f);
+    s->cm_clksel2_pll_mpu = qemu_get_be32(f);
+    s->cm_clkstctrl_mpu = qemu_get_be32(f);
+    s->cm_clkstst_mpu = qemu_get_be32(f);
+    
+    s->cm_fclken1_core = qemu_get_be32(f);
+    s->cm_fclken3_core = qemu_get_be32(f);
+    s->cm_iclken1_core = qemu_get_be32(f);
+    s->cm_iclken2_core = qemu_get_be32(f);
+    s->cm_iclken3_core = qemu_get_be32(f);
+    s->cm_idlest1_core = qemu_get_be32(f);
+    s->cm_idlest2_core = qemu_get_be32(f);
+    s->cm_idlest3_core = qemu_get_be32(f);
+    s->cm_autoidle1_core = qemu_get_be32(f);
+    s->cm_autoidle2_core = qemu_get_be32(f);
+    s->cm_autoidle3_core = qemu_get_be32(f);
+    s->cm_clksel_core = qemu_get_be32(f);
+    s->cm_clkstctrl_core = qemu_get_be32(f);
+    s->cm_clkstst_core = qemu_get_be32(f);
+    
+    s->cm_fclken_sgx = qemu_get_be32(f);
+    s->cm_iclken_sgx = qemu_get_be32(f);
+    s->cm_idlest_sgx = qemu_get_be32(f);
+    s->cm_clksel_sgx = qemu_get_be32(f);
+    s->cm_sleepdep_sgx = qemu_get_be32(f);
+    s->cm_clkstctrl_sgx = qemu_get_be32(f);
+    s->cm_clkstst_sgx = qemu_get_be32(f);
+    
+    s->cm_fclken_wkup = qemu_get_be32(f);
+    s->cm_iclken_wkup = qemu_get_be32(f);
+    s->cm_idlest_wkup = qemu_get_be32(f);
+    s->cm_autoidle_wkup = qemu_get_be32(f);
+    s->cm_clksel_wkup = qemu_get_be32(f);
+    s->cm_c48 = qemu_get_be32(f);
+    
+    s->cm_clken_pll = qemu_get_be32(f);
+    s->cm_clken2_pll = qemu_get_be32(f);
+    s->cm_idlest_ckgen = qemu_get_be32(f);
+    s->cm_idlest2_ckgen = qemu_get_be32(f);
+    s->cm_autoidle_pll = qemu_get_be32(f);
+    s->cm_autoidle2_pll = qemu_get_be32(f);
+    s->cm_clksel1_pll = qemu_get_be32(f);
+    s->cm_clksel2_pll = qemu_get_be32(f);
+    s->cm_clksel3_pll = qemu_get_be32(f);
+    s->cm_clksel4_pll = qemu_get_be32(f);
+    s->cm_clksel5_pll = qemu_get_be32(f);
+    s->cm_clkout_ctrl = qemu_get_be32(f);
+    
+    s->cm_fclken_dss = qemu_get_be32(f);
+    s->cm_iclken_dss = qemu_get_be32(f);
+    s->cm_idlest_dss = qemu_get_be32(f);
+    s->cm_autoidle_dss = qemu_get_be32(f);
+    s->cm_clksel_dss = qemu_get_be32(f);
+    s->cm_sleepdep_dss = qemu_get_be32(f);
+    s->cm_clkstctrl_dss = qemu_get_be32(f);
+    s->cm_clkstst_dss = qemu_get_be32(f);
+    
+    s->cm_fclken_cam = qemu_get_be32(f);
+    s->cm_iclken_cam = qemu_get_be32(f);
+    s->cm_idlest_cam = qemu_get_be32(f);
+    s->cm_autoidle_cam = qemu_get_be32(f);
+    s->cm_clksel_cam = qemu_get_be32(f);
+    s->cm_sleepdep_cam = qemu_get_be32(f);
+    s->cm_clkstctrl_cam = qemu_get_be32(f);
+    s->cm_clkstst_cam = qemu_get_be32(f);
+    
+    s->cm_fclken_per = qemu_get_be32(f);
+    s->cm_iclken_per = qemu_get_be32(f);
+    s->cm_idlest_per = qemu_get_be32(f);
+    s->cm_autoidle_per = qemu_get_be32(f);
+    s->cm_clksel_per = qemu_get_be32(f);
+    s->cm_sleepdep_per = qemu_get_be32(f);
+    s->cm_clkstctrl_per = qemu_get_be32(f);
+    s->cm_clkstst_per = qemu_get_be32(f);
+    
+    s->cm_clksel1_emu = qemu_get_be32(f);
+    s->cm_clkstctrl_emu = qemu_get_be32(f);
+    s->cm_clkstst_emu = qemu_get_be32(f);
+    s->cm_clksel2_emu = qemu_get_be32(f);
+    s->cm_clksel3_emu = qemu_get_be32(f);
+    
+    s->cm_polctrl = qemu_get_be32(f);
+    
+    s->cm_idlest_neon = qemu_get_be32(f);
+    s->cm_clkstctrl_neon = qemu_get_be32(f);
+    
+    s->cm_fclken_usbhost = qemu_get_be32(f);
+    s->cm_iclken_usbhost = qemu_get_be32(f);
+    s->cm_idlest_usbhost = qemu_get_be32(f);
+    s->cm_autoidle_usbhost = qemu_get_be32(f);
+    s->cm_sleepdep_usbhost = qemu_get_be32(f);
+    s->cm_clkstctrl_usbhost = qemu_get_be32(f);
+    s->cm_clkstst_usbhost = qemu_get_be32(f);
+
+    omap3_cm_iva2_update(s);
+    omap3_cm_mpu_update(s);
+    omap3_cm_fclken1_core_update(s);
+    omap3_cm_iclken1_core_update(s);
+    omap3_cm_gp10gp11_update(s);
+    omap3_cm_l3l4iclk_update(s);
+    omap_clk_onoff(omap_findclk(s->mpu, "omap3_gp1_fclk"),
+                   s->cm_fclken_wkup & 1);
+    omap_clk_onoff(omap_findclk(s->mpu, "omap3_wkup_l4_iclk"),
+                   s->cm_iclken_wkup ? 1 : 0);
+    omap3_cm_clksel_wkup_update(s);
+    omap3_cm_dpll3_update(s);
+    omap3_cm_dpll4_update(s);
+    omap3_cm_dpll5_update(s);
+    omap3_cm_48m_update(s);
+    omap3_cm_clkout2_update(s);
+    omap3_cm_per_gptimer_update(s);
+    
+    return 0;
+}
 
 static CPUReadMemoryFunc *omap3_cm_readfn[] = {
     omap_badwidth_read32,
@@ -2763,6 +3297,8 @@ struct omap3_cm_s *omap3_cm_init(struct omap_target_agent_s *ta,
     omap_l4_attach(ta, 0, iomemtype);
     omap_l4_attach(ta, 1, iomemtype);
 
+    register_savevm("omap3_cm", -1, 0,
+                    omap3_cm_save_state, omap3_cm_load_state, s);
     return s;
 }
 
@@ -3037,6 +3573,59 @@ static void omap3_mpu_wdt_timer_tick(void *opaque)
     omap3_wdt_timer_update(wdt_timer);
 }
 
+static void omap3_mpu_wdt_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap3_wdt_s *s = (struct omap3_wdt_s *)opaque;
+
+    qemu_put_timer(f, s->timer);
+    qemu_put_sbe32(f, s->active);
+    qemu_put_be64(f, s->rate);
+    qemu_put_be64(f, s->time);
+    qemu_put_be32(f, s->wd_sysconfig);
+    qemu_put_be32(f, s->wd_sysstatus);
+    qemu_put_be32(f, s->wisr);
+    qemu_put_be32(f, s->wier);
+    qemu_put_be32(f, s->wclr);
+    qemu_put_be32(f, s->wcrr);
+    qemu_put_be32(f, s->wldr);
+    qemu_put_be32(f, s->wtgr);
+    qemu_put_be32(f, s->wwps);
+    qemu_put_be32(f, s->wspr);
+    qemu_put_be32(f, s->pre);
+    qemu_put_be32(f, s->ptv);
+    qemu_put_be16(f, s->writeh);
+    qemu_put_be16(f, s->readh);
+}
+
+static int omap3_mpu_wdt_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap3_wdt_s *s = (struct omap3_wdt_s *)opaque;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    qemu_get_timer(f, s->timer);
+    s->active = qemu_get_sbe32(f);
+    s->rate = qemu_get_be64(f);
+    s->time = qemu_get_be64(f);
+    s->wd_sysconfig = qemu_get_be32(f);
+    s->wd_sysstatus = qemu_get_be32(f);
+    s->wisr = qemu_get_be32(f);
+    s->wier = qemu_get_be32(f);
+    s->wclr = qemu_get_be32(f);
+    s->wcrr = qemu_get_be32(f);
+    s->wldr = qemu_get_be32(f);
+    s->wtgr = qemu_get_be32(f);
+    s->wwps = qemu_get_be32(f);
+    s->wspr = qemu_get_be32(f);
+    s->pre = qemu_get_be32(f);
+    s->ptv = qemu_get_be32(f);
+    s->writeh = qemu_get_be16(f);
+    s->readh = qemu_get_be16(f);
+    
+    return 0;
+}
+
 static struct omap3_wdt_s *omap3_mpu_wdt_init(struct omap_target_agent_s *ta,
                                               qemu_irq irq, omap_clk fclk,
                                               omap_clk iclk,
@@ -3057,8 +3646,9 @@ static struct omap3_wdt_s *omap3_mpu_wdt_init(struct omap_target_agent_s *ta,
                                       omap3_mpu_wdt_writefn, s);
     omap_l4_attach(ta, 0, iomemtype);
 
+    register_savevm("omap3_mpu_wdt", -1, 0,
+                    omap3_mpu_wdt_save_state, omap3_mpu_wdt_load_state, s);
     return s;
-
 }
 
 struct omap3_scm_s {
@@ -3072,6 +3662,41 @@ struct omap3_scm_s {
        uint32 general_wkup[8];  /*0x4800 2a60*/
 };
 
+static void omap3_scm_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap3_scm_s *s = (struct omap3_scm_s *)opaque;
+    int i;
+
+    qemu_put_buffer(f, s->interface, sizeof(s->interface));
+    qemu_put_buffer(f, s->padconfs, sizeof(s->padconfs));
+    for (i = 0; i < sizeof(s->general)/sizeof(uint32); i++)
+        qemu_put_be32(f, s->general[i]);
+    qemu_put_buffer(f, s->mem_wkup, sizeof(s->mem_wkup));
+    qemu_put_buffer(f, s->padconfs_wkup, sizeof(s->padconfs_wkup));
+    for (i = 0; i < sizeof(s->general_wkup)/sizeof(uint32); i++)
+        qemu_put_be32(f, s->general_wkup[i]);
+}
+
+static int omap3_scm_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap3_scm_s *s = (struct omap3_scm_s *)opaque;
+    int i;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    qemu_get_buffer(f, s->interface, sizeof(s->interface));
+    qemu_get_buffer(f, s->padconfs, sizeof(s->padconfs));
+    for (i = 0; i < sizeof(s->general)/sizeof(uint32); i++)
+        s->general[i] = qemu_get_be32(f);
+    qemu_get_buffer(f, s->mem_wkup, sizeof(s->mem_wkup));
+    qemu_get_buffer(f, s->padconfs_wkup, sizeof(s->padconfs_wkup));
+    for (i = 0; i < sizeof(s->general_wkup)/sizeof(uint32); i++)
+        s->general_wkup[i] = qemu_get_be32(f);
+
+    return 0;
+}
+
 #define PADCONFS_VALUE(wakeup0,wakeup1,offmode0,offmode1, \
                                                inputenable0,inputenable1,pupd0,pupd1,muxmode0,muxmode1,offset) \
        do { \
@@ -3379,6 +4004,8 @@ static struct omap3_scm_s *omap3_scm_init(struct omap_target_agent_s *ta,
                                       omap3_scm_writefn, s);
     omap_l4_attach(ta, 0, iomemtype);
     
+    register_savevm("omap3_scm", -1, 0,
+                    omap3_scm_save_state, omap3_scm_load_state, s);
     return s;
 }
 
@@ -3408,6 +4035,79 @@ struct omap3_sms_s
     uint32 sms_rot_physical_ba[12];
 };
 
+static void omap3_sms_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap3_sms_s *s = (struct omap3_sms_s *)opaque;
+    int i;
+
+    qemu_put_be32(f, s->sms_sysconfig);
+    qemu_put_be32(f, s->sms_sysstatus);
+    for (i = 0; i < 8; i++) {
+        qemu_put_be32(f, s->sms_rg_att[i]);
+        qemu_put_be32(f, s->sms_rg_rdperm[i]);
+        qemu_put_be32(f, s->sms_rg_wrperm[i]);
+        if (i < 7) {
+            qemu_put_be32(f, s->sms_rg_start[i]);
+            qemu_put_be32(f, s->sms_rg_end[i]);
+        }
+    }
+    qemu_put_be32(f, s->sms_security_control);
+    qemu_put_be32(f, s->sms_class_arbiter0);
+    qemu_put_be32(f, s->sms_class_arbiter1);
+    qemu_put_be32(f, s->sms_class_arbiter2);
+    qemu_put_be32(f, s->sms_interclass_arbiter);
+    qemu_put_be32(f, s->sms_class_rotation[0]);
+    qemu_put_be32(f, s->sms_class_rotation[1]);
+    qemu_put_be32(f, s->sms_class_rotation[2]);
+    qemu_put_be32(f, s->sms_err_addr);
+    qemu_put_be32(f, s->sms_err_type);
+    qemu_put_be32(f, s->sms_pow_ctrl);
+    for (i = 0; i< 12; i++) {
+        qemu_put_be32(f, s->sms_rot_control[i]);
+        qemu_put_be32(f, s->sms_rot_size[i]);
+        qemu_put_be32(f, s->sms_rot_physical_ba[i]);
+    }
+}
+
+static int omap3_sms_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap3_sms_s *s = (struct omap3_sms_s *)opaque;
+    int i;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    s->sms_sysconfig = qemu_get_be32(f);
+    s->sms_sysstatus = qemu_get_be32(f);
+    for (i = 0; i < 8; i++) {
+        s->sms_rg_att[i] = qemu_get_be32(f);
+        s->sms_rg_rdperm[i] = qemu_get_be32(f);
+        s->sms_rg_wrperm[i] = qemu_get_be32(f);
+        if (i < 7) {
+            s->sms_rg_start[i] = qemu_get_be32(f);
+            s->sms_rg_end[i] = qemu_get_be32(f);
+        }
+    }
+    s->sms_security_control = qemu_get_be32(f);
+    s->sms_class_arbiter0 = qemu_get_be32(f);
+    s->sms_class_arbiter1 = qemu_get_be32(f);
+    s->sms_class_arbiter2 = qemu_get_be32(f);
+    s->sms_interclass_arbiter = qemu_get_be32(f);
+    s->sms_class_rotation[0] = qemu_get_be32(f);
+    s->sms_class_rotation[1] = qemu_get_be32(f);
+    s->sms_class_rotation[2] = qemu_get_be32(f);
+    s->sms_err_addr = qemu_get_be32(f);
+    s->sms_err_type = qemu_get_be32(f);
+    s->sms_pow_ctrl = qemu_get_be32(f);
+    for (i = 0; i< 12; i++) {
+        s->sms_rot_control[i] = qemu_get_be32(f);
+        s->sms_rot_size[i] = qemu_get_be32(f);
+        s->sms_rot_physical_ba[i] = qemu_get_be32(f);
+    }
+    
+    return 0;
+}
+
 static uint32_t omap3_sms_read32(void *opaque, target_phys_addr_t addr)
 {
     struct omap3_sms_s *s = (struct omap3_sms_s *) opaque;
@@ -3707,11 +4407,11 @@ static struct omap3_sms_s *omap3_sms_init(struct omap_mpu_state_s *mpu)
                                        omap3_sms_writefn, s);
     cpu_register_physical_memory(0x6c000000, 0x10000, iomemtype);
 
+    register_savevm("omap3_sms", -1, 0,
+                    omap3_sms_save_state, omap3_sms_load_state, s);
     return s;
 }
 
-#define OMAP3_BOOT_ROM_SIZE 0x1c000 /* 80 + 32 kB */
-
 static const struct dma_irq_map omap3_dma_irq_map[] = {
     {0, OMAP_INT_3XXX_SDMA_IRQ0},
     {0, OMAP_INT_3XXX_SDMA_IRQ1},
@@ -3756,9 +4456,10 @@ struct omap_mpu_state_s *omap3530_mpu_init(unsigned long sdram_size,
     cpu_register_physical_memory(OMAP3_SRAM_BASE, s->sram_size,
                                  sram_base | IO_MEM_RAM);
     bootrom_base = qemu_ram_alloc(OMAP3XXX_BOOTROM_SIZE);
-    cpu_register_physical_memory(OMAP3_Q1_BASE + 0x14000, OMAP3_BOOT_ROM_SIZE,
+    cpu_register_physical_memory(OMAP3_Q1_BASE + 0x14000,
+                                 OMAP3XXX_BOOTROM_SIZE,
                                  bootrom_base | IO_MEM_ROM);
-    cpu_register_physical_memory(0, OMAP3_BOOT_ROM_SIZE,
+    cpu_register_physical_memory(0, OMAP3XXX_BOOTROM_SIZE,
                                  bootrom_base | IO_MEM_ROM);
 
     s->l4 = omap_l4_init(OMAP3_L4_BASE, 
index dc7b2b8..402db19 100644 (file)
@@ -668,6 +668,96 @@ static CPUWriteMemoryFunc *omap3_mmc_writefn[] = {
     omap3_mmc_write,
 };
 
+static void omap3_mmc_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap3_mmc_s *s = (struct omap3_mmc_s *)opaque;
+    int i;
+    
+    qemu_put_be32(f, s->sysconfig);
+    qemu_put_be32(f, s->sysstatus);
+    qemu_put_be32(f, s->csre);
+    qemu_put_be32(f, s->systest);
+    qemu_put_be32(f, s->con);
+    qemu_put_be32(f, s->pwcnt);
+    qemu_put_be32(f, s->blk);
+    qemu_put_be32(f, s->arg);
+    qemu_put_be32(f, s->cmd);
+    qemu_put_be32(f, s->rsp10);
+    qemu_put_be32(f, s->rsp32);
+    qemu_put_be32(f, s->rsp54);
+    qemu_put_be32(f, s->rsp76);
+    qemu_put_be32(f, s->data);
+    qemu_put_be32(f, s->pstate);
+    qemu_put_be32(f, s->hctl);
+    qemu_put_be32(f, s->sysctl);
+    qemu_put_be32(f, s->stat);
+    qemu_put_be32(f, s->ie);
+    qemu_put_be32(f, s->ise);
+    qemu_put_be32(f, s->ac12);
+    qemu_put_be32(f, s->capa);
+    qemu_put_be32(f, s->cur_capa);
+    qemu_put_be32(f, s->rev);
+    qemu_put_be16(f, s->blen_counter);
+    qemu_put_be16(f, s->nblk_counter);
+    for (i = 0; i < sizeof(s->fifo)/sizeof(uint32_t); i++)
+        qemu_put_be32(f, s->fifo[i]);
+    qemu_put_sbe32(f, s->fifo_start);
+    qemu_put_sbe32(f, s->fifo_len);
+    qemu_put_sbe32(f, s->ddir);
+    qemu_put_sbe32(f, s->transfer);
+    qemu_put_sbe32(f, s->stop);
+    qemu_put_be32(f, s->stat_pending);
+}
+
+static int omap3_mmc_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap3_mmc_s *s = (struct omap3_mmc_s *)opaque;
+    int i;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    s->sysconfig = qemu_get_be32(f);
+    s->sysstatus = qemu_get_be32(f);
+    s->csre = qemu_get_be32(f);
+    s->systest = qemu_get_be32(f);
+    s->con = qemu_get_be32(f);
+    s->pwcnt = qemu_get_be32(f);
+    s->blk = qemu_get_be32(f);
+    s->arg = qemu_get_be32(f);
+    s->cmd = qemu_get_be32(f);
+    s->rsp10 = qemu_get_be32(f);
+    s->rsp32 = qemu_get_be32(f);
+    s->rsp54 = qemu_get_be32(f);
+    s->rsp76 = qemu_get_be32(f);
+    s->data = qemu_get_be32(f);
+    s->pstate = qemu_get_be32(f);
+    s->hctl = qemu_get_be32(f);
+    s->sysctl = qemu_get_be32(f);
+    s->stat = qemu_get_be32(f);
+    s->ie = qemu_get_be32(f);
+    s->ise = qemu_get_be32(f);
+    s->ac12 = qemu_get_be32(f);
+    s->capa = qemu_get_be32(f);
+    s->cur_capa = qemu_get_be32(f);
+    s->rev = qemu_get_be32(f);
+    s->blen_counter = qemu_get_be16(f);
+    s->nblk_counter = qemu_get_be16(f);
+    for (i = 0; i < sizeof(s->fifo)/sizeof(uint32_t); i++)
+        s->fifo[i] = qemu_get_be32(f);
+    s->fifo_start = qemu_get_sbe32(f);
+    s->fifo_len = qemu_get_sbe32(f);
+    s->ddir = qemu_get_sbe32(f);
+    s->transfer = qemu_get_sbe32(f);
+    s->stop = qemu_get_sbe32(f);
+    s->stat_pending = qemu_get_be32(f);
+    
+    omap3_mmc_fifolevel_update(s);
+    omap3_mmc_interrupts_update(s);
+    
+    return 0;
+}
+
 struct omap3_mmc_s *omap3_mmc_init(struct omap_target_agent_s *ta,
                                    qemu_irq irq, qemu_irq dma[],
                                    omap_clk fclk, omap_clk iclk)
@@ -686,6 +776,8 @@ struct omap3_mmc_s *omap3_mmc_init(struct omap_target_agent_s *ta,
                                       omap3_mmc_writefn, s);
     omap_l4_attach(ta, 0, iomemtype);
 
+    register_savevm("omap3_mmc", (ta->base >> 12) & 0xff, 0,
+                    omap3_mmc_save_state, omap3_mmc_load_state, s);
     return s;
 }
 
index 5243bfb..fea0e91 100644 (file)
@@ -23,6 +23,7 @@
 #include "omap.h"
 #include "irq.h"
 #include "soc_dma.h"
+#include "hw.h"
 
 //#define OMAP_DMA_DEBUG
 
@@ -2031,8 +2032,7 @@ static void omap_dma4_write(void *opaque, target_phys_addr_t addr,
     case 0x40: /* DMA4_CCFN */
         /* f.ex. linux kernel writes zeroes to these registers as well
            when performing a DMA channel reset. let's just ignore the
-           writes instead of reporting "dummy" errors; that's what the
-           real hardware does as well */
+           writes instead of reporting "dummy" errors */
         /*OMAP_RO_REG(0x80 + chnum * 0x60 + addr);*/
         break;
 
@@ -2053,6 +2053,185 @@ static CPUWriteMemoryFunc *omap_dma4_writefn[] = {
     omap_dma4_write,
 };
 
+static void omap_dma4_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap_dma_s *s = (struct omap_dma_s *)opaque;
+    int i, j;
+        
+    qemu_put_be32(f, s->gcr);
+    qemu_put_be32(f, s->ocp);
+    for (i = 0; i < 5; i++) {
+        qemu_put_be32(f, s->caps[i]);
+        if (i < 4) {
+            qemu_put_be32(f, s->irqen[i]);
+            qemu_put_be32(f, s->irqstat[i]);
+        }
+    }
+    for (i = 0; i < 32; i++) {
+        qemu_put_be32(f, s->ch[i].elements);
+        qemu_put_be16(f, s->ch[i].frames);
+        qemu_put_sbe32(f, s->ch[i].data_type);
+        for (j = 0; j < 2; j++) {
+            qemu_put_sbe32(f, s->ch[i].burst[j]);
+            qemu_put_sbe32(f, s->ch[i].pack[j]);
+            qemu_put_sbe32(f, s->ch[i].endian[j]);
+            qemu_put_sbe32(f, s->ch[i].endian_lock[j]);
+            qemu_put_sbe32(f, s->ch[i].translate[j]);
+            qemu_put_sbe32(f, s->ch[i].port[j]);
+#if TARGET_PHYS_ADDR_BITS == 32
+            qemu_put_be32(f, s->ch[i].addr[j]);
+#elif TARGET_PHYS_ADDR_BITS == 64
+            qemu_put_be64(f, s->ch[i].addr[j]);
+#else
+#error TARGET_PHYS_ADDR_BITS undefined
+#endif
+            qemu_put_sbe32(f, s->ch[i].mode[j]);
+            qemu_put_sbe32(f, s->ch[i].frame_index[j]);
+            qemu_put_sbe16(f, s->ch[i].element_index[j]);
+        }
+        qemu_put_sbe32(f, s->ch[i].transparent_copy);
+        qemu_put_sbe32(f, s->ch[i].constant_fill);
+        qemu_put_be32(f, s->ch[i].color);
+        qemu_put_sbe32(f, s->ch[i].prefetch);
+        qemu_put_sbe32(f, s->ch[i].end_prog);
+        qemu_put_sbe32(f, s->ch[i].repeat);
+        qemu_put_sbe32(f, s->ch[i].auto_init);
+        qemu_put_sbe32(f, s->ch[i].link_enabled);
+        qemu_put_sbe32(f, s->ch[i].link_next_ch);
+        qemu_put_sbe32(f, s->ch[i].interrupts);
+        qemu_put_sbe32(f, s->ch[i].status);
+        qemu_put_sbe32(f, s->ch[i].cstatus);
+        qemu_put_sbe32(f, s->ch[i].active);
+        qemu_put_sbe32(f, s->ch[i].enable);
+        qemu_put_sbe32(f, s->ch[i].sync);
+        qemu_put_sbe32(f, s->ch[i].src_sync);
+        qemu_put_sbe32(f, s->ch[i].pending_request);
+        qemu_put_sbe32(f, s->ch[i].waiting_end_prog);
+        qemu_put_be16(f, s->ch[i].cpc);
+        qemu_put_sbe32(f, s->ch[i].set_update);
+        qemu_put_sbe32(f, s->ch[i].fs);
+        qemu_put_sbe32(f, s->ch[i].bs);
+        qemu_put_sbe32(f, s->ch[i].omap_3_1_compatible_disable);
+#if TARGET_PHYS_ADDR_BITS == 32
+        qemu_put_be32(f, s->ch[i].active_set.src);
+        qemu_put_be32(f, s->ch[i].active_set.dest);
+#elif TARGET_PHYS_ADDR_BITS == 64
+        qemu_put_be64(f, s->ch[i].active_set.src);
+        qemu_put_be64(f, s->ch[i].active_set.dest);
+#else
+#error TARGET_PHYS_ADDR_BITS undefined
+#endif
+        qemu_put_sbe32(f, s->ch[i].active_set.frame);
+        qemu_put_sbe32(f, s->ch[i].active_set.element);
+        qemu_put_sbe32(f, s->ch[i].active_set.pck_element);
+        qemu_put_sbe32(f, s->ch[i].active_set.frame_delta[0]);
+        qemu_put_sbe32(f, s->ch[i].active_set.frame_delta[1]);
+        qemu_put_sbe32(f, s->ch[i].active_set.elem_delta[0]);
+        qemu_put_sbe32(f, s->ch[i].active_set.elem_delta[1]);
+        qemu_put_sbe32(f, s->ch[i].active_set.frames);
+        qemu_put_sbe32(f, s->ch[i].active_set.elements);
+        qemu_put_sbe32(f, s->ch[i].active_set.pck_elements);
+        qemu_put_sbe32(f, s->ch[i].write_mode);
+        qemu_put_sbe32(f, s->ch[i].priority);
+        qemu_put_sbe32(f, s->ch[i].interleave_disabled);
+        qemu_put_sbe32(f, s->ch[i].type);
+        qemu_put_sbe32(f, s->ch[i].suspend);
+        qemu_put_sbe32(f, s->ch[i].buf_disable);
+    }
+}
+
+static int omap_dma4_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap_dma_s *s = (struct omap_dma_s *)opaque;
+    int i, j;
+
+    if (version_id)
+        return -EINVAL;
+
+    s->gcr = qemu_get_be32(f);
+    s->ocp = qemu_get_be32(f);
+    for (i = 0; i < 5; i++) {
+        s->caps[i] = qemu_get_be32(f);
+        if (i < 4) {
+            s->irqen[i] = qemu_get_be32(f);
+            s->irqstat[i] = qemu_get_be32(f);
+        }
+    }
+    for (i = 0; i < 32; i++) {
+        s->ch[i].elements = qemu_get_be32(f);
+        s->ch[i].frames = qemu_get_be16(f);
+        s->ch[i].data_type = qemu_get_sbe32(f);
+        for (j = 0; j < 2; j++) {
+            s->ch[i].burst[j] = qemu_get_sbe32(f);
+            s->ch[i].pack[j] = qemu_get_sbe32(f);
+            s->ch[i].endian[j] = qemu_get_sbe32(f);
+            s->ch[i].endian_lock[j] = qemu_get_sbe32(f);
+            s->ch[i].translate[j] = qemu_get_sbe32(f);
+            s->ch[i].port[j] = qemu_get_sbe32(f);
+#if TARGET_PHYS_ADDR_BITS == 32
+            s->ch[i].addr[j] = qemu_get_be32(f);
+#elif TARGET_PHYS_ADDR_BITS == 64
+            s->ch[i].addr[j] = qemu_get_be64(f);
+#else
+#error TARGET_PHYS_ADDR_BITS undefined
+#endif
+            s->ch[i].mode[j] = qemu_get_sbe32(f);
+            s->ch[i].frame_index[j] = qemu_get_sbe32(f);
+            s->ch[i].element_index[j] = qemu_get_sbe16(f);
+        }
+        s->ch[i].transparent_copy = qemu_get_sbe32(f);
+        s->ch[i].constant_fill = qemu_get_sbe32(f);
+        s->ch[i].color = qemu_get_be32(f);
+        s->ch[i].prefetch = qemu_get_sbe32(f);
+        s->ch[i].end_prog = qemu_get_sbe32(f);
+        s->ch[i].repeat = qemu_get_sbe32(f);
+        s->ch[i].auto_init = qemu_get_sbe32(f);
+        s->ch[i].link_enabled = qemu_get_sbe32(f);
+        s->ch[i].link_next_ch = qemu_get_sbe32(f);
+        s->ch[i].interrupts = qemu_get_sbe32(f);
+        s->ch[i].status = qemu_get_sbe32(f);
+        s->ch[i].cstatus = qemu_get_sbe32(f);
+        s->ch[i].active = qemu_get_sbe32(f);
+        s->ch[i].enable = qemu_get_sbe32(f);
+        s->ch[i].sync = qemu_get_sbe32(f);
+        s->ch[i].src_sync = qemu_get_sbe32(f);
+        s->ch[i].pending_request = qemu_get_sbe32(f);
+        s->ch[i].waiting_end_prog = qemu_get_sbe32(f);
+        s->ch[i].cpc = qemu_get_be16(f);
+        s->ch[i].set_update = qemu_get_sbe32(f);
+        s->ch[i].fs = qemu_get_sbe32(f);
+        s->ch[i].bs = qemu_get_sbe32(f);
+        s->ch[i].omap_3_1_compatible_disable = qemu_get_sbe32(f);
+#if TARGET_PHYS_ADDR_BITS == 32
+        s->ch[i].active_set.src = qemu_get_be32(f);
+        s->ch[i].active_set.dest = qemu_get_be32(f);
+#elif TARGET_PHYS_ADDR_BITS == 64
+        s->ch[i].active_set.src = qemu_get_be64(f);
+        s->ch[i].active_set.dest = qemu_get_be64(f);
+#else
+#error TARGET_PHYS_ADDR_BITS undefined
+#endif
+        s->ch[i].active_set.frame = qemu_get_sbe32(f);
+        s->ch[i].active_set.element = qemu_get_sbe32(f);
+        s->ch[i].active_set.pck_element = qemu_get_sbe32(f);
+        s->ch[i].active_set.frame_delta[0] = qemu_get_sbe32(f);
+        s->ch[i].active_set.frame_delta[1] = qemu_get_sbe32(f);
+        s->ch[i].active_set.elem_delta[0] = qemu_get_sbe32(f);
+        s->ch[i].active_set.elem_delta[1] = qemu_get_sbe32(f);
+        s->ch[i].active_set.frames = qemu_get_sbe32(f);
+        s->ch[i].active_set.elements = qemu_get_sbe32(f);
+        s->ch[i].active_set.pck_elements = qemu_get_sbe32(f);
+        s->ch[i].write_mode = qemu_get_sbe32(f);
+        s->ch[i].priority = qemu_get_sbe32(f);
+        s->ch[i].interleave_disabled = qemu_get_sbe32(f);
+        s->ch[i].type = qemu_get_sbe32(f);
+        s->ch[i].suspend = qemu_get_sbe32(f);
+        s->ch[i].buf_disable = qemu_get_sbe32(f);
+    }
+    
+    return 0;
+}
+    
 struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
                 struct omap_mpu_state_s *mpu, int fifo,
                 int chans, omap_clk iclk, omap_clk fclk)
@@ -2091,6 +2270,9 @@ struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
 
     mpu->drq = s->dma->drq;
 
+    register_savevm("omap_dma4", -1, 0,
+                    omap_dma4_save_state, omap_dma4_load_state, s);
+    
     return s->dma;
 }
 
index 45d6cb1..61a3f46 100644 (file)
@@ -154,6 +154,217 @@ static void omap_dss_interrupt_update(struct omap_dss_s *s)
                  | (s->dispc.irqst & s->dispc.irqen));
 }
 
+static void omap_dss_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap_dss_s *s = (struct omap_dss_s *)opaque;
+    int i, j;
+    
+    qemu_put_sbe32(f, s->autoidle);
+    qemu_put_sbe32(f, s->control);
+    qemu_put_be32(f, s->sdi_control);
+    qemu_put_be32(f, s->pll_control);
+    qemu_put_sbe32(f, s->enable);
+    qemu_put_sbe32(f, s->dig.enable);
+    qemu_put_sbe32(f, s->dig.nx);
+    qemu_put_sbe32(f, s->dig.ny);
+    qemu_put_sbe32(f, s->dig.x);
+    qemu_put_sbe32(f, s->dig.y);
+    qemu_put_sbe32(f, s->lcd.enable);
+    qemu_put_sbe32(f, s->lcd.nx);
+    qemu_put_sbe32(f, s->lcd.ny);
+    qemu_put_sbe32(f, s->lcd.x);
+    qemu_put_sbe32(f, s->lcd.y);
+    qemu_put_be32(f, s->dispc.idlemode);
+    qemu_put_be32(f, s->dispc.irqst);
+    qemu_put_be32(f, s->dispc.irqen);
+    qemu_put_be32(f, s->dispc.control);
+    qemu_put_be32(f, s->dispc.config);
+    qemu_put_be32(f, s->dispc.capable);
+    qemu_put_be32(f, s->dispc.timing[0]);
+    qemu_put_be32(f, s->dispc.timing[1]);
+    qemu_put_be32(f, s->dispc.timing[2]);
+    qemu_put_be32(f, s->dispc.timing[3]);
+    qemu_put_sbe32(f, s->dispc.line);
+    qemu_put_be32(f, s->dispc.bg[0]);
+    qemu_put_be32(f, s->dispc.bg[1]);
+    qemu_put_be32(f, s->dispc.trans[0]);
+    qemu_put_be32(f, s->dispc.trans[1]);
+    qemu_put_be32(f, s->dispc.global_alpha);
+    qemu_put_be32(f, s->dispc.cpr_coef_r);
+    qemu_put_be32(f, s->dispc.cpr_coef_g);
+    qemu_put_be32(f, s->dispc.cpr_coef_b);
+    for (i = 0; i < 3; i++) {
+        qemu_put_sbe32(f, s->dispc.l[i].enable);
+        qemu_put_sbe32(f, s->dispc.l[i].bpp);
+        qemu_put_sbe32(f, s->dispc.l[i].posx);
+        qemu_put_sbe32(f, s->dispc.l[i].posy);
+        qemu_put_sbe32(f, s->dispc.l[i].nx);
+        qemu_put_sbe32(f, s->dispc.l[i].ny);
+        qemu_put_sbe32(f, s->dispc.l[i].rotation_flag);
+        qemu_put_sbe32(f, s->dispc.l[i].gfx_format);
+        qemu_put_sbe32(f, s->dispc.l[i].gfx_channel);
+        for (j = 0; j < 3; j++) {
+#if TARGET_PHYS_ADDR_BITS == 32
+            qemu_put_be32(f, s->dispc.l[i].addr[j]);
+#elif TARGET_PHYS_ADDR_BITS == 64
+            qemu_put_be64(f, s->dispc.l[i].addr[j]);
+#else
+#error TARGET_PHYS_ADDR_BITS undefined
+#endif
+        }
+        qemu_put_be32(f, s->dispc.l[i].attr);
+        qemu_put_be32(f, s->dispc.l[i].tresh);
+        qemu_put_sbe32(f, s->dispc.l[i].rowinc);
+        qemu_put_sbe32(f, s->dispc.l[i].colinc);
+        qemu_put_sbe32(f, s->dispc.l[i].wininc);
+        qemu_put_be32(f, s->dispc.l[i].preload);
+        qemu_put_be32(f, s->dispc.l[i].fir);
+        for (j = 0; j < 8; j++) {
+            qemu_put_be32(f, s->dispc.l[i].fir_coef_h[j]);
+            qemu_put_be32(f, s->dispc.l[i].fir_coef_hv[j]);
+            qemu_put_be32(f, s->dispc.l[i].fir_coef_v[j]);
+            if (j < 5)
+                qemu_put_be32(f, s->dispc.l[i].conv_coef[j]);
+        }
+        qemu_put_be32(f, s->dispc.l[i].picture_size);
+        qemu_put_be32(f, s->dispc.l[i].accu[0]);
+        qemu_put_be32(f, s->dispc.l[i].accu[1]);
+    }
+    qemu_put_sbe32(f, s->dispc.invalidate);
+    for (i = 0; i < 256; i++)
+        qemu_put_be16(f, s->dispc.palette[i]);
+    qemu_put_sbe32(f, s->rfbi.idlemode);
+    qemu_put_be32(f, s->rfbi.control);
+    qemu_put_sbe32(f, s->rfbi.enable);
+    qemu_put_sbe32(f, s->rfbi.pixels);
+    qemu_put_sbe32(f, s->rfbi.busy);
+    qemu_put_sbe32(f, s->rfbi.skiplines);
+    qemu_put_be16(f, s->rfbi.rxbuf);
+    for (i = 0; i < 6; i++) {
+        if (i < 2)
+            qemu_put_be32(f, s->rfbi.config[i]);
+        if (i < 4)
+            qemu_put_be32(f, s->rfbi.time[i]);
+        qemu_put_be32(f, s->rfbi.data[i]);
+    }
+    qemu_put_be16(f, s->rfbi.vsync);
+    qemu_put_be16(f, s->rfbi.hsync);
+    qemu_put_be32(f, s->dsi.irqst);
+    qemu_put_be32(f, s->dsi.irqen);
+}
+
+static int omap_dss_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap_dss_s *s = (struct omap_dss_s *)opaque;
+    int i, j;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    s->autoidle = qemu_get_sbe32(f);
+    s->control = qemu_get_sbe32(f);
+    s->sdi_control = qemu_get_be32(f);
+    s->pll_control = qemu_get_be32(f);
+    s->enable = qemu_get_sbe32(f);
+    s->dig.enable = qemu_get_sbe32(f);
+    s->dig.nx = qemu_get_sbe32(f);
+    s->dig.ny = qemu_get_sbe32(f);
+    s->dig.x = qemu_get_sbe32(f);
+    s->dig.y = qemu_get_sbe32(f);
+    s->lcd.enable = qemu_get_sbe32(f);
+    s->lcd.nx = qemu_get_sbe32(f);
+    s->lcd.ny = qemu_get_sbe32(f);
+    s->lcd.x = qemu_get_sbe32(f);
+    s->lcd.y = qemu_get_sbe32(f);
+    s->dispc.idlemode = qemu_get_be32(f);
+    s->dispc.irqst = qemu_get_be32(f);
+    s->dispc.irqen = qemu_get_be32(f);
+    s->dispc.control = qemu_get_be32(f);
+    s->dispc.config = qemu_get_be32(f);
+    s->dispc.capable = qemu_get_be32(f);
+    s->dispc.timing[0] = qemu_get_be32(f);
+    s->dispc.timing[1] = qemu_get_be32(f);
+    s->dispc.timing[2] = qemu_get_be32(f);
+    s->dispc.timing[3] = qemu_get_be32(f);
+    s->dispc.line = qemu_get_sbe32(f);
+    s->dispc.bg[0] = qemu_get_be32(f);
+    s->dispc.bg[1] = qemu_get_be32(f);
+    s->dispc.trans[0] = qemu_get_be32(f);
+    s->dispc.trans[1] = qemu_get_be32(f);
+    s->dispc.global_alpha = qemu_get_be32(f);
+    s->dispc.cpr_coef_r = qemu_get_be32(f);
+    s->dispc.cpr_coef_g = qemu_get_be32(f);
+    s->dispc.cpr_coef_b = qemu_get_be32(f);
+    for (i = 0; i < 3; i++) {
+        s->dispc.l[i].enable = qemu_get_sbe32(f);
+        s->dispc.l[i].bpp = qemu_get_sbe32(f);
+        s->dispc.l[i].posx = qemu_get_sbe32(f);
+        s->dispc.l[i].posy = qemu_get_sbe32(f);
+        s->dispc.l[i].nx = qemu_get_sbe32(f);
+        s->dispc.l[i].ny = qemu_get_sbe32(f);
+        s->dispc.l[i].rotation_flag = qemu_get_sbe32(f);
+        s->dispc.l[i].gfx_format = qemu_get_sbe32(f);
+        s->dispc.l[i].gfx_channel = qemu_get_sbe32(f);
+        for (j = 0; j < 3; j++) {
+#if TARGET_PHYS_ADDR_BITS == 32
+            s->dispc.l[i].addr[j] = qemu_get_be32(f);
+#elif TARGET_PHYS_ADDR_BITS == 64
+            s->dispc.l[i].addr[j] = qemu_get_be64(f);
+#else
+#error TARGET_PHYS_ADDR_BITS undefined
+#endif
+        }
+        s->dispc.l[i].attr = qemu_get_be32(f);
+        s->dispc.l[i].tresh = qemu_get_be32(f);
+        s->dispc.l[i].rowinc = qemu_get_sbe32(f);
+        s->dispc.l[i].colinc = qemu_get_sbe32(f);
+        s->dispc.l[i].wininc = qemu_get_sbe32(f);
+        s->dispc.l[i].preload = qemu_get_be32(f);
+        s->dispc.l[i].fir = qemu_get_be32(f);
+        for (j = 0; j < 8; j++) {
+            s->dispc.l[i].fir_coef_h[j] = qemu_get_be32(f);
+            s->dispc.l[i].fir_coef_hv[j] = qemu_get_be32(f);
+            s->dispc.l[i].fir_coef_v[j] = qemu_get_be32(f);
+            if (j < 5)
+                s->dispc.l[i].conv_coef[j] = qemu_get_be32(f);
+        }
+        s->dispc.l[i].picture_size = qemu_get_be32(f);
+        s->dispc.l[i].accu[0] = qemu_get_be32(f);
+        s->dispc.l[i].accu[1] = qemu_get_be32(f);
+    }
+    s->dispc.invalidate = qemu_get_sbe32(f);
+    for (i = 0; i < 256; i++)
+        s->dispc.palette[i] = qemu_get_be16(f);
+    s->rfbi.idlemode = qemu_get_sbe32(f);
+    s->rfbi.control = qemu_get_be32(f);
+    s->rfbi.enable = qemu_get_sbe32(f);
+    s->rfbi.pixels = qemu_get_sbe32(f);
+    s->rfbi.busy = qemu_get_sbe32(f);
+    s->rfbi.skiplines = qemu_get_sbe32(f);
+    s->rfbi.rxbuf = qemu_get_be16(f);
+    for (i = 0; i < 6; i++) {
+        if (i < 2)
+            s->rfbi.config[i] = qemu_get_be32(f);
+        if (i < 4)
+            s->rfbi.time[i] = qemu_get_be32(f);
+        s->rfbi.data[i] = qemu_get_be32(f);
+    }
+    s->rfbi.vsync = qemu_get_be16(f);
+    s->rfbi.hsync = qemu_get_be16(f);
+    s->dsi.irqst = qemu_get_be32(f);
+    s->dsi.irqen = qemu_get_be32(f);
+    
+    s->dispc.invalidate = 1; /* force refresh of display parameters */
+    if (s->omap_lcd_panel[0])
+        s->omap_lcd_panel[0]->invalidate = 1;
+    if (s->omap_lcd_panel[1])
+        s->omap_lcd_panel[1]->invalidate = 1;
+    
+    omap_dss_interrupt_update(s);
+
+    return 0;
+}
+
 static void omap_rfbi_reset(struct omap_dss_s *s)
 {
     s->rfbi.idlemode = 0;
@@ -1498,6 +1709,9 @@ struct omap_dss_s *omap_dss_init(struct omap_mpu_state_s *mpu,
                                     omap_invalidate_display, omap_screen_dump, s);
 #endif
 
+    register_savevm("omap_dss", -1, 0,
+                    omap_dss_save_state, omap_dss_load_state, s);
+    
     return s;
 }
 
index f9b339c..f570776 100644 (file)
@@ -645,6 +645,71 @@ static CPUWriteMemoryFunc *omap_i2c_writefn[] = {
     omap_badwidth_write16,
 };
 
+static void omap_i2c_save_state(QEMUFile *f, void *opaque)
+{
+    struct omap_i2c_s *s = (struct omap_i2c_s *)opaque;
+    
+    /* TODO: slave setup(s) */
+    qemu_put_be16(f, s->mask);
+    qemu_put_be16(f, s->stat);
+    qemu_put_be16(f, s->we);
+    qemu_put_be16(f, s->dma);
+    qemu_put_be16(f, s->count);
+    qemu_put_sbe32(f, s->count_cur);
+    qemu_put_be16(f, s->sysc);
+    qemu_put_be16(f, s->control);
+    qemu_put_be16(f, s->own_addr[0]);
+    qemu_put_be16(f, s->own_addr[1]);
+    qemu_put_be16(f, s->own_addr[2]);
+    qemu_put_be16(f, s->own_addr[3]);
+    qemu_put_be16(f, s->slave_addr);
+    qemu_put_byte(f, s->sblock);
+    qemu_put_byte(f, s->divider);
+    qemu_put_be16(f, s->times[0]);
+    qemu_put_be16(f, s->times[1]);
+    qemu_put_be16(f, s->test);
+    qemu_put_sbe32(f, s->fifostart);
+    qemu_put_sbe32(f, s->fifolen);
+    qemu_put_sbe32(f, s->fifosize);
+    qemu_put_buffer(f, s->fifo, sizeof(s->fifo));
+}
+
+static int omap_i2c_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct omap_i2c_s *s = (struct omap_i2c_s *)opaque;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    /* TODO: slave setup(s) */
+    s->mask = qemu_get_be16(f);
+    s->stat = qemu_get_be16(f);
+    s->we = qemu_get_be16(f);
+    s->dma = qemu_get_be16(f);
+    s->count = qemu_get_be16(f);
+    s->count_cur = qemu_get_sbe32(f);
+    s->sysc = qemu_get_be16(f);
+    s->control = qemu_get_be16(f);
+    s->own_addr[0] = qemu_get_be16(f);
+    s->own_addr[1] = qemu_get_be16(f);
+    s->own_addr[2] = qemu_get_be16(f);
+    s->own_addr[3] = qemu_get_be16(f);
+    s->slave_addr = qemu_get_be16(f);
+    s->sblock = qemu_get_byte(f);
+    s->divider = qemu_get_byte(f);
+    s->times[0] = qemu_get_be16(f);
+    s->times[1] = qemu_get_be16(f);
+    s->test = qemu_get_be16(f);
+    s->fifostart = qemu_get_sbe32(f);
+    s->fifolen = qemu_get_sbe32(f);
+    s->fifosize = qemu_get_sbe32(f);
+    qemu_get_buffer(f, s->fifo, sizeof(s->fifo));
+
+    omap_i2c_interrupts_update(s);
+    
+    return 0;
+}
+
 struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
                 qemu_irq irq, qemu_irq *dma, omap_clk clk)
 {
@@ -725,6 +790,8 @@ struct omap_i2c_s *omap3_i2c_init(struct omap_target_agent_s *ta,
                                       omap_i2c_writefn, s);
     omap_l4_attach(ta, 0, iomemtype);
     
+    register_savevm("omap3_i2c", (ta->base >> 12) & 0xff, 0,
+                    omap_i2c_save_state, omap_i2c_load_state, s);
     return s;
 }
 
diff --git a/hw/sd.c b/hw/sd.c
index 030da32..e12fd99 100644 (file)
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -369,14 +369,14 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv)
 
     bdrv_get_geometry(bdrv, &sect);
     sect <<= 9;
-
+    
     if (sect > 0x40000000)
         size = 0x40000000;     /* 1 gig */
     else
         size = sect + 1;
-
+    
     sect = (size >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)) + 1;
-
+    
     sd->state = sd_idle_state;
     sd->rca = 0x0000;
     sd_set_ocr(sd);
@@ -410,6 +410,95 @@ static void sd_cardchange(void *opaque)
     }
 }
 
+static void sd_save_state(QEMUFile *f, void *opaque)
+{
+    struct SDState *s = (struct SDState *)opaque;
+    int i;
+    uint32_t wpgc = (s->size >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)) + 1;
+    char *filename;
+    
+    filename = qemu_mallocz(1024);
+    bdrv_get_backing_filename(s->bdrv, filename, 1024);
+    qemu_put_buffer(f, (uint8_t *)filename, 1024);
+    free(filename);
+    
+    qemu_put_sbe32(f, s->mode);
+    qemu_put_sbe32(f, s->state);
+    qemu_put_be32(f, s->ocr);
+    qemu_put_buffer(f, s->scr, sizeof(s->scr));
+    qemu_put_buffer(f, s->cid, sizeof(s->cid));
+    qemu_put_buffer(f, s->csd, sizeof(s->csd));
+    qemu_put_be16(f, s->rca);
+    qemu_put_be32(f, s->card_status);
+    qemu_put_buffer(f, s->sd_status, sizeof(s->sd_status));
+    qemu_put_be32(f, s->vhs);
+    for (i = 0; i < wpgc; i++)
+        qemu_put_sbe32(f, s->wp_groups[i]);
+    qemu_put_sbe32(f, s->blk_len);
+    qemu_put_be32(f, s->erase_start);
+    qemu_put_be32(f, s->erase_end);
+    qemu_put_buffer(f, s->pwd, sizeof(s->pwd));
+    qemu_put_sbe32(f, s->pwd_len);
+    for (i = 0; i < 6; i++)
+        qemu_put_sbe32(f, s->function_group[i]);
+    qemu_put_sbe32(f, s->current_cmd);
+    qemu_put_sbe32(f, s->blk_written);
+    qemu_put_be32(f, s->data_start);
+    qemu_put_be32(f, s->data_offset);
+    qemu_put_buffer(f, s->data, sizeof(s->data));
+    qemu_put_buffer(f, s->buf, 512);
+    qemu_put_sbe32(f, s->enable);
+}
+
+static int sd_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct SDState *s = (struct SDState *)opaque;
+    int i;
+    uint32_t wpgc = (s->size >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)) + 1;
+    char *filename1, *filename2;
+    int result = 0;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    filename1 = qemu_mallocz(1024);
+    filename2 = qemu_mallocz(1024);
+    bdrv_get_backing_filename(s->bdrv, filename1, 1024);
+    qemu_get_buffer(f, (uint8_t *)filename2, 1024);
+    if (!strcmp(filename1, filename2)) {
+        s->mode = qemu_get_sbe32(f);
+        s->state = qemu_get_sbe32(f);
+        s->ocr = qemu_get_be32(f);
+        qemu_get_buffer(f, s->scr, sizeof(s->scr));
+        qemu_get_buffer(f, s->cid, sizeof(s->cid));
+        qemu_get_buffer(f, s->csd, sizeof(s->csd));
+        s->rca = qemu_get_be16(f);
+        s->card_status = qemu_get_be32(f);
+        qemu_get_buffer(f, s->sd_status, sizeof(s->sd_status));
+        s->vhs = qemu_get_be32(f);
+        for (i = 0; i < wpgc; i++)
+            s->wp_groups[i] = qemu_get_sbe32(f);
+        s->blk_len = qemu_get_sbe32(f);
+        s->erase_start = qemu_get_be32(f);
+        s->erase_end = qemu_get_be32(f);
+        qemu_get_buffer(f, s->pwd, sizeof(s->pwd));
+        s->pwd_len = qemu_get_sbe32(f);
+        for (i = 0; i < 6; i++)
+            s->function_group[i] = qemu_get_sbe32(f);
+        s->current_cmd = qemu_get_sbe32(f);
+        s->blk_written = qemu_get_sbe32(f);
+        s->data_start = qemu_get_be32(f);
+        s->data_offset = qemu_get_be32(f);
+        qemu_get_buffer(f, s->data, sizeof(s->data));
+        qemu_get_buffer(f, s->buf, 512);
+        s->enable = qemu_get_sbe32(f);
+    } else 
+        result = -EINVAL;
+    free(filename2);
+    free(filename1);
+    return result;
+}
+
 /* We do not model the chip select pin, so allow the board to select
    whether card should be in SSI or MMC/SD mode.  It is also up to the
    board to ensure that ssi transfers only occur when the chip select
@@ -417,6 +506,7 @@ static void sd_cardchange(void *opaque)
 SDState *sd_init(BlockDriverState *bs, int is_spi)
 {
     SDState *sd;
+    static int instance_number = 1;
 
     sd = (SDState *) qemu_mallocz(sizeof(SDState));
     sd->buf = qemu_memalign(512, 512);
@@ -424,6 +514,8 @@ SDState *sd_init(BlockDriverState *bs, int is_spi)
     sd->enable = 1;
     sd_reset(sd, bs);
     bdrv_set_change_cb(sd->bdrv, sd_cardchange, sd);
+    register_savevm("sd", instance_number++, 0,
+                    sd_save_state, sd_load_state, sd);
     return sd;
 }
 
index 2967b52..0fef249 100644 (file)
@@ -21,6 +21,7 @@
 #include "qemu-common.h"
 #include "qemu-timer.h"
 #include "soc_dma.h"
+#include "hw.h"
 
 static void transfer_mem2mem(struct soc_dma_ch_s *ch)
 {
@@ -235,6 +236,73 @@ void soc_dma_reset(struct soc_dma_s *soc)
     soc_dma_ch_freq_update(s);
 }
 
+static void soc_dma_save_state(QEMUFile *f, void *opaque)
+{
+    struct dma_s *s = (struct dma_s *)opaque;
+    int i;
+    
+    qemu_put_be64(f, s->soc.drqbmp);
+    qemu_put_sbe64(f, s->soc.freq);
+    qemu_put_be64(f, s->ch_enable_mask);
+    qemu_put_sbe64(f, s->channel_freq);
+    qemu_put_sbe32(f, s->enabled_count);
+    for (i = 0; i < s->chnum; i++) {
+        qemu_put_timer(f, s->ch[i].timer);
+        qemu_put_sbe32(f, s->ch[i].enable);
+        qemu_put_sbe32(f, s->ch[i].update);
+        qemu_put_sbe32(f, s->ch[i].bytes);
+        qemu_put_sbe32(f, s->ch[i].type[0]);
+        qemu_put_sbe32(f, s->ch[i].type[1]);
+#if TARGET_PHYS_ADDR_BITS == 32
+        qemu_put_be32(f, s->ch[i].vaddr[0]);
+        qemu_put_be32(f, s->ch[i].vaddr[1]);
+#elif TARGET_PHYS_ADDR_BITS == 64
+        qemu_put_be64(f, s->ch[i].vaddr[0]);
+        qemu_put_be64(f, s->ch[i].vaddr[1]);
+#else
+#error TARGET_PHYS_ADDR_BITS undefined
+#endif
+        qemu_put_sbe32(f, s->ch[i].running);
+    }
+}
+
+static int soc_dma_load_state(QEMUFile *f, void *opaque, int version_id)
+{
+    struct dma_s *s = (struct dma_s *)opaque;
+    int i;
+    
+    if (version_id)
+        return -EINVAL;
+    
+    s->soc.drqbmp = qemu_get_be64(f);
+    s->soc.freq = qemu_get_sbe64(f);
+    s->ch_enable_mask = qemu_get_be64(f);
+    s->channel_freq = qemu_get_sbe64(f);
+    s->enabled_count = qemu_get_sbe32(f);
+    for (i = 0; i < s->chnum; i++) {
+        qemu_get_timer(f, s->ch[i].timer);
+        s->ch[i].enable = qemu_get_sbe32(f);
+        s->ch[i].update = qemu_get_sbe32(f);
+        s->ch[i].bytes = qemu_get_sbe32(f);
+        s->ch[i].type[0] = qemu_get_sbe32(f);
+        s->ch[i].type[1] = qemu_get_sbe32(f);
+#if TARGET_PHYS_ADDR_BITS == 32
+        s->ch[i].vaddr[0] = qemu_get_be32(f);
+        s->ch[i].vaddr[1] = qemu_get_be32(f);
+#elif TARGET_PHYS_ADDR_BITS == 64
+        s->ch[i].vaddr[0] = qemu_get_be64(f);
+        s->ch[i].vaddr[1] = qemu_get_be64(f);
+#else
+#error TARGET_PHYS_ADDR_BITS undefined
+#endif
+        s->ch[i].running = qemu_get_sbe32(f);
+        
+        soc_dma_ch_update(&s->ch[i]);
+    }
+    
+    return 0;
+}
+
 /* TODO: take a functional-clock argument */
 struct soc_dma_s *soc_dma_init(int n)
 {
@@ -252,6 +320,8 @@ struct soc_dma_s *soc_dma_init(int n)
     soc_dma_reset(&s->soc);
     fifo_size = 0;
 
+    register_savevm("soc_dma", -1, 0,
+                    soc_dma_save_state, soc_dma_load_state, s);
     return &s->soc;
 }