hw/arm: Restore local modifications
[qemu/ar7.git] / hw / usb / bcm2835_usb.c
blob596cd420c66626673e5cf405888972ad57b2401b
1 /*
2 * Raspberry Pi emulation (c) 2012-2013 Gregory Estrade
3 * This code is licensed under the GNU GPLv2 and later.
4 */
6 /* This is wrong at so many levels, but well, I'm releasing it anyway */
8 #include "qemu/osdep.h"
9 #include "qemu/log.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
17 * support.
18 * The problem is that frame scheduling is all done by software, so a LOT of
19 * interrupts are generated, which doesn't help... */
20 #define SOF_INCR 1
21 #define SOF_DELAY 5000
23 static void bcm2835_usb_update_irq(BCM2835UsbState *s)
25 int n;
27 s->haint = 0;
28 for (n = 0; n < BCM2835_USB_HCHANS; n++) {
29 if (s->hchan[n].hcint & s->hchan[n].hcintmsk) {
30 s->haint |= (1 << n);
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;
41 } else {
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);
49 } else {
50 if (s->gintsts & s->gintmsk) {
51 qemu_set_irq(s->irq, 1);
52 } else {
53 qemu_set_irq(s->irq, 0);
59 static void bcm2835_usb_sof_tick(void *opaque)
61 BCM2835UsbState *s = (BCM2835UsbState *)opaque;
62 int64_t now;
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)
76 USBEndpoint *ep;
77 USBDevice *dev;
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; /* ??? */
86 int actual_length;
87 int qpid;
89 if (!c->parent->reset_done) {
90 return;
93 if (c->hcchar & hcchar_epdir) {
94 /* IN */
95 qpid = USB_TOKEN_IN;
96 } else {
97 /* OUT/SETUP */
98 if (pid == DWC_HCTSIZ_SETUP) {
99 qpid = USB_TOKEN_SETUP;
100 } else {
101 qpid = USB_TOKEN_OUT;
105 dev = usb_find_device(&c->parent->port, devaddr);
106 assert(dev != NULL);
108 ep = usb_ep_get(dev, qpid, epnum);
109 usb_packet_setup(&c->packet, qpid, ep, 0, devaddr, 0, 0);
111 if (xfersize > 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,
127 actual_length);
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);
135 } else {
136 /* assert(0); */
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,
144 int offset)
146 BCM2835UsbHcState *c = &s->hchan[ch];
147 uint32_t res;
149 switch (offset) {
150 case 0x0:
151 res = c->hcchar;
152 break;
153 case 0x4:
154 res = c->hcsplt;
155 break;
156 case 0x8:
157 res = c->hcint;
158 break;
159 case 0xc:
160 res = c->hcintmsk;
161 break;
162 case 0x10:
163 res = c->hctsiz;
164 break;
165 case 0x14:
166 res = c->hcdma;
167 break;
168 case 0x1c:
169 res = c->hcdmab;
170 break;
171 default:
172 res = 0;
173 break;
175 return res;
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];
182 switch (offset) {
183 case 0x0:
184 c->hcchar = value;
185 if (value & hcchar_chdis) {
186 c->hcchar &= ~(hcchar_chdis | hcchar_chen);
187 /* TODO irq */
189 if (value & hcchar_chen) {
190 channel_enable(c);
192 break;
193 case 0x4:
194 c->hcsplt = value;
195 break;
196 case 0x8:
197 /* Looks like a standard interrupt register */
198 c->hcint &= ~value;
199 *pset_irq = 1;
200 break;
201 case 0xc:
202 c->hcintmsk = value;
203 break;
204 case 0x10:
205 c->hctsiz = value;
206 break;
207 case 0x14:
208 c->hcdma = value;
209 break;
210 case 0x1c:
211 c->hcdmab = value;
212 break;
213 default:
214 break;
218 static uint64_t bcm2835_usb_read(void *opaque, hwaddr offset,
219 unsigned size)
221 BCM2835UsbState *s = (BCM2835UsbState *)opaque;
222 uint32_t res = 0;
223 int i;
225 assert(size == 4);
227 switch (offset) {
228 case 0x0:
229 res = s->gotgctl;
230 break;
231 case 0x4:
232 res = s->gotgint;
233 break;
234 case 0x8:
235 res = s->gahbcfg;
236 break;
237 case 0xc:
238 res = s->gusbcfg;
239 break;
240 case 0x10:
241 res = s->grstctl;
242 break;
243 case 0x14:
244 res = s->gintsts;
245 /* Enforce Host mode */
246 res |= gintsts_curmode;
247 break;
248 case 0x18:
249 res = s->gintmsk;
250 break;
251 case 0x24:
252 res = s->grxfsiz;
253 break;
254 case 0x28:
255 res = s->gnptxfsiz;
256 break;
257 case 0x2c:
258 res = s->gnptxsts;
259 break;
260 case 0x3c:
261 res = s->guid;
262 break;
263 case 0x40:
264 res = 0x4f54280a;
265 break;
266 case 0x44:
267 res = 0;
268 break;
269 case 0x48:
270 res = 0x228ddd50;
271 break;
272 case 0x4c:
273 res = 0x0ff000e8;
274 break;
275 case 0x50:
276 res = 0x1ff00020;
277 break;
278 case 0x5c:
279 res = s->gdfifocfg;
280 break;
281 case 0x100:
282 res = s->hptxfsiz;
283 break;
284 case 0x400:
285 res = s->hcfg;
286 break;
287 case 0x408:
288 res = s->hfnum;
289 break;
290 case 0x410:
291 res = s->hptxsts;
292 break;
293 case 0x414:
294 res = s->haint;
295 break;
296 case 0x418:
297 res = s->haintmsk;
298 break;
299 case 0x440:
300 res = s->hprt0;
301 res &= ~hprt0_prtconnsts;
302 if (s->attached) {
303 res |= hprt0_prtconnsts;
305 break;
306 case 0x800:
307 res = s->dcfg;
308 break;
310 case 0xe00:
311 case 0x54:
312 case 0x58:
313 res = 0;
314 break;
316 default:
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);
322 } else {
323 qemu_log_mask(LOG_GUEST_ERROR,
324 "bcm2835_usb_read: Bad offset %x\n", (int)offset);
325 res = 0;
327 break;
329 return res;
332 static void bcm2835_usb_write(void *opaque, hwaddr offset,
333 uint64_t value, unsigned size)
335 BCM2835UsbState *s = (BCM2835UsbState *)opaque;
337 int i;
338 int set_irq = 0;
340 assert(size == 4);
342 switch (offset) {
343 case 0x0:
344 s->gotgctl = value;
345 break;
346 case 0x4:
347 /* Looks like a standard interrupt register */
348 s->gotgint &= ~value;
349 break;
350 case 0x8:
351 s->gahbcfg = value;
352 set_irq = 1;
353 break;
354 case 0xc:
355 s->gusbcfg = value;
356 break;
357 case 0x10:
358 s->grstctl &= ~0x7c0;
359 s->grstctl |= value & 0x7c0;
360 break;
361 case 0x14:
362 s->gintsts &= ~value;
363 /* Enforce Host mode */
364 s->gintsts |= gintsts_curmode;
365 set_irq = 1;
366 break;
367 case 0x18:
368 s->gintmsk = value;
369 break;
370 case 0x24:
371 s->grxfsiz = value;
372 break;
373 case 0x28:
374 s->gnptxfsiz = value;
375 break;
376 case 0x3c:
377 s->guid = value;
378 break;
379 case 0x5c:
380 s->gdfifocfg = value;
381 break;
382 case 0x100:
383 s->hptxfsiz = value;
384 break;
385 case 0x400:
386 s->hcfg = value;
387 break;
388 case 0x408:
389 /* Probably RO */
390 break;
391 case 0x410:
392 /* Probably RO */
393 break;
394 case 0x414:
395 /* Probably RO */
396 break;
397 case 0x418:
398 s->haintmsk = value & ((1 << BCM2835_USB_HCHANS) - 1);
399 set_irq = 1;
400 break;
401 case 0x440:
402 if (!(s->hprt0 & hprt0_prtpwr) && (value & hprt0_prtpwr)) {
403 /* Trigger the port status change interrupt on power on */
404 if (s->attached) {
405 s->hprt0 |= hprt0_prtconndet;
406 set_irq = 1;
407 /* Reset the device (that's probably not the right place) */
408 usb_device_reset(s->port.dev);
409 s->reset_done = 1;
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;
418 set_irq = 1;
420 s->hprt0 &= ~(hprt0_prtena | hprt0_prtres);
421 if (value & hprt0_prtres) {
422 s->hprt0 |= hprt0_prtres;
423 } else {
424 s->hprt0 |= hprt0_prtena;
427 /* Interrupt clears */
428 if (value & hprt0_prtconndet) {
429 s->hprt0 &= ~hprt0_prtconndet;
430 set_irq = 1;
432 if (value & hprt0_prtenchng) {
433 s->hprt0 &= ~hprt0_prtenchng;
434 set_irq = 1;
437 break;
439 case 0xe00:
440 case 0x54:
441 case 0x58:
442 break;
444 default:
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);
450 } else {
451 qemu_log_mask(LOG_GUEST_ERROR,
452 "bcm2835_usb_write: Bad offset %x\n", (int)offset);
454 break;
457 if (set_irq) {
458 bcm2835_usb_update_irq(s);
462 static void bcm2835_usb_attach(USBPort *port1)
464 BCM2835UsbState *s = port1->opaque;
465 s->attached = 1;
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,
489 .version_id = 1,
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)
520 int n;
521 BCM2835UsbState *s = BCM2835_USB(dev);
522 Error *err = NULL;
523 Object *obj;
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");
528 return;
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;
546 s->gotgint = 0;
547 s->gintsts = 0;
548 s->gintmsk = 0;
549 s->gdfifocfg = 0x00000000;
550 s->hprt0 = DWC_HPRT0_PRTSPD_FULL_SPEED << hprt0_prtspd_shift;
551 s->gnptxsts = 0x080100;
552 s->hfnum = 0;
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);
571 s->attached = 0;
572 s->reset_done = 0;
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)