hcd-ehci-sysbus.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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. static const VMStateDescription vmstate_ehci_sysbus = {
  22. .name = "ehci-sysbus",
  23. .version_id = 2,
  24. .minimum_version_id = 1,
  25. .fields = (const VMStateField[]) {
  26. VMSTATE_STRUCT(ehci, EHCISysBusState, 2, vmstate_ehci, EHCIState),
  27. VMSTATE_END_OF_LIST()
  28. }
  29. };
  30. static const Property ehci_sysbus_properties[] = {
  31. DEFINE_PROP_UINT32("maxframes", EHCISysBusState, ehci.maxframes, 128),
  32. DEFINE_PROP_BOOL("companion-enable", EHCISysBusState, ehci.companion_enable,
  33. false),
  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_finalize(Object *obj)
  65. {
  66. EHCISysBusState *i = SYS_BUS_EHCI(obj);
  67. EHCIState *s = &i->ehci;
  68. usb_ehci_finalize(s);
  69. }
  70. static void ehci_sysbus_class_init(ObjectClass *klass, void *data)
  71. {
  72. DeviceClass *dc = DEVICE_CLASS(klass);
  73. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(klass);
  74. sec->portscbase = 0x44;
  75. sec->portnr = EHCI_PORTS;
  76. dc->realize = usb_ehci_sysbus_realize;
  77. dc->vmsd = &vmstate_ehci_sysbus;
  78. device_class_set_props(dc, ehci_sysbus_properties);
  79. device_class_set_legacy_reset(dc, usb_ehci_sysbus_reset);
  80. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  81. }
  82. static void ehci_platform_class_init(ObjectClass *oc, void *data)
  83. {
  84. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  85. DeviceClass *dc = DEVICE_CLASS(oc);
  86. sec->capsbase = 0x0;
  87. sec->opregbase = 0x20;
  88. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  89. }
  90. static void ehci_exynos4210_class_init(ObjectClass *oc, void *data)
  91. {
  92. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  93. DeviceClass *dc = DEVICE_CLASS(oc);
  94. sec->capsbase = 0x0;
  95. sec->opregbase = 0x10;
  96. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  97. }
  98. static void ehci_aw_h3_class_init(ObjectClass *oc, void *data)
  99. {
  100. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  101. DeviceClass *dc = DEVICE_CLASS(oc);
  102. sec->capsbase = 0x0;
  103. sec->opregbase = 0x10;
  104. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  105. }
  106. static void ehci_npcm7xx_class_init(ObjectClass *oc, void *data)
  107. {
  108. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  109. DeviceClass *dc = DEVICE_CLASS(oc);
  110. sec->capsbase = 0x0;
  111. sec->opregbase = 0x10;
  112. sec->portscbase = 0x44;
  113. sec->portnr = 1;
  114. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  115. }
  116. static void ehci_tegra2_class_init(ObjectClass *oc, void *data)
  117. {
  118. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  119. DeviceClass *dc = DEVICE_CLASS(oc);
  120. sec->capsbase = 0x100;
  121. sec->opregbase = 0x140;
  122. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  123. }
  124. static void ehci_ppc4xx_init(Object *o)
  125. {
  126. EHCISysBusState *s = SYS_BUS_EHCI(o);
  127. s->ehci.companion_enable = true;
  128. }
  129. static void ehci_ppc4xx_class_init(ObjectClass *oc, void *data)
  130. {
  131. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  132. DeviceClass *dc = DEVICE_CLASS(oc);
  133. sec->capsbase = 0x0;
  134. sec->opregbase = 0x10;
  135. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  136. }
  137. /*
  138. * Faraday FUSBH200 USB 2.0 EHCI
  139. */
  140. /**
  141. * FUSBH200EHCIRegs:
  142. * @FUSBH200_REG_EOF_ASTR: EOF/Async. Sleep Timer Register
  143. * @FUSBH200_REG_BMCSR: Bus Monitor Control/Status Register
  144. */
  145. enum FUSBH200EHCIRegs {
  146. FUSBH200_REG_EOF_ASTR = 0x34,
  147. FUSBH200_REG_BMCSR = 0x40,
  148. };
  149. static uint64_t fusbh200_ehci_read(void *opaque, hwaddr addr, unsigned size)
  150. {
  151. EHCIState *s = opaque;
  152. hwaddr off = s->opregbase + s->portscbase + 4 * s->portnr + addr;
  153. switch (off) {
  154. case FUSBH200_REG_EOF_ASTR:
  155. return 0x00000041;
  156. case FUSBH200_REG_BMCSR:
  157. /* High-Speed, VBUS valid, interrupt level-high active */
  158. return (2 << 9) | (1 << 8) | (1 << 3);
  159. }
  160. return 0;
  161. }
  162. static void fusbh200_ehci_write(void *opaque, hwaddr addr, uint64_t val,
  163. unsigned size)
  164. {
  165. }
  166. static const MemoryRegionOps fusbh200_ehci_mmio_ops = {
  167. .read = fusbh200_ehci_read,
  168. .write = fusbh200_ehci_write,
  169. .valid.min_access_size = 4,
  170. .valid.max_access_size = 4,
  171. .endianness = DEVICE_LITTLE_ENDIAN,
  172. };
  173. static void fusbh200_ehci_init(Object *obj)
  174. {
  175. EHCISysBusState *i = SYS_BUS_EHCI(obj);
  176. FUSBH200EHCIState *f = FUSBH200_EHCI(obj);
  177. EHCIState *s = &i->ehci;
  178. memory_region_init_io(&f->mem_vendor, OBJECT(f), &fusbh200_ehci_mmio_ops, s,
  179. "fusbh200", 0x4c);
  180. memory_region_add_subregion(&s->mem,
  181. s->opregbase + s->portscbase + 4 * s->portnr,
  182. &f->mem_vendor);
  183. }
  184. static void fusbh200_ehci_class_init(ObjectClass *oc, void *data)
  185. {
  186. SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
  187. DeviceClass *dc = DEVICE_CLASS(oc);
  188. sec->capsbase = 0x0;
  189. sec->opregbase = 0x10;
  190. sec->portscbase = 0x20;
  191. sec->portnr = 1;
  192. set_bit(DEVICE_CATEGORY_USB, dc->categories);
  193. }
  194. static const TypeInfo ehci_sysbus_types[] = {
  195. {
  196. .name = TYPE_SYS_BUS_EHCI,
  197. .parent = TYPE_SYS_BUS_DEVICE,
  198. .instance_size = sizeof(EHCISysBusState),
  199. .instance_init = ehci_sysbus_init,
  200. .instance_finalize = ehci_sysbus_finalize,
  201. .abstract = true,
  202. .class_init = ehci_sysbus_class_init,
  203. .class_size = sizeof(SysBusEHCIClass),
  204. },
  205. {
  206. .name = TYPE_PLATFORM_EHCI,
  207. .parent = TYPE_SYS_BUS_EHCI,
  208. .class_init = ehci_platform_class_init,
  209. },
  210. {
  211. .name = TYPE_EXYNOS4210_EHCI,
  212. .parent = TYPE_SYS_BUS_EHCI,
  213. .class_init = ehci_exynos4210_class_init,
  214. },
  215. {
  216. .name = TYPE_AW_H3_EHCI,
  217. .parent = TYPE_SYS_BUS_EHCI,
  218. .class_init = ehci_aw_h3_class_init,
  219. },
  220. {
  221. .name = TYPE_NPCM7XX_EHCI,
  222. .parent = TYPE_SYS_BUS_EHCI,
  223. .class_init = ehci_npcm7xx_class_init,
  224. },
  225. {
  226. .name = TYPE_TEGRA2_EHCI,
  227. .parent = TYPE_SYS_BUS_EHCI,
  228. .class_init = ehci_tegra2_class_init,
  229. },
  230. {
  231. .name = TYPE_PPC4xx_EHCI,
  232. .parent = TYPE_SYS_BUS_EHCI,
  233. .class_init = ehci_ppc4xx_class_init,
  234. .instance_init = ehci_ppc4xx_init,
  235. },
  236. {
  237. .name = TYPE_FUSBH200_EHCI,
  238. .parent = TYPE_SYS_BUS_EHCI,
  239. .instance_size = sizeof(FUSBH200EHCIState),
  240. .instance_init = fusbh200_ehci_init,
  241. .class_init = fusbh200_ehci_class_init,
  242. },
  243. };
  244. DEFINE_TYPES(ehci_sysbus_types)