2
0

designware.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. /*
  2. * Copyright (c) 2018, Impinj, Inc.
  3. *
  4. * Designware PCIe IP block emulation
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. #include "qemu/osdep.h"
  21. #include "qapi/error.h"
  22. #include "qemu/module.h"
  23. #include "qemu/log.h"
  24. #include "hw/pci/msi.h"
  25. #include "hw/pci/pci_bridge.h"
  26. #include "hw/pci/pci_host.h"
  27. #include "hw/pci/pcie_port.h"
  28. #include "hw/qdev-properties.h"
  29. #include "migration/vmstate.h"
  30. #include "hw/irq.h"
  31. #include "hw/pci-host/designware.h"
  32. #define DESIGNWARE_PCIE_PORT_LINK_CONTROL 0x710
  33. #define DESIGNWARE_PCIE_PHY_DEBUG_R1 0x72C
  34. #define DESIGNWARE_PCIE_PHY_DEBUG_R1_XMLH_LINK_UP BIT(4)
  35. #define DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
  36. #define DESIGNWARE_PCIE_PORT_LOGIC_SPEED_CHANGE BIT(17)
  37. #define DESIGNWARE_PCIE_MSI_ADDR_LO 0x820
  38. #define DESIGNWARE_PCIE_MSI_ADDR_HI 0x824
  39. #define DESIGNWARE_PCIE_MSI_INTR0_ENABLE 0x828
  40. #define DESIGNWARE_PCIE_MSI_INTR0_MASK 0x82C
  41. #define DESIGNWARE_PCIE_MSI_INTR0_STATUS 0x830
  42. #define DESIGNWARE_PCIE_ATU_VIEWPORT 0x900
  43. #define DESIGNWARE_PCIE_ATU_REGION_INBOUND BIT(31)
  44. #define DESIGNWARE_PCIE_ATU_CR1 0x904
  45. #define DESIGNWARE_PCIE_ATU_TYPE_MEM (0x0 << 0)
  46. #define DESIGNWARE_PCIE_ATU_CR2 0x908
  47. #define DESIGNWARE_PCIE_ATU_ENABLE BIT(31)
  48. #define DESIGNWARE_PCIE_ATU_LOWER_BASE 0x90C
  49. #define DESIGNWARE_PCIE_ATU_UPPER_BASE 0x910
  50. #define DESIGNWARE_PCIE_ATU_LIMIT 0x914
  51. #define DESIGNWARE_PCIE_ATU_LOWER_TARGET 0x918
  52. #define DESIGNWARE_PCIE_ATU_BUS(x) (((x) >> 24) & 0xff)
  53. #define DESIGNWARE_PCIE_ATU_DEVFN(x) (((x) >> 16) & 0xff)
  54. #define DESIGNWARE_PCIE_ATU_UPPER_TARGET 0x91C
  55. #define DESIGNWARE_PCIE_IRQ_MSI 3
  56. static DesignwarePCIEHost *
  57. designware_pcie_root_to_host(DesignwarePCIERoot *root)
  58. {
  59. BusState *bus = qdev_get_parent_bus(DEVICE(root));
  60. return DESIGNWARE_PCIE_HOST(bus->parent);
  61. }
  62. static uint64_t designware_pcie_root_msi_read(void *opaque, hwaddr addr,
  63. unsigned size)
  64. {
  65. /*
  66. * Attempts to read from the MSI address are undefined in
  67. * the PCI specifications. For this hardware, the datasheet
  68. * specifies that a read from the magic address is simply not
  69. * intercepted by the MSI controller, and will go out to the
  70. * AHB/AXI bus like any other PCI-device-initiated DMA read.
  71. * This is not trivial to implement in QEMU, so since
  72. * well-behaved guests won't ever ask a PCI device to DMA from
  73. * this address we just log the missing functionality.
  74. */
  75. qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__);
  76. return 0;
  77. }
  78. static void designware_pcie_root_msi_write(void *opaque, hwaddr addr,
  79. uint64_t val, unsigned len)
  80. {
  81. DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(opaque);
  82. DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
  83. root->msi.intr[0].status |= BIT(val) & root->msi.intr[0].enable;
  84. if (root->msi.intr[0].status & ~root->msi.intr[0].mask) {
  85. qemu_set_irq(host->pci.irqs[DESIGNWARE_PCIE_IRQ_MSI], 1);
  86. }
  87. }
  88. static const MemoryRegionOps designware_pci_host_msi_ops = {
  89. .read = designware_pcie_root_msi_read,
  90. .write = designware_pcie_root_msi_write,
  91. .endianness = DEVICE_LITTLE_ENDIAN,
  92. .valid = {
  93. .min_access_size = 4,
  94. .max_access_size = 4,
  95. },
  96. };
  97. static void designware_pcie_root_update_msi_mapping(DesignwarePCIERoot *root)
  98. {
  99. MemoryRegion *mem = &root->msi.iomem;
  100. const uint64_t base = root->msi.base;
  101. const bool enable = root->msi.intr[0].enable;
  102. memory_region_set_address(mem, base);
  103. memory_region_set_enabled(mem, enable);
  104. }
  105. static DesignwarePCIEViewport *
  106. designware_pcie_root_get_current_viewport(DesignwarePCIERoot *root)
  107. {
  108. const unsigned int idx = root->atu_viewport & 0xF;
  109. const unsigned int dir =
  110. !!(root->atu_viewport & DESIGNWARE_PCIE_ATU_REGION_INBOUND);
  111. return &root->viewports[dir][idx];
  112. }
  113. static uint32_t
  114. designware_pcie_root_config_read(PCIDevice *d, uint32_t address, int len)
  115. {
  116. DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(d);
  117. DesignwarePCIEViewport *viewport =
  118. designware_pcie_root_get_current_viewport(root);
  119. uint32_t val;
  120. switch (address) {
  121. case DESIGNWARE_PCIE_PORT_LINK_CONTROL:
  122. /*
  123. * Linux guest uses this register only to configure number of
  124. * PCIE lane (which in our case is irrelevant) and doesn't
  125. * really care about the value it reads from this register
  126. */
  127. val = 0xDEADBEEF;
  128. break;
  129. case DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL:
  130. /*
  131. * To make sure that any code in guest waiting for speed
  132. * change does not time out we always report
  133. * PORT_LOGIC_SPEED_CHANGE as set
  134. */
  135. val = DESIGNWARE_PCIE_PORT_LOGIC_SPEED_CHANGE;
  136. break;
  137. case DESIGNWARE_PCIE_MSI_ADDR_LO:
  138. val = root->msi.base;
  139. break;
  140. case DESIGNWARE_PCIE_MSI_ADDR_HI:
  141. val = root->msi.base >> 32;
  142. break;
  143. case DESIGNWARE_PCIE_MSI_INTR0_ENABLE:
  144. val = root->msi.intr[0].enable;
  145. break;
  146. case DESIGNWARE_PCIE_MSI_INTR0_MASK:
  147. val = root->msi.intr[0].mask;
  148. break;
  149. case DESIGNWARE_PCIE_MSI_INTR0_STATUS:
  150. val = root->msi.intr[0].status;
  151. break;
  152. case DESIGNWARE_PCIE_PHY_DEBUG_R1:
  153. val = DESIGNWARE_PCIE_PHY_DEBUG_R1_XMLH_LINK_UP;
  154. break;
  155. case DESIGNWARE_PCIE_ATU_VIEWPORT:
  156. val = root->atu_viewport;
  157. break;
  158. case DESIGNWARE_PCIE_ATU_LOWER_BASE:
  159. val = viewport->base;
  160. break;
  161. case DESIGNWARE_PCIE_ATU_UPPER_BASE:
  162. val = viewport->base >> 32;
  163. break;
  164. case DESIGNWARE_PCIE_ATU_LOWER_TARGET:
  165. val = viewport->target;
  166. break;
  167. case DESIGNWARE_PCIE_ATU_UPPER_TARGET:
  168. val = viewport->target >> 32;
  169. break;
  170. case DESIGNWARE_PCIE_ATU_LIMIT:
  171. val = viewport->limit;
  172. break;
  173. case DESIGNWARE_PCIE_ATU_CR1:
  174. case DESIGNWARE_PCIE_ATU_CR2:
  175. val = viewport->cr[(address - DESIGNWARE_PCIE_ATU_CR1) /
  176. sizeof(uint32_t)];
  177. break;
  178. default:
  179. val = pci_default_read_config(d, address, len);
  180. break;
  181. }
  182. return val;
  183. }
  184. static uint64_t designware_pcie_root_data_access(void *opaque, hwaddr addr,
  185. uint64_t *val, unsigned len)
  186. {
  187. DesignwarePCIEViewport *viewport = opaque;
  188. DesignwarePCIERoot *root = viewport->root;
  189. const uint8_t busnum = DESIGNWARE_PCIE_ATU_BUS(viewport->target);
  190. const uint8_t devfn = DESIGNWARE_PCIE_ATU_DEVFN(viewport->target);
  191. PCIBus *pcibus = pci_get_bus(PCI_DEVICE(root));
  192. PCIDevice *pcidev = pci_find_device(pcibus, busnum, devfn);
  193. if (pcidev) {
  194. addr &= pci_config_size(pcidev) - 1;
  195. if (val) {
  196. pci_host_config_write_common(pcidev, addr,
  197. pci_config_size(pcidev),
  198. *val, len);
  199. } else {
  200. return pci_host_config_read_common(pcidev, addr,
  201. pci_config_size(pcidev),
  202. len);
  203. }
  204. }
  205. return UINT64_MAX;
  206. }
  207. static uint64_t designware_pcie_root_data_read(void *opaque, hwaddr addr,
  208. unsigned len)
  209. {
  210. return designware_pcie_root_data_access(opaque, addr, NULL, len);
  211. }
  212. static void designware_pcie_root_data_write(void *opaque, hwaddr addr,
  213. uint64_t val, unsigned len)
  214. {
  215. designware_pcie_root_data_access(opaque, addr, &val, len);
  216. }
  217. static const MemoryRegionOps designware_pci_host_conf_ops = {
  218. .read = designware_pcie_root_data_read,
  219. .write = designware_pcie_root_data_write,
  220. .endianness = DEVICE_LITTLE_ENDIAN,
  221. .valid = {
  222. .min_access_size = 1,
  223. .max_access_size = 4,
  224. },
  225. };
  226. static void designware_pcie_update_viewport(DesignwarePCIERoot *root,
  227. DesignwarePCIEViewport *viewport)
  228. {
  229. const uint64_t target = viewport->target;
  230. const uint64_t base = viewport->base;
  231. const uint64_t size = (uint64_t)viewport->limit - base + 1;
  232. const bool enabled = viewport->cr[1] & DESIGNWARE_PCIE_ATU_ENABLE;
  233. MemoryRegion *current, *other;
  234. if (viewport->cr[0] == DESIGNWARE_PCIE_ATU_TYPE_MEM) {
  235. current = &viewport->mem;
  236. other = &viewport->cfg;
  237. memory_region_set_alias_offset(current, target);
  238. } else {
  239. current = &viewport->cfg;
  240. other = &viewport->mem;
  241. }
  242. /*
  243. * An outbound viewport can be reconfigure from being MEM to CFG,
  244. * to account for that we disable the "other" memory region that
  245. * becomes unused due to that fact.
  246. */
  247. memory_region_set_enabled(other, false);
  248. if (enabled) {
  249. memory_region_set_size(current, size);
  250. memory_region_set_address(current, base);
  251. }
  252. memory_region_set_enabled(current, enabled);
  253. }
  254. static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address,
  255. uint32_t val, int len)
  256. {
  257. DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(d);
  258. DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
  259. DesignwarePCIEViewport *viewport =
  260. designware_pcie_root_get_current_viewport(root);
  261. switch (address) {
  262. case DESIGNWARE_PCIE_PORT_LINK_CONTROL:
  263. case DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL:
  264. case DESIGNWARE_PCIE_PHY_DEBUG_R1:
  265. /* No-op */
  266. break;
  267. case DESIGNWARE_PCIE_MSI_ADDR_LO:
  268. root->msi.base &= 0xFFFFFFFF00000000ULL;
  269. root->msi.base |= val;
  270. designware_pcie_root_update_msi_mapping(root);
  271. break;
  272. case DESIGNWARE_PCIE_MSI_ADDR_HI:
  273. root->msi.base &= 0x00000000FFFFFFFFULL;
  274. root->msi.base |= (uint64_t)val << 32;
  275. designware_pcie_root_update_msi_mapping(root);
  276. break;
  277. case DESIGNWARE_PCIE_MSI_INTR0_ENABLE:
  278. root->msi.intr[0].enable = val;
  279. designware_pcie_root_update_msi_mapping(root);
  280. break;
  281. case DESIGNWARE_PCIE_MSI_INTR0_MASK:
  282. root->msi.intr[0].mask = val;
  283. break;
  284. case DESIGNWARE_PCIE_MSI_INTR0_STATUS:
  285. root->msi.intr[0].status ^= val;
  286. if (!root->msi.intr[0].status) {
  287. qemu_set_irq(host->pci.irqs[DESIGNWARE_PCIE_IRQ_MSI], 0);
  288. }
  289. break;
  290. case DESIGNWARE_PCIE_ATU_VIEWPORT:
  291. root->atu_viewport = val;
  292. break;
  293. case DESIGNWARE_PCIE_ATU_LOWER_BASE:
  294. viewport->base &= 0xFFFFFFFF00000000ULL;
  295. viewport->base |= val;
  296. break;
  297. case DESIGNWARE_PCIE_ATU_UPPER_BASE:
  298. viewport->base &= 0x00000000FFFFFFFFULL;
  299. viewport->base |= (uint64_t)val << 32;
  300. break;
  301. case DESIGNWARE_PCIE_ATU_LOWER_TARGET:
  302. viewport->target &= 0xFFFFFFFF00000000ULL;
  303. viewport->target |= val;
  304. break;
  305. case DESIGNWARE_PCIE_ATU_UPPER_TARGET:
  306. viewport->target &= 0x00000000FFFFFFFFULL;
  307. viewport->target |= val;
  308. break;
  309. case DESIGNWARE_PCIE_ATU_LIMIT:
  310. viewport->limit = val;
  311. break;
  312. case DESIGNWARE_PCIE_ATU_CR1:
  313. viewport->cr[0] = val;
  314. break;
  315. case DESIGNWARE_PCIE_ATU_CR2:
  316. viewport->cr[1] = val;
  317. designware_pcie_update_viewport(root, viewport);
  318. break;
  319. default:
  320. pci_bridge_write_config(d, address, val, len);
  321. break;
  322. }
  323. }
  324. static char *designware_pcie_viewport_name(const char *direction,
  325. unsigned int i,
  326. const char *type)
  327. {
  328. return g_strdup_printf("PCI %s Viewport %u [%s]",
  329. direction, i, type);
  330. }
  331. static void designware_pcie_root_realize(PCIDevice *dev, Error **errp)
  332. {
  333. DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(dev);
  334. DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
  335. MemoryRegion *address_space = &host->pci.memory;
  336. PCIBridge *br = PCI_BRIDGE(dev);
  337. DesignwarePCIEViewport *viewport;
  338. /*
  339. * Dummy values used for initial configuration of MemoryRegions
  340. * that belong to a given viewport
  341. */
  342. const hwaddr dummy_offset = 0;
  343. const uint64_t dummy_size = 4;
  344. size_t i;
  345. br->bus_name = "dw-pcie";
  346. pci_set_word(dev->config + PCI_COMMAND,
  347. PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
  348. pci_config_set_interrupt_pin(dev->config, 1);
  349. pci_bridge_initfn(dev, TYPE_PCIE_BUS);
  350. pcie_port_init_reg(dev);
  351. pcie_cap_init(dev, 0x70, PCI_EXP_TYPE_ROOT_PORT,
  352. 0, &error_fatal);
  353. msi_nonbroken = true;
  354. msi_init(dev, 0x50, 32, true, true, &error_fatal);
  355. for (i = 0; i < DESIGNWARE_PCIE_NUM_VIEWPORTS; i++) {
  356. MemoryRegion *source, *destination, *mem;
  357. const char *direction;
  358. char *name;
  359. viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_INBOUND][i];
  360. viewport->inbound = true;
  361. viewport->base = 0x0000000000000000ULL;
  362. viewport->target = 0x0000000000000000ULL;
  363. viewport->limit = UINT32_MAX;
  364. viewport->cr[0] = DESIGNWARE_PCIE_ATU_TYPE_MEM;
  365. source = &host->pci.address_space_root;
  366. destination = get_system_memory();
  367. direction = "Inbound";
  368. /*
  369. * Configure MemoryRegion implementing PCI -> CPU memory
  370. * access
  371. */
  372. mem = &viewport->mem;
  373. name = designware_pcie_viewport_name(direction, i, "MEM");
  374. memory_region_init_alias(mem, OBJECT(root), name, destination,
  375. dummy_offset, dummy_size);
  376. memory_region_add_subregion_overlap(source, dummy_offset, mem, -1);
  377. memory_region_set_enabled(mem, false);
  378. g_free(name);
  379. viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_OUTBOUND][i];
  380. viewport->root = root;
  381. viewport->inbound = false;
  382. viewport->base = 0x0000000000000000ULL;
  383. viewport->target = 0x0000000000000000ULL;
  384. viewport->limit = UINT32_MAX;
  385. viewport->cr[0] = DESIGNWARE_PCIE_ATU_TYPE_MEM;
  386. destination = &host->pci.memory;
  387. direction = "Outbound";
  388. source = get_system_memory();
  389. /*
  390. * Configure MemoryRegion implementing CPU -> PCI memory
  391. * access
  392. */
  393. mem = &viewport->mem;
  394. name = designware_pcie_viewport_name(direction, i, "MEM");
  395. memory_region_init_alias(mem, OBJECT(root), name, destination,
  396. dummy_offset, dummy_size);
  397. memory_region_add_subregion(source, dummy_offset, mem);
  398. memory_region_set_enabled(mem, false);
  399. g_free(name);
  400. /*
  401. * Configure MemoryRegion implementing access to configuration
  402. * space
  403. */
  404. mem = &viewport->cfg;
  405. name = designware_pcie_viewport_name(direction, i, "CFG");
  406. memory_region_init_io(&viewport->cfg, OBJECT(root),
  407. &designware_pci_host_conf_ops,
  408. viewport, name, dummy_size);
  409. memory_region_add_subregion(source, dummy_offset, mem);
  410. memory_region_set_enabled(mem, false);
  411. g_free(name);
  412. }
  413. /*
  414. * If no inbound iATU windows are configured, HW defaults to
  415. * letting inbound TLPs to pass in. We emulate that by exlicitly
  416. * configuring first inbound window to cover all of target's
  417. * address space.
  418. *
  419. * NOTE: This will not work correctly for the case when first
  420. * configured inbound window is window 0
  421. */
  422. viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_INBOUND][0];
  423. viewport->cr[1] = DESIGNWARE_PCIE_ATU_ENABLE;
  424. designware_pcie_update_viewport(root, viewport);
  425. memory_region_init_io(&root->msi.iomem, OBJECT(root),
  426. &designware_pci_host_msi_ops,
  427. root, "pcie-msi", 0x4);
  428. /*
  429. * We initially place MSI interrupt I/O region a adress 0 and
  430. * disable it. It'll be later moved to correct offset and enabled
  431. * in designware_pcie_root_update_msi_mapping() as a part of
  432. * initialization done by guest OS
  433. */
  434. memory_region_add_subregion(address_space, dummy_offset, &root->msi.iomem);
  435. memory_region_set_enabled(&root->msi.iomem, false);
  436. }
  437. static void designware_pcie_set_irq(void *opaque, int irq_num, int level)
  438. {
  439. DesignwarePCIEHost *host = DESIGNWARE_PCIE_HOST(opaque);
  440. qemu_set_irq(host->pci.irqs[irq_num], level);
  441. }
  442. static const char *
  443. designware_pcie_host_root_bus_path(PCIHostState *host_bridge, PCIBus *rootbus)
  444. {
  445. return "0000:00";
  446. }
  447. static const VMStateDescription vmstate_designware_pcie_msi_bank = {
  448. .name = "designware-pcie-msi-bank",
  449. .version_id = 1,
  450. .minimum_version_id = 1,
  451. .fields = (VMStateField[]) {
  452. VMSTATE_UINT32(enable, DesignwarePCIEMSIBank),
  453. VMSTATE_UINT32(mask, DesignwarePCIEMSIBank),
  454. VMSTATE_UINT32(status, DesignwarePCIEMSIBank),
  455. VMSTATE_END_OF_LIST()
  456. }
  457. };
  458. static const VMStateDescription vmstate_designware_pcie_msi = {
  459. .name = "designware-pcie-msi",
  460. .version_id = 1,
  461. .minimum_version_id = 1,
  462. .fields = (VMStateField[]) {
  463. VMSTATE_UINT64(base, DesignwarePCIEMSI),
  464. VMSTATE_STRUCT_ARRAY(intr,
  465. DesignwarePCIEMSI,
  466. DESIGNWARE_PCIE_NUM_MSI_BANKS,
  467. 1,
  468. vmstate_designware_pcie_msi_bank,
  469. DesignwarePCIEMSIBank),
  470. VMSTATE_END_OF_LIST()
  471. }
  472. };
  473. static const VMStateDescription vmstate_designware_pcie_viewport = {
  474. .name = "designware-pcie-viewport",
  475. .version_id = 1,
  476. .minimum_version_id = 1,
  477. .fields = (VMStateField[]) {
  478. VMSTATE_UINT64(base, DesignwarePCIEViewport),
  479. VMSTATE_UINT64(target, DesignwarePCIEViewport),
  480. VMSTATE_UINT32(limit, DesignwarePCIEViewport),
  481. VMSTATE_UINT32_ARRAY(cr, DesignwarePCIEViewport, 2),
  482. VMSTATE_END_OF_LIST()
  483. }
  484. };
  485. static const VMStateDescription vmstate_designware_pcie_root = {
  486. .name = "designware-pcie-root",
  487. .version_id = 1,
  488. .minimum_version_id = 1,
  489. .fields = (VMStateField[]) {
  490. VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
  491. VMSTATE_UINT32(atu_viewport, DesignwarePCIERoot),
  492. VMSTATE_STRUCT_2DARRAY(viewports,
  493. DesignwarePCIERoot,
  494. 2,
  495. DESIGNWARE_PCIE_NUM_VIEWPORTS,
  496. 1,
  497. vmstate_designware_pcie_viewport,
  498. DesignwarePCIEViewport),
  499. VMSTATE_STRUCT(msi,
  500. DesignwarePCIERoot,
  501. 1,
  502. vmstate_designware_pcie_msi,
  503. DesignwarePCIEMSI),
  504. VMSTATE_END_OF_LIST()
  505. }
  506. };
  507. static void designware_pcie_root_class_init(ObjectClass *klass, void *data)
  508. {
  509. PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
  510. DeviceClass *dc = DEVICE_CLASS(klass);
  511. set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
  512. k->vendor_id = PCI_VENDOR_ID_SYNOPSYS;
  513. k->device_id = 0xABCD;
  514. k->revision = 0;
  515. k->class_id = PCI_CLASS_BRIDGE_PCI;
  516. k->exit = pci_bridge_exitfn;
  517. k->realize = designware_pcie_root_realize;
  518. k->config_read = designware_pcie_root_config_read;
  519. k->config_write = designware_pcie_root_config_write;
  520. dc->reset = pci_bridge_reset;
  521. /*
  522. * PCI-facing part of the host bridge, not usable without the
  523. * host-facing part, which can't be device_add'ed, yet.
  524. */
  525. dc->user_creatable = false;
  526. dc->vmsd = &vmstate_designware_pcie_root;
  527. }
  528. static uint64_t designware_pcie_host_mmio_read(void *opaque, hwaddr addr,
  529. unsigned int size)
  530. {
  531. PCIHostState *pci = PCI_HOST_BRIDGE(opaque);
  532. PCIDevice *device = pci_find_device(pci->bus, 0, 0);
  533. return pci_host_config_read_common(device,
  534. addr,
  535. pci_config_size(device),
  536. size);
  537. }
  538. static void designware_pcie_host_mmio_write(void *opaque, hwaddr addr,
  539. uint64_t val, unsigned int size)
  540. {
  541. PCIHostState *pci = PCI_HOST_BRIDGE(opaque);
  542. PCIDevice *device = pci_find_device(pci->bus, 0, 0);
  543. return pci_host_config_write_common(device,
  544. addr,
  545. pci_config_size(device),
  546. val, size);
  547. }
  548. static const MemoryRegionOps designware_pci_mmio_ops = {
  549. .read = designware_pcie_host_mmio_read,
  550. .write = designware_pcie_host_mmio_write,
  551. .endianness = DEVICE_LITTLE_ENDIAN,
  552. .impl = {
  553. /*
  554. * Our device would not work correctly if the guest was doing
  555. * unaligned access. This might not be a limitation on the real
  556. * device but in practice there is no reason for a guest to access
  557. * this device unaligned.
  558. */
  559. .min_access_size = 4,
  560. .max_access_size = 4,
  561. .unaligned = false,
  562. },
  563. };
  564. static AddressSpace *designware_pcie_host_set_iommu(PCIBus *bus, void *opaque,
  565. int devfn)
  566. {
  567. DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(opaque);
  568. return &s->pci.address_space;
  569. }
  570. static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
  571. {
  572. PCIHostState *pci = PCI_HOST_BRIDGE(dev);
  573. DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(dev);
  574. SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
  575. size_t i;
  576. for (i = 0; i < ARRAY_SIZE(s->pci.irqs); i++) {
  577. sysbus_init_irq(sbd, &s->pci.irqs[i]);
  578. }
  579. memory_region_init_io(&s->mmio,
  580. OBJECT(s),
  581. &designware_pci_mmio_ops,
  582. s,
  583. "pcie.reg", 4 * 1024);
  584. sysbus_init_mmio(sbd, &s->mmio);
  585. memory_region_init(&s->pci.io, OBJECT(s), "pcie-pio", 16);
  586. memory_region_init(&s->pci.memory, OBJECT(s),
  587. "pcie-bus-memory",
  588. UINT64_MAX);
  589. pci->bus = pci_register_root_bus(dev, "pcie",
  590. designware_pcie_set_irq,
  591. pci_swizzle_map_irq_fn,
  592. s,
  593. &s->pci.memory,
  594. &s->pci.io,
  595. 0, 4,
  596. TYPE_PCIE_BUS);
  597. memory_region_init(&s->pci.address_space_root,
  598. OBJECT(s),
  599. "pcie-bus-address-space-root",
  600. UINT64_MAX);
  601. memory_region_add_subregion(&s->pci.address_space_root,
  602. 0x0, &s->pci.memory);
  603. address_space_init(&s->pci.address_space,
  604. &s->pci.address_space_root,
  605. "pcie-bus-address-space");
  606. pci_setup_iommu(pci->bus, designware_pcie_host_set_iommu, s);
  607. qdev_realize(DEVICE(&s->root), BUS(pci->bus), &error_fatal);
  608. }
  609. static const VMStateDescription vmstate_designware_pcie_host = {
  610. .name = "designware-pcie-host",
  611. .version_id = 1,
  612. .minimum_version_id = 1,
  613. .fields = (VMStateField[]) {
  614. VMSTATE_STRUCT(root,
  615. DesignwarePCIEHost,
  616. 1,
  617. vmstate_designware_pcie_root,
  618. DesignwarePCIERoot),
  619. VMSTATE_END_OF_LIST()
  620. }
  621. };
  622. static void designware_pcie_host_class_init(ObjectClass *klass, void *data)
  623. {
  624. DeviceClass *dc = DEVICE_CLASS(klass);
  625. PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
  626. hc->root_bus_path = designware_pcie_host_root_bus_path;
  627. dc->realize = designware_pcie_host_realize;
  628. set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
  629. dc->fw_name = "pci";
  630. dc->vmsd = &vmstate_designware_pcie_host;
  631. }
  632. static void designware_pcie_host_init(Object *obj)
  633. {
  634. DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(obj);
  635. DesignwarePCIERoot *root = &s->root;
  636. object_initialize_child(obj, "root", root, TYPE_DESIGNWARE_PCIE_ROOT);
  637. qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0));
  638. qdev_prop_set_bit(DEVICE(root), "multifunction", false);
  639. }
  640. static const TypeInfo designware_pcie_root_info = {
  641. .name = TYPE_DESIGNWARE_PCIE_ROOT,
  642. .parent = TYPE_PCI_BRIDGE,
  643. .instance_size = sizeof(DesignwarePCIERoot),
  644. .class_init = designware_pcie_root_class_init,
  645. .interfaces = (InterfaceInfo[]) {
  646. { INTERFACE_PCIE_DEVICE },
  647. { }
  648. },
  649. };
  650. static const TypeInfo designware_pcie_host_info = {
  651. .name = TYPE_DESIGNWARE_PCIE_HOST,
  652. .parent = TYPE_PCI_HOST_BRIDGE,
  653. .instance_size = sizeof(DesignwarePCIEHost),
  654. .instance_init = designware_pcie_host_init,
  655. .class_init = designware_pcie_host_class_init,
  656. };
  657. static void designware_pcie_register(void)
  658. {
  659. type_register_static(&designware_pcie_root_info);
  660. type_register_static(&designware_pcie_host_info);
  661. }
  662. type_init(designware_pcie_register)