2
0

designware.c 26 KB

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