Commit e24ad6f140f23e1edc1646ea248819698b77f0e2

Authored by pbrook
1 parent 60a9f9ec

OHCI USB PXA support (Andrzej Zaborowski).


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2490 c046a42c-6fe2-441c-8c8c-71466251a162
hw/ppc_chrp.c
@@ -501,7 +501,7 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device, @@ -501,7 +501,7 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
501 } 501 }
502 502
503 if (usb_enabled) { 503 if (usb_enabled) {
504 - usb_ohci_init(pci_bus, 3, -1); 504 + usb_ohci_init_pci(pci_bus, 3, -1);
505 } 505 }
506 506
507 if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8) 507 if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
hw/ppc_prep.c
@@ -666,7 +666,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device, @@ -666,7 +666,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
666 #endif 666 #endif
667 667
668 if (usb_enabled) { 668 if (usb_enabled) {
669 - usb_ohci_init(pci_bus, 3, -1); 669 + usb_ohci_init_pci(pci_bus, 3, -1);
670 } 670 }
671 671
672 nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE, 59); 672 nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE, 59);
hw/realview.c
@@ -57,7 +57,7 @@ static void realview_init(int ram_size, int vga_ram_size, int boot_device, @@ -57,7 +57,7 @@ static void realview_init(int ram_size, int vga_ram_size, int boot_device,
57 57
58 pci_bus = pci_vpb_init(pic, 48, 1); 58 pci_bus = pci_vpb_init(pic, 48, 1);
59 if (usb_enabled) { 59 if (usb_enabled) {
60 - usb_ohci_init(pci_bus, 3, -1); 60 + usb_ohci_init_pci(pci_bus, 3, -1);
61 } 61 }
62 scsi_hba = lsi_scsi_init(pci_bus, -1); 62 scsi_hba = lsi_scsi_init(pci_bus, -1);
63 for (n = 0; n < MAX_DISKS; n++) { 63 for (n = 0; n < MAX_DISKS; n++) {
hw/usb-ohci.c
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 * QEMU USB OHCI Emulation 2 * QEMU USB OHCI Emulation
3 * Copyright (c) 2004 Gianni Tedesco 3 * Copyright (c) 2004 Gianni Tedesco
4 * Copyright (c) 2006 CodeSourcery 4 * Copyright (c) 2006 CodeSourcery
  5 + * Copyright (c) 2006 Openedhand Ltd.
5 * 6 *
6 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public 8 * modify it under the terms of the GNU Lesser General Public
@@ -52,11 +53,19 @@ typedef struct OHCIPort { @@ -52,11 +53,19 @@ typedef struct OHCIPort {
52 uint32_t ctrl; 53 uint32_t ctrl;
53 } OHCIPort; 54 } OHCIPort;
54 55
  56 +enum ohci_type {
  57 + OHCI_TYPE_PCI,
  58 + OHCI_TYPE_PXA
  59 +};
  60 +
55 typedef struct { 61 typedef struct {
56 - struct PCIDevice pci_dev; 62 + void *pic;
  63 + int irq;
  64 + enum ohci_type type;
57 target_phys_addr_t mem_base; 65 target_phys_addr_t mem_base;
58 int mem; 66 int mem;
59 int num_ports; 67 int num_ports;
  68 + const char *name;
60 69
61 QEMUTimer *eof_timer; 70 QEMUTimer *eof_timer;
62 int64_t sof_time; 71 int64_t sof_time;
@@ -90,6 +99,12 @@ typedef struct { @@ -90,6 +99,12 @@ typedef struct {
90 uint32_t rhstatus; 99 uint32_t rhstatus;
91 OHCIPort rhport[OHCI_MAX_PORTS]; 100 OHCIPort rhport[OHCI_MAX_PORTS];
92 101
  102 + /* PXA27x Non-OHCI events */
  103 + uint32_t hstatus;
  104 + uint32_t hmask;
  105 + uint32_t hreset;
  106 + uint32_t htest;
  107 +
93 /* Active packets. */ 108 /* Active packets. */
94 uint32_t old_ctl; 109 uint32_t old_ctl;
95 USBPacket usb_packet; 110 USBPacket usb_packet;
@@ -256,6 +271,8 @@ struct ohci_td { @@ -256,6 +271,8 @@ struct ohci_td {
256 #define OHCI_CC_BUFFEROVERRUN 0xc 271 #define OHCI_CC_BUFFEROVERRUN 0xc
257 #define OHCI_CC_BUFFERUNDERRUN 0xd 272 #define OHCI_CC_BUFFERUNDERRUN 0xd
258 273
  274 +#define OHCI_HRESET_FSBIR (1 << 0)
  275 +
259 /* Update IRQ levels */ 276 /* Update IRQ levels */
260 static inline void ohci_intr_update(OHCIState *ohci) 277 static inline void ohci_intr_update(OHCIState *ohci)
261 { 278 {
@@ -265,7 +282,10 @@ static inline void ohci_intr_update(OHCIState *ohci) @@ -265,7 +282,10 @@ static inline void ohci_intr_update(OHCIState *ohci)
265 (ohci->intr_status & ohci->intr)) 282 (ohci->intr_status & ohci->intr))
266 level = 1; 283 level = 1;
267 284
268 - pci_set_irq(&ohci->pci_dev, 0, level); 285 + if (ohci->type == OHCI_TYPE_PCI)
  286 + pci_set_irq((PCIDevice *)ohci->pic, ohci->irq, level);
  287 + else
  288 + pic_set_irq_new(ohci->pic, ohci->irq, level);
269 } 289 }
270 290
271 /* Set an interrupt */ 291 /* Set an interrupt */
@@ -295,6 +315,11 @@ static void ohci_attach(USBPort *port1, USBDevice *dev) @@ -295,6 +315,11 @@ static void ohci_attach(USBPort *port1, USBDevice *dev)
295 else 315 else
296 port->ctrl &= ~OHCI_PORT_LSDA; 316 port->ctrl &= ~OHCI_PORT_LSDA;
297 port->port.dev = dev; 317 port->port.dev = dev;
  318 +
  319 + /* notify of remote-wakeup */
  320 + if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND)
  321 + ohci_set_interrupt(s, OHCI_INTR_RD);
  322 +
298 /* send the attach message */ 323 /* send the attach message */
299 usb_send_msg(dev, USB_MSG_ATTACH); 324 usb_send_msg(dev, USB_MSG_ATTACH);
300 dprintf("usb-ohci: Attached port %d\n", port1->index); 325 dprintf("usb-ohci: Attached port %d\n", port1->index);
@@ -367,7 +392,7 @@ static void ohci_reset(OHCIState *ohci) @@ -367,7 +392,7 @@ static void ohci_reset(OHCIState *ohci)
367 usb_cancel_packet(&ohci->usb_packet); 392 usb_cancel_packet(&ohci->usb_packet);
368 ohci->async_td = 0; 393 ohci->async_td = 0;
369 } 394 }
370 - dprintf("usb-ohci: Reset %s\n", ohci->pci_dev.name); 395 + dprintf("usb-ohci: Reset %s\n", ohci->name);
371 } 396 }
372 397
373 /* Get an array of dwords from main memory */ 398 /* Get an array of dwords from main memory */
@@ -795,13 +820,12 @@ static int ohci_bus_start(OHCIState *ohci) @@ -795,13 +820,12 @@ static int ohci_bus_start(OHCIState *ohci)
795 ohci); 820 ohci);
796 821
797 if (ohci->eof_timer == NULL) { 822 if (ohci->eof_timer == NULL) {
798 - fprintf(stderr, "usb-ohci: %s: qemu_new_timer failed\n",  
799 - ohci->pci_dev.name); 823 + fprintf(stderr, "usb-ohci: %s: qemu_new_timer failed\n", ohci->name);
800 /* TODO: Signal unrecoverable error */ 824 /* TODO: Signal unrecoverable error */
801 return 0; 825 return 0;
802 } 826 }
803 827
804 - dprintf("usb-ohci: %s: USB Operational\n", ohci->pci_dev.name); 828 + dprintf("usb-ohci: %s: USB Operational\n", ohci->name);
805 829
806 ohci_sof(ohci); 830 ohci_sof(ohci);
807 831
@@ -854,7 +878,7 @@ static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val) @@ -854,7 +878,7 @@ static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val)
854 878
855 if (val != ohci->fi) { 879 if (val != ohci->fi) {
856 dprintf("usb-ohci: %s: FrameInterval = 0x%x (%u)\n", 880 dprintf("usb-ohci: %s: FrameInterval = 0x%x (%u)\n",
857 - ohci->pci_dev.name, ohci->fi, ohci->fi); 881 + ohci->name, ohci->fi, ohci->fi);
858 } 882 }
859 883
860 ohci->fi = val; 884 ohci->fi = val;
@@ -892,13 +916,13 @@ static void ohci_set_ctl(OHCIState *ohci, uint32_t val) @@ -892,13 +916,13 @@ static void ohci_set_ctl(OHCIState *ohci, uint32_t val)
892 break; 916 break;
893 case OHCI_USB_SUSPEND: 917 case OHCI_USB_SUSPEND:
894 ohci_bus_stop(ohci); 918 ohci_bus_stop(ohci);
895 - dprintf("usb-ohci: %s: USB Suspended\n", ohci->pci_dev.name); 919 + dprintf("usb-ohci: %s: USB Suspended\n", ohci->name);
896 break; 920 break;
897 case OHCI_USB_RESUME: 921 case OHCI_USB_RESUME:
898 - dprintf("usb-ohci: %s: USB Resume\n", ohci->pci_dev.name); 922 + dprintf("usb-ohci: %s: USB Resume\n", ohci->name);
899 break; 923 break;
900 case OHCI_USB_RESET: 924 case OHCI_USB_RESET:
901 - dprintf("usb-ohci: %s: USB Reset\n", ohci->pci_dev.name); 925 + dprintf("usb-ohci: %s: USB Reset\n", ohci->name);
902 break; 926 break;
903 } 927 }
904 } 928 }
@@ -1086,6 +1110,19 @@ static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr) @@ -1086,6 +1110,19 @@ static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr)
1086 case 20: /* HcRhStatus */ 1110 case 20: /* HcRhStatus */
1087 return ohci->rhstatus; 1111 return ohci->rhstatus;
1088 1112
  1113 + /* PXA27x specific registers */
  1114 + case 24: /* HcStatus */
  1115 + return ohci->hstatus & ohci->hmask;
  1116 +
  1117 + case 25: /* HcHReset */
  1118 + return ohci->hreset;
  1119 +
  1120 + case 26: /* HcHInterruptEnable */
  1121 + return ohci->hmask;
  1122 +
  1123 + case 27: /* HcHInterruptTest */
  1124 + return ohci->htest;
  1125 +
1089 default: 1126 default:
1090 fprintf(stderr, "ohci_read: Bad offset %x\n", (int)addr); 1127 fprintf(stderr, "ohci_read: Bad offset %x\n", (int)addr);
1091 return 0xffffffff; 1128 return 0xffffffff;
@@ -1187,6 +1224,24 @@ static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val) @@ -1187,6 +1224,24 @@ static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val)
1187 ohci_set_hub_status(ohci, val); 1224 ohci_set_hub_status(ohci, val);
1188 break; 1225 break;
1189 1226
  1227 + /* PXA27x specific registers */
  1228 + case 24: /* HcStatus */
  1229 + ohci->hstatus &= ~(val & ohci->hmask);
  1230 +
  1231 + case 25: /* HcHReset */
  1232 + ohci->hreset = val & ~OHCI_HRESET_FSBIR;
  1233 + if (val & OHCI_HRESET_FSBIR)
  1234 + ohci_reset(ohci);
  1235 + break;
  1236 +
  1237 + case 26: /* HcHInterruptEnable */
  1238 + ohci->hmask = val;
  1239 + break;
  1240 +
  1241 + case 27: /* HcHInterruptTest */
  1242 + ohci->htest = val;
  1243 + break;
  1244 +
1190 default: 1245 default:
1191 fprintf(stderr, "ohci_write: Bad offset %x\n", (int)addr); 1246 fprintf(stderr, "ohci_write: Bad offset %x\n", (int)addr);
1192 break; 1247 break;
@@ -1207,22 +1262,11 @@ static CPUWriteMemoryFunc *ohci_writefn[3]={ @@ -1207,22 +1262,11 @@ static CPUWriteMemoryFunc *ohci_writefn[3]={
1207 ohci_mem_write 1262 ohci_mem_write
1208 }; 1263 };
1209 1264
1210 -static void ohci_mapfunc(PCIDevice *pci_dev, int i,  
1211 - uint32_t addr, uint32_t size, int type)  
1212 -{  
1213 - OHCIState *ohci = (OHCIState *)pci_dev;  
1214 - ohci->mem_base = addr;  
1215 - cpu_register_physical_memory(addr, size, ohci->mem);  
1216 -}  
1217 -  
1218 -void usb_ohci_init(struct PCIBus *bus, int num_ports, int devfn) 1265 +static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn,
  1266 + void *pic, int irq, enum ohci_type type, const char *name)
1219 { 1267 {
1220 - OHCIState *ohci;  
1221 - int vid = 0x106b;  
1222 - int did = 0x003f;  
1223 int i; 1268 int i;
1224 1269
1225 -  
1226 if (usb_frame_time == 0) { 1270 if (usb_frame_time == 0) {
1227 #if OHCI_TIME_WARP 1271 #if OHCI_TIME_WARP
1228 usb_frame_time = ticks_per_sec; 1272 usb_frame_time = ticks_per_sec;
@@ -1239,8 +1283,43 @@ void usb_ohci_init(struct PCIBus *bus, int num_ports, int devfn) @@ -1239,8 +1283,43 @@ void usb_ohci_init(struct PCIBus *bus, int num_ports, int devfn)
1239 usb_frame_time, usb_bit_time); 1283 usb_frame_time, usb_bit_time);
1240 } 1284 }
1241 1285
1242 - ohci = (OHCIState *)pci_register_device(bus, "OHCI USB", sizeof(*ohci),  
1243 - devfn, NULL, NULL); 1286 + ohci->mem = cpu_register_io_memory(0, ohci_readfn, ohci_writefn, ohci);
  1287 + ohci->name = name;
  1288 +
  1289 + ohci->pic = pic;
  1290 + ohci->irq = irq;
  1291 + ohci->type = type;
  1292 +
  1293 + ohci->num_ports = num_ports;
  1294 + for (i = 0; i < num_ports; i++) {
  1295 + qemu_register_usb_port(&ohci->rhport[i].port, ohci, i, ohci_attach);
  1296 + }
  1297 +
  1298 + ohci->async_td = 0;
  1299 + ohci_reset(ohci);
  1300 +}
  1301 +
  1302 +typedef struct {
  1303 + PCIDevice pci_dev;
  1304 + OHCIState state;
  1305 +} OHCIPCIState;
  1306 +
  1307 +static void ohci_mapfunc(PCIDevice *pci_dev, int i,
  1308 + uint32_t addr, uint32_t size, int type)
  1309 +{
  1310 + OHCIPCIState *ohci = (OHCIPCIState *)pci_dev;
  1311 + ohci->state.mem_base = addr;
  1312 + cpu_register_physical_memory(addr, size, ohci->state.mem);
  1313 +}
  1314 +
  1315 +void usb_ohci_init_pci(struct PCIBus *bus, int num_ports, int devfn)
  1316 +{
  1317 + OHCIPCIState *ohci;
  1318 + int vid = 0x106b;
  1319 + int did = 0x003f;
  1320 +
  1321 + ohci = (OHCIPCIState *)pci_register_device(bus, "OHCI USB", sizeof(*ohci),
  1322 + devfn, NULL, NULL);
1244 if (ohci == NULL) { 1323 if (ohci == NULL) {
1245 fprintf(stderr, "usb-ohci: Failed to register PCI device\n"); 1324 fprintf(stderr, "usb-ohci: Failed to register PCI device\n");
1246 return; 1325 return;
@@ -1255,16 +1334,21 @@ void usb_ohci_init(struct PCIBus *bus, int num_ports, int devfn) @@ -1255,16 +1334,21 @@ void usb_ohci_init(struct PCIBus *bus, int num_ports, int devfn)
1255 ohci->pci_dev.config[0x0b] = 0xc; 1334 ohci->pci_dev.config[0x0b] = 0xc;
1256 ohci->pci_dev.config[0x3d] = 0x01; /* interrupt pin 1 */ 1335 ohci->pci_dev.config[0x3d] = 0x01; /* interrupt pin 1 */
1257 1336
1258 - ohci->mem = cpu_register_io_memory(0, ohci_readfn, ohci_writefn, ohci); 1337 + usb_ohci_init(&ohci->state, num_ports, devfn, &ohci->pci_dev,
  1338 + 0, OHCI_TYPE_PCI, ohci->pci_dev.name);
1259 1339
1260 pci_register_io_region((struct PCIDevice *)ohci, 0, 256, 1340 pci_register_io_region((struct PCIDevice *)ohci, 0, 256,
1261 PCI_ADDRESS_SPACE_MEM, ohci_mapfunc); 1341 PCI_ADDRESS_SPACE_MEM, ohci_mapfunc);
  1342 +}
1262 1343
1263 - ohci->num_ports = num_ports;  
1264 - for (i = 0; i < num_ports; i++) {  
1265 - qemu_register_usb_port(&ohci->rhport[i].port, ohci, i, ohci_attach);  
1266 - } 1344 +void usb_ohci_init_pxa(target_phys_addr_t base, int num_ports, int devfn,
  1345 + void *pic, int irq)
  1346 +{
  1347 + OHCIState *ohci = (OHCIState *)qemu_mallocz(sizeof(OHCIState));
1267 1348
1268 - ohci->async_td = 0;  
1269 - ohci_reset(ohci); 1349 + usb_ohci_init(ohci, num_ports, devfn, pic, irq,
  1350 + OHCI_TYPE_PXA, "OHCI USB");
  1351 + ohci->mem_base = base;
  1352 +
  1353 + cpu_register_physical_memory(ohci->mem_base, 0xfff, ohci->mem);
1270 } 1354 }
hw/usb.h
@@ -206,7 +206,9 @@ USBDevice *usb_hub_init(int nb_ports); @@ -206,7 +206,9 @@ USBDevice *usb_hub_init(int nb_ports);
206 void usb_uhci_init(PCIBus *bus, int devfn); 206 void usb_uhci_init(PCIBus *bus, int devfn);
207 207
208 /* usb-ohci.c */ 208 /* usb-ohci.c */
209 -void usb_ohci_init(struct PCIBus *bus, int num_ports, int devfn); 209 +void usb_ohci_init_pci(struct PCIBus *bus, int num_ports, int devfn);
  210 +void usb_ohci_init_pxa(target_phys_addr_t base, int num_ports, int devfn,
  211 + void *pic, int irq);
210 212
211 /* usb-linux.c */ 213 /* usb-linux.c */
212 USBDevice *usb_host_device_open(const char *devname); 214 USBDevice *usb_host_device_open(const char *devname);
hw/versatilepb.c
@@ -195,7 +195,7 @@ static void versatile_init(int ram_size, int vga_ram_size, int boot_device, @@ -195,7 +195,7 @@ static void versatile_init(int ram_size, int vga_ram_size, int boot_device,
195 } 195 }
196 } 196 }
197 if (usb_enabled) { 197 if (usb_enabled) {
198 - usb_ohci_init(pci_bus, 3, -1); 198 + usb_ohci_init_pci(pci_bus, 3, -1);
199 } 199 }
200 scsi_hba = lsi_scsi_init(pci_bus, -1); 200 scsi_hba = lsi_scsi_init(pci_bus, -1);
201 for (n = 0; n < MAX_DISKS; n++) { 201 for (n = 0; n < MAX_DISKS; n++) {