ppc440_pcix.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. /*
  2. * Emulation of the ibm,plb-pcix PCI controller
  3. * This is found in some 440 SoCs e.g. the 460EX.
  4. *
  5. * Copyright (c) 2016-2018 BALATON Zoltan
  6. *
  7. * Derived from ppc4xx_pci.c and pci-host/ppce500.c
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License, version 2, as
  11. * published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #include "qemu/osdep.h"
  22. #include "qemu/error-report.h"
  23. #include "qemu/log.h"
  24. #include "qemu/module.h"
  25. #include "qemu/units.h"
  26. #include "hw/irq.h"
  27. #include "hw/pci-host/ppc4xx.h"
  28. #include "hw/pci/pci_device.h"
  29. #include "hw/pci/pci_host.h"
  30. #include "trace.h"
  31. #include "qom/object.h"
  32. struct PLBOutMap {
  33. uint64_t la;
  34. uint64_t pcia;
  35. uint32_t sa;
  36. MemoryRegion mr;
  37. };
  38. struct PLBInMap {
  39. uint64_t sa;
  40. uint64_t la;
  41. MemoryRegion mr;
  42. };
  43. OBJECT_DECLARE_SIMPLE_TYPE(PPC440PCIXState, PPC440_PCIX_HOST)
  44. #define PPC440_PCIX_NR_POMS 3
  45. #define PPC440_PCIX_NR_PIMS 3
  46. struct PPC440PCIXState {
  47. PCIHostState parent_obj;
  48. uint8_t config[PCI_CONFIG_SPACE_SIZE];
  49. struct PLBOutMap pom[PPC440_PCIX_NR_POMS];
  50. struct PLBInMap pim[PPC440_PCIX_NR_PIMS];
  51. uint32_t sts;
  52. qemu_irq irq;
  53. AddressSpace bm_as;
  54. MemoryRegion bm;
  55. MemoryRegion container;
  56. MemoryRegion iomem;
  57. MemoryRegion busmem;
  58. MemoryRegion regs;
  59. };
  60. #define PPC440_REG_BASE 0x80000
  61. #define PPC440_REG_SIZE 0xff
  62. #define PCIC0_CFGADDR 0x0
  63. #define PCIC0_CFGDATA 0x4
  64. #define PCIX0_POM0LAL 0x68
  65. #define PCIX0_POM0LAH 0x6c
  66. #define PCIX0_POM0SA 0x70
  67. #define PCIX0_POM0PCIAL 0x74
  68. #define PCIX0_POM0PCIAH 0x78
  69. #define PCIX0_POM1LAL 0x7c
  70. #define PCIX0_POM1LAH 0x80
  71. #define PCIX0_POM1SA 0x84
  72. #define PCIX0_POM1PCIAL 0x88
  73. #define PCIX0_POM1PCIAH 0x8c
  74. #define PCIX0_POM2SA 0x90
  75. #define PCIX0_PIM0SAL 0x98
  76. #define PCIX0_PIM0LAL 0x9c
  77. #define PCIX0_PIM0LAH 0xa0
  78. #define PCIX0_PIM1SA 0xa4
  79. #define PCIX0_PIM1LAL 0xa8
  80. #define PCIX0_PIM1LAH 0xac
  81. #define PCIX0_PIM2SAL 0xb0
  82. #define PCIX0_PIM2LAL 0xb4
  83. #define PCIX0_PIM2LAH 0xb8
  84. #define PCIX0_PIM0SAH 0xf8
  85. #define PCIX0_PIM2SAH 0xfc
  86. #define PCIX0_STS 0xe0
  87. #define PCI_ALL_SIZE (PPC440_REG_BASE + PPC440_REG_SIZE)
  88. static void ppc440_pcix_clear_region(MemoryRegion *parent,
  89. MemoryRegion *mem)
  90. {
  91. if (memory_region_is_mapped(mem)) {
  92. memory_region_del_subregion(parent, mem);
  93. object_unparent(OBJECT(mem));
  94. }
  95. }
  96. /* DMA mapping */
  97. static void ppc440_pcix_update_pim(PPC440PCIXState *s, int idx)
  98. {
  99. MemoryRegion *mem = &s->pim[idx].mr;
  100. char *name;
  101. uint64_t size;
  102. /* Before we modify anything, unmap and destroy the region */
  103. ppc440_pcix_clear_region(&s->bm, mem);
  104. if (!(s->pim[idx].sa & 1)) {
  105. /* Not enabled, nothing to do */
  106. return;
  107. }
  108. name = g_strdup_printf("PCI Inbound Window %d", idx);
  109. size = ~(s->pim[idx].sa & ~7ULL) + 1;
  110. memory_region_init_alias(mem, OBJECT(s), name, get_system_memory(),
  111. s->pim[idx].la, size);
  112. memory_region_add_subregion_overlap(&s->bm, 0, mem, -1);
  113. g_free(name);
  114. trace_ppc440_pcix_update_pim(idx, size, s->pim[idx].la);
  115. }
  116. /* BAR mapping */
  117. static void ppc440_pcix_update_pom(PPC440PCIXState *s, int idx)
  118. {
  119. MemoryRegion *mem = &s->pom[idx].mr;
  120. MemoryRegion *address_space_mem = get_system_memory();
  121. char *name;
  122. uint32_t size;
  123. /* Before we modify anything, unmap and destroy the region */
  124. ppc440_pcix_clear_region(address_space_mem, mem);
  125. if (!(s->pom[idx].sa & 1)) {
  126. /* Not enabled, nothing to do */
  127. return;
  128. }
  129. name = g_strdup_printf("PCI Outbound Window %d", idx);
  130. size = ~(s->pom[idx].sa & 0xfffffffe) + 1;
  131. if (!size) {
  132. size = 0xffffffff;
  133. }
  134. memory_region_init_alias(mem, OBJECT(s), name, &s->busmem,
  135. s->pom[idx].pcia, size);
  136. memory_region_add_subregion(address_space_mem, s->pom[idx].la, mem);
  137. g_free(name);
  138. trace_ppc440_pcix_update_pom(idx, size, s->pom[idx].la, s->pom[idx].pcia);
  139. }
  140. static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr,
  141. uint64_t val, unsigned size)
  142. {
  143. struct PPC440PCIXState *s = opaque;
  144. trace_ppc440_pcix_reg_write(addr, val, size);
  145. switch (addr) {
  146. case PCI_VENDOR_ID ... PCI_MAX_LAT:
  147. stl_le_p(s->config + addr, val);
  148. break;
  149. case PCIX0_POM0LAL:
  150. s->pom[0].la &= 0xffffffff00000000ULL;
  151. s->pom[0].la |= val;
  152. ppc440_pcix_update_pom(s, 0);
  153. break;
  154. case PCIX0_POM0LAH:
  155. s->pom[0].la &= 0xffffffffULL;
  156. s->pom[0].la |= val << 32;
  157. ppc440_pcix_update_pom(s, 0);
  158. break;
  159. case PCIX0_POM0SA:
  160. s->pom[0].sa = val;
  161. ppc440_pcix_update_pom(s, 0);
  162. break;
  163. case PCIX0_POM0PCIAL:
  164. s->pom[0].pcia &= 0xffffffff00000000ULL;
  165. s->pom[0].pcia |= val;
  166. ppc440_pcix_update_pom(s, 0);
  167. break;
  168. case PCIX0_POM0PCIAH:
  169. s->pom[0].pcia &= 0xffffffffULL;
  170. s->pom[0].pcia |= val << 32;
  171. ppc440_pcix_update_pom(s, 0);
  172. break;
  173. case PCIX0_POM1LAL:
  174. s->pom[1].la &= 0xffffffff00000000ULL;
  175. s->pom[1].la |= val;
  176. ppc440_pcix_update_pom(s, 1);
  177. break;
  178. case PCIX0_POM1LAH:
  179. s->pom[1].la &= 0xffffffffULL;
  180. s->pom[1].la |= val << 32;
  181. ppc440_pcix_update_pom(s, 1);
  182. break;
  183. case PCIX0_POM1SA:
  184. s->pom[1].sa = val;
  185. ppc440_pcix_update_pom(s, 1);
  186. break;
  187. case PCIX0_POM1PCIAL:
  188. s->pom[1].pcia &= 0xffffffff00000000ULL;
  189. s->pom[1].pcia |= val;
  190. ppc440_pcix_update_pom(s, 1);
  191. break;
  192. case PCIX0_POM1PCIAH:
  193. s->pom[1].pcia &= 0xffffffffULL;
  194. s->pom[1].pcia |= val << 32;
  195. ppc440_pcix_update_pom(s, 1);
  196. break;
  197. case PCIX0_POM2SA:
  198. s->pom[2].sa = val;
  199. break;
  200. case PCIX0_PIM0SAL:
  201. s->pim[0].sa &= 0xffffffff00000000ULL;
  202. s->pim[0].sa |= val;
  203. ppc440_pcix_update_pim(s, 0);
  204. break;
  205. case PCIX0_PIM0LAL:
  206. s->pim[0].la &= 0xffffffff00000000ULL;
  207. s->pim[0].la |= val;
  208. ppc440_pcix_update_pim(s, 0);
  209. break;
  210. case PCIX0_PIM0LAH:
  211. s->pim[0].la &= 0xffffffffULL;
  212. s->pim[0].la |= val << 32;
  213. ppc440_pcix_update_pim(s, 0);
  214. break;
  215. case PCIX0_PIM1SA:
  216. s->pim[1].sa = val;
  217. ppc440_pcix_update_pim(s, 1);
  218. break;
  219. case PCIX0_PIM1LAL:
  220. s->pim[1].la &= 0xffffffff00000000ULL;
  221. s->pim[1].la |= val;
  222. ppc440_pcix_update_pim(s, 1);
  223. break;
  224. case PCIX0_PIM1LAH:
  225. s->pim[1].la &= 0xffffffffULL;
  226. s->pim[1].la |= val << 32;
  227. ppc440_pcix_update_pim(s, 1);
  228. break;
  229. case PCIX0_PIM2SAL:
  230. s->pim[2].sa &= 0xffffffff00000000ULL;
  231. s->pim[2].sa |= val;
  232. ppc440_pcix_update_pim(s, 2);
  233. break;
  234. case PCIX0_PIM2LAL:
  235. s->pim[2].la &= 0xffffffff00000000ULL;
  236. s->pim[2].la |= val;
  237. ppc440_pcix_update_pim(s, 2);
  238. break;
  239. case PCIX0_PIM2LAH:
  240. s->pim[2].la &= 0xffffffffULL;
  241. s->pim[2].la |= val << 32;
  242. ppc440_pcix_update_pim(s, 2);
  243. break;
  244. case PCIX0_STS:
  245. s->sts = val;
  246. break;
  247. case PCIX0_PIM0SAH:
  248. s->pim[0].sa &= 0xffffffffULL;
  249. s->pim[0].sa |= val << 32;
  250. ppc440_pcix_update_pim(s, 0);
  251. break;
  252. case PCIX0_PIM2SAH:
  253. s->pim[2].sa &= 0xffffffffULL;
  254. s->pim[2].sa |= val << 32;
  255. ppc440_pcix_update_pim(s, 2);
  256. break;
  257. default:
  258. qemu_log_mask(LOG_UNIMP,
  259. "%s: unhandled PCI internal register 0x%"HWADDR_PRIx"\n",
  260. __func__, addr);
  261. break;
  262. }
  263. }
  264. static uint64_t ppc440_pcix_reg_read4(void *opaque, hwaddr addr,
  265. unsigned size)
  266. {
  267. struct PPC440PCIXState *s = opaque;
  268. uint32_t val;
  269. switch (addr) {
  270. case PCI_VENDOR_ID ... PCI_MAX_LAT:
  271. val = ldl_le_p(s->config + addr);
  272. break;
  273. case PCIX0_POM0LAL:
  274. val = s->pom[0].la;
  275. break;
  276. case PCIX0_POM0LAH:
  277. val = s->pom[0].la >> 32;
  278. break;
  279. case PCIX0_POM0SA:
  280. val = s->pom[0].sa;
  281. break;
  282. case PCIX0_POM0PCIAL:
  283. val = s->pom[0].pcia;
  284. break;
  285. case PCIX0_POM0PCIAH:
  286. val = s->pom[0].pcia >> 32;
  287. break;
  288. case PCIX0_POM1LAL:
  289. val = s->pom[1].la;
  290. break;
  291. case PCIX0_POM1LAH:
  292. val = s->pom[1].la >> 32;
  293. break;
  294. case PCIX0_POM1SA:
  295. val = s->pom[1].sa;
  296. break;
  297. case PCIX0_POM1PCIAL:
  298. val = s->pom[1].pcia;
  299. break;
  300. case PCIX0_POM1PCIAH:
  301. val = s->pom[1].pcia >> 32;
  302. break;
  303. case PCIX0_POM2SA:
  304. val = s->pom[2].sa;
  305. break;
  306. case PCIX0_PIM0SAL:
  307. val = s->pim[0].sa;
  308. break;
  309. case PCIX0_PIM0LAL:
  310. val = s->pim[0].la;
  311. break;
  312. case PCIX0_PIM0LAH:
  313. val = s->pim[0].la >> 32;
  314. break;
  315. case PCIX0_PIM1SA:
  316. val = s->pim[1].sa;
  317. break;
  318. case PCIX0_PIM1LAL:
  319. val = s->pim[1].la;
  320. break;
  321. case PCIX0_PIM1LAH:
  322. val = s->pim[1].la >> 32;
  323. break;
  324. case PCIX0_PIM2SAL:
  325. val = s->pim[2].sa;
  326. break;
  327. case PCIX0_PIM2LAL:
  328. val = s->pim[2].la;
  329. break;
  330. case PCIX0_PIM2LAH:
  331. val = s->pim[2].la >> 32;
  332. break;
  333. case PCIX0_STS:
  334. val = s->sts;
  335. break;
  336. case PCIX0_PIM0SAH:
  337. val = s->pim[0].sa >> 32;
  338. break;
  339. case PCIX0_PIM2SAH:
  340. val = s->pim[2].sa >> 32;
  341. break;
  342. default:
  343. qemu_log_mask(LOG_UNIMP,
  344. "%s: invalid PCI internal register 0x%" HWADDR_PRIx "\n",
  345. __func__, addr);
  346. val = 0;
  347. }
  348. trace_ppc440_pcix_reg_read(addr, val);
  349. return val;
  350. }
  351. static const MemoryRegionOps pci_reg_ops = {
  352. .read = ppc440_pcix_reg_read4,
  353. .write = ppc440_pcix_reg_write4,
  354. .endianness = DEVICE_LITTLE_ENDIAN,
  355. };
  356. static void ppc440_pcix_reset(DeviceState *dev)
  357. {
  358. struct PPC440PCIXState *s = PPC440_PCIX_HOST(dev);
  359. int i;
  360. for (i = 0; i < PPC440_PCIX_NR_POMS; i++) {
  361. ppc440_pcix_clear_region(get_system_memory(), &s->pom[i].mr);
  362. }
  363. for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) {
  364. ppc440_pcix_clear_region(&s->bm, &s->pim[i].mr);
  365. }
  366. memset(s->pom, 0, sizeof(s->pom));
  367. memset(s->pim, 0, sizeof(s->pim));
  368. for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) {
  369. s->pim[i].sa = 0xffffffff00000000ULL;
  370. }
  371. s->sts = 0;
  372. }
  373. /*
  374. * All four IRQ[ABCD] pins from all slots are tied to a single board
  375. * IRQ, so our mapping function here maps everything to IRQ 0.
  376. * The code in pci_change_irq_level() tracks the number of times
  377. * the mapped IRQ is asserted and deasserted, so if multiple devices
  378. * assert an IRQ at the same time the behaviour is correct.
  379. *
  380. * This may need further refactoring for boards that use multiple IRQ lines.
  381. */
  382. static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num)
  383. {
  384. trace_ppc440_pcix_map_irq(pci_dev->devfn, irq_num, 0);
  385. return 0;
  386. }
  387. static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level)
  388. {
  389. qemu_irq *pci_irq = opaque;
  390. trace_ppc440_pcix_set_irq(irq_num);
  391. if (irq_num < 0) {
  392. error_report("%s: PCI irq %d", __func__, irq_num);
  393. return;
  394. }
  395. qemu_set_irq(*pci_irq, level);
  396. }
  397. static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int devfn)
  398. {
  399. PPC440PCIXState *s = opaque;
  400. return &s->bm_as;
  401. }
  402. static const PCIIOMMUOps ppc440_iommu_ops = {
  403. .get_address_space = ppc440_pcix_set_iommu,
  404. };
  405. /*
  406. * Some guests on sam460ex write all kinds of garbage here such as
  407. * missing enable bit and low bits set and still expect this to work
  408. * (apparently it does on real hardware because these boot there) so
  409. * we have to override these ops here and fix it up
  410. */
  411. static void pci_host_config_write(void *opaque, hwaddr addr,
  412. uint64_t val, unsigned len)
  413. {
  414. PCIHostState *s = opaque;
  415. if (addr != 0 || len != 4) {
  416. return;
  417. }
  418. s->config_reg = (val & 0xfffffffcULL) | (1UL << 31);
  419. }
  420. static uint64_t pci_host_config_read(void *opaque, hwaddr addr,
  421. unsigned len)
  422. {
  423. PCIHostState *s = opaque;
  424. uint32_t val = s->config_reg;
  425. return val;
  426. }
  427. const MemoryRegionOps ppc440_pcix_host_conf_ops = {
  428. .read = pci_host_config_read,
  429. .write = pci_host_config_write,
  430. .endianness = DEVICE_LITTLE_ENDIAN,
  431. };
  432. static void ppc440_pcix_realize(DeviceState *dev, Error **errp)
  433. {
  434. SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
  435. PPC440PCIXState *s;
  436. PCIHostState *h;
  437. h = PCI_HOST_BRIDGE(dev);
  438. s = PPC440_PCIX_HOST(dev);
  439. sysbus_init_irq(sbd, &s->irq);
  440. memory_region_init(&s->busmem, OBJECT(dev), "pci-mem", UINT64_MAX);
  441. memory_region_init(&s->iomem, OBJECT(dev), "pci-io", 64 * KiB);
  442. h->bus = pci_register_root_bus(dev, NULL, ppc440_pcix_set_irq,
  443. ppc440_pcix_map_irq, &s->irq, &s->busmem, &s->iomem,
  444. PCI_DEVFN(1, 0), 1, TYPE_PCI_BUS);
  445. memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX);
  446. memory_region_add_subregion(&s->bm, 0x0, &s->busmem);
  447. address_space_init(&s->bm_as, &s->bm, "pci-bm");
  448. pci_setup_iommu(h->bus, &ppc440_iommu_ops, s);
  449. memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE);
  450. memory_region_init_io(&h->conf_mem, OBJECT(s), &ppc440_pcix_host_conf_ops,
  451. h, "pci-conf-idx", 4);
  452. memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops,
  453. h, "pci-conf-data", 4);
  454. memory_region_init_io(&s->regs, OBJECT(s), &pci_reg_ops, s, "pci-reg",
  455. PPC440_REG_SIZE);
  456. memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
  457. memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
  458. memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->regs);
  459. sysbus_init_mmio(sbd, &s->container);
  460. sysbus_init_mmio(sbd, &s->iomem);
  461. }
  462. static void ppc440_pcix_class_init(ObjectClass *klass, void *data)
  463. {
  464. DeviceClass *dc = DEVICE_CLASS(klass);
  465. dc->realize = ppc440_pcix_realize;
  466. device_class_set_legacy_reset(dc, ppc440_pcix_reset);
  467. }
  468. static const TypeInfo ppc440_pcix_info = {
  469. .name = TYPE_PPC440_PCIX_HOST,
  470. .parent = TYPE_PCI_HOST_BRIDGE,
  471. .instance_size = sizeof(PPC440PCIXState),
  472. .class_init = ppc440_pcix_class_init,
  473. };
  474. static void ppc440_pcix_register_types(void)
  475. {
  476. type_register_static(&ppc440_pcix_info);
  477. }
  478. type_init(ppc440_pcix_register_types)