pcie-xilinx-cpm.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * PCIe host controller driver for Xilinx Versal CPM DMA Bridge
  4. *
  5. * (C) Copyright 2019 - 2020, Xilinx, Inc.
  6. */
  7. #include <linux/bitfield.h>
  8. #include <linux/interrupt.h>
  9. #include <linux/irq.h>
  10. #include <linux/irqchip.h>
  11. #include <linux/irqchip/chained_irq.h>
  12. #include <linux/irqdomain.h>
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/of_address.h>
  16. #include <linux/of_pci.h>
  17. #include <linux/of_platform.h>
  18. #include "../pci.h"
  19. #include "pcie-xilinx-common.h"
  20. /* Register definitions */
  21. #define XILINX_CPM_PCIE_REG_IDR 0x00000E10
  22. #define XILINX_CPM_PCIE_REG_IMR 0x00000E14
  23. #define XILINX_CPM_PCIE_REG_PSCR 0x00000E1C
  24. #define XILINX_CPM_PCIE_REG_RPSC 0x00000E20
  25. #define XILINX_CPM_PCIE_REG_RPEFR 0x00000E2C
  26. #define XILINX_CPM_PCIE_REG_IDRN 0x00000E38
  27. #define XILINX_CPM_PCIE_REG_IDRN_MASK 0x00000E3C
  28. #define XILINX_CPM_PCIE_MISC_IR_STATUS 0x00000340
  29. #define XILINX_CPM_PCIE_MISC_IR_ENABLE 0x00000348
  30. #define XILINX_CPM_PCIE0_MISC_IR_LOCAL BIT(1)
  31. #define XILINX_CPM_PCIE1_MISC_IR_LOCAL BIT(2)
  32. #define XILINX_CPM_PCIE0_IR_STATUS 0x000002A0
  33. #define XILINX_CPM_PCIE1_IR_STATUS 0x000002B4
  34. #define XILINX_CPM_PCIE0_IR_ENABLE 0x000002A8
  35. #define XILINX_CPM_PCIE1_IR_ENABLE 0x000002BC
  36. #define XILINX_CPM_PCIE_IR_LOCAL BIT(0)
  37. #define IMR(x) BIT(XILINX_PCIE_INTR_ ##x)
  38. #define XILINX_CPM_PCIE_IMR_ALL_MASK \
  39. ( \
  40. IMR(LINK_DOWN) | \
  41. IMR(HOT_RESET) | \
  42. IMR(CFG_PCIE_TIMEOUT) | \
  43. IMR(CFG_TIMEOUT) | \
  44. IMR(CORRECTABLE) | \
  45. IMR(NONFATAL) | \
  46. IMR(FATAL) | \
  47. IMR(CFG_ERR_POISON) | \
  48. IMR(PME_TO_ACK_RCVD) | \
  49. IMR(INTX) | \
  50. IMR(PM_PME_RCVD) | \
  51. IMR(SLV_UNSUPP) | \
  52. IMR(SLV_UNEXP) | \
  53. IMR(SLV_COMPL) | \
  54. IMR(SLV_ERRP) | \
  55. IMR(SLV_CMPABT) | \
  56. IMR(SLV_ILLBUR) | \
  57. IMR(MST_DECERR) | \
  58. IMR(MST_SLVERR) | \
  59. IMR(SLV_PCIE_TIMEOUT) \
  60. )
  61. #define XILINX_CPM_PCIE_IDR_ALL_MASK 0xFFFFFFFF
  62. #define XILINX_CPM_PCIE_IDRN_MASK GENMASK(19, 16)
  63. #define XILINX_CPM_PCIE_IDRN_SHIFT 16
  64. /* Root Port Error FIFO Read Register definitions */
  65. #define XILINX_CPM_PCIE_RPEFR_ERR_VALID BIT(18)
  66. #define XILINX_CPM_PCIE_RPEFR_REQ_ID GENMASK(15, 0)
  67. #define XILINX_CPM_PCIE_RPEFR_ALL_MASK 0xFFFFFFFF
  68. /* Root Port Status/control Register definitions */
  69. #define XILINX_CPM_PCIE_REG_RPSC_BEN BIT(0)
  70. /* Phy Status/Control Register definitions */
  71. #define XILINX_CPM_PCIE_REG_PSCR_LNKUP BIT(11)
  72. enum xilinx_cpm_version {
  73. CPM,
  74. CPM5,
  75. CPM5_HOST1,
  76. CPM5NC_HOST,
  77. };
  78. /**
  79. * struct xilinx_cpm_variant - CPM variant information
  80. * @version: CPM version
  81. * @ir_status: Offset for the error interrupt status register
  82. * @ir_enable: Offset for the CPM5 local error interrupt enable register
  83. * @ir_misc_value: A bitmask for the miscellaneous interrupt status
  84. */
  85. struct xilinx_cpm_variant {
  86. enum xilinx_cpm_version version;
  87. u32 ir_status;
  88. u32 ir_enable;
  89. u32 ir_misc_value;
  90. };
  91. /**
  92. * struct xilinx_cpm_pcie - PCIe port information
  93. * @dev: Device pointer
  94. * @reg_base: Bridge Register Base
  95. * @cpm_base: CPM System Level Control and Status Register(SLCR) Base
  96. * @intx_domain: Legacy IRQ domain pointer
  97. * @cpm_domain: CPM IRQ domain pointer
  98. * @cfg: Holds mappings of config space window
  99. * @intx_irq: legacy interrupt number
  100. * @irq: Error interrupt number
  101. * @lock: lock protecting shared register access
  102. * @variant: CPM version check pointer
  103. */
  104. struct xilinx_cpm_pcie {
  105. struct device *dev;
  106. void __iomem *reg_base;
  107. void __iomem *cpm_base;
  108. struct irq_domain *intx_domain;
  109. struct irq_domain *cpm_domain;
  110. struct pci_config_window *cfg;
  111. int intx_irq;
  112. int irq;
  113. raw_spinlock_t lock;
  114. const struct xilinx_cpm_variant *variant;
  115. };
  116. static u32 pcie_read(struct xilinx_cpm_pcie *port, u32 reg)
  117. {
  118. return readl_relaxed(port->reg_base + reg);
  119. }
  120. static void pcie_write(struct xilinx_cpm_pcie *port,
  121. u32 val, u32 reg)
  122. {
  123. writel_relaxed(val, port->reg_base + reg);
  124. }
  125. static bool cpm_pcie_link_up(struct xilinx_cpm_pcie *port)
  126. {
  127. return (pcie_read(port, XILINX_CPM_PCIE_REG_PSCR) &
  128. XILINX_CPM_PCIE_REG_PSCR_LNKUP);
  129. }
  130. static void cpm_pcie_clear_err_interrupts(struct xilinx_cpm_pcie *port)
  131. {
  132. unsigned long val = pcie_read(port, XILINX_CPM_PCIE_REG_RPEFR);
  133. if (val & XILINX_CPM_PCIE_RPEFR_ERR_VALID) {
  134. dev_dbg(port->dev, "Requester ID %lu\n",
  135. val & XILINX_CPM_PCIE_RPEFR_REQ_ID);
  136. pcie_write(port, XILINX_CPM_PCIE_RPEFR_ALL_MASK,
  137. XILINX_CPM_PCIE_REG_RPEFR);
  138. }
  139. }
  140. static void xilinx_cpm_mask_leg_irq(struct irq_data *data)
  141. {
  142. struct xilinx_cpm_pcie *port = irq_data_get_irq_chip_data(data);
  143. unsigned long flags;
  144. u32 mask;
  145. u32 val;
  146. mask = BIT(data->hwirq + XILINX_CPM_PCIE_IDRN_SHIFT);
  147. raw_spin_lock_irqsave(&port->lock, flags);
  148. val = pcie_read(port, XILINX_CPM_PCIE_REG_IDRN_MASK);
  149. pcie_write(port, (val & (~mask)), XILINX_CPM_PCIE_REG_IDRN_MASK);
  150. raw_spin_unlock_irqrestore(&port->lock, flags);
  151. }
  152. static void xilinx_cpm_unmask_leg_irq(struct irq_data *data)
  153. {
  154. struct xilinx_cpm_pcie *port = irq_data_get_irq_chip_data(data);
  155. unsigned long flags;
  156. u32 mask;
  157. u32 val;
  158. mask = BIT(data->hwirq + XILINX_CPM_PCIE_IDRN_SHIFT);
  159. raw_spin_lock_irqsave(&port->lock, flags);
  160. val = pcie_read(port, XILINX_CPM_PCIE_REG_IDRN_MASK);
  161. pcie_write(port, (val | mask), XILINX_CPM_PCIE_REG_IDRN_MASK);
  162. raw_spin_unlock_irqrestore(&port->lock, flags);
  163. }
  164. static struct irq_chip xilinx_cpm_leg_irq_chip = {
  165. .name = "INTx",
  166. .irq_mask = xilinx_cpm_mask_leg_irq,
  167. .irq_unmask = xilinx_cpm_unmask_leg_irq,
  168. };
  169. /**
  170. * xilinx_cpm_pcie_intx_map - Set the handler for the INTx and mark IRQ as valid
  171. * @domain: IRQ domain
  172. * @irq: Virtual IRQ number
  173. * @hwirq: HW interrupt number
  174. *
  175. * Return: Always returns 0.
  176. */
  177. static int xilinx_cpm_pcie_intx_map(struct irq_domain *domain,
  178. unsigned int irq, irq_hw_number_t hwirq)
  179. {
  180. irq_set_chip_and_handler(irq, &xilinx_cpm_leg_irq_chip,
  181. handle_level_irq);
  182. irq_set_chip_data(irq, domain->host_data);
  183. irq_set_status_flags(irq, IRQ_LEVEL);
  184. return 0;
  185. }
  186. /* INTx IRQ Domain operations */
  187. static const struct irq_domain_ops intx_domain_ops = {
  188. .map = xilinx_cpm_pcie_intx_map,
  189. };
  190. static void xilinx_cpm_pcie_intx_flow(struct irq_desc *desc)
  191. {
  192. struct xilinx_cpm_pcie *port = irq_desc_get_handler_data(desc);
  193. struct irq_chip *chip = irq_desc_get_chip(desc);
  194. unsigned long val;
  195. int i;
  196. chained_irq_enter(chip, desc);
  197. val = FIELD_GET(XILINX_CPM_PCIE_IDRN_MASK,
  198. pcie_read(port, XILINX_CPM_PCIE_REG_IDRN));
  199. for_each_set_bit(i, &val, PCI_NUM_INTX)
  200. generic_handle_domain_irq(port->intx_domain, i);
  201. chained_irq_exit(chip, desc);
  202. }
  203. static void xilinx_cpm_mask_event_irq(struct irq_data *d)
  204. {
  205. struct xilinx_cpm_pcie *port = irq_data_get_irq_chip_data(d);
  206. u32 val;
  207. raw_spin_lock(&port->lock);
  208. val = pcie_read(port, XILINX_CPM_PCIE_REG_IMR);
  209. val &= ~BIT(d->hwirq);
  210. pcie_write(port, val, XILINX_CPM_PCIE_REG_IMR);
  211. raw_spin_unlock(&port->lock);
  212. }
  213. static void xilinx_cpm_unmask_event_irq(struct irq_data *d)
  214. {
  215. struct xilinx_cpm_pcie *port = irq_data_get_irq_chip_data(d);
  216. u32 val;
  217. raw_spin_lock(&port->lock);
  218. val = pcie_read(port, XILINX_CPM_PCIE_REG_IMR);
  219. val |= BIT(d->hwirq);
  220. pcie_write(port, val, XILINX_CPM_PCIE_REG_IMR);
  221. raw_spin_unlock(&port->lock);
  222. }
  223. static struct irq_chip xilinx_cpm_event_irq_chip = {
  224. .name = "RC-Event",
  225. .irq_mask = xilinx_cpm_mask_event_irq,
  226. .irq_unmask = xilinx_cpm_unmask_event_irq,
  227. };
  228. static int xilinx_cpm_pcie_event_map(struct irq_domain *domain,
  229. unsigned int irq, irq_hw_number_t hwirq)
  230. {
  231. irq_set_chip_and_handler(irq, &xilinx_cpm_event_irq_chip,
  232. handle_level_irq);
  233. irq_set_chip_data(irq, domain->host_data);
  234. irq_set_status_flags(irq, IRQ_LEVEL);
  235. return 0;
  236. }
  237. static const struct irq_domain_ops event_domain_ops = {
  238. .map = xilinx_cpm_pcie_event_map,
  239. };
  240. static void xilinx_cpm_pcie_event_flow(struct irq_desc *desc)
  241. {
  242. struct xilinx_cpm_pcie *port = irq_desc_get_handler_data(desc);
  243. struct irq_chip *chip = irq_desc_get_chip(desc);
  244. const struct xilinx_cpm_variant *variant = port->variant;
  245. unsigned long val;
  246. int i;
  247. chained_irq_enter(chip, desc);
  248. val = pcie_read(port, XILINX_CPM_PCIE_REG_IDR);
  249. val &= pcie_read(port, XILINX_CPM_PCIE_REG_IMR);
  250. for_each_set_bit(i, &val, 32)
  251. generic_handle_domain_irq(port->cpm_domain, i);
  252. pcie_write(port, val, XILINX_CPM_PCIE_REG_IDR);
  253. if (variant->ir_status) {
  254. val = readl_relaxed(port->cpm_base + variant->ir_status);
  255. if (val)
  256. writel_relaxed(val, port->cpm_base +
  257. variant->ir_status);
  258. }
  259. /*
  260. * XILINX_CPM_PCIE_MISC_IR_STATUS register is mapped to
  261. * CPM SLCR block.
  262. */
  263. val = readl_relaxed(port->cpm_base + XILINX_CPM_PCIE_MISC_IR_STATUS);
  264. if (val)
  265. writel_relaxed(val,
  266. port->cpm_base + XILINX_CPM_PCIE_MISC_IR_STATUS);
  267. chained_irq_exit(chip, desc);
  268. }
  269. #define _IC(x, s) \
  270. [XILINX_PCIE_INTR_ ## x] = { __stringify(x), s }
  271. static const struct {
  272. const char *sym;
  273. const char *str;
  274. } intr_cause[32] = {
  275. _IC(LINK_DOWN, "Link Down"),
  276. _IC(HOT_RESET, "Hot reset"),
  277. _IC(CFG_TIMEOUT, "ECAM access timeout"),
  278. _IC(CORRECTABLE, "Correctable error message"),
  279. _IC(NONFATAL, "Non fatal error message"),
  280. _IC(FATAL, "Fatal error message"),
  281. _IC(SLV_UNSUPP, "Slave unsupported request"),
  282. _IC(SLV_UNEXP, "Slave unexpected completion"),
  283. _IC(SLV_COMPL, "Slave completion timeout"),
  284. _IC(SLV_ERRP, "Slave Error Poison"),
  285. _IC(SLV_CMPABT, "Slave Completer Abort"),
  286. _IC(SLV_ILLBUR, "Slave Illegal Burst"),
  287. _IC(MST_DECERR, "Master decode error"),
  288. _IC(MST_SLVERR, "Master slave error"),
  289. _IC(CFG_PCIE_TIMEOUT, "PCIe ECAM access timeout"),
  290. _IC(CFG_ERR_POISON, "ECAM poisoned completion received"),
  291. _IC(PME_TO_ACK_RCVD, "PME_TO_ACK message received"),
  292. _IC(PM_PME_RCVD, "PM_PME message received"),
  293. _IC(SLV_PCIE_TIMEOUT, "PCIe completion timeout received"),
  294. };
  295. static irqreturn_t xilinx_cpm_pcie_intr_handler(int irq, void *dev_id)
  296. {
  297. struct xilinx_cpm_pcie *port = dev_id;
  298. struct device *dev = port->dev;
  299. struct irq_data *d;
  300. d = irq_domain_get_irq_data(port->cpm_domain, irq);
  301. switch (d->hwirq) {
  302. case XILINX_PCIE_INTR_CORRECTABLE:
  303. case XILINX_PCIE_INTR_NONFATAL:
  304. case XILINX_PCIE_INTR_FATAL:
  305. cpm_pcie_clear_err_interrupts(port);
  306. fallthrough;
  307. default:
  308. if (intr_cause[d->hwirq].str)
  309. dev_warn(dev, "%s\n", intr_cause[d->hwirq].str);
  310. else
  311. dev_warn(dev, "Unknown IRQ %ld\n", d->hwirq);
  312. }
  313. return IRQ_HANDLED;
  314. }
  315. static void xilinx_cpm_free_irq_domains(struct xilinx_cpm_pcie *port)
  316. {
  317. if (port->intx_domain) {
  318. irq_domain_remove(port->intx_domain);
  319. port->intx_domain = NULL;
  320. }
  321. if (port->cpm_domain) {
  322. irq_domain_remove(port->cpm_domain);
  323. port->cpm_domain = NULL;
  324. }
  325. }
  326. /**
  327. * xilinx_cpm_pcie_init_irq_domain - Initialize IRQ domain
  328. * @port: PCIe port information
  329. *
  330. * Return: '0' on success and error value on failure
  331. */
  332. static int xilinx_cpm_pcie_init_irq_domain(struct xilinx_cpm_pcie *port)
  333. {
  334. struct device *dev = port->dev;
  335. struct device_node *node = dev->of_node;
  336. struct device_node *pcie_intc_node;
  337. /* Setup INTx */
  338. pcie_intc_node = of_get_next_child(node, NULL);
  339. if (!pcie_intc_node) {
  340. dev_err(dev, "No PCIe Intc node found\n");
  341. return -EINVAL;
  342. }
  343. port->cpm_domain = irq_domain_create_linear(of_fwnode_handle(pcie_intc_node), 32,
  344. &event_domain_ops, port);
  345. if (!port->cpm_domain)
  346. goto out;
  347. irq_domain_update_bus_token(port->cpm_domain, DOMAIN_BUS_NEXUS);
  348. port->intx_domain = irq_domain_create_linear(of_fwnode_handle(pcie_intc_node), PCI_NUM_INTX,
  349. &intx_domain_ops, port);
  350. if (!port->intx_domain)
  351. goto out;
  352. irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED);
  353. of_node_put(pcie_intc_node);
  354. raw_spin_lock_init(&port->lock);
  355. return 0;
  356. out:
  357. xilinx_cpm_free_irq_domains(port);
  358. of_node_put(pcie_intc_node);
  359. dev_err(dev, "Failed to allocate IRQ domains\n");
  360. return -ENOMEM;
  361. }
  362. static int xilinx_cpm_setup_irq(struct xilinx_cpm_pcie *port)
  363. {
  364. struct device *dev = port->dev;
  365. struct platform_device *pdev = to_platform_device(dev);
  366. int i, irq;
  367. port->irq = platform_get_irq(pdev, 0);
  368. if (port->irq < 0)
  369. return port->irq;
  370. for (i = 0; i < ARRAY_SIZE(intr_cause); i++) {
  371. int err;
  372. if (!intr_cause[i].str)
  373. continue;
  374. irq = irq_create_mapping(port->cpm_domain, i);
  375. if (!irq) {
  376. dev_err(dev, "Failed to map interrupt\n");
  377. return -ENXIO;
  378. }
  379. err = devm_request_irq(dev, irq, xilinx_cpm_pcie_intr_handler,
  380. 0, intr_cause[i].sym, port);
  381. if (err) {
  382. dev_err(dev, "Failed to request IRQ %d\n", irq);
  383. return err;
  384. }
  385. }
  386. port->intx_irq = irq_create_mapping(port->cpm_domain,
  387. XILINX_PCIE_INTR_INTX);
  388. if (!port->intx_irq) {
  389. dev_err(dev, "Failed to map INTx interrupt\n");
  390. return -ENXIO;
  391. }
  392. /* Plug the INTx chained handler */
  393. irq_set_chained_handler_and_data(port->intx_irq,
  394. xilinx_cpm_pcie_intx_flow, port);
  395. /* Plug the main event chained handler */
  396. irq_set_chained_handler_and_data(port->irq,
  397. xilinx_cpm_pcie_event_flow, port);
  398. return 0;
  399. }
  400. /**
  401. * xilinx_cpm_pcie_init_port - Initialize hardware
  402. * @port: PCIe port information
  403. */
  404. static void xilinx_cpm_pcie_init_port(struct xilinx_cpm_pcie *port)
  405. {
  406. const struct xilinx_cpm_variant *variant = port->variant;
  407. if (variant->version == CPM5NC_HOST)
  408. return;
  409. if (cpm_pcie_link_up(port))
  410. dev_info(port->dev, "PCIe Link is UP\n");
  411. else
  412. dev_info(port->dev, "PCIe Link is DOWN\n");
  413. /* Disable all interrupts */
  414. pcie_write(port, ~XILINX_CPM_PCIE_IDR_ALL_MASK,
  415. XILINX_CPM_PCIE_REG_IMR);
  416. /* Clear pending interrupts */
  417. pcie_write(port, pcie_read(port, XILINX_CPM_PCIE_REG_IDR) &
  418. XILINX_CPM_PCIE_IMR_ALL_MASK,
  419. XILINX_CPM_PCIE_REG_IDR);
  420. /*
  421. * XILINX_CPM_PCIE_MISC_IR_ENABLE register is mapped to
  422. * CPM SLCR block.
  423. */
  424. writel(variant->ir_misc_value,
  425. port->cpm_base + XILINX_CPM_PCIE_MISC_IR_ENABLE);
  426. if (variant->ir_enable) {
  427. writel(XILINX_CPM_PCIE_IR_LOCAL,
  428. port->cpm_base + variant->ir_enable);
  429. }
  430. /* Set Bridge enable bit */
  431. pcie_write(port, pcie_read(port, XILINX_CPM_PCIE_REG_RPSC) |
  432. XILINX_CPM_PCIE_REG_RPSC_BEN,
  433. XILINX_CPM_PCIE_REG_RPSC);
  434. }
  435. /**
  436. * xilinx_cpm_pcie_parse_dt - Parse Device tree
  437. * @port: PCIe port information
  438. * @bus_range: Bus resource
  439. *
  440. * Return: '0' on success and error value on failure
  441. */
  442. static int xilinx_cpm_pcie_parse_dt(struct xilinx_cpm_pcie *port,
  443. struct resource *bus_range)
  444. {
  445. struct device *dev = port->dev;
  446. struct platform_device *pdev = to_platform_device(dev);
  447. struct resource *res;
  448. port->cpm_base = devm_platform_ioremap_resource_byname(pdev,
  449. "cpm_slcr");
  450. if (IS_ERR(port->cpm_base))
  451. return PTR_ERR(port->cpm_base);
  452. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
  453. if (!res)
  454. return -ENXIO;
  455. port->cfg = pci_ecam_create(dev, res, bus_range,
  456. &pci_generic_ecam_ops);
  457. if (IS_ERR(port->cfg))
  458. return PTR_ERR(port->cfg);
  459. if (port->variant->version == CPM5 ||
  460. port->variant->version == CPM5_HOST1) {
  461. port->reg_base = devm_platform_ioremap_resource_byname(pdev,
  462. "cpm_csr");
  463. if (IS_ERR(port->reg_base))
  464. return PTR_ERR(port->reg_base);
  465. } else {
  466. port->reg_base = port->cfg->win;
  467. }
  468. return 0;
  469. }
  470. static void xilinx_cpm_free_interrupts(struct xilinx_cpm_pcie *port)
  471. {
  472. irq_set_chained_handler_and_data(port->intx_irq, NULL, NULL);
  473. irq_set_chained_handler_and_data(port->irq, NULL, NULL);
  474. }
  475. /**
  476. * xilinx_cpm_pcie_probe - Probe function
  477. * @pdev: Platform device pointer
  478. *
  479. * Return: '0' on success and error value on failure
  480. */
  481. static int xilinx_cpm_pcie_probe(struct platform_device *pdev)
  482. {
  483. struct xilinx_cpm_pcie *port;
  484. struct device *dev = &pdev->dev;
  485. struct pci_host_bridge *bridge;
  486. struct resource_entry *bus;
  487. int err;
  488. bridge = devm_pci_alloc_host_bridge(dev, sizeof(*port));
  489. if (!bridge)
  490. return -ENODEV;
  491. port = pci_host_bridge_priv(bridge);
  492. port->dev = dev;
  493. port->variant = of_device_get_match_data(dev);
  494. if (port->variant->version != CPM5NC_HOST) {
  495. err = xilinx_cpm_pcie_init_irq_domain(port);
  496. if (err)
  497. return err;
  498. }
  499. bus = resource_list_first_type(&bridge->windows, IORESOURCE_BUS);
  500. if (!bus) {
  501. err = -ENODEV;
  502. goto err_free_irq_domains;
  503. }
  504. err = xilinx_cpm_pcie_parse_dt(port, bus->res);
  505. if (err) {
  506. dev_err(dev, "Parsing DT failed\n");
  507. goto err_free_irq_domains;
  508. }
  509. xilinx_cpm_pcie_init_port(port);
  510. if (port->variant->version != CPM5NC_HOST) {
  511. err = xilinx_cpm_setup_irq(port);
  512. if (err) {
  513. dev_err(dev, "Failed to set up interrupts\n");
  514. goto err_setup_irq;
  515. }
  516. }
  517. bridge->sysdata = port->cfg;
  518. bridge->ops = (struct pci_ops *)&pci_generic_ecam_ops.pci_ops;
  519. err = pci_host_probe(bridge);
  520. if (err < 0)
  521. goto err_host_bridge;
  522. return 0;
  523. err_host_bridge:
  524. if (port->variant->version != CPM5NC_HOST)
  525. xilinx_cpm_free_interrupts(port);
  526. err_setup_irq:
  527. pci_ecam_free(port->cfg);
  528. err_free_irq_domains:
  529. if (port->variant->version != CPM5NC_HOST)
  530. xilinx_cpm_free_irq_domains(port);
  531. return err;
  532. }
  533. static const struct xilinx_cpm_variant cpm_host = {
  534. .version = CPM,
  535. .ir_misc_value = XILINX_CPM_PCIE0_MISC_IR_LOCAL,
  536. };
  537. static const struct xilinx_cpm_variant cpm5_host = {
  538. .version = CPM5,
  539. .ir_misc_value = XILINX_CPM_PCIE0_MISC_IR_LOCAL,
  540. .ir_status = XILINX_CPM_PCIE0_IR_STATUS,
  541. .ir_enable = XILINX_CPM_PCIE0_IR_ENABLE,
  542. };
  543. static const struct xilinx_cpm_variant cpm5_host1 = {
  544. .version = CPM5_HOST1,
  545. .ir_misc_value = XILINX_CPM_PCIE1_MISC_IR_LOCAL,
  546. .ir_status = XILINX_CPM_PCIE1_IR_STATUS,
  547. .ir_enable = XILINX_CPM_PCIE1_IR_ENABLE,
  548. };
  549. static const struct xilinx_cpm_variant cpm5n_host = {
  550. .version = CPM5NC_HOST,
  551. };
  552. static const struct of_device_id xilinx_cpm_pcie_of_match[] = {
  553. {
  554. .compatible = "xlnx,versal-cpm-host-1.00",
  555. .data = &cpm_host,
  556. },
  557. {
  558. .compatible = "xlnx,versal-cpm5-host",
  559. .data = &cpm5_host,
  560. },
  561. {
  562. .compatible = "xlnx,versal-cpm5-host1",
  563. .data = &cpm5_host1,
  564. },
  565. {
  566. .compatible = "xlnx,versal-cpm5nc-host",
  567. .data = &cpm5n_host,
  568. },
  569. {}
  570. };
  571. static struct platform_driver xilinx_cpm_pcie_driver = {
  572. .driver = {
  573. .name = "xilinx-cpm-pcie",
  574. .of_match_table = xilinx_cpm_pcie_of_match,
  575. .suppress_bind_attrs = true,
  576. },
  577. .probe = xilinx_cpm_pcie_probe,
  578. };
  579. builtin_platform_driver(xilinx_cpm_pcie_driver);