2 * S5PC1XX UART Emulation
4 * Copyright (c) 2009 Samsung Electronics.
5 * Contributed by Kirill Batuzov <batuzovk@ispras.ru>
9 #include "qemu-common.h"
10 #include "qemu-timer.h"
19 #define USB_INT_MODEMIS (1 << 1) /* Mode Mismatch Interrupt */
20 #define USB_INT_OTGINT (1 << 2) /* OTG Interrupt */
21 #define USB_INT_SOF (1 << 3) /* Start of (micro) Frame */
22 #define USB_INT_RXFLVL (1 << 4) /* RxFIFO Non-Empty */
23 #define USB_INT_NPTXFEMP (1 << 5) /* Non-periodic TxFIFO Empty */
24 #define USB_INT_GINNAKEFF (1 << 6) /* Global IN Non-periodic NAK Effective */
25 #define USB_INT_GOUTNAKEFF (1 << 7) /* Global OUT NAK Effective */
26 #define USB_INT_ERLYSUSP (1 << 10) /* Early Suspend */
27 #define USB_INT_USBSUSP (1 << 11) /* USB Suspend */
28 #define USB_INT_USBRST (1 << 12) /* USB Reset */
29 #define USB_INT_ENUMDONE (1 << 13) /* Enumeration Done */
30 #define USB_INT_ISOUTDROP (1 << 14) /* Isochronous OUT Packet Dropped */
31 #define USB_INT_EOPF (1 << 15) /* End of Periodic Frame */
32 #define USB_INT_IEPINT (1 << 18) /* IN Endpoints Interrupt */
33 #define USB_INT_OEPINT (1 << 19) /* OUT Endpoints Interrupt */
34 #define USB_INT_INCOMPLISOIN \
35 (1 << 20) /* Incomplete Isochronous IN Transfer */
36 #define USB_INT_INCOMPLISOOUT \
37 (1 << 21) /* Incomplete Isochronous OUT Transfer */
38 #define USB_INT_FETSUSP (1 << 22) /* Data Fetch Suspended */
39 //#define USB_INT_PRTINT (1 << 24) /* Host Port Interrupt */
40 //#define USB_INT_HCHINT (1 << 25) /* Host Channels Interrupt */
41 #define USB_INT_PTXFEMP (1 << 26) /* Periodic TxFIFO Empty */
42 #define USB_INT_CONIDSTSCHNG \
43 (1 << 28) /* Connector ID Status Change */
44 #define USB_INT_DISCONINT (1 << 29) /* Disconnect Detected Interrupt */
45 #define USB_INT_SESSREQINT (1 << 30) /* New Session Detected Interrupt */
46 #define USB_INT_WKUPINT (1 << 31) /* Resume Interrupt */
48 #define EP_INT_XFERCOMPL (1 << 0) /* Transfer complete */
49 #define EP_INT_EPDISABLED (1 << 1) /* Endpoint disabled */
50 #define EP_INT_AHBERR (1 << 2) /* AHB error */
51 #define EP_INT_SETUP (1 << 3) /* [OUT] Setup phase done */
52 #define EP_INT_TIMEOUT (1 << 3) /* [IN] Timeout */
53 #define EP_INT_OUTTKNEPDIS (1 << 4) /* [OUT] Token Received When EP Disabled */
54 #define EP_INT_INTKNFIFOEMP (1 << 4) /* [IN] Token Received When FIFO is Empty */
55 #define EP_INT_STSPHSERCVD (1 << 5) /* [OUT] Status Phase Received For Control Write */
56 #define EP_INT_INTTKNEPMIS (1 << 5) /* [IN] Token Received With EP Missmatch */
57 #define EP_INT_BACK2BACK (1 << 6) /* [OUT] Back-to-Back SETUP Packets Receive */
58 #define EP_INT_INEPNAKEFF (1 << 6) /* [IN] Endpoint NAK Effective */
59 #define EP_INT_TXFEMP (1 << 7) /* Transmit FIFO Empty */
60 #define EP_INT_OUTPKTERR (1 << 8) /* [OUT] Packet Error */
61 #define EP_INT_TXFIFOUNDRN (1 << 8) /* [IN] FIFO Underrun */
62 #define EP_INT_BNAINTR (1 << 9) /* Buffer not Available */
65 #define OTG_EP_DIR_IN 0x80
66 #define OTG_EP_DIR_OUT 0
68 #define OTG_EP_ENABLE (1U << 31)
69 #define OTG_EP_DISABLE (1 << 30)
71 #define OTG_EP_COUNT 16
77 OTG_STATE_SPEEDDETECT,
78 OTG_STATE_SETCONFIG_S,
79 OTG_STATE_SETCONFIG_W,
80 OTG_STATE_SETCONFIG_D,
87 typedef struct S5pc1xxUsbOtgEndPoint {
91 uint32_t transfer_size;
94 uint32_t in_fifo_size;
98 struct S5pc1xxUsbOtgState *parent;
99 } S5pc1xxUsbOtgEndPoint;
101 typedef struct S5pc1xxUsbOtgState {
104 struct S5pc1xxPhyState {
130 S5pc1xxUsbOtgEndPoint ep_in[OTG_EP_COUNT];
131 S5pc1xxUsbOtgEndPoint ep_out[OTG_EP_COUNT];
133 OtgLogicalState state;
141 } S5pc1xxUsbOtgState;
144 static const uint8_t otg_setup_packet[] = {
145 0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00
147 static const uint8_t otg_setup_iface[] = {
148 0x01, 0x0B, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00
150 static const uint8_t otg_setup_config[] = {
151 0x00, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
154 static void s5pc1xx_usb_otg_update_irq(S5pc1xxUsbOtgState *s)
156 if (s->gint_sts & s->gint_msk) {
157 qemu_irq_raise(s->irq);
159 qemu_irq_lower(s->irq);
163 static void s5pc1xx_usb_otg_initial_reset(DeviceState *d)
165 S5pc1xxUsbOtgState *s =
166 FROM_SYSBUS(S5pc1xxUsbOtgState, sysbus_from_qdev(d));
169 s->phy.power = 0x000001F9;
170 s->phy.clock = 0x00000000;
171 s->phy.reset = 0x00000009; /* TODO: I believe it should be 0 */
172 s->phy.tune0 = 0x000919B3;
173 s->phy.tune1 = 0x000919B3;
175 s->gotg_ctl = 0x00010000;
176 s->gotg_int = 0x00000000;
177 s->gahb_cfg = 0x00000000;
178 s->gusb_cfg = 0x00001408;
179 s->grst_ctl = 0x80000000;
180 s->gint_sts = 0x04000020;
181 s->gint_msk = 0x00000000;
183 for (i = 0; i < OTG_EP_COUNT; i++) {
184 s->ep_in[i].parent = s;
185 s->ep_in[i].dir = OTG_EP_DIR_IN;
187 s->ep_out[i].parent = s;
188 s->ep_out[i].dir = OTG_EP_DIR_OUT;
192 s->state = OTG_STATE_START;
196 static void s5pc1xx_usb_otg_reset(S5pc1xxUsbOtgState *s)
198 s5pc1xx_usb_otg_initial_reset(&s->busdev.qdev);
199 s->state = OTG_STATE_RESET;
200 s->gotg_ctl += 0x000C0000;
201 s->gint_sts |= USB_INT_USBRST;
204 static uint32_t s5pc1xx_usb_otg_phy_mm_read(void *opaque,
205 target_phys_addr_t offset)
207 S5pc1xxUsbOtgState *s = (S5pc1xxUsbOtgState *)opaque;
221 hw_error("s5pc1xx.usb_otg: bad read offset 0x" TARGET_FMT_plx "\n",
226 static void s5pc1xx_usb_otg_phy_mm_write(void *opaque, target_phys_addr_t offset,
229 S5pc1xxUsbOtgState *s = (S5pc1xxUsbOtgState *)opaque;
239 /* TODO: actually reset USB OTG */
241 s5pc1xx_usb_otg_reset(s);
242 s->gint_sts |= USB_INT_USBRST;
243 s5pc1xx_usb_otg_update_irq(s);
253 hw_error("s5pc1xx.usb_otg: bad write offset 0x" TARGET_FMT_plx "\n",
258 static void s5pc1xx_usb_otg_ep_update_irq(S5pc1xxUsbOtgEndPoint *s)
261 if (s->dir == OTG_EP_DIR_IN) {
262 s->parent->daint_sts |= (1 << s->n);
263 if (s->parent->daint_sts & s->parent->daint_msk & 0xffff) {
264 s->parent->gint_sts |= USB_INT_IEPINT;
266 s->parent->gint_sts &= ~USB_INT_IEPINT;
269 s->parent->daint_sts |= (1 << (s->n + 16));
270 if (s->parent->daint_sts & s->parent->daint_msk & 0xffff0000) {
271 s->parent->gint_sts |= USB_INT_OEPINT;
273 s->parent->gint_sts &= ~USB_INT_OEPINT;
277 if (s->dir == OTG_EP_DIR_IN) {
278 s->parent->daint_sts &= ~(1 << s->n);
279 if (s->parent->daint_sts & s->parent->daint_msk & 0xffff) {
280 s->parent->gint_sts |= USB_INT_IEPINT;
282 s->parent->gint_sts &= ~USB_INT_IEPINT;
285 s->parent->daint_sts &= ~(1 << (s->n + 16));
286 if (s->parent->daint_sts & s->parent->daint_msk & 0xffff0000) {
287 s->parent->gint_sts |= USB_INT_OEPINT;
289 s->parent->gint_sts &= ~USB_INT_OEPINT;
293 s5pc1xx_usb_otg_update_irq(s->parent);
296 static void s5pc1xx_usb_otg_act(S5pc1xxUsbOtgState *s)
299 case OTG_STATE_START:
300 case OTG_STATE_RESET:
301 case OTG_STATE_SPEEDDETECT:
303 case OTG_STATE_SETCONFIG_S:
304 if (s->ep_out[0].ctrl & OTG_EP_ENABLE) {
305 s->state = OTG_STATE_SETCONFIG_W;
306 cpu_physical_memory_write(s->ep_out[0].dma_addr,
307 otg_setup_config, 8);
308 s->ep_out[0].ctrl &= ~OTG_EP_ENABLE;
309 s->ep_out[0].interrupt |= EP_INT_SETUP|EP_INT_XFERCOMPL;
310 s5pc1xx_usb_otg_ep_update_irq(&s->ep_out[0]);
313 case OTG_STATE_SETIFACE_S:
314 if (s->ep_out[0].ctrl & OTG_EP_ENABLE) {
315 s->state = OTG_STATE_SETIFACE_W;
316 cpu_physical_memory_write(s->ep_out[0].dma_addr,
318 s->ep_out[0].ctrl &= ~OTG_EP_ENABLE;
319 s->ep_out[0].interrupt |= EP_INT_SETUP|EP_INT_XFERCOMPL;
320 s5pc1xx_usb_otg_ep_update_irq(&s->ep_out[0]);
328 static void s5pc1xx_usb_otg_data_tx(S5pc1xxUsbOtgEndPoint *s)
331 uint32_t size = s->transfer_size & 0x7ffff;
333 cpu_physical_memory_read(s->dma_addr, buf, size);
334 qemu_send_packet(&s->parent->nic->nc, buf, size);
335 s->interrupt |= EP_INT_XFERCOMPL|EP_INT_TXFEMP;
336 s5pc1xx_usb_otg_ep_update_irq(s);
339 static void s5pc1xx_usb_otg_data_rx(S5pc1xxUsbOtgEndPoint *s)
341 uint32_t size = s->parent->buf_size;
343 if (s->parent->buf_size > (s->transfer_size & 0x7ffff)) {
344 s->parent->buf_full = 0;
348 cpu_physical_memory_write(s->dma_addr, s->parent->buf, size);
349 s->dma_buf = s->dma_addr + size;
350 s->transfer_size -= size;
351 s->ctrl &= ~OTG_EP_ENABLE;
352 s->interrupt |= EP_INT_XFERCOMPL;
353 s->parent->buf_full = 0;
354 s5pc1xx_usb_otg_ep_update_irq(s);
357 static uint32_t s5pc1xx_usb_otg_ep_read(S5pc1xxUsbOtgEndPoint *s,
358 target_phys_addr_t addr)
366 return s->transfer_size;
372 hw_error("s5pc1xx.usb_otg: bad write offset 0x" TARGET_FMT_plx "\n",
377 static uint32_t s5pc1xx_usb_otg_ep_write(S5pc1xxUsbOtgEndPoint *s,
378 target_phys_addr_t addr, uint32_t val)
382 if ((val & OTG_EP_DISABLE) && (s->ctrl & OTG_EP_ENABLE)) {
383 s->ctrl &= ~OTG_EP_ENABLE;
384 val &= ~OTG_EP_DISABLE;
385 s->interrupt |= EP_INT_EPDISABLED;
386 s5pc1xx_usb_otg_ep_update_irq(s);
388 val &= ~OTG_EP_DISABLE;
389 if (val & OTG_EP_ENABLE) {
390 s5pc1xx_usb_otg_act(s->parent);
391 if (s->n == 0 && s->dir == OTG_EP_DIR_IN) {
392 s->interrupt |= EP_INT_XFERCOMPL|EP_INT_TXFEMP;
393 if (s->parent->state == OTG_STATE_SETCONFIG_W) {
394 s->parent->state = OTG_STATE_SETIFACE_S;
395 } else if (s->parent->state == OTG_STATE_SETIFACE_W) {
396 s->parent->state = OTG_STATE_OPERATIONAL;
398 s5pc1xx_usb_otg_ep_update_irq(s);
400 if (s->n != 0 && s->dir == OTG_EP_DIR_IN) {
401 s5pc1xx_usb_otg_data_tx(s);
402 val &= ~OTG_EP_ENABLE;
404 if (s->n != 0 && s->dir == OTG_EP_DIR_OUT &&
405 s->parent->buf_full == 1) {
406 s5pc1xx_usb_otg_data_rx(s);
407 val &= ~OTG_EP_ENABLE;
410 val &= ~(0xC << 24); /* TODO: handle NAK? */
412 /* TODO: handle control */
415 s->interrupt &= ~val;
416 s5pc1xx_usb_otg_ep_update_irq(s);
419 s->transfer_size = val;
425 hw_error("s5pc1xx.usb_otg: bad write offset 0x" TARGET_FMT_plx "\n",
431 static uint32_t s5pc1xx_usb_otg_read(void *opaque, target_phys_addr_t addr)
433 S5pc1xxUsbOtgState *s = (S5pc1xxUsbOtgState *)opaque;
435 if (addr >= 0x100000 && addr < 0x100028) {
436 return s5pc1xx_usb_otg_phy_mm_read(opaque, addr - 0x100000);
461 return s->gnptx_fsiz;
465 return s->hnptx_fsiz;
466 case 0x100 ... 0x13C:
467 return s->ep_in[(addr - 0x100) >> 2].in_fifo_size;
476 case 0x900 ... 0xAFC:
478 return s5pc1xx_usb_otg_ep_read(&s->ep_in[addr >> 5], addr & 0x1f);
479 case 0xB00 ... 0xCFC:
481 return s5pc1xx_usb_otg_ep_read(&s->ep_out[addr >> 5], addr & 0x1f);
486 static void s5pc1xx_usb_otg_write(void *opaque, target_phys_addr_t addr,
490 S5pc1xxUsbOtgState *s = (S5pc1xxUsbOtgState *)opaque;
492 if (addr >= 0x100000 && addr < 0x100028) {
493 s5pc1xx_usb_otg_phy_mm_write(opaque, addr - 0x100000, val);
503 s5pc1xx_usb_otg_update_irq(s);
513 s5pc1xx_usb_otg_reset(s);
514 s->gint_sts |= USB_INT_USBRST;
515 s->state = OTG_STATE_RESET;
516 s5pc1xx_usb_otg_update_irq(s);
517 } else if (val & 0x0f) {
518 s->gint_sts |= USB_INT_USBRST;
519 s->state = OTG_STATE_RESET;
520 s5pc1xx_usb_otg_update_irq(s);
522 s->grst_ctl = val & (~0x3f);
523 s5pc1xx_usb_otg_update_irq(s);
532 s->gint_sts |= USB_INT_ENUMDONE;
533 s->state = OTG_STATE_SPEEDDETECT;
534 s5pc1xx_usb_otg_act(s);
536 if (val == USB_INT_ENUMDONE) {
537 s->state = OTG_STATE_SETCONFIG_S;
538 s5pc1xx_usb_otg_act(s);
540 s5pc1xx_usb_otg_update_irq(s);
554 case 0x100 ... 0x13C:
555 s->ep_in[(addr - 0x100 ) >> 2].in_fifo_size = val;
559 for (i = 0; i < OTG_EP_COUNT; i++) {
560 s5pc1xx_usb_otg_ep_update_irq(&s->ep_in[i]);
565 for (i = 0; i < OTG_EP_COUNT; i++) {
566 s5pc1xx_usb_otg_ep_update_irq(&s->ep_out[i]);
571 if (s->daint_sts & 0xffff & s->daint_msk) {
572 s->gint_sts |= USB_INT_IEPINT;
574 s->gint_sts &= ~USB_INT_IEPINT;
576 if ((s->daint_sts & s->daint_msk) >> 16) {
577 s->gint_sts |= USB_INT_OEPINT;
579 s->gint_sts &= ~USB_INT_OEPINT;
581 s5pc1xx_usb_otg_update_irq(s);
583 case 0x900 ... 0xAFC:
585 s5pc1xx_usb_otg_ep_write(&s->ep_in[addr >> 5], addr & 0x1f, val);
587 case 0xB00 ... 0xCFC:
589 s5pc1xx_usb_otg_ep_write(&s->ep_out[addr >> 5], addr & 0x1f, val);
594 static CPUReadMemoryFunc * const s5pc1xx_usb_otg_readfn[] = {
595 s5pc1xx_usb_otg_read,
596 s5pc1xx_usb_otg_read,
600 static CPUWriteMemoryFunc * const s5pc1xx_usb_otg_writefn[] = {
601 s5pc1xx_usb_otg_write,
602 s5pc1xx_usb_otg_write,
603 s5pc1xx_usb_otg_write
606 static void s5pc1xx_usb_otg_save(QEMUFile *f, void *opaque)
608 S5pc1xxUsbOtgState *s = (S5pc1xxUsbOtgState *)opaque;
611 qemu_put_be32s(f, &s->phy.power);
612 qemu_put_be32s(f, &s->phy.clock);
613 qemu_put_be32s(f, &s->phy.reset);
614 qemu_put_be32s(f, &s->phy.tune0);
615 qemu_put_be32s(f, &s->phy.tune1);
617 qemu_put_be32s(f, &s->gotg_ctl);
618 qemu_put_be32s(f, &s->gotg_int);
619 qemu_put_be32s(f, &s->gahb_cfg);
620 qemu_put_be32s(f, &s->gusb_cfg);
621 qemu_put_be32s(f, &s->grst_ctl);
622 qemu_put_be32s(f, &s->gint_sts);
623 qemu_put_be32s(f, &s->gint_msk);
624 qemu_put_be32s(f, &s->grx_stsr);
625 qemu_put_be32s(f, &s->grx_stsp);
626 qemu_put_be32s(f, &s->grx_fsiz);
627 qemu_put_be32s(f, &s->gnptx_fsiz);
628 qemu_put_be32s(f, &s->gnptx_sts);
629 qemu_put_be32s(f, &s->hnptx_fsiz);
630 qemu_put_be32s(f, &s->daint_sts);
631 qemu_put_be32s(f, &s->daint_msk);
632 qemu_put_be32s(f, &s->diep_msk);
633 qemu_put_be32s(f, &s->doep_msk);
634 qemu_put_byte (f, (uint8_t) s->state);
636 for (i = 0; i < OTG_EP_COUNT; i++) {
637 qemu_put_be32s(f, &s->ep_in[i].ctrl);
638 qemu_put_be32s(f, &s->ep_in[i].interrupt);
639 qemu_put_be32s(f, &s->ep_in[i].transfer_size);
640 qemu_put_be32s(f, &s->ep_in[i].dma_addr);
641 qemu_put_be32s(f, &s->ep_in[i].dma_buf);
642 qemu_put_be32s(f, &s->ep_in[i].in_fifo_size);
644 qemu_put_be32s(f, &s->ep_out[i].ctrl);
645 qemu_put_be32s(f, &s->ep_out[i].interrupt);
646 qemu_put_be32s(f, &s->ep_out[i].transfer_size);
647 qemu_put_be32s(f, &s->ep_out[i].dma_addr);
648 qemu_put_be32s(f, &s->ep_out[i].dma_buf);
649 qemu_put_be32s(f, &s->ep_out[i].in_fifo_size);
651 /* FIXME: must the structure below be saved?
653 qemu_put_be32s (f, &s->buf_size);
654 qemu_put_buffer(f, s->buf, s->buf_size);
655 qemu_put_8s (f, &s->buf_full);
658 static int s5pc1xx_usb_otg_load(QEMUFile *f, void *opaque, int version_id)
660 S5pc1xxUsbOtgState *s = (S5pc1xxUsbOtgState *)opaque;
663 if (version_id != 1) {
667 qemu_get_be32s(f, &s->phy.power);
668 qemu_get_be32s(f, &s->phy.clock);
669 qemu_get_be32s(f, &s->phy.reset);
670 qemu_get_be32s(f, &s->phy.tune0);
671 qemu_get_be32s(f, &s->phy.tune1);
673 qemu_get_be32s(f, &s->gotg_ctl);
674 qemu_get_be32s(f, &s->gotg_int);
675 qemu_get_be32s(f, &s->gahb_cfg);
676 qemu_get_be32s(f, &s->gusb_cfg);
677 qemu_get_be32s(f, &s->grst_ctl);
678 qemu_get_be32s(f, &s->gint_sts);
679 qemu_get_be32s(f, &s->gint_msk);
680 qemu_get_be32s(f, &s->grx_stsr);
681 qemu_get_be32s(f, &s->grx_stsp);
682 qemu_get_be32s(f, &s->grx_fsiz);
683 qemu_get_be32s(f, &s->gnptx_fsiz);
684 qemu_get_be32s(f, &s->gnptx_sts);
685 qemu_get_be32s(f, &s->hnptx_fsiz);
686 qemu_get_be32s(f, &s->daint_sts);
687 qemu_get_be32s(f, &s->daint_msk);
688 qemu_get_be32s(f, &s->diep_msk);
689 qemu_get_be32s(f, &s->doep_msk);
690 s->state = qemu_get_byte(f);
692 for (i = 0; i < OTG_EP_COUNT; i++) {
693 qemu_get_be32s(f, &s->ep_in[i].ctrl);
694 qemu_get_be32s(f, &s->ep_in[i].interrupt);
695 qemu_get_be32s(f, &s->ep_in[i].transfer_size);
696 qemu_get_be32s(f, &s->ep_in[i].dma_addr);
697 qemu_get_be32s(f, &s->ep_in[i].dma_buf);
698 qemu_get_be32s(f, &s->ep_in[i].in_fifo_size);
700 qemu_get_be32s(f, &s->ep_out[i].ctrl);
701 qemu_get_be32s(f, &s->ep_out[i].interrupt);
702 qemu_get_be32s(f, &s->ep_out[i].transfer_size);
703 qemu_get_be32s(f, &s->ep_out[i].dma_addr);
704 qemu_get_be32s(f, &s->ep_out[i].dma_buf);
705 qemu_get_be32s(f, &s->ep_out[i].in_fifo_size);
707 /* FIXME: NICState *nic; */
708 qemu_get_be32s (f, &s->buf_size);
709 qemu_get_buffer(f, s->buf, s->buf_size);
710 qemu_get_8s (f, &s->buf_full);
715 static int s5pc1xx_usb_otg_can_receive(VLANClientState *nc)
717 S5pc1xxUsbOtgState *s = (DO_UPCAST(NICState, nc, nc))->opaque;
722 static ssize_t s5pc1xx_usb_otg_receive(VLANClientState *nc, const uint8_t *buf,
725 S5pc1xxUsbOtgState *s = (DO_UPCAST(NICState, nc, nc))->opaque;
730 memcpy(s->buf, buf, size);
731 for (i = 0; i < OTG_EP_COUNT; i++) {
732 if (s->ep_out[i].ctrl & OTG_EP_ENABLE) {
733 s5pc1xx_usb_otg_data_rx(&s->ep_out[i]);
740 static void s5pc1xx_usb_otg_cleanup(VLANClientState *nc)
742 S5pc1xxUsbOtgState *s = (DO_UPCAST(NICState, nc, nc))->opaque;
747 static NetClientInfo net_s5pc1xx_usb_otg_info = {
748 .type = NET_CLIENT_TYPE_NIC,
749 .size = sizeof(NICState),
750 .can_receive = s5pc1xx_usb_otg_can_receive,
751 .receive = s5pc1xx_usb_otg_receive,
752 .cleanup = s5pc1xx_usb_otg_cleanup,
755 static int s5pc1xx_usb_otg_init1(SysBusDevice *dev)
758 S5pc1xxUsbOtgState *s = FROM_SYSBUS(S5pc1xxUsbOtgState, dev);
761 cpu_register_io_memory(s5pc1xx_usb_otg_readfn,
762 s5pc1xx_usb_otg_writefn, s, DEVICE_NATIVE_ENDIAN);
763 sysbus_init_mmio(dev, 0x100030, iomemtype);
764 sysbus_init_irq(dev, &s->irq);
766 qemu_macaddr_default_if_unset(&s->conf.macaddr);
768 s5pc1xx_usb_otg_initial_reset(&s->busdev.qdev);
770 s->nic = qemu_new_nic(&net_s5pc1xx_usb_otg_info, &s->conf,
771 dev->qdev.info->name, dev->qdev.id, s);
772 qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
774 register_savevm(&dev->qdev, "s5pc1xx.usb.otg", -1, 1,
775 s5pc1xx_usb_otg_save, s5pc1xx_usb_otg_load, s);
780 static SysBusDeviceInfo s5pc1xx_usb_otg_info = {
781 .init = s5pc1xx_usb_otg_init1,
782 .qdev.name = "s5pc1xx.usb.otg",
783 .qdev.size = sizeof(S5pc1xxUsbOtgState),
784 .qdev.reset = s5pc1xx_usb_otg_initial_reset,
785 .qdev.props = (Property[]) {
786 DEFINE_NIC_PROPERTIES(S5pc1xxUsbOtgState, conf),
787 DEFINE_PROP_END_OF_LIST(),
791 static void s5pc1xx_usb_otg_register_devices(void)
793 sysbus_register_withprop(&s5pc1xx_usb_otg_info);
796 /* Legacy helper function. Should go away when machine config files are
798 void s5pc1xx_usb_otg_init(NICInfo *nd, target_phys_addr_t base, qemu_irq irq)
803 qemu_check_nic_model(nd, "s5pc1xx-usb-otg");
804 dev = qdev_create(NULL, "s5pc1xx.usb.otg");
805 qdev_set_nic_properties(dev, nd);
806 qdev_init_nofail(dev);
807 s = sysbus_from_qdev(dev);
808 sysbus_mmio_map(s, 0, base);
809 sysbus_connect_irq(s, 0, irq);
812 device_init(s5pc1xx_usb_otg_register_devices)