All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH 04/12] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs
  2017-08-13 17:04 [Qemu-devel] [RFC PATCH 00/12] Sam460ex emulation BALATON Zoltan
                   ` (3 preceding siblings ...)
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 02/12] ppc4xx: Make MAL emulation more generic BALATON Zoltan
@ 2017-08-13 17:04 ` BALATON Zoltan
  2017-08-14  4:36   ` David Gibson
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 03/12] ohci: Allow sysbus version to be used as a companion BALATON Zoltan
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-13 17:04 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/usb/hcd-ehci-sysbus.c | 25 +++++++++++++++++++++++++
 hw/usb/hcd-ehci.h        |  1 +
 2 files changed, 26 insertions(+)

diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
index 6c20604..3b83beb 100644
--- a/hw/usb/hcd-ehci-sysbus.c
+++ b/hw/usb/hcd-ehci-sysbus.c
@@ -142,6 +142,30 @@ static const TypeInfo ehci_tegra2_type_info = {
     .class_init    = ehci_tegra2_class_init,
 };
 
+static void ehci_ppc4xx_init(Object *o)
+{
+    EHCISysBusState *s = SYS_BUS_EHCI(o);
+
+    s->ehci.companion_enable = true;
+}
+
+static void ehci_ppc4xx_class_init(ObjectClass *oc, void *data)
+{
+    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    sec->capsbase = 0x0;
+    sec->opregbase = 0x10;
+    set_bit(DEVICE_CATEGORY_USB, dc->categories);
+}
+
+static const TypeInfo ehci_ppc4xx_type_info = {
+    .name          = TYPE_PPC4xx_EHCI,
+    .parent        = TYPE_SYS_BUS_EHCI,
+    .class_init    = ehci_ppc4xx_class_init,
+    .instance_init = ehci_ppc4xx_init,
+};
+
 /*
  * Faraday FUSBH200 USB 2.0 EHCI
  */
@@ -224,6 +248,7 @@ static void ehci_sysbus_register_types(void)
     type_register_static(&ehci_xlnx_type_info);
     type_register_static(&ehci_exynos4210_type_info);
     type_register_static(&ehci_tegra2_type_info);
+    type_register_static(&ehci_ppc4xx_type_info);
     type_register_static(&ehci_fusbh200_type_info);
 }
 
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index 821f1de..0bc364b 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -344,6 +344,7 @@ typedef struct EHCIPCIState {
 #define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb"
 #define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
 #define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
+#define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
 #define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
 
 #define SYS_BUS_EHCI(obj) \
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [Qemu-devel] [RFC PATCH 03/12] ohci: Allow sysbus version to be used as a companion
  2017-08-13 17:04 [Qemu-devel] [RFC PATCH 00/12] Sam460ex emulation BALATON Zoltan
                   ` (4 preceding siblings ...)
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 04/12] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs BALATON Zoltan
@ 2017-08-13 17:04 ` BALATON Zoltan
  2017-08-15  4:13   ` David Gibson
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 07/12] ppc4xx_i2c: Implement basic I2C functions BALATON Zoltan
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-13 17:04 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/usb/hcd-ohci.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 267982e..17beedd 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1999,7 +1999,9 @@ typedef struct {
     /*< public >*/
 
     OHCIState ohci;
+    char *masterbus;
     uint32_t num_ports;
+    uint32_t firstport;
     dma_addr_t dma_offset;
 } OHCISysBusState;
 
@@ -2007,10 +2009,15 @@ static void ohci_realize_pxa(DeviceState *dev, Error **errp)
 {
     OHCISysBusState *s = SYSBUS_OHCI(dev);
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    Error *err = NULL;
 
-    /* Cannot fail as we pass NULL for masterbus */
-    usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, NULL, 0,
-                  &address_space_memory, &error_abort);
+    usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset,
+                  s->masterbus, s->firstport,
+                  &address_space_memory, &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
     sysbus_init_irq(sbd, &s->ohci.irq);
     sysbus_init_mmio(sbd, &s->ohci.mem);
 }
@@ -2142,7 +2149,9 @@ static const TypeInfo ohci_pci_info = {
 };
 
 static Property ohci_sysbus_properties[] = {
+    DEFINE_PROP_STRING("masterbus", OHCISysBusState, masterbus),
     DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
+    DEFINE_PROP_UINT32("firstport", OHCISysBusState, firstport, 0),
     DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 0),
     DEFINE_PROP_END_OF_LIST(),
 };
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [Qemu-devel] [RFC PATCH 07/12] ppc4xx_i2c: Implement basic I2C functions
  2017-08-13 17:04 [Qemu-devel] [RFC PATCH 00/12] Sam460ex emulation BALATON Zoltan
                   ` (5 preceding siblings ...)
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 03/12] ohci: Allow sysbus version to be used as a companion BALATON Zoltan
@ 2017-08-13 17:04 ` BALATON Zoltan
  2017-08-18  1:42   ` David Gibson
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 11/12] ppc4xx: Export ECB and PLB emulation BALATON Zoltan
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-13 17:04 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Enough to please U-Boot and make it able to detect SDRAM SPD EEPROMs

Signed-off-by: François Revol <revol@free.fr>
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/ppc4xx_i2c.c         | 214 +++++++++++++++++++++++++++++++++++++-------
 include/hw/i2c/ppc4xx_i2c.h |   5 ++
 2 files changed, 189 insertions(+), 30 deletions(-)

diff --git a/hw/ppc/ppc4xx_i2c.c b/hw/ppc/ppc4xx_i2c.c
index fafbb34..0b088e6 100644
--- a/hw/ppc/ppc4xx_i2c.c
+++ b/hw/ppc/ppc4xx_i2c.c
@@ -2,6 +2,8 @@
  * PPC4xx I2C controller emulation
  *
  * Copyright (c) 2007 Jocelyn Mayer
+ * Copyright (c) 2012 François Revol
+ * Copyright (c) 2016 BALATON Zoltan
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -25,25 +27,126 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
+#include "qemu/log.h"
 #include "cpu.h"
 #include "hw/hw.h"
 #include "hw/i2c/ppc4xx_i2c.h"
 
 /*#define DEBUG_I2C*/
 
-#define PPC4xx_I2C_MEM_SIZE 0x11
+#ifdef DEBUG_I2C
+#define DPRINTF(fmt, args...) printf("[%s]%s: " fmt, TYPE_PPC4xx_I2C, \
+                                     __func__, ##args);
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+#define PPC4xx_I2C_MEM_SIZE 0x12
+
+#define IIC_CNTL_PT         (1 << 0)
+#define IIC_CNTL_READ       (1 << 1)
+#define IIC_CNTL_CHT        (1 << 2)
+#define IIC_CNTL_RPST       (1 << 3)
+
+#define IIC_STS_PT          (1 << 0)
+#define IIC_STS_ERR         (1 << 2)
+#define IIC_STS_MDBS        (1 << 5)
+
+#define IIC_EXTSTS_XFRA     (1 << 0)
+
+#define IIC_XTCNTLSS_SRST   (1 << 0)
+
+static void ppc4xx_i2c_reset(DeviceState *s)
+{
+    PPC4xxI2CState *i2c = PPC4xx_I2C(s);
+
+    /* FIXME: Should also reset bus?
+     *if (s->address != ADDR_RESET) {
+     *    i2c_end_transfer(s->bus);
+     *}
+     */
+
+    i2c->mdata = 0;
+    i2c->lmadr = 0;
+    i2c->hmadr = 0;
+    i2c->cntl = 0;
+    i2c->mdcntl = 0;
+    i2c->sts = 0;
+    i2c->extsts = 0x8f;
+    i2c->sdata = 0;
+    i2c->lsadr = 0;
+    i2c->hsadr = 0;
+    i2c->clkdiv = 0;
+    i2c->intrmsk = 0;
+    i2c->xfrcnt = 0;
+    i2c->xtcntlss = 0;
+    i2c->directcntl = 0x0f;
+    i2c->intr = 0;
+}
+
+static inline bool ppc4xx_i2c_is_master(PPC4xxI2CState *i2c)
+{
+    return true;
+}
 
 static uint8_t ppc4xx_i2c_readb(PPC4xxI2CState *i2c, hwaddr addr)
 {
-    uint8_t ret;
+    int ret;
 
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
     switch (addr) {
     case 0x00:
-        /*i2c_readbyte(&i2c->mdata);*/
         ret = i2c->mdata;
+        if (ppc4xx_i2c_is_master(i2c)) {
+            ret = 0xff;
+
+            if (!(i2c->sts & IIC_STS_MDBS)) {
+                qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read "
+                              "without starting transfer\n",
+                              TYPE_PPC4xx_I2C, __func__);
+            } else {
+                int pending = (i2c->cntl >> 4) & 3;
+
+                /* get the next byte */
+                ret = i2c_recv(i2c->bus);
+                DPRINTF("received byte %04x\n", ret);
+
+                if (ret < 0) {
+                    qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: read failed "
+                                  "for device 0x%02x\n", TYPE_PPC4xx_I2C,
+                                  __func__, i2c->lmadr);
+                    ret = 0xff;
+                } else {
+                    /* Raise interrupt if enabled */
+                    /*ppc4xx_i2c_raise_interrupt(i2c)*/;
+                }
+
+                if (!pending) {
+                    i2c->sts &= ~IIC_STS_MDBS;
+                    /*i2c_end_transfer(i2c->bus);*/
+                /*} else if (i2c->cntl & (IIC_CNTL_RPST | IIC_CNTL_CHT)) {*/
+                } else if (pending) {
+                    /* current smbus implementation doesn't like
+                       multibyte xfer repeated start */
+                    i2c_end_transfer(i2c->bus);
+                    if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 1)) {
+                        /* if non zero is returned, the adress is not valid */
+                        i2c->sts &= ~IIC_STS_PT;
+                        i2c->sts |= IIC_STS_ERR;
+                        i2c->extsts |= IIC_EXTSTS_XFRA;
+                    } else {
+                        /*i2c->sts |= IIC_STS_PT;*/
+                        i2c->sts |= IIC_STS_MDBS;
+                        i2c->sts &= ~IIC_STS_ERR;
+                        i2c->extsts = 0;
+                    }
+                }
+                pending--;
+                i2c->cntl = (i2c->cntl & 0xcf) | (pending << 4);
+            }
+        } else {
+            qemu_log_mask(LOG_UNIMP, "[%s]%s: slave mode not implemented\n",
+                          TYPE_PPC4xx_I2C, __func__);
+        }
         break;
     case 0x02:
         ret = i2c->sdata;
@@ -87,39 +190,88 @@ static uint8_t ppc4xx_i2c_readb(PPC4xxI2CState *i2c, hwaddr addr)
     case 0x10:
         ret = i2c->directcntl;
         break;
+    case 0x11:
+        ret = i2c->intr;
+        break;
     default:
-        ret = 0x00;
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
+                      HWADDR_PRIx "\n", TYPE_PPC4xx_I2C, __func__, addr);
+        ret = 0;
         break;
     }
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, ret);
-#endif
 
     return ret;
 }
 
 static void ppc4xx_i2c_writeb(PPC4xxI2CState *i2c, hwaddr addr, uint8_t value)
 {
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n",
-           __func__, addr, value);
-#endif
     switch (addr) {
     case 0x00:
         i2c->mdata = value;
-        /*i2c_sendbyte(&i2c->mdata);*/
+        if (!i2c_bus_busy(i2c->bus)) {
+            /* assume we start a write transfer */
+            if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 0)) {
+                /* if non zero is returned, the adress is not valid */
+                i2c->sts &= ~IIC_STS_PT;
+                i2c->sts |= IIC_STS_ERR;
+                i2c->extsts |= IIC_EXTSTS_XFRA;
+            } else {
+                i2c->sts |= IIC_STS_PT;
+                i2c->sts &= ~IIC_STS_ERR;
+                i2c->extsts = 0;
+            }
+        }
+        if (i2c_bus_busy(i2c->bus)) {
+            DPRINTF("sending byte %02x\n", i2c->mdata);
+            if (i2c_send(i2c->bus, i2c->mdata)) {
+                /* if the target return non zero then end the transfer */
+                i2c->sts &= ~IIC_STS_PT;
+                i2c->sts |= IIC_STS_ERR;
+                i2c->extsts |= IIC_EXTSTS_XFRA;
+                i2c_end_transfer(i2c->bus);
+            }
+        }
         break;
     case 0x02:
         i2c->sdata = value;
         break;
     case 0x04:
         i2c->lmadr = value;
+        if (i2c_bus_busy(i2c->bus)) {
+            i2c_end_transfer(i2c->bus);
+        }
+        DPRINTF("%s: device addr %02x\n", __func__, i2c->lmadr);
         break;
     case 0x05:
         i2c->hmadr = value;
         break;
     case 0x06:
         i2c->cntl = value;
+        if (i2c->cntl & IIC_CNTL_PT) {
+            if (i2c->cntl & IIC_CNTL_READ) {
+                DPRINTF("read xfer %d\n", ((i2c->cntl >> 4) & 3) + 1);
+                if (i2c_bus_busy(i2c->bus)) {
+                    /* end previous transfer */
+                    i2c->sts &= ~IIC_STS_PT;
+                    i2c_end_transfer(i2c->bus);
+                }
+                if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 1)) {
+                    /* if non zero is returned, the adress is not valid */
+                    i2c->sts &= ~IIC_STS_PT;
+                    i2c->sts |= IIC_STS_ERR;
+                    i2c->extsts |= IIC_EXTSTS_XFRA;
+                } else {
+                    /*i2c->sts |= IIC_STS_PT;*/
+                    i2c->sts |= IIC_STS_MDBS;
+                    i2c->sts &= ~IIC_STS_ERR;
+                    i2c->extsts = 0;
+                }
+            } else {
+                DPRINTF("write xfer %d\n", ((i2c->cntl >> 4) & 3) + 1);
+                /* we actually already did the write transfer... */
+                i2c->sts &= ~IIC_STS_PT;
+            }
+        }
         break;
     case 0x07:
         i2c->mdcntl = value & 0xDF;
@@ -132,6 +284,7 @@ static void ppc4xx_i2c_writeb(PPC4xxI2CState *i2c, hwaddr addr, uint8_t value)
         break;
     case 0x0A:
         i2c->lsadr = value;
+        /*i2c_set_slave_address(i2c->bus, i2c->lsadr);*/
         break;
     case 0x0B:
         i2c->hsadr = value;
@@ -146,11 +299,23 @@ static void ppc4xx_i2c_writeb(PPC4xxI2CState *i2c, hwaddr addr, uint8_t value)
         i2c->xfrcnt = value & 0x77;
         break;
     case 0x0F:
+        if (value & IIC_XTCNTLSS_SRST) {
+            /* Is it actually a full reset? U-Boot sets some regs before */
+            ppc4xx_i2c_reset(DEVICE(i2c));
+            break;
+        }
         i2c->xtcntlss = value;
         break;
     case 0x10:
         i2c->directcntl = value & 0x7;
         break;
+    case 0x11:
+        i2c->intr = value;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
+                      HWADDR_PRIx "\n", TYPE_PPC4xx_I2C, __func__, addr);
+        break;
     }
 }
 
@@ -160,10 +325,12 @@ static uint64_t ppc4xx_i2c_read(void *opaque, hwaddr addr, unsigned int size)
     int i;
     uint64_t ret = 0;
 
+    DPRINTF("read I2C " TARGET_FMT_plx " size %u\n", addr, size);
     for (i = 0; i < size; i++) {
         ret <<= 8;
         ret |= ppc4xx_i2c_readb(s, addr + i);
     }
+    DPRINTF("read I2C " TARGET_FMT_plx " %02" PRIx64 "\n", addr, ret);
 
     return ret;
 }
@@ -174,6 +341,8 @@ static void ppc4xx_i2c_write(void *opaque, hwaddr addr, uint64_t value,
     PPC4xxI2CState *s = PPC4xx_I2C(opaque);
     int i;
 
+    DPRINTF("write I2C " TARGET_FMT_plx " size %u val %08" PRIx64 "\n",
+            addr, size, value);
     for (i = 0; i < size; i++) {
         ppc4xx_i2c_writeb(s, addr + i, value & 0xff);
         value >>= 8;
@@ -188,21 +357,6 @@ static const MemoryRegionOps ppc4xx_i2c_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void ppc4xx_i2c_reset(DeviceState *s)
-{
-    PPC4xxI2CState *i2c = PPC4xx_I2C(s);
-
-    i2c->mdata = 0x00;
-    i2c->sdata = 0x00;
-    i2c->cntl = 0x00;
-    i2c->mdcntl = 0x00;
-    i2c->sts = 0x00;
-    i2c->extsts = 0x00;
-    i2c->clkdiv = 0x00;
-    i2c->xfrcnt = 0x00;
-    i2c->directcntl = 0x0F;
-}
-
 static void ppc4xx_i2c_init(Object *o)
 {
     PPC4xxI2CState *s = PPC4xx_I2C(o);
diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h
index 7f1e6be..71fb392 100644
--- a/include/hw/i2c/ppc4xx_i2c.h
+++ b/include/hw/i2c/ppc4xx_i2c.h
@@ -2,6 +2,8 @@
  * PPC4xx I2C controller emulation
  *
  * Copyright (c) 2007 Jocelyn Mayer
+ * Copyright (c) 2012 François Revol
+ * Copyright (c) 2016 BALATON Zoltan
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -28,6 +30,7 @@
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "hw/sysbus.h"
+#include "hw/i2c/i2c.h"
 
 #define TYPE_PPC4xx_I2C "ppc4xx-i2c"
 #define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2C)
@@ -37,6 +40,7 @@ typedef struct PPC4xxI2CState {
     SysBusDevice parent_obj;
 
     /*< public >*/
+    I2CBus *bus;
     qemu_irq irq;
     MemoryRegion iomem;
     uint8_t mdata;
@@ -54,6 +58,7 @@ typedef struct PPC4xxI2CState {
     uint8_t xfrcnt;
     uint8_t xtcntlss;
     uint8_t directcntl;
+    uint8_t intr;
 } PPC4xxI2CState;
 
 #endif /* PPC4XX_I2C_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [Qemu-devel] [RFC PATCH 06/12] ppc4xx_i2c: QOMify
  2017-08-13 17:04 [Qemu-devel] [RFC PATCH 00/12] Sam460ex emulation BALATON Zoltan
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs BALATON Zoltan
@ 2017-08-13 17:04 ` BALATON Zoltan
  2017-08-15  4:17   ` David Gibson
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 08/12] hw/ide: Emulate SiI3112 SATA controller BALATON Zoltan
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-13 17:04 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/ppc405.h             |   2 -
 hw/ppc/ppc405_uc.c          |   5 +-
 hw/ppc/ppc4xx_i2c.c         | 153 +++++++++++++++++---------------------------
 include/hw/i2c/ppc4xx_i2c.h |  59 +++++++++++++++++
 4 files changed, 121 insertions(+), 98 deletions(-)
 create mode 100644 include/hw/i2c/ppc4xx_i2c.h

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 61ec739..a9ffc87 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -59,8 +59,6 @@ struct ppc4xx_bd_info_t {
 ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
                                 uint32_t flags);
 
-void ppc405_i2c_init(hwaddr base, qemu_irq irq);
-
 CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
                         MemoryRegion ram_memories[4],
                         hwaddr ram_bases[4],
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 3925e4c..8f44cb4 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -28,6 +28,7 @@
 #include "hw/hw.h"
 #include "hw/ppc/ppc.h"
 #include "hw/boards.h"
+#include "hw/i2c/ppc4xx_i2c.h"
 #include "ppc405.h"
 #include "hw/char/serial.h"
 #include "qemu/timer.h"
@@ -1663,7 +1664,7 @@ CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
                        DEVICE_BIG_ENDIAN);
     }
     /* IIC controller */
-    ppc405_i2c_init(0xef600500, pic[2]);
+    sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, pic[2]);
     /* GPIO */
     ppc405_gpio_init(0xef600700);
     /* CPU control */
@@ -2010,7 +2011,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
     dma_irqs[3] = pic[8];
     ppc405_dma_init(env, dma_irqs);
     /* IIC controller */
-    ppc405_i2c_init(0xef600500, pic[2]);
+    sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, pic[2]);
     /* GPIO */
     ppc405_gpio_init(0xef600700);
     /* Serial ports */
diff --git a/hw/ppc/ppc4xx_i2c.c b/hw/ppc/ppc4xx_i2c.c
index 15f2dea..fafbb34 100644
--- a/hw/ppc/ppc4xx_i2c.c
+++ b/hw/ppc/ppc4xx_i2c.c
@@ -27,42 +27,19 @@
 #include "qemu-common.h"
 #include "cpu.h"
 #include "hw/hw.h"
-#include "exec/address-spaces.h"
-#include "hw/ppc/ppc.h"
-#include "ppc405.h"
+#include "hw/i2c/ppc4xx_i2c.h"
 
 /*#define DEBUG_I2C*/
 
-typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
-struct ppc4xx_i2c_t {
-    qemu_irq irq;
-    MemoryRegion iomem;
-    uint8_t mdata;
-    uint8_t lmadr;
-    uint8_t hmadr;
-    uint8_t cntl;
-    uint8_t mdcntl;
-    uint8_t sts;
-    uint8_t extsts;
-    uint8_t sdata;
-    uint8_t lsadr;
-    uint8_t hsadr;
-    uint8_t clkdiv;
-    uint8_t intrmsk;
-    uint8_t xfrcnt;
-    uint8_t xtcntlss;
-    uint8_t directcntl;
-};
+#define PPC4xx_I2C_MEM_SIZE 0x11
 
-static uint32_t ppc4xx_i2c_readb(void *opaque, hwaddr addr)
+static uint8_t ppc4xx_i2c_readb(PPC4xxI2CState *i2c, hwaddr addr)
 {
-    ppc4xx_i2c_t *i2c;
-    uint32_t ret;
+    uint8_t ret;
 
 #ifdef DEBUG_I2C
     printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
 #endif
-    i2c = opaque;
     switch (addr) {
     case 0x00:
         /*i2c_readbyte(&i2c->mdata);*/
@@ -121,16 +98,12 @@ static uint32_t ppc4xx_i2c_readb(void *opaque, hwaddr addr)
     return ret;
 }
 
-static void ppc4xx_i2c_writeb(void *opaque,
-                              hwaddr addr, uint32_t value)
+static void ppc4xx_i2c_writeb(PPC4xxI2CState *i2c, hwaddr addr, uint8_t value)
 {
-    ppc4xx_i2c_t *i2c;
-
 #ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n",
+           __func__, addr, value);
 #endif
-    i2c = opaque;
     switch (addr) {
     case 0x00:
         i2c->mdata = value;
@@ -181,71 +154,44 @@ static void ppc4xx_i2c_writeb(void *opaque,
     }
 }
 
-static uint32_t ppc4xx_i2c_readw(void *opaque, hwaddr addr)
+static uint64_t ppc4xx_i2c_read(void *opaque, hwaddr addr, unsigned int size)
 {
-    uint32_t ret;
+    PPC4xxI2CState *s = PPC4xx_I2C(opaque);
+    int i;
+    uint64_t ret = 0;
 
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
+    for (i = 0; i < size; i++) {
+        ret <<= 8;
+        ret |= ppc4xx_i2c_readb(s, addr + i);
+    }
 
     return ret;
 }
 
-static void ppc4xx_i2c_writew(void *opaque,
-                              hwaddr addr, uint32_t value)
+static void ppc4xx_i2c_write(void *opaque, hwaddr addr, uint64_t value,
+                             unsigned int size)
 {
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
-    ppc4xx_i2c_writeb(opaque, addr + 1, value);
-}
-
-static uint32_t ppc4xx_i2c_readl(void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
-
-    return ret;
-}
+    PPC4xxI2CState *s = PPC4xx_I2C(opaque);
+    int i;
 
-static void ppc4xx_i2c_writel(void *opaque,
-                              hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
-    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
-    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
-    ppc4xx_i2c_writeb(opaque, addr + 3, value);
+    for (i = 0; i < size; i++) {
+        ppc4xx_i2c_writeb(s, addr + i, value & 0xff);
+        value >>= 8;
+    }
 }
 
-static const MemoryRegionOps i2c_ops = {
-    .old_mmio = {
-        .read = { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, },
-        .write = { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writel, },
-    },
+static const MemoryRegionOps ppc4xx_i2c_ops = {
+    .read = ppc4xx_i2c_read,
+    .write = ppc4xx_i2c_write,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 4,
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void ppc4xx_i2c_reset(void *opaque)
+static void ppc4xx_i2c_reset(DeviceState *s)
 {
-    ppc4xx_i2c_t *i2c;
+    PPC4xxI2CState *i2c = PPC4xx_I2C(s);
 
-    i2c = opaque;
     i2c->mdata = 0x00;
     i2c->sdata = 0x00;
     i2c->cntl = 0x00;
@@ -257,16 +203,35 @@ static void ppc4xx_i2c_reset(void *opaque)
     i2c->directcntl = 0x0F;
 }
 
-void ppc405_i2c_init(hwaddr base, qemu_irq irq)
+static void ppc4xx_i2c_init(Object *o)
 {
-    ppc4xx_i2c_t *i2c;
+    PPC4xxI2CState *s = PPC4xx_I2C(o);
 
-    i2c = g_malloc0(sizeof(ppc4xx_i2c_t));
-    i2c->irq = irq;
-#ifdef DEBUG_I2C
-    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
-#endif
-    memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011);
-    memory_region_add_subregion(get_system_memory(), base, &i2c->iomem);
-    qemu_register_reset(ppc4xx_i2c_reset, i2c);
+    memory_region_init_io(&s->iomem, OBJECT(s), &ppc4xx_i2c_ops, s,
+                          TYPE_PPC4xx_I2C, PPC4xx_I2C_MEM_SIZE);
+    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
+    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
+    s->bus = i2c_init_bus(DEVICE(s), "i2c");
 }
+
+static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = ppc4xx_i2c_reset;
+}
+
+static const TypeInfo ppc4xx_i2c_type_info = {
+    .name = TYPE_PPC4xx_I2C,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PPC4xxI2CState),
+    .instance_init = ppc4xx_i2c_init,
+    .class_init = ppc4xx_i2c_class_init,
+};
+
+static void ppc4xx_i2c_register_types(void)
+{
+    type_register_static(&ppc4xx_i2c_type_info);
+}
+
+type_init(ppc4xx_i2c_register_types)
diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h
new file mode 100644
index 0000000..7f1e6be
--- /dev/null
+++ b/include/hw/i2c/ppc4xx_i2c.h
@@ -0,0 +1,59 @@
+/*
+ * PPC4xx I2C controller emulation
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef PPC4XX_I2C_H
+#define PPC4XX_I2C_H
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "hw/sysbus.h"
+
+#define TYPE_PPC4xx_I2C "ppc4xx-i2c"
+#define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2C)
+
+typedef struct PPC4xxI2CState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+
+    /*< public >*/
+    qemu_irq irq;
+    MemoryRegion iomem;
+    uint8_t mdata;
+    uint8_t lmadr;
+    uint8_t hmadr;
+    uint8_t cntl;
+    uint8_t mdcntl;
+    uint8_t sts;
+    uint8_t extsts;
+    uint8_t sdata;
+    uint8_t lsadr;
+    uint8_t hsadr;
+    uint8_t clkdiv;
+    uint8_t intrmsk;
+    uint8_t xfrcnt;
+    uint8_t xtcntlss;
+    uint8_t directcntl;
+} PPC4xxI2CState;
+
+#endif /* PPC4XX_I2C_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [Qemu-devel] [RFC PATCH 10/12] ppc: Add 460EX embedded CPU
  2017-08-13 17:04 [Qemu-devel] [RFC PATCH 00/12] Sam460ex emulation BALATON Zoltan
                   ` (10 preceding siblings ...)
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 12/12] ppc: Add aCube Sam460ex board BALATON Zoltan
@ 2017-08-13 17:04 ` BALATON Zoltan
  2017-08-14  4:40   ` David Gibson
  11 siblings, 1 reply; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-13 17:04 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Despite its name it is a 440 core CPU

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 target/ppc/cpu-models.c     |  3 +++
 target/ppc/cpu-models.h     |  1 +
 target/ppc/translate_init.c | 38 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+)

diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
index 4d3e635..7c368fc 100644
--- a/target/ppc/cpu-models.c
+++ b/target/ppc/cpu-models.c
@@ -348,6 +348,8 @@
                 "PowerPC 440 EPb")
     POWERPC_DEF("440EPX",        CPU_POWERPC_440EPX,                 440EP,
                 "PowerPC 440 EPX")
+    POWERPC_DEF("460EXb",        CPU_POWERPC_460EXb,                 460EX,
+                "PowerPC 460 EXb")
 #if defined(TODO_USER_ONLY)
     POWERPC_DEF("440GPb",        CPU_POWERPC_440GPb,                 440GP,
                 "PowerPC 440 GPb")
@@ -1238,6 +1240,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "440GP", "440GPc" },
     { "440GR", "440GRa" },
     { "440GX", "440GXf" },
+    { "460EX", "460EXb" },
 
     { "RCPU", "MPC5xx" },
     /* MPC5xx microcontrollers */
diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h
index b563c45..92f99c0 100644
--- a/target/ppc/cpu-models.h
+++ b/target/ppc/cpu-models.h
@@ -241,6 +241,7 @@ enum {
     CPU_POWERPC_440SP              = 0x53221850,
     CPU_POWERPC_440SP2             = 0x53221891,
     CPU_POWERPC_440SPE             = 0x53421890,
+    CPU_POWERPC_460EXb             = 0x130218A4, /* called 460 but 440 core */
     /* PowerPC 460 family */
 #if 0
     /* Generic PowerPC 464 */
diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
index 8fb407e..1e0d566 100644
--- a/target/ppc/translate_init.c
+++ b/target/ppc/translate_init.c
@@ -3832,6 +3832,44 @@ POWERPC_FAMILY(440EP)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
+POWERPC_FAMILY(460EX)(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    dc->desc = "PowerPC 460 EX";
+    pcc->init_proc = init_proc_440EP;
+    pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
+                       PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
+                       PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
+                       PPC_FLOAT_STFIWX |
+                       PPC_DCR | PPC_DCRX | PPC_WRTEE | PPC_RFMCI |
+                       PPC_CACHE | PPC_CACHE_ICBI |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_MEM_TLBSYNC | PPC_MFTB |
+                       PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
+                       PPC_440_SPEC;
+    pcc->msr_mask = (1ull << MSR_POW) |
+                    (1ull << MSR_CE) |
+                    (1ull << MSR_EE) |
+                    (1ull << MSR_PR) |
+                    (1ull << MSR_FP) |
+                    (1ull << MSR_ME) |
+                    (1ull << MSR_FE0) |
+                    (1ull << MSR_DWE) |
+                    (1ull << MSR_DE) |
+                    (1ull << MSR_FE1) |
+                    (1ull << MSR_IR) |
+                    (1ull << MSR_DR);
+    pcc->mmu_model = POWERPC_MMU_BOOKE;
+    pcc->excp_model = POWERPC_EXCP_BOOKE;
+    pcc->bus_model = PPC_FLAGS_INPUT_BookE;
+    pcc->bfd_mach = bfd_mach_ppc_403;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE |
+                 POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
+}
+
 static void init_proc_440GP(CPUPPCState *env)
 {
     /* Time base */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [Qemu-devel] [RFC PATCH 11/12] ppc4xx: Export ECB and PLB emulation
  2017-08-13 17:04 [Qemu-devel] [RFC PATCH 00/12] Sam460ex emulation BALATON Zoltan
                   ` (6 preceding siblings ...)
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 07/12] ppc4xx_i2c: Implement basic I2C functions BALATON Zoltan
@ 2017-08-13 17:04 ` BALATON Zoltan
  2017-08-14  4:44   ` David Gibson
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 05/12] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file BALATON Zoltan
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-13 17:04 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

These devices are found in some other ppc4xx cores too.
Also add some more PLB registers for 460EX.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/ppc405.h    |  3 +++
 hw/ppc/ppc405_uc.c | 16 +++++++++++-----
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index a9ffc87..7ed25cf 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -59,6 +59,9 @@ struct ppc4xx_bd_info_t {
 ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
                                 uint32_t flags);
 
+void ppc4xx_plb_init(CPUPPCState *env);
+void ppc405_ebc_init(CPUPPCState *env);
+
 CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
                         MemoryRegion ram_memories[4],
                         hwaddr ram_bases[4],
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 8f44cb4..8e58065 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -105,9 +105,12 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
 /*****************************************************************************/
 /* Peripheral local bus arbitrer */
 enum {
-    PLB0_BESR = 0x084,
-    PLB0_BEAR = 0x086,
-    PLB0_ACR  = 0x087,
+    PLB3A0_ACR = 0x077,
+    PLB4A0_ACR = 0x081,
+    PLB0_BESR  = 0x084,
+    PLB0_BEAR  = 0x086,
+    PLB0_ACR   = 0x087,
+    PLB4A1_ACR = 0x089,
 };
 
 typedef struct ppc4xx_plb_t ppc4xx_plb_t;
@@ -174,14 +177,17 @@ static void ppc4xx_plb_reset (void *opaque)
     plb->besr = 0x00000000;
 }
 
-static void ppc4xx_plb_init(CPUPPCState *env)
+void ppc4xx_plb_init(CPUPPCState *env)
 {
     ppc4xx_plb_t *plb;
 
     plb = g_malloc0(sizeof(ppc4xx_plb_t));
+    ppc_dcr_register(env, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
+    ppc_dcr_register(env, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
     ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
     ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
     ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
+    ppc_dcr_register(env, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb);
     qemu_register_reset(ppc4xx_plb_reset, plb);
 }
 
@@ -585,7 +591,7 @@ static void ebc_reset (void *opaque)
     ebc->cfg = 0x80400000;
 }
 
-static void ppc405_ebc_init(CPUPPCState *env)
+void ppc405_ebc_init(CPUPPCState *env)
 {
     ppc4xx_ebc_t *ebc;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [Qemu-devel] [RFC PATCH 00/12] Sam460ex emulation
@ 2017-08-13 17:04 BALATON Zoltan
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs BALATON Zoltan
                   ` (11 more replies)
  0 siblings, 12 replies; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-13 17:04 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Hello,

Here's a series to add emulation of the Sam460ex to QEMU. (This board
is interesting because besides Linux, it is supported by several Amiga
like OSes.) This code is based on previous work by François Revol,
cleaning it up and adding some missing parts to get it to start
working at least for the Linux kernel and the original U-Boot firmware
of the board (which is needed to boot the Amiga like OSes easily).

This is not complete and cannot run most of the interesting OSes yet
as there are still missing parts and likely some bugs I could not fix
but since I have limited time and knowledge to work on this, I'd like
to submit it now to get it reviewed and maybe some advice or even some
help to finish it from other interested parties (especially if you
have better knowledge of this hardware). Hence this RFC series, but it
is probably in a shape now like some of the similar boards already in
QEMU so if after review it is deemed fit I'd like to submit it for
inclusion when development opens again.

Some resources and status for those who want to help:

The board is described on the manufacturer's site:
http://www.acube-systems.biz/index.php?page=hardware&pid=5
where links can also be found to the official firmware and Linux
images. Only the original 2010.06.05 firmware is tested from the
20110414 updater (there is a newer version but that's only relevant
for real hardware and may not work with this emulation so that's not
recommended). This firmware works and starts booting but that's when
problems start and you'll most likely hit some problem with most
images before they boot.

AROS and Linux iso-s use the Parthenope (ub2lb) bootloader which
currently fails when it calls the start_unit_scan with NULL first
argument in cdrom.c:get_dev() which causes a null pointer dereference
in U-Boot/board/ACube/common/sys_dep.c:start_unit_scan() which causes
an exception in QEMU (vector 1300, I think it's Data TLB Error) and
this leads to breakage. This may be a bug in the firmware but
apparently on real hardware this works somehow so this suggests a
difference in emulation that should be fixed. If I fix this in U-Boot
then it hits another bug in board/ACube/common/cmd_boota.c where it
references stack variable beyond its scope and gets garbled text (I
wonder how this was working, maybe they used different compiler and
were lucky). This causes Parthenope not find its menu.lst config. Also
fixing this (here's a binary with both fixes:
http://zero.eik.bme.hu/~balaton/qemu/ ) finally it gets further
booting but then AROS fails while setting up the MMU so maybe this
means there are some bugs or differences between the MMU/TLB/exception
emulation and real hardware (assuming it works on real hardware at
all). But I don't know how real hardware works so I could not find it
out. Does anyone have an idea?

Linux can also be booted via -kernel -dtb -initrd instead of booting
the iso via the firmware and this gets to executing the initrd but
then it seems to hang and I could not identify where and why. There
are different Linux images so maybe some work better or worse but I
could not fully boot a Linux system yet only to the initrd (although
I've only tried a few not all of them). Also most of these images are
network installers and the on board ppc4xx ethernet port is not yet
emulated so this may cause the hang. Anyone wants to contribute?

MorphOS starts booting but does not find PCI devices so it fails.
Unfortunately I don't know how to set kernel parameters to enable
debug logging (passing them via the bootloader like on Mac does not
work and MorphOS people haven't reply my query about it) so I don't
care for now until other OSes easier to debug can't boot. (Besides,
MorphOS could also run on the Mac emulation and may get a new version
soon which might change a few things so it's low priority now; maybe
I look at it again when new version is available.) I could not test
AmigaOS because I don't have that but I would not be surprised if it
would also fail during boot for some reason but if someone has a copy
and can try it let me know how it fails (try -serial stdio to hopefully
get some logs).

How can you help? (Besides fixing bugs and implementing missing parts
if you can do that, but in that case you probably know what to do.)
No monetary donations are solicited or accepted (I'm saying this
because I got some anonymous donations in the past which I did not
claim so they went to the QEMU project and did not help this work in
any way, so this is not a good way to support this activity.) What
would be more useful is to test on real hardware to get logs for
comparison so if you have a Sam460ex (or its simpler Sam460cr version)
and could gather debug logs over the serial port try getting some with
an AROS iso then contact me with the log and for an AROS iso with more
logging enabled to get more details.

In any case, I do this in my free time and for personal interest so
don't expect any support or roadmap for this. If the info here is not
enough for you to get it working for testing then it's not ready for
you yet. I don't have time to help people with this so if you can't
find it out you should wait until it's more developed (which may take
years or could be never). Sorry for this disclaimer here but I've
learned that the situation with Amiga like OSes can sometimes be
interesting and I would like to avoid misunderstandings. This is very
much work in progress not useful for the general users at the moment,
only for interested developers.


BALATON Zoltan (12):
  ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs
  ppc4xx: Make MAL emulation more generic
  ohci: Allow sysbus version to be used as a companion
  ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs
  ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file
  ppc4xx_i2c: QOMify
  ppc4xx_i2c: Implement basic I2C functions
  hw/ide: Emulate SiI3112 SATA controller
  ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  ppc: Add 460EX embedded CPU
  ppc4xx: Export ECB and PLB emulation
  ppc: Add aCube Sam460ex board

 default-configs/ppcemb-softmmu.mak |    3 +
 hw/ide/Makefile.objs               |    1 +
 hw/ide/sii3112.c                   |  365 +++++++
 hw/ppc/Makefile.objs               |    4 +-
 hw/ppc/ppc405.h                    |    3 +
 hw/ppc/ppc405_uc.c                 |  527 +---------
 hw/ppc/ppc440_pcix.c               |  506 ++++++++++
 hw/ppc/ppc4xx_devs.c               |  227 +++++
 hw/ppc/ppc4xx_i2c.c                |  391 ++++++++
 hw/ppc/sam460ex.c                  | 1895 ++++++++++++++++++++++++++++++++++++
 hw/usb/hcd-ehci-sysbus.c           |   25 +
 hw/usb/hcd-ehci.h                  |    1 +
 hw/usb/hcd-ohci.c                  |   15 +-
 include/hw/i2c/ppc4xx_i2c.h        |   64 ++
 include/hw/pci/pcie_host.h         |    2 +-
 include/hw/ppc/ppc4xx.h            |    3 +
 target/ppc/cpu-models.c            |    3 +
 target/ppc/cpu-models.h            |    1 +
 target/ppc/translate_init.c        |   38 +
 19 files changed, 3557 insertions(+), 517 deletions(-)
 create mode 100644 hw/ide/sii3112.c
 create mode 100644 hw/ppc/ppc440_pcix.c
 create mode 100644 hw/ppc/ppc4xx_i2c.c
 create mode 100644 hw/ppc/sam460ex.c
 create mode 100644 include/hw/i2c/ppc4xx_i2c.h

-- 
2.7.4

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [Qemu-devel] [RFC PATCH 05/12] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file
  2017-08-13 17:04 [Qemu-devel] [RFC PATCH 00/12] Sam460ex emulation BALATON Zoltan
                   ` (7 preceding siblings ...)
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 11/12] ppc4xx: Export ECB and PLB emulation BALATON Zoltan
@ 2017-08-13 17:04 ` BALATON Zoltan
  2017-08-14  4:41   ` David Gibson
  2017-08-14  9:00   ` Paolo Bonzini
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 01/12] ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs BALATON Zoltan
                   ` (2 subsequent siblings)
  11 siblings, 2 replies; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-13 17:04 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/Makefile.objs |   2 +-
 hw/ppc/ppc405.h      |   2 +
 hw/ppc/ppc405_uc.c   | 241 ---------------------------------------------
 hw/ppc/ppc4xx_i2c.c  | 272 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 275 insertions(+), 242 deletions(-)
 create mode 100644 hw/ppc/ppc4xx_i2c.c

diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 7efc686..2077216 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -13,7 +13,7 @@ endif
 obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
 # PowerPC 4xx boards
 obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
-obj-y += ppc4xx_pci.o
+obj-y += ppc4xx_pci.o ppc4xx_i2c.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
 obj-$(CONFIG_PREP) += prep_systemio.o
diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index a9ffc87..61ec739 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -59,6 +59,8 @@ struct ppc4xx_bd_info_t {
 ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
                                 uint32_t flags);
 
+void ppc405_i2c_init(hwaddr base, qemu_irq irq);
+
 CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
                         MemoryRegion ram_memories[4],
                         hwaddr ram_bases[4],
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 03856d5..3925e4c 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -40,7 +40,6 @@
 //#define DEBUG_GPIO
 //#define DEBUG_SERIAL
 //#define DEBUG_OCM
-//#define DEBUG_I2C
 //#define DEBUG_GPT
 //#define DEBUG_CLOCKS
 //#define DEBUG_CLOCKS_LL
@@ -993,246 +992,6 @@ static void ppc405_ocm_init(CPUPPCState *env)
 }
 
 /*****************************************************************************/
-/* I2C controller */
-typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
-struct ppc4xx_i2c_t {
-    qemu_irq irq;
-    MemoryRegion iomem;
-    uint8_t mdata;
-    uint8_t lmadr;
-    uint8_t hmadr;
-    uint8_t cntl;
-    uint8_t mdcntl;
-    uint8_t sts;
-    uint8_t extsts;
-    uint8_t sdata;
-    uint8_t lsadr;
-    uint8_t hsadr;
-    uint8_t clkdiv;
-    uint8_t intrmsk;
-    uint8_t xfrcnt;
-    uint8_t xtcntlss;
-    uint8_t directcntl;
-};
-
-static uint32_t ppc4xx_i2c_readb (void *opaque, hwaddr addr)
-{
-    ppc4xx_i2c_t *i2c;
-    uint32_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    i2c = opaque;
-    switch (addr) {
-    case 0x00:
-        //        i2c_readbyte(&i2c->mdata);
-        ret = i2c->mdata;
-        break;
-    case 0x02:
-        ret = i2c->sdata;
-        break;
-    case 0x04:
-        ret = i2c->lmadr;
-        break;
-    case 0x05:
-        ret = i2c->hmadr;
-        break;
-    case 0x06:
-        ret = i2c->cntl;
-        break;
-    case 0x07:
-        ret = i2c->mdcntl;
-        break;
-    case 0x08:
-        ret = i2c->sts;
-        break;
-    case 0x09:
-        ret = i2c->extsts;
-        break;
-    case 0x0A:
-        ret = i2c->lsadr;
-        break;
-    case 0x0B:
-        ret = i2c->hsadr;
-        break;
-    case 0x0C:
-        ret = i2c->clkdiv;
-        break;
-    case 0x0D:
-        ret = i2c->intrmsk;
-        break;
-    case 0x0E:
-        ret = i2c->xfrcnt;
-        break;
-    case 0x0F:
-        ret = i2c->xtcntlss;
-        break;
-    case 0x10:
-        ret = i2c->directcntl;
-        break;
-    default:
-        ret = 0x00;
-        break;
-    }
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, ret);
-#endif
-
-    return ret;
-}
-
-static void ppc4xx_i2c_writeb (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-    ppc4xx_i2c_t *i2c;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    i2c = opaque;
-    switch (addr) {
-    case 0x00:
-        i2c->mdata = value;
-        //        i2c_sendbyte(&i2c->mdata);
-        break;
-    case 0x02:
-        i2c->sdata = value;
-        break;
-    case 0x04:
-        i2c->lmadr = value;
-        break;
-    case 0x05:
-        i2c->hmadr = value;
-        break;
-    case 0x06:
-        i2c->cntl = value;
-        break;
-    case 0x07:
-        i2c->mdcntl = value & 0xDF;
-        break;
-    case 0x08:
-        i2c->sts &= ~(value & 0x0A);
-        break;
-    case 0x09:
-        i2c->extsts &= ~(value & 0x8F);
-        break;
-    case 0x0A:
-        i2c->lsadr = value;
-        break;
-    case 0x0B:
-        i2c->hsadr = value;
-        break;
-    case 0x0C:
-        i2c->clkdiv = value;
-        break;
-    case 0x0D:
-        i2c->intrmsk = value;
-        break;
-    case 0x0E:
-        i2c->xfrcnt = value & 0x77;
-        break;
-    case 0x0F:
-        i2c->xtcntlss = value;
-        break;
-    case 0x10:
-        i2c->directcntl = value & 0x7;
-        break;
-    }
-}
-
-static uint32_t ppc4xx_i2c_readw (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
-
-    return ret;
-}
-
-static void ppc4xx_i2c_writew (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
-    ppc4xx_i2c_writeb(opaque, addr + 1, value);
-}
-
-static uint32_t ppc4xx_i2c_readl (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
-
-    return ret;
-}
-
-static void ppc4xx_i2c_writel (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
-    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
-    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
-    ppc4xx_i2c_writeb(opaque, addr + 3, value);
-}
-
-static const MemoryRegionOps i2c_ops = {
-    .old_mmio = {
-        .read = { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, },
-        .write = { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ppc4xx_i2c_reset (void *opaque)
-{
-    ppc4xx_i2c_t *i2c;
-
-    i2c = opaque;
-    i2c->mdata = 0x00;
-    i2c->sdata = 0x00;
-    i2c->cntl = 0x00;
-    i2c->mdcntl = 0x00;
-    i2c->sts = 0x00;
-    i2c->extsts = 0x00;
-    i2c->clkdiv = 0x00;
-    i2c->xfrcnt = 0x00;
-    i2c->directcntl = 0x0F;
-}
-
-static void ppc405_i2c_init(hwaddr base, qemu_irq irq)
-{
-    ppc4xx_i2c_t *i2c;
-
-    i2c = g_malloc0(sizeof(ppc4xx_i2c_t));
-    i2c->irq = irq;
-#ifdef DEBUG_I2C
-    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
-#endif
-    memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011);
-    memory_region_add_subregion(get_system_memory(), base, &i2c->iomem);
-    qemu_register_reset(ppc4xx_i2c_reset, i2c);
-}
-
-/*****************************************************************************/
 /* General purpose timers */
 typedef struct ppc4xx_gpt_t ppc4xx_gpt_t;
 struct ppc4xx_gpt_t {
diff --git a/hw/ppc/ppc4xx_i2c.c b/hw/ppc/ppc4xx_i2c.c
new file mode 100644
index 0000000..15f2dea
--- /dev/null
+++ b/hw/ppc/ppc4xx_i2c.c
@@ -0,0 +1,272 @@
+/*
+ * PPC4xx I2C controller emulation
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "hw/hw.h"
+#include "exec/address-spaces.h"
+#include "hw/ppc/ppc.h"
+#include "ppc405.h"
+
+/*#define DEBUG_I2C*/
+
+typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
+struct ppc4xx_i2c_t {
+    qemu_irq irq;
+    MemoryRegion iomem;
+    uint8_t mdata;
+    uint8_t lmadr;
+    uint8_t hmadr;
+    uint8_t cntl;
+    uint8_t mdcntl;
+    uint8_t sts;
+    uint8_t extsts;
+    uint8_t sdata;
+    uint8_t lsadr;
+    uint8_t hsadr;
+    uint8_t clkdiv;
+    uint8_t intrmsk;
+    uint8_t xfrcnt;
+    uint8_t xtcntlss;
+    uint8_t directcntl;
+};
+
+static uint32_t ppc4xx_i2c_readb(void *opaque, hwaddr addr)
+{
+    ppc4xx_i2c_t *i2c;
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    i2c = opaque;
+    switch (addr) {
+    case 0x00:
+        /*i2c_readbyte(&i2c->mdata);*/
+        ret = i2c->mdata;
+        break;
+    case 0x02:
+        ret = i2c->sdata;
+        break;
+    case 0x04:
+        ret = i2c->lmadr;
+        break;
+    case 0x05:
+        ret = i2c->hmadr;
+        break;
+    case 0x06:
+        ret = i2c->cntl;
+        break;
+    case 0x07:
+        ret = i2c->mdcntl;
+        break;
+    case 0x08:
+        ret = i2c->sts;
+        break;
+    case 0x09:
+        ret = i2c->extsts;
+        break;
+    case 0x0A:
+        ret = i2c->lsadr;
+        break;
+    case 0x0B:
+        ret = i2c->hsadr;
+        break;
+    case 0x0C:
+        ret = i2c->clkdiv;
+        break;
+    case 0x0D:
+        ret = i2c->intrmsk;
+        break;
+    case 0x0E:
+        ret = i2c->xfrcnt;
+        break;
+    case 0x0F:
+        ret = i2c->xtcntlss;
+        break;
+    case 0x10:
+        ret = i2c->directcntl;
+        break;
+    default:
+        ret = 0x00;
+        break;
+    }
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, ret);
+#endif
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writeb(void *opaque,
+                              hwaddr addr, uint32_t value)
+{
+    ppc4xx_i2c_t *i2c;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    i2c = opaque;
+    switch (addr) {
+    case 0x00:
+        i2c->mdata = value;
+        /*i2c_sendbyte(&i2c->mdata);*/
+        break;
+    case 0x02:
+        i2c->sdata = value;
+        break;
+    case 0x04:
+        i2c->lmadr = value;
+        break;
+    case 0x05:
+        i2c->hmadr = value;
+        break;
+    case 0x06:
+        i2c->cntl = value;
+        break;
+    case 0x07:
+        i2c->mdcntl = value & 0xDF;
+        break;
+    case 0x08:
+        i2c->sts &= ~(value & 0x0A);
+        break;
+    case 0x09:
+        i2c->extsts &= ~(value & 0x8F);
+        break;
+    case 0x0A:
+        i2c->lsadr = value;
+        break;
+    case 0x0B:
+        i2c->hsadr = value;
+        break;
+    case 0x0C:
+        i2c->clkdiv = value;
+        break;
+    case 0x0D:
+        i2c->intrmsk = value;
+        break;
+    case 0x0E:
+        i2c->xfrcnt = value & 0x77;
+        break;
+    case 0x0F:
+        i2c->xtcntlss = value;
+        break;
+    case 0x10:
+        i2c->directcntl = value & 0x7;
+        break;
+    }
+}
+
+static uint32_t ppc4xx_i2c_readw(void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writew(void *opaque,
+                              hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
+    ppc4xx_i2c_writeb(opaque, addr + 1, value);
+}
+
+static uint32_t ppc4xx_i2c_readl(void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writel(void *opaque,
+                              hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
+    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
+    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
+    ppc4xx_i2c_writeb(opaque, addr + 3, value);
+}
+
+static const MemoryRegionOps i2c_ops = {
+    .old_mmio = {
+        .read = { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, },
+        .write = { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ppc4xx_i2c_reset(void *opaque)
+{
+    ppc4xx_i2c_t *i2c;
+
+    i2c = opaque;
+    i2c->mdata = 0x00;
+    i2c->sdata = 0x00;
+    i2c->cntl = 0x00;
+    i2c->mdcntl = 0x00;
+    i2c->sts = 0x00;
+    i2c->extsts = 0x00;
+    i2c->clkdiv = 0x00;
+    i2c->xfrcnt = 0x00;
+    i2c->directcntl = 0x0F;
+}
+
+void ppc405_i2c_init(hwaddr base, qemu_irq irq)
+{
+    ppc4xx_i2c_t *i2c;
+
+    i2c = g_malloc0(sizeof(ppc4xx_i2c_t));
+    i2c->irq = irq;
+#ifdef DEBUG_I2C
+    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
+#endif
+    memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011);
+    memory_region_add_subregion(get_system_memory(), base, &i2c->iomem);
+    qemu_register_reset(ppc4xx_i2c_reset, i2c);
+}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [Qemu-devel] [RFC PATCH 02/12] ppc4xx: Make MAL emulation more generic
  2017-08-13 17:04 [Qemu-devel] [RFC PATCH 00/12] Sam460ex emulation BALATON Zoltan
                   ` (2 preceding siblings ...)
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 08/12] hw/ide: Emulate SiI3112 SATA controller BALATON Zoltan
@ 2017-08-13 17:04 ` BALATON Zoltan
  2017-08-15  4:11   ` David Gibson
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 04/12] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs BALATON Zoltan
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-13 17:04 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Allow MAL with more RX and TX channels as found in newer versions.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/ppc405_uc.c      |   2 +-
 hw/ppc/ppc4xx_devs.c    | 171 +++++++++++++++++++-----------------------------
 include/hw/ppc/ppc4xx.h |   3 +-
 3 files changed, 70 insertions(+), 106 deletions(-)

diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 3c74402..03856d5 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -2281,7 +2281,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
     mal_irqs[1] = pic[12];
     mal_irqs[2] = pic[13];
     mal_irqs[3] = pic[14];
-    ppc405_mal_init(env, mal_irqs);
+    ppc4xx_mal_init(env, 4, 2, mal_irqs);
     /* Ethernet */
     /* Uses pic[9], pic[15], pic[17] */
     /* CPU control */
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 8e4f78e..6e1cc09 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -737,6 +737,7 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
 
 /*****************************************************************************/
 /* MAL */
+
 enum {
     MAL0_CFG      = 0x180,
     MAL0_ESR      = 0x181,
@@ -750,17 +751,13 @@ enum {
     MAL0_RXEOBISR = 0x192,
     MAL0_RXDEIR   = 0x193,
     MAL0_TXCTP0R  = 0x1A0,
-    MAL0_TXCTP1R  = 0x1A1,
-    MAL0_TXCTP2R  = 0x1A2,
-    MAL0_TXCTP3R  = 0x1A3,
     MAL0_RXCTP0R  = 0x1C0,
-    MAL0_RXCTP1R  = 0x1C1,
     MAL0_RCBS0    = 0x1E0,
     MAL0_RCBS1    = 0x1E1,
 };
 
-typedef struct ppc40x_mal_t ppc40x_mal_t;
-struct ppc40x_mal_t {
+typedef struct ppc4xx_mal_t ppc4xx_mal_t;
+struct ppc4xx_mal_t {
     qemu_irq irqs[4];
     uint32_t cfg;
     uint32_t esr;
@@ -773,16 +770,32 @@ struct ppc40x_mal_t {
     uint32_t rxcarr;
     uint32_t rxeobisr;
     uint32_t rxdeir;
-    uint32_t txctpr[4];
-    uint32_t rxctpr[2];
-    uint32_t rcbs[2];
+    uint32_t *txctpr;
+    uint32_t *rxctpr;
+    uint32_t *rcbs;
+    uint8_t  txcnum;
+    uint8_t  rxcnum;
 };
 
-static void ppc40x_mal_reset(void *opaque);
+static void ppc4xx_mal_reset(void *opaque)
+{
+    ppc4xx_mal_t *mal;
+
+    mal = opaque;
+    mal->cfg = 0x0007C000;
+    mal->esr = 0x00000000;
+    mal->ier = 0x00000000;
+    mal->rxcasr = 0x00000000;
+    mal->rxdeir = 0x00000000;
+    mal->rxeobisr = 0x00000000;
+    mal->txcasr = 0x00000000;
+    mal->txdeir = 0x00000000;
+    mal->txeobisr = 0x00000000;
+}
 
 static uint32_t dcr_read_mal(void *opaque, int dcrn)
 {
-    ppc40x_mal_t *mal;
+    ppc4xx_mal_t *mal;
     uint32_t ret;
 
     mal = opaque;
@@ -820,48 +833,32 @@ static uint32_t dcr_read_mal(void *opaque, int dcrn)
     case MAL0_RXDEIR:
         ret = mal->rxdeir;
         break;
-    case MAL0_TXCTP0R:
-        ret = mal->txctpr[0];
-        break;
-    case MAL0_TXCTP1R:
-        ret = mal->txctpr[1];
-        break;
-    case MAL0_TXCTP2R:
-        ret = mal->txctpr[2];
-        break;
-    case MAL0_TXCTP3R:
-        ret = mal->txctpr[3];
-        break;
-    case MAL0_RXCTP0R:
-        ret = mal->rxctpr[0];
-        break;
-    case MAL0_RXCTP1R:
-        ret = mal->rxctpr[1];
-        break;
-    case MAL0_RCBS0:
-        ret = mal->rcbs[0];
-        break;
-    case MAL0_RCBS1:
-        ret = mal->rcbs[1];
-        break;
     default:
         ret = 0;
         break;
     }
+    if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
+        ret = mal->txctpr[dcrn - MAL0_TXCTP0R];
+    }
+    if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
+        ret = mal->rxctpr[dcrn - MAL0_RXCTP0R];
+    }
+    if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
+        ret = mal->rcbs[dcrn - MAL0_RCBS0];
+    }
 
     return ret;
 }
 
 static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
 {
-    ppc40x_mal_t *mal;
-    int idx;
+    ppc4xx_mal_t *mal;
 
     mal = opaque;
     switch (dcrn) {
     case MAL0_CFG:
         if (val & 0x80000000) {
-            ppc40x_mal_reset(mal);
+            ppc4xx_mal_reset(mal);
         }
         mal->cfg = val & 0x00FFC087;
         break;
@@ -900,65 +897,35 @@ static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
         /* Read/clear */
         mal->rxdeir &= ~val;
         break;
-    case MAL0_TXCTP0R:
-        idx = 0;
-        goto update_tx_ptr;
-    case MAL0_TXCTP1R:
-        idx = 1;
-        goto update_tx_ptr;
-    case MAL0_TXCTP2R:
-        idx = 2;
-        goto update_tx_ptr;
-    case MAL0_TXCTP3R:
-        idx = 3;
-    update_tx_ptr:
-        mal->txctpr[idx] = val;
-        break;
-    case MAL0_RXCTP0R:
-        idx = 0;
-        goto update_rx_ptr;
-    case MAL0_RXCTP1R:
-        idx = 1;
-    update_rx_ptr:
-        mal->rxctpr[idx] = val;
-        break;
-    case MAL0_RCBS0:
-        idx = 0;
-        goto update_rx_size;
-    case MAL0_RCBS1:
-        idx = 1;
-    update_rx_size:
-        mal->rcbs[idx] = val & 0x000000FF;
-        break;
+    }
+    if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
+        mal->txctpr[dcrn - MAL0_TXCTP0R] = val;
+    }
+    if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
+        mal->rxctpr[dcrn - MAL0_RXCTP0R] = val;
+    }
+    if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
+        mal->rcbs[dcrn - MAL0_RCBS0] = val & 0x000000FF;
     }
 }
 
-static void ppc40x_mal_reset(void *opaque)
-{
-    ppc40x_mal_t *mal;
-
-    mal = opaque;
-    mal->cfg = 0x0007C000;
-    mal->esr = 0x00000000;
-    mal->ier = 0x00000000;
-    mal->rxcasr = 0x00000000;
-    mal->rxdeir = 0x00000000;
-    mal->rxeobisr = 0x00000000;
-    mal->txcasr = 0x00000000;
-    mal->txdeir = 0x00000000;
-    mal->txeobisr = 0x00000000;
-}
-
-void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
+void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
+                     qemu_irq irqs[4])
 {
-    ppc40x_mal_t *mal;
+    ppc4xx_mal_t *mal;
     int i;
 
-    mal = g_malloc0(sizeof(ppc40x_mal_t));
+    assert(txcnum <= 32 && rxcnum <= 32);
+    mal = g_malloc0(sizeof(*mal));
+    mal->txcnum = txcnum;
+    mal->rxcnum = rxcnum;
+    mal->txctpr = g_new0(uint32_t, txcnum);
+    mal->rxctpr = g_new0(uint32_t, rxcnum);
+    mal->rcbs = g_new0(uint32_t, rxcnum);
     for (i = 0; i < 4; i++) {
         mal->irqs[i] = irqs[i];
     }
-    qemu_register_reset(&ppc40x_mal_reset, mal);
+    qemu_register_reset(&ppc4xx_mal_reset, mal);
     ppc_dcr_register(env, MAL0_CFG,
                      mal, &dcr_read_mal, &dcr_write_mal);
     ppc_dcr_register(env, MAL0_ESR,
@@ -981,20 +948,16 @@ void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
                      mal, &dcr_read_mal, &dcr_write_mal);
     ppc_dcr_register(env, MAL0_RXDEIR,
                      mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP0R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP1R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP2R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP3R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCTP0R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCTP1R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RCBS0,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RCBS1,
-                     mal, &dcr_read_mal, &dcr_write_mal);
+    for (i = 0; i < txcnum; i++) {
+        ppc_dcr_register(env, MAL0_TXCTP0R + i,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+    }
+    for (i = 0; i < rxcnum; i++) {
+        ppc_dcr_register(env, MAL0_RXCTP0R + i,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+    }
+    for (i = 0; i < rxcnum; i++) {
+        ppc_dcr_register(env, MAL0_RCBS0 + i,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+    }
 }
diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index db50cfa..cb0bb55 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -53,7 +53,8 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
                         hwaddr *ram_sizes,
                         int do_init);
 
-void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4]);
+void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
+                     qemu_irq irqs[4]);
 
 #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [Qemu-devel] [RFC PATCH 01/12] ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs
  2017-08-13 17:04 [Qemu-devel] [RFC PATCH 00/12] Sam460ex emulation BALATON Zoltan
                   ` (8 preceding siblings ...)
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 05/12] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file BALATON Zoltan
@ 2017-08-13 17:04 ` BALATON Zoltan
  2017-08-14  4:37   ` David Gibson
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 12/12] ppc: Add aCube Sam460ex board BALATON Zoltan
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 10/12] ppc: Add 460EX embedded CPU BALATON Zoltan
  11 siblings, 1 reply; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-13 17:04 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

This device appears in other SoCs as well not just in 405 ones

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/ppc405_uc.c      | 263 -----------------------------------------------
 hw/ppc/ppc4xx_devs.c    | 264 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/ppc/ppc4xx.h |   2 +
 3 files changed, 266 insertions(+), 263 deletions(-)

diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index f6fe3e6..3c74402 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -42,7 +42,6 @@
 //#define DEBUG_OCM
 //#define DEBUG_I2C
 //#define DEBUG_GPT
-//#define DEBUG_MAL
 //#define DEBUG_CLOCKS
 //#define DEBUG_CLOCKS_LL
 
@@ -1513,268 +1512,6 @@ static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5])
 }
 
 /*****************************************************************************/
-/* MAL */
-enum {
-    MAL0_CFG      = 0x180,
-    MAL0_ESR      = 0x181,
-    MAL0_IER      = 0x182,
-    MAL0_TXCASR   = 0x184,
-    MAL0_TXCARR   = 0x185,
-    MAL0_TXEOBISR = 0x186,
-    MAL0_TXDEIR   = 0x187,
-    MAL0_RXCASR   = 0x190,
-    MAL0_RXCARR   = 0x191,
-    MAL0_RXEOBISR = 0x192,
-    MAL0_RXDEIR   = 0x193,
-    MAL0_TXCTP0R  = 0x1A0,
-    MAL0_TXCTP1R  = 0x1A1,
-    MAL0_TXCTP2R  = 0x1A2,
-    MAL0_TXCTP3R  = 0x1A3,
-    MAL0_RXCTP0R  = 0x1C0,
-    MAL0_RXCTP1R  = 0x1C1,
-    MAL0_RCBS0    = 0x1E0,
-    MAL0_RCBS1    = 0x1E1,
-};
-
-typedef struct ppc40x_mal_t ppc40x_mal_t;
-struct ppc40x_mal_t {
-    qemu_irq irqs[4];
-    uint32_t cfg;
-    uint32_t esr;
-    uint32_t ier;
-    uint32_t txcasr;
-    uint32_t txcarr;
-    uint32_t txeobisr;
-    uint32_t txdeir;
-    uint32_t rxcasr;
-    uint32_t rxcarr;
-    uint32_t rxeobisr;
-    uint32_t rxdeir;
-    uint32_t txctpr[4];
-    uint32_t rxctpr[2];
-    uint32_t rcbs[2];
-};
-
-static void ppc40x_mal_reset (void *opaque);
-
-static uint32_t dcr_read_mal (void *opaque, int dcrn)
-{
-    ppc40x_mal_t *mal;
-    uint32_t ret;
-
-    mal = opaque;
-    switch (dcrn) {
-    case MAL0_CFG:
-        ret = mal->cfg;
-        break;
-    case MAL0_ESR:
-        ret = mal->esr;
-        break;
-    case MAL0_IER:
-        ret = mal->ier;
-        break;
-    case MAL0_TXCASR:
-        ret = mal->txcasr;
-        break;
-    case MAL0_TXCARR:
-        ret = mal->txcarr;
-        break;
-    case MAL0_TXEOBISR:
-        ret = mal->txeobisr;
-        break;
-    case MAL0_TXDEIR:
-        ret = mal->txdeir;
-        break;
-    case MAL0_RXCASR:
-        ret = mal->rxcasr;
-        break;
-    case MAL0_RXCARR:
-        ret = mal->rxcarr;
-        break;
-    case MAL0_RXEOBISR:
-        ret = mal->rxeobisr;
-        break;
-    case MAL0_RXDEIR:
-        ret = mal->rxdeir;
-        break;
-    case MAL0_TXCTP0R:
-        ret = mal->txctpr[0];
-        break;
-    case MAL0_TXCTP1R:
-        ret = mal->txctpr[1];
-        break;
-    case MAL0_TXCTP2R:
-        ret = mal->txctpr[2];
-        break;
-    case MAL0_TXCTP3R:
-        ret = mal->txctpr[3];
-        break;
-    case MAL0_RXCTP0R:
-        ret = mal->rxctpr[0];
-        break;
-    case MAL0_RXCTP1R:
-        ret = mal->rxctpr[1];
-        break;
-    case MAL0_RCBS0:
-        ret = mal->rcbs[0];
-        break;
-    case MAL0_RCBS1:
-        ret = mal->rcbs[1];
-        break;
-    default:
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_mal (void *opaque, int dcrn, uint32_t val)
-{
-    ppc40x_mal_t *mal;
-    int idx;
-
-    mal = opaque;
-    switch (dcrn) {
-    case MAL0_CFG:
-        if (val & 0x80000000)
-            ppc40x_mal_reset(mal);
-        mal->cfg = val & 0x00FFC087;
-        break;
-    case MAL0_ESR:
-        /* Read/clear */
-        mal->esr &= ~val;
-        break;
-    case MAL0_IER:
-        mal->ier = val & 0x0000001F;
-        break;
-    case MAL0_TXCASR:
-        mal->txcasr = val & 0xF0000000;
-        break;
-    case MAL0_TXCARR:
-        mal->txcarr = val & 0xF0000000;
-        break;
-    case MAL0_TXEOBISR:
-        /* Read/clear */
-        mal->txeobisr &= ~val;
-        break;
-    case MAL0_TXDEIR:
-        /* Read/clear */
-        mal->txdeir &= ~val;
-        break;
-    case MAL0_RXCASR:
-        mal->rxcasr = val & 0xC0000000;
-        break;
-    case MAL0_RXCARR:
-        mal->rxcarr = val & 0xC0000000;
-        break;
-    case MAL0_RXEOBISR:
-        /* Read/clear */
-        mal->rxeobisr &= ~val;
-        break;
-    case MAL0_RXDEIR:
-        /* Read/clear */
-        mal->rxdeir &= ~val;
-        break;
-    case MAL0_TXCTP0R:
-        idx = 0;
-        goto update_tx_ptr;
-    case MAL0_TXCTP1R:
-        idx = 1;
-        goto update_tx_ptr;
-    case MAL0_TXCTP2R:
-        idx = 2;
-        goto update_tx_ptr;
-    case MAL0_TXCTP3R:
-        idx = 3;
-    update_tx_ptr:
-        mal->txctpr[idx] = val;
-        break;
-    case MAL0_RXCTP0R:
-        idx = 0;
-        goto update_rx_ptr;
-    case MAL0_RXCTP1R:
-        idx = 1;
-    update_rx_ptr:
-        mal->rxctpr[idx] = val;
-        break;
-    case MAL0_RCBS0:
-        idx = 0;
-        goto update_rx_size;
-    case MAL0_RCBS1:
-        idx = 1;
-    update_rx_size:
-        mal->rcbs[idx] = val & 0x000000FF;
-        break;
-    }
-}
-
-static void ppc40x_mal_reset (void *opaque)
-{
-    ppc40x_mal_t *mal;
-
-    mal = opaque;
-    mal->cfg = 0x0007C000;
-    mal->esr = 0x00000000;
-    mal->ier = 0x00000000;
-    mal->rxcasr = 0x00000000;
-    mal->rxdeir = 0x00000000;
-    mal->rxeobisr = 0x00000000;
-    mal->txcasr = 0x00000000;
-    mal->txdeir = 0x00000000;
-    mal->txeobisr = 0x00000000;
-}
-
-static void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
-{
-    ppc40x_mal_t *mal;
-    int i;
-
-    mal = g_malloc0(sizeof(ppc40x_mal_t));
-    for (i = 0; i < 4; i++)
-        mal->irqs[i] = irqs[i];
-    qemu_register_reset(&ppc40x_mal_reset, mal);
-    ppc_dcr_register(env, MAL0_CFG,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_ESR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_IER,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCASR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCARR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXEOBISR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXDEIR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCASR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCARR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXEOBISR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXDEIR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP0R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP1R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP2R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP3R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCTP0R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCTP1R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RCBS0,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RCBS1,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-}
-
-/*****************************************************************************/
 /* SPR */
 void ppc40x_core_reset(PowerPCCPU *cpu)
 {
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index e7f413e..8e4f78e 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -734,3 +734,267 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
 
     return ram_size;
 }
+
+/*****************************************************************************/
+/* MAL */
+enum {
+    MAL0_CFG      = 0x180,
+    MAL0_ESR      = 0x181,
+    MAL0_IER      = 0x182,
+    MAL0_TXCASR   = 0x184,
+    MAL0_TXCARR   = 0x185,
+    MAL0_TXEOBISR = 0x186,
+    MAL0_TXDEIR   = 0x187,
+    MAL0_RXCASR   = 0x190,
+    MAL0_RXCARR   = 0x191,
+    MAL0_RXEOBISR = 0x192,
+    MAL0_RXDEIR   = 0x193,
+    MAL0_TXCTP0R  = 0x1A0,
+    MAL0_TXCTP1R  = 0x1A1,
+    MAL0_TXCTP2R  = 0x1A2,
+    MAL0_TXCTP3R  = 0x1A3,
+    MAL0_RXCTP0R  = 0x1C0,
+    MAL0_RXCTP1R  = 0x1C1,
+    MAL0_RCBS0    = 0x1E0,
+    MAL0_RCBS1    = 0x1E1,
+};
+
+typedef struct ppc40x_mal_t ppc40x_mal_t;
+struct ppc40x_mal_t {
+    qemu_irq irqs[4];
+    uint32_t cfg;
+    uint32_t esr;
+    uint32_t ier;
+    uint32_t txcasr;
+    uint32_t txcarr;
+    uint32_t txeobisr;
+    uint32_t txdeir;
+    uint32_t rxcasr;
+    uint32_t rxcarr;
+    uint32_t rxeobisr;
+    uint32_t rxdeir;
+    uint32_t txctpr[4];
+    uint32_t rxctpr[2];
+    uint32_t rcbs[2];
+};
+
+static void ppc40x_mal_reset(void *opaque);
+
+static uint32_t dcr_read_mal(void *opaque, int dcrn)
+{
+    ppc40x_mal_t *mal;
+    uint32_t ret;
+
+    mal = opaque;
+    switch (dcrn) {
+    case MAL0_CFG:
+        ret = mal->cfg;
+        break;
+    case MAL0_ESR:
+        ret = mal->esr;
+        break;
+    case MAL0_IER:
+        ret = mal->ier;
+        break;
+    case MAL0_TXCASR:
+        ret = mal->txcasr;
+        break;
+    case MAL0_TXCARR:
+        ret = mal->txcarr;
+        break;
+    case MAL0_TXEOBISR:
+        ret = mal->txeobisr;
+        break;
+    case MAL0_TXDEIR:
+        ret = mal->txdeir;
+        break;
+    case MAL0_RXCASR:
+        ret = mal->rxcasr;
+        break;
+    case MAL0_RXCARR:
+        ret = mal->rxcarr;
+        break;
+    case MAL0_RXEOBISR:
+        ret = mal->rxeobisr;
+        break;
+    case MAL0_RXDEIR:
+        ret = mal->rxdeir;
+        break;
+    case MAL0_TXCTP0R:
+        ret = mal->txctpr[0];
+        break;
+    case MAL0_TXCTP1R:
+        ret = mal->txctpr[1];
+        break;
+    case MAL0_TXCTP2R:
+        ret = mal->txctpr[2];
+        break;
+    case MAL0_TXCTP3R:
+        ret = mal->txctpr[3];
+        break;
+    case MAL0_RXCTP0R:
+        ret = mal->rxctpr[0];
+        break;
+    case MAL0_RXCTP1R:
+        ret = mal->rxctpr[1];
+        break;
+    case MAL0_RCBS0:
+        ret = mal->rcbs[0];
+        break;
+    case MAL0_RCBS1:
+        ret = mal->rcbs[1];
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
+{
+    ppc40x_mal_t *mal;
+    int idx;
+
+    mal = opaque;
+    switch (dcrn) {
+    case MAL0_CFG:
+        if (val & 0x80000000) {
+            ppc40x_mal_reset(mal);
+        }
+        mal->cfg = val & 0x00FFC087;
+        break;
+    case MAL0_ESR:
+        /* Read/clear */
+        mal->esr &= ~val;
+        break;
+    case MAL0_IER:
+        mal->ier = val & 0x0000001F;
+        break;
+    case MAL0_TXCASR:
+        mal->txcasr = val & 0xF0000000;
+        break;
+    case MAL0_TXCARR:
+        mal->txcarr = val & 0xF0000000;
+        break;
+    case MAL0_TXEOBISR:
+        /* Read/clear */
+        mal->txeobisr &= ~val;
+        break;
+    case MAL0_TXDEIR:
+        /* Read/clear */
+        mal->txdeir &= ~val;
+        break;
+    case MAL0_RXCASR:
+        mal->rxcasr = val & 0xC0000000;
+        break;
+    case MAL0_RXCARR:
+        mal->rxcarr = val & 0xC0000000;
+        break;
+    case MAL0_RXEOBISR:
+        /* Read/clear */
+        mal->rxeobisr &= ~val;
+        break;
+    case MAL0_RXDEIR:
+        /* Read/clear */
+        mal->rxdeir &= ~val;
+        break;
+    case MAL0_TXCTP0R:
+        idx = 0;
+        goto update_tx_ptr;
+    case MAL0_TXCTP1R:
+        idx = 1;
+        goto update_tx_ptr;
+    case MAL0_TXCTP2R:
+        idx = 2;
+        goto update_tx_ptr;
+    case MAL0_TXCTP3R:
+        idx = 3;
+    update_tx_ptr:
+        mal->txctpr[idx] = val;
+        break;
+    case MAL0_RXCTP0R:
+        idx = 0;
+        goto update_rx_ptr;
+    case MAL0_RXCTP1R:
+        idx = 1;
+    update_rx_ptr:
+        mal->rxctpr[idx] = val;
+        break;
+    case MAL0_RCBS0:
+        idx = 0;
+        goto update_rx_size;
+    case MAL0_RCBS1:
+        idx = 1;
+    update_rx_size:
+        mal->rcbs[idx] = val & 0x000000FF;
+        break;
+    }
+}
+
+static void ppc40x_mal_reset(void *opaque)
+{
+    ppc40x_mal_t *mal;
+
+    mal = opaque;
+    mal->cfg = 0x0007C000;
+    mal->esr = 0x00000000;
+    mal->ier = 0x00000000;
+    mal->rxcasr = 0x00000000;
+    mal->rxdeir = 0x00000000;
+    mal->rxeobisr = 0x00000000;
+    mal->txcasr = 0x00000000;
+    mal->txdeir = 0x00000000;
+    mal->txeobisr = 0x00000000;
+}
+
+void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
+{
+    ppc40x_mal_t *mal;
+    int i;
+
+    mal = g_malloc0(sizeof(ppc40x_mal_t));
+    for (i = 0; i < 4; i++) {
+        mal->irqs[i] = irqs[i];
+    }
+    qemu_register_reset(&ppc40x_mal_reset, mal);
+    ppc_dcr_register(env, MAL0_CFG,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_ESR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_IER,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCASR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCARR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXEOBISR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXDEIR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCASR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCARR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXEOBISR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXDEIR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP0R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP1R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP2R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP3R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCTP0R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCTP1R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RCBS0,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RCBS1,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+}
diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index 66e57a5..db50cfa 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -53,6 +53,8 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
                         hwaddr *ram_sizes,
                         int do_init);
 
+void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4]);
+
 #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"
 
 #endif /* PPC4XX_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [Qemu-devel] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-13 17:04 [Qemu-devel] [RFC PATCH 00/12] Sam460ex emulation BALATON Zoltan
@ 2017-08-13 17:04 ` BALATON Zoltan
  2017-08-18  1:53   ` David Gibson
  2017-08-18  9:30   ` [Qemu-devel] [Qemu-ppc] " luigi burdo
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 06/12] ppc4xx_i2c: QOMify BALATON Zoltan
                   ` (10 subsequent siblings)
  11 siblings, 2 replies; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-13 17:04 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/Makefile.objs |   2 +-
 hw/ppc/ppc440_pcix.c | 506 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 507 insertions(+), 1 deletion(-)
 create mode 100644 hw/ppc/ppc440_pcix.c

diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 2077216..9c5d58a 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -13,7 +13,7 @@ endif
 obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
 # PowerPC 4xx boards
 obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
-obj-y += ppc4xx_pci.o ppc4xx_i2c.o
+obj-y += ppc4xx_pci.o ppc440_pcix.o ppc4xx_i2c.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
 obj-$(CONFIG_PREP) += prep_systemio.o
diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c
new file mode 100644
index 0000000..3abd0d0
--- /dev/null
+++ b/hw/ppc/ppc440_pcix.c
@@ -0,0 +1,506 @@
+/*
+ * Emulation of the ibm,plb-pcix PCI controller
+ * This is found in some 440 SoCs e.g. the 460EX.
+ *
+ * Copyright (c) 2016 BALATON Zoltan
+ *
+ * Derived from ppc4xx_pci.c and pci-host/ppce500.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/hw.h"
+#include "hw/ppc/ppc.h"
+#include "hw/ppc/ppc4xx.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "exec/address-spaces.h"
+
+/*#define DEBUG_PCI*/
+
+#ifdef DEBUG_PCI
+#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
+#else
+#define DPRINTF(fmt, ...)
+#endif /* DEBUG */
+
+struct PLBOutMap {
+    uint64_t la;
+    uint64_t pcia;
+    uint32_t sa;
+    MemoryRegion mr;
+};
+
+struct PLBInMap {
+    uint64_t sa;
+    uint64_t la;
+    MemoryRegion mr;
+};
+
+#define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host"
+#define PPC440_PCIX_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(PPC440PCIXState, (obj), TYPE_PPC440_PCIX_HOST_BRIDGE)
+
+#define PPC440_PCIX_NR_POMS 3
+#define PPC440_PCIX_NR_PIMS 3
+
+typedef struct PPC440PCIXState {
+    PCIHostState parent_obj;
+
+    PCIDevice *dev;
+    struct PLBOutMap pom[PPC440_PCIX_NR_POMS];
+    struct PLBInMap pim[PPC440_PCIX_NR_PIMS];
+    uint32_t sts;
+    qemu_irq irq[PCI_NUM_PINS];
+    AddressSpace bm_as;
+    MemoryRegion bm;
+
+    MemoryRegion container;
+    MemoryRegion iomem;
+    MemoryRegion busmem;
+} PPC440PCIXState;
+
+#define PPC440_REG_BASE     0x80000
+#define PPC440_REG_SIZE     0xff
+
+#define PCIC0_CFGADDR       0x0
+#define PCIC0_CFGDATA       0x4
+
+#define PCIX0_POM0LAL       0x68
+#define PCIX0_POM0LAH       0x6c
+#define PCIX0_POM0SA        0x70
+#define PCIX0_POM0PCIAL     0x74
+#define PCIX0_POM0PCIAH     0x78
+#define PCIX0_POM1LAL       0x7c
+#define PCIX0_POM1LAH       0x80
+#define PCIX0_POM1SA        0x84
+#define PCIX0_POM1PCIAL     0x88
+#define PCIX0_POM1PCIAH     0x8c
+#define PCIX0_POM2SA        0x90
+
+#define PCIX0_PIM0SAL       0x98
+#define PCIX0_PIM0LAL       0x9c
+#define PCIX0_PIM0LAH       0xa0
+#define PCIX0_PIM1SA        0xa4
+#define PCIX0_PIM1LAL       0xa8
+#define PCIX0_PIM1LAH       0xac
+#define PCIX0_PIM2SAL       0xb0
+#define PCIX0_PIM2LAL       0xb4
+#define PCIX0_PIM2LAH       0xb8
+#define PCIX0_PIM0SAH       0xf8
+#define PCIX0_PIM2SAH       0xfc
+
+#define PCIX0_STS           0xe0
+
+#define PCI_ALL_SIZE        (PPC440_REG_BASE + PPC440_REG_SIZE)
+
+/* DMA mapping */
+static void ppc440_pcix_update_pim(PPC440PCIXState *s, int idx)
+{
+    MemoryRegion *mem = &s->pim[idx].mr;
+    char *name;
+    uint64_t size;
+
+    if (memory_region_is_mapped(mem)) {
+        /* Before we modify anything, unmap and destroy the region */
+        memory_region_del_subregion(&s->bm, mem);
+        object_unparent(OBJECT(mem));
+    }
+
+    if (!(s->pim[idx].sa & 1)) {
+        /* Not enabled, nothing to do */
+        return;
+    }
+
+    name = g_strdup_printf("PCI Inbound Window %d", idx);
+    size = ~(s->pim[idx].sa & ~7ULL) + 1;
+    memory_region_init_alias(mem, OBJECT(s), name, get_system_memory(),
+                             s->pim[idx].la, size);
+    memory_region_add_subregion_overlap(&s->bm, 0, mem, -1);
+    g_free(name);
+
+    DPRINTF("%s: Added window %d of size=%#"PRIx64" to CPU=%#"PRIx64"\n",
+            __func__, idx, size, s->pim[idx].la);
+}
+
+/* BAR mapping */
+static void ppc440_pcix_update_pom(PPC440PCIXState *s, int idx)
+{
+    MemoryRegion *mem = &s->pom[idx].mr;
+    MemoryRegion *address_space_mem = get_system_memory();
+    char *name;
+    uint32_t size;
+
+    if (memory_region_is_mapped(mem)) {
+        /* Before we modify anything, unmap and destroy the region */
+        memory_region_del_subregion(address_space_mem, mem);
+        object_unparent(OBJECT(mem));
+    }
+
+    if (!(s->pom[idx].sa & 1)) {
+        /* Not enabled, nothing to do */
+        return;
+    }
+
+    name = g_strdup_printf("PCI Outbound Window %d", idx);
+    size = ~(s->pom[idx].sa & 0xfffffffe) + 1;
+    if (!size) {
+        size = 0xffffffff;
+    }
+    memory_region_init_alias(mem, OBJECT(s), name, &s->busmem,
+                             s->pom[idx].pcia, size);
+    memory_region_add_subregion(address_space_mem, s->pom[idx].la, mem);
+    g_free(name);
+
+    DPRINTF("%s: Added window %d of size=%#x from CPU=%#"PRIx64
+            " to PCI=%#"PRIx64"\n", __func__, idx, size, s->pom[idx].la,
+            s->pom[idx].pcia);
+}
+
+static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr,
+                                   uint64_t val, unsigned size)
+{
+    struct PPC440PCIXState *s = opaque;
+
+    DPRINTF("%s: addr 0x%"PRIx64 " = %"PRIx64 "\n", __func__, addr, val);
+    switch (addr) {
+    case PCI_VENDOR_ID ... PCI_MAX_LAT:
+        stl_le_p(s->dev->config + addr, val);
+        break;
+
+    case PCIX0_POM0LAL:
+        s->pom[0].la &= 0xffffffff00000000ULL;
+        s->pom[0].la |= val;
+        ppc440_pcix_update_pom(s, 0);
+        break;
+    case PCIX0_POM0LAH:
+        s->pom[0].la &= 0xffffffffULL;
+        s->pom[0].la |= val << 32;
+        ppc440_pcix_update_pom(s, 0);
+        break;
+    case PCIX0_POM0SA:
+        s->pom[0].sa = val;
+        ppc440_pcix_update_pom(s, 0);
+        break;
+    case PCIX0_POM0PCIAL:
+        s->pom[0].pcia &= 0xffffffff00000000ULL;
+        s->pom[0].pcia |= val;
+        ppc440_pcix_update_pom(s, 0);
+        break;
+    case PCIX0_POM0PCIAH:
+        s->pom[0].pcia &= 0xffffffffULL;
+        s->pom[0].pcia |= val << 32;
+        ppc440_pcix_update_pom(s, 0);
+        break;
+    case PCIX0_POM1LAL:
+        s->pom[1].la &= 0xffffffff00000000ULL;
+        s->pom[1].la |= val;
+        ppc440_pcix_update_pom(s, 1);
+        break;
+    case PCIX0_POM1LAH:
+        s->pom[1].la &= 0xffffffffULL;
+        s->pom[1].la |= val << 32;
+        ppc440_pcix_update_pom(s, 1);
+        break;
+    case PCIX0_POM1SA:
+        s->pom[1].sa = val;
+        ppc440_pcix_update_pom(s, 1);
+        break;
+    case PCIX0_POM1PCIAL:
+        s->pom[1].pcia &= 0xffffffff00000000ULL;
+        s->pom[1].pcia |= val;
+        ppc440_pcix_update_pom(s, 1);
+        break;
+    case PCIX0_POM1PCIAH:
+        s->pom[1].pcia &= 0xffffffffULL;
+        s->pom[1].pcia |= val << 32;
+        ppc440_pcix_update_pom(s, 1);
+        break;
+    case PCIX0_POM2SA:
+        s->pom[2].sa = val;
+        break;
+
+    case PCIX0_PIM0SAL:
+        s->pim[0].sa &= 0xffffffff00000000ULL;
+        s->pim[0].sa |= val;
+        ppc440_pcix_update_pim(s, 0);
+        break;
+    case PCIX0_PIM0LAL:
+        s->pim[0].la &= 0xffffffff00000000ULL;
+        s->pim[0].la |= val;
+        ppc440_pcix_update_pim(s, 0);
+        break;
+    case PCIX0_PIM0LAH:
+        s->pim[0].la &= 0xffffffffULL;
+        s->pim[0].la |= val << 32;
+        ppc440_pcix_update_pim(s, 0);
+        break;
+    case PCIX0_PIM1SA:
+        s->pim[1].sa = val;
+        ppc440_pcix_update_pim(s, 1);
+        break;
+    case PCIX0_PIM1LAL:
+        s->pim[1].la &= 0xffffffff00000000ULL;
+        s->pim[1].la |= val;
+        ppc440_pcix_update_pim(s, 1);
+        break;
+    case PCIX0_PIM1LAH:
+        s->pim[1].la &= 0xffffffffULL;
+        s->pim[1].la |= val << 32;
+        ppc440_pcix_update_pim(s, 1);
+        break;
+    case PCIX0_PIM2SAL:
+        s->pim[2].sa &= 0xffffffff00000000ULL;
+        s->pim[2].sa = val;
+        ppc440_pcix_update_pim(s, 2);
+        break;
+    case PCIX0_PIM2LAL:
+        s->pim[2].la &= 0xffffffff00000000ULL;
+        s->pim[2].la |= val;
+        ppc440_pcix_update_pim(s, 2);
+        break;
+    case PCIX0_PIM2LAH:
+        s->pim[2].la &= 0xffffffffULL;
+        s->pim[2].la |= val << 32;
+        ppc440_pcix_update_pim(s, 2);
+        break;
+
+    case PCIX0_STS:
+        s->sts = val;
+        break;
+
+    case PCIX0_PIM0SAH:
+        s->pim[0].sa &= 0xffffffffULL;
+        s->pim[0].sa |= val << 32;
+        ppc440_pcix_update_pim(s, 0);
+        break;
+    case PCIX0_PIM2SAH:
+        s->pim[2].sa &= 0xffffffffULL;
+        s->pim[2].sa |= val << 32;
+        ppc440_pcix_update_pim(s, 2);
+        break;
+
+    default:
+        printf("%s: unhandled PCI internal register 0x%lx\n", __func__,
+               (unsigned long)addr);
+        break;
+    }
+}
+
+static uint64_t ppc440_pcix_reg_read4(void *opaque, hwaddr addr,
+                                     unsigned size)
+{
+    struct PPC440PCIXState *s = opaque;
+    uint32_t val;
+
+    switch (addr) {
+    case PCI_VENDOR_ID ... PCI_MAX_LAT:
+        val = ldl_le_p(s->dev->config + addr);
+        break;
+
+    case PCIX0_POM0LAL:
+        val = s->pom[0].la;
+        break;
+    case PCIX0_POM0LAH:
+        val = s->pom[0].la >> 32;
+        break;
+    case PCIX0_POM0SA:
+        val = s->pom[0].sa;
+        break;
+    case PCIX0_POM0PCIAL:
+        val = s->pom[0].pcia;
+        break;
+    case PCIX0_POM0PCIAH:
+        val = s->pom[0].pcia >> 32;
+        break;
+    case PCIX0_POM1LAL:
+        val = s->pom[1].la;
+        break;
+    case PCIX0_POM1LAH:
+        val = s->pom[1].la >> 32;
+        break;
+    case PCIX0_POM1SA:
+        val = s->pom[1].sa;
+        break;
+    case PCIX0_POM1PCIAL:
+        val = s->pom[1].pcia;
+        break;
+    case PCIX0_POM1PCIAH:
+        val = s->pom[1].pcia >> 32;
+        break;
+    case PCIX0_POM2SA:
+        val = s->pom[2].sa;
+        break;
+
+    case PCIX0_PIM0SAL:
+        val = s->pim[0].sa;
+        break;
+    case PCIX0_PIM0LAL:
+        val = s->pim[0].la;
+        break;
+    case PCIX0_PIM0LAH:
+        val = s->pim[0].la >> 32;
+        break;
+    case PCIX0_PIM1SA:
+        val = s->pim[1].sa;
+        break;
+    case PCIX0_PIM1LAL:
+        val = s->pim[1].la;
+        break;
+    case PCIX0_PIM1LAH:
+        val = s->pim[1].la >> 32;
+        break;
+    case PCIX0_PIM2SAL:
+        val = s->pim[2].sa;
+        break;
+    case PCIX0_PIM2LAL:
+        val = s->pim[2].la;
+        break;
+    case PCIX0_PIM2LAH:
+        val = s->pim[2].la >> 32;
+        break;
+
+    case PCIX0_STS:
+        val = s->sts;
+        break;
+
+    case PCIX0_PIM0SAH:
+        val = s->pim[0].sa  >> 32;
+        break;
+    case PCIX0_PIM2SAH:
+        val = s->pim[2].sa  >> 32;
+        break;
+
+    default:
+        printf("%s: invalid PCI internal register 0x%lx\n", __func__,
+               (unsigned long)addr);
+        val = 0;
+    }
+
+    DPRINTF("%s: addr 0x%"PRIx64 " = %"PRIx32 "\n", __func__, addr, val);
+    return val;
+}
+
+static const MemoryRegionOps pci_reg_ops = {
+    .read = ppc440_pcix_reg_read4,
+    .write = ppc440_pcix_reg_write4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void ppc440_pcix_reset(DeviceState *dev)
+{
+    struct PPC440PCIXState *s = PPC440_PCIX_HOST_BRIDGE(dev);
+    int i;
+
+    memset(s->pom, 0, sizeof(s->pom));
+    memset(s->pim, 0, sizeof(s->pim));
+    for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) {
+        s->pim[i].sa = 0xffffffff00000000ULL;
+    }
+    s->sts = 0;
+}
+
+/* All pins from each slot are tied to a single board IRQ.
+ * This may need further refactoring for other boards. */
+static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    int slot = pci_dev->devfn >> 3;
+
+    DPRINTF("%s: devfn %x irq %d -> %d\n", __func__,
+            pci_dev->devfn, irq_num, slot);
+
+    return slot - 1;
+}
+
+static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level)
+{
+    qemu_irq *pci_irqs = opaque;
+
+    DPRINTF("%s: PCI irq %d\n", __func__, irq_num);
+    if (irq_num < 0) {
+        fprintf(stderr, "%s: PCI irq %d\n", __func__, irq_num);
+        return;
+    }
+    qemu_set_irq(pci_irqs[irq_num], level);
+}
+
+static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int devfn)
+{
+    PPC440PCIXState *s = opaque;
+
+    return &s->bm_as;
+}
+
+static int ppc440_pcix_initfn(SysBusDevice *dev)
+{
+    PPC440PCIXState *s;
+    PCIHostState *h;
+    int i;
+
+    h = PCI_HOST_BRIDGE(dev);
+    s = PPC440_PCIX_HOST_BRIDGE(dev);
+
+    for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
+        sysbus_init_irq(dev, &s->irq[i]);
+    }
+
+    memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX);
+    h->bus = pci_register_bus(DEVICE(dev), NULL, ppc440_pcix_set_irq,
+                         ppc440_pcix_map_irq, s->irq, &s->busmem,
+                         get_system_io(), PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
+
+    s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bridge");
+
+    memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX);
+    memory_region_add_subregion(&s->bm, 0x0, &s->busmem);
+    address_space_init(&s->bm_as, &s->bm, "pci-bm");
+    pci_setup_iommu(h->bus, ppc440_pcix_set_iommu, s);
+
+    memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE);
+    memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, h,
+                          "pci-conf-idx", 4);
+    memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, h,
+                          "pci-conf-data", 4);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s,
+                          "pci.reg", PPC440_REG_SIZE);
+    memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
+    memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
+    memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem);
+    sysbus_init_mmio(dev, &s->container);
+
+    return 0;
+}
+
+static void ppc440_pcix_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    k->init = ppc440_pcix_initfn;
+    dc->reset = ppc440_pcix_reset;
+}
+
+static const TypeInfo ppc440_pcix_info = {
+    .name          = TYPE_PPC440_PCIX_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(PPC440PCIXState),
+    .class_init    = ppc440_pcix_class_init,
+};
+
+static void ppc440_pcix_register_types(void)
+{
+    type_register_static(&ppc440_pcix_info);
+}
+
+type_init(ppc440_pcix_register_types)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [Qemu-devel] [RFC PATCH 08/12] hw/ide: Emulate SiI3112 SATA controller
  2017-08-13 17:04 [Qemu-devel] [RFC PATCH 00/12] Sam460ex emulation BALATON Zoltan
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs BALATON Zoltan
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 06/12] ppc4xx_i2c: QOMify BALATON Zoltan
@ 2017-08-13 17:04 ` BALATON Zoltan
  2017-08-14  4:42   ` David Gibson
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 02/12] ppc4xx: Make MAL emulation more generic BALATON Zoltan
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-13 17:04 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ide/Makefile.objs |   1 +
 hw/ide/sii3112.c     | 365 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 366 insertions(+)
 create mode 100644 hw/ide/sii3112.c

diff --git a/hw/ide/Makefile.objs b/hw/ide/Makefile.objs
index 729e9bd..76f3d6d 100644
--- a/hw/ide/Makefile.objs
+++ b/hw/ide/Makefile.objs
@@ -10,3 +10,4 @@ common-obj-$(CONFIG_IDE_VIA) += via.o
 common-obj-$(CONFIG_MICRODRIVE) += microdrive.o
 common-obj-$(CONFIG_AHCI) += ahci.o
 common-obj-$(CONFIG_AHCI) += ich.o
+common-obj-$(CONFIG_IDE_SII3112) += sii3112.o
diff --git a/hw/ide/sii3112.c b/hw/ide/sii3112.c
new file mode 100644
index 0000000..d3f34b5
--- /dev/null
+++ b/hw/ide/sii3112.c
@@ -0,0 +1,365 @@
+/*
+ * QEMU SiI3112A PCI to Serial ATA Controller Emulation
+ *
+ * Copyright (C) 2017 BALATON Zoltan <balaton@eik.bme.hu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include <qemu/osdep.h>
+#include <hw/ide/pci.h>
+
+#ifdef DEBUG_IDE
+#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
+#else
+#define DPRINTF(fmt, ...)
+#endif /* DEBUG */
+
+#define TYPE_SII3112_PCI "sii3112"
+#define SII3112_PCI(obj) OBJECT_CHECK(SiI3112PCIState, (obj), \
+                         TYPE_SII3112_PCI)
+
+typedef struct SiI3112Regs {
+    uint32_t confstat;
+    uint32_t scontrol;
+    uint16_t sien;
+    uint8_t swdata;
+} SiI3112Regs;
+
+typedef struct SiI3112PCIState {
+    PCIIDEState i;
+    MemoryRegion mmio;
+    SiI3112Regs regs[2];
+} SiI3112PCIState;
+
+static uint64_t sii3112_reg_read(void *opaque, hwaddr addr,
+                                unsigned int size)
+{
+    SiI3112PCIState *d = opaque;
+    uint64_t val = 0;
+
+    switch (addr) {
+    case 0x00:
+        val = d->i.bmdma[0].cmd;
+        break;
+    case 0x01:
+        val = d->regs[0].swdata;
+        break;
+    case 0x02:
+        val = d->i.bmdma[0].status;
+        break;
+    case 0x03:
+        val = 0;
+        break;
+    case 0x04 ... 0x07:
+        val = bmdma_addr_ioport_ops.read(&d->i.bmdma[0], addr - 4, size);
+        break;
+    case 0x08:
+        val = d->i.bmdma[1].cmd;
+        break;
+    case 0x09:
+        val = d->regs[1].swdata;
+        break;
+    case 0x0a:
+        val = d->i.bmdma[1].status;
+        break;
+    case 0x0b:
+        val = 0;
+        break;
+    case 0x0c ... 0x0f:
+        val = bmdma_addr_ioport_ops.read(&d->i.bmdma[1], addr - 12, size);
+        break;
+    case 0x10:
+        val = d->i.bmdma[0].cmd;
+        val |= (d->regs[0].confstat & (1UL << 11) ? (1 << 4) : 0); /*SATAINT0*/
+        val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 6) : 0); /*SATAINT1*/
+        val |= (d->i.bmdma[1].status & BM_STATUS_INT ? (1 << 14) : 0);
+        val |= d->i.bmdma[0].status << 16;
+        val |= d->i.bmdma[1].status << 24;
+        break;
+    case 0x18:
+        val = d->i.bmdma[1].cmd;
+        val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 4) : 0);
+        val |= d->i.bmdma[1].status << 16;
+        break;
+    case 0x80 ... 0x87:
+        if (size == 1) {
+            val = ide_ioport_read(&d->i.bus[0], addr - 0x80);
+        } else if (addr == 0x80) {
+            val = (size == 2) ? ide_data_readw(&d->i.bus[0], 0) :
+                                ide_data_readl(&d->i.bus[0], 0);
+        } else {
+            val = (1ULL << (size * 8)) - 1;
+        }
+        break;
+    case 0x8a:
+        val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
+                            (1ULL << (size * 8)) - 1;
+        break;
+    case 0xa0:
+        val = d->regs[0].confstat;
+        break;
+    case 0xc0 ... 0xc7:
+        if (size == 1) {
+            val = ide_ioport_read(&d->i.bus[1], addr - 0xc0);
+        } else if (addr == 0xc0) {
+            val = (size == 2) ? ide_data_readw(&d->i.bus[1], 0) :
+                                ide_data_readl(&d->i.bus[1], 0);
+        } else {
+            val = (1ULL << (size * 8)) - 1;
+        }
+        break;
+    case 0xca:
+        val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
+                            (1ULL << (size * 8)) - 1;
+        break;
+    case 0xe0:
+        val = d->regs[1].confstat;
+        break;
+    case 0x100:
+        val = d->regs[0].scontrol;
+        break;
+    case 0x104:
+        val = (d->i.bus[0].ifs[0].blk) ? 0x113 : 0;
+        break;
+    case 0x148:
+        val = d->regs[0].sien << 16;
+        break;
+    case 0x180:
+        val = d->regs[1].scontrol;
+        break;
+    case 0x184:
+        val = (d->i.bus[1].ifs[0].blk) ? 0x113 : 0;
+        break;
+    case 0x1c8:
+        val = d->regs[1].sien << 16;
+        break;
+    default:
+        val = 0;
+    }
+    DPRINTF("%s: addr 0x%"PRIx64 " size %d = %"PRIx64 "\n",
+            __func__, addr, size, val);
+    return val;
+}
+
+static void sii3112_reg_write(void *opaque, hwaddr addr,
+                              uint64_t val, unsigned int size)
+{
+    SiI3112PCIState *d = opaque;
+
+    DPRINTF("%s: addr 0x%"PRIx64 " size %d = %"PRIx64 "\n",
+            __func__, addr, size, val);
+    switch (addr) {
+    case 0x00:
+    case 0x10:
+        bmdma_cmd_writeb(&d->i.bmdma[0], val);
+        break;
+    case 0x01:
+    case 0x11:
+        d->regs[0].swdata = val & 0x3f;
+        break;
+    case 0x02:
+    case 0x12:
+        d->i.bmdma[0].status = (val & 0x60) | (d->i.bmdma[0].status & 1) |
+                               (d->i.bmdma[0].status & ~val & 6);
+        break;
+    case 0x04 ... 0x07:
+        bmdma_addr_ioport_ops.write(&d->i.bmdma[0], addr - 4, val, size);
+        break;
+    case 0x08:
+    case 0x18:
+        bmdma_cmd_writeb(&d->i.bmdma[1], val);
+        break;
+    case 0x09:
+    case 0x19:
+        d->regs[1].swdata = val & 0x3f;
+        break;
+    case 0x0a:
+    case 0x1a:
+        d->i.bmdma[1].status = (val & 0x60) | (d->i.bmdma[1].status & 1) |
+                               (d->i.bmdma[1].status & ~val & 6);
+        break;
+    case 0x0c ... 0x0f:
+        bmdma_addr_ioport_ops.write(&d->i.bmdma[1], addr - 12, val, size);
+        break;
+    case 0x80 ... 0x87:
+        if (size == 1) {
+            ide_ioport_write(&d->i.bus[0], addr - 0x80, val);
+        } else if (addr == 0x80) {
+            if (size == 2) {
+                ide_data_writew(&d->i.bus[0], 0, val);
+            } else {
+                ide_data_writel(&d->i.bus[0], 0, val);
+            }
+        }
+        break;
+    case 0x8a:
+        if (size == 1) {
+            ide_cmd_write(&d->i.bus[0], 4, val);
+        }
+        break;
+    case 0xc0 ... 0xc7:
+        if (size == 1) {
+            ide_ioport_write(&d->i.bus[1], addr - 0xc0, val);
+        } else if (addr == 0xc0) {
+            if (size == 2) {
+                ide_data_writew(&d->i.bus[1], 0, val);
+            } else {
+                ide_data_writel(&d->i.bus[1], 0, val);
+            }
+        }
+        break;
+    case 0xca:
+        if (size == 1) {
+            ide_cmd_write(&d->i.bus[1], 4, val);
+        }
+        break;
+    case 0x100:
+        d->regs[0].scontrol = val & 0xfff;
+        if (val & 1) {
+            ide_bus_reset(&d->i.bus[0]);
+        }
+        break;
+    case 0x148:
+        d->regs[0].sien = (val >> 16) & 0x3eed;
+        break;
+    case 0x180:
+        d->regs[1].scontrol = val & 0xfff;
+        if (val & 1) {
+            ide_bus_reset(&d->i.bus[1]);
+        }
+        break;
+    case 0x1c8:
+        d->regs[1].sien = (val >> 16) & 0x3eed;
+        break;
+    default:
+        val = 0;
+    }
+}
+
+static const MemoryRegionOps sii3112_reg_ops = {
+    .read = sii3112_reg_read,
+    .write = sii3112_reg_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+/* the PCI irq level is the logical OR of the two channels */
+static void sii3112_update_irq(SiI3112PCIState *s)
+{
+    int i, set = 0;
+
+    for (i = 0; i < 2; i++) {
+        set |= s->regs[i].confstat & (1UL << 11);
+    }
+    pci_set_irq(PCI_DEVICE(s), (set ? 1 : 0));
+}
+
+static void sii3112_set_irq(void *opaque, int channel, int level)
+{
+    SiI3112PCIState *s = opaque;
+
+    DPRINTF("%s: channel %d level %d\n", __func__, channel, level);
+    if (level) {
+        s->regs[channel].confstat |= (1UL << 11);
+    } else {
+        s->regs[channel].confstat &= ~(1UL << 11);
+    }
+
+    sii3112_update_irq(s);
+}
+
+static void sii3112_reset(void *opaque)
+{
+    SiI3112PCIState *s = opaque;
+    int i;
+
+    for (i = 0; i < 2; i++) {
+        s->regs[i].confstat = 0x6515 << 16;
+        ide_bus_reset(&s->i.bus[i]);
+    }
+}
+
+static void sii3112_pci_realize(PCIDevice *dev, Error **errp)
+{
+    SiI3112PCIState *d = SII3112_PCI(dev);
+    PCIIDEState *s = PCI_IDE(dev);
+    MemoryRegion *mr;
+    qemu_irq *irq;
+    int i;
+
+    pci_config_set_interrupt_pin(dev->config, 1);
+    pci_set_byte(dev->config + PCI_CACHE_LINE_SIZE, 8);
+
+    memory_region_init_io(&d->mmio, OBJECT(d), &sii3112_reg_ops, d,
+                         "sii3112.bar5", 0x200);
+    pci_register_bar(dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
+
+    mr = g_new(MemoryRegion, 1);
+    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar0", &d->mmio, 0x80, 8);
+    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, mr);
+    mr = g_new(MemoryRegion, 1);
+    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar1", &d->mmio, 0x88, 4);
+    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, mr);
+    mr = g_new(MemoryRegion, 1);
+    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar2", &d->mmio, 0xc0, 8);
+    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, mr);
+    mr = g_new(MemoryRegion, 1);
+    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar3", &d->mmio, 0xc8, 4);
+    pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, mr);
+    mr = g_new(MemoryRegion, 1);
+    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar4", &d->mmio, 0, 16);
+    pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, mr);
+
+    irq = qemu_allocate_irqs(sii3112_set_irq, d, 2);
+    for (i = 0; i < 2; i++) {
+        ide_bus_new(&s->bus[i], sizeof(s->bus[i]), DEVICE(dev), i, 1);
+        ide_init2(&s->bus[i], irq[i]);
+
+        bmdma_init(&s->bus[i], &s->bmdma[i], s);
+        s->bmdma[i].bus = &s->bus[i];
+        ide_register_restart_cb(&s->bus[i]);
+    }
+    qemu_register_reset(sii3112_reset, s);
+}
+
+static void sii3112_pci_exitfn(PCIDevice *dev)
+{
+    PCIIDEState *d = PCI_IDE(dev);
+    int i;
+
+    for (i = 0; i < 2; ++i) {
+        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io);
+        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport);
+    }
+}
+
+static void sii3112_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *pd = PCI_DEVICE_CLASS(klass);
+
+    pd->vendor_id = 0x1095;
+    pd->device_id = 0x3112;
+    pd->class_id = PCI_CLASS_STORAGE_RAID;
+    pd->revision = 1;
+    pd->realize = sii3112_pci_realize;
+    pd->exit = sii3112_pci_exitfn;
+    dc->desc = "SiI3112A SATA controller";
+    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
+}
+
+static const TypeInfo sii3112_pci_info = {
+    .name = TYPE_SII3112_PCI,
+    .parent = TYPE_PCI_IDE,
+    .instance_size = sizeof(SiI3112PCIState),
+    .class_init = sii3112_pci_class_init,
+};
+
+static void sii3112_register_types(void)
+{
+    type_register_static(&sii3112_pci_info);
+}
+
+type_init(sii3112_register_types)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [Qemu-devel] [RFC PATCH 12/12] ppc: Add aCube Sam460ex board
  2017-08-13 17:04 [Qemu-devel] [RFC PATCH 00/12] Sam460ex emulation BALATON Zoltan
                   ` (9 preceding siblings ...)
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 01/12] ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs BALATON Zoltan
@ 2017-08-13 17:04 ` BALATON Zoltan
  2017-08-18  6:10   ` David Gibson
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 10/12] ppc: Add 460EX embedded CPU BALATON Zoltan
  11 siblings, 1 reply; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-13 17:04 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC.
This is not a full implementation yet with a lot of components still
missing but enough to start a Linux kernel and the U-Boot firmware.

Signed-off-by: François Revol <revol@free.fr>
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 default-configs/ppcemb-softmmu.mak |    3 +
 hw/ppc/Makefile.objs               |    2 +
 hw/ppc/sam460ex.c                  | 1895 ++++++++++++++++++++++++++++++++++++
 include/hw/pci/pcie_host.h         |    2 +-
 4 files changed, 1901 insertions(+), 1 deletion(-)
 create mode 100644 hw/ppc/sam460ex.c

diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
index 94340de..9a0a177 100644
--- a/default-configs/ppcemb-softmmu.mak
+++ b/default-configs/ppcemb-softmmu.mak
@@ -16,3 +16,6 @@ CONFIG_XILINX=y
 CONFIG_XILINX_ETHLITE=y
 CONFIG_LIBDECNUMBER=y
 CONFIG_SM501=y
+CONFIG_USB_EHCI_SYSBUS=y
+CONFIG_IDE_SII3112=y
+CONFIG_SAM460EX=y
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 9c5d58a..a242a59 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -27,3 +27,5 @@ obj-$(CONFIG_E500) += e500.o mpc8544ds.o e500plat.o
 obj-$(CONFIG_E500) += mpc8544_guts.o ppce500_spin.o
 # PowerPC 440 Xilinx ML507 reference board.
 obj-$(CONFIG_XILINX) += virtex_ml507.o
+# ACube Sam460ex board.
+obj-$(CONFIG_SAM460EX) += sam460ex.o
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
new file mode 100644
index 0000000..c61eb99
--- /dev/null
+++ b/hw/ppc/sam460ex.c
@@ -0,0 +1,1895 @@
+/*
+ * QEMU aCube Sam460ex board emulation
+ *
+ * Copyright (c) 2012 François Revol
+ * Copyright (c) 2016-2017 BALATON Zoltan
+ *
+ * This file is derived from hw/ppc440_bamboo.c,
+ * the copyright for that material belongs to the original owners.
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/cutils.h"
+#include "qapi/error.h"
+#include "hw/hw.h"
+#include "sysemu/blockdev.h"
+#include "hw/boards.h"
+#include "sysemu/kvm.h"
+#include "kvm_ppc.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/block-backend.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "exec/address-spaces.h"
+#include "exec/memory.h"
+#include "hw/ppc/ppc.h"
+#include "hw/ppc/ppc405.h"
+#include "hw/block/flash.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "hw/char/serial.h"
+#include "hw/i2c/ppc4xx_i2c.h"
+#include "hw/i2c/smbus.h"
+#include "hw/usb/hcd-ehci.h"
+
+#undef DEBUG_SDRAM
+#undef DEBUG_L2SRAM
+#undef DEBUG_CPR
+#undef DEBUG_SDR
+#undef DEBUG_AHB
+#undef DEBUG_PCIE
+
+#define BINARY_DEVICE_TREE_FILE "sam460ex.dtb"
+#define UBOOT_FILENAME "u-boot-sam460-20100605.bin"
+/* to extract the official U-Boot bin from the updater: */
+/* dd bs=1 skip=$(($(stat -c '%s' updater/updater-460) - 0x80000)) \
+     if=updater/updater-460 of=u-boot-sam460-20100605.bin */
+
+/* from Sam460 U-Boot include/configs/Sam460ex.h */
+#define FLASH_BASE             0xfff00000
+#define FLASH_BASE_H           0x4
+#define FLASH_SIZE             (1 << 20)
+#define UBOOT_LOAD_BASE        0xfff80000
+#define UBOOT_SIZE             0x00080000
+#define UBOOT_ENTRY            0xfffffffc
+
+/* from U-Boot */
+#define EPAPR_MAGIC           (0x45504150)
+#define KERNEL_ADDR           0x1000000
+#define FDT_ADDR              0x1800000
+#define RAMDISK_ADDR          0x1900000
+
+/* Sam460ex IRQ MAP:
+   IRQ0  = ETH_INT
+   IRQ1  = FPGA_INT
+   IRQ2  = PCI_INT (PCIA, PCIB, PCIC, PCIB)
+   IRQ3  = FPGA_INT2
+   IRQ11 = RTC_INT
+   IRQ12 = SM502_INT
+*/
+
+#define SDRAM_NR_BANKS 4
+
+/* FIXME: See u-boot.git 8ac41e */
+static const unsigned int ppc460ex_sdram_bank_sizes[] = {
+    1024 << 20, 512 << 20, 256 << 20, 128 << 20, 64 << 20, 32 << 20, 0
+};
+
+struct boot_info {
+    uint32_t dt_base;
+    uint32_t dt_size;
+    uint32_t entry;
+};
+
+/*****************************************************************************/
+/* L2 Cache as SRAM */
+/* FIXME:fix names */
+enum {
+    DCR_L2CACHE_BASE  = 0x030,
+    DCR_L2CACHE_CFG   = DCR_L2CACHE_BASE,
+    DCR_L2CACHE_CMD,
+    DCR_L2CACHE_ADDR,
+    DCR_L2CACHE_DATA,
+    DCR_L2CACHE_STAT,
+    DCR_L2CACHE_CVER,
+    DCR_L2CACHE_SNP0,
+    DCR_L2CACHE_SNP1,
+    DCR_L2CACHE_END   = DCR_L2CACHE_SNP1,
+};
+
+/* base is 460ex-specific, cf. U-Boot, ppc4xx-isram.h */
+enum {
+    DCR_ISRAM0_BASE   = 0x020,
+    DCR_ISRAM0_SB0CR  = DCR_ISRAM0_BASE,
+    DCR_ISRAM0_SB1CR,
+    DCR_ISRAM0_SB2CR,
+    DCR_ISRAM0_SB3CR,
+    DCR_ISRAM0_BEAR,
+    DCR_ISRAM0_BESR0,
+    DCR_ISRAM0_BESR1,
+    DCR_ISRAM0_PMEG,
+    DCR_ISRAM0_CID,
+    DCR_ISRAM0_REVID,
+    DCR_ISRAM0_DPC,
+    DCR_ISRAM0_END    = DCR_ISRAM0_DPC
+};
+
+enum {
+    DCR_ISRAM1_BASE   = 0x0b0,
+    DCR_ISRAM1_SB0CR  = DCR_ISRAM1_BASE,
+    /* single bank */
+    DCR_ISRAM1_BEAR   = DCR_ISRAM1_BASE + 0x04,
+    DCR_ISRAM1_BESR0,
+    DCR_ISRAM1_BESR1,
+    DCR_ISRAM1_PMEG,
+    DCR_ISRAM1_CID,
+    DCR_ISRAM1_REVID,
+    DCR_ISRAM1_DPC,
+    DCR_ISRAM1_END    = DCR_ISRAM1_DPC
+};
+
+typedef struct ppc4xx_l2sram_t {
+    MemoryRegion bank[4];
+    uint32_t l2cache[8];
+    uint32_t isram0[11];
+} ppc4xx_l2sram_t;
+
+#ifdef MAP_L2SRAM
+static void l2sram_update_mappings(ppc4xx_l2sram_t *l2sram,
+                                   uint32_t isarc, uint32_t isacntl,
+                                   uint32_t dsarc, uint32_t dsacntl)
+{
+#ifdef DEBUG_L2SRAM
+    printf("L2SRAM update ISA %08" PRIx32 " %08" PRIx32 " (%08" PRIx32
+           " %08" PRIx32 ") DSA %08" PRIx32 " %08" PRIx32
+           " (%08" PRIx32 " %08" PRIx32 ")\n",
+           isarc, isacntl, dsarc, dsacntl,
+           l2sram->isarc, l2sram->isacntl, l2sram->dsarc, l2sram->dsacntl);
+#endif
+    if (l2sram->isarc != isarc ||
+        (l2sram->isacntl & 0x80000000) != (isacntl & 0x80000000)) {
+        if (l2sram->isacntl & 0x80000000) {
+            /* Unmap previously assigned memory region */
+            printf("L2SRAM unmap ISA %08" PRIx32 "\n", l2sram->isarc);
+            memory_region_del_subregion(get_system_memory(),
+                                        &l2sram->isarc_ram);
+        }
+        if (isacntl & 0x80000000) {
+            /* Map new instruction memory region */
+#ifdef DEBUG_L2SRAM
+            printf("L2SRAM map ISA %08" PRIx32 "\n", isarc);
+#endif
+            memory_region_add_subregion(get_system_memory(), isarc,
+                                        &l2sram->isarc_ram);
+        }
+    }
+    if (l2sram->dsarc != dsarc ||
+        (l2sram->dsacntl & 0x80000000) != (dsacntl & 0x80000000)) {
+        if (l2sram->dsacntl & 0x80000000) {
+            /* Beware not to unmap the region we just mapped */
+            if (!(isacntl & 0x80000000) || l2sram->dsarc != isarc) {
+                /* Unmap previously assigned memory region */
+#ifdef DEBUG_L2SRAM
+                printf("L2SRAM unmap DSA %08" PRIx32 "\n", l2sram->dsarc);
+#endif
+                memory_region_del_subregion(get_system_memory(),
+                                            &l2sram->dsarc_ram);
+            }
+        }
+        if (dsacntl & 0x80000000) {
+            /* Beware not to remap the region we just mapped */
+            if (!(isacntl & 0x80000000) || dsarc != isarc) {
+                /* Map new data memory region */
+#ifdef DEBUG_L2SRAM
+                printf("L2SRAM map DSA %08" PRIx32 "\n", dsarc);
+#endif
+                memory_region_add_subregion(get_system_memory(), dsarc,
+                                            &l2sram->dsarc_ram);
+            }
+        }
+    }
+}
+#endif
+
+static uint32_t dcr_read_l2sram(void *opaque, int dcrn)
+{
+    ppc4xx_l2sram_t *l2sram;
+    uint32_t ret;
+
+    l2sram = opaque;
+    switch (dcrn) {
+    case DCR_L2CACHE_CFG:
+    case DCR_L2CACHE_CMD:
+    case DCR_L2CACHE_ADDR:
+    case DCR_L2CACHE_DATA:
+    case DCR_L2CACHE_STAT:
+    case DCR_L2CACHE_CVER:
+    case DCR_L2CACHE_SNP0:
+    case DCR_L2CACHE_SNP1:
+        ret = l2sram->l2cache[dcrn - DCR_L2CACHE_BASE];
+#ifdef DEBUG_L2SRAM
+        printf("L2SRAM: read DCR[%x(L2CACHE+%x)]: %08" PRIx32 "\n",
+               dcrn, dcrn - DCR_L2CACHE_BASE, ret);
+#endif
+        break;
+
+    case DCR_ISRAM0_SB0CR:
+    case DCR_ISRAM0_SB1CR:
+    case DCR_ISRAM0_SB2CR:
+    case DCR_ISRAM0_SB3CR:
+    case DCR_ISRAM0_BEAR:
+    case DCR_ISRAM0_BESR0:
+    case DCR_ISRAM0_BESR1:
+    case DCR_ISRAM0_PMEG:
+    case DCR_ISRAM0_CID:
+    case DCR_ISRAM0_REVID:
+    case DCR_ISRAM0_DPC:
+        ret = l2sram->isram0[dcrn - DCR_ISRAM0_BASE];
+#ifdef DEBUG_L2SRAM
+        printf("L2SRAM: read DCR[%x(ISRAM0+%x)]: %08" PRIx32 "\n",
+               dcrn, dcrn - DCR_ISRAM0_BASE, ret);
+#endif
+        break;
+
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_l2sram(void *opaque, int dcrn, uint32_t val)
+{
+    /*ppc4xx_l2sram_t *l2sram = opaque;*/
+    /* TODO */
+
+    switch (dcrn) {
+    case DCR_L2CACHE_CFG:
+    case DCR_L2CACHE_CMD:
+    case DCR_L2CACHE_ADDR:
+    case DCR_L2CACHE_DATA:
+    case DCR_L2CACHE_STAT:
+    case DCR_L2CACHE_CVER:
+    case DCR_L2CACHE_SNP0:
+    case DCR_L2CACHE_SNP1:
+        /*l2sram->l2cache[dcrn - DCR_L2CACHE_BASE] = val;*/
+#ifdef DEBUG_L2SRAM
+        printf("L2SRAM: write DCR[%x(L2CACHE+%x)]: %08" PRIx32 "\n",
+               dcrn, dcrn - DCR_L2CACHE_BASE, val);
+#endif
+        break;
+
+    case DCR_ISRAM0_SB0CR:
+    case DCR_ISRAM0_SB1CR:
+    case DCR_ISRAM0_SB2CR:
+    case DCR_ISRAM0_SB3CR:
+    case DCR_ISRAM0_BEAR:
+    case DCR_ISRAM0_BESR0:
+    case DCR_ISRAM0_BESR1:
+    case DCR_ISRAM0_PMEG:
+    case DCR_ISRAM0_CID:
+    case DCR_ISRAM0_REVID:
+    case DCR_ISRAM0_DPC:
+        /*l2sram->isram0[dcrn - DCR_L2CACHE_BASE] = val;*/
+#ifdef DEBUG_L2SRAM
+        printf("L2SRAM: write DCR[%x(ISRAM0+%x)]: %08" PRIx32 "\n",
+               dcrn, dcrn - DCR_ISRAM0_BASE, val);
+#endif
+        break;
+
+    case DCR_ISRAM1_SB0CR:
+    case DCR_ISRAM1_BEAR:
+    case DCR_ISRAM1_BESR0:
+    case DCR_ISRAM1_BESR1:
+    case DCR_ISRAM1_PMEG:
+    case DCR_ISRAM1_CID:
+    case DCR_ISRAM1_REVID:
+    case DCR_ISRAM1_DPC:
+        /*l2sram->isram1[dcrn - DCR_L2CACHE_BASE] = val;*/
+#ifdef DEBUG_L2SRAM
+        printf("L2SRAM: write DCR[%x(ISRAM1+%x)]: %08" PRIx32 "\n",
+               dcrn, dcrn - DCR_ISRAM1_BASE, val);
+#endif
+        break;
+    }
+    /*l2sram_update_mappings(l2sram, isarc, isacntl, dsarc, dsacntl);*/
+}
+
+static void l2sram_reset(void *opaque)
+{
+    ppc4xx_l2sram_t *l2sram;
+    /*uint32_t isarc, dsarc, isacntl, dsacntl;*/
+
+    l2sram = opaque;
+    memset(l2sram->l2cache, 0, sizeof(l2sram->l2cache));
+    l2sram->l2cache[DCR_L2CACHE_STAT - DCR_L2CACHE_BASE] = 0x80000000;
+    memset(l2sram->isram0, 0, sizeof(l2sram->isram0));
+    /*l2sram_update_mappings(l2sram, isarc, isacntl, dsarc, dsacntl);*/
+}
+
+static void ppc4xx_l2sram_init(CPUPPCState *env)
+{
+    ppc4xx_l2sram_t *l2sram;
+
+    l2sram = g_malloc0(sizeof(ppc4xx_l2sram_t));
+    /* XXX: Size is 4*64kB for 460ex, cf. U-Boot, ppc4xx-isram.h */
+    memory_region_init_ram(&l2sram->bank[0], NULL, "ppc4xx.l2sram_bank0",
+                           64 * 1024, &error_abort);
+    memory_region_init_ram(&l2sram->bank[1], NULL, "ppc4xx.l2sram_bank1",
+                           64 * 1024, &error_abort);
+    memory_region_init_ram(&l2sram->bank[2], NULL, "ppc4xx.l2sram_bank2",
+                           64 * 1024, &error_abort);
+    memory_region_init_ram(&l2sram->bank[3], NULL, "ppc4xx.l2sram_bank3",
+                           64 * 1024, &error_abort);
+    qemu_register_reset(&l2sram_reset, l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_CFG,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_CMD,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_ADDR,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_DATA,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_STAT,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_CVER,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_SNP0,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_SNP1,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+
+    ppc_dcr_register(env, DCR_ISRAM0_SB0CR,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_ISRAM0_SB1CR,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_ISRAM0_SB2CR,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_ISRAM0_SB3CR,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_ISRAM0_PMEG,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_ISRAM0_DPC,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+
+    ppc_dcr_register(env, DCR_ISRAM1_SB0CR,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_ISRAM1_PMEG,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_ISRAM1_DPC,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+}
+
+/*****************************************************************************/
+/* Clocking Power on Reset */
+enum {
+    CPR0_CFGADDR = 0x00C,
+    CPR0_CFGDATA = 0x00D,
+};
+
+typedef struct ppc4xx_cpr_t {
+    uint32_t addr;
+} ppc4xx_cpr_t;
+
+static uint32_t dcr_read_cpr(void *opaque, int dcrn)
+{
+    ppc4xx_cpr_t *cpr = opaque;
+    uint32_t ret;
+
+    switch (dcrn) {
+    case CPR0_CFGADDR:
+        ret = cpr->addr;
+#ifdef DEBUG_CPR
+        printf("read DCR[%x(CPR0ADDR)]: %08" PRIx32 "\n", dcrn, ret);
+#endif
+        break;
+    case CPR0_CFGDATA:
+        ret = 0;
+#ifdef DEBUG_CPR
+        printf("read DCR[%x(CPR0DATA)]: %08" PRIx32 "\n", dcrn, ret);
+#endif
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_cpr(void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_cpr_t *cpr = opaque;
+
+    switch (dcrn) {
+    case CPR0_CFGADDR:
+        cpr->addr = val;
+#ifdef DEBUG_CPR
+        printf("write DCR[%x(CPRADDR)]: %08" PRIx32 "\n", dcrn, val);
+#endif
+        break;
+    case CPR0_CFGDATA:
+#ifdef DEBUG_CPR
+        printf("write DCR[%x(CPRDATA)]: %08" PRIx32 "\n", dcrn, val);
+#endif
+        break;
+    default:
+#ifdef DEBUG_CPR
+        printf("write DCR[%x]: %08" PRIx32 "\n", dcrn, val);
+#endif
+        break;
+    }
+}
+
+static void ppc4xx_cpr_reset(void *opaque)
+{
+    ppc4xx_cpr_t *cpr = opaque;
+
+    cpr->addr = 0;
+}
+
+static void ppc4xx_cpr_init(CPUPPCState *env)
+{
+    ppc4xx_cpr_t *cpr;
+
+    cpr = g_malloc0(sizeof(*cpr));
+    ppc_dcr_register(env, CPR0_CFGADDR, cpr, &dcr_read_cpr, &dcr_write_cpr);
+    ppc_dcr_register(env, CPR0_CFGDATA, cpr, &dcr_read_cpr, &dcr_write_cpr);
+    qemu_register_reset(ppc4xx_cpr_reset, cpr);
+}
+
+/*****************************************************************************/
+/* System DCRs */
+typedef struct ppc4xx_sdr_t ppc4xx_sdr_t;
+struct ppc4xx_sdr_t {
+    uint32_t addr;
+};
+
+enum {
+    SDR0_CFGADDR = 0x00e,
+    SDR0_CFGDATA,
+    SDR0_STRP0 = 0x020,
+    SDR0_STRP1,
+    SDR0_ECID3 = 0x083,
+    SDR0_DDR0 = 0x0e1,
+    SDR0_USB0 = 0x320,
+};
+
+enum {
+    PESDR0_LOOP = 0x303,
+    PESDR0_RCSSET,
+    PESDR0_RCSSTS,
+    PESDR0_RSTSTA = 0x310,
+    PESDR1_LOOP = 0x343,
+    PESDR1_RCSSET,
+    PESDR1_RCSSTS,
+    PESDR1_RSTSTA = 0x365,
+};
+
+#define SDR0_DDR0_DDRM_ENCODE(n)  ((((unsigned long)(n)) & 0x03) << 29)
+#define SDR0_DDR0_DDRM_DDR1       0x20000000
+#define SDR0_DDR0_DDRM_DDR2       0x40000000
+
+static uint32_t dcr_read_sdr(void *opaque, int dcrn)
+{
+    ppc4xx_sdr_t *sdr;
+    uint32_t ret;
+
+    sdr = opaque;
+    switch (dcrn) {
+    case SDR0_CFGADDR:
+        ret = sdr->addr;
+        break;
+    case SDR0_CFGDATA:
+        switch (sdr->addr) {
+        case SDR0_STRP0:
+            /* FIXME: Is this correct? This breaks timing */
+            ret = 0 /*5 << 8 | 15 << 4*/;
+            break;
+        case SDR0_STRP1:
+            ret = 5 << 29 | 2 << 26 | 1 << 24;
+            break;
+        case SDR0_ECID3:
+            ret = 1 << 20; /* No Security/Kasumi support */
+            break;
+        case SDR0_DDR0:
+            ret = SDR0_DDR0_DDRM_ENCODE(1) | SDR0_DDR0_DDRM_DDR1;
+            break;
+        case PESDR0_RCSSET:
+        case PESDR1_RCSSET:
+            ret = (1 << 24) | (1 << 16);
+            break;
+        case PESDR0_RCSSTS:
+        case PESDR1_RCSSTS:
+            ret = (1 << 16) | (1 << 12);
+            break;
+        case PESDR0_RSTSTA:
+        case PESDR1_RSTSTA:
+            ret = 1;
+            break;
+        case PESDR0_LOOP:
+        case PESDR1_LOOP:
+            ret = 1 << 12;
+            break;
+        default:
+            ret = 0;
+            break;
+        }
+#ifdef DEBUG_SDR
+        if (sdr->addr != 0x20 && sdr->addr != 0x21) {
+            printf("read DCR[%x(SDRDATA[%x])]: %08" PRIx32 "\n",
+                   dcrn, sdr->addr, ret);
+        }
+#endif
+        break;
+    default:
+        ret = 0;
+#ifdef DEBUG_SDR
+        printf("read DCR[%x]: %08" PRIx32 "\n", dcrn, ret);
+#endif
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_sdr(void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_sdr_t *sdr;
+
+    sdr = opaque;
+    switch (dcrn) {
+    case SDR0_CFGADDR:
+        sdr->addr = val;
+        break;
+    case SDR0_CFGDATA:
+#ifdef DEBUG_SDR
+        printf("write DCR[%x(SDRDATA[%x])]: %08" PRIx32 "\n",
+               dcrn, sdr->addr, val);
+#endif
+        switch (sdr->addr) {
+        case 0x00: /* B0CR */
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+#ifdef DEBUG_SDR
+        printf("write DCR[%x]: %08" PRIx32 "\n", dcrn, val);
+#endif
+        break;
+    }
+}
+
+static void sdr_reset(void *opaque)
+{
+    ppc4xx_sdr_t *sdr;
+
+    sdr = opaque;
+    sdr->addr = 0;
+}
+
+static void ppc4xx_sdr_init(CPUPPCState *env)
+{
+    ppc4xx_sdr_t *sdr;
+
+    sdr = g_malloc0(sizeof(ppc4xx_sdr_t));
+    qemu_register_reset(&sdr_reset, sdr);
+    ppc_dcr_register(env, SDR0_CFGADDR,
+                     sdr, &dcr_read_sdr, &dcr_write_sdr);
+    ppc_dcr_register(env, SDR0_CFGDATA,
+                     sdr, &dcr_read_sdr, &dcr_write_sdr);
+    ppc_dcr_register(env, SDR0_USB0,
+                     sdr, &dcr_read_sdr, &dcr_write_sdr);
+}
+
+/*****************************************************************************/
+/* SDRAM controller */
+typedef struct ppc4xx_sdram_t {
+    uint32_t addr;
+    int nbanks;
+    MemoryRegion containers[4]; /* used for clipping */
+    MemoryRegion *ram_memories;
+    hwaddr ram_bases[4];
+    hwaddr ram_sizes[4];
+    uint32_t bcr[4];
+} ppc4xx_sdram_t;
+
+enum {
+    SDRAM_R0BAS = 0x040,
+    SDRAM_R1BAS,
+    SDRAM_R2BAS,
+    SDRAM_R3BAS,
+    SDRAM_CONF1HB = 0x045,
+    SDRAM_PLBADDULL = 0x04a,
+    SDRAM_CONF1LL = 0x04b,
+    SDRAM_CONFPATHB = 0x04f,
+    SDRAM_PLBADDUHB = 0x050,
+    SDRAM0_CFGADDR = 0x010,
+    SDRAM0_CFGDATA,
+};
+
+/* XXX: TOFIX: some patches have made this code become inconsistent:
+ *      there are type inconsistencies, mixing hwaddr, target_ulong
+ *      and uint32_t
+ */
+static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
+{
+    uint32_t bcr;
+
+    switch (ram_size) {
+    case (8 * M_BYTE):
+        bcr = 0xffc0;
+        break;
+    case (16 * M_BYTE):
+        bcr = 0xff80;
+        break;
+    case (32 * M_BYTE):
+        bcr = 0xff00;
+        break;
+    case (64 * M_BYTE):
+        bcr = 0xfe00;
+        break;
+    case (128 * M_BYTE):
+        bcr = 0xfc00;
+        break;
+    case (256 * M_BYTE):
+        bcr = 0xf800;
+        break;
+    case (512 * M_BYTE):
+        bcr = 0xf000;
+        break;
+    case (1 * G_BYTE):
+        bcr = 0xe000;
+        break;
+/*
+    case (2 * G_BYTE):
+        bcr = 0xc000;
+        break;
+    case (4 * G_BYTE):
+        bcr = 0x8000;
+        break;
+*/
+    default:
+        printf("%s: invalid RAM size " TARGET_FMT_plx "\n", __func__,
+               ram_size);
+        return 0;
+    }
+    bcr |= ram_base & 0xFF800000;
+    bcr |= 1;
+
+    return bcr;
+}
+
+static inline hwaddr sdram_base(uint32_t bcr)
+{
+    return bcr & 0xFF800000;
+}
+
+static target_ulong sdram_size(uint32_t bcr)
+{
+    target_ulong size;
+    int sh;
+
+    sh = 1024 - ((bcr >> 6) & 0x3ff);
+    if (sh == 0) {
+        size = -1;
+    } else {
+        size = 8 * M_BYTE * sh;
+    }
+
+    return size;
+}
+
+static void sdram_set_bcr(ppc4xx_sdram_t *sdram,
+                          uint32_t *bcrp, uint32_t bcr, int enabled)
+{
+    unsigned n = bcrp - sdram->bcr;
+
+    if (*bcrp & 1) {
+        /* Unmap RAM */
+#ifdef DEBUG_SDRAM
+        printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
+               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
+#endif
+        memory_region_del_subregion(get_system_memory(),
+                                    &sdram->containers[n]);
+        memory_region_del_subregion(&sdram->containers[n],
+                                    &sdram->ram_memories[n]);
+        object_unparent(OBJECT(&sdram->containers[n]));
+    }
+    *bcrp = bcr & 0xFFDEE001;
+    if (enabled && (bcr & 1)) {
+#ifdef DEBUG_SDRAM
+        printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
+               __func__, sdram_base(bcr), sdram_size(bcr));
+#endif
+        memory_region_init(&sdram->containers[n], NULL, "sdram-containers",
+                           sdram_size(bcr));
+        memory_region_add_subregion(&sdram->containers[n], 0,
+                                    &sdram->ram_memories[n]);
+        memory_region_add_subregion(get_system_memory(),
+                                    sdram_base(bcr),
+                                    &sdram->containers[n]);
+    }
+}
+
+static void sdram_map_bcr(ppc4xx_sdram_t *sdram)
+{
+    int i;
+
+    for (i = 0; i < sdram->nbanks; i++) {
+        if (sdram->ram_sizes[i] != 0) {
+            sdram_set_bcr(sdram,
+                          &sdram->bcr[i],
+                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
+                          1);
+        } else {
+            sdram_set_bcr(sdram, &sdram->bcr[i], 0, 0);
+        }
+    }
+}
+
+static uint32_t dcr_read_sdram(void *opaque, int dcrn)
+{
+    ppc4xx_sdram_t *sdram;
+    uint32_t ret;
+
+    sdram = opaque;
+#ifdef DEBUG_SDR
+        printf("read DCR[%x(SDRAM)]\n", dcrn);
+#endif
+    switch (dcrn) {
+    case SDRAM_R0BAS:
+    case SDRAM_R1BAS:
+    case SDRAM_R2BAS:
+    case SDRAM_R3BAS:
+        ret = sdram_bcr(sdram->ram_bases[dcrn - SDRAM_R0BAS],
+                        sdram->ram_sizes[dcrn - SDRAM_R0BAS]);
+        break;
+    case SDRAM_CONF1HB:
+    case SDRAM_CONF1LL:
+    case SDRAM_CONFPATHB:
+    case SDRAM_PLBADDULL:
+    case SDRAM_PLBADDUHB:
+        ret = 0;
+        break;
+    case SDRAM0_CFGADDR:
+        ret = sdram->addr;
+#ifdef DEBUG_SDR
+        printf("read DCR[%x(SDRAMADDR)]: %08" PRIx32 "\n", dcrn, ret);
+#endif
+        break;
+    case SDRAM0_CFGDATA:
+        switch (sdram->addr) {
+        case 0x0014: /* SDRAM_MCSTAT (405EX) */
+        case 0x001F:
+            ret = 0x80000000;
+            break;
+        case 0x0021: /* SDRAM_MCOPT2 */
+            ret = 0x08000000;
+            break;
+        case 0x0040: /* SDRAM_MB0CF */
+            ret = 0x00008001;
+            break;
+        case 0x007A: /* SDRAM_DLCR */
+            ret = 0x02000000;
+            break;
+        case 0x00E1: /* SDR0_DDR0 */
+            ret = SDR0_DDR0_DDRM_ENCODE(1) | SDR0_DDR0_DDRM_DDR1;
+            break;
+        default:
+            ret = 0;
+            break;
+        }
+#ifdef DEBUG_SDR
+        printf("read DCR[%x(SDRAMDATA)]: %08" PRIx32 "\n", dcrn, ret);
+#endif
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+#ifdef DEBUG_SDR
+        printf("write DCR[%x(SDRAM)]: %08" PRIx32 "\n", dcrn, val);
+#endif
+    switch (dcrn) {
+    case SDRAM_R0BAS:
+    case SDRAM_R1BAS:
+    case SDRAM_R2BAS:
+    case SDRAM_R3BAS:
+    case SDRAM_CONF1HB:
+    case SDRAM_CONF1LL:
+    case SDRAM_CONFPATHB:
+    case SDRAM_PLBADDULL:
+    case SDRAM_PLBADDUHB:
+        break;
+    case SDRAM0_CFGADDR:
+        sdram->addr = val;
+#ifdef DEBUG_SDR
+        printf("write DCR[%x(SDRAMADDR)]: %08" PRIx32 "\n", dcrn, val);
+#endif
+        break;
+    case SDRAM0_CFGDATA:
+#ifdef DEBUG_SDR
+        printf("write DCR[%x(SDRAMDATA)]: %08" PRIx32 "\n", dcrn, val);
+#endif
+        switch (sdram->addr) {
+        case 0x00: /* B0CR */
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+static void sdram_reset(void *opaque)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+    sdram->addr = 0;
+}
+
+static void ppc440_sdram_init(CPUPPCState *env, int nbanks,
+                              MemoryRegion *ram_memories,
+                              hwaddr *ram_bases,
+                              hwaddr *ram_sizes,
+                              int do_init)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = g_malloc0(sizeof(ppc4xx_sdram_t));
+    sdram->nbanks = nbanks;
+    sdram->ram_memories = ram_memories;
+    memcpy(sdram->ram_bases, ram_bases, nbanks * sizeof(hwaddr));
+    memcpy(sdram->ram_sizes, ram_sizes, nbanks * sizeof(hwaddr));
+    qemu_register_reset(&sdram_reset, sdram);
+    ppc_dcr_register(env, SDRAM0_CFGADDR,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM0_CFGDATA,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    if (do_init) {
+        sdram_map_bcr(sdram);
+    }
+
+    ppc_dcr_register(env, SDRAM_R0BAS,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_R1BAS,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_R2BAS,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_R3BAS,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_CONF1HB,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_PLBADDULL,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_CONF1LL,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_CONFPATHB,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_PLBADDUHB,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+}
+
+/*****************************************************************************/
+/* PLB to AHB bridge */
+enum {
+    AHB_TOP    = 0x0A4,
+    AHB_BOT    = 0x0A5,
+};
+
+typedef struct ppc4xx_ahb_t {
+    uint32_t top;
+    uint32_t bot;
+} ppc4xx_ahb_t;
+
+static uint32_t dcr_read_ahb(void *opaque, int dcrn)
+{
+    ppc4xx_ahb_t *ahb;
+    uint32_t ret;
+
+    ahb = opaque;
+    switch (dcrn) {
+    case AHB_TOP:
+        ret = ahb->top;
+        break;
+    case AHB_BOT:
+        ret = ahb->bot;
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+#ifdef DEBUG_AHB
+    printf("read DCR[%x(AHB+%x)]: %08" PRIx32 "\n", dcrn, dcrn - 0xA0, ret);
+#endif
+
+    return ret;
+}
+
+static void dcr_write_ahb(void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_ahb_t *ahb;
+
+    ahb = opaque;
+#ifdef DEBUG_AHB
+    printf("write DCR[%x(AHB+%x)]: %08" PRIx32 "\n", dcrn, dcrn - 0xA0, val);
+#endif
+    switch (dcrn) {
+    case AHB_TOP:
+        ahb->top = val;
+        break;
+    case AHB_BOT:
+        ahb->bot = val;
+        break;
+    }
+}
+
+static void ppc4xx_ahb_reset(void *opaque)
+{
+    ppc4xx_ahb_t *ahb;
+
+    ahb = opaque;
+    /* No error */
+    ahb->top = 0;
+    ahb->bot = 0;
+}
+
+static void ppc4xx_ahb_init(CPUPPCState *env)
+{
+    ppc4xx_ahb_t *ahb;
+
+    ahb = g_malloc0(sizeof(ppc4xx_ahb_t));
+    ppc_dcr_register(env, AHB_TOP, ahb, &dcr_read_ahb, &dcr_write_ahb);
+    ppc_dcr_register(env, AHB_BOT, ahb, &dcr_read_ahb, &dcr_write_ahb);
+    qemu_register_reset(ppc4xx_ahb_reset, ahb);
+}
+
+/*****************************************************************************/
+/* PCI Express controller */
+/* This is not complete and not meant to work, only implemented partially
+ * to allow firmware and guests to find an empty bus. Cards should use PCI.
+ */
+#include "hw/pci/pcie_host.h"
+
+#define TYPE_PPC460EX_PCIE_HOST "ppc460ex-pcie-host"
+#define PPC460EX_PCIE_HOST(obj) \
+    OBJECT_CHECK(PPC460EXPCIEState, (obj), TYPE_PPC460EX_PCIE_HOST)
+
+typedef struct PPC460EXPCIEState {
+    PCIExpressHost host;
+
+    MemoryRegion iomem;
+    qemu_irq irq[4];
+    int32_t dcrn_base;
+
+    uint64_t cfg_base;
+    uint32_t cfg_mask;
+    uint64_t msg_base;
+    uint32_t msg_mask;
+    uint64_t omr1_base;
+    uint64_t omr1_mask;
+    uint64_t omr2_base;
+    uint64_t omr2_mask;
+    uint64_t omr3_base;
+    uint64_t omr3_mask;
+    uint64_t reg_base;
+    uint32_t reg_mask;
+    uint32_t special;
+    uint32_t cfg;
+} PPC460EXPCIEState;
+
+#define DCRN_PCIE0_BASE 0x100
+#define DCRN_PCIE1_BASE 0x120
+
+enum {
+    PEGPL_CFGBAH = 0x0,
+    PEGPL_CFGBAL,
+    PEGPL_CFGMSK,
+    PEGPL_MSGBAH,
+    PEGPL_MSGBAL,
+    PEGPL_MSGMSK,
+    PEGPL_OMR1BAH,
+    PEGPL_OMR1BAL,
+    PEGPL_OMR1MSKH,
+    PEGPL_OMR1MSKL,
+    PEGPL_OMR2BAH,
+    PEGPL_OMR2BAL,
+    PEGPL_OMR2MSKH,
+    PEGPL_OMR2MSKL,
+    PEGPL_OMR3BAH,
+    PEGPL_OMR3BAL,
+    PEGPL_OMR3MSKH,
+    PEGPL_OMR3MSKL,
+    PEGPL_REGBAH,
+    PEGPL_REGBAL,
+    PEGPL_REGMSK,
+    PEGPL_SPECIAL,
+    PEGPL_CFG,
+};
+
+#ifdef DEBUG_PCIE
+static void dump_pcie_regs(PPC460EXPCIEState *state)
+{
+    printf("dcrn_base=%x\n", state->dcrn_base);
+    printf("cfg  base=%lx, mask=%x, size=%x\n", state->cfg_base,
+           state->cfg_mask, ~(state->cfg_mask & 0xfffffffe) + 1);
+    printf("msg  base=%lx, mask=%x, size=%x\n", state->msg_base,
+           state->msg_mask, ~(state->msg_mask & 0xfffffffe) + 1);
+    printf("omr1 base=%lx, mask=%lx, size=%"PRIu64"\n", state->omr1_base,
+           state->omr1_mask, ~state->omr1_mask + 1);
+    printf("omr2 base=%lx, mask=%lx, size=%"PRIu64"\n", state->omr2_base,
+           state->omr2_mask, ~state->omr2_mask + 1);
+    printf("omr3 base=%lx, mask=%lx, size=%"PRIu64"\n", state->omr3_base,
+           state->omr3_mask, ~state->omr3_mask + 1);
+    printf("reg  base=%lx, mask=%x, size=%x\n", state->reg_base,
+           state->reg_mask, ~(state->reg_mask & 0xfffffffe) + 1);
+    printf("special=%x, cfg=%x\n", state->special, state->cfg);
+}
+#endif
+
+static uint32_t dcr_read_pcie(void *opaque, int dcrn)
+{
+    uint32_t ret = 0;
+    PPC460EXPCIEState *state = opaque;
+
+    switch (dcrn - state->dcrn_base) {
+    case PEGPL_CFGBAH:
+        ret = state->cfg_base >> 32;
+        break;
+    case PEGPL_CFGBAL:
+        ret = state->cfg_base;
+        break;
+    case PEGPL_CFGMSK:
+        ret = state->cfg_mask;
+        break;
+    case PEGPL_MSGBAH:
+        ret = state->msg_base >> 32;
+        break;
+    case PEGPL_MSGBAL:
+        ret = state->msg_base;
+        break;
+    case PEGPL_MSGMSK:
+        ret = state->msg_mask;
+        break;
+    case PEGPL_OMR1BAH:
+        ret = state->omr1_base >> 32;
+        break;
+    case PEGPL_OMR1BAL:
+        ret = state->omr1_base;
+        break;
+    case PEGPL_OMR1MSKH:
+        ret = state->omr1_mask >> 32;
+        break;
+    case PEGPL_OMR1MSKL:
+        ret = state->omr1_mask;
+        break;
+    case PEGPL_OMR2BAH:
+        ret = state->omr2_base >> 32;
+        break;
+    case PEGPL_OMR2BAL:
+        ret = state->omr2_base;
+        break;
+    case PEGPL_OMR2MSKH:
+        ret = state->omr2_mask >> 32;
+        break;
+    case PEGPL_OMR2MSKL:
+        ret = state->omr3_mask;
+        break;
+    case PEGPL_OMR3BAH:
+        ret = state->omr3_base >> 32;
+        break;
+    case PEGPL_OMR3BAL:
+        ret = state->omr3_base;
+        break;
+    case PEGPL_OMR3MSKH:
+        ret = state->omr3_mask >> 32;
+        break;
+    case PEGPL_OMR3MSKL:
+        ret = state->omr3_mask;
+        break;
+    case PEGPL_REGBAH:
+        ret = state->reg_base >> 32;
+        break;
+    case PEGPL_REGBAL:
+        ret = state->reg_base;
+        break;
+    case PEGPL_REGMSK:
+        ret = state->reg_mask;
+        break;
+    case PEGPL_SPECIAL:
+        ret = state->special;
+        break;
+    case PEGPL_CFG:
+        ret = state->cfg;
+        break;
+    }
+#ifdef DEBUG_PCIE
+        printf("read DCR[%x(PCIE)]: %08" PRIx32 "\n", dcrn, ret);
+#endif
+
+    return ret;
+}
+
+static void dcr_write_pcie(void *opaque, int dcrn, uint32_t val)
+{
+    PPC460EXPCIEState *s = opaque;
+    uint64_t size;
+
+#ifdef DEBUG_PCIE
+    printf("write DCR[%x(PCIE)]: %08" PRIx32 "\n", dcrn, val);
+#endif
+    switch (dcrn - s->dcrn_base) {
+    case PEGPL_CFGBAH:
+        s->cfg_base = ((uint64_t)val << 32) | (s->cfg_base & 0xffffffff);
+        break;
+    case PEGPL_CFGBAL:
+        s->cfg_base = (s->cfg_base & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_CFGMSK:
+        s->cfg_mask = val;
+        size = ~(val & 0xfffffffe) + 1;
+#ifdef DEBUG_PCIE
+        printf("%s: %smapping cfg at %lx/%x (size=%lx)\n", __func__,
+               (val & 1 ? "" : "un"), s->cfg_base, val, size);
+#endif
+        qemu_mutex_lock_iothread();
+        pcie_host_mmcfg_update(PCIE_HOST_BRIDGE(s), val & 1, s->cfg_base, size);
+        qemu_mutex_unlock_iothread();
+        break;
+    case PEGPL_MSGBAH:
+        s->msg_base = ((uint64_t)val << 32) | (s->msg_base & 0xffffffff);
+        break;
+    case PEGPL_MSGBAL:
+        s->msg_base = (s->msg_base & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_MSGMSK:
+        s->msg_mask = val;
+        break;
+    case PEGPL_OMR1BAH:
+        s->omr1_base = ((uint64_t)val << 32) | (s->omr1_base & 0xffffffff);
+        break;
+    case PEGPL_OMR1BAL:
+        s->omr1_base = (s->omr1_base & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_OMR1MSKH:
+        s->omr1_mask = ((uint64_t)val << 32) | (s->omr1_mask & 0xffffffff);
+        break;
+    case PEGPL_OMR1MSKL:
+        s->omr1_mask = (s->omr1_mask & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_OMR2BAH:
+        s->omr2_base = ((uint64_t)val << 32) | (s->omr2_base & 0xffffffff);
+        break;
+    case PEGPL_OMR2BAL:
+        s->omr2_base = (s->omr2_base & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_OMR2MSKH:
+        s->omr2_mask = ((uint64_t)val << 32) | (s->omr2_mask & 0xffffffff);
+        break;
+    case PEGPL_OMR2MSKL:
+        s->omr2_mask = (s->omr2_mask & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_OMR3BAH:
+        s->omr3_base = ((uint64_t)val << 32) | (s->omr3_base & 0xffffffff);
+        break;
+    case PEGPL_OMR3BAL:
+        s->omr3_base = (s->omr3_base & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_OMR3MSKH:
+        s->omr3_mask = ((uint64_t)val << 32) | (s->omr3_mask & 0xffffffff);
+        break;
+    case PEGPL_OMR3MSKL:
+        s->omr3_mask = (s->omr3_mask & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_REGBAH:
+        s->reg_base = ((uint64_t)val << 32) | (s->reg_base & 0xffffffff);
+        break;
+    case PEGPL_REGBAL:
+        s->reg_base = (s->reg_base & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_REGMSK:
+        s->reg_mask = val;
+        /* FIXME: how is size encoded? */
+        size = (val == 0x7001 ? 4096 : ~(val & 0xfffffffe) + 1);
+#ifdef DEBUG_PCIE
+        printf("%s: %smapping reg at %lx/%x (size=%lx)\n", __func__,
+               (val & 1 ? "" : "un"), s->reg_base, val, size);
+#endif
+        break;
+    case PEGPL_SPECIAL:
+        s->special = val;
+        break;
+    case PEGPL_CFG:
+        s->cfg = val;
+#ifdef DEBUG_PCIE
+        dump_pcie_regs(s);
+#endif
+        break;
+    }
+}
+
+static void ppc460ex_set_irq(void *opaque, int irq_num, int level)
+{
+       PPC460EXPCIEState *s = opaque;
+       qemu_set_irq(s->irq[irq_num], level);
+}
+
+static void ppc460ex_pcie_realize(DeviceState *dev, Error **errp)
+{
+    PPC460EXPCIEState *s = PPC460EX_PCIE_HOST(dev);
+    PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+    int i, id;
+    char buf[16];
+
+    switch (s->dcrn_base) {
+    case DCRN_PCIE0_BASE:
+        id = 0;
+        break;
+    case DCRN_PCIE1_BASE:
+        id = 1;
+        break;
+    }
+    snprintf(buf, sizeof(buf), "pcie%d-io", id);
+    memory_region_init(&s->iomem, OBJECT(s), buf, UINT64_MAX);
+    for (i = 0; i < 4; i++) {
+        sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]);
+    }
+    snprintf(buf, sizeof(buf), "pcie.%d", id);
+    pci->bus = pci_register_bus(DEVICE(s), buf, ppc460ex_set_irq,
+                                pci_swizzle_map_irq_fn, s, &s->iomem,
+                                get_system_io(), 0, 4, TYPE_PCIE_BUS);
+}
+
+static Property ppc460ex_pcie_props[] = {
+    DEFINE_PROP_INT32("dcrn-base", PPC460EXPCIEState, dcrn_base, -1),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ppc460ex_pcie_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+    dc->realize = ppc460ex_pcie_realize;
+    dc->props = ppc460ex_pcie_props;
+    dc->hotpluggable = false;
+}
+
+static const TypeInfo ppc460ex_pcie_host_info = {
+    .name = TYPE_PPC460EX_PCIE_HOST,
+    .parent = TYPE_PCIE_HOST_BRIDGE,
+    .instance_size = sizeof(PPC460EXPCIEState),
+    .class_init = ppc460ex_pcie_class_init,
+};
+
+static void ppc460ex_pcie_register(void)
+{
+    type_register_static(&ppc460ex_pcie_host_info);
+}
+
+type_init(ppc460ex_pcie_register)
+
+static void ppc460ex_pcie_register_dcrs(PPC460EXPCIEState *s, CPUPPCState *env)
+{
+#ifdef DEBUG_PCIE
+    printf("%s: base=%x\n", __func__, s->dcrn_base);
+#endif
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGBAH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGBAL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGMSK, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGBAH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGBAL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGMSK, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1BAH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1BAL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1MSKH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1MSKL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2BAH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2BAL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2MSKH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2MSKL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3BAH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3BAL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3MSKH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3MSKL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_REGBAH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_REGBAL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_REGMSK, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_SPECIAL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_CFG, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+}
+
+static void ppc460ex_pcie_init(CPUPPCState *env)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, TYPE_PPC460EX_PCIE_HOST);
+    qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE0_BASE);
+    qdev_init_nofail(dev);
+    object_property_set_bool(OBJECT(dev), true, "realized", NULL);
+    ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env);
+
+    dev = qdev_create(NULL, TYPE_PPC460EX_PCIE_HOST);
+    qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE1_BASE);
+    qdev_init_nofail(dev);
+    object_property_set_bool(OBJECT(dev), true, "realized", NULL);
+    ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env);
+}
+
+/*****************************************************************************/
+/* SPD eeprom content from mips_malta.c */
+
+struct _eeprom24c0x_t {
+  uint8_t tick;
+  uint8_t address;
+  uint8_t command;
+  uint8_t ack;
+  uint8_t scl;
+  uint8_t sda;
+  uint8_t data;
+  uint8_t contents[256];
+};
+
+typedef struct _eeprom24c0x_t eeprom24c0x_t;
+
+static eeprom24c0x_t spd_eeprom = {
+    .contents = {
+        /* 00000000: */ 0x80, 0x08, 0xFF, 0x0D, 0x0A, 0xFF, 0x40, 0x00,
+        /* 00000008: */ 0x04, 0x75, 0x54, 0x00, 0x82, 0x08, 0x00, 0x01,
+        /* 00000010: */ 0x8F, 0x04, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
+        /* 00000018: */ 0x00, 0x00, 0x00, 0x14, 0x0F, 0x14, 0x2D, 0xFF,
+        /* 00000020: */ 0x15, 0x08, 0x15, 0x08, 0x00, 0x00, 0x00, 0x00,
+        /* 00000028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xD0,
+        /* 00000040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xF4,
+    },
+};
+
+static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size)
+{
+    enum { SDR = 0x4, DDR1 = 0x7, DDR2 = 0x8 } type;
+    uint8_t *spd = spd_eeprom.contents;
+    uint8_t nbanks = 0;
+    uint16_t density = 0;
+    int i;
+
+    /* work in terms of MB */
+    ram_size >>= 20;
+
+    while ((ram_size >= 4) && (nbanks <= 2)) {
+        int sz_log2 = MIN(31 - clz32(ram_size), 14);
+        nbanks++;
+        density |= 1 << (sz_log2 - 2);
+        ram_size -= 1 << sz_log2;
+    }
+
+    /* split to 2 banks if possible */
+    if ((nbanks == 1) && (density > 1)) {
+        nbanks++;
+        density >>= 1;
+    }
+
+    if (density & 0xff00) {
+        density = (density & 0xe0) | ((density >> 8) & 0x1f);
+        type = DDR2;
+    } else if (!(density & 0x1f)) {
+        type = DDR2;
+    } else {
+        type = SDR;
+    }
+
+    if (ram_size) {
+        fprintf(stderr, "Warning: SPD cannot represent final %dMB"
+                " of SDRAM\n", (int)ram_size);
+    }
+
+    /* fill in SPD memory information */
+    spd[2] = type;
+    spd[5] = nbanks;
+    spd[31] = density;
+#ifdef DEBUG_SDRAM
+    printf("SPD: nbanks %d density %d\n", nbanks, density);
+#endif
+    /* XXX: this is totally random */
+    spd[9] = 0x10; /* CAS tcyc */
+    spd[18] = 0x20; /* CAS bit */
+    spd[23] = 0x10; /* CAS tcyc */
+    spd[25] = 0x10; /* CAS tcyc */
+
+    /* checksum */
+    spd[63] = 0;
+    for (i = 0; i < 63; i++) {
+        spd[63] += spd[i];
+    }
+
+    /* copy for SMBUS */
+    memcpy(eeprom, spd, sizeof(spd_eeprom.contents));
+}
+
+static void generate_eeprom_serial(uint8_t *eeprom)
+{
+    int i, pos = 0;
+    uint8_t mac[6] = { 0x00 };
+    uint8_t sn[5] = { 0x01, 0x23, 0x45, 0x67, 0x89 };
+
+    /* version */
+    eeprom[pos++] = 0x01;
+
+    /* count */
+    eeprom[pos++] = 0x02;
+
+    /* MAC address */
+    eeprom[pos++] = 0x01; /* MAC */
+    eeprom[pos++] = 0x06; /* length */
+    memcpy(&eeprom[pos], mac, sizeof(mac));
+    pos += sizeof(mac);
+
+    /* serial number */
+    eeprom[pos++] = 0x02; /* serial */
+    eeprom[pos++] = 0x05; /* length */
+    memcpy(&eeprom[pos], sn, sizeof(sn));
+    pos += sizeof(sn);
+
+    /* checksum */
+    eeprom[pos] = 0;
+    for (i = 0; i < pos; i++) {
+        eeprom[pos] += eeprom[i];
+    }
+}
+
+/*****************************************************************************/
+
+static int sam460ex_load_uboot(void)
+{
+    DriveInfo *dinfo;
+    BlockBackend *blk = NULL;
+    hwaddr base = FLASH_BASE | ((hwaddr)FLASH_BASE_H << 32);
+    long bios_size = FLASH_SIZE;
+    int fl_sectors;
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (dinfo) {
+        blk = blk_by_legacy_dinfo(dinfo);
+        bios_size = blk_getlength(blk);
+    }
+    fl_sectors = (bios_size + 65535) >> 16;
+
+    if (!pflash_cfi01_register(base, NULL, "sam460ex.flash", bios_size,
+                               blk, (64 * 1024), fl_sectors,
+                               1, 0x89, 0x18, 0x0000, 0x0, 1)) {
+        fprintf(stderr, "qemu: Error registering flash memory.\n");
+        /* XXX: return an error instead? */
+        exit(1);
+    }
+
+    if (!blk) {
+        /*fprintf(stderr, "No flash image given with the 'pflash' parameter,"
+                " using default u-boot image\n");*/
+        base = UBOOT_LOAD_BASE | ((hwaddr)FLASH_BASE_H << 32);
+        rom_add_file_fixed(UBOOT_FILENAME, base, -1);
+    }
+
+    return 0;
+}
+
+static int sam460ex_load_device_tree(hwaddr addr,
+                                     uint32_t ramsize,
+                                     hwaddr initrd_base,
+                                     hwaddr initrd_size,
+                                     const char *kernel_cmdline)
+{
+    int ret = -1;
+    uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) };
+    char *filename;
+    int fdt_size;
+    void *fdt;
+    uint32_t tb_freq = 400000000;
+    uint32_t clock_freq = 400000000;
+
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
+    if (!filename) {
+        goto out;
+    }
+    fdt = load_device_tree(filename, &fdt_size);
+    g_free(filename);
+    if (fdt == NULL) {
+        goto out;
+    }
+
+    /* Manipulate device tree in memory. */
+
+    ret = qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property,
+                               sizeof(mem_reg_property));
+    if (ret < 0) {
+        fprintf(stderr, "couldn't set /memory/reg\n");
+    }
+
+    /* default FDT doesn't have a /chosen node... */
+    qemu_fdt_add_subnode(fdt, "/chosen");
+
+    ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+                                    initrd_base);
+    if (ret < 0) {
+        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
+    }
+
+    ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
+                                    (initrd_base + initrd_size));
+    if (ret < 0) {
+        fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
+    }
+
+    ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
+                                      kernel_cmdline);
+    if (ret < 0) {
+        fprintf(stderr, "couldn't set /chosen/bootargs\n");
+    }
+
+    /* Copy data from the host device tree into the guest. Since the guest can
+     * directly access the timebase without host involvement, we must expose
+     * the correct frequencies. */
+    if (kvm_enabled()) {
+        tb_freq = kvmppc_get_tbfreq();
+        clock_freq = kvmppc_get_clockfreq();
+    }
+
+    qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
+                              clock_freq);
+    qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
+                              tb_freq);
+
+    rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
+    g_free(fdt);
+    ret = fdt_size;
+
+out:
+
+    return ret;
+}
+
+/* Create reset TLB entries for BookE, mapping only the flash memory.  */
+static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env)
+{
+    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
+
+    /* on reset the flash is mapped by a shadow TLB,
+     * but since we don't implement them we need to use
+     * the same values U-Boot will use to avoid a fault.
+     */
+    tlb->attr = 0;
+    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+    tlb->size = 0x10000000; /* up to 0xffffffff  */
+    tlb->EPN = 0xf0000000 & TARGET_PAGE_MASK;
+    tlb->RPN = (0xf0000000 & TARGET_PAGE_MASK) | 0x4;
+    tlb->PID = 0;
+}
+
+/* Create reset TLB entries for BookE, spanning the 32bit addr space.  */
+static void mmubooke_create_initial_mapping(CPUPPCState *env,
+                                     target_ulong va,
+                                     hwaddr pa)
+{
+    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
+
+    tlb->attr = 0;
+    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+    tlb->size = 1 << 31; /* up to 0x80000000  */
+    tlb->EPN = va & TARGET_PAGE_MASK;
+    tlb->RPN = pa & TARGET_PAGE_MASK;
+    tlb->PID = 0;
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    struct boot_info *bi = env->load_info;
+
+    cpu_reset(CPU(cpu));
+
+    /* either we have a kernel to boot or we jump to U-Boot */
+    if (bi->entry != UBOOT_ENTRY) {
+        env->gpr[1] = (16 << 20) - 8;
+        env->gpr[3] = FDT_ADDR;
+
+        fprintf(stderr, "cpu reset: kernel entry %x\n", bi->entry);
+        env->nip = bi->entry;
+
+        /* Create a mapping for the kernel.  */
+        mmubooke_create_initial_mapping(env, 0, 0);
+        env->gpr[6] = tswap32(EPAPR_MAGIC);
+        env->gpr[7] = (16 << 20) - 8; /*bi->ima_size;*/
+
+    } else {
+        env->nip = UBOOT_ENTRY;
+        mmubooke_create_initial_mapping_uboot(env);
+        fprintf(stderr, "cpu reset: U-Boot entry\n");
+    }
+}
+
+static void sam460ex_init(MachineState *machine)
+{
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *isa = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_memories = g_new(MemoryRegion, SDRAM_NR_BANKS);
+    hwaddr ram_bases[SDRAM_NR_BANKS];
+    hwaddr ram_sizes[SDRAM_NR_BANKS];
+    MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1);
+    qemu_irq *irqs, *uic[4];
+    PCIBus *pci_bus;
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    PPC4xxI2CState *i2c[2];
+    hwaddr entry = UBOOT_ENTRY;
+    hwaddr loadaddr = 0;
+    target_long initrd_size = 0;
+    DeviceState *dev;
+    SysBusDevice *sbdev;
+    int success;
+    int i;
+    struct boot_info *boot_info;
+    const size_t smbus_eeprom_size = 8 * 256;
+    uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size);
+
+    /* Setup CPU. */
+    if (machine->cpu_model == NULL) {
+        machine->cpu_model = "460EX";
+    }
+    cpu = cpu_ppc_init(machine->cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to initialize CPU!\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    qemu_register_reset(main_cpu_reset, cpu);
+    boot_info = g_malloc0(sizeof(*boot_info));
+    env->load_info = boot_info;
+
+    ppc_booke_timers_init(cpu, 50000000, 0);
+    ppc_dcr_init(env, NULL, NULL);
+
+    /* PLB arbitrer */
+    ppc4xx_plb_init(env);
+
+    /* interrupt controllers */
+    irqs = g_malloc0(sizeof(*irqs) * PPCUIC_OUTPUT_NB);
+    irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
+    irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
+    uic[0] = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+    uic[1] = ppcuic_init(env, &uic[0][30], 0x0D0, 0, 1);
+    uic[2] = ppcuic_init(env, &uic[0][10], 0x0E0, 0, 1);
+    uic[3] = ppcuic_init(env, &uic[0][16], 0x0F0, 0, 1);
+
+    /* SDRAM controller */
+    memset(ram_bases, 0, sizeof(ram_bases));
+    memset(ram_sizes, 0, sizeof(ram_sizes));
+    /* put all RAM on first bank because board has one slot
+     * and firmware only checks that */
+    machine->ram_size = ppc4xx_sdram_adjust(machine->ram_size,
+                                   1/*SDRAM_NR_BANKS*/,
+                                   ram_memories,
+                                   ram_bases, ram_sizes,
+                                   ppc460ex_sdram_bank_sizes);
+#ifdef DEBUG_SDRAM
+    printf("RAMSIZE %dMB\n", (int)(machine->ram_size / M_BYTE));
+#endif
+
+    /* XXX does 460EX have ECC interrupts? */
+    ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories,
+                      ram_bases, ram_sizes, 1);
+
+    /* generate SPD EEPROM data */
+    for (i = 0; i < SDRAM_NR_BANKS; i++) {
+#ifdef DEBUG_SDRAM
+        printf("bank %d: %" HWADDR_PRIx "\n", i, ram_sizes[i]);
+#endif
+        generate_eeprom_spd(&smbus_eeprom_buf[i * 256], ram_sizes[i]);
+    }
+    generate_eeprom_serial(&smbus_eeprom_buf[4 * 256]);
+    generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]);
+
+    /* IIC controllers */
+    dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, uic[0][2]);
+    i2c[0] = PPC4xx_I2C(dev);
+    object_property_set_bool(OBJECT(dev), true, "realized", NULL);
+    smbus_eeprom_init(i2c[0]->bus, 8, smbus_eeprom_buf, smbus_eeprom_size);
+    g_free(smbus_eeprom_buf);
+
+    dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, uic[0][3]);
+    i2c[1] = PPC4xx_I2C(dev);
+
+    /* External bus controller */
+    ppc405_ebc_init(env);
+
+    /* CPR */
+    ppc4xx_cpr_init(env);
+
+    /* PLB to AHB bridge */
+    ppc4xx_ahb_init(env);
+
+    /* System DCRs */
+    ppc4xx_sdr_init(env);
+
+    /* MAL */
+    ppc4xx_mal_init(env, 4, 16, &uic[2][3]);
+
+    /* 256K of L2 cache as memory */
+    ppc4xx_l2sram_init(env);
+    /* FIXME: remove this after fixing l2sram mapping above? */
+    memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 << 10,
+                           &error_abort);
+    memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_ram);
+
+    /* USB */
+    sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, uic[2][29]);
+    dev = qdev_create(NULL, "sysbus-ohci");
+    qdev_prop_set_string(dev, "masterbus", "usb-bus.0");
+    qdev_prop_set_uint32(dev, "num-ports", 6);
+    qdev_init_nofail(dev);
+    sbdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(sbdev, 0, 0x4bffd0000);
+    sysbus_connect_irq(sbdev, 0, uic[2][30]);
+    usb_create_simple(usb_bus_find(-1), "usb-kbd");
+    usb_create_simple(usb_bus_find(-1), "usb-mouse");
+
+    /* PCI bus */
+    ppc460ex_pcie_init(env);
+    /*XXX: FIXME: is this correct? */
+    dev = sysbus_create_varargs("ppc440-pcix-host", 0xc0ec00000,
+                                uic[1][0], uic[1][20], uic[1][21], uic[1][22],
+                                NULL);
+    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
+    if (!pci_bus) {
+        fprintf(stderr, "couldn't create PCI controller!\n");
+        exit(1);
+    }
+    memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(),
+                             0, 0x10000);
+    memory_region_add_subregion(get_system_memory(), 0xc08000000, isa);
+
+    /* PCI devices */
+    pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501");
+    /* SoC has a single SATA port but we don't emulate that yet
+     * However, firmware and usual clients have driver for SiI311x
+     * so add one for convenience by default */
+    pci_create_simple(pci_bus, -1, "sii3112");
+
+    /* SoC has 4 UARTs
+     * but board has only one wired and two are present in fdt */
+    if (serial_hds[0] != NULL) {
+        serial_mm_init(address_space_mem, 0x4ef600300, 0, uic[1][1],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
+                       DEVICE_BIG_ENDIAN);
+    }
+    if (serial_hds[1] != NULL) {
+        serial_mm_init(address_space_mem, 0x4ef600400, 0, uic[0][1],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
+                       DEVICE_BIG_ENDIAN);
+    }
+
+    /* Load U-Boot image. */
+    if (!machine->kernel_filename) {
+        success = sam460ex_load_uboot();
+        if (success < 0) {
+            fprintf(stderr, "qemu: could not load firmware\n");
+            exit(1);
+        }
+    }
+
+    /* Load kernel. */
+    if (machine->kernel_filename) {
+        success = load_uimage(machine->kernel_filename, &entry, &loadaddr, NULL,
+            NULL, NULL);
+        fprintf(stderr, "load_uimage: %d\n", success);
+        if (success < 0) {
+            uint64_t elf_entry, elf_lowaddr;
+
+            success = load_elf(machine->kernel_filename, NULL, NULL, &elf_entry,
+                               &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, 0, 0);
+            fprintf(stderr, "load_elf: %d\n", success);
+            entry = elf_entry;
+            loadaddr = elf_lowaddr;
+        }
+        /* XXX try again as binary */
+        if (success < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    machine->kernel_filename);
+            exit(1);
+        }
+    }
+
+    /* Load initrd. */
+    if (machine->initrd_filename) {
+        initrd_size = load_image_targphys(machine->initrd_filename,
+                                          RAMDISK_ADDR,
+                                          machine->ram_size - RAMDISK_ADDR);
+        fprintf(stderr, "load_image: %d\n", initrd_size);
+        if (initrd_size < 0) {
+            fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n",
+                    machine->initrd_filename, RAMDISK_ADDR);
+            exit(1);
+        }
+    }
+
+    /* If we're loading a kernel directly, we must load the device tree too. */
+    if (machine->kernel_filename) {
+        int dt_size;
+
+        dt_size = sam460ex_load_device_tree(FDT_ADDR, machine->ram_size,
+                                    RAMDISK_ADDR, initrd_size,
+                                    machine->kernel_cmdline);
+        if (dt_size < 0) {
+            fprintf(stderr, "couldn't load device tree\n");
+            exit(1);
+        }
+
+        boot_info->dt_base = FDT_ADDR;
+        boot_info->dt_size = dt_size;
+    }
+
+    boot_info->entry = entry;
+}
+
+static void sam460ex_machine_init(MachineClass *mc)
+{
+    mc->desc = "aCube Sam460ex";
+    mc->init = sam460ex_init;
+    mc->default_ram_size = 512 * M_BYTE;
+}
+
+DEFINE_MACHINE("sam460ex", sam460ex_machine_init)
diff --git a/include/hw/pci/pcie_host.h b/include/hw/pci/pcie_host.h
index 4d23c80..3f7b988 100644
--- a/include/hw/pci/pcie_host.h
+++ b/include/hw/pci/pcie_host.h
@@ -65,7 +65,7 @@ void pcie_host_mmcfg_update(PCIExpressHost *e,
  * bit 12 - 14: function number
  * bit  0 - 11: offset in configuration space of a given device
  */
-#define PCIE_MMCFG_SIZE_MAX             (1ULL << 28)
+#define PCIE_MMCFG_SIZE_MAX             (1ULL << 29)
 #define PCIE_MMCFG_SIZE_MIN             (1ULL << 20)
 #define PCIE_MMCFG_BUS_BIT              20
 #define PCIE_MMCFG_BUS_MASK             0x1ff
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 04/12] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 04/12] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs BALATON Zoltan
@ 2017-08-14  4:36   ` David Gibson
  0 siblings, 0 replies; 49+ messages in thread
From: David Gibson @ 2017-08-14  4:36 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 2544 bytes --]

On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:

This needs a commit message.  AFAICT the new device is basically a
sysbus EHCI with some altered initial values.  Why do those values
need to be different?  Where do the new values come from?

> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>  hw/usb/hcd-ehci-sysbus.c | 25 +++++++++++++++++++++++++
>  hw/usb/hcd-ehci.h        |  1 +
>  2 files changed, 26 insertions(+)
> 
> diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
> index 6c20604..3b83beb 100644
> --- a/hw/usb/hcd-ehci-sysbus.c
> +++ b/hw/usb/hcd-ehci-sysbus.c
> @@ -142,6 +142,30 @@ static const TypeInfo ehci_tegra2_type_info = {
>      .class_init    = ehci_tegra2_class_init,
>  };
>  
> +static void ehci_ppc4xx_init(Object *o)
> +{
> +    EHCISysBusState *s = SYS_BUS_EHCI(o);
> +
> +    s->ehci.companion_enable = true;
> +}
> +
> +static void ehci_ppc4xx_class_init(ObjectClass *oc, void *data)
> +{
> +    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +
> +    sec->capsbase = 0x0;
> +    sec->opregbase = 0x10;
> +    set_bit(DEVICE_CATEGORY_USB, dc->categories);
> +}
> +
> +static const TypeInfo ehci_ppc4xx_type_info = {
> +    .name          = TYPE_PPC4xx_EHCI,
> +    .parent        = TYPE_SYS_BUS_EHCI,
> +    .class_init    = ehci_ppc4xx_class_init,
> +    .instance_init = ehci_ppc4xx_init,
> +};
> +
>  /*
>   * Faraday FUSBH200 USB 2.0 EHCI
>   */
> @@ -224,6 +248,7 @@ static void ehci_sysbus_register_types(void)
>      type_register_static(&ehci_xlnx_type_info);
>      type_register_static(&ehci_exynos4210_type_info);
>      type_register_static(&ehci_tegra2_type_info);
> +    type_register_static(&ehci_ppc4xx_type_info);
>      type_register_static(&ehci_fusbh200_type_info);
>  }
>  
> diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
> index 821f1de..0bc364b 100644
> --- a/hw/usb/hcd-ehci.h
> +++ b/hw/usb/hcd-ehci.h
> @@ -344,6 +344,7 @@ typedef struct EHCIPCIState {
>  #define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb"
>  #define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
>  #define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
> +#define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
>  #define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
>  
>  #define SYS_BUS_EHCI(obj) \

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 01/12] ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 01/12] ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs BALATON Zoltan
@ 2017-08-14  4:37   ` David Gibson
  0 siblings, 0 replies; 49+ messages in thread
From: David Gibson @ 2017-08-14  4:37 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 17634 bytes --]

On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> This device appears in other SoCs as well not just in 405 ones
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

> ---
>  hw/ppc/ppc405_uc.c      | 263 -----------------------------------------------
>  hw/ppc/ppc4xx_devs.c    | 264 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/hw/ppc/ppc4xx.h |   2 +
>  3 files changed, 266 insertions(+), 263 deletions(-)
> 
> diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
> index f6fe3e6..3c74402 100644
> --- a/hw/ppc/ppc405_uc.c
> +++ b/hw/ppc/ppc405_uc.c
> @@ -42,7 +42,6 @@
>  //#define DEBUG_OCM
>  //#define DEBUG_I2C
>  //#define DEBUG_GPT
> -//#define DEBUG_MAL
>  //#define DEBUG_CLOCKS
>  //#define DEBUG_CLOCKS_LL
>  
> @@ -1513,268 +1512,6 @@ static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5])
>  }
>  
>  /*****************************************************************************/
> -/* MAL */
> -enum {
> -    MAL0_CFG      = 0x180,
> -    MAL0_ESR      = 0x181,
> -    MAL0_IER      = 0x182,
> -    MAL0_TXCASR   = 0x184,
> -    MAL0_TXCARR   = 0x185,
> -    MAL0_TXEOBISR = 0x186,
> -    MAL0_TXDEIR   = 0x187,
> -    MAL0_RXCASR   = 0x190,
> -    MAL0_RXCARR   = 0x191,
> -    MAL0_RXEOBISR = 0x192,
> -    MAL0_RXDEIR   = 0x193,
> -    MAL0_TXCTP0R  = 0x1A0,
> -    MAL0_TXCTP1R  = 0x1A1,
> -    MAL0_TXCTP2R  = 0x1A2,
> -    MAL0_TXCTP3R  = 0x1A3,
> -    MAL0_RXCTP0R  = 0x1C0,
> -    MAL0_RXCTP1R  = 0x1C1,
> -    MAL0_RCBS0    = 0x1E0,
> -    MAL0_RCBS1    = 0x1E1,
> -};
> -
> -typedef struct ppc40x_mal_t ppc40x_mal_t;
> -struct ppc40x_mal_t {
> -    qemu_irq irqs[4];
> -    uint32_t cfg;
> -    uint32_t esr;
> -    uint32_t ier;
> -    uint32_t txcasr;
> -    uint32_t txcarr;
> -    uint32_t txeobisr;
> -    uint32_t txdeir;
> -    uint32_t rxcasr;
> -    uint32_t rxcarr;
> -    uint32_t rxeobisr;
> -    uint32_t rxdeir;
> -    uint32_t txctpr[4];
> -    uint32_t rxctpr[2];
> -    uint32_t rcbs[2];
> -};
> -
> -static void ppc40x_mal_reset (void *opaque);
> -
> -static uint32_t dcr_read_mal (void *opaque, int dcrn)
> -{
> -    ppc40x_mal_t *mal;
> -    uint32_t ret;
> -
> -    mal = opaque;
> -    switch (dcrn) {
> -    case MAL0_CFG:
> -        ret = mal->cfg;
> -        break;
> -    case MAL0_ESR:
> -        ret = mal->esr;
> -        break;
> -    case MAL0_IER:
> -        ret = mal->ier;
> -        break;
> -    case MAL0_TXCASR:
> -        ret = mal->txcasr;
> -        break;
> -    case MAL0_TXCARR:
> -        ret = mal->txcarr;
> -        break;
> -    case MAL0_TXEOBISR:
> -        ret = mal->txeobisr;
> -        break;
> -    case MAL0_TXDEIR:
> -        ret = mal->txdeir;
> -        break;
> -    case MAL0_RXCASR:
> -        ret = mal->rxcasr;
> -        break;
> -    case MAL0_RXCARR:
> -        ret = mal->rxcarr;
> -        break;
> -    case MAL0_RXEOBISR:
> -        ret = mal->rxeobisr;
> -        break;
> -    case MAL0_RXDEIR:
> -        ret = mal->rxdeir;
> -        break;
> -    case MAL0_TXCTP0R:
> -        ret = mal->txctpr[0];
> -        break;
> -    case MAL0_TXCTP1R:
> -        ret = mal->txctpr[1];
> -        break;
> -    case MAL0_TXCTP2R:
> -        ret = mal->txctpr[2];
> -        break;
> -    case MAL0_TXCTP3R:
> -        ret = mal->txctpr[3];
> -        break;
> -    case MAL0_RXCTP0R:
> -        ret = mal->rxctpr[0];
> -        break;
> -    case MAL0_RXCTP1R:
> -        ret = mal->rxctpr[1];
> -        break;
> -    case MAL0_RCBS0:
> -        ret = mal->rcbs[0];
> -        break;
> -    case MAL0_RCBS1:
> -        ret = mal->rcbs[1];
> -        break;
> -    default:
> -        ret = 0;
> -        break;
> -    }
> -
> -    return ret;
> -}
> -
> -static void dcr_write_mal (void *opaque, int dcrn, uint32_t val)
> -{
> -    ppc40x_mal_t *mal;
> -    int idx;
> -
> -    mal = opaque;
> -    switch (dcrn) {
> -    case MAL0_CFG:
> -        if (val & 0x80000000)
> -            ppc40x_mal_reset(mal);
> -        mal->cfg = val & 0x00FFC087;
> -        break;
> -    case MAL0_ESR:
> -        /* Read/clear */
> -        mal->esr &= ~val;
> -        break;
> -    case MAL0_IER:
> -        mal->ier = val & 0x0000001F;
> -        break;
> -    case MAL0_TXCASR:
> -        mal->txcasr = val & 0xF0000000;
> -        break;
> -    case MAL0_TXCARR:
> -        mal->txcarr = val & 0xF0000000;
> -        break;
> -    case MAL0_TXEOBISR:
> -        /* Read/clear */
> -        mal->txeobisr &= ~val;
> -        break;
> -    case MAL0_TXDEIR:
> -        /* Read/clear */
> -        mal->txdeir &= ~val;
> -        break;
> -    case MAL0_RXCASR:
> -        mal->rxcasr = val & 0xC0000000;
> -        break;
> -    case MAL0_RXCARR:
> -        mal->rxcarr = val & 0xC0000000;
> -        break;
> -    case MAL0_RXEOBISR:
> -        /* Read/clear */
> -        mal->rxeobisr &= ~val;
> -        break;
> -    case MAL0_RXDEIR:
> -        /* Read/clear */
> -        mal->rxdeir &= ~val;
> -        break;
> -    case MAL0_TXCTP0R:
> -        idx = 0;
> -        goto update_tx_ptr;
> -    case MAL0_TXCTP1R:
> -        idx = 1;
> -        goto update_tx_ptr;
> -    case MAL0_TXCTP2R:
> -        idx = 2;
> -        goto update_tx_ptr;
> -    case MAL0_TXCTP3R:
> -        idx = 3;
> -    update_tx_ptr:
> -        mal->txctpr[idx] = val;
> -        break;
> -    case MAL0_RXCTP0R:
> -        idx = 0;
> -        goto update_rx_ptr;
> -    case MAL0_RXCTP1R:
> -        idx = 1;
> -    update_rx_ptr:
> -        mal->rxctpr[idx] = val;
> -        break;
> -    case MAL0_RCBS0:
> -        idx = 0;
> -        goto update_rx_size;
> -    case MAL0_RCBS1:
> -        idx = 1;
> -    update_rx_size:
> -        mal->rcbs[idx] = val & 0x000000FF;
> -        break;
> -    }
> -}
> -
> -static void ppc40x_mal_reset (void *opaque)
> -{
> -    ppc40x_mal_t *mal;
> -
> -    mal = opaque;
> -    mal->cfg = 0x0007C000;
> -    mal->esr = 0x00000000;
> -    mal->ier = 0x00000000;
> -    mal->rxcasr = 0x00000000;
> -    mal->rxdeir = 0x00000000;
> -    mal->rxeobisr = 0x00000000;
> -    mal->txcasr = 0x00000000;
> -    mal->txdeir = 0x00000000;
> -    mal->txeobisr = 0x00000000;
> -}
> -
> -static void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
> -{
> -    ppc40x_mal_t *mal;
> -    int i;
> -
> -    mal = g_malloc0(sizeof(ppc40x_mal_t));
> -    for (i = 0; i < 4; i++)
> -        mal->irqs[i] = irqs[i];
> -    qemu_register_reset(&ppc40x_mal_reset, mal);
> -    ppc_dcr_register(env, MAL0_CFG,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_ESR,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_IER,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXCASR,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXCARR,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXEOBISR,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXDEIR,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RXCASR,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RXCARR,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RXEOBISR,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RXDEIR,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXCTP0R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXCTP1R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXCTP2R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXCTP3R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RXCTP0R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RXCTP1R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RCBS0,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RCBS1,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -}
> -
> -/*****************************************************************************/
>  /* SPR */
>  void ppc40x_core_reset(PowerPCCPU *cpu)
>  {
> diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
> index e7f413e..8e4f78e 100644
> --- a/hw/ppc/ppc4xx_devs.c
> +++ b/hw/ppc/ppc4xx_devs.c
> @@ -734,3 +734,267 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
>  
>      return ram_size;
>  }
> +
> +/*****************************************************************************/
> +/* MAL */
> +enum {
> +    MAL0_CFG      = 0x180,
> +    MAL0_ESR      = 0x181,
> +    MAL0_IER      = 0x182,
> +    MAL0_TXCASR   = 0x184,
> +    MAL0_TXCARR   = 0x185,
> +    MAL0_TXEOBISR = 0x186,
> +    MAL0_TXDEIR   = 0x187,
> +    MAL0_RXCASR   = 0x190,
> +    MAL0_RXCARR   = 0x191,
> +    MAL0_RXEOBISR = 0x192,
> +    MAL0_RXDEIR   = 0x193,
> +    MAL0_TXCTP0R  = 0x1A0,
> +    MAL0_TXCTP1R  = 0x1A1,
> +    MAL0_TXCTP2R  = 0x1A2,
> +    MAL0_TXCTP3R  = 0x1A3,
> +    MAL0_RXCTP0R  = 0x1C0,
> +    MAL0_RXCTP1R  = 0x1C1,
> +    MAL0_RCBS0    = 0x1E0,
> +    MAL0_RCBS1    = 0x1E1,
> +};
> +
> +typedef struct ppc40x_mal_t ppc40x_mal_t;
> +struct ppc40x_mal_t {
> +    qemu_irq irqs[4];
> +    uint32_t cfg;
> +    uint32_t esr;
> +    uint32_t ier;
> +    uint32_t txcasr;
> +    uint32_t txcarr;
> +    uint32_t txeobisr;
> +    uint32_t txdeir;
> +    uint32_t rxcasr;
> +    uint32_t rxcarr;
> +    uint32_t rxeobisr;
> +    uint32_t rxdeir;
> +    uint32_t txctpr[4];
> +    uint32_t rxctpr[2];
> +    uint32_t rcbs[2];
> +};
> +
> +static void ppc40x_mal_reset(void *opaque);
> +
> +static uint32_t dcr_read_mal(void *opaque, int dcrn)
> +{
> +    ppc40x_mal_t *mal;
> +    uint32_t ret;
> +
> +    mal = opaque;
> +    switch (dcrn) {
> +    case MAL0_CFG:
> +        ret = mal->cfg;
> +        break;
> +    case MAL0_ESR:
> +        ret = mal->esr;
> +        break;
> +    case MAL0_IER:
> +        ret = mal->ier;
> +        break;
> +    case MAL0_TXCASR:
> +        ret = mal->txcasr;
> +        break;
> +    case MAL0_TXCARR:
> +        ret = mal->txcarr;
> +        break;
> +    case MAL0_TXEOBISR:
> +        ret = mal->txeobisr;
> +        break;
> +    case MAL0_TXDEIR:
> +        ret = mal->txdeir;
> +        break;
> +    case MAL0_RXCASR:
> +        ret = mal->rxcasr;
> +        break;
> +    case MAL0_RXCARR:
> +        ret = mal->rxcarr;
> +        break;
> +    case MAL0_RXEOBISR:
> +        ret = mal->rxeobisr;
> +        break;
> +    case MAL0_RXDEIR:
> +        ret = mal->rxdeir;
> +        break;
> +    case MAL0_TXCTP0R:
> +        ret = mal->txctpr[0];
> +        break;
> +    case MAL0_TXCTP1R:
> +        ret = mal->txctpr[1];
> +        break;
> +    case MAL0_TXCTP2R:
> +        ret = mal->txctpr[2];
> +        break;
> +    case MAL0_TXCTP3R:
> +        ret = mal->txctpr[3];
> +        break;
> +    case MAL0_RXCTP0R:
> +        ret = mal->rxctpr[0];
> +        break;
> +    case MAL0_RXCTP1R:
> +        ret = mal->rxctpr[1];
> +        break;
> +    case MAL0_RCBS0:
> +        ret = mal->rcbs[0];
> +        break;
> +    case MAL0_RCBS1:
> +        ret = mal->rcbs[1];
> +        break;
> +    default:
> +        ret = 0;
> +        break;
> +    }
> +
> +    return ret;
> +}
> +
> +static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
> +{
> +    ppc40x_mal_t *mal;
> +    int idx;
> +
> +    mal = opaque;
> +    switch (dcrn) {
> +    case MAL0_CFG:
> +        if (val & 0x80000000) {
> +            ppc40x_mal_reset(mal);
> +        }
> +        mal->cfg = val & 0x00FFC087;
> +        break;
> +    case MAL0_ESR:
> +        /* Read/clear */
> +        mal->esr &= ~val;
> +        break;
> +    case MAL0_IER:
> +        mal->ier = val & 0x0000001F;
> +        break;
> +    case MAL0_TXCASR:
> +        mal->txcasr = val & 0xF0000000;
> +        break;
> +    case MAL0_TXCARR:
> +        mal->txcarr = val & 0xF0000000;
> +        break;
> +    case MAL0_TXEOBISR:
> +        /* Read/clear */
> +        mal->txeobisr &= ~val;
> +        break;
> +    case MAL0_TXDEIR:
> +        /* Read/clear */
> +        mal->txdeir &= ~val;
> +        break;
> +    case MAL0_RXCASR:
> +        mal->rxcasr = val & 0xC0000000;
> +        break;
> +    case MAL0_RXCARR:
> +        mal->rxcarr = val & 0xC0000000;
> +        break;
> +    case MAL0_RXEOBISR:
> +        /* Read/clear */
> +        mal->rxeobisr &= ~val;
> +        break;
> +    case MAL0_RXDEIR:
> +        /* Read/clear */
> +        mal->rxdeir &= ~val;
> +        break;
> +    case MAL0_TXCTP0R:
> +        idx = 0;
> +        goto update_tx_ptr;
> +    case MAL0_TXCTP1R:
> +        idx = 1;
> +        goto update_tx_ptr;
> +    case MAL0_TXCTP2R:
> +        idx = 2;
> +        goto update_tx_ptr;
> +    case MAL0_TXCTP3R:
> +        idx = 3;
> +    update_tx_ptr:
> +        mal->txctpr[idx] = val;
> +        break;
> +    case MAL0_RXCTP0R:
> +        idx = 0;
> +        goto update_rx_ptr;
> +    case MAL0_RXCTP1R:
> +        idx = 1;
> +    update_rx_ptr:
> +        mal->rxctpr[idx] = val;
> +        break;
> +    case MAL0_RCBS0:
> +        idx = 0;
> +        goto update_rx_size;
> +    case MAL0_RCBS1:
> +        idx = 1;
> +    update_rx_size:
> +        mal->rcbs[idx] = val & 0x000000FF;
> +        break;
> +    }
> +}
> +
> +static void ppc40x_mal_reset(void *opaque)
> +{
> +    ppc40x_mal_t *mal;
> +
> +    mal = opaque;
> +    mal->cfg = 0x0007C000;
> +    mal->esr = 0x00000000;
> +    mal->ier = 0x00000000;
> +    mal->rxcasr = 0x00000000;
> +    mal->rxdeir = 0x00000000;
> +    mal->rxeobisr = 0x00000000;
> +    mal->txcasr = 0x00000000;
> +    mal->txdeir = 0x00000000;
> +    mal->txeobisr = 0x00000000;
> +}
> +
> +void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
> +{
> +    ppc40x_mal_t *mal;
> +    int i;
> +
> +    mal = g_malloc0(sizeof(ppc40x_mal_t));
> +    for (i = 0; i < 4; i++) {
> +        mal->irqs[i] = irqs[i];
> +    }
> +    qemu_register_reset(&ppc40x_mal_reset, mal);
> +    ppc_dcr_register(env, MAL0_CFG,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_ESR,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_IER,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_TXCASR,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_TXCARR,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_TXEOBISR,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_TXDEIR,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_RXCASR,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_RXCARR,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_RXEOBISR,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_RXDEIR,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_TXCTP0R,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_TXCTP1R,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_TXCTP2R,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_TXCTP3R,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_RXCTP0R,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_RXCTP1R,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_RCBS0,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +    ppc_dcr_register(env, MAL0_RCBS1,
> +                     mal, &dcr_read_mal, &dcr_write_mal);
> +}
> diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
> index 66e57a5..db50cfa 100644
> --- a/include/hw/ppc/ppc4xx.h
> +++ b/include/hw/ppc/ppc4xx.h
> @@ -53,6 +53,8 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
>                          hwaddr *ram_sizes,
>                          int do_init);
>  
> +void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4]);
> +
>  #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"
>  
>  #endif /* PPC4XX_H */

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 10/12] ppc: Add 460EX embedded CPU
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 10/12] ppc: Add 460EX embedded CPU BALATON Zoltan
@ 2017-08-14  4:40   ` David Gibson
  0 siblings, 0 replies; 49+ messages in thread
From: David Gibson @ 2017-08-14  4:40 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 4139 bytes --]

On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> Despite its name it is a 440 core CPU
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

> ---
>  target/ppc/cpu-models.c     |  3 +++
>  target/ppc/cpu-models.h     |  1 +
>  target/ppc/translate_init.c | 38 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 42 insertions(+)
> 
> diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
> index 4d3e635..7c368fc 100644
> --- a/target/ppc/cpu-models.c
> +++ b/target/ppc/cpu-models.c
> @@ -348,6 +348,8 @@
>                  "PowerPC 440 EPb")
>      POWERPC_DEF("440EPX",        CPU_POWERPC_440EPX,                 440EP,
>                  "PowerPC 440 EPX")
> +    POWERPC_DEF("460EXb",        CPU_POWERPC_460EXb,                 460EX,
> +                "PowerPC 460 EXb")
>  #if defined(TODO_USER_ONLY)
>      POWERPC_DEF("440GPb",        CPU_POWERPC_440GPb,                 440GP,
>                  "PowerPC 440 GPb")
> @@ -1238,6 +1240,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
>      { "440GP", "440GPc" },
>      { "440GR", "440GRa" },
>      { "440GX", "440GXf" },
> +    { "460EX", "460EXb" },
>  
>      { "RCPU", "MPC5xx" },
>      /* MPC5xx microcontrollers */
> diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h
> index b563c45..92f99c0 100644
> --- a/target/ppc/cpu-models.h
> +++ b/target/ppc/cpu-models.h
> @@ -241,6 +241,7 @@ enum {
>      CPU_POWERPC_440SP              = 0x53221850,
>      CPU_POWERPC_440SP2             = 0x53221891,
>      CPU_POWERPC_440SPE             = 0x53421890,
> +    CPU_POWERPC_460EXb             = 0x130218A4, /* called 460 but 440 core */
>      /* PowerPC 460 family */
>  #if 0
>      /* Generic PowerPC 464 */
> diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
> index 8fb407e..1e0d566 100644
> --- a/target/ppc/translate_init.c
> +++ b/target/ppc/translate_init.c
> @@ -3832,6 +3832,44 @@ POWERPC_FAMILY(440EP)(ObjectClass *oc, void *data)
>                   POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
>  }
>  
> +POWERPC_FAMILY(460EX)(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
> +
> +    dc->desc = "PowerPC 460 EX";
> +    pcc->init_proc = init_proc_440EP;
> +    pcc->check_pow = check_pow_nocheck;
> +    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> +                       PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
> +                       PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> +                       PPC_FLOAT_STFIWX |
> +                       PPC_DCR | PPC_DCRX | PPC_WRTEE | PPC_RFMCI |
> +                       PPC_CACHE | PPC_CACHE_ICBI |
> +                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
> +                       PPC_MEM_TLBSYNC | PPC_MFTB |
> +                       PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
> +                       PPC_440_SPEC;
> +    pcc->msr_mask = (1ull << MSR_POW) |
> +                    (1ull << MSR_CE) |
> +                    (1ull << MSR_EE) |
> +                    (1ull << MSR_PR) |
> +                    (1ull << MSR_FP) |
> +                    (1ull << MSR_ME) |
> +                    (1ull << MSR_FE0) |
> +                    (1ull << MSR_DWE) |
> +                    (1ull << MSR_DE) |
> +                    (1ull << MSR_FE1) |
> +                    (1ull << MSR_IR) |
> +                    (1ull << MSR_DR);
> +    pcc->mmu_model = POWERPC_MMU_BOOKE;
> +    pcc->excp_model = POWERPC_EXCP_BOOKE;
> +    pcc->bus_model = PPC_FLAGS_INPUT_BookE;
> +    pcc->bfd_mach = bfd_mach_ppc_403;
> +    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE |
> +                 POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
> +}
> +
>  static void init_proc_440GP(CPUPPCState *env)
>  {
>      /* Time base */

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 05/12] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 05/12] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file BALATON Zoltan
@ 2017-08-14  4:41   ` David Gibson
  2017-08-14  9:00   ` Paolo Bonzini
  1 sibling, 0 replies; 49+ messages in thread
From: David Gibson @ 2017-08-14  4:41 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 16821 bytes --]

On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:

Needs a commit message: why is this a useful thing to do?

> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>  hw/ppc/Makefile.objs |   2 +-
>  hw/ppc/ppc405.h      |   2 +
>  hw/ppc/ppc405_uc.c   | 241 ---------------------------------------------
>  hw/ppc/ppc4xx_i2c.c  | 272 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 275 insertions(+), 242 deletions(-)
>  create mode 100644 hw/ppc/ppc4xx_i2c.c
> 
> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
> index 7efc686..2077216 100644
> --- a/hw/ppc/Makefile.objs
> +++ b/hw/ppc/Makefile.objs
> @@ -13,7 +13,7 @@ endif
>  obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
>  # PowerPC 4xx boards
>  obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
> -obj-y += ppc4xx_pci.o
> +obj-y += ppc4xx_pci.o ppc4xx_i2c.o
>  # PReP
>  obj-$(CONFIG_PREP) += prep.o
>  obj-$(CONFIG_PREP) += prep_systemio.o
> diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
> index a9ffc87..61ec739 100644
> --- a/hw/ppc/ppc405.h
> +++ b/hw/ppc/ppc405.h
> @@ -59,6 +59,8 @@ struct ppc4xx_bd_info_t {
>  ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
>                                  uint32_t flags);
>  
> +void ppc405_i2c_init(hwaddr base, qemu_irq irq);
> +
>  CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
>                          MemoryRegion ram_memories[4],
>                          hwaddr ram_bases[4],
> diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
> index 03856d5..3925e4c 100644
> --- a/hw/ppc/ppc405_uc.c
> +++ b/hw/ppc/ppc405_uc.c
> @@ -40,7 +40,6 @@
>  //#define DEBUG_GPIO
>  //#define DEBUG_SERIAL
>  //#define DEBUG_OCM
> -//#define DEBUG_I2C
>  //#define DEBUG_GPT
>  //#define DEBUG_CLOCKS
>  //#define DEBUG_CLOCKS_LL
> @@ -993,246 +992,6 @@ static void ppc405_ocm_init(CPUPPCState *env)
>  }
>  
>  /*****************************************************************************/
> -/* I2C controller */
> -typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
> -struct ppc4xx_i2c_t {
> -    qemu_irq irq;
> -    MemoryRegion iomem;
> -    uint8_t mdata;
> -    uint8_t lmadr;
> -    uint8_t hmadr;
> -    uint8_t cntl;
> -    uint8_t mdcntl;
> -    uint8_t sts;
> -    uint8_t extsts;
> -    uint8_t sdata;
> -    uint8_t lsadr;
> -    uint8_t hsadr;
> -    uint8_t clkdiv;
> -    uint8_t intrmsk;
> -    uint8_t xfrcnt;
> -    uint8_t xtcntlss;
> -    uint8_t directcntl;
> -};
> -
> -static uint32_t ppc4xx_i2c_readb (void *opaque, hwaddr addr)
> -{
> -    ppc4xx_i2c_t *i2c;
> -    uint32_t ret;
> -
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
> -#endif
> -    i2c = opaque;
> -    switch (addr) {
> -    case 0x00:
> -        //        i2c_readbyte(&i2c->mdata);
> -        ret = i2c->mdata;
> -        break;
> -    case 0x02:
> -        ret = i2c->sdata;
> -        break;
> -    case 0x04:
> -        ret = i2c->lmadr;
> -        break;
> -    case 0x05:
> -        ret = i2c->hmadr;
> -        break;
> -    case 0x06:
> -        ret = i2c->cntl;
> -        break;
> -    case 0x07:
> -        ret = i2c->mdcntl;
> -        break;
> -    case 0x08:
> -        ret = i2c->sts;
> -        break;
> -    case 0x09:
> -        ret = i2c->extsts;
> -        break;
> -    case 0x0A:
> -        ret = i2c->lsadr;
> -        break;
> -    case 0x0B:
> -        ret = i2c->hsadr;
> -        break;
> -    case 0x0C:
> -        ret = i2c->clkdiv;
> -        break;
> -    case 0x0D:
> -        ret = i2c->intrmsk;
> -        break;
> -    case 0x0E:
> -        ret = i2c->xfrcnt;
> -        break;
> -    case 0x0F:
> -        ret = i2c->xtcntlss;
> -        break;
> -    case 0x10:
> -        ret = i2c->directcntl;
> -        break;
> -    default:
> -        ret = 0x00;
> -        break;
> -    }
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, ret);
> -#endif
> -
> -    return ret;
> -}
> -
> -static void ppc4xx_i2c_writeb (void *opaque,
> -                               hwaddr addr, uint32_t value)
> -{
> -    ppc4xx_i2c_t *i2c;
> -
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
> -           value);
> -#endif
> -    i2c = opaque;
> -    switch (addr) {
> -    case 0x00:
> -        i2c->mdata = value;
> -        //        i2c_sendbyte(&i2c->mdata);
> -        break;
> -    case 0x02:
> -        i2c->sdata = value;
> -        break;
> -    case 0x04:
> -        i2c->lmadr = value;
> -        break;
> -    case 0x05:
> -        i2c->hmadr = value;
> -        break;
> -    case 0x06:
> -        i2c->cntl = value;
> -        break;
> -    case 0x07:
> -        i2c->mdcntl = value & 0xDF;
> -        break;
> -    case 0x08:
> -        i2c->sts &= ~(value & 0x0A);
> -        break;
> -    case 0x09:
> -        i2c->extsts &= ~(value & 0x8F);
> -        break;
> -    case 0x0A:
> -        i2c->lsadr = value;
> -        break;
> -    case 0x0B:
> -        i2c->hsadr = value;
> -        break;
> -    case 0x0C:
> -        i2c->clkdiv = value;
> -        break;
> -    case 0x0D:
> -        i2c->intrmsk = value;
> -        break;
> -    case 0x0E:
> -        i2c->xfrcnt = value & 0x77;
> -        break;
> -    case 0x0F:
> -        i2c->xtcntlss = value;
> -        break;
> -    case 0x10:
> -        i2c->directcntl = value & 0x7;
> -        break;
> -    }
> -}
> -
> -static uint32_t ppc4xx_i2c_readw (void *opaque, hwaddr addr)
> -{
> -    uint32_t ret;
> -
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
> -#endif
> -    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
> -    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
> -
> -    return ret;
> -}
> -
> -static void ppc4xx_i2c_writew (void *opaque,
> -                               hwaddr addr, uint32_t value)
> -{
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
> -           value);
> -#endif
> -    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
> -    ppc4xx_i2c_writeb(opaque, addr + 1, value);
> -}
> -
> -static uint32_t ppc4xx_i2c_readl (void *opaque, hwaddr addr)
> -{
> -    uint32_t ret;
> -
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
> -#endif
> -    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
> -    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
> -    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
> -    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
> -
> -    return ret;
> -}
> -
> -static void ppc4xx_i2c_writel (void *opaque,
> -                               hwaddr addr, uint32_t value)
> -{
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
> -           value);
> -#endif
> -    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
> -    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
> -    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
> -    ppc4xx_i2c_writeb(opaque, addr + 3, value);
> -}
> -
> -static const MemoryRegionOps i2c_ops = {
> -    .old_mmio = {
> -        .read = { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, },
> -        .write = { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writel, },
> -    },
> -    .endianness = DEVICE_NATIVE_ENDIAN,
> -};
> -
> -static void ppc4xx_i2c_reset (void *opaque)
> -{
> -    ppc4xx_i2c_t *i2c;
> -
> -    i2c = opaque;
> -    i2c->mdata = 0x00;
> -    i2c->sdata = 0x00;
> -    i2c->cntl = 0x00;
> -    i2c->mdcntl = 0x00;
> -    i2c->sts = 0x00;
> -    i2c->extsts = 0x00;
> -    i2c->clkdiv = 0x00;
> -    i2c->xfrcnt = 0x00;
> -    i2c->directcntl = 0x0F;
> -}
> -
> -static void ppc405_i2c_init(hwaddr base, qemu_irq irq)
> -{
> -    ppc4xx_i2c_t *i2c;
> -
> -    i2c = g_malloc0(sizeof(ppc4xx_i2c_t));
> -    i2c->irq = irq;
> -#ifdef DEBUG_I2C
> -    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
> -#endif
> -    memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011);
> -    memory_region_add_subregion(get_system_memory(), base, &i2c->iomem);
> -    qemu_register_reset(ppc4xx_i2c_reset, i2c);
> -}
> -
> -/*****************************************************************************/
>  /* General purpose timers */
>  typedef struct ppc4xx_gpt_t ppc4xx_gpt_t;
>  struct ppc4xx_gpt_t {
> diff --git a/hw/ppc/ppc4xx_i2c.c b/hw/ppc/ppc4xx_i2c.c
> new file mode 100644
> index 0000000..15f2dea
> --- /dev/null
> +++ b/hw/ppc/ppc4xx_i2c.c
> @@ -0,0 +1,272 @@
> +/*
> + * PPC4xx I2C controller emulation
> + *
> + * Copyright (c) 2007 Jocelyn Mayer
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu-common.h"
> +#include "cpu.h"
> +#include "hw/hw.h"
> +#include "exec/address-spaces.h"
> +#include "hw/ppc/ppc.h"
> +#include "ppc405.h"
> +
> +/*#define DEBUG_I2C*/
> +
> +typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
> +struct ppc4xx_i2c_t {
> +    qemu_irq irq;
> +    MemoryRegion iomem;
> +    uint8_t mdata;
> +    uint8_t lmadr;
> +    uint8_t hmadr;
> +    uint8_t cntl;
> +    uint8_t mdcntl;
> +    uint8_t sts;
> +    uint8_t extsts;
> +    uint8_t sdata;
> +    uint8_t lsadr;
> +    uint8_t hsadr;
> +    uint8_t clkdiv;
> +    uint8_t intrmsk;
> +    uint8_t xfrcnt;
> +    uint8_t xtcntlss;
> +    uint8_t directcntl;
> +};
> +
> +static uint32_t ppc4xx_i2c_readb(void *opaque, hwaddr addr)
> +{
> +    ppc4xx_i2c_t *i2c;
> +    uint32_t ret;
> +
> +#ifdef DEBUG_I2C
> +    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
> +#endif
> +    i2c = opaque;
> +    switch (addr) {
> +    case 0x00:
> +        /*i2c_readbyte(&i2c->mdata);*/
> +        ret = i2c->mdata;
> +        break;
> +    case 0x02:
> +        ret = i2c->sdata;
> +        break;
> +    case 0x04:
> +        ret = i2c->lmadr;
> +        break;
> +    case 0x05:
> +        ret = i2c->hmadr;
> +        break;
> +    case 0x06:
> +        ret = i2c->cntl;
> +        break;
> +    case 0x07:
> +        ret = i2c->mdcntl;
> +        break;
> +    case 0x08:
> +        ret = i2c->sts;
> +        break;
> +    case 0x09:
> +        ret = i2c->extsts;
> +        break;
> +    case 0x0A:
> +        ret = i2c->lsadr;
> +        break;
> +    case 0x0B:
> +        ret = i2c->hsadr;
> +        break;
> +    case 0x0C:
> +        ret = i2c->clkdiv;
> +        break;
> +    case 0x0D:
> +        ret = i2c->intrmsk;
> +        break;
> +    case 0x0E:
> +        ret = i2c->xfrcnt;
> +        break;
> +    case 0x0F:
> +        ret = i2c->xtcntlss;
> +        break;
> +    case 0x10:
> +        ret = i2c->directcntl;
> +        break;
> +    default:
> +        ret = 0x00;
> +        break;
> +    }
> +#ifdef DEBUG_I2C
> +    printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, ret);
> +#endif
> +
> +    return ret;
> +}
> +
> +static void ppc4xx_i2c_writeb(void *opaque,
> +                              hwaddr addr, uint32_t value)
> +{
> +    ppc4xx_i2c_t *i2c;
> +
> +#ifdef DEBUG_I2C
> +    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
> +           value);
> +#endif
> +    i2c = opaque;
> +    switch (addr) {
> +    case 0x00:
> +        i2c->mdata = value;
> +        /*i2c_sendbyte(&i2c->mdata);*/
> +        break;
> +    case 0x02:
> +        i2c->sdata = value;
> +        break;
> +    case 0x04:
> +        i2c->lmadr = value;
> +        break;
> +    case 0x05:
> +        i2c->hmadr = value;
> +        break;
> +    case 0x06:
> +        i2c->cntl = value;
> +        break;
> +    case 0x07:
> +        i2c->mdcntl = value & 0xDF;
> +        break;
> +    case 0x08:
> +        i2c->sts &= ~(value & 0x0A);
> +        break;
> +    case 0x09:
> +        i2c->extsts &= ~(value & 0x8F);
> +        break;
> +    case 0x0A:
> +        i2c->lsadr = value;
> +        break;
> +    case 0x0B:
> +        i2c->hsadr = value;
> +        break;
> +    case 0x0C:
> +        i2c->clkdiv = value;
> +        break;
> +    case 0x0D:
> +        i2c->intrmsk = value;
> +        break;
> +    case 0x0E:
> +        i2c->xfrcnt = value & 0x77;
> +        break;
> +    case 0x0F:
> +        i2c->xtcntlss = value;
> +        break;
> +    case 0x10:
> +        i2c->directcntl = value & 0x7;
> +        break;
> +    }
> +}
> +
> +static uint32_t ppc4xx_i2c_readw(void *opaque, hwaddr addr)
> +{
> +    uint32_t ret;
> +
> +#ifdef DEBUG_I2C
> +    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
> +#endif
> +    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
> +    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
> +
> +    return ret;
> +}
> +
> +static void ppc4xx_i2c_writew(void *opaque,
> +                              hwaddr addr, uint32_t value)
> +{
> +#ifdef DEBUG_I2C
> +    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
> +           value);
> +#endif
> +    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
> +    ppc4xx_i2c_writeb(opaque, addr + 1, value);
> +}
> +
> +static uint32_t ppc4xx_i2c_readl(void *opaque, hwaddr addr)
> +{
> +    uint32_t ret;
> +
> +#ifdef DEBUG_I2C
> +    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
> +#endif
> +    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
> +    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
> +    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
> +    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
> +
> +    return ret;
> +}
> +
> +static void ppc4xx_i2c_writel(void *opaque,
> +                              hwaddr addr, uint32_t value)
> +{
> +#ifdef DEBUG_I2C
> +    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
> +           value);
> +#endif
> +    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
> +    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
> +    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
> +    ppc4xx_i2c_writeb(opaque, addr + 3, value);
> +}
> +
> +static const MemoryRegionOps i2c_ops = {
> +    .old_mmio = {
> +        .read = { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, },
> +        .write = { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writel, },
> +    },
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +static void ppc4xx_i2c_reset(void *opaque)
> +{
> +    ppc4xx_i2c_t *i2c;
> +
> +    i2c = opaque;
> +    i2c->mdata = 0x00;
> +    i2c->sdata = 0x00;
> +    i2c->cntl = 0x00;
> +    i2c->mdcntl = 0x00;
> +    i2c->sts = 0x00;
> +    i2c->extsts = 0x00;
> +    i2c->clkdiv = 0x00;
> +    i2c->xfrcnt = 0x00;
> +    i2c->directcntl = 0x0F;
> +}
> +
> +void ppc405_i2c_init(hwaddr base, qemu_irq irq)
> +{
> +    ppc4xx_i2c_t *i2c;
> +
> +    i2c = g_malloc0(sizeof(ppc4xx_i2c_t));
> +    i2c->irq = irq;
> +#ifdef DEBUG_I2C
> +    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
> +#endif
> +    memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011);
> +    memory_region_add_subregion(get_system_memory(), base, &i2c->iomem);
> +    qemu_register_reset(ppc4xx_i2c_reset, i2c);
> +}

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 08/12] hw/ide: Emulate SiI3112 SATA controller
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 08/12] hw/ide: Emulate SiI3112 SATA controller BALATON Zoltan
@ 2017-08-14  4:42   ` David Gibson
  2017-08-14 11:16     ` BALATON Zoltan
  0 siblings, 1 reply; 49+ messages in thread
From: David Gibson @ 2017-08-14  4:42 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 13123 bytes --]

On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

Needs a commit message: where does this controller appear? what's
distinctive about it? is there a link to a datasheet or programming manual?

> ---
>  hw/ide/Makefile.objs |   1 +
>  hw/ide/sii3112.c     | 365 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 366 insertions(+)
>  create mode 100644 hw/ide/sii3112.c
> 
> diff --git a/hw/ide/Makefile.objs b/hw/ide/Makefile.objs
> index 729e9bd..76f3d6d 100644
> --- a/hw/ide/Makefile.objs
> +++ b/hw/ide/Makefile.objs
> @@ -10,3 +10,4 @@ common-obj-$(CONFIG_IDE_VIA) += via.o
>  common-obj-$(CONFIG_MICRODRIVE) += microdrive.o
>  common-obj-$(CONFIG_AHCI) += ahci.o
>  common-obj-$(CONFIG_AHCI) += ich.o
> +common-obj-$(CONFIG_IDE_SII3112) += sii3112.o
> diff --git a/hw/ide/sii3112.c b/hw/ide/sii3112.c
> new file mode 100644
> index 0000000..d3f34b5
> --- /dev/null
> +++ b/hw/ide/sii3112.c
> @@ -0,0 +1,365 @@
> +/*
> + * QEMU SiI3112A PCI to Serial ATA Controller Emulation
> + *
> + * Copyright (C) 2017 BALATON Zoltan <balaton@eik.bme.hu>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + *
> + */
> +
> +#include <qemu/osdep.h>
> +#include <hw/ide/pci.h>
> +
> +#ifdef DEBUG_IDE
> +#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
> +#else
> +#define DPRINTF(fmt, ...)
> +#endif /* DEBUG */
> +
> +#define TYPE_SII3112_PCI "sii3112"
> +#define SII3112_PCI(obj) OBJECT_CHECK(SiI3112PCIState, (obj), \
> +                         TYPE_SII3112_PCI)
> +
> +typedef struct SiI3112Regs {
> +    uint32_t confstat;
> +    uint32_t scontrol;
> +    uint16_t sien;
> +    uint8_t swdata;
> +} SiI3112Regs;
> +
> +typedef struct SiI3112PCIState {
> +    PCIIDEState i;
> +    MemoryRegion mmio;
> +    SiI3112Regs regs[2];
> +} SiI3112PCIState;
> +
> +static uint64_t sii3112_reg_read(void *opaque, hwaddr addr,
> +                                unsigned int size)
> +{
> +    SiI3112PCIState *d = opaque;
> +    uint64_t val = 0;
> +
> +    switch (addr) {
> +    case 0x00:
> +        val = d->i.bmdma[0].cmd;
> +        break;
> +    case 0x01:
> +        val = d->regs[0].swdata;
> +        break;
> +    case 0x02:
> +        val = d->i.bmdma[0].status;
> +        break;
> +    case 0x03:
> +        val = 0;
> +        break;
> +    case 0x04 ... 0x07:
> +        val = bmdma_addr_ioport_ops.read(&d->i.bmdma[0], addr - 4, size);
> +        break;
> +    case 0x08:
> +        val = d->i.bmdma[1].cmd;
> +        break;
> +    case 0x09:
> +        val = d->regs[1].swdata;
> +        break;
> +    case 0x0a:
> +        val = d->i.bmdma[1].status;
> +        break;
> +    case 0x0b:
> +        val = 0;
> +        break;
> +    case 0x0c ... 0x0f:
> +        val = bmdma_addr_ioport_ops.read(&d->i.bmdma[1], addr - 12, size);
> +        break;
> +    case 0x10:
> +        val = d->i.bmdma[0].cmd;
> +        val |= (d->regs[0].confstat & (1UL << 11) ? (1 << 4) : 0); /*SATAINT0*/
> +        val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 6) : 0); /*SATAINT1*/
> +        val |= (d->i.bmdma[1].status & BM_STATUS_INT ? (1 << 14) : 0);
> +        val |= d->i.bmdma[0].status << 16;
> +        val |= d->i.bmdma[1].status << 24;
> +        break;
> +    case 0x18:
> +        val = d->i.bmdma[1].cmd;
> +        val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 4) : 0);
> +        val |= d->i.bmdma[1].status << 16;
> +        break;
> +    case 0x80 ... 0x87:
> +        if (size == 1) {
> +            val = ide_ioport_read(&d->i.bus[0], addr - 0x80);
> +        } else if (addr == 0x80) {
> +            val = (size == 2) ? ide_data_readw(&d->i.bus[0], 0) :
> +                                ide_data_readl(&d->i.bus[0], 0);
> +        } else {
> +            val = (1ULL << (size * 8)) - 1;
> +        }
> +        break;
> +    case 0x8a:
> +        val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
> +                            (1ULL << (size * 8)) - 1;
> +        break;
> +    case 0xa0:
> +        val = d->regs[0].confstat;
> +        break;
> +    case 0xc0 ... 0xc7:
> +        if (size == 1) {
> +            val = ide_ioport_read(&d->i.bus[1], addr - 0xc0);
> +        } else if (addr == 0xc0) {
> +            val = (size == 2) ? ide_data_readw(&d->i.bus[1], 0) :
> +                                ide_data_readl(&d->i.bus[1], 0);
> +        } else {
> +            val = (1ULL << (size * 8)) - 1;
> +        }
> +        break;
> +    case 0xca:
> +        val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
> +                            (1ULL << (size * 8)) - 1;
> +        break;
> +    case 0xe0:
> +        val = d->regs[1].confstat;
> +        break;
> +    case 0x100:
> +        val = d->regs[0].scontrol;
> +        break;
> +    case 0x104:
> +        val = (d->i.bus[0].ifs[0].blk) ? 0x113 : 0;
> +        break;
> +    case 0x148:
> +        val = d->regs[0].sien << 16;
> +        break;
> +    case 0x180:
> +        val = d->regs[1].scontrol;
> +        break;
> +    case 0x184:
> +        val = (d->i.bus[1].ifs[0].blk) ? 0x113 : 0;
> +        break;
> +    case 0x1c8:
> +        val = d->regs[1].sien << 16;
> +        break;
> +    default:
> +        val = 0;
> +    }
> +    DPRINTF("%s: addr 0x%"PRIx64 " size %d = %"PRIx64 "\n",
> +            __func__, addr, size, val);
> +    return val;
> +}
> +
> +static void sii3112_reg_write(void *opaque, hwaddr addr,
> +                              uint64_t val, unsigned int size)
> +{
> +    SiI3112PCIState *d = opaque;
> +
> +    DPRINTF("%s: addr 0x%"PRIx64 " size %d = %"PRIx64 "\n",
> +            __func__, addr, size, val);
> +    switch (addr) {
> +    case 0x00:
> +    case 0x10:
> +        bmdma_cmd_writeb(&d->i.bmdma[0], val);
> +        break;
> +    case 0x01:
> +    case 0x11:
> +        d->regs[0].swdata = val & 0x3f;
> +        break;
> +    case 0x02:
> +    case 0x12:
> +        d->i.bmdma[0].status = (val & 0x60) | (d->i.bmdma[0].status & 1) |
> +                               (d->i.bmdma[0].status & ~val & 6);
> +        break;
> +    case 0x04 ... 0x07:
> +        bmdma_addr_ioport_ops.write(&d->i.bmdma[0], addr - 4, val, size);
> +        break;
> +    case 0x08:
> +    case 0x18:
> +        bmdma_cmd_writeb(&d->i.bmdma[1], val);
> +        break;
> +    case 0x09:
> +    case 0x19:
> +        d->regs[1].swdata = val & 0x3f;
> +        break;
> +    case 0x0a:
> +    case 0x1a:
> +        d->i.bmdma[1].status = (val & 0x60) | (d->i.bmdma[1].status & 1) |
> +                               (d->i.bmdma[1].status & ~val & 6);
> +        break;
> +    case 0x0c ... 0x0f:
> +        bmdma_addr_ioport_ops.write(&d->i.bmdma[1], addr - 12, val, size);
> +        break;
> +    case 0x80 ... 0x87:
> +        if (size == 1) {
> +            ide_ioport_write(&d->i.bus[0], addr - 0x80, val);
> +        } else if (addr == 0x80) {
> +            if (size == 2) {
> +                ide_data_writew(&d->i.bus[0], 0, val);
> +            } else {
> +                ide_data_writel(&d->i.bus[0], 0, val);
> +            }
> +        }
> +        break;
> +    case 0x8a:
> +        if (size == 1) {
> +            ide_cmd_write(&d->i.bus[0], 4, val);
> +        }
> +        break;
> +    case 0xc0 ... 0xc7:
> +        if (size == 1) {
> +            ide_ioport_write(&d->i.bus[1], addr - 0xc0, val);
> +        } else if (addr == 0xc0) {
> +            if (size == 2) {
> +                ide_data_writew(&d->i.bus[1], 0, val);
> +            } else {
> +                ide_data_writel(&d->i.bus[1], 0, val);
> +            }
> +        }
> +        break;
> +    case 0xca:
> +        if (size == 1) {
> +            ide_cmd_write(&d->i.bus[1], 4, val);
> +        }
> +        break;
> +    case 0x100:
> +        d->regs[0].scontrol = val & 0xfff;
> +        if (val & 1) {
> +            ide_bus_reset(&d->i.bus[0]);
> +        }
> +        break;
> +    case 0x148:
> +        d->regs[0].sien = (val >> 16) & 0x3eed;
> +        break;
> +    case 0x180:
> +        d->regs[1].scontrol = val & 0xfff;
> +        if (val & 1) {
> +            ide_bus_reset(&d->i.bus[1]);
> +        }
> +        break;
> +    case 0x1c8:
> +        d->regs[1].sien = (val >> 16) & 0x3eed;
> +        break;
> +    default:
> +        val = 0;
> +    }
> +}
> +
> +static const MemoryRegionOps sii3112_reg_ops = {
> +    .read = sii3112_reg_read,
> +    .write = sii3112_reg_write,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
> +/* the PCI irq level is the logical OR of the two channels */
> +static void sii3112_update_irq(SiI3112PCIState *s)
> +{
> +    int i, set = 0;
> +
> +    for (i = 0; i < 2; i++) {
> +        set |= s->regs[i].confstat & (1UL << 11);
> +    }
> +    pci_set_irq(PCI_DEVICE(s), (set ? 1 : 0));
> +}
> +
> +static void sii3112_set_irq(void *opaque, int channel, int level)
> +{
> +    SiI3112PCIState *s = opaque;
> +
> +    DPRINTF("%s: channel %d level %d\n", __func__, channel, level);
> +    if (level) {
> +        s->regs[channel].confstat |= (1UL << 11);
> +    } else {
> +        s->regs[channel].confstat &= ~(1UL << 11);
> +    }
> +
> +    sii3112_update_irq(s);
> +}
> +
> +static void sii3112_reset(void *opaque)
> +{
> +    SiI3112PCIState *s = opaque;
> +    int i;
> +
> +    for (i = 0; i < 2; i++) {
> +        s->regs[i].confstat = 0x6515 << 16;
> +        ide_bus_reset(&s->i.bus[i]);
> +    }
> +}
> +
> +static void sii3112_pci_realize(PCIDevice *dev, Error **errp)
> +{
> +    SiI3112PCIState *d = SII3112_PCI(dev);
> +    PCIIDEState *s = PCI_IDE(dev);
> +    MemoryRegion *mr;
> +    qemu_irq *irq;
> +    int i;
> +
> +    pci_config_set_interrupt_pin(dev->config, 1);
> +    pci_set_byte(dev->config + PCI_CACHE_LINE_SIZE, 8);
> +
> +    memory_region_init_io(&d->mmio, OBJECT(d), &sii3112_reg_ops, d,
> +                         "sii3112.bar5", 0x200);
> +    pci_register_bar(dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
> +
> +    mr = g_new(MemoryRegion, 1);
> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar0", &d->mmio, 0x80, 8);
> +    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, mr);
> +    mr = g_new(MemoryRegion, 1);
> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar1", &d->mmio, 0x88, 4);
> +    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, mr);
> +    mr = g_new(MemoryRegion, 1);
> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar2", &d->mmio, 0xc0, 8);
> +    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, mr);
> +    mr = g_new(MemoryRegion, 1);
> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar3", &d->mmio, 0xc8, 4);
> +    pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, mr);
> +    mr = g_new(MemoryRegion, 1);
> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar4", &d->mmio, 0, 16);
> +    pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, mr);
> +
> +    irq = qemu_allocate_irqs(sii3112_set_irq, d, 2);
> +    for (i = 0; i < 2; i++) {
> +        ide_bus_new(&s->bus[i], sizeof(s->bus[i]), DEVICE(dev), i, 1);
> +        ide_init2(&s->bus[i], irq[i]);
> +
> +        bmdma_init(&s->bus[i], &s->bmdma[i], s);
> +        s->bmdma[i].bus = &s->bus[i];
> +        ide_register_restart_cb(&s->bus[i]);
> +    }
> +    qemu_register_reset(sii3112_reset, s);
> +}
> +
> +static void sii3112_pci_exitfn(PCIDevice *dev)
> +{
> +    PCIIDEState *d = PCI_IDE(dev);
> +    int i;
> +
> +    for (i = 0; i < 2; ++i) {
> +        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io);
> +        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport);
> +    }
> +}
> +
> +static void sii3112_pci_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    PCIDeviceClass *pd = PCI_DEVICE_CLASS(klass);
> +
> +    pd->vendor_id = 0x1095;
> +    pd->device_id = 0x3112;
> +    pd->class_id = PCI_CLASS_STORAGE_RAID;
> +    pd->revision = 1;
> +    pd->realize = sii3112_pci_realize;
> +    pd->exit = sii3112_pci_exitfn;
> +    dc->desc = "SiI3112A SATA controller";
> +    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
> +}
> +
> +static const TypeInfo sii3112_pci_info = {
> +    .name = TYPE_SII3112_PCI,
> +    .parent = TYPE_PCI_IDE,
> +    .instance_size = sizeof(SiI3112PCIState),
> +    .class_init = sii3112_pci_class_init,
> +};
> +
> +static void sii3112_register_types(void)
> +{
> +    type_register_static(&sii3112_pci_info);
> +}
> +
> +type_init(sii3112_register_types)

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 11/12] ppc4xx: Export ECB and PLB emulation
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 11/12] ppc4xx: Export ECB and PLB emulation BALATON Zoltan
@ 2017-08-14  4:44   ` David Gibson
  2017-08-14 11:06     ` BALATON Zoltan
  0 siblings, 1 reply; 49+ messages in thread
From: David Gibson @ 2017-08-14  4:44 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 3168 bytes --]

On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> These devices are found in some other ppc4xx cores too.

Elsewhere in the series you moved things that were used elsewhere out
of 405_uc, why not do that here as well?

> Also add some more PLB registers for 460EX.

Separate patch for that please, it's logically unrelated.  Plus the
commit message should say what these registers are, where they appear,
why do we need them?

> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>  hw/ppc/ppc405.h    |  3 +++
>  hw/ppc/ppc405_uc.c | 16 +++++++++++-----
>  2 files changed, 14 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
> index a9ffc87..7ed25cf 100644
> --- a/hw/ppc/ppc405.h
> +++ b/hw/ppc/ppc405.h
> @@ -59,6 +59,9 @@ struct ppc4xx_bd_info_t {
>  ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
>                                  uint32_t flags);
>  
> +void ppc4xx_plb_init(CPUPPCState *env);
> +void ppc405_ebc_init(CPUPPCState *env);
> +
>  CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
>                          MemoryRegion ram_memories[4],
>                          hwaddr ram_bases[4],
> diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
> index 8f44cb4..8e58065 100644
> --- a/hw/ppc/ppc405_uc.c
> +++ b/hw/ppc/ppc405_uc.c
> @@ -105,9 +105,12 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
>  /*****************************************************************************/
>  /* Peripheral local bus arbitrer */
>  enum {
> -    PLB0_BESR = 0x084,
> -    PLB0_BEAR = 0x086,
> -    PLB0_ACR  = 0x087,
> +    PLB3A0_ACR = 0x077,
> +    PLB4A0_ACR = 0x081,
> +    PLB0_BESR  = 0x084,
> +    PLB0_BEAR  = 0x086,
> +    PLB0_ACR   = 0x087,
> +    PLB4A1_ACR = 0x089,
>  };
>  
>  typedef struct ppc4xx_plb_t ppc4xx_plb_t;
> @@ -174,14 +177,17 @@ static void ppc4xx_plb_reset (void *opaque)
>      plb->besr = 0x00000000;
>  }
>  
> -static void ppc4xx_plb_init(CPUPPCState *env)
> +void ppc4xx_plb_init(CPUPPCState *env)
>  {
>      ppc4xx_plb_t *plb;
>  
>      plb = g_malloc0(sizeof(ppc4xx_plb_t));
> +    ppc_dcr_register(env, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
> +    ppc_dcr_register(env, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>      ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>      ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
>      ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
> +    ppc_dcr_register(env, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>      qemu_register_reset(ppc4xx_plb_reset, plb);
>  }
>  
> @@ -585,7 +591,7 @@ static void ebc_reset (void *opaque)
>      ebc->cfg = 0x80400000;
>  }
>  
> -static void ppc405_ebc_init(CPUPPCState *env)
> +void ppc405_ebc_init(CPUPPCState *env)
>  {
>      ppc4xx_ebc_t *ebc;
>  

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 05/12] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 05/12] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file BALATON Zoltan
  2017-08-14  4:41   ` David Gibson
@ 2017-08-14  9:00   ` Paolo Bonzini
  2017-08-14 11:18     ` BALATON Zoltan
  1 sibling, 1 reply; 49+ messages in thread
From: Paolo Bonzini @ 2017-08-14  9:00 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel, qemu-ppc
  Cc: Francois Revol, Alexander Graf, David Gibson

On 13/08/2017 19:04, BALATON Zoltan wrote:
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>  hw/ppc/Makefile.objs |   2 +-
>  hw/ppc/ppc405.h      |   2 +
>  hw/ppc/ppc405_uc.c   | 241 ---------------------------------------------
>  hw/ppc/ppc4xx_i2c.c  | 272 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 275 insertions(+), 242 deletions(-)
>  create mode 100644 hw/ppc/ppc4xx_i2c.c

Can you move it to hw/i2c while you're at it?

Paolo

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 11/12] ppc4xx: Export ECB and PLB emulation
  2017-08-14  4:44   ` David Gibson
@ 2017-08-14 11:06     ` BALATON Zoltan
  2017-08-18  6:11       ` David Gibson
  0 siblings, 1 reply; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-14 11:06 UTC (permalink / raw)
  To: David Gibson; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

On Mon, 14 Aug 2017, David Gibson wrote:
> On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
>> These devices are found in some other ppc4xx cores too.

Thanks for the quick review, hope more will follow for other patches 
too maybe also from others.

> Elsewhere in the series you moved things that were used elsewhere out
> of 405_uc, why not do that here as well?

I've moved those because those devices needed to be modified extensively 
while these two in this patch are used basically unchanged (they may not 
even be completely correct for 460EX but seem to work well enough) so I've 
left them here. I could add this explanation to the commit message or 
maybe move them to ppc4xx_devs to make it clearer that they are not only 
used by 405 emulation.

>> Also add some more PLB registers for 460EX.
>
> Separate patch for that please, it's logically unrelated.  Plus the
> commit message should say what these registers are, where they appear,
> why do we need them?

OK. I don't really know what these registers are. I guess we need them 
because U-Boot or other guests poke them but they are only added to avoid 
the crash, not really emulated (just read zero, ignore write) for now.

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 08/12] hw/ide: Emulate SiI3112 SATA controller
  2017-08-14  4:42   ` David Gibson
@ 2017-08-14 11:16     ` BALATON Zoltan
  2017-08-15 11:40       ` David Gibson
  0 siblings, 1 reply; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-14 11:16 UTC (permalink / raw)
  To: David Gibson; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

On Mon, 14 Aug 2017, David Gibson wrote:
> On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>
> Needs a commit message: where does this controller appear? what's
> distinctive about it? is there a link to a datasheet or programming manual?

This is just a generic PCI SATA controller, quite common and also used in 
PCs. Nothing special about it apart from guests running on Sam460ex 
usually have a driver for it (unlike other already emulated SATA 
controllers) and it is simpler to implement than the on board SATA 
controller of the 460EX and also has two ports instead of one so more 
useful to have.

I could add this as commit message if you think that would be better or 
just submit it separately through the IDE branch then use from these 
patch series.

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 05/12] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file
  2017-08-14  9:00   ` Paolo Bonzini
@ 2017-08-14 11:18     ` BALATON Zoltan
  2017-08-14 14:19       ` Paolo Bonzini
  2017-08-14 14:25       ` Peter Maydell
  0 siblings, 2 replies; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-14 11:18 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: qemu-devel, qemu-ppc, Francois Revol, Alexander Graf, David Gibson

On Mon, 14 Aug 2017, Paolo Bonzini wrote:
> On 13/08/2017 19:04, BALATON Zoltan wrote:
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>> ---
>>  hw/ppc/Makefile.objs |   2 +-
>>  hw/ppc/ppc405.h      |   2 +
>>  hw/ppc/ppc405_uc.c   | 241 ---------------------------------------------
>>  hw/ppc/ppc4xx_i2c.c  | 272 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 275 insertions(+), 242 deletions(-)
>>  create mode 100644 hw/ppc/ppc4xx_i2c.c
>
> Can you move it to hw/i2c while you're at it?

I could if that's the preferred way but I've left it in hw/ppc because 
this is not a generic device but specific to PPC SoCs and it was easier
to work with files in one dir than scattered through the tree. Should I 
still move it to hw/i2c?

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 05/12] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file
  2017-08-14 11:18     ` BALATON Zoltan
@ 2017-08-14 14:19       ` Paolo Bonzini
  2017-08-14 14:25       ` Peter Maydell
  1 sibling, 0 replies; 49+ messages in thread
From: Paolo Bonzini @ 2017-08-14 14:19 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, qemu-ppc, Francois Revol, Alexander Graf, David Gibson

On 14/08/2017 13:18, BALATON Zoltan wrote:
> On Mon, 14 Aug 2017, Paolo Bonzini wrote:
>> On 13/08/2017 19:04, BALATON Zoltan wrote:
>>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>>> ---
>>>  hw/ppc/Makefile.objs |   2 +-
>>>  hw/ppc/ppc405.h      |   2 +
>>>  hw/ppc/ppc405_uc.c   | 241
>>> ---------------------------------------------
>>>  hw/ppc/ppc4xx_i2c.c  | 272
>>> +++++++++++++++++++++++++++++++++++++++++++++++++++
>>>  4 files changed, 275 insertions(+), 242 deletions(-)
>>>  create mode 100644 hw/ppc/ppc4xx_i2c.c
>>
>> Can you move it to hw/i2c while you're at it?
> 
> I could if that's the preferred way but I've left it in hw/ppc because
> this is not a generic device but specific to PPC SoCs and it was easier
> to work with files in one dir than scattered through the tree. Should I
> still move it to hw/i2c?

Please do, having devices in hw/* helps when you do all-tree cleanups.

Paolo

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 05/12] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file
  2017-08-14 11:18     ` BALATON Zoltan
  2017-08-14 14:19       ` Paolo Bonzini
@ 2017-08-14 14:25       ` Peter Maydell
  1 sibling, 0 replies; 49+ messages in thread
From: Peter Maydell @ 2017-08-14 14:25 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: Paolo Bonzini, Francois Revol, qemu-ppc, QEMU Developers,
	David Gibson, Alexander Graf

On 14 August 2017 at 12:18, BALATON Zoltan <balaton@eik.bme.hu> wrote:
> On Mon, 14 Aug 2017, Paolo Bonzini wrote:
>> Can you move it to hw/i2c while you're at it?

> I could if that's the preferred way but I've left it in hw/ppc because this
> is not a generic device but specific to PPC SoCs and it was easier
> to work with files in one dir than scattered through the tree. Should I
> still move it to hw/i2c?

Yeah, when you have a device that's both "type X" and
"architecture Y" you can't put it both in hw/Y and hw/X,
and the choice we've made is that hw/$ARCH is for:
 * board models
 * SoC container objects which just instantiate other devices
and "leaf" devices go under the relevand hw/$CATEGORY
(which may be hw/misc if nothing more appropriate exists).
It's a little bit arbitrary, but it follows a similar practice
in the Linux kernel source tree layout.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 02/12] ppc4xx: Make MAL emulation more generic
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 02/12] ppc4xx: Make MAL emulation more generic BALATON Zoltan
@ 2017-08-15  4:11   ` David Gibson
  0 siblings, 0 replies; 49+ messages in thread
From: David Gibson @ 2017-08-15  4:11 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 9780 bytes --]

On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> Allow MAL with more RX and TX channels as found in newer versions.
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

Looks reasonable.

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

> ---
>  hw/ppc/ppc405_uc.c      |   2 +-
>  hw/ppc/ppc4xx_devs.c    | 171 +++++++++++++++++++-----------------------------
>  include/hw/ppc/ppc4xx.h |   3 +-
>  3 files changed, 70 insertions(+), 106 deletions(-)
> 
> diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
> index 3c74402..03856d5 100644
> --- a/hw/ppc/ppc405_uc.c
> +++ b/hw/ppc/ppc405_uc.c
> @@ -2281,7 +2281,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
>      mal_irqs[1] = pic[12];
>      mal_irqs[2] = pic[13];
>      mal_irqs[3] = pic[14];
> -    ppc405_mal_init(env, mal_irqs);
> +    ppc4xx_mal_init(env, 4, 2, mal_irqs);
>      /* Ethernet */
>      /* Uses pic[9], pic[15], pic[17] */
>      /* CPU control */
> diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
> index 8e4f78e..6e1cc09 100644
> --- a/hw/ppc/ppc4xx_devs.c
> +++ b/hw/ppc/ppc4xx_devs.c
> @@ -737,6 +737,7 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
>  
>  /*****************************************************************************/
>  /* MAL */
> +
>  enum {
>      MAL0_CFG      = 0x180,
>      MAL0_ESR      = 0x181,
> @@ -750,17 +751,13 @@ enum {
>      MAL0_RXEOBISR = 0x192,
>      MAL0_RXDEIR   = 0x193,
>      MAL0_TXCTP0R  = 0x1A0,
> -    MAL0_TXCTP1R  = 0x1A1,
> -    MAL0_TXCTP2R  = 0x1A2,
> -    MAL0_TXCTP3R  = 0x1A3,
>      MAL0_RXCTP0R  = 0x1C0,
> -    MAL0_RXCTP1R  = 0x1C1,
>      MAL0_RCBS0    = 0x1E0,
>      MAL0_RCBS1    = 0x1E1,
>  };
>  
> -typedef struct ppc40x_mal_t ppc40x_mal_t;
> -struct ppc40x_mal_t {
> +typedef struct ppc4xx_mal_t ppc4xx_mal_t;
> +struct ppc4xx_mal_t {
>      qemu_irq irqs[4];
>      uint32_t cfg;
>      uint32_t esr;
> @@ -773,16 +770,32 @@ struct ppc40x_mal_t {
>      uint32_t rxcarr;
>      uint32_t rxeobisr;
>      uint32_t rxdeir;
> -    uint32_t txctpr[4];
> -    uint32_t rxctpr[2];
> -    uint32_t rcbs[2];
> +    uint32_t *txctpr;
> +    uint32_t *rxctpr;
> +    uint32_t *rcbs;
> +    uint8_t  txcnum;
> +    uint8_t  rxcnum;
>  };
>  
> -static void ppc40x_mal_reset(void *opaque);
> +static void ppc4xx_mal_reset(void *opaque)
> +{
> +    ppc4xx_mal_t *mal;
> +
> +    mal = opaque;
> +    mal->cfg = 0x0007C000;
> +    mal->esr = 0x00000000;
> +    mal->ier = 0x00000000;
> +    mal->rxcasr = 0x00000000;
> +    mal->rxdeir = 0x00000000;
> +    mal->rxeobisr = 0x00000000;
> +    mal->txcasr = 0x00000000;
> +    mal->txdeir = 0x00000000;
> +    mal->txeobisr = 0x00000000;
> +}
>  
>  static uint32_t dcr_read_mal(void *opaque, int dcrn)
>  {
> -    ppc40x_mal_t *mal;
> +    ppc4xx_mal_t *mal;
>      uint32_t ret;
>  
>      mal = opaque;
> @@ -820,48 +833,32 @@ static uint32_t dcr_read_mal(void *opaque, int dcrn)
>      case MAL0_RXDEIR:
>          ret = mal->rxdeir;
>          break;
> -    case MAL0_TXCTP0R:
> -        ret = mal->txctpr[0];
> -        break;
> -    case MAL0_TXCTP1R:
> -        ret = mal->txctpr[1];
> -        break;
> -    case MAL0_TXCTP2R:
> -        ret = mal->txctpr[2];
> -        break;
> -    case MAL0_TXCTP3R:
> -        ret = mal->txctpr[3];
> -        break;
> -    case MAL0_RXCTP0R:
> -        ret = mal->rxctpr[0];
> -        break;
> -    case MAL0_RXCTP1R:
> -        ret = mal->rxctpr[1];
> -        break;
> -    case MAL0_RCBS0:
> -        ret = mal->rcbs[0];
> -        break;
> -    case MAL0_RCBS1:
> -        ret = mal->rcbs[1];
> -        break;
>      default:
>          ret = 0;
>          break;
>      }
> +    if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
> +        ret = mal->txctpr[dcrn - MAL0_TXCTP0R];
> +    }
> +    if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
> +        ret = mal->rxctpr[dcrn - MAL0_RXCTP0R];
> +    }
> +    if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
> +        ret = mal->rcbs[dcrn - MAL0_RCBS0];
> +    }
>  
>      return ret;
>  }
>  
>  static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
>  {
> -    ppc40x_mal_t *mal;
> -    int idx;
> +    ppc4xx_mal_t *mal;
>  
>      mal = opaque;
>      switch (dcrn) {
>      case MAL0_CFG:
>          if (val & 0x80000000) {
> -            ppc40x_mal_reset(mal);
> +            ppc4xx_mal_reset(mal);
>          }
>          mal->cfg = val & 0x00FFC087;
>          break;
> @@ -900,65 +897,35 @@ static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
>          /* Read/clear */
>          mal->rxdeir &= ~val;
>          break;
> -    case MAL0_TXCTP0R:
> -        idx = 0;
> -        goto update_tx_ptr;
> -    case MAL0_TXCTP1R:
> -        idx = 1;
> -        goto update_tx_ptr;
> -    case MAL0_TXCTP2R:
> -        idx = 2;
> -        goto update_tx_ptr;
> -    case MAL0_TXCTP3R:
> -        idx = 3;
> -    update_tx_ptr:
> -        mal->txctpr[idx] = val;
> -        break;
> -    case MAL0_RXCTP0R:
> -        idx = 0;
> -        goto update_rx_ptr;
> -    case MAL0_RXCTP1R:
> -        idx = 1;
> -    update_rx_ptr:
> -        mal->rxctpr[idx] = val;
> -        break;
> -    case MAL0_RCBS0:
> -        idx = 0;
> -        goto update_rx_size;
> -    case MAL0_RCBS1:
> -        idx = 1;
> -    update_rx_size:
> -        mal->rcbs[idx] = val & 0x000000FF;
> -        break;
> +    }
> +    if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
> +        mal->txctpr[dcrn - MAL0_TXCTP0R] = val;
> +    }
> +    if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
> +        mal->rxctpr[dcrn - MAL0_RXCTP0R] = val;
> +    }
> +    if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
> +        mal->rcbs[dcrn - MAL0_RCBS0] = val & 0x000000FF;
>      }
>  }
>  
> -static void ppc40x_mal_reset(void *opaque)
> -{
> -    ppc40x_mal_t *mal;
> -
> -    mal = opaque;
> -    mal->cfg = 0x0007C000;
> -    mal->esr = 0x00000000;
> -    mal->ier = 0x00000000;
> -    mal->rxcasr = 0x00000000;
> -    mal->rxdeir = 0x00000000;
> -    mal->rxeobisr = 0x00000000;
> -    mal->txcasr = 0x00000000;
> -    mal->txdeir = 0x00000000;
> -    mal->txeobisr = 0x00000000;
> -}
> -
> -void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
> +void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
> +                     qemu_irq irqs[4])
>  {
> -    ppc40x_mal_t *mal;
> +    ppc4xx_mal_t *mal;
>      int i;
>  
> -    mal = g_malloc0(sizeof(ppc40x_mal_t));
> +    assert(txcnum <= 32 && rxcnum <= 32);
> +    mal = g_malloc0(sizeof(*mal));
> +    mal->txcnum = txcnum;
> +    mal->rxcnum = rxcnum;
> +    mal->txctpr = g_new0(uint32_t, txcnum);
> +    mal->rxctpr = g_new0(uint32_t, rxcnum);
> +    mal->rcbs = g_new0(uint32_t, rxcnum);
>      for (i = 0; i < 4; i++) {
>          mal->irqs[i] = irqs[i];
>      }
> -    qemu_register_reset(&ppc40x_mal_reset, mal);
> +    qemu_register_reset(&ppc4xx_mal_reset, mal);
>      ppc_dcr_register(env, MAL0_CFG,
>                       mal, &dcr_read_mal, &dcr_write_mal);
>      ppc_dcr_register(env, MAL0_ESR,
> @@ -981,20 +948,16 @@ void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
>                       mal, &dcr_read_mal, &dcr_write_mal);
>      ppc_dcr_register(env, MAL0_RXDEIR,
>                       mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXCTP0R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXCTP1R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXCTP2R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXCTP3R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RXCTP0R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RXCTP1R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RCBS0,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RCBS1,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> +    for (i = 0; i < txcnum; i++) {
> +        ppc_dcr_register(env, MAL0_TXCTP0R + i,
> +                         mal, &dcr_read_mal, &dcr_write_mal);
> +    }
> +    for (i = 0; i < rxcnum; i++) {
> +        ppc_dcr_register(env, MAL0_RXCTP0R + i,
> +                         mal, &dcr_read_mal, &dcr_write_mal);
> +    }
> +    for (i = 0; i < rxcnum; i++) {
> +        ppc_dcr_register(env, MAL0_RCBS0 + i,
> +                         mal, &dcr_read_mal, &dcr_write_mal);
> +    }
>  }
> diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
> index db50cfa..cb0bb55 100644
> --- a/include/hw/ppc/ppc4xx.h
> +++ b/include/hw/ppc/ppc4xx.h
> @@ -53,7 +53,8 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
>                          hwaddr *ram_sizes,
>                          int do_init);
>  
> -void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4]);
> +void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
> +                     qemu_irq irqs[4]);
>  
>  #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"
>  

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 03/12] ohci: Allow sysbus version to be used as a companion
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 03/12] ohci: Allow sysbus version to be used as a companion BALATON Zoltan
@ 2017-08-15  4:13   ` David Gibson
  0 siblings, 0 replies; 49+ messages in thread
From: David Gibson @ 2017-08-15  4:13 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 2183 bytes --]

On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:

Wants a commit message - why do you need this functionality.

Patch itself looks fine to me, but you should probably CC Gerd
<kraxel@redhat.com> for review.

> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>  hw/usb/hcd-ohci.c | 15 ++++++++++++---
>  1 file changed, 12 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
> index 267982e..17beedd 100644
> --- a/hw/usb/hcd-ohci.c
> +++ b/hw/usb/hcd-ohci.c
> @@ -1999,7 +1999,9 @@ typedef struct {
>      /*< public >*/
>  
>      OHCIState ohci;
> +    char *masterbus;
>      uint32_t num_ports;
> +    uint32_t firstport;
>      dma_addr_t dma_offset;
>  } OHCISysBusState;
>  
> @@ -2007,10 +2009,15 @@ static void ohci_realize_pxa(DeviceState *dev, Error **errp)
>  {
>      OHCISysBusState *s = SYSBUS_OHCI(dev);
>      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +    Error *err = NULL;
>  
> -    /* Cannot fail as we pass NULL for masterbus */
> -    usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, NULL, 0,
> -                  &address_space_memory, &error_abort);
> +    usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset,
> +                  s->masterbus, s->firstport,
> +                  &address_space_memory, &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
>      sysbus_init_irq(sbd, &s->ohci.irq);
>      sysbus_init_mmio(sbd, &s->ohci.mem);
>  }
> @@ -2142,7 +2149,9 @@ static const TypeInfo ohci_pci_info = {
>  };
>  
>  static Property ohci_sysbus_properties[] = {
> +    DEFINE_PROP_STRING("masterbus", OHCISysBusState, masterbus),
>      DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
> +    DEFINE_PROP_UINT32("firstport", OHCISysBusState, firstport, 0),
>      DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 0),
>      DEFINE_PROP_END_OF_LIST(),
>  };

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 06/12] ppc4xx_i2c: QOMify
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 06/12] ppc4xx_i2c: QOMify BALATON Zoltan
@ 2017-08-15  4:17   ` David Gibson
  0 siblings, 0 replies; 49+ messages in thread
From: David Gibson @ 2017-08-15  4:17 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 11637 bytes --]

On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

Mostly good, one niggle below.

> ---
>  hw/ppc/ppc405.h             |   2 -
>  hw/ppc/ppc405_uc.c          |   5 +-
>  hw/ppc/ppc4xx_i2c.c         | 153 +++++++++++++++++---------------------------
>  include/hw/i2c/ppc4xx_i2c.h |  59 +++++++++++++++++
>  4 files changed, 121 insertions(+), 98 deletions(-)
>  create mode 100644 include/hw/i2c/ppc4xx_i2c.h
> 
> diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
> index 61ec739..a9ffc87 100644
> --- a/hw/ppc/ppc405.h
> +++ b/hw/ppc/ppc405.h
> @@ -59,8 +59,6 @@ struct ppc4xx_bd_info_t {
>  ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
>                                  uint32_t flags);
>  
> -void ppc405_i2c_init(hwaddr base, qemu_irq irq);
> -
>  CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
>                          MemoryRegion ram_memories[4],
>                          hwaddr ram_bases[4],
> diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
> index 3925e4c..8f44cb4 100644
> --- a/hw/ppc/ppc405_uc.c
> +++ b/hw/ppc/ppc405_uc.c
> @@ -28,6 +28,7 @@
>  #include "hw/hw.h"
>  #include "hw/ppc/ppc.h"
>  #include "hw/boards.h"
> +#include "hw/i2c/ppc4xx_i2c.h"
>  #include "ppc405.h"
>  #include "hw/char/serial.h"
>  #include "qemu/timer.h"
> @@ -1663,7 +1664,7 @@ CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
>                         DEVICE_BIG_ENDIAN);
>      }
>      /* IIC controller */
> -    ppc405_i2c_init(0xef600500, pic[2]);
> +    sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, pic[2]);
>      /* GPIO */
>      ppc405_gpio_init(0xef600700);
>      /* CPU control */
> @@ -2010,7 +2011,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
>      dma_irqs[3] = pic[8];
>      ppc405_dma_init(env, dma_irqs);
>      /* IIC controller */
> -    ppc405_i2c_init(0xef600500, pic[2]);
> +    sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, pic[2]);
>      /* GPIO */
>      ppc405_gpio_init(0xef600700);
>      /* Serial ports */
> diff --git a/hw/ppc/ppc4xx_i2c.c b/hw/ppc/ppc4xx_i2c.c
> index 15f2dea..fafbb34 100644
> --- a/hw/ppc/ppc4xx_i2c.c
> +++ b/hw/ppc/ppc4xx_i2c.c
> @@ -27,42 +27,19 @@
>  #include "qemu-common.h"
>  #include "cpu.h"
>  #include "hw/hw.h"
> -#include "exec/address-spaces.h"
> -#include "hw/ppc/ppc.h"
> -#include "ppc405.h"
> +#include "hw/i2c/ppc4xx_i2c.h"
>  
>  /*#define DEBUG_I2C*/
>  
> -typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
> -struct ppc4xx_i2c_t {
> -    qemu_irq irq;
> -    MemoryRegion iomem;
> -    uint8_t mdata;
> -    uint8_t lmadr;
> -    uint8_t hmadr;
> -    uint8_t cntl;
> -    uint8_t mdcntl;
> -    uint8_t sts;
> -    uint8_t extsts;
> -    uint8_t sdata;
> -    uint8_t lsadr;
> -    uint8_t hsadr;
> -    uint8_t clkdiv;
> -    uint8_t intrmsk;
> -    uint8_t xfrcnt;
> -    uint8_t xtcntlss;
> -    uint8_t directcntl;
> -};
> +#define PPC4xx_I2C_MEM_SIZE 0x11
>  
> -static uint32_t ppc4xx_i2c_readb(void *opaque, hwaddr addr)
> +static uint8_t ppc4xx_i2c_readb(PPC4xxI2CState *i2c, hwaddr addr)
>  {
> -    ppc4xx_i2c_t *i2c;
> -    uint32_t ret;
> +    uint8_t ret;
>  
>  #ifdef DEBUG_I2C
>      printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
>  #endif
> -    i2c = opaque;
>      switch (addr) {
>      case 0x00:
>          /*i2c_readbyte(&i2c->mdata);*/
> @@ -121,16 +98,12 @@ static uint32_t ppc4xx_i2c_readb(void *opaque, hwaddr addr)
>      return ret;
>  }
>  
> -static void ppc4xx_i2c_writeb(void *opaque,
> -                              hwaddr addr, uint32_t value)
> +static void ppc4xx_i2c_writeb(PPC4xxI2CState *i2c, hwaddr addr, uint8_t value)
>  {
> -    ppc4xx_i2c_t *i2c;
> -
>  #ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
> -           value);
> +    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n",
> +           __func__, addr, value);
>  #endif
> -    i2c = opaque;
>      switch (addr) {
>      case 0x00:
>          i2c->mdata = value;
> @@ -181,71 +154,44 @@ static void ppc4xx_i2c_writeb(void *opaque,
>      }
>  }
>  
> -static uint32_t ppc4xx_i2c_readw(void *opaque, hwaddr addr)
> +static uint64_t ppc4xx_i2c_read(void *opaque, hwaddr addr, unsigned int size)
>  {
> -    uint32_t ret;
> +    PPC4xxI2CState *s = PPC4xx_I2C(opaque);
> +    int i;
> +    uint64_t ret = 0;
>  
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
> -#endif
> -    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
> -    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
> +    for (i = 0; i < size; i++) {
> +        ret <<= 8;
> +        ret |= ppc4xx_i2c_readb(s, addr + i);
> +    }

You shouldn't need to implement your own multibyte accessors in terms
of the byte accessors..

>  
>      return ret;
>  }
>  
> -static void ppc4xx_i2c_writew(void *opaque,
> -                              hwaddr addr, uint32_t value)
> +static void ppc4xx_i2c_write(void *opaque, hwaddr addr, uint64_t value,
> +                             unsigned int size)
>  {
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
> -           value);
> -#endif
> -    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
> -    ppc4xx_i2c_writeb(opaque, addr + 1, value);
> -}
> -
> -static uint32_t ppc4xx_i2c_readl(void *opaque, hwaddr addr)
> -{
> -    uint32_t ret;
> -
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
> -#endif
> -    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
> -    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
> -    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
> -    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
> -
> -    return ret;
> -}
> +    PPC4xxI2CState *s = PPC4xx_I2C(opaque);
> +    int i;
>  
> -static void ppc4xx_i2c_writel(void *opaque,
> -                              hwaddr addr, uint32_t value)
> -{
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
> -           value);
> -#endif
> -    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
> -    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
> -    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
> -    ppc4xx_i2c_writeb(opaque, addr + 3, value);
> +    for (i = 0; i < size; i++) {
> +        ppc4xx_i2c_writeb(s, addr + i, value & 0xff);
> +        value >>= 8;
> +    }
>  }
>  
> -static const MemoryRegionOps i2c_ops = {
> -    .old_mmio = {
> -        .read = { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, },
> -        .write = { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writel, },
> -    },
> +static const MemoryRegionOps ppc4xx_i2c_ops = {
> +    .read = ppc4xx_i2c_read,
> +    .write = ppc4xx_i2c_write,
> +    .valid.min_access_size = 1,
> +    .valid.max_access_size = 4,

.. instead you should be able to set .valid.* to one thing and .impl.*
to just 1,1 and the memory acces core should break up the accesses
into bytes for you.

>      .endianness = DEVICE_NATIVE_ENDIAN,
>  };
>  
> -static void ppc4xx_i2c_reset(void *opaque)
> +static void ppc4xx_i2c_reset(DeviceState *s)
>  {
> -    ppc4xx_i2c_t *i2c;
> +    PPC4xxI2CState *i2c = PPC4xx_I2C(s);
>  
> -    i2c = opaque;
>      i2c->mdata = 0x00;
>      i2c->sdata = 0x00;
>      i2c->cntl = 0x00;
> @@ -257,16 +203,35 @@ static void ppc4xx_i2c_reset(void *opaque)
>      i2c->directcntl = 0x0F;
>  }
>  
> -void ppc405_i2c_init(hwaddr base, qemu_irq irq)
> +static void ppc4xx_i2c_init(Object *o)
>  {
> -    ppc4xx_i2c_t *i2c;
> +    PPC4xxI2CState *s = PPC4xx_I2C(o);
>  
> -    i2c = g_malloc0(sizeof(ppc4xx_i2c_t));
> -    i2c->irq = irq;
> -#ifdef DEBUG_I2C
> -    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
> -#endif
> -    memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011);
> -    memory_region_add_subregion(get_system_memory(), base, &i2c->iomem);
> -    qemu_register_reset(ppc4xx_i2c_reset, i2c);
> +    memory_region_init_io(&s->iomem, OBJECT(s), &ppc4xx_i2c_ops, s,
> +                          TYPE_PPC4xx_I2C, PPC4xx_I2C_MEM_SIZE);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
> +    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
> +    s->bus = i2c_init_bus(DEVICE(s), "i2c");
>  }
> +
> +static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->reset = ppc4xx_i2c_reset;
> +}
> +
> +static const TypeInfo ppc4xx_i2c_type_info = {
> +    .name = TYPE_PPC4xx_I2C,
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(PPC4xxI2CState),
> +    .instance_init = ppc4xx_i2c_init,
> +    .class_init = ppc4xx_i2c_class_init,
> +};
> +
> +static void ppc4xx_i2c_register_types(void)
> +{
> +    type_register_static(&ppc4xx_i2c_type_info);
> +}
> +
> +type_init(ppc4xx_i2c_register_types)
> diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h
> new file mode 100644
> index 0000000..7f1e6be
> --- /dev/null
> +++ b/include/hw/i2c/ppc4xx_i2c.h
> @@ -0,0 +1,59 @@
> +/*
> + * PPC4xx I2C controller emulation
> + *
> + * Copyright (c) 2007 Jocelyn Mayer
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#ifndef PPC4XX_I2C_H
> +#define PPC4XX_I2C_H
> +
> +#include "qemu/osdep.h"
> +#include "qemu-common.h"
> +#include "hw/sysbus.h"
> +
> +#define TYPE_PPC4xx_I2C "ppc4xx-i2c"
> +#define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2C)
> +
> +typedef struct PPC4xxI2CState {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +
> +    /*< public >*/
> +    qemu_irq irq;
> +    MemoryRegion iomem;
> +    uint8_t mdata;
> +    uint8_t lmadr;
> +    uint8_t hmadr;
> +    uint8_t cntl;
> +    uint8_t mdcntl;
> +    uint8_t sts;
> +    uint8_t extsts;
> +    uint8_t sdata;
> +    uint8_t lsadr;
> +    uint8_t hsadr;
> +    uint8_t clkdiv;
> +    uint8_t intrmsk;
> +    uint8_t xfrcnt;
> +    uint8_t xtcntlss;
> +    uint8_t directcntl;
> +} PPC4xxI2CState;
> +
> +#endif /* PPC4XX_I2C_H */

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 08/12] hw/ide: Emulate SiI3112 SATA controller
  2017-08-14 11:16     ` BALATON Zoltan
@ 2017-08-15 11:40       ` David Gibson
  0 siblings, 0 replies; 49+ messages in thread
From: David Gibson @ 2017-08-15 11:40 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 1236 bytes --]

On Mon, Aug 14, 2017 at 01:16:13PM +0200, BALATON Zoltan wrote:
> On Mon, 14 Aug 2017, David Gibson wrote:
> > On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> > > Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> > 
> > Needs a commit message: where does this controller appear? what's
> > distinctive about it? is there a link to a datasheet or programming manual?
> 
> This is just a generic PCI SATA controller, quite common and also used in
> PCs. Nothing special about it apart from guests running on Sam460ex usually
> have a driver for it (unlike other already emulated SATA controllers) and it
> is simpler to implement than the on board SATA controller of the 460EX and
> also has two ports instead of one so more useful to have.
> 
> I could add this as commit message if you think that would be better or just
> submit it separately through the IDE branch then use from these patch
> series.

Please do add that as a commit message.  We probably should get an ack
from Jon Snow for this.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 07/12] ppc4xx_i2c: Implement basic I2C functions
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 07/12] ppc4xx_i2c: Implement basic I2C functions BALATON Zoltan
@ 2017-08-18  1:42   ` David Gibson
  0 siblings, 0 replies; 49+ messages in thread
From: David Gibson @ 2017-08-18  1:42 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 13483 bytes --]

On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> Enough to please U-Boot and make it able to detect SDRAM SPD EEPROMs
> 
> Signed-off-by: François Revol <revol@free.fr>
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

I don't have the knowledge to review this deeply (or, rather, I don't
have the time to refresh myself on the 4xx manuals).  However there's
nothing obviously bogus, and what we had previously was clearly a
stub.  So I'll be happy to apply this for 2.11 if no-one with better
knowledge objects.

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

> ---
>  hw/ppc/ppc4xx_i2c.c         | 214 +++++++++++++++++++++++++++++++++++++-------
>  include/hw/i2c/ppc4xx_i2c.h |   5 ++
>  2 files changed, 189 insertions(+), 30 deletions(-)
> 
> diff --git a/hw/ppc/ppc4xx_i2c.c b/hw/ppc/ppc4xx_i2c.c
> index fafbb34..0b088e6 100644
> --- a/hw/ppc/ppc4xx_i2c.c
> +++ b/hw/ppc/ppc4xx_i2c.c
> @@ -2,6 +2,8 @@
>   * PPC4xx I2C controller emulation
>   *
>   * Copyright (c) 2007 Jocelyn Mayer
> + * Copyright (c) 2012 François Revol
> + * Copyright (c) 2016 BALATON Zoltan
>   *
>   * Permission is hereby granted, free of charge, to any person obtaining a copy
>   * of this software and associated documentation files (the "Software"), to deal
> @@ -25,25 +27,126 @@
>  #include "qemu/osdep.h"
>  #include "qapi/error.h"
>  #include "qemu-common.h"
> +#include "qemu/log.h"
>  #include "cpu.h"
>  #include "hw/hw.h"
>  #include "hw/i2c/ppc4xx_i2c.h"
>  
>  /*#define DEBUG_I2C*/
>  
> -#define PPC4xx_I2C_MEM_SIZE 0x11
> +#ifdef DEBUG_I2C
> +#define DPRINTF(fmt, args...) printf("[%s]%s: " fmt, TYPE_PPC4xx_I2C, \
> +                                     __func__, ##args);
> +#else
> +#define DPRINTF(fmt, args...)
> +#endif
> +
> +#define PPC4xx_I2C_MEM_SIZE 0x12
> +
> +#define IIC_CNTL_PT         (1 << 0)
> +#define IIC_CNTL_READ       (1 << 1)
> +#define IIC_CNTL_CHT        (1 << 2)
> +#define IIC_CNTL_RPST       (1 << 3)
> +
> +#define IIC_STS_PT          (1 << 0)
> +#define IIC_STS_ERR         (1 << 2)
> +#define IIC_STS_MDBS        (1 << 5)
> +
> +#define IIC_EXTSTS_XFRA     (1 << 0)
> +
> +#define IIC_XTCNTLSS_SRST   (1 << 0)
> +
> +static void ppc4xx_i2c_reset(DeviceState *s)
> +{
> +    PPC4xxI2CState *i2c = PPC4xx_I2C(s);
> +
> +    /* FIXME: Should also reset bus?
> +     *if (s->address != ADDR_RESET) {
> +     *    i2c_end_transfer(s->bus);
> +     *}
> +     */
> +
> +    i2c->mdata = 0;
> +    i2c->lmadr = 0;
> +    i2c->hmadr = 0;
> +    i2c->cntl = 0;
> +    i2c->mdcntl = 0;
> +    i2c->sts = 0;
> +    i2c->extsts = 0x8f;
> +    i2c->sdata = 0;
> +    i2c->lsadr = 0;
> +    i2c->hsadr = 0;
> +    i2c->clkdiv = 0;
> +    i2c->intrmsk = 0;
> +    i2c->xfrcnt = 0;
> +    i2c->xtcntlss = 0;
> +    i2c->directcntl = 0x0f;
> +    i2c->intr = 0;
> +}
> +
> +static inline bool ppc4xx_i2c_is_master(PPC4xxI2CState *i2c)
> +{
> +    return true;
> +}
>  
>  static uint8_t ppc4xx_i2c_readb(PPC4xxI2CState *i2c, hwaddr addr)
>  {
> -    uint8_t ret;
> +    int ret;
>  
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
> -#endif
>      switch (addr) {
>      case 0x00:
> -        /*i2c_readbyte(&i2c->mdata);*/
>          ret = i2c->mdata;
> +        if (ppc4xx_i2c_is_master(i2c)) {
> +            ret = 0xff;
> +
> +            if (!(i2c->sts & IIC_STS_MDBS)) {
> +                qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read "
> +                              "without starting transfer\n",
> +                              TYPE_PPC4xx_I2C, __func__);
> +            } else {
> +                int pending = (i2c->cntl >> 4) & 3;
> +
> +                /* get the next byte */
> +                ret = i2c_recv(i2c->bus);
> +                DPRINTF("received byte %04x\n", ret);
> +
> +                if (ret < 0) {
> +                    qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: read failed "
> +                                  "for device 0x%02x\n", TYPE_PPC4xx_I2C,
> +                                  __func__, i2c->lmadr);
> +                    ret = 0xff;
> +                } else {
> +                    /* Raise interrupt if enabled */
> +                    /*ppc4xx_i2c_raise_interrupt(i2c)*/;
> +                }
> +
> +                if (!pending) {
> +                    i2c->sts &= ~IIC_STS_MDBS;
> +                    /*i2c_end_transfer(i2c->bus);*/
> +                /*} else if (i2c->cntl & (IIC_CNTL_RPST | IIC_CNTL_CHT)) {*/
> +                } else if (pending) {
> +                    /* current smbus implementation doesn't like
> +                       multibyte xfer repeated start */
> +                    i2c_end_transfer(i2c->bus);
> +                    if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 1)) {
> +                        /* if non zero is returned, the adress is not valid */
> +                        i2c->sts &= ~IIC_STS_PT;
> +                        i2c->sts |= IIC_STS_ERR;
> +                        i2c->extsts |= IIC_EXTSTS_XFRA;
> +                    } else {
> +                        /*i2c->sts |= IIC_STS_PT;*/
> +                        i2c->sts |= IIC_STS_MDBS;
> +                        i2c->sts &= ~IIC_STS_ERR;
> +                        i2c->extsts = 0;
> +                    }
> +                }
> +                pending--;
> +                i2c->cntl = (i2c->cntl & 0xcf) | (pending << 4);
> +            }
> +        } else {
> +            qemu_log_mask(LOG_UNIMP, "[%s]%s: slave mode not implemented\n",
> +                          TYPE_PPC4xx_I2C, __func__);
> +        }
>          break;
>      case 0x02:
>          ret = i2c->sdata;
> @@ -87,39 +190,88 @@ static uint8_t ppc4xx_i2c_readb(PPC4xxI2CState *i2c, hwaddr addr)
>      case 0x10:
>          ret = i2c->directcntl;
>          break;
> +    case 0x11:
> +        ret = i2c->intr;
> +        break;
>      default:
> -        ret = 0x00;
> +        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
> +                      HWADDR_PRIx "\n", TYPE_PPC4xx_I2C, __func__, addr);
> +        ret = 0;
>          break;
>      }
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, ret);
> -#endif
>  
>      return ret;
>  }
>  
>  static void ppc4xx_i2c_writeb(PPC4xxI2CState *i2c, hwaddr addr, uint8_t value)
>  {
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n",
> -           __func__, addr, value);
> -#endif
>      switch (addr) {
>      case 0x00:
>          i2c->mdata = value;
> -        /*i2c_sendbyte(&i2c->mdata);*/
> +        if (!i2c_bus_busy(i2c->bus)) {
> +            /* assume we start a write transfer */
> +            if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 0)) {
> +                /* if non zero is returned, the adress is not valid */
> +                i2c->sts &= ~IIC_STS_PT;
> +                i2c->sts |= IIC_STS_ERR;
> +                i2c->extsts |= IIC_EXTSTS_XFRA;
> +            } else {
> +                i2c->sts |= IIC_STS_PT;
> +                i2c->sts &= ~IIC_STS_ERR;
> +                i2c->extsts = 0;
> +            }
> +        }
> +        if (i2c_bus_busy(i2c->bus)) {
> +            DPRINTF("sending byte %02x\n", i2c->mdata);
> +            if (i2c_send(i2c->bus, i2c->mdata)) {
> +                /* if the target return non zero then end the transfer */
> +                i2c->sts &= ~IIC_STS_PT;
> +                i2c->sts |= IIC_STS_ERR;
> +                i2c->extsts |= IIC_EXTSTS_XFRA;
> +                i2c_end_transfer(i2c->bus);
> +            }
> +        }
>          break;
>      case 0x02:
>          i2c->sdata = value;
>          break;
>      case 0x04:
>          i2c->lmadr = value;
> +        if (i2c_bus_busy(i2c->bus)) {
> +            i2c_end_transfer(i2c->bus);
> +        }
> +        DPRINTF("%s: device addr %02x\n", __func__, i2c->lmadr);
>          break;
>      case 0x05:
>          i2c->hmadr = value;
>          break;
>      case 0x06:
>          i2c->cntl = value;
> +        if (i2c->cntl & IIC_CNTL_PT) {
> +            if (i2c->cntl & IIC_CNTL_READ) {
> +                DPRINTF("read xfer %d\n", ((i2c->cntl >> 4) & 3) + 1);
> +                if (i2c_bus_busy(i2c->bus)) {
> +                    /* end previous transfer */
> +                    i2c->sts &= ~IIC_STS_PT;
> +                    i2c_end_transfer(i2c->bus);
> +                }
> +                if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 1)) {
> +                    /* if non zero is returned, the adress is not valid */
> +                    i2c->sts &= ~IIC_STS_PT;
> +                    i2c->sts |= IIC_STS_ERR;
> +                    i2c->extsts |= IIC_EXTSTS_XFRA;
> +                } else {
> +                    /*i2c->sts |= IIC_STS_PT;*/
> +                    i2c->sts |= IIC_STS_MDBS;
> +                    i2c->sts &= ~IIC_STS_ERR;
> +                    i2c->extsts = 0;
> +                }
> +            } else {
> +                DPRINTF("write xfer %d\n", ((i2c->cntl >> 4) & 3) + 1);
> +                /* we actually already did the write transfer... */
> +                i2c->sts &= ~IIC_STS_PT;
> +            }
> +        }
>          break;
>      case 0x07:
>          i2c->mdcntl = value & 0xDF;
> @@ -132,6 +284,7 @@ static void ppc4xx_i2c_writeb(PPC4xxI2CState *i2c, hwaddr addr, uint8_t value)
>          break;
>      case 0x0A:
>          i2c->lsadr = value;
> +        /*i2c_set_slave_address(i2c->bus, i2c->lsadr);*/
>          break;
>      case 0x0B:
>          i2c->hsadr = value;
> @@ -146,11 +299,23 @@ static void ppc4xx_i2c_writeb(PPC4xxI2CState *i2c, hwaddr addr, uint8_t value)
>          i2c->xfrcnt = value & 0x77;
>          break;
>      case 0x0F:
> +        if (value & IIC_XTCNTLSS_SRST) {
> +            /* Is it actually a full reset? U-Boot sets some regs before */
> +            ppc4xx_i2c_reset(DEVICE(i2c));
> +            break;
> +        }
>          i2c->xtcntlss = value;
>          break;
>      case 0x10:
>          i2c->directcntl = value & 0x7;
>          break;
> +    case 0x11:
> +        i2c->intr = value;
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
> +                      HWADDR_PRIx "\n", TYPE_PPC4xx_I2C, __func__, addr);
> +        break;
>      }
>  }
>  
> @@ -160,10 +325,12 @@ static uint64_t ppc4xx_i2c_read(void *opaque, hwaddr addr, unsigned int size)
>      int i;
>      uint64_t ret = 0;
>  
> +    DPRINTF("read I2C " TARGET_FMT_plx " size %u\n", addr, size);
>      for (i = 0; i < size; i++) {
>          ret <<= 8;
>          ret |= ppc4xx_i2c_readb(s, addr + i);
>      }
> +    DPRINTF("read I2C " TARGET_FMT_plx " %02" PRIx64 "\n", addr, ret);
>  
>      return ret;
>  }
> @@ -174,6 +341,8 @@ static void ppc4xx_i2c_write(void *opaque, hwaddr addr, uint64_t value,
>      PPC4xxI2CState *s = PPC4xx_I2C(opaque);
>      int i;
>  
> +    DPRINTF("write I2C " TARGET_FMT_plx " size %u val %08" PRIx64 "\n",
> +            addr, size, value);
>      for (i = 0; i < size; i++) {
>          ppc4xx_i2c_writeb(s, addr + i, value & 0xff);
>          value >>= 8;
> @@ -188,21 +357,6 @@ static const MemoryRegionOps ppc4xx_i2c_ops = {
>      .endianness = DEVICE_NATIVE_ENDIAN,
>  };
>  
> -static void ppc4xx_i2c_reset(DeviceState *s)
> -{
> -    PPC4xxI2CState *i2c = PPC4xx_I2C(s);
> -
> -    i2c->mdata = 0x00;
> -    i2c->sdata = 0x00;
> -    i2c->cntl = 0x00;
> -    i2c->mdcntl = 0x00;
> -    i2c->sts = 0x00;
> -    i2c->extsts = 0x00;
> -    i2c->clkdiv = 0x00;
> -    i2c->xfrcnt = 0x00;
> -    i2c->directcntl = 0x0F;
> -}
> -
>  static void ppc4xx_i2c_init(Object *o)
>  {
>      PPC4xxI2CState *s = PPC4xx_I2C(o);
> diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h
> index 7f1e6be..71fb392 100644
> --- a/include/hw/i2c/ppc4xx_i2c.h
> +++ b/include/hw/i2c/ppc4xx_i2c.h
> @@ -2,6 +2,8 @@
>   * PPC4xx I2C controller emulation
>   *
>   * Copyright (c) 2007 Jocelyn Mayer
> + * Copyright (c) 2012 François Revol
> + * Copyright (c) 2016 BALATON Zoltan
>   *
>   * Permission is hereby granted, free of charge, to any person obtaining a copy
>   * of this software and associated documentation files (the "Software"), to deal
> @@ -28,6 +30,7 @@
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
>  #include "hw/sysbus.h"
> +#include "hw/i2c/i2c.h"
>  
>  #define TYPE_PPC4xx_I2C "ppc4xx-i2c"
>  #define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2C)
> @@ -37,6 +40,7 @@ typedef struct PPC4xxI2CState {
>      SysBusDevice parent_obj;
>  
>      /*< public >*/
> +    I2CBus *bus;
>      qemu_irq irq;
>      MemoryRegion iomem;
>      uint8_t mdata;
> @@ -54,6 +58,7 @@ typedef struct PPC4xxI2CState {
>      uint8_t xfrcnt;
>      uint8_t xtcntlss;
>      uint8_t directcntl;
> +    uint8_t intr;
>  } PPC4xxI2CState;
>  
>  #endif /* PPC4XX_I2C_H */

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs BALATON Zoltan
@ 2017-08-18  1:53   ` David Gibson
  2017-08-18 11:07     ` François Revol
  2017-08-18  9:30   ` [Qemu-devel] [Qemu-ppc] " luigi burdo
  1 sibling, 1 reply; 49+ messages in thread
From: David Gibson @ 2017-08-18  1:53 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 4510 bytes --]

On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:

You know I'm going to say it, right: needs a commit message.

What's a "plb-pcix", and what's an example of a 440 SoCs which has it.

This is basically a new device, so I'm pretty willing to merge for
2.11 with minimal review once rebased with the rest of the series.

Couple of comments below

[snip]
> +static void ppc440_pcix_reset(DeviceState *dev)
> +{
> +    struct PPC440PCIXState *s = PPC440_PCIX_HOST_BRIDGE(dev);
> +    int i;
> +
> +    memset(s->pom, 0, sizeof(s->pom));
> +    memset(s->pim, 0, sizeof(s->pim));

Is it safe to just memset() the memory region objects within the
pim/pom arrays without cleaning them up?  I'm guessing not..

> +    for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) {
> +        s->pim[i].sa = 0xffffffff00000000ULL;
> +    }
> +    s->sts = 0;
> +}
> +
> +/* All pins from each slot are tied to a single board IRQ.
> + * This may need further refactoring for other boards. */
> +static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num)
> +{
> +    int slot = pci_dev->devfn >> 3;
> +
> +    DPRINTF("%s: devfn %x irq %d -> %d\n", __func__,
> +            pci_dev->devfn, irq_num, slot);
> +
> +    return slot - 1;
> +}
> +
> +static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level)
> +{
> +    qemu_irq *pci_irqs = opaque;
> +
> +    DPRINTF("%s: PCI irq %d\n", __func__, irq_num);
> +    if (irq_num < 0) {
> +        fprintf(stderr, "%s: PCI irq %d\n", __func__, irq_num);

Use report_error() please.

> +        return;
> +    }
> +    qemu_set_irq(pci_irqs[irq_num], level);
> +}
> +
> +static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int devfn)
> +{
> +    PPC440PCIXState *s = opaque;
> +
> +    return &s->bm_as;
> +}
> +
> +static int ppc440_pcix_initfn(SysBusDevice *dev)
> +{
> +    PPC440PCIXState *s;
> +    PCIHostState *h;
> +    int i;
> +
> +    h = PCI_HOST_BRIDGE(dev);
> +    s = PPC440_PCIX_HOST_BRIDGE(dev);
> +
> +    for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
> +        sysbus_init_irq(dev, &s->irq[i]);
> +    }
> +
> +    memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX);
> +    h->bus = pci_register_bus(DEVICE(dev), NULL, ppc440_pcix_set_irq,
> +                         ppc440_pcix_map_irq, s->irq, &s->busmem,
> +                         get_system_io(), PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
> +
> +    s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bridge");
> +
> +    memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX);
> +    memory_region_add_subregion(&s->bm, 0x0, &s->busmem);
> +    address_space_init(&s->bm_as, &s->bm, "pci-bm");
> +    pci_setup_iommu(h->bus, ppc440_pcix_set_iommu, s);
> +
> +    memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE);
> +    memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, h,
> +                          "pci-conf-idx", 4);
> +    memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, h,
> +                          "pci-conf-data", 4);
> +    memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s,
> +                          "pci.reg", PPC440_REG_SIZE);
> +    memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
> +    memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
> +    memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem);
> +    sysbus_init_mmio(dev, &s->container);
> +
> +    return 0;
> +}
> +
> +static void ppc440_pcix_class_init(ObjectClass *klass, void *data)
> +{
> +    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    k->init = ppc440_pcix_initfn;
> +    dc->reset = ppc440_pcix_reset;
> +}
> +
> +static const TypeInfo ppc440_pcix_info = {
> +    .name          = TYPE_PPC440_PCIX_HOST_BRIDGE,
> +    .parent        = TYPE_PCI_HOST_BRIDGE,
> +    .instance_size = sizeof(PPC440PCIXState),
> +    .class_init    = ppc440_pcix_class_init,
> +};
> +
> +static void ppc440_pcix_register_types(void)
> +{
> +    type_register_static(&ppc440_pcix_info);
> +}
> +
> +type_init(ppc440_pcix_register_types)

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 12/12] ppc: Add aCube Sam460ex board
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 12/12] ppc: Add aCube Sam460ex board BALATON Zoltan
@ 2017-08-18  6:10   ` David Gibson
  2017-08-18 11:24     ` François Revol
  2017-08-18 12:46     ` BALATON Zoltan
  0 siblings, 2 replies; 49+ messages in thread
From: David Gibson @ 2017-08-18  6:10 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 870 bytes --]

On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC.
> This is not a full implementation yet with a lot of components still
> missing but enough to start a Linux kernel and the U-Boot firmware.
> 
> Signed-off-by: François Revol <revol@free.fr>
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

There are a *lot* of devices defined here.  Most of them look like
they belong to the SoC, not the board (since they use DCRs), so it
doesn't really make sense to define them in a board file.  It would
also make it easier to review if they were split up into separate
patches.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 11/12] ppc4xx: Export ECB and PLB emulation
  2017-08-14 11:06     ` BALATON Zoltan
@ 2017-08-18  6:11       ` David Gibson
  0 siblings, 0 replies; 49+ messages in thread
From: David Gibson @ 2017-08-18  6:11 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 1745 bytes --]

On Mon, Aug 14, 2017 at 01:06:42PM +0200, BALATON Zoltan wrote:
> On Mon, 14 Aug 2017, David Gibson wrote:
> > On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> > > These devices are found in some other ppc4xx cores too.
> 
> Thanks for the quick review, hope more will follow for other patches too
> maybe also from others.
> 
> > Elsewhere in the series you moved things that were used elsewhere out
> > of 405_uc, why not do that here as well?
> 
> I've moved those because those devices needed to be modified extensively
> while these two in this patch are used basically unchanged (they may not
> even be completely correct for 460EX but seem to work well enough) so I've
> left them here. I could add this explanation to the commit message or maybe
> move them to ppc4xx_devs to make it clearer that they are not only used by
> 405 emulation.

I think move them.  Probably to their own file - I think smaller files
are usually going to be more readable than one big file with heaps of
4xx devices.

> > > Also add some more PLB registers for 460EX.
> > 
> > Separate patch for that please, it's logically unrelated.  Plus the
> > commit message should say what these registers are, where they appear,
> > why do we need them?
> 
> OK. I don't really know what these registers are. I guess we need them
> because U-Boot or other guests poke them but they are only added to avoid
> the crash, not really emulated (just read zero, ignore write) for
> now.

Ok, so say that in the commit message.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs BALATON Zoltan
  2017-08-18  1:53   ` David Gibson
@ 2017-08-18  9:30   ` luigi burdo
  2017-08-18 11:20     ` François Revol
  2017-08-18 12:34     ` BALATON Zoltan
  1 sibling, 2 replies; 49+ messages in thread
From: luigi burdo @ 2017-08-18  9:30 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Francois Revol, David Gibson

hi Balaton,
i can help with amigaos4 for sam .
i can test it on P5040 book3e and on G5 quad book3s machine.
note sam for boot amigaos need a special modified version of uboot that is available on acube website it is a firmware update. without modified uboot will be not posdible auto boot amigaos.
idont know if is possible use standard uboot incuded in qemu for boot amigaos from uboot command line. i can ask help to Enrico Vidale as my FB friend but i dont know if he will be available for this kind of helping.

bye
luigi

Inviato da iPad

> Il giorno 14 ago 2017, alle ore 01:30, BALATON Zoltan <balaton@eik.bme.hu> ha scritto:
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
> hw/ppc/Makefile.objs |   2 +-
> hw/ppc/ppc440_pcix.c | 506 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 507 insertions(+), 1 deletion(-)
> create mode 100644 hw/ppc/ppc440_pcix.c
> 
> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
> index 2077216..9c5d58a 100644
> --- a/hw/ppc/Makefile.objs
> +++ b/hw/ppc/Makefile.objs
> @@ -13,7 +13,7 @@ endif
> obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
> # PowerPC 4xx boards
> obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
> -obj-y += ppc4xx_pci.o ppc4xx_i2c.o
> +obj-y += ppc4xx_pci.o ppc440_pcix.o ppc4xx_i2c.o
> # PReP
> obj-$(CONFIG_PREP) += prep.o
> obj-$(CONFIG_PREP) += prep_systemio.o
> diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c
> new file mode 100644
> index 0000000..3abd0d0
> --- /dev/null
> +++ b/hw/ppc/ppc440_pcix.c
> @@ -0,0 +1,506 @@
> +/*
> + * Emulation of the ibm,plb-pcix PCI controller
> + * This is found in some 440 SoCs e.g. the 460EX.
> + *
> + * Copyright (c) 2016 BALATON Zoltan
> + *
> + * Derived from ppc4xx_pci.c and pci-host/ppce500.c
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, version 2, as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * 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, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/hw.h"
> +#include "hw/ppc/ppc.h"
> +#include "hw/ppc/ppc4xx.h"
> +#include "hw/pci/pci.h"
> +#include "hw/pci/pci_host.h"
> +#include "exec/address-spaces.h"
> +
> +/*#define DEBUG_PCI*/
> +
> +#ifdef DEBUG_PCI
> +#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
> +#else
> +#define DPRINTF(fmt, ...)
> +#endif /* DEBUG */
> +
> +struct PLBOutMap {
> +    uint64_t la;
> +    uint64_t pcia;
> +    uint32_t sa;
> +    MemoryRegion mr;
> +};
> +
> +struct PLBInMap {
> +    uint64_t sa;
> +    uint64_t la;
> +    MemoryRegion mr;
> +};
> +
> +#define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host"
> +#define PPC440_PCIX_HOST_BRIDGE(obj) \
> +    OBJECT_CHECK(PPC440PCIXState, (obj), TYPE_PPC440_PCIX_HOST_BRIDGE)
> +
> +#define PPC440_PCIX_NR_POMS 3
> +#define PPC440_PCIX_NR_PIMS 3
> +
> +typedef struct PPC440PCIXState {
> +    PCIHostState parent_obj;
> +
> +    PCIDevice *dev;
> +    struct PLBOutMap pom[PPC440_PCIX_NR_POMS];
> +    struct PLBInMap pim[PPC440_PCIX_NR_PIMS];
> +    uint32_t sts;
> +    qemu_irq irq[PCI_NUM_PINS];
> +    AddressSpace bm_as;
> +    MemoryRegion bm;
> +
> +    MemoryRegion container;
> +    MemoryRegion iomem;
> +    MemoryRegion busmem;
> +} PPC440PCIXState;
> +
> +#define PPC440_REG_BASE     0x80000
> +#define PPC440_REG_SIZE     0xff
> +
> +#define PCIC0_CFGADDR       0x0
> +#define PCIC0_CFGDATA       0x4
> +
> +#define PCIX0_POM0LAL       0x68
> +#define PCIX0_POM0LAH       0x6c
> +#define PCIX0_POM0SA        0x70
> +#define PCIX0_POM0PCIAL     0x74
> +#define PCIX0_POM0PCIAH     0x78
> +#define PCIX0_POM1LAL       0x7c
> +#define PCIX0_POM1LAH       0x80
> +#define PCIX0_POM1SA        0x84
> +#define PCIX0_POM1PCIAL     0x88
> +#define PCIX0_POM1PCIAH     0x8c
> +#define PCIX0_POM2SA        0x90
> +
> +#define PCIX0_PIM0SAL       0x98
> +#define PCIX0_PIM0LAL       0x9c
> +#define PCIX0_PIM0LAH       0xa0
> +#define PCIX0_PIM1SA        0xa4
> +#define PCIX0_PIM1LAL       0xa8
> +#define PCIX0_PIM1LAH       0xac
> +#define PCIX0_PIM2SAL       0xb0
> +#define PCIX0_PIM2LAL       0xb4
> +#define PCIX0_PIM2LAH       0xb8
> +#define PCIX0_PIM0SAH       0xf8
> +#define PCIX0_PIM2SAH       0xfc
> +
> +#define PCIX0_STS           0xe0
> +
> +#define PCI_ALL_SIZE        (PPC440_REG_BASE + PPC440_REG_SIZE)
> +
> +/* DMA mapping */
> +static void ppc440_pcix_update_pim(PPC440PCIXState *s, int idx)
> +{
> +    MemoryRegion *mem = &s->pim[idx].mr;
> +    char *name;
> +    uint64_t size;
> +
> +    if (memory_region_is_mapped(mem)) {
> +        /* Before we modify anything, unmap and destroy the region */
> +        memory_region_del_subregion(&s->bm, mem);
> +        object_unparent(OBJECT(mem));
> +    }
> +
> +    if (!(s->pim[idx].sa & 1)) {
> +        /* Not enabled, nothing to do */
> +        return;
> +    }
> +
> +    name = g_strdup_printf("PCI Inbound Window %d", idx);
> +    size = ~(s->pim[idx].sa & ~7ULL) + 1;
> +    memory_region_init_alias(mem, OBJECT(s), name, get_system_memory(),
> +                             s->pim[idx].la, size);
> +    memory_region_add_subregion_overlap(&s->bm, 0, mem, -1);
> +    g_free(name);
> +
> +    DPRINTF("%s: Added window %d of size=%#"PRIx64" to CPU=%#"PRIx64"\n",
> +            __func__, idx, size, s->pim[idx].la);
> +}
> +
> +/* BAR mapping */
> +static void ppc440_pcix_update_pom(PPC440PCIXState *s, int idx)
> +{
> +    MemoryRegion *mem = &s->pom[idx].mr;
> +    MemoryRegion *address_space_mem = get_system_memory();
> +    char *name;
> +    uint32_t size;
> +
> +    if (memory_region_is_mapped(mem)) {
> +        /* Before we modify anything, unmap and destroy the region */
> +        memory_region_del_subregion(address_space_mem, mem);
> +        object_unparent(OBJECT(mem));
> +    }
> +
> +    if (!(s->pom[idx].sa & 1)) {
> +        /* Not enabled, nothing to do */
> +        return;
> +    }
> +
> +    name = g_strdup_printf("PCI Outbound Window %d", idx);
> +    size = ~(s->pom[idx].sa & 0xfffffffe) + 1;
> +    if (!size) {
> +        size = 0xffffffff;
> +    }
> +    memory_region_init_alias(mem, OBJECT(s), name, &s->busmem,
> +                             s->pom[idx].pcia, size);
> +    memory_region_add_subregion(address_space_mem, s->pom[idx].la, mem);
> +    g_free(name);
> +
> +    DPRINTF("%s: Added window %d of size=%#x from CPU=%#"PRIx64
> +            " to PCI=%#"PRIx64"\n", __func__, idx, size, s->pom[idx].la,
> +            s->pom[idx].pcia);
> +}
> +
> +static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr,
> +                                   uint64_t val, unsigned size)
> +{
> +    struct PPC440PCIXState *s = opaque;
> +
> +    DPRINTF("%s: addr 0x%"PRIx64 " = %"PRIx64 "\n", __func__, addr, val);
> +    switch (addr) {
> +    case PCI_VENDOR_ID ... PCI_MAX_LAT:
> +        stl_le_p(s->dev->config + addr, val);
> +        break;
> +
> +    case PCIX0_POM0LAL:
> +        s->pom[0].la &= 0xffffffff00000000ULL;
> +        s->pom[0].la |= val;
> +        ppc440_pcix_update_pom(s, 0);
> +        break;
> +    case PCIX0_POM0LAH:
> +        s->pom[0].la &= 0xffffffffULL;
> +        s->pom[0].la |= val << 32;
> +        ppc440_pcix_update_pom(s, 0);
> +        break;
> +    case PCIX0_POM0SA:
> +        s->pom[0].sa = val;
> +        ppc440_pcix_update_pom(s, 0);
> +        break;
> +    case PCIX0_POM0PCIAL:
> +        s->pom[0].pcia &= 0xffffffff00000000ULL;
> +        s->pom[0].pcia |= val;
> +        ppc440_pcix_update_pom(s, 0);
> +        break;
> +    case PCIX0_POM0PCIAH:
> +        s->pom[0].pcia &= 0xffffffffULL;
> +        s->pom[0].pcia |= val << 32;
> +        ppc440_pcix_update_pom(s, 0);
> +        break;
> +    case PCIX0_POM1LAL:
> +        s->pom[1].la &= 0xffffffff00000000ULL;
> +        s->pom[1].la |= val;
> +        ppc440_pcix_update_pom(s, 1);
> +        break;
> +    case PCIX0_POM1LAH:
> +        s->pom[1].la &= 0xffffffffULL;
> +        s->pom[1].la |= val << 32;
> +        ppc440_pcix_update_pom(s, 1);
> +        break;
> +    case PCIX0_POM1SA:
> +        s->pom[1].sa = val;
> +        ppc440_pcix_update_pom(s, 1);
> +        break;
> +    case PCIX0_POM1PCIAL:
> +        s->pom[1].pcia &= 0xffffffff00000000ULL;
> +        s->pom[1].pcia |= val;
> +        ppc440_pcix_update_pom(s, 1);
> +        break;
> +    case PCIX0_POM1PCIAH:
> +        s->pom[1].pcia &= 0xffffffffULL;
> +        s->pom[1].pcia |= val << 32;
> +        ppc440_pcix_update_pom(s, 1);
> +        break;
> +    case PCIX0_POM2SA:
> +        s->pom[2].sa = val;
> +        break;
> +
> +    case PCIX0_PIM0SAL:
> +        s->pim[0].sa &= 0xffffffff00000000ULL;
> +        s->pim[0].sa |= val;
> +        ppc440_pcix_update_pim(s, 0);
> +        break;
> +    case PCIX0_PIM0LAL:
> +        s->pim[0].la &= 0xffffffff00000000ULL;
> +        s->pim[0].la |= val;
> +        ppc440_pcix_update_pim(s, 0);
> +        break;
> +    case PCIX0_PIM0LAH:
> +        s->pim[0].la &= 0xffffffffULL;
> +        s->pim[0].la |= val << 32;
> +        ppc440_pcix_update_pim(s, 0);
> +        break;
> +    case PCIX0_PIM1SA:
> +        s->pim[1].sa = val;
> +        ppc440_pcix_update_pim(s, 1);
> +        break;
> +    case PCIX0_PIM1LAL:
> +        s->pim[1].la &= 0xffffffff00000000ULL;
> +        s->pim[1].la |= val;
> +        ppc440_pcix_update_pim(s, 1);
> +        break;
> +    case PCIX0_PIM1LAH:
> +        s->pim[1].la &= 0xffffffffULL;
> +        s->pim[1].la |= val << 32;
> +        ppc440_pcix_update_pim(s, 1);
> +        break;
> +    case PCIX0_PIM2SAL:
> +        s->pim[2].sa &= 0xffffffff00000000ULL;
> +        s->pim[2].sa = val;
> +        ppc440_pcix_update_pim(s, 2);
> +        break;
> +    case PCIX0_PIM2LAL:
> +        s->pim[2].la &= 0xffffffff00000000ULL;
> +        s->pim[2].la |= val;
> +        ppc440_pcix_update_pim(s, 2);
> +        break;
> +    case PCIX0_PIM2LAH:
> +        s->pim[2].la &= 0xffffffffULL;
> +        s->pim[2].la |= val << 32;
> +        ppc440_pcix_update_pim(s, 2);
> +        break;
> +
> +    case PCIX0_STS:
> +        s->sts = val;
> +        break;
> +
> +    case PCIX0_PIM0SAH:
> +        s->pim[0].sa &= 0xffffffffULL;
> +        s->pim[0].sa |= val << 32;
> +        ppc440_pcix_update_pim(s, 0);
> +        break;
> +    case PCIX0_PIM2SAH:
> +        s->pim[2].sa &= 0xffffffffULL;
> +        s->pim[2].sa |= val << 32;
> +        ppc440_pcix_update_pim(s, 2);
> +        break;
> +
> +    default:
> +        printf("%s: unhandled PCI internal register 0x%lx\n", __func__,
> +               (unsigned long)addr);
> +        break;
> +    }
> +}
> +
> +static uint64_t ppc440_pcix_reg_read4(void *opaque, hwaddr addr,
> +                                     unsigned size)
> +{
> +    struct PPC440PCIXState *s = opaque;
> +    uint32_t val;
> +
> +    switch (addr) {
> +    case PCI_VENDOR_ID ... PCI_MAX_LAT:
> +        val = ldl_le_p(s->dev->config + addr);
> +        break;
> +
> +    case PCIX0_POM0LAL:
> +        val = s->pom[0].la;
> +        break;
> +    case PCIX0_POM0LAH:
> +        val = s->pom[0].la >> 32;
> +        break;
> +    case PCIX0_POM0SA:
> +        val = s->pom[0].sa;
> +        break;
> +    case PCIX0_POM0PCIAL:
> +        val = s->pom[0].pcia;
> +        break;
> +    case PCIX0_POM0PCIAH:
> +        val = s->pom[0].pcia >> 32;
> +        break;
> +    case PCIX0_POM1LAL:
> +        val = s->pom[1].la;
> +        break;
> +    case PCIX0_POM1LAH:
> +        val = s->pom[1].la >> 32;
> +        break;
> +    case PCIX0_POM1SA:
> +        val = s->pom[1].sa;
> +        break;
> +    case PCIX0_POM1PCIAL:
> +        val = s->pom[1].pcia;
> +        break;
> +    case PCIX0_POM1PCIAH:
> +        val = s->pom[1].pcia >> 32;
> +        break;
> +    case PCIX0_POM2SA:
> +        val = s->pom[2].sa;
> +        break;
> +
> +    case PCIX0_PIM0SAL:
> +        val = s->pim[0].sa;
> +        break;
> +    case PCIX0_PIM0LAL:
> +        val = s->pim[0].la;
> +        break;
> +    case PCIX0_PIM0LAH:
> +        val = s->pim[0].la >> 32;
> +        break;
> +    case PCIX0_PIM1SA:
> +        val = s->pim[1].sa;
> +        break;
> +    case PCIX0_PIM1LAL:
> +        val = s->pim[1].la;
> +        break;
> +    case PCIX0_PIM1LAH:
> +        val = s->pim[1].la >> 32;
> +        break;
> +    case PCIX0_PIM2SAL:
> +        val = s->pim[2].sa;
> +        break;
> +    case PCIX0_PIM2LAL:
> +        val = s->pim[2].la;
> +        break;
> +    case PCIX0_PIM2LAH:
> +        val = s->pim[2].la >> 32;
> +        break;
> +
> +    case PCIX0_STS:
> +        val = s->sts;
> +        break;
> +
> +    case PCIX0_PIM0SAH:
> +        val = s->pim[0].sa  >> 32;
> +        break;
> +    case PCIX0_PIM2SAH:
> +        val = s->pim[2].sa  >> 32;
> +        break;
> +
> +    default:
> +        printf("%s: invalid PCI internal register 0x%lx\n", __func__,
> +               (unsigned long)addr);
> +        val = 0;
> +    }
> +
> +    DPRINTF("%s: addr 0x%"PRIx64 " = %"PRIx32 "\n", __func__, addr, val);
> +    return val;
> +}
> +
> +static const MemoryRegionOps pci_reg_ops = {
> +    .read = ppc440_pcix_reg_read4,
> +    .write = ppc440_pcix_reg_write4,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
> +static void ppc440_pcix_reset(DeviceState *dev)
> +{
> +    struct PPC440PCIXState *s = PPC440_PCIX_HOST_BRIDGE(dev);
> +    int i;
> +
> +    memset(s->pom, 0, sizeof(s->pom));
> +    memset(s->pim, 0, sizeof(s->pim));
> +    for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) {
> +        s->pim[i].sa = 0xffffffff00000000ULL;
> +    }
> +    s->sts = 0;
> +}
> +
> +/* All pins from each slot are tied to a single board IRQ.
> + * This may need further refactoring for other boards. */
> +static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num)
> +{
> +    int slot = pci_dev->devfn >> 3;
> +
> +    DPRINTF("%s: devfn %x irq %d -> %d\n", __func__,
> +            pci_dev->devfn, irq_num, slot);
> +
> +    return slot - 1;
> +}
> +
> +static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level)
> +{
> +    qemu_irq *pci_irqs = opaque;
> +
> +    DPRINTF("%s: PCI irq %d\n", __func__, irq_num);
> +    if (irq_num < 0) {
> +        fprintf(stderr, "%s: PCI irq %d\n", __func__, irq_num);
> +        return;
> +    }
> +    qemu_set_irq(pci_irqs[irq_num], level);
> +}
> +
> +static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int devfn)
> +{
> +    PPC440PCIXState *s = opaque;
> +
> +    return &s->bm_as;
> +}
> +
> +static int ppc440_pcix_initfn(SysBusDevice *dev)
> +{
> +    PPC440PCIXState *s;
> +    PCIHostState *h;
> +    int i;
> +
> +    h = PCI_HOST_BRIDGE(dev);
> +    s = PPC440_PCIX_HOST_BRIDGE(dev);
> +
> +    for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
> +        sysbus_init_irq(dev, &s->irq[i]);
> +    }
> +
> +    memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX);
> +    h->bus = pci_register_bus(DEVICE(dev), NULL, ppc440_pcix_set_irq,
> +                         ppc440_pcix_map_irq, s->irq, &s->busmem,
> +                         get_system_io(), PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
> +
> +    s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bridge");
> +
> +    memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX);
> +    memory_region_add_subregion(&s->bm, 0x0, &s->busmem);
> +    address_space_init(&s->bm_as, &s->bm, "pci-bm");
> +    pci_setup_iommu(h->bus, ppc440_pcix_set_iommu, s);
> +
> +    memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE);
> +    memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, h,
> +                          "pci-conf-idx", 4);
> +    memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, h,
> +                          "pci-conf-data", 4);
> +    memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s,
> +                          "pci.reg", PPC440_REG_SIZE);
> +    memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
> +    memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
> +    memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem);
> +    sysbus_init_mmio(dev, &s->container);
> +
> +    return 0;
> +}
> +
> +static void ppc440_pcix_class_init(ObjectClass *klass, void *data)
> +{
> +    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    k->init = ppc440_pcix_initfn;
> +    dc->reset = ppc440_pcix_reset;
> +}
> +
> +static const TypeInfo ppc440_pcix_info = {
> +    .name          = TYPE_PPC440_PCIX_HOST_BRIDGE,
> +    .parent        = TYPE_PCI_HOST_BRIDGE,
> +    .instance_size = sizeof(PPC440PCIXState),
> +    .class_init    = ppc440_pcix_class_init,
> +};
> +
> +static void ppc440_pcix_register_types(void)
> +{
> +    type_register_static(&ppc440_pcix_info);
> +}
> +
> +type_init(ppc440_pcix_register_types)
> -- 
> 2.7.4
> 
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-18  1:53   ` David Gibson
@ 2017-08-18 11:07     ` François Revol
  2017-08-18 12:15       ` [Qemu-devel] [Qemu-ppc] " BALATON Zoltan
  2017-08-18 12:18       ` [Qemu-devel] " David Gibson
  0 siblings, 2 replies; 49+ messages in thread
From: François Revol @ 2017-08-18 11:07 UTC (permalink / raw)
  To: David Gibson, BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf

[-- Attachment #1: Type: text/plain, Size: 530 bytes --]

Hi,

Le 18/08/2017 à 03:53, David Gibson a écrit :
> On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> 
> You know I'm going to say it, right: needs a commit message.
> 
> What's a "plb-pcix", and what's an example of a 440 SoCs which has it.

IIRC that's the PCI(express) controller, which is not memory-mapped but
inside the DCR address space, so accessed from the PLB.

See:

http://www.embeddeddeveloper.com/assets/processors/amcc/datasheets/PP460EX_DS2063.pdf

page 9, 13.



François.


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-18  9:30   ` [Qemu-devel] [Qemu-ppc] " luigi burdo
@ 2017-08-18 11:20     ` François Revol
  2017-08-18 13:03       ` BALATON Zoltan
  2017-08-18 12:34     ` BALATON Zoltan
  1 sibling, 1 reply; 49+ messages in thread
From: François Revol @ 2017-08-18 11:20 UTC (permalink / raw)
  To: luigi burdo, BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, David Gibson

Hi,

Le 18/08/2017 à 11:30, luigi burdo a écrit :
> hi Balaton, i can help with amigaos4 for sam . i can test it on P5040
> book3e and on G5 quad book3s machine. note sam for boot amigaos need
> a special modified version of uboot that is available on acube
> website it is a firmware update. without modified uboot will be not
> posdible auto boot amigaos. idont know if is possible use standard
> uboot incuded in qemu for boot amigaos from uboot command line. i can
> ask help to Enrico Vidale as my FB friend but i dont know if he will
> be available for this kind of helping.
> 

Yes they use their own custom U-Boot, with a lot of changes and code
duplication, and added x86 emulation to run a VGA BIOS, and never
upstreamed the changes... much like any other vendor, sadly.

I once managed to build a binary from their published source code with
an old compiler, although it's not exactly the same of the binary used,
which I think is actually run with the on-chip RAM or something weird alike.

François.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 12/12] ppc: Add aCube Sam460ex board
  2017-08-18  6:10   ` David Gibson
@ 2017-08-18 11:24     ` François Revol
  2017-08-18 12:46     ` BALATON Zoltan
  1 sibling, 0 replies; 49+ messages in thread
From: François Revol @ 2017-08-18 11:24 UTC (permalink / raw)
  To: David Gibson, BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf

[-- Attachment #1: Type: text/plain, Size: 1050 bytes --]

Le 18/08/2017 à 08:10, David Gibson a écrit :
> On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
>> Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC.
>> This is not a full implementation yet with a lot of components still
>> missing but enough to start a Linux kernel and the U-Boot firmware.
>>
>> Signed-off-by: François Revol <revol@free.fr>
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> 
> There are a *lot* of devices defined here.  Most of them look like
> they belong to the SoC, not the board (since they use DCRs), so it
> doesn't really make sense to define them in a board file.  It would
> also make it easier to review if they were split up into separate
> patches.
> 


Indeed, I never thought it would need that many devices to run, and I
intended to move that out but never did.

While it'd make it easier to review, I also recall waiting 3 years to
get a simple patch in just because someone wanted the code to first be
refactored (hint: wacom) :p

François.


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-18 11:07     ` François Revol
@ 2017-08-18 12:15       ` BALATON Zoltan
  2017-08-18 12:18       ` [Qemu-devel] " David Gibson
  1 sibling, 0 replies; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-18 12:15 UTC (permalink / raw)
  To: David Gibson; +Cc: François Revol, qemu-ppc, qemu-devel

On Fri, 18 Aug 2017, François Revol wrote:
> Le 18/08/2017 à 03:53, David Gibson a écrit :
>> On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
>>
>> You know I'm going to say it, right: needs a commit message.
>>
>> What's a "plb-pcix", and what's an example of a 440 SoCs which has it.
>
> IIRC that's the PCI(express) controller, which is not memory-mapped but
> inside the DCR address space, so accessed from the PLB.

This is the PCI(X) controller only, the PCIe(xpress) controller is 
(partially) implemented in sam460ex.c 
TYPE_PPC460EX_PCIE_HOST/"ppc460ex-pcie-host". The plb-pcix is the 
compatible name the fdt refers to. I only know of the 460EX that has it 
but probably other similar SoCs (like some 440 variants) also have this 
kind of PCI controller (according to #defines in U-Boot source but don't 
remember the details).

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-18 11:07     ` François Revol
  2017-08-18 12:15       ` [Qemu-devel] [Qemu-ppc] " BALATON Zoltan
@ 2017-08-18 12:18       ` David Gibson
  1 sibling, 0 replies; 49+ messages in thread
From: David Gibson @ 2017-08-18 12:18 UTC (permalink / raw)
  To: François Revol; +Cc: BALATON Zoltan, qemu-devel, qemu-ppc, Alexander Graf

[-- Attachment #1: Type: text/plain, Size: 950 bytes --]

On Fri, Aug 18, 2017 at 01:07:28PM +0200, François Revol wrote:
> Hi,
> 
> Le 18/08/2017 à 03:53, David Gibson a écrit :
> > On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> > 
> > You know I'm going to say it, right: needs a commit message.
> > 
> > What's a "plb-pcix", and what's an example of a 440 SoCs which has it.
> 
> IIRC that's the PCI(express) controller, which is not memory-mapped but
> inside the DCR address space, so accessed from the PLB.
> 
> See:
> 
> http://www.embeddeddeveloper.com/assets/processors/amcc/datasheets/PP460EX_DS2063.pdf
> 
> page 9, 13.

Sure, I can guess that.  But my point is that this is the sort of
information (including the link) that ought to be in the commit
message.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-18  9:30   ` [Qemu-devel] [Qemu-ppc] " luigi burdo
  2017-08-18 11:20     ` François Revol
@ 2017-08-18 12:34     ` BALATON Zoltan
  2017-08-18 19:43       ` luigi burdo
  1 sibling, 1 reply; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-18 12:34 UTC (permalink / raw)
  To: luigi burdo; +Cc: qemu-devel, qemu-ppc, Francois Revol, David Gibson

On Fri, 18 Aug 2017, luigi burdo wrote:
> hi Balaton,

Ciao Luigi,

> i can help with amigaos4 for sam .
> i can test it on P5040 book3e and on G5 quad book3s machine.

Thanks for the offer but unfortunately that would not help because these 
are different CPUs than the 460EX used in the Sam board. I'd definitely 
need logs from Sam460ex or Sam460cr, other logs are not the same and not 
help to find differences between real hardware and emulation.

> note sam for boot amigaos need a special modified version of uboot that 
> is available on acube website it is a firmware update. without modified 
> uboot will be not posdible auto boot amigaos.

I know about this and if you read the cover message (RFC PATCH 00/12) I 
link to a fixed version of that U-Boot firmware (rebuilt from source with 
the mentioned patches) which works with this emulation. (The original one 
from the updater also starts but cannot boot due to some problems which 
are fixed by these patches in my image. This is described in the cover 
message.) With that fixed firmware image it should be possible to at least 
try booting AmigaOS on the emulation and get some logs. I'd be surprised 
if it also worked at this point but I could not try it as it needs an 
appropriate AmigaOS version that runs on the Sam460. It should produce 
some logs though with -serial stdio which may help finding what is 
missing.

> idont know if is possible use standard uboot incuded in qemu for boot 
> amigaos from uboot command line. i can ask help to Enrico Vidale as my 
> FB friend but i dont know if he will be available for this kind of 
> helping.

I think it would not be possible to use the U-Boot in QEMU now as that is 
for e500 CPU but this is not needed either. See above, we are aiming to 
emulate enough of the board that it can run the original firmware which 
should be able to boot these Amiga like OSes and normal Linux images used 
on the Sam460ex. This already works but things fail after or during boot 
currently. This is what needs to be debugged. So we'd need someone who has 
a Sam460 (ex or cr) board and can test on that to get logs from OSes on 
real hardware for comparison.

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 12/12] ppc: Add aCube Sam460ex board
  2017-08-18  6:10   ` David Gibson
  2017-08-18 11:24     ` François Revol
@ 2017-08-18 12:46     ` BALATON Zoltan
  2017-08-22  2:35       ` David Gibson
  1 sibling, 1 reply; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-18 12:46 UTC (permalink / raw)
  To: David Gibson; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

On Fri, 18 Aug 2017, David Gibson wrote:
> On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
>> Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC.
>> This is not a full implementation yet with a lot of components still
>> missing but enough to start a Linux kernel and the U-Boot firmware.
>>
>> Signed-off-by: François Revol <revol@free.fr>
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>
> There are a *lot* of devices defined here.  Most of them look like
> they belong to the SoC, not the board (since they use DCRs), so it
> doesn't really make sense to define them in a board file.  It would
> also make it easier to review if they were split up into separate
> patches.

I thought it's simpler to review a series with 12 reasonably sized patches 
than one with twice as many which only modify a few lines here and there 
each. Also adding a lot of code scattered in hw directories is probably 
less clear than having them all at one place. But of course each approach 
can be reasoned. I thought this might have to be split up but I've left it 
one place for now for first review to get some advice on what's preferred.

Maybe I should put things that belong to the SoC in ppc440_uc.c (similar 
to ppc405uc.c we already have) and move common devices used by both to 
ppc4xx_devs.c (which already seems to serve that purpose). If more cleanup 
is needed that could be done separately afterwards, I don't think it's a 
good idea to mix in too much cleanup now to keep patches relatively 
simple. (I already have some moving around included as clean up patches 
but I'd like to focus on actual functions than clean up at this point).

Does putting these devices from board code to ppc440_uc.c sound 
acceptable?

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-18 11:20     ` François Revol
@ 2017-08-18 13:03       ` BALATON Zoltan
  0 siblings, 0 replies; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-18 13:03 UTC (permalink / raw)
  To: François Revol; +Cc: luigi burdo, qemu-devel, qemu-ppc, David Gibson

On Fri, 18 Aug 2017, François Revol wrote:
> I once managed to build a binary from their published source code with
> an old compiler,

It builds here with the patch I've posted next to the bin image.

> although it's not exactly the same of the binary used,
> which I think is actually run with the on-chip RAM or something weird alike.

Maybe it's the same but we may have a problem with MMU emulation so it 
behaves differently (or they've compiled with different compiler/version 
which generates different code, I haven't checked that deep).

But AROS has a problem with MMU so it may be a bug. I'll send a separate 
message about that.

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-18 12:34     ` BALATON Zoltan
@ 2017-08-18 19:43       ` luigi burdo
  2017-08-18 20:52         ` François Revol
  2017-08-19 10:03         ` BALATON Zoltan
  0 siblings, 2 replies; 49+ messages in thread
From: luigi burdo @ 2017-08-18 19:43 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Francois Revol, David Gibson


hi Balaton,
> I know about this and if you read the cover message (RFC PATCH 00/12) I link to a fixed version of that U-Boot firmware (rebuilt from source with the mentioned patches) which works with this emulation. (The original one from the updater also starts but cannot boot due to some problems which are fixed by these patches in my image. This is described in the cover message.) With that fixed firmware image it should be possible to at least try booting AmigaOS on the emulation and get some logs. I'd be surprised if it also worked at this point but I could not try it as it needs an appropriate AmigaOS version that runs on the Sam460. It should produce some logs though with -serial stdio which may help finding what is missing.

i have sam460 amigaos cdrom iso as my backup and can test it inside qemu. sharing the logs if you needed.

> I think it would not be possible to use the U-Boot in QEMU now as that is for e500 CPU but this is not needed either. See above, we are aiming to emulate enough of the board that it can run the original firmware which should be able to boot these Amiga like OSes and normal Linux images used on the Sam460ex. This already works but things fail after or during boot currently. This is what needs to be debugged. So we'd need someone who has a Sam460 (ex or cr) board and can test on that to get logs from OSes on real hardware for comparison.

 about real hardware no problem i will ask inside amigan community if someone have the opportunity to share the serial debug of sam 460 runinng amigaos.

can i ask you something ?
why you dont try to integrate in qemu the pegasos 2 or the efika machine. i have the feeling that probably it can be more simple because more old machine and components.

bye 
luigi

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-18 19:43       ` luigi burdo
@ 2017-08-18 20:52         ` François Revol
  2017-08-19 10:03         ` BALATON Zoltan
  1 sibling, 0 replies; 49+ messages in thread
From: François Revol @ 2017-08-18 20:52 UTC (permalink / raw)
  To: luigi burdo, BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, David Gibson

Le 18/08/2017 à 21:43, luigi burdo a écrit :
> can i ask you something ? why you dont try to integrate in qemu the
> pegasos 2 or the efika machine. i have the feeling that probably it
> can be more simple because more old machine and components.
> 

Except they are antique, and the Pegasos at least has an horribly buggy
OpenFirmware implementation.

I'd rather work on BeBox support ;-)

François.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-18 19:43       ` luigi burdo
  2017-08-18 20:52         ` François Revol
@ 2017-08-19 10:03         ` BALATON Zoltan
  1 sibling, 0 replies; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-19 10:03 UTC (permalink / raw)
  To: luigi burdo; +Cc: qemu-devel, qemu-ppc, Francois Revol, David Gibson

On Fri, 18 Aug 2017, luigi burdo wrote:
> i have sam460 amigaos cdrom iso as my backup and can test it inside 
> qemu. sharing the logs if you needed.

It may help if you can do that. You need to compile QEMU from git with 
this patch series applied and copy the u-boot-sam460-20100605-fixed.bin 
linked from the cover message as u-boot-sam460-20100605.bin to the current 
dir. Then try booting the CD and see if it shows something. It should 
print some messages to console where it's started with -serial stdio when 
you start AmigaOS with debug (you may need to set os4_commandline in 
U-Boot for this but I don't know AmigaOS).

> about real hardware no problem i will ask inside amigan community if 
> someone have the opportunity to share the serial debug of sam 460 
> runinng amigaos.

Do you know about a good place for such requests? Is there some forum or 
mailing list I should be aware of?

> can i ask you something ?
> why you dont try to integrate in qemu the pegasos 2 or the efika 
> machine. i have the feeling that probably it can be more simple because 
> more old machine and components.

The age of a machine and components has nothing to do with how easy it is 
to emulate. It depends on what is already emulated in QEMU. If none of 
those old components are implemented by QEMU already then it's a lot of 
work to write emulation of them. (Such as the Marvell system controller 
chip in Pegasos or the SoC the Efika uses. Besides, does AmigaOS run on 
Efika?) If there are some previous work we can build on then it's easier. 
QEMU already had ppc440 emulation including a similar board and Francois 
has started sam460ex emulation so it was easier to finish this than making 
a new one. (Also firmware and graphics emulation may be more difficult for 
those other boards.)

At the end it does not matter which machine we emulate if the goal is to 
run these OSes. If we have any of the supported boards they will run so we 
don't need more of these just one and it was the sam460 which was nearest 
to start working. (The MorphOS team or one of the developers may have some 
Pegasos 2 emulation but they don't intend to publish that and I don't know 
about previous work on Efika so the Sam460ex seems like a good choice with 
support for a lot of OSes, including porting Haiku which was why Francois 
has started emulating it so this may help that activity as well 
increasing the available OSes.)

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 12/12] ppc: Add aCube Sam460ex board
  2017-08-18 12:46     ` BALATON Zoltan
@ 2017-08-22  2:35       ` David Gibson
  2017-08-22 11:18         ` BALATON Zoltan
  0 siblings, 1 reply; 49+ messages in thread
From: David Gibson @ 2017-08-22  2:35 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 2855 bytes --]

On Fri, Aug 18, 2017 at 02:46:42PM +0200, BALATON Zoltan wrote:
> On Fri, 18 Aug 2017, David Gibson wrote:
> > On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> > > Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC.
> > > This is not a full implementation yet with a lot of components still
> > > missing but enough to start a Linux kernel and the U-Boot firmware.
> > > 
> > > Signed-off-by: François Revol <revol@free.fr>
> > > Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> > 
> > There are a *lot* of devices defined here.  Most of them look like
> > they belong to the SoC, not the board (since they use DCRs), so it
> > doesn't really make sense to define them in a board file.  It would
> > also make it easier to review if they were split up into separate
> > patches.
> 
> I thought it's simpler to review a series with 12 reasonably sized patches
> than one with twice as many which only modify a few lines here and there
> each. Also adding a lot of code scattered in hw directories is probably less
> clear than having them all at one place. But of course each approach can be
> reasoned. I thought this might have to be split up but I've left it one
> place for now for first review to get some advice on what's preferred.

Well, it depends on the content of the patches.  If splitting it up
means a lot of looking between patches to make sense of what's going
on then that's certainly not good.  But if the small patches are
independent of each other and can be assessed on their own merits,
then that usually makes it easier.

In this case the various new 440 devices should be pretty much
independent of each other, so I think splitting is the better option.

> Maybe I should put things that belong to the SoC in ppc440_uc.c (similar to
> ppc405uc.c we already have) and move common devices used by both to
> ppc4xx_devs.c (which already seems to serve that purpose). If more cleanup
> is needed that could be done separately afterwards, I don't think it's a
> good idea to mix in too much cleanup now to keep patches relatively simple.
> (I already have some moving around included as clean up patches but I'd like
> to focus on actual functions than clean up at this point).
> 
> Does putting these devices from board code to ppc440_uc.c sound
> acceptable?

That'd be ok - though again, I'd prefer to see each device as a
separate patch.  It would probably be preferable to put each device in
a separate file as well though, unless they're _really_ tiny.  Nothing
inherently wrong with small .c files, if they're still more or less
self contained.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 12/12] ppc: Add aCube Sam460ex board
  2017-08-22  2:35       ` David Gibson
@ 2017-08-22 11:18         ` BALATON Zoltan
  2017-08-23  0:35           ` David Gibson
  0 siblings, 1 reply; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-22 11:18 UTC (permalink / raw)
  To: David Gibson; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

On Tue, 22 Aug 2017, David Gibson wrote:
> On Fri, Aug 18, 2017 at 02:46:42PM +0200, BALATON Zoltan wrote:
>> On Fri, 18 Aug 2017, David Gibson wrote:
>>> On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
>>>> Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC.
>>>> This is not a full implementation yet with a lot of components still
>>>> missing but enough to start a Linux kernel and the U-Boot firmware.
>>>>
>>>> Signed-off-by: François Revol <revol@free.fr>
>>>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>>>
>>> There are a *lot* of devices defined here.  Most of them look like
>>> they belong to the SoC, not the board (since they use DCRs), so it
>>> doesn't really make sense to define them in a board file.  It would
>>> also make it easier to review if they were split up into separate
>>> patches.
>>
>> I thought it's simpler to review a series with 12 reasonably sized patches
>> than one with twice as many which only modify a few lines here and there
>> each. Also adding a lot of code scattered in hw directories is probably less
>> clear than having them all at one place. But of course each approach can be
>> reasoned. I thought this might have to be split up but I've left it one
>> place for now for first review to get some advice on what's preferred.
>
> Well, it depends on the content of the patches.  If splitting it up
> means a lot of looking between patches to make sense of what's going
> on then that's certainly not good.  But if the small patches are
> independent of each other and can be assessed on their own merits,
> then that usually makes it easier.
>
> In this case the various new 440 devices should be pretty much
> independent of each other, so I think splitting is the better option.
>
>> Maybe I should put things that belong to the SoC in ppc440_uc.c (similar to
>> ppc405uc.c we already have) and move common devices used by both to
>> ppc4xx_devs.c (which already seems to serve that purpose). If more cleanup
>> is needed that could be done separately afterwards, I don't think it's a
>> good idea to mix in too much cleanup now to keep patches relatively simple.
>> (I already have some moving around included as clean up patches but I'd like
>> to focus on actual functions than clean up at this point).
>>
>> Does putting these devices from board code to ppc440_uc.c sound
>> acceptable?
>
> That'd be ok - though again, I'd prefer to see each device as a
> separate patch.  It would probably be preferable to put each device in
> a separate file as well though, unless they're _really_ tiny.  Nothing
> inherently wrong with small .c files, if they're still more or less
> self contained.

Since most of these are just stubs for now and not really full emulation 
of the device I'd leave them in one file similar to ppc405 for now. They 
both could be cleaned up later if it's found necessary or devices that are 
deemed ready and big enough to be moved out could be split off (like I did 
with i2c and pcix). If you insist, I can split it now but I think it's 
more difficult to work with a lot of small files scattered in hw instead 
of everything related to ppc440 in one place until there's still missing 
fucntionality. I consider splitting it up cleanup which could be done 
later separately unless it's a requirement to get this series in.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 12/12] ppc: Add aCube Sam460ex board
  2017-08-22 11:18         ` BALATON Zoltan
@ 2017-08-23  0:35           ` David Gibson
  2017-08-23  0:48             ` BALATON Zoltan
  0 siblings, 1 reply; 49+ messages in thread
From: David Gibson @ 2017-08-23  0:35 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 3920 bytes --]

On Tue, Aug 22, 2017 at 01:18:02PM +0200, BALATON Zoltan wrote:
> On Tue, 22 Aug 2017, David Gibson wrote:
> > On Fri, Aug 18, 2017 at 02:46:42PM +0200, BALATON Zoltan wrote:
> > > On Fri, 18 Aug 2017, David Gibson wrote:
> > > > On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> > > > > Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC.
> > > > > This is not a full implementation yet with a lot of components still
> > > > > missing but enough to start a Linux kernel and the U-Boot firmware.
> > > > > 
> > > > > Signed-off-by: François Revol <revol@free.fr>
> > > > > Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> > > > 
> > > > There are a *lot* of devices defined here.  Most of them look like
> > > > they belong to the SoC, not the board (since they use DCRs), so it
> > > > doesn't really make sense to define them in a board file.  It would
> > > > also make it easier to review if they were split up into separate
> > > > patches.
> > > 
> > > I thought it's simpler to review a series with 12 reasonably sized patches
> > > than one with twice as many which only modify a few lines here and there
> > > each. Also adding a lot of code scattered in hw directories is probably less
> > > clear than having them all at one place. But of course each approach can be
> > > reasoned. I thought this might have to be split up but I've left it one
> > > place for now for first review to get some advice on what's preferred.
> > 
> > Well, it depends on the content of the patches.  If splitting it up
> > means a lot of looking between patches to make sense of what's going
> > on then that's certainly not good.  But if the small patches are
> > independent of each other and can be assessed on their own merits,
> > then that usually makes it easier.
> > 
> > In this case the various new 440 devices should be pretty much
> > independent of each other, so I think splitting is the better option.
> > 
> > > Maybe I should put things that belong to the SoC in ppc440_uc.c (similar to
> > > ppc405uc.c we already have) and move common devices used by both to
> > > ppc4xx_devs.c (which already seems to serve that purpose). If more cleanup
> > > is needed that could be done separately afterwards, I don't think it's a
> > > good idea to mix in too much cleanup now to keep patches relatively simple.
> > > (I already have some moving around included as clean up patches but I'd like
> > > to focus on actual functions than clean up at this point).
> > > 
> > > Does putting these devices from board code to ppc440_uc.c sound
> > > acceptable?
> > 
> > That'd be ok - though again, I'd prefer to see each device as a
> > separate patch.  It would probably be preferable to put each device in
> > a separate file as well though, unless they're _really_ tiny.  Nothing
> > inherently wrong with small .c files, if they're still more or less
> > self contained.
> 
> Since most of these are just stubs for now and not really full emulation of
> the device I'd leave them in one file similar to ppc405 for now. They both
> could be cleaned up later if it's found necessary or devices that are deemed
> ready and big enough to be moved out could be split off (like I did with i2c
> and pcix). If you insist, I can split it now but I think it's more difficult
> to work with a lot of small files scattered in hw instead of everything
> related to ppc440 in one place until there's still missing fucntionality. I
> consider splitting it up cleanup which could be done later separately unless
> it's a requirement to get this series in.

Ok, that's a reasonable argument.  Go ahead and put them in a
ppc440_uc.c file.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 12/12] ppc: Add aCube Sam460ex board
  2017-08-23  0:35           ` David Gibson
@ 2017-08-23  0:48             ` BALATON Zoltan
  0 siblings, 0 replies; 49+ messages in thread
From: BALATON Zoltan @ 2017-08-23  0:48 UTC (permalink / raw)
  To: David Gibson; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

On Wed, 23 Aug 2017, David Gibson wrote:
> On Tue, Aug 22, 2017 at 01:18:02PM +0200, BALATON Zoltan wrote:
>> On Tue, 22 Aug 2017, David Gibson wrote:
>>> On Fri, Aug 18, 2017 at 02:46:42PM +0200, BALATON Zoltan wrote:
>>>> On Fri, 18 Aug 2017, David Gibson wrote:
>>>>> On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
>>>>>> Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC.
>>>>>> This is not a full implementation yet with a lot of components still
>>>>>> missing but enough to start a Linux kernel and the U-Boot firmware.
>>>>>>
>>>>>> Signed-off-by: François Revol <revol@free.fr>
>>>>>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>>>>>
>>>>> There are a *lot* of devices defined here.  Most of them look like
>>>>> they belong to the SoC, not the board (since they use DCRs), so it
>>>>> doesn't really make sense to define them in a board file.  It would
>>>>> also make it easier to review if they were split up into separate
>>>>> patches.
>>>>
>>>> I thought it's simpler to review a series with 12 reasonably sized patches
>>>> than one with twice as many which only modify a few lines here and there
>>>> each. Also adding a lot of code scattered in hw directories is probably less
>>>> clear than having them all at one place. But of course each approach can be
>>>> reasoned. I thought this might have to be split up but I've left it one
>>>> place for now for first review to get some advice on what's preferred.
>>>
>>> Well, it depends on the content of the patches.  If splitting it up
>>> means a lot of looking between patches to make sense of what's going
>>> on then that's certainly not good.  But if the small patches are
>>> independent of each other and can be assessed on their own merits,
>>> then that usually makes it easier.
>>>
>>> In this case the various new 440 devices should be pretty much
>>> independent of each other, so I think splitting is the better option.
>>>
>>>> Maybe I should put things that belong to the SoC in ppc440_uc.c (similar to
>>>> ppc405uc.c we already have) and move common devices used by both to
>>>> ppc4xx_devs.c (which already seems to serve that purpose). If more cleanup
>>>> is needed that could be done separately afterwards, I don't think it's a
>>>> good idea to mix in too much cleanup now to keep patches relatively simple.
>>>> (I already have some moving around included as clean up patches but I'd like
>>>> to focus on actual functions than clean up at this point).
>>>>
>>>> Does putting these devices from board code to ppc440_uc.c sound
>>>> acceptable?
>>>
>>> That'd be ok - though again, I'd prefer to see each device as a
>>> separate patch.  It would probably be preferable to put each device in
>>> a separate file as well though, unless they're _really_ tiny.  Nothing
>>> inherently wrong with small .c files, if they're still more or less
>>> self contained.
>>
>> Since most of these are just stubs for now and not really full emulation of
>> the device I'd leave them in one file similar to ppc405 for now. They both
>> could be cleaned up later if it's found necessary or devices that are deemed
>> ready and big enough to be moved out could be split off (like I did with i2c
>> and pcix). If you insist, I can split it now but I think it's more difficult
>> to work with a lot of small files scattered in hw instead of everything
>> related to ppc440 in one place until there's still missing fucntionality. I
>> consider splitting it up cleanup which could be done later separately unless
>> it's a requirement to get this series in.
>
> Ok, that's a reasonable argument.  Go ahead and put them in a
> ppc440_uc.c file.

I already did in the non RFC submission of the series I've sent last 
Sunday (in [PATCH 14/15] ppc4xx: Add device models found in PPC440 core).

^ permalink raw reply	[flat|nested] 49+ messages in thread

end of thread, other threads:[~2017-08-23  0:48 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-13 17:04 [Qemu-devel] [RFC PATCH 00/12] Sam460ex emulation BALATON Zoltan
2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs BALATON Zoltan
2017-08-18  1:53   ` David Gibson
2017-08-18 11:07     ` François Revol
2017-08-18 12:15       ` [Qemu-devel] [Qemu-ppc] " BALATON Zoltan
2017-08-18 12:18       ` [Qemu-devel] " David Gibson
2017-08-18  9:30   ` [Qemu-devel] [Qemu-ppc] " luigi burdo
2017-08-18 11:20     ` François Revol
2017-08-18 13:03       ` BALATON Zoltan
2017-08-18 12:34     ` BALATON Zoltan
2017-08-18 19:43       ` luigi burdo
2017-08-18 20:52         ` François Revol
2017-08-19 10:03         ` BALATON Zoltan
2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 06/12] ppc4xx_i2c: QOMify BALATON Zoltan
2017-08-15  4:17   ` David Gibson
2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 08/12] hw/ide: Emulate SiI3112 SATA controller BALATON Zoltan
2017-08-14  4:42   ` David Gibson
2017-08-14 11:16     ` BALATON Zoltan
2017-08-15 11:40       ` David Gibson
2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 02/12] ppc4xx: Make MAL emulation more generic BALATON Zoltan
2017-08-15  4:11   ` David Gibson
2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 04/12] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs BALATON Zoltan
2017-08-14  4:36   ` David Gibson
2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 03/12] ohci: Allow sysbus version to be used as a companion BALATON Zoltan
2017-08-15  4:13   ` David Gibson
2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 07/12] ppc4xx_i2c: Implement basic I2C functions BALATON Zoltan
2017-08-18  1:42   ` David Gibson
2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 11/12] ppc4xx: Export ECB and PLB emulation BALATON Zoltan
2017-08-14  4:44   ` David Gibson
2017-08-14 11:06     ` BALATON Zoltan
2017-08-18  6:11       ` David Gibson
2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 05/12] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file BALATON Zoltan
2017-08-14  4:41   ` David Gibson
2017-08-14  9:00   ` Paolo Bonzini
2017-08-14 11:18     ` BALATON Zoltan
2017-08-14 14:19       ` Paolo Bonzini
2017-08-14 14:25       ` Peter Maydell
2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 01/12] ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs BALATON Zoltan
2017-08-14  4:37   ` David Gibson
2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 12/12] ppc: Add aCube Sam460ex board BALATON Zoltan
2017-08-18  6:10   ` David Gibson
2017-08-18 11:24     ` François Revol
2017-08-18 12:46     ` BALATON Zoltan
2017-08-22  2:35       ` David Gibson
2017-08-22 11:18         ` BALATON Zoltan
2017-08-23  0:35           ` David Gibson
2017-08-23  0:48             ` BALATON Zoltan
2017-08-13 17:04 ` [Qemu-devel] [RFC PATCH 10/12] ppc: Add 460EX embedded CPU BALATON Zoltan
2017-08-14  4:40   ` David Gibson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.