hcd-ehci-sysbus.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /*
  2. * QEMU USB EHCI Emulation
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public License
  15. * along with this program; if not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "qemu/osdep.h"
  18. #include "hw/qdev-properties.h"
  19. #include "hw/usb/hcd-ehci.h"
  20. #include "migration/vmstate.h"
  21. #include "qemu/module.h"
  22. static const VMStateDescription vmstate_ehci_sysbus = {
  23. .name = "ehci-sysbus",
  24. .version_id = 2,
  25. .minimum_version_id = 1,
  26. .fields = (VMStateField[]) {
  27. VMSTATE_STRUCT(ehci, EHCISysBusState, 2, vmstate_ehci, EHCIState),
  28. VMSTATE_END_OF_LIST()
  29. }
  30. };
  31. static Property ehci_sysbus_properties[] = {
  32. DEFINE_PROP_UINT32("maxframes", EHCISysBusState, ehci.maxframes, 128),
  33. DEFINE_PROP_END_OF_LIST(),
  34. };
  35. static void usb_ehci_sysbus_realize(DeviceState *dev, Error **errp)
  36. {
  37. SysBusDevice *d = SYS_BUS_DEVICE(dev);
  38. EHCISysBusState *i = SYS_BUS_EHCI(dev);
  39. EHCIState *s = &i->ehci;
  40. usb_ehci_realize(s, dev, errp);
  41. sysbus_init_irq(d, &s->irq);
  42. }
  43. static void usb_ehci_sysbus_reset(DeviceState *dev)
  44. {
  45. SysBusDevice *d = SYS_BUS_DEVICE(dev);
  46. EHCISysBusState *i = SYS_BUS_EHCI(d);
  47. EHCIState *s = &i->ehci;
  48. ehci_reset(s);
  49. }
  50. static void ehci_sysbus_init(Object *obj)
  51. {
  52. SysBusDevice *d = SYS_BUS_DEVICE(obj);
  53. EHCISysBusState *i = SYS_BUS_EHCI(obj);
  54. SysBusEHCIClass *sec = SYS_BUS_EHCI_GET_CLASS(obj);
  55. EHCIState *s = &i->ehci;
  56. s->capsbase = sec->capsbase;
  57. s->opregbase = sec->opregbase;
  58. s->portscbase = sec->portscbase;
  59. s->portnr = sec->portnr;
  60. s->as = &address_space_memory;
  61. usb_ehci_init(s, DEVICE(obj));
  62. sysbus_init_mmio(d, &s->mem);
  63. }
  64. static void ehci_sysbus_class_init(ObjectClass *klass, void *data)
  65. {
  66. DeviceClass *dc = DEVICE_CLASS(klass);
  67. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(klass);
  68. sec->portscbase = 0x44;
  69. sec->portnr = NB_PORTS;
  70. dc->realize = usb_ehci_sysbus_realize;
  71. dc->vmsd = &vmstate_ehci_sysbus;
  72. dc->props = ehci_sysbus_properties;
  73. dc->reset = usb_ehci_sysbus_reset;
  74. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  75. }
  76. static const TypeInfo ehci_type_info = {
  77. .name = TYPE_SYS_BUS_EHCI,
  78. .parent = TYPE_SYS_BUS_DEVICE,
  79. .instance_size = sizeof(EHCISysBusState),
  80. .instance_init = ehci_sysbus_init,
  81. .abstract = true,
  82. .class_init = ehci_sysbus_class_init,
  83. .class_size = sizeof(SysBusEHCIClass),
  84. };
  85. static void ehci_platform_class_init(ObjectClass *oc, void *data)
  86. {
  87. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  88. DeviceClass *dc = DEVICE_CLASS(oc);
  89. sec->capsbase = 0x0;
  90. sec->opregbase = 0x20;
  91. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  92. }
  93. static const TypeInfo ehci_platform_type_info = {
  94. .name = TYPE_PLATFORM_EHCI,
  95. .parent = TYPE_SYS_BUS_EHCI,
  96. .class_init = ehci_platform_class_init,
  97. };
  98. static void ehci_xlnx_class_init(ObjectClass *oc, void *data)
  99. {
  100. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  101. DeviceClass *dc = DEVICE_CLASS(oc);
  102. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  103. sec->capsbase = 0x100;
  104. sec->opregbase = 0x140;
  105. }
  106. static const TypeInfo ehci_xlnx_type_info = {
  107. .name = "xlnx,ps7-usb",
  108. .parent = TYPE_SYS_BUS_EHCI,
  109. .class_init = ehci_xlnx_class_init,
  110. };
  111. static void ehci_exynos4210_class_init(ObjectClass *oc, void *data)
  112. {
  113. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  114. DeviceClass *dc = DEVICE_CLASS(oc);
  115. sec->capsbase = 0x0;
  116. sec->opregbase = 0x10;
  117. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  118. }
  119. static const TypeInfo ehci_exynos4210_type_info = {
  120. .name = TYPE_EXYNOS4210_EHCI,
  121. .parent = TYPE_SYS_BUS_EHCI,
  122. .class_init = ehci_exynos4210_class_init,
  123. };
  124. static void ehci_tegra2_class_init(ObjectClass *oc, void *data)
  125. {
  126. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  127. DeviceClass *dc = DEVICE_CLASS(oc);
  128. sec->capsbase = 0x100;
  129. sec->opregbase = 0x140;
  130. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  131. }
  132. static const TypeInfo ehci_tegra2_type_info = {
  133. .name = TYPE_TEGRA2_EHCI,
  134. .parent = TYPE_SYS_BUS_EHCI,
  135. .class_init = ehci_tegra2_class_init,
  136. };
  137. static void ehci_ppc4xx_init(Object *o)
  138. {
  139. EHCISysBusState *s = SYS_BUS_EHCI(o);
  140. s->ehci.companion_enable = true;
  141. }
  142. static void ehci_ppc4xx_class_init(ObjectClass *oc, void *data)
  143. {
  144. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  145. DeviceClass *dc = DEVICE_CLASS(oc);
  146. sec->capsbase = 0x0;
  147. sec->opregbase = 0x10;
  148. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  149. }
  150. static const TypeInfo ehci_ppc4xx_type_info = {
  151. .name = TYPE_PPC4xx_EHCI,
  152. .parent = TYPE_SYS_BUS_EHCI,
  153. .class_init = ehci_ppc4xx_class_init,
  154. .instance_init = ehci_ppc4xx_init,
  155. };
  156. /*
  157. * Faraday FUSBH200 USB 2.0 EHCI
  158. */
  159. /**
  160. * FUSBH200EHCIRegs:
  161. * @FUSBH200_REG_EOF_ASTR: EOF/Async. Sleep Timer Register
  162. * @FUSBH200_REG_BMCSR: Bus Monitor Control/Status Register
  163. */
  164. enum FUSBH200EHCIRegs {
  165. FUSBH200_REG_EOF_ASTR = 0x34,
  166. FUSBH200_REG_BMCSR = 0x40,
  167. };
  168. static uint64_t fusbh200_ehci_read(void *opaque, hwaddr addr, unsigned size)
  169. {
  170. EHCIState *s = opaque;
  171. hwaddr off = s->opregbase + s->portscbase + 4 * s->portnr + addr;
  172. switch (off) {
  173. case FUSBH200_REG_EOF_ASTR:
  174. return 0x00000041;
  175. case FUSBH200_REG_BMCSR:
  176. /* High-Speed, VBUS valid, interrupt level-high active */
  177. return (2 << 9) | (1 << 8) | (1 << 3);
  178. }
  179. return 0;
  180. }
  181. static void fusbh200_ehci_write(void *opaque, hwaddr addr, uint64_t val,
  182. unsigned size)
  183. {
  184. }
  185. static const MemoryRegionOps fusbh200_ehci_mmio_ops = {
  186. .read = fusbh200_ehci_read,
  187. .write = fusbh200_ehci_write,
  188. .valid.min_access_size = 4,
  189. .valid.max_access_size = 4,
  190. .endianness = DEVICE_LITTLE_ENDIAN,
  191. };
  192. static void fusbh200_ehci_init(Object *obj)
  193. {
  194. EHCISysBusState *i = SYS_BUS_EHCI(obj);
  195. FUSBH200EHCIState *f = FUSBH200_EHCI(obj);
  196. EHCIState *s = &i->ehci;
  197. memory_region_init_io(&f->mem_vendor, OBJECT(f), &fusbh200_ehci_mmio_ops, s,
  198. "fusbh200", 0x4c);
  199. memory_region_add_subregion(&s->mem,
  200. s->opregbase + s->portscbase + 4 * s->portnr,
  201. &f->mem_vendor);
  202. }
  203. static void fusbh200_ehci_class_init(ObjectClass *oc, void *data)
  204. {
  205. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  206. DeviceClass *dc = DEVICE_CLASS(oc);
  207. sec->capsbase = 0x0;
  208. sec->opregbase = 0x10;
  209. sec->portscbase = 0x20;
  210. sec->portnr = 1;
  211. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  212. }
  213. static const TypeInfo ehci_fusbh200_type_info = {
  214. .name = TYPE_FUSBH200_EHCI,
  215. .parent = TYPE_SYS_BUS_EHCI,
  216. .instance_size = sizeof(FUSBH200EHCIState),
  217. .instance_init = fusbh200_ehci_init,
  218. .class_init = fusbh200_ehci_class_init,
  219. };
  220. static void ehci_sysbus_register_types(void)
  221. {
  222. type_register_static(&ehci_type_info);
  223. type_register_static(&ehci_platform_type_info);
  224. type_register_static(&ehci_xlnx_type_info);
  225. type_register_static(&ehci_exynos4210_type_info);
  226. type_register_static(&ehci_tegra2_type_info);
  227. type_register_static(&ehci_ppc4xx_type_info);
  228. type_register_static(&ehci_fusbh200_type_info);
  229. }
  230. type_init(ehci_sysbus_register_types)