2
0

designware.c 26 KB

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