2 * Raspberry Pi emulation (c) 2012-2013 Gregory Estrade
3 * This code is licensed under the GNU GPLv2 and later.
6 /* This is wrong at so many levels, but well, I'm releasing it anyway */
8 #include "qemu/osdep.h"
10 #include "hw/irq.h" /* qemu_set_irq */
11 #include "hw/usb/bcm2835_usb.h"
12 #include "migration/vmstate.h" /* VMStateDescription */
13 #include "qapi/error.h"
14 #include "sysemu/dma.h"
16 #include "bcm2835_usb_regs.h"
18 /* You may have to change these parameters to get an almost-usable mouse
20 * The problem is that frame scheduling is all done by software, so a LOT of
21 * interrupts are generated, which doesn't help... */
23 #define SOF_DELAY 5000
25 static void bcm2835_usb_update_irq(BCM2835UsbState
*s
)
30 for (n
= 0; n
< BCM2835_USB_HCHANS
; n
++) {
31 if (s
->hchan
[n
].hcint
& s
->hchan
[n
].hcintmsk
) {
35 s
->gintsts
&= ~gintsts_hcintr
;
36 if (s
->haint
& s
->haintmsk
) {
37 s
->gintsts
|= gintsts_hcintr
;
40 if ((s
->hprt0
& hprt0_prtconndet
)
41 || (s
->hprt0
& hprt0_prtenchng
)) {
42 s
->gintsts
|= gintsts_portintr
;
44 s
->gintsts
&= ~gintsts_portintr
;
47 s
->gintsts
|= gintsts_nptxfempty
| gintsts_ptxfempty
;
49 if (!(s
->gahbcfg
& gahbcfg_glblintrmsk
)) {
50 qemu_set_irq(s
->irq
, 0);
52 if (s
->gintsts
& s
->gintmsk
) {
53 qemu_set_irq(s
->irq
, 1);
55 qemu_set_irq(s
->irq
, 0);
61 static void bcm2835_usb_sof_tick(void *opaque
)
63 BCM2835UsbState
*s
= (BCM2835UsbState
*)opaque
;
66 uint32_t num
= (s
->hfnum
& 0x3fff) + SOF_INCR
;
67 s
->hfnum
= (num
& 0x3fff) | (0x3210 << 16);
68 s
->gintsts
|= gintsts_sofintr
;
70 bcm2835_usb_update_irq(s
);
72 now
= qemu_clock_get_us(QEMU_CLOCK_VIRTUAL
);
73 timer_mod(s
->sof_timer
, now
+ SOF_DELAY
);
76 static void channel_enable(BCM2835UsbHcState
*c
)
81 uint32_t epnum
= (c
->hcchar
>> hcchar_epnum_shift
) & hcchar_epnum_mask
;
82 uint32_t devaddr
= (c
->hcchar
>> hcchar_devaddr_shift
)
83 & hcchar_devaddr_mask
;
84 uint32_t xfersize
= (c
->hctsiz
>> hctsiz_xfersize_shift
)
85 & hctsiz_xfersize_mask
;
86 uint32_t pid
= (c
->hctsiz
>> hctsiz_pid_shift
) & hctsiz_pid_mask
;
87 uint32_t dma_addr
= c
->hcdma
; /* ??? */
91 if (!c
->parent
->reset_done
) {
95 if (c
->hcchar
& hcchar_epdir
) {
100 if (pid
== DWC_HCTSIZ_SETUP
) {
101 qpid
= USB_TOKEN_SETUP
;
103 qpid
= USB_TOKEN_OUT
;
107 dev
= usb_find_device(&c
->parent
->port
, devaddr
);
110 ep
= usb_ep_get(dev
, qpid
, epnum
);
111 usb_packet_setup(&c
->packet
, qpid
, ep
, 0, devaddr
, 0, 0);
114 dma_memory_read(&c
->parent
->dma_as
, dma_addr
, c
->buffer
, xfersize
);
116 usb_packet_addbuf(&c
->packet
, c
->buffer
, xfersize
);
118 usb_handle_packet(dev
, &c
->packet
);
120 if (c
->packet
.status
== USB_RET_SUCCESS
) {
121 if (qpid
== USB_TOKEN_IN
) {
122 actual_length
= c
->packet
.actual_length
;
124 xfersize
-= actual_length
;
125 c
->hctsiz
&= ~(hctsiz_xfersize_mask
<< hctsiz_xfersize_shift
);
126 c
->hctsiz
|= xfersize
<< hctsiz_xfersize_shift
;
128 dma_memory_write(&c
->parent
->dma_as
, dma_addr
, c
->buffer
,
132 c
->hcint
|= hcint_xfercomp
| hcint_chhltd
;
133 bcm2835_usb_update_irq(c
->parent
);
134 } else if (c
->packet
.status
== USB_RET_NAK
) {
135 c
->hcint
|= hcint_chhltd
| hcint_nak
;
136 bcm2835_usb_update_irq(c
->parent
);
139 c
->hcint
|= hcint_chhltd
| hcint_stall
;
140 bcm2835_usb_update_irq(c
->parent
);
145 static uint32_t bcm2835_usb_hchan_read(BCM2835UsbState
*s
, int ch
,
148 BCM2835UsbHcState
*c
= &s
->hchan
[ch
];
179 static void bcm2835_usb_hchan_write(BCM2835UsbState
*s
, int ch
,
180 int offset
, uint32_t value
, int *pset_irq
)
182 BCM2835UsbHcState
*c
= &s
->hchan
[ch
];
187 if (value
& hcchar_chdis
) {
188 c
->hcchar
&= ~(hcchar_chdis
| hcchar_chen
);
191 if (value
& hcchar_chen
) {
199 /* Looks like a standard interrupt register */
220 static uint64_t bcm2835_usb_read(void *opaque
, hwaddr offset
,
223 BCM2835UsbState
*s
= (BCM2835UsbState
*)opaque
;
247 /* Enforce Host mode */
248 res
|= gintsts_curmode
;
303 res
&= ~hprt0_prtconnsts
;
305 res
|= hprt0_prtconnsts
;
319 if ((offset
>= 0x104) && (offset
< 0x104 + (15 << 2))) {
320 res
= s
->dtxfsiz
[(offset
- 0x104) >> 2];
321 } else if ((offset
>= 0x500) && (offset
< 0x500 + 0x20*BCM2835_USB_HCHANS
)) {
322 i
= (offset
- 0x500) >> 5;
323 res
= bcm2835_usb_hchan_read(s
, i
, offset
& 0x1f);
325 qemu_log_mask(LOG_GUEST_ERROR
,
326 "bcm2835_usb_read: Bad offset %x\n", (int)offset
);
334 static void bcm2835_usb_write(void *opaque
, hwaddr offset
,
335 uint64_t value
, unsigned size
)
337 BCM2835UsbState
*s
= (BCM2835UsbState
*)opaque
;
349 /* Looks like a standard interrupt register */
350 s
->gotgint
&= ~value
;
360 s
->grstctl
&= ~0x7c0;
361 s
->grstctl
|= value
& 0x7c0;
364 s
->gintsts
&= ~value
;
365 /* Enforce Host mode */
366 s
->gintsts
|= gintsts_curmode
;
376 s
->gnptxfsiz
= value
;
382 s
->gdfifocfg
= value
;
400 s
->haintmsk
= value
& ((1 << BCM2835_USB_HCHANS
) - 1);
404 if (!(s
->hprt0
& hprt0_prtpwr
) && (value
& hprt0_prtpwr
)) {
405 /* Trigger the port status change interrupt on power on */
407 s
->hprt0
|= hprt0_prtconndet
;
409 /* Reset the device (that's probably not the right place) */
410 usb_device_reset(s
->port
.dev
);
412 timer_mod(s
->sof_timer
, 0);
415 s
->hprt0
&= ~hprt0_prtpwr
;
416 s
->hprt0
|= value
& hprt0_prtpwr
;
418 if ((s
->hprt0
& hprt0_prtres
) ^ (value
& hprt0_prtres
)) {
419 s
->hprt0
|= hprt0_prtenchng
;
422 s
->hprt0
&= ~(hprt0_prtena
| hprt0_prtres
);
423 if (value
& hprt0_prtres
) {
424 s
->hprt0
|= hprt0_prtres
;
426 s
->hprt0
|= hprt0_prtena
;
429 /* Interrupt clears */
430 if (value
& hprt0_prtconndet
) {
431 s
->hprt0
&= ~hprt0_prtconndet
;
434 if (value
& hprt0_prtenchng
) {
435 s
->hprt0
&= ~hprt0_prtenchng
;
447 if ((offset
>= 0x104) && (offset
< 0x104 + (15 << 2))) {
448 s
->dtxfsiz
[(offset
- 0x104) >> 2] = value
;
449 } else if ((offset
>= 0x500) && (offset
< 0x500 + 0x20*BCM2835_USB_HCHANS
)) {
450 i
= (offset
- 0x500) >> 5;
451 bcm2835_usb_hchan_write(s
, i
, offset
& 0x1f, value
, &set_irq
);
453 qemu_log_mask(LOG_GUEST_ERROR
,
454 "bcm2835_usb_write: Bad offset %x\n", (int)offset
);
460 bcm2835_usb_update_irq(s
);
464 static void bcm2835_usb_attach(USBPort
*port1
)
466 BCM2835UsbState
*s
= port1
->opaque
;
469 static void bcm2835_usb_detach(USBPort
*port1
)
472 static void bcm2835_usb_child_detach(USBPort
*port1
, USBDevice
*child
)
475 static void bcm2835_usb_wakeup(USBPort
*port1
)
478 static void bcm2835_usb_async_complete(USBPort
*port
, USBPacket
*packet
)
483 static const MemoryRegionOps bcm2835_usb_ops
= {
484 .read
= bcm2835_usb_read
,
485 .write
= bcm2835_usb_write
,
486 .endianness
= DEVICE_NATIVE_ENDIAN
,
489 static const VMStateDescription vmstate_bcm2835_usb
= {
490 .name
= TYPE_BCM2835_USB
,
492 .minimum_version_id
= 1,
493 .minimum_version_id_old
= 1,
494 .fields
= (VMStateField
[]) {
495 VMSTATE_END_OF_LIST()
499 static USBPortOps bcm2835_usb_port_ops
= {
500 .attach
= bcm2835_usb_attach
,
501 .detach
= bcm2835_usb_detach
,
502 .child_detach
= bcm2835_usb_child_detach
,
503 .wakeup
= bcm2835_usb_wakeup
,
504 .complete
= bcm2835_usb_async_complete
,
507 static USBBusOps bcm2835_usb_bus_ops
= {
510 static void bcm2835_usb_init(Object
*obj
)
512 BCM2835UsbState
*s
= BCM2835_USB(obj
);
514 memory_region_init_io(&s
->iomem
, obj
, &bcm2835_usb_ops
, s
,
515 TYPE_BCM2835_USB
, 0x20000);
516 sysbus_init_mmio(SYS_BUS_DEVICE(s
), &s
->iomem
);
517 sysbus_init_irq(SYS_BUS_DEVICE(s
), &s
->irq
);
520 static void bcm2835_usb_realize(DeviceState
*dev
, Error
**errp
)
523 BCM2835UsbState
*s
= BCM2835_USB(dev
);
527 obj
= object_property_get_link(OBJECT(dev
), "dma_mr", &err
);
528 if (err
|| obj
== NULL
) {
529 error_setg(errp
, "bcm2835_usb: required dma_mr property not found");
533 s
->dma_mr
= MEMORY_REGION(obj
);
534 address_space_init(&s
->dma_as
, s
->dma_mr
, NULL
);
536 s
->gusbcfg
= 0x20402700;
537 s
->hptxfsiz
= 0x02002000;
538 s
->hcfg
= 0x00000001;
539 s
->dcfg
= 0x00000000;
540 s
->grxfsiz
= 0x00001000;
541 s
->gnptxfsiz
= 0x01001000;
542 for (n
= 0; n
< 15; n
++) {
543 s
->dtxfsiz
[n
] = 0x02002000;
545 s
->gahbcfg
= 0x0000000e;
546 s
->grstctl
= 0x80000000;
547 s
->gotgctl
= 0x001c0000;
551 s
->gdfifocfg
= 0x00000000;
552 s
->hprt0
= DWC_HPRT0_PRTSPD_FULL_SPEED
<< hprt0_prtspd_shift
;
553 s
->gnptxsts
= 0x080100;
555 s
->hptxsts
= 0x080200;
556 s
->guid
= 0x2708A000;
558 for (n
= 0; n
< BCM2835_USB_HCHANS
; n
++) {
559 s
->hchan
[n
].parent
= s
;
560 s
->hchan
[n
].index
= n
;
562 s
->hchan
[n
].hcchar
= 0;
563 s
->hchan
[n
].hcsplt
= 0;
564 s
->hchan
[n
].hcint
= 0;
565 s
->hchan
[n
].hcintmsk
= 0;
566 s
->hchan
[n
].hctsiz
= 0;
567 s
->hchan
[n
].hcdma
= 0;
568 s
->hchan
[n
].hcdmab
= 0;
570 usb_packet_init(&s
->hchan
[n
].packet
);
576 s
->sof_timer
= timer_new_us(QEMU_CLOCK_VIRTUAL
, bcm2835_usb_sof_tick
, s
);
578 usb_bus_new(&s
->bus
, sizeof(s
->bus
), &bcm2835_usb_bus_ops
, DEVICE(s
));
579 usb_register_port(&s
->bus
, &s
->port
, s
, 0, &bcm2835_usb_port_ops
,
580 USB_SPEED_MASK_LOW
| USB_SPEED_MASK_FULL
);
583 static void bcm2835_usb_class_init(ObjectClass
*klass
, void *data
)
585 DeviceClass
*dc
= DEVICE_CLASS(klass
);
587 dc
->realize
= bcm2835_usb_realize
;
588 dc
->vmsd
= &vmstate_bcm2835_usb
;
591 static TypeInfo bcm2835_usb_info
= {
592 .name
= TYPE_BCM2835_USB
,
593 .parent
= TYPE_SYS_BUS_DEVICE
,
594 .instance_size
= sizeof(BCM2835UsbState
),
595 .class_init
= bcm2835_usb_class_init
,
596 .instance_init
= bcm2835_usb_init
,
599 static void bcm2835_usb_register_types(void)
601 type_register_static(&bcm2835_usb_info
);
604 type_init(bcm2835_usb_register_types
)