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/usb/bcm2835_usb.h"
11 #include "qapi/error.h"
12 #include "sysemu/dma.h"
14 #include "bcm2835_usb_regs.h"
16 /* You may have to change these parameters to get an almost-usable mouse
18 * The problem is that frame scheduling is all done by software, so a LOT of
19 * interrupts are generated, which doesn't help... */
21 #define SOF_DELAY 5000
23 static void bcm2835_usb_update_irq(BCM2835UsbState
*s
)
28 for (n
= 0; n
< BCM2835_USB_HCHANS
; n
++) {
29 if (s
->hchan
[n
].hcint
& s
->hchan
[n
].hcintmsk
) {
33 s
->gintsts
&= ~gintsts_hcintr
;
34 if (s
->haint
& s
->haintmsk
) {
35 s
->gintsts
|= gintsts_hcintr
;
38 if ((s
->hprt0
& hprt0_prtconndet
)
39 || (s
->hprt0
& hprt0_prtenchng
)) {
40 s
->gintsts
|= gintsts_portintr
;
42 s
->gintsts
&= ~gintsts_portintr
;
45 s
->gintsts
|= gintsts_nptxfempty
| gintsts_ptxfempty
;
47 if (!(s
->gahbcfg
& gahbcfg_glblintrmsk
)) {
48 qemu_set_irq(s
->irq
, 0);
50 if (s
->gintsts
& s
->gintmsk
) {
51 qemu_set_irq(s
->irq
, 1);
53 qemu_set_irq(s
->irq
, 0);
59 static void bcm2835_usb_sof_tick(void *opaque
)
61 BCM2835UsbState
*s
= (BCM2835UsbState
*)opaque
;
64 uint32_t num
= (s
->hfnum
& 0x3fff) + SOF_INCR
;
65 s
->hfnum
= (num
& 0x3fff) | (0x3210 << 16);
66 s
->gintsts
|= gintsts_sofintr
;
68 bcm2835_usb_update_irq(s
);
70 now
= qemu_clock_get_us(QEMU_CLOCK_VIRTUAL
);
71 timer_mod(s
->sof_timer
, now
+ SOF_DELAY
);
74 static void channel_enable(BCM2835UsbHcState
*c
)
79 uint32_t epnum
= (c
->hcchar
>> hcchar_epnum_shift
) & hcchar_epnum_mask
;
80 uint32_t devaddr
= (c
->hcchar
>> hcchar_devaddr_shift
)
81 & hcchar_devaddr_mask
;
82 uint32_t xfersize
= (c
->hctsiz
>> hctsiz_xfersize_shift
)
83 & hctsiz_xfersize_mask
;
84 uint32_t pid
= (c
->hctsiz
>> hctsiz_pid_shift
) & hctsiz_pid_mask
;
85 uint32_t dma_addr
= c
->hcdma
; /* ??? */
89 if (!c
->parent
->reset_done
) {
93 if (c
->hcchar
& hcchar_epdir
) {
98 if (pid
== DWC_HCTSIZ_SETUP
) {
99 qpid
= USB_TOKEN_SETUP
;
101 qpid
= USB_TOKEN_OUT
;
105 dev
= usb_find_device(&c
->parent
->port
, devaddr
);
108 ep
= usb_ep_get(dev
, qpid
, epnum
);
109 usb_packet_setup(&c
->packet
, qpid
, ep
, 0, devaddr
, 0, 0);
112 dma_memory_read(&c
->parent
->dma_as
, dma_addr
, c
->buffer
, xfersize
);
114 usb_packet_addbuf(&c
->packet
, c
->buffer
, xfersize
);
116 usb_handle_packet(dev
, &c
->packet
);
118 if (c
->packet
.status
== USB_RET_SUCCESS
) {
119 if (qpid
== USB_TOKEN_IN
) {
120 actual_length
= c
->packet
.actual_length
;
122 xfersize
-= actual_length
;
123 c
->hctsiz
&= ~(hctsiz_xfersize_mask
<< hctsiz_xfersize_shift
);
124 c
->hctsiz
|= xfersize
<< hctsiz_xfersize_shift
;
126 dma_memory_write(&c
->parent
->dma_as
, dma_addr
, c
->buffer
,
130 c
->hcint
|= hcint_xfercomp
| hcint_chhltd
;
131 bcm2835_usb_update_irq(c
->parent
);
132 } else if (c
->packet
.status
== USB_RET_NAK
) {
133 c
->hcint
|= hcint_chhltd
| hcint_nak
;
134 bcm2835_usb_update_irq(c
->parent
);
137 c
->hcint
|= hcint_chhltd
| hcint_stall
;
138 bcm2835_usb_update_irq(c
->parent
);
143 static uint32_t bcm2835_usb_hchan_read(BCM2835UsbState
*s
, int ch
,
146 BCM2835UsbHcState
*c
= &s
->hchan
[ch
];
177 static void bcm2835_usb_hchan_write(BCM2835UsbState
*s
, int ch
,
178 int offset
, uint32_t value
, int *pset_irq
)
180 BCM2835UsbHcState
*c
= &s
->hchan
[ch
];
185 if (value
& hcchar_chdis
) {
186 c
->hcchar
&= ~(hcchar_chdis
| hcchar_chen
);
189 if (value
& hcchar_chen
) {
197 /* Looks like a standard interrupt register */
218 static uint64_t bcm2835_usb_read(void *opaque
, hwaddr offset
,
221 BCM2835UsbState
*s
= (BCM2835UsbState
*)opaque
;
245 /* Enforce Host mode */
246 res
|= gintsts_curmode
;
301 res
&= ~hprt0_prtconnsts
;
303 res
|= hprt0_prtconnsts
;
317 if ((offset
>= 0x104) && (offset
< 0x104 + (15 << 2))) {
318 res
= s
->dtxfsiz
[(offset
- 0x104) >> 2];
319 } else if ((offset
>= 0x500) && (offset
< 0x500 + 0x20*BCM2835_USB_HCHANS
)) {
320 i
= (offset
- 0x500) >> 5;
321 res
= bcm2835_usb_hchan_read(s
, i
, offset
& 0x1f);
323 qemu_log_mask(LOG_GUEST_ERROR
,
324 "bcm2835_usb_read: Bad offset %x\n", (int)offset
);
332 static void bcm2835_usb_write(void *opaque
, hwaddr offset
,
333 uint64_t value
, unsigned size
)
335 BCM2835UsbState
*s
= (BCM2835UsbState
*)opaque
;
347 /* Looks like a standard interrupt register */
348 s
->gotgint
&= ~value
;
358 s
->grstctl
&= ~0x7c0;
359 s
->grstctl
|= value
& 0x7c0;
362 s
->gintsts
&= ~value
;
363 /* Enforce Host mode */
364 s
->gintsts
|= gintsts_curmode
;
374 s
->gnptxfsiz
= value
;
380 s
->gdfifocfg
= value
;
398 s
->haintmsk
= value
& ((1 << BCM2835_USB_HCHANS
) - 1);
402 if (!(s
->hprt0
& hprt0_prtpwr
) && (value
& hprt0_prtpwr
)) {
403 /* Trigger the port status change interrupt on power on */
405 s
->hprt0
|= hprt0_prtconndet
;
407 /* Reset the device (that's probably not the right place) */
408 usb_device_reset(s
->port
.dev
);
410 timer_mod(s
->sof_timer
, 0);
413 s
->hprt0
&= ~hprt0_prtpwr
;
414 s
->hprt0
|= value
& hprt0_prtpwr
;
416 if ((s
->hprt0
& hprt0_prtres
) ^ (value
& hprt0_prtres
)) {
417 s
->hprt0
|= hprt0_prtenchng
;
420 s
->hprt0
&= ~(hprt0_prtena
| hprt0_prtres
);
421 if (value
& hprt0_prtres
) {
422 s
->hprt0
|= hprt0_prtres
;
424 s
->hprt0
|= hprt0_prtena
;
427 /* Interrupt clears */
428 if (value
& hprt0_prtconndet
) {
429 s
->hprt0
&= ~hprt0_prtconndet
;
432 if (value
& hprt0_prtenchng
) {
433 s
->hprt0
&= ~hprt0_prtenchng
;
445 if ((offset
>= 0x104) && (offset
< 0x104 + (15 << 2))) {
446 s
->dtxfsiz
[(offset
- 0x104) >> 2] = value
;
447 } else if ((offset
>= 0x500) && (offset
< 0x500 + 0x20*BCM2835_USB_HCHANS
)) {
448 i
= (offset
- 0x500) >> 5;
449 bcm2835_usb_hchan_write(s
, i
, offset
& 0x1f, value
, &set_irq
);
451 qemu_log_mask(LOG_GUEST_ERROR
,
452 "bcm2835_usb_write: Bad offset %x\n", (int)offset
);
458 bcm2835_usb_update_irq(s
);
462 static void bcm2835_usb_attach(USBPort
*port1
)
464 BCM2835UsbState
*s
= port1
->opaque
;
467 static void bcm2835_usb_detach(USBPort
*port1
)
470 static void bcm2835_usb_child_detach(USBPort
*port1
, USBDevice
*child
)
473 static void bcm2835_usb_wakeup(USBPort
*port1
)
476 static void bcm2835_usb_async_complete(USBPort
*port
, USBPacket
*packet
)
481 static const MemoryRegionOps bcm2835_usb_ops
= {
482 .read
= bcm2835_usb_read
,
483 .write
= bcm2835_usb_write
,
484 .endianness
= DEVICE_NATIVE_ENDIAN
,
487 static const VMStateDescription vmstate_bcm2835_usb
= {
488 .name
= TYPE_BCM2835_USB
,
490 .minimum_version_id
= 1,
491 .minimum_version_id_old
= 1,
492 .fields
= (VMStateField
[]) {
493 VMSTATE_END_OF_LIST()
497 static USBPortOps bcm2835_usb_port_ops
= {
498 .attach
= bcm2835_usb_attach
,
499 .detach
= bcm2835_usb_detach
,
500 .child_detach
= bcm2835_usb_child_detach
,
501 .wakeup
= bcm2835_usb_wakeup
,
502 .complete
= bcm2835_usb_async_complete
,
505 static USBBusOps bcm2835_usb_bus_ops
= {
508 static void bcm2835_usb_init(Object
*obj
)
510 BCM2835UsbState
*s
= BCM2835_USB(obj
);
512 memory_region_init_io(&s
->iomem
, obj
, &bcm2835_usb_ops
, s
,
513 TYPE_BCM2835_USB
, 0x20000);
514 sysbus_init_mmio(SYS_BUS_DEVICE(s
), &s
->iomem
);
515 sysbus_init_irq(SYS_BUS_DEVICE(s
), &s
->irq
);
518 static void bcm2835_usb_realize(DeviceState
*dev
, Error
**errp
)
521 BCM2835UsbState
*s
= BCM2835_USB(dev
);
525 obj
= object_property_get_link(OBJECT(dev
), "dma_mr", &err
);
526 if (err
|| obj
== NULL
) {
527 error_setg(errp
, "bcm2835_usb: required dma_mr property not found");
531 s
->dma_mr
= MEMORY_REGION(obj
);
532 address_space_init(&s
->dma_as
, s
->dma_mr
, NULL
);
534 s
->gusbcfg
= 0x20402700;
535 s
->hptxfsiz
= 0x02002000;
536 s
->hcfg
= 0x00000001;
537 s
->dcfg
= 0x00000000;
538 s
->grxfsiz
= 0x00001000;
539 s
->gnptxfsiz
= 0x01001000;
540 for (n
= 0; n
< 15; n
++) {
541 s
->dtxfsiz
[n
] = 0x02002000;
543 s
->gahbcfg
= 0x0000000e;
544 s
->grstctl
= 0x80000000;
545 s
->gotgctl
= 0x001c0000;
549 s
->gdfifocfg
= 0x00000000;
550 s
->hprt0
= DWC_HPRT0_PRTSPD_FULL_SPEED
<< hprt0_prtspd_shift
;
551 s
->gnptxsts
= 0x080100;
553 s
->hptxsts
= 0x080200;
554 s
->guid
= 0x2708A000;
556 for (n
= 0; n
< BCM2835_USB_HCHANS
; n
++) {
557 s
->hchan
[n
].parent
= s
;
558 s
->hchan
[n
].index
= n
;
560 s
->hchan
[n
].hcchar
= 0;
561 s
->hchan
[n
].hcsplt
= 0;
562 s
->hchan
[n
].hcint
= 0;
563 s
->hchan
[n
].hcintmsk
= 0;
564 s
->hchan
[n
].hctsiz
= 0;
565 s
->hchan
[n
].hcdma
= 0;
566 s
->hchan
[n
].hcdmab
= 0;
568 usb_packet_init(&s
->hchan
[n
].packet
);
574 s
->sof_timer
= timer_new_us(QEMU_CLOCK_VIRTUAL
, bcm2835_usb_sof_tick
, s
);
576 usb_bus_new(&s
->bus
, sizeof(s
->bus
), &bcm2835_usb_bus_ops
, DEVICE(s
));
577 usb_register_port(&s
->bus
, &s
->port
, s
, 0, &bcm2835_usb_port_ops
,
578 USB_SPEED_MASK_LOW
| USB_SPEED_MASK_FULL
);
581 static void bcm2835_usb_class_init(ObjectClass
*klass
, void *data
)
583 DeviceClass
*dc
= DEVICE_CLASS(klass
);
585 dc
->realize
= bcm2835_usb_realize
;
586 dc
->vmsd
= &vmstate_bcm2835_usb
;
589 static TypeInfo bcm2835_usb_info
= {
590 .name
= TYPE_BCM2835_USB
,
591 .parent
= TYPE_SYS_BUS_DEVICE
,
592 .instance_size
= sizeof(BCM2835UsbState
),
593 .class_init
= bcm2835_usb_class_init
,
594 .instance_init
= bcm2835_usb_init
,
597 static void bcm2835_usb_register_types(void)
599 type_register_static(&bcm2835_usb_info
);
602 type_init(bcm2835_usb_register_types
)