]> git.proxmox.com Git - qemu.git/blobdiff - hw/tusb6010.c
msi: Guard msi/msix_write_config with msi_present
[qemu.git] / hw / tusb6010.c
index 6f37779135e92ce2f6f4c0ac124034e0ae5dd653..5ba8da6d6adeb97aae568f95c071e805225051e2 100644 (file)
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "qemu-common.h"
 #include "qemu-timer.h"
 #include "omap.h"
 #include "irq.h"
 #include "devices.h"
+#include "sysbus.h"
 
-struct tusb_s {
-    int iomemtype[2];
+typedef struct TUSBState {
+    SysBusDevice busdev;
+    MemoryRegion iomem[2];
     qemu_irq irq;
-    struct musb_s *musb;
+    MUSBState *musb;
     QEMUTimer *otg_timer;
     QEMUTimer *pwr_timer;
 
@@ -61,7 +61,7 @@ struct tusb_s {
     uint32_t pullup[2];
     uint32_t control_config;
     uint32_t otg_timer_val;
-};
+} TUSBState;
 
 #define TUSB_DEVCLOCK                  60000000        /* 60 MHz */
 
@@ -236,17 +236,7 @@ struct tusb_s {
 #define TUSB_EP_CONFIG_XFR_SIZE(v)     ((v) & 0x7fffffff)
 #define TUSB_PROD_TEST_RESET_VAL       0xa596
 
-int tusb6010_sync_io(struct tusb_s *s)
-{
-    return s->iomemtype[0];
-}
-
-int tusb6010_async_io(struct tusb_s *s)
-{
-    return s->iomemtype[1];
-}
-
-static void tusb_intr_update(struct tusb_s *s)
+static void tusb_intr_update(TUSBState *s)
 {
     if (s->control_config & TUSB_INT_CTRL_CONF_INT_POLARITY)
         qemu_set_irq(s->irq, s->intr & ~s->mask & s->intr_ok);
@@ -254,7 +244,7 @@ static void tusb_intr_update(struct tusb_s *s)
         qemu_set_irq(s->irq, (!(s->intr & ~s->mask)) & s->intr_ok);
 }
 
-static void tusb_usbip_intr_update(struct tusb_s *s)
+static void tusb_usbip_intr_update(TUSBState *s)
 {
     /* TX interrupt in the MUSB */
     if (s->usbip_intr & 0x0000ffff & ~s->usbip_mask)
@@ -273,7 +263,7 @@ static void tusb_usbip_intr_update(struct tusb_s *s)
     tusb_intr_update(s);
 }
 
-static void tusb_dma_intr_update(struct tusb_s *s)
+static void tusb_dma_intr_update(TUSBState *s)
 {
     if (s->dma_intr & ~s->dma_mask)
         s->intr |= TUSB_INT_SRC_TXRX_DMA_DONE;
@@ -283,17 +273,17 @@ static void tusb_dma_intr_update(struct tusb_s *s)
     tusb_intr_update(s);
 }
 
-static void tusb_gpio_intr_update(struct tusb_s *s)
+static void tusb_gpio_intr_update(TUSBState *s)
 {
     /* TODO: How is this signalled?  */
 }
 
-extern CPUReadMemoryFunc *musb_read[];
-extern CPUWriteMemoryFunc *musb_write[];
+extern CPUReadMemoryFunc * const musb_read[];
+extern CPUWriteMemoryFunc * const musb_write[];
 
 static uint32_t tusb_async_readb(void *opaque, target_phys_addr_t addr)
 {
-    struct tusb_s *s = (struct tusb_s *) opaque;
+    TUSBState *s = (TUSBState *) opaque;
 
     switch (addr & 0xfff) {
     case TUSB_BASE_OFFSET ... (TUSB_BASE_OFFSET | 0x1ff):
@@ -310,7 +300,7 @@ static uint32_t tusb_async_readb(void *opaque, target_phys_addr_t addr)
 
 static uint32_t tusb_async_readh(void *opaque, target_phys_addr_t addr)
 {
-    struct tusb_s *s = (struct tusb_s *) opaque;
+    TUSBState *s = (TUSBState *) opaque;
 
     switch (addr & 0xfff) {
     case TUSB_BASE_OFFSET ... (TUSB_BASE_OFFSET | 0x1ff):
@@ -327,7 +317,7 @@ static uint32_t tusb_async_readh(void *opaque, target_phys_addr_t addr)
 
 static uint32_t tusb_async_readw(void *opaque, target_phys_addr_t addr)
 {
-    struct tusb_s *s = (struct tusb_s *) opaque;
+    TUSBState *s = (TUSBState *) opaque;
     int offset = addr & 0xfff;
     int epnum;
     uint32_t ret;
@@ -427,7 +417,6 @@ static uint32_t tusb_async_readw(void *opaque, target_phys_addr_t addr)
         return s->rx_config[epnum];
     case TUSB_EP_MAX_PACKET_SIZE_OFFSET ...
             (TUSB_EP_MAX_PACKET_SIZE_OFFSET + 0x3b):
-        epnum = (offset - TUSB_EP_MAX_PACKET_SIZE_OFFSET) >> 2;
         return 0x00000000;     /* TODO */
     case TUSB_WAIT_COUNT:
         return 0x00;           /* TODO */
@@ -452,7 +441,7 @@ static uint32_t tusb_async_readw(void *opaque, target_phys_addr_t addr)
 static void tusb_async_writeb(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
-    struct tusb_s *s = (struct tusb_s *) opaque;
+    TUSBState *s = (TUSBState *) opaque;
 
     switch (addr & 0xfff) {
     case TUSB_BASE_OFFSET ... (TUSB_BASE_OFFSET | 0x1ff):
@@ -473,7 +462,7 @@ static void tusb_async_writeb(void *opaque, target_phys_addr_t addr,
 static void tusb_async_writeh(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
-    struct tusb_s *s = (struct tusb_s *) opaque;
+    TUSBState *s = (TUSBState *) opaque;
 
     switch (addr & 0xfff) {
     case TUSB_BASE_OFFSET ... (TUSB_BASE_OFFSET | 0x1ff):
@@ -494,7 +483,7 @@ static void tusb_async_writeh(void *opaque, target_phys_addr_t addr,
 static void tusb_async_writew(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
-    struct tusb_s *s = (struct tusb_s *) opaque;
+    TUSBState *s = (TUSBState *) opaque;
     int offset = addr & 0xfff;
     int epnum;
 
@@ -514,8 +503,7 @@ static void tusb_async_writew(void *opaque, target_phys_addr_t addr,
         s->dev_config = value;
         s->host_mode = (value & TUSB_DEV_CONF_USB_HOST_MODE);
         if (value & TUSB_DEV_CONF_PROD_TEST_MODE)
-            cpu_abort(cpu_single_env, "%s: Product Test mode not allowed\n",
-                            __FUNCTION__);
+            hw_error("%s: Product Test mode not allowed\n", __FUNCTION__);
         break;
 
     case TUSB_PHY_OTG_CTRL_ENABLE:
@@ -524,9 +512,9 @@ static void tusb_async_writew(void *opaque, target_phys_addr_t addr,
     case TUSB_DEV_OTG_TIMER:
         s->otg_timer_val = value;
         if (value & TUSB_DEV_OTG_TIMER_ENABLE)
-            qemu_mod_timer(s->otg_timer, qemu_get_clock(vm_clock) +
+            qemu_mod_timer(s->otg_timer, qemu_get_clock_ns(vm_clock) +
                             muldiv64(TUSB_DEV_OTG_TIMER_VAL(value),
-                                    ticks_per_sec, TUSB_DEVCLOCK));
+                                     get_ticks_per_sec(), TUSB_DEVCLOCK));
         else
             qemu_del_timer(s->otg_timer);
         break;
@@ -633,7 +621,6 @@ static void tusb_async_writew(void *opaque, target_phys_addr_t addr,
         break;
     case TUSB_EP_MAX_PACKET_SIZE_OFFSET ...
             (TUSB_EP_MAX_PACKET_SIZE_OFFSET + 0x3b):
-        epnum = (offset - TUSB_EP_MAX_PACKET_SIZE_OFFSET) >> 2;
         return;                /* TODO */
     case TUSB_WAIT_COUNT:
         return;                /* TODO */
@@ -652,21 +639,17 @@ static void tusb_async_writew(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc *tusb_async_readfn[] = {
-    tusb_async_readb,
-    tusb_async_readh,
-    tusb_async_readw,
-};
-
-static CPUWriteMemoryFunc *tusb_async_writefn[] = {
-    tusb_async_writeb,
-    tusb_async_writeh,
-    tusb_async_writew,
+static const MemoryRegionOps tusb_async_ops = {
+    .old_mmio = {
+        .read = { tusb_async_readb, tusb_async_readh, tusb_async_readw, },
+        .write =  { tusb_async_writeb, tusb_async_writeh, tusb_async_writew, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void tusb_otg_tick(void *opaque)
 {
-    struct tusb_s *s = (struct tusb_s *) opaque;
+    TUSBState *s = (TUSBState *) opaque;
 
     s->otg_timer_val = 0;
     s->intr |= TUSB_INT_SRC_OTG_TIMEOUT;
@@ -675,7 +658,7 @@ static void tusb_otg_tick(void *opaque)
 
 static void tusb_power_tick(void *opaque)
 {
-    struct tusb_s *s = (struct tusb_s *) opaque;
+    TUSBState *s = (TUSBState *) opaque;
 
     if (s->power) {
         s->intr_ok = ~0;
@@ -685,7 +668,7 @@ static void tusb_power_tick(void *opaque)
 
 static void tusb_musb_core_intr(void *opaque, int source, int level)
 {
-    struct tusb_s *s = (struct tusb_s *) opaque;
+    TUSBState *s = (TUSBState *) opaque;
     uint16_t otg_status = s->otg_status;
 
     switch (source) {
@@ -732,9 +715,33 @@ static void tusb_musb_core_intr(void *opaque, int source, int level)
     }
 }
 
-struct tusb_s *tusb6010_init(qemu_irq intr)
+static void tusb6010_power(TUSBState *s, int on)
 {
-    struct tusb_s *s = qemu_mallocz(sizeof(*s));
+    if (!on) {
+        s->power = 0;
+    } else if (!s->power && on) {
+        s->power = 1;
+        /* Pull the interrupt down after TUSB6010 comes up.  */
+        s->intr_ok = 0;
+        tusb_intr_update(s);
+        qemu_mod_timer(s->pwr_timer,
+                       qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 2);
+    }
+}
+
+static void tusb6010_irq(void *opaque, int source, int level)
+{
+    if (source) {
+        tusb_musb_core_intr(opaque, source - 1, level);
+    } else {
+        tusb6010_power(opaque, level);
+    }
+}
+
+static void tusb6010_reset(DeviceState *dev)
+{
+    TUSBState *s = FROM_SYSBUS(TUSBState, sysbus_from_qdev(dev));
+    int i;
 
     s->test_reset = TUSB_PROD_TEST_RESET_VAL;
     s->host_mode = 0;
@@ -744,28 +751,63 @@ struct tusb_s *tusb6010_init(qemu_irq intr)
     s->mask = 0xffffffff;
     s->intr = 0x00000000;
     s->otg_timer_val = 0;
-    s->iomemtype[1] = cpu_register_io_memory(0, tusb_async_readfn,
-                    tusb_async_writefn, s);
-    s->irq = intr;
-    s->otg_timer = qemu_new_timer(vm_clock, tusb_otg_tick, s);
-    s->pwr_timer = qemu_new_timer(vm_clock, tusb_power_tick, s);
-    s->musb = musb_init(qemu_allocate_irqs(tusb_musb_core_intr, s,
-                            __musb_irq_max));
-
-    return s;
+    s->scratch = 0;
+    s->prcm_config = 0;
+    s->prcm_mngmt = 0;
+    s->intr_ok = 0;
+    s->usbip_intr = 0;
+    s->usbip_mask = 0;
+    s->gpio_intr = 0;
+    s->gpio_mask = 0;
+    s->gpio_config = 0;
+    s->dma_intr = 0;
+    s->dma_mask = 0;
+    s->dma_map = 0;
+    s->dma_config = 0;
+    s->ep0_config = 0;
+    s->wkup_mask = 0;
+    s->pullup[0] = s->pullup[1] = 0;
+    s->control_config = 0;
+    for (i = 0; i < 15; i++) {
+        s->rx_config[i] = s->tx_config[i] = 0;
+    }
+    musb_reset(s->musb);
 }
 
-void tusb6010_power(struct tusb_s *s, int on)
+static int tusb6010_init(SysBusDevice *dev)
 {
-    if (!on)
-        s->power = 0;
-    else if (!s->power && on) {
-        s->power = 1;
+    TUSBState *s = FROM_SYSBUS(TUSBState, dev);
+    s->otg_timer = qemu_new_timer_ns(vm_clock, tusb_otg_tick, s);
+    s->pwr_timer = qemu_new_timer_ns(vm_clock, tusb_power_tick, s);
+    memory_region_init_io(&s->iomem[1], &tusb_async_ops, s, "tusb-async",
+                          UINT32_MAX);
+    sysbus_init_mmio(dev, &s->iomem[0]);
+    sysbus_init_mmio(dev, &s->iomem[1]);
+    sysbus_init_irq(dev, &s->irq);
+    qdev_init_gpio_in(&dev->qdev, tusb6010_irq, musb_irq_max + 1);
+    s->musb = musb_init(&dev->qdev, 1);
+    return 0;
+}
 
-        /* Pull the interrupt down after TUSB6010 comes up.  */
-        s->intr_ok = 0;
-        tusb_intr_update(s);
-        qemu_mod_timer(s->pwr_timer,
-                        qemu_get_clock(vm_clock) + ticks_per_sec / 2);
-    }
+static void tusb6010_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = tusb6010_init;
+    dc->reset = tusb6010_reset;
+}
+
+static TypeInfo tusb6010_info = {
+    .name          = "tusb6010",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(TUSBState),
+    .class_init    = tusb6010_class_init,
+};
+
+static void tusb6010_register_types(void)
+{
+    type_register_static(&tusb6010_info);
 }
+
+type_init(tusb6010_register_types)