Merge commit 'gnu/master' into test
[qemu] / hw / usb-ohci.c
index 55cb77b..7c37f70 100644 (file)
@@ -16,7 +16,7 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
  *
  * TODO:
  *  o Isochronous transfers
@@ -32,6 +32,8 @@
 #include "usb.h"
 #include "pci.h"
 #include "pxa.h"
+#include "omap.h"
+#include "devices.h"
 
 //#define DEBUG_OHCI
 /* Dump packet contents.  */
@@ -60,13 +62,14 @@ typedef struct OHCIPort {
 
 enum ohci_type {
     OHCI_TYPE_PCI,
-    OHCI_TYPE_PXA
+    OHCI_TYPE_PXA,
+    OHCI_TYPE_OMAP,
+    OHCI_TYPE_SM501,
 };
 
 typedef struct {
     qemu_irq irq;
     enum ohci_type type;
-    target_phys_addr_t mem_base;
     int mem;
     int num_ports;
     const char *name;
@@ -109,6 +112,9 @@ typedef struct {
     uint32_t hreset;
     uint32_t htest;
 
+    /* SM501 local memory offset */
+    target_phys_addr_t localmem_base;
+
     /* Active packets.  */
     uint32_t old_ctl;
     USBPacket usb_packet;
@@ -426,10 +432,13 @@ static void ohci_reset(void *opaque)
 }
 
 /* Get an array of dwords from main memory */
-static inline int get_dwords(uint32_t addr, uint32_t *buf, int num)
+static inline int get_dwords(OHCIState *ohci,
+                             uint32_t addr, uint32_t *buf, int num)
 {
     int i;
 
+    addr += ohci->localmem_base;
+
     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
         cpu_physical_memory_rw(addr, (uint8_t *)buf, sizeof(*buf), 0);
         *buf = le32_to_cpu(*buf);
@@ -439,10 +448,13 @@ static inline int get_dwords(uint32_t addr, uint32_t *buf, int num)
 }
 
 /* Put an array of dwords in to main memory */
-static inline int put_dwords(uint32_t addr, uint32_t *buf, int num)
+static inline int put_dwords(OHCIState *ohci,
+                             uint32_t addr, uint32_t *buf, int num)
 {
     int i;
 
+    addr += ohci->localmem_base;
+
     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
         uint32_t tmp = cpu_to_le32(*buf);
         cpu_physical_memory_rw(addr, (uint8_t *)&tmp, sizeof(tmp), 1);
@@ -452,10 +464,13 @@ static inline int put_dwords(uint32_t addr, uint32_t *buf, int num)
 }
 
 /* Get an array of words from main memory */
-static inline int get_words(uint32_t addr, uint16_t *buf, int num)
+static inline int get_words(OHCIState *ohci,
+                            uint32_t addr, uint16_t *buf, int num)
 {
     int i;
 
+    addr += ohci->localmem_base;
+
     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
         cpu_physical_memory_rw(addr, (uint8_t *)buf, sizeof(*buf), 0);
         *buf = le16_to_cpu(*buf);
@@ -465,10 +480,13 @@ static inline int get_words(uint32_t addr, uint16_t *buf, int num)
 }
 
 /* Put an array of words in to main memory */
-static inline int put_words(uint32_t addr, uint16_t *buf, int num)
+static inline int put_words(OHCIState *ohci,
+                            uint32_t addr, uint16_t *buf, int num)
 {
     int i;
 
+    addr += ohci->localmem_base;
+
     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
         uint16_t tmp = cpu_to_le16(*buf);
         cpu_physical_memory_rw(addr, (uint8_t *)&tmp, sizeof(tmp), 1);
@@ -477,40 +495,63 @@ static inline int put_words(uint32_t addr, uint16_t *buf, int num)
     return 1;
 }
 
-static inline int ohci_read_ed(uint32_t addr, struct ohci_ed *ed)
+static inline int ohci_read_ed(OHCIState *ohci,
+                               uint32_t addr, struct ohci_ed *ed)
+{
+    return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2);
+}
+
+static inline int ohci_read_td(OHCIState *ohci,
+                               uint32_t addr, struct ohci_td *td)
+{
+    return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
+}
+
+static inline int ohci_read_iso_td(OHCIState *ohci,
+                                   uint32_t addr, struct ohci_iso_td *td)
 {
-    return get_dwords(addr, (uint32_t *)ed, sizeof(*ed) >> 2);
+    return (get_dwords(ohci, addr, (uint32_t *)td, 4) &&
+            get_words(ohci, addr + 16, td->offset, 8));
 }
 
-static inline int ohci_read_td(uint32_t addr, struct ohci_td *td)
+static inline int ohci_read_hcca(OHCIState *ohci,
+                                 uint32_t addr, struct ohci_hcca *hcca)
 {
-    return get_dwords(addr, (uint32_t *)td, sizeof(*td) >> 2);
+    cpu_physical_memory_rw(addr + ohci->localmem_base,
+                           (uint8_t *)hcca, sizeof(*hcca), 0);
+    return 1;
 }
 
-static inline int ohci_read_iso_td(uint32_t addr, struct ohci_iso_td *td)
+static inline int ohci_put_ed(OHCIState *ohci,
+                              uint32_t addr, struct ohci_ed *ed)
 {
-    return (get_dwords(addr, (uint32_t *)td, 4) &&
-            get_words(addr + 16, td->offset, 8));
+    return put_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2);
 }
 
-static inline int ohci_put_ed(uint32_t addr, struct ohci_ed *ed)
+static inline int ohci_put_td(OHCIState *ohci,
+                              uint32_t addr, struct ohci_td *td)
 {
-    return put_dwords(addr, (uint32_t *)ed, sizeof(*ed) >> 2);
+    return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
 }
 
-static inline int ohci_put_td(uint32_t addr, struct ohci_td *td)
+static inline int ohci_put_iso_td(OHCIState *ohci,
+                                  uint32_t addr, struct ohci_iso_td *td)
 {
-    return put_dwords(addr, (uint32_t *)td, sizeof(*td) >> 2);
+    return (put_dwords(ohci, addr, (uint32_t *)td, 4) &&
+            put_words(ohci, addr + 16, td->offset, 8));
 }
 
-static inline int ohci_put_iso_td(uint32_t addr, struct ohci_iso_td *td)
+static inline int ohci_put_hcca(OHCIState *ohci,
+                                uint32_t addr, struct ohci_hcca *hcca)
 {
-    return (put_dwords(addr, (uint32_t *)td, 4) &&
-            put_words(addr + 16, td->offset, 8));
+    cpu_physical_memory_rw(addr + ohci->localmem_base,
+                           (uint8_t *)hcca, sizeof(*hcca), 1);
+    return 1;
 }
 
 /* Read/Write the contents of a TD from/to main memory.  */
-static void ohci_copy_td(struct ohci_td *td, uint8_t *buf, int len, int write)
+static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
+                         uint8_t *buf, int len, int write)
 {
     uint32_t ptr;
     uint32_t n;
@@ -519,16 +560,17 @@ static void ohci_copy_td(struct ohci_td *td, uint8_t *buf, int len, int write)
     n = 0x1000 - (ptr & 0xfff);
     if (n > len)
         n = len;
-    cpu_physical_memory_rw(ptr, buf, n, write);
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write);
     if (n == len)
         return;
     ptr = td->be & ~0xfffu;
     buf += n;
-    cpu_physical_memory_rw(ptr, buf, len - n, write);
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write);
 }
 
 /* Read/Write the contents of an ISO TD from/to main memory.  */
-static void ohci_copy_iso_td(uint32_t start_addr, uint32_t end_addr,
+static void ohci_copy_iso_td(OHCIState *ohci,
+                             uint32_t start_addr, uint32_t end_addr,
                              uint8_t *buf, int len, int write)
 {
     uint32_t ptr;
@@ -538,12 +580,12 @@ static void ohci_copy_iso_td(uint32_t start_addr, uint32_t end_addr,
     n = 0x1000 - (ptr & 0xfff);
     if (n > len)
         n = len;
-    cpu_physical_memory_rw(ptr, buf, n, write);
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write);
     if (n == len)
         return;
     ptr = end_addr & ~0xfffu;
     buf += n;
-    cpu_physical_memory_rw(ptr, buf, len - n, write);
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write);
 }
 
 static void ohci_process_lists(OHCIState *ohci, int completion);
@@ -580,7 +622,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
 
     addr = ed->head & OHCI_DPTR_MASK;
 
-    if (!ohci_read_iso_td(addr, &iso_td)) {
+    if (!ohci_read_iso_td(ohci, addr, &iso_td)) {
         printf("usb-ohci: ISO_TD read error at %x\n", addr);
         return 0;
     }
@@ -622,7 +664,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
         i = OHCI_BM(iso_td.flags, TD_DI);
         if (i < ohci->done_count)
             ohci->done_count = i;
-        ohci_put_iso_td(addr, &iso_td);        
+        ohci_put_iso_td(ohci, addr, &iso_td);
         return 0;
     }
 
@@ -697,7 +739,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
     }
 
     if (len && dir != OHCI_TD_DIR_IN) {
-        ohci_copy_iso_td(start_addr, end_addr, ohci->usb_buf, len, 0);
+        ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len, 0);
     }
 
     if (completion) {
@@ -733,7 +775,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
     /* Writeback */
     if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) {
         /* IN transfer succeeded */
-        ohci_copy_iso_td(start_addr, end_addr, ohci->usb_buf, ret, 1);
+        ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret, 1);
         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
                     OHCI_CC_NOERROR);
         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret);
@@ -789,7 +831,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
         if (i < ohci->done_count)
             ohci->done_count = i;
     }
-    ohci_put_iso_td(addr, &iso_td);
+    ohci_put_iso_td(ohci, addr, &iso_td);
     return 1;
 }
 
@@ -819,7 +861,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
 #endif
         return 1;
     }
-    if (!ohci_read_td(addr, &td)) {
+    if (!ohci_read_td(ohci, addr, &td)) {
         fprintf(stderr, "usb-ohci: TD read error at %x\n", addr);
         return 0;
     }
@@ -860,7 +902,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
         }
 
         if (len && dir != OHCI_TD_DIR_IN && !completion) {
-            ohci_copy_td(&td, ohci->usb_buf, len, 0);
+            ohci_copy_td(ohci, &td, ohci->usb_buf, len, 0);
         }
     }
 
@@ -919,7 +961,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
     }
     if (ret >= 0) {
         if (dir == OHCI_TD_DIR_IN) {
-            ohci_copy_td(&td, ohci->usb_buf, ret, 1);
+            ohci_copy_td(ohci, &td, ohci->usb_buf, ret, 1);
 #ifdef DEBUG_PACKET
             dprintf("  data:");
             for (i = 0; i < ret; i++)
@@ -988,7 +1030,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
     i = OHCI_BM(td.flags, TD_DI);
     if (i < ohci->done_count)
         ohci->done_count = i;
-    ohci_put_td(addr, &td);
+    ohci_put_td(ohci, addr, &td);
     return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
 }
 
@@ -1006,7 +1048,7 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
         return 0;
 
     for (cur = head; cur; cur = next_ed) {
-        if (!ohci_read_ed(cur, &ed)) {
+        if (!ohci_read_ed(ohci, cur, &ed)) {
             fprintf(stderr, "usb-ohci: ED read error at %x\n", cur);
             return 0;
         }
@@ -1047,7 +1089,7 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
             }
         }
 
-        ohci_put_ed(cur, &ed);
+        ohci_put_ed(ohci, cur, &ed);
     }
 
     return active;
@@ -1088,7 +1130,7 @@ static void ohci_frame_boundary(void *opaque)
     OHCIState *ohci = opaque;
     struct ohci_hcca hcca;
 
-    cpu_physical_memory_rw(ohci->hcca, (uint8_t *)&hcca, sizeof(hcca), 0);
+    ohci_read_hcca(ohci, ohci->hcca, &hcca);
 
     /* Process all the lists at the end of the frame */
     if (ohci->ctl & OHCI_CTL_PLE) {
@@ -1132,7 +1174,7 @@ static void ohci_frame_boundary(void *opaque)
     ohci_sof(ohci);
 
     /* Writeback HCCA */
-    cpu_physical_memory_rw(ohci->hcca, (uint8_t *)&hcca, sizeof(hcca), 1);
+    ohci_put_hcca(ohci, ohci->hcca, &hcca);
 }
 
 /* Start sending SOF tokens across the USB bus, lists are processed in
@@ -1361,106 +1403,134 @@ static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
 static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr)
 {
     OHCIState *ohci = ptr;
-
-    addr -= ohci->mem_base;
+    uint32_t retval;
 
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
         fprintf(stderr, "usb-ohci: Mis-aligned read\n");
         return 0xffffffff;
-    }
-
-    if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
+    } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
         /* HcRhPortStatus */
-        return ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS;
+        retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS;
+    } else {
+        switch (addr >> 2) {
+        case 0: /* HcRevision */
+            retval = 0x10;
+            break;
+
+        case 1: /* HcControl */
+            retval = ohci->ctl;
+            break;
+
+        case 2: /* HcCommandStatus */
+            retval = ohci->status;
+            break;
+
+        case 3: /* HcInterruptStatus */
+            retval = ohci->intr_status;
+            break;
+
+        case 4: /* HcInterruptEnable */
+        case 5: /* HcInterruptDisable */
+            retval = ohci->intr;
+            break;
+
+        case 6: /* HcHCCA */
+            retval = ohci->hcca;
+            break;
+
+        case 7: /* HcPeriodCurrentED */
+            retval = ohci->per_cur;
+            break;
+
+        case 8: /* HcControlHeadED */
+            retval = ohci->ctrl_head;
+            break;
+
+        case 9: /* HcControlCurrentED */
+            retval = ohci->ctrl_cur;
+            break;
+
+        case 10: /* HcBulkHeadED */
+            retval = ohci->bulk_head;
+            break;
+
+        case 11: /* HcBulkCurrentED */
+            retval = ohci->bulk_cur;
+            break;
+
+        case 12: /* HcDoneHead */
+            retval = ohci->done;
+            break;
+
+        case 13: /* HcFmInterretval */
+            retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi);
+            break;
+
+        case 14: /* HcFmRemaining */
+            retval = ohci_get_frame_remaining(ohci);
+            break;
+
+        case 15: /* HcFmNumber */
+            retval = ohci->frame_number;
+            break;
+
+        case 16: /* HcPeriodicStart */
+            retval = ohci->pstart;
+            break;
+
+        case 17: /* HcLSThreshold */
+            retval = ohci->lst;
+            break;
+
+        case 18: /* HcRhDescriptorA */
+            retval = ohci->rhdesc_a;
+            break;
+
+        case 19: /* HcRhDescriptorB */
+            retval = ohci->rhdesc_b;
+            break;
+
+        case 20: /* HcRhStatus */
+            retval = ohci->rhstatus;
+            break;
+
+        /* PXA27x specific registers */
+        case 24: /* HcStatus */
+            retval = ohci->hstatus & ohci->hmask;
+            break;
+
+        case 25: /* HcHReset */
+            retval = ohci->hreset;
+            break;
+
+        case 26: /* HcHInterruptEnable */
+            retval = ohci->hmask;
+            break;
+
+        case 27: /* HcHInterruptTest */
+            retval = ohci->htest;
+            break;
+
+        default:
+            fprintf(stderr, "ohci_read: Bad offset %x\n", (int)addr);
+            retval = 0xffffffff;
+        }
     }
 
-    switch (addr >> 2) {
-    case 0: /* HcRevision */
-        return 0x10;
-
-    case 1: /* HcControl */
-        return ohci->ctl;
-
-    case 2: /* HcCommandStatus */
-        return ohci->status;
-
-    case 3: /* HcInterruptStatus */
-        return ohci->intr_status;
-
-    case 4: /* HcInterruptEnable */
-    case 5: /* HcInterruptDisable */
-        return ohci->intr;
-
-    case 6: /* HcHCCA */
-        return ohci->hcca;
-
-    case 7: /* HcPeriodCurrentED */
-        return ohci->per_cur;
-
-    case 8: /* HcControlHeadED */
-        return ohci->ctrl_head;
-
-    case 9: /* HcControlCurrentED */
-        return ohci->ctrl_cur;
-
-    case 10: /* HcBulkHeadED */
-        return ohci->bulk_head;
-
-    case 11: /* HcBulkCurrentED */
-        return ohci->bulk_cur;
-
-    case 12: /* HcDoneHead */
-        return ohci->done;
-
-    case 13: /* HcFmInterval */
-        return (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi);
-
-    case 14: /* HcFmRemaining */
-        return ohci_get_frame_remaining(ohci);
-
-    case 15: /* HcFmNumber */
-        return ohci->frame_number;
-
-    case 16: /* HcPeriodicStart */
-        return ohci->pstart;
-
-    case 17: /* HcLSThreshold */
-        return ohci->lst;
-
-    case 18: /* HcRhDescriptorA */
-        return ohci->rhdesc_a;
-
-    case 19: /* HcRhDescriptorB */
-        return ohci->rhdesc_b;
-
-    case 20: /* HcRhStatus */
-        return ohci->rhstatus;
-
-    /* PXA27x specific registers */
-    case 24: /* HcStatus */
-        return ohci->hstatus & ohci->hmask;
-
-    case 25: /* HcHReset */
-        return ohci->hreset;
-
-    case 26: /* HcHInterruptEnable */
-        return ohci->hmask;
-
-    case 27: /* HcHInterruptTest */
-        return ohci->htest;
-
-    default:
-        fprintf(stderr, "ohci_read: Bad offset %x\n", (int)addr);
-        return 0xffffffff;
-    }
+#ifdef TARGET_WORDS_BIGENDIAN
+    retval = bswap32(retval);
+#endif
+    return retval;
 }
 
 static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val)
 {
     OHCIState *ohci = ptr;
 
-    addr -= ohci->mem_base;
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
 
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
@@ -1593,7 +1663,8 @@ static CPUWriteMemoryFunc *ohci_writefn[3]={
 };
 
 static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn,
-            qemu_irq irq, enum ohci_type type, const char *name)
+                          qemu_irq irq, enum ohci_type type,
+                          const char *name, uint32_t localmem_base)
 {
     int i;
 
@@ -1614,6 +1685,7 @@ static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn,
     }
 
     ohci->mem = cpu_register_io_memory(0, ohci_readfn, ohci_writefn, ohci);
+    ohci->localmem_base = localmem_base;
     ohci->name = name;
 
     ohci->irq = irq;
@@ -1625,7 +1697,7 @@ static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn,
     }
 
     ohci->async_td = 0;
-    qemu_register_reset(ohci_reset, ohci);
+    qemu_register_reset(ohci_reset, 0, ohci);
     ohci_reset(ohci);
 }
 
@@ -1638,15 +1710,12 @@ static void ohci_mapfunc(PCIDevice *pci_dev, int i,
             uint32_t addr, uint32_t size, int type)
 {
     OHCIPCIState *ohci = (OHCIPCIState *)pci_dev;
-    ohci->state.mem_base = addr;
     cpu_register_physical_memory(addr, size, ohci->state.mem);
 }
 
 void usb_ohci_init_pci(struct PCIBus *bus, int num_ports, int devfn)
 {
     OHCIPCIState *ohci;
-    int vid = 0x106b;
-    int did = 0x003f;
 
     ohci = (OHCIPCIState *)pci_register_device(bus, "OHCI USB", sizeof(*ohci),
                                                devfn, NULL, NULL);
@@ -1655,17 +1724,15 @@ void usb_ohci_init_pci(struct PCIBus *bus, int num_ports, int devfn)
         return;
     }
 
-    ohci->pci_dev.config[0x00] = vid & 0xff;
-    ohci->pci_dev.config[0x01] = (vid >> 8) & 0xff;
-    ohci->pci_dev.config[0x02] = did & 0xff;
-    ohci->pci_dev.config[0x03] = (did >> 8) & 0xff;
+    pci_config_set_vendor_id(ohci->pci_dev.config, PCI_VENDOR_ID_APPLE);
+    pci_config_set_device_id(ohci->pci_dev.config,
+                             PCI_DEVICE_ID_APPLE_IPID_USB);
     ohci->pci_dev.config[0x09] = 0x10; /* OHCI */
-    ohci->pci_dev.config[0x0a] = 0x3;
-    ohci->pci_dev.config[0x0b] = 0xc;
+    pci_config_set_class(ohci->pci_dev.config, PCI_CLASS_SERIAL_USB);
     ohci->pci_dev.config[0x3d] = 0x01; /* interrupt pin 1 */
 
     usb_ohci_init(&ohci->state, num_ports, devfn, ohci->pci_dev.irq[0],
-                  OHCI_TYPE_PCI, ohci->pci_dev.name);
+                  OHCI_TYPE_PCI, ohci->pci_dev.name, 0);
 
     pci_register_io_region((struct PCIDevice *)ohci, 0, 256,
                            PCI_ADDRESS_SPACE_MEM, ohci_mapfunc);
@@ -1677,8 +1744,29 @@ void usb_ohci_init_pxa(target_phys_addr_t base, int num_ports, int devfn,
     OHCIState *ohci = (OHCIState *)qemu_mallocz(sizeof(OHCIState));
 
     usb_ohci_init(ohci, num_ports, devfn, irq,
-                  OHCI_TYPE_PXA, "OHCI USB");
-    ohci->mem_base = base;
+                  OHCI_TYPE_PXA, "OHCI USB", 0);
 
-    cpu_register_physical_memory(ohci->mem_base, 0x1000, ohci->mem);
+    cpu_register_physical_memory(base, 0x1000, ohci->mem);
 }
+
+void usb_ohci_init_omap(target_phys_addr_t base, uint32_t region_size,
+                       int num_ports, qemu_irq irq)
+{
+    OHCIState *ohci = (OHCIState *)qemu_mallocz(sizeof(OHCIState));
+    
+    usb_ohci_init(ohci, num_ports, -1, irq, OHCI_TYPE_OMAP, "OHCI USB" ,0);
+
+    cpu_register_physical_memory(base, 0x1000, ohci->mem);
+}
+
+void usb_ohci_init_sm501(uint32_t mmio_base, uint32_t localmem_base,
+                         int num_ports, int devfn, qemu_irq irq)
+{
+    OHCIState *ohci = (OHCIState *)qemu_mallocz(sizeof(OHCIState));
+
+    usb_ohci_init(ohci, num_ports, devfn, irq,
+                  OHCI_TYPE_SM501, "OHCI USB", localmem_base);
+
+    cpu_register_physical_memory(mmio_base, 0x1000, ohci->mem);
+}
+