]> git.proxmox.com Git - qemu.git/blobdiff - hw/zaurus.c
Merge remote-tracking branch 'riku/linux-user-for-upstream' into staging
[qemu.git] / hw / zaurus.c
index 482834fb7b52e293e2c1b6775acd951b27fa53cb..c24aeb5763e36e9e1a2248b6c837861f8d4a44b8 100644 (file)
  * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "hw.h"
-#include "pxa.h"
 #include "sharpsl.h"
+#include "sysbus.h"
 
 #undef REG_FMT
-#if TARGET_PHYS_ADDR_BITS == 32
-#define REG_FMT                        "0x%02x"
-#else
 #define REG_FMT                        "0x%02lx"
-#endif
 
 /* SCOOP devices */
 
-struct scoop_info_s {
+typedef struct ScoopInfo ScoopInfo;
+struct ScoopInfo {
+    SysBusDevice busdev;
     qemu_irq handler[16];
-    qemu_irq *in;
     uint16_t status;
     uint16_t power;
     uint32_t gpio_level;
@@ -58,7 +54,7 @@ struct scoop_info_s {
 #define SCOOP_GPWR     0x24
 #define SCOOP_GPRR     0x28
 
-static inline void scoop_gpio_handler_update(struct scoop_info_s *s) {
+static inline void scoop_gpio_handler_update(ScoopInfo *s) {
     uint32_t level, diff;
     int bit;
     level = s->gpio_level & s->gpio_dir;
@@ -73,9 +69,9 @@ static inline void scoop_gpio_handler_update(struct scoop_info_s *s) {
 
 static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr)
 {
-    struct scoop_info_s *s = (struct scoop_info_s *) opaque;
+    ScoopInfo *s = (ScoopInfo *) opaque;
 
-    switch (addr) {
+    switch (addr & 0x3f) {
     case SCOOP_MCR:
         return s->mcr;
     case SCOOP_CDR:
@@ -98,7 +94,7 @@ static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr)
     case SCOOP_GPRR:
         return s->gpio_level;
     default:
-        zaurus_printf("Bad register offset " REG_FMT "\n", addr);
+        zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr);
     }
 
     return 0;
@@ -106,10 +102,10 @@ static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr)
 
 static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
 {
-    struct scoop_info_s *s = (struct scoop_info_s *) opaque;
+    ScoopInfo *s = (ScoopInfo *) opaque;
     value &= 0xffff;
 
-    switch (addr) {
+    switch (addr & 0x3f) {
     case SCOOP_MCR:
         s->mcr = value;
         break;
@@ -143,24 +139,24 @@ static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
         scoop_gpio_handler_update(s);
         break;
     default:
-        zaurus_printf("Bad register offset " REG_FMT "\n", addr);
+        zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr);
     }
 }
 
-static CPUReadMemoryFunc *scoop_readfn[] = {
+static CPUReadMemoryFunc * const scoop_readfn[] = {
     scoop_readb,
     scoop_readb,
     scoop_readb,
 };
-static CPUWriteMemoryFunc *scoop_writefn[] = {
+static CPUWriteMemoryFunc * const scoop_writefn[] = {
     scoop_writeb,
     scoop_writeb,
     scoop_writeb,
 };
 
-void scoop_gpio_set(void *opaque, int line, int level)
+static void scoop_gpio_set(void *opaque, int line, int level)
 {
-    struct scoop_info_s *s = (struct scoop_info_s *) s;
+    ScoopInfo *s = (ScoopInfo *) opaque;
 
     if (level)
         s->gpio_level |= (1 << line);
@@ -168,77 +164,83 @@ void scoop_gpio_set(void *opaque, int line, int level)
         s->gpio_level &= ~(1 << line);
 }
 
-qemu_irq *scoop_gpio_in_get(struct scoop_info_s *s)
+static int scoop_init(SysBusDevice *dev)
 {
-    return s->in;
-}
+    ScoopInfo *s = FROM_SYSBUS(ScoopInfo, dev);
+    int iomemtype;
 
-void scoop_gpio_out_set(struct scoop_info_s *s, int line,
-                qemu_irq handler) {
-    if (line >= 16) {
-        fprintf(stderr, "No GPIO pin %i\n", line);
-        exit(-1);
-    }
+    s->status = 0x02;
+    qdev_init_gpio_out(&s->busdev.qdev, s->handler, 16);
+    qdev_init_gpio_in(&s->busdev.qdev, scoop_gpio_set, 16);
+    iomemtype = cpu_register_io_memory(scoop_readfn,
+                    scoop_writefn, s, DEVICE_NATIVE_ENDIAN);
 
-    s->handler[line] = handler;
-}
+    sysbus_init_mmio(dev, 0x1000, iomemtype);
 
-static void scoop_save(QEMUFile *f, void *opaque)
-{
-    struct scoop_info_s *s = (struct scoop_info_s *) opaque;
-    qemu_put_be16s(f, &s->status);
-    qemu_put_be16s(f, &s->power);
-    qemu_put_be32s(f, &s->gpio_level);
-    qemu_put_be32s(f, &s->gpio_dir);
-    qemu_put_be32s(f, &s->prev_level);
-    qemu_put_be16s(f, &s->mcr);
-    qemu_put_be16s(f, &s->cdr);
-    qemu_put_be16s(f, &s->ccr);
-    qemu_put_be16s(f, &s->irr);
-    qemu_put_be16s(f, &s->imr);
-    qemu_put_be16s(f, &s->isr);
+    return 0;
 }
 
-static int scoop_load(QEMUFile *f, void *opaque, int version_id)
+static int scoop_post_load(void *opaque, int version_id)
 {
-    uint16_t dummy;
-    struct scoop_info_s *s = (struct scoop_info_s *) opaque;
-    qemu_get_be16s(f, &s->status);
-    qemu_get_be16s(f, &s->power);
-    qemu_get_be32s(f, &s->gpio_level);
-    qemu_get_be32s(f, &s->gpio_dir);
-    qemu_get_be32s(f, &s->prev_level);
-    qemu_get_be16s(f, &s->mcr);
-    qemu_get_be16s(f, &s->cdr);
-    qemu_get_be16s(f, &s->ccr);
-    qemu_get_be16s(f, &s->irr);
-    qemu_get_be16s(f, &s->imr);
-    qemu_get_be16s(f, &s->isr);
-    if (version_id < 1)
-           qemu_get_be16s(f, &dummy);
+    ScoopInfo *s = (ScoopInfo *) opaque;
+    int i;
+    uint32_t level;
+
+    level = s->gpio_level & s->gpio_dir;
+
+    for (i = 0; i < 16; i++) {
+        qemu_set_irq(s->handler[i], (level >> i) & 1);
+    }
+
+    s->prev_level = level;
 
     return 0;
 }
 
-struct scoop_info_s *scoop_init(struct pxa2xx_state_s *cpu,
-               int instance,
-               target_phys_addr_t target_base) {
-    int iomemtype;
-    struct scoop_info_s *s;
+static bool is_version_0 (void *opaque, int version_id)
+{
+    return version_id == 0;
+}
 
-    s = (struct scoop_info_s *)
-            qemu_mallocz(sizeof(struct scoop_info_s));
-    memset(s, 0, sizeof(struct scoop_info_s));
+static const VMStateDescription vmstate_scoop_regs = {
+    .name = "scoop",
+    .version_id = 1,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .post_load = scoop_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT16(status, ScoopInfo),
+        VMSTATE_UINT16(power, ScoopInfo),
+        VMSTATE_UINT32(gpio_level, ScoopInfo),
+        VMSTATE_UINT32(gpio_dir, ScoopInfo),
+        VMSTATE_UINT32(prev_level, ScoopInfo),
+        VMSTATE_UINT16(mcr, ScoopInfo),
+        VMSTATE_UINT16(cdr, ScoopInfo),
+        VMSTATE_UINT16(ccr, ScoopInfo),
+        VMSTATE_UINT16(irr, ScoopInfo),
+        VMSTATE_UINT16(imr, ScoopInfo),
+        VMSTATE_UINT16(isr, ScoopInfo),
+        VMSTATE_UNUSED_TEST(is_version_0, 2),
+        VMSTATE_END_OF_LIST(),
+    },
+};
 
-    s->status = 0x02;
-    s->in = qemu_allocate_irqs(scoop_gpio_set, s, 16);
-    iomemtype = cpu_register_io_memory(0, scoop_readfn,
-                    scoop_writefn, s);
-    cpu_register_physical_memory(target_base, 0x1000, iomemtype);
-    register_savevm("scoop", instance, 1, scoop_save, scoop_load, s);
+static SysBusDeviceInfo scoop_sysbus_info = {
+    .init           = scoop_init,
+    .qdev.name      = "scoop",
+    .qdev.desc      = "Scoop2 Sharp custom ASIC",
+    .qdev.size      = sizeof(ScoopInfo),
+    .qdev.vmsd      = &vmstate_scoop_regs,
+    .qdev.props     = (Property[]) {
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
 
-    return s;
+static void scoop_register(void)
+{
+    sysbus_register_withprop(&scoop_sysbus_info);
 }
+device_init(scoop_register);
 
 /* Write the bootloader parameters memory area.  */