hcd-ehci-sysbus.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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_BOOL("companion-enable", EHCISysBusState, ehci.companion_enable,
  34. false),
  35. DEFINE_PROP_END_OF_LIST(),
  36. };
  37. static void usb_ehci_sysbus_realize(DeviceState *dev, Error **errp)
  38. {
  39. SysBusDevice *d = SYS_BUS_DEVICE(dev);
  40. EHCISysBusState *i = SYS_BUS_EHCI(dev);
  41. EHCIState *s = &i->ehci;
  42. usb_ehci_realize(s, dev, errp);
  43. sysbus_init_irq(d, &s->irq);
  44. }
  45. static void usb_ehci_sysbus_reset(DeviceState *dev)
  46. {
  47. SysBusDevice *d = SYS_BUS_DEVICE(dev);
  48. EHCISysBusState *i = SYS_BUS_EHCI(d);
  49. EHCIState *s = &i->ehci;
  50. ehci_reset(s);
  51. }
  52. static void ehci_sysbus_init(Object *obj)
  53. {
  54. SysBusDevice *d = SYS_BUS_DEVICE(obj);
  55. EHCISysBusState *i = SYS_BUS_EHCI(obj);
  56. SysBusEHCIClass *sec = SYS_BUS_EHCI_GET_CLASS(obj);
  57. EHCIState *s = &i->ehci;
  58. s->capsbase = sec->capsbase;
  59. s->opregbase = sec->opregbase;
  60. s->portscbase = sec->portscbase;
  61. s->portnr = sec->portnr;
  62. s->as = &address_space_memory;
  63. usb_ehci_init(s, DEVICE(obj));
  64. sysbus_init_mmio(d, &s->mem);
  65. }
  66. static void ehci_sysbus_class_init(ObjectClass *klass, void *data)
  67. {
  68. DeviceClass *dc = DEVICE_CLASS(klass);
  69. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(klass);
  70. sec->portscbase = 0x44;
  71. sec->portnr = NB_PORTS;
  72. dc->realize = usb_ehci_sysbus_realize;
  73. dc->vmsd = &vmstate_ehci_sysbus;
  74. device_class_set_props(dc, ehci_sysbus_properties);
  75. dc->reset = usb_ehci_sysbus_reset;
  76. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  77. }
  78. static const TypeInfo ehci_type_info = {
  79. .name = TYPE_SYS_BUS_EHCI,
  80. .parent = TYPE_SYS_BUS_DEVICE,
  81. .instance_size = sizeof(EHCISysBusState),
  82. .instance_init = ehci_sysbus_init,
  83. .abstract = true,
  84. .class_init = ehci_sysbus_class_init,
  85. .class_size = sizeof(SysBusEHCIClass),
  86. };
  87. static void ehci_platform_class_init(ObjectClass *oc, void *data)
  88. {
  89. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  90. DeviceClass *dc = DEVICE_CLASS(oc);
  91. sec->capsbase = 0x0;
  92. sec->opregbase = 0x20;
  93. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  94. }
  95. static const TypeInfo ehci_platform_type_info = {
  96. .name = TYPE_PLATFORM_EHCI,
  97. .parent = TYPE_SYS_BUS_EHCI,
  98. .class_init = ehci_platform_class_init,
  99. };
  100. static void ehci_exynos4210_class_init(ObjectClass *oc, void *data)
  101. {
  102. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  103. DeviceClass *dc = DEVICE_CLASS(oc);
  104. sec->capsbase = 0x0;
  105. sec->opregbase = 0x10;
  106. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  107. }
  108. static const TypeInfo ehci_exynos4210_type_info = {
  109. .name = TYPE_EXYNOS4210_EHCI,
  110. .parent = TYPE_SYS_BUS_EHCI,
  111. .class_init = ehci_exynos4210_class_init,
  112. };
  113. static void ehci_aw_h3_class_init(ObjectClass *oc, void *data)
  114. {
  115. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  116. DeviceClass *dc = DEVICE_CLASS(oc);
  117. sec->capsbase = 0x0;
  118. sec->opregbase = 0x10;
  119. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  120. }
  121. static const TypeInfo ehci_aw_h3_type_info = {
  122. .name = TYPE_AW_H3_EHCI,
  123. .parent = TYPE_SYS_BUS_EHCI,
  124. .class_init = ehci_aw_h3_class_init,
  125. };
  126. static void ehci_tegra2_class_init(ObjectClass *oc, void *data)
  127. {
  128. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  129. DeviceClass *dc = DEVICE_CLASS(oc);
  130. sec->capsbase = 0x100;
  131. sec->opregbase = 0x140;
  132. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  133. }
  134. static const TypeInfo ehci_tegra2_type_info = {
  135. .name = TYPE_TEGRA2_EHCI,
  136. .parent = TYPE_SYS_BUS_EHCI,
  137. .class_init = ehci_tegra2_class_init,
  138. };
  139. static void ehci_ppc4xx_init(Object *o)
  140. {
  141. EHCISysBusState *s = SYS_BUS_EHCI(o);
  142. s->ehci.companion_enable = true;
  143. }
  144. static void ehci_ppc4xx_class_init(ObjectClass *oc, void *data)
  145. {
  146. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  147. DeviceClass *dc = DEVICE_CLASS(oc);
  148. sec->capsbase = 0x0;
  149. sec->opregbase = 0x10;
  150. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  151. }
  152. static const TypeInfo ehci_ppc4xx_type_info = {
  153. .name = TYPE_PPC4xx_EHCI,
  154. .parent = TYPE_SYS_BUS_EHCI,
  155. .class_init = ehci_ppc4xx_class_init,
  156. .instance_init = ehci_ppc4xx_init,
  157. };
  158. /*
  159. * Faraday FUSBH200 USB 2.0 EHCI
  160. */
  161. /**
  162. * FUSBH200EHCIRegs:
  163. * @FUSBH200_REG_EOF_ASTR: EOF/Async. Sleep Timer Register
  164. * @FUSBH200_REG_BMCSR: Bus Monitor Control/Status Register
  165. */
  166. enum FUSBH200EHCIRegs {
  167. FUSBH200_REG_EOF_ASTR = 0x34,
  168. FUSBH200_REG_BMCSR = 0x40,
  169. };
  170. static uint64_t fusbh200_ehci_read(void *opaque, hwaddr addr, unsigned size)
  171. {
  172. EHCIState *s = opaque;
  173. hwaddr off = s->opregbase + s->portscbase + 4 * s->portnr + addr;
  174. switch (off) {
  175. case FUSBH200_REG_EOF_ASTR:
  176. return 0x00000041;
  177. case FUSBH200_REG_BMCSR:
  178. /* High-Speed, VBUS valid, interrupt level-high active */
  179. return (2 << 9) | (1 << 8) | (1 << 3);
  180. }
  181. return 0;
  182. }
  183. static void fusbh200_ehci_write(void *opaque, hwaddr addr, uint64_t val,
  184. unsigned size)
  185. {
  186. }
  187. static const MemoryRegionOps fusbh200_ehci_mmio_ops = {
  188. .read = fusbh200_ehci_read,
  189. .write = fusbh200_ehci_write,
  190. .valid.min_access_size = 4,
  191. .valid.max_access_size = 4,
  192. .endianness = DEVICE_LITTLE_ENDIAN,
  193. };
  194. static void fusbh200_ehci_init(Object *obj)
  195. {
  196. EHCISysBusState *i = SYS_BUS_EHCI(obj);
  197. FUSBH200EHCIState *f = FUSBH200_EHCI(obj);
  198. EHCIState *s = &i->ehci;
  199. memory_region_init_io(&f->mem_vendor, OBJECT(f), &fusbh200_ehci_mmio_ops, s,
  200. "fusbh200", 0x4c);
  201. memory_region_add_subregion(&s->mem,
  202. s->opregbase + s->portscbase + 4 * s->portnr,
  203. &f->mem_vendor);
  204. }
  205. static void fusbh200_ehci_class_init(ObjectClass *oc, void *data)
  206. {
  207. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  208. DeviceClass *dc = DEVICE_CLASS(oc);
  209. sec->capsbase = 0x0;
  210. sec->opregbase = 0x10;
  211. sec->portscbase = 0x20;
  212. sec->portnr = 1;
  213. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  214. }
  215. static const TypeInfo ehci_fusbh200_type_info = {
  216. .name = TYPE_FUSBH200_EHCI,
  217. .parent = TYPE_SYS_BUS_EHCI,
  218. .instance_size = sizeof(FUSBH200EHCIState),
  219. .instance_init = fusbh200_ehci_init,
  220. .class_init = fusbh200_ehci_class_init,
  221. };
  222. static void ehci_sysbus_register_types(void)
  223. {
  224. type_register_static(&ehci_type_info);
  225. type_register_static(&ehci_platform_type_info);
  226. type_register_static(&ehci_exynos4210_type_info);
  227. type_register_static(&ehci_aw_h3_type_info);
  228. type_register_static(&ehci_tegra2_type_info);
  229. type_register_static(&ehci_ppc4xx_type_info);
  230. type_register_static(&ehci_fusbh200_type_info);
  231. }
  232. type_init(ehci_sysbus_register_types)