pcie-dw_platfrom.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-09-23 GuEe-GUI first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #define DBG_TAG "pcie.dw.platfrom"
  13. #define DBG_LVL DBG_INFO
  14. #include <rtdbg.h>
  15. #include "pcie-dw.h"
  16. struct dw_dw_platform_pcie_soc_data
  17. {
  18. enum dw_pcie_device_mode mode;
  19. };
  20. struct dw_platform_pcie
  21. {
  22. struct dw_pcie *pci;
  23. struct rt_syscon *regmap;
  24. const struct dw_dw_platform_pcie_soc_data *soc_data;
  25. };
  26. static rt_err_t dw_platform_pcie_host_init(struct dw_pcie_port *port)
  27. {
  28. struct dw_pcie *pci = to_dw_pcie_from_port(port);
  29. dw_pcie_setup_rc(port);
  30. dw_pcie_wait_for_link(pci);
  31. dw_pcie_msi_init(port);
  32. return RT_EOK;
  33. }
  34. static void dw_platform_set_irq_count(struct dw_pcie_port *pp)
  35. {
  36. pp->irq_count = MAX_MSI_IRQS;
  37. }
  38. static const struct dw_pcie_host_ops dw_platform_pcie_host_ops =
  39. {
  40. .host_init = dw_platform_pcie_host_init,
  41. .set_irq_count = dw_platform_set_irq_count,
  42. };
  43. static rt_err_t dw_platform_pcie_establish_link(struct dw_pcie *pci)
  44. {
  45. return RT_EOK;
  46. }
  47. static const struct dw_pcie_ops dw_platform_pcie_ops =
  48. {
  49. .start_link = dw_platform_pcie_establish_link,
  50. };
  51. static rt_err_t dw_platform_pcie_ep_init(struct dw_pcie_ep *ep)
  52. {
  53. struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
  54. for (int bar = 0; bar < PCI_STD_NUM_BARS; ++bar)
  55. {
  56. dw_pcie_ep_reset_bar(pci, bar);
  57. }
  58. return RT_EOK;
  59. }
  60. static rt_err_t dw_platform_pcie_ep_raise_irq(struct dw_pcie_ep *ep,
  61. rt_uint8_t func_no, enum rt_pci_ep_irq type, unsigned irq)
  62. {
  63. switch (type)
  64. {
  65. case RT_PCI_EP_IRQ_LEGACY:
  66. return dw_pcie_ep_raise_legacy_irq(ep, func_no);
  67. case RT_PCI_EP_IRQ_MSI:
  68. return dw_pcie_ep_raise_msi_irq(ep, func_no, irq);
  69. case RT_PCI_EP_IRQ_MSIX:
  70. return dw_pcie_ep_raise_msix_irq(ep, func_no, irq);
  71. default:
  72. LOG_E("Unknown IRQ type = %d", type);
  73. }
  74. return RT_EOK;
  75. }
  76. static const struct dw_pcie_ep_ops dw_platform_pcie_ep_ops =
  77. {
  78. .ep_init = dw_platform_pcie_ep_init,
  79. .raise_irq = dw_platform_pcie_ep_raise_irq,
  80. };
  81. static rt_err_t dw_platform_add_pcie_port(struct dw_platform_pcie *plat_pcie,
  82. struct rt_device *dev)
  83. {
  84. rt_err_t err;
  85. struct dw_pcie *pci = plat_pcie->pci;
  86. struct dw_pcie_port *port = &pci->port;
  87. port->sys_irq = rt_dm_dev_get_irq(dev, 1);
  88. if (port->sys_irq < 0)
  89. {
  90. return port->sys_irq;
  91. }
  92. #ifdef RT_PCI_MSI
  93. port->msi_irq = rt_dm_dev_get_irq(dev, 0);
  94. if (port->msi_irq < 0)
  95. {
  96. return port->msi_irq;
  97. }
  98. #endif
  99. port->ops = &dw_platform_pcie_host_ops;
  100. if ((err = dw_pcie_host_init(port)))
  101. {
  102. LOG_E("Failed to initialize host");
  103. return err;
  104. }
  105. return RT_EOK;
  106. }
  107. static rt_err_t dw_platform_add_pcie_ep(struct dw_platform_pcie *plat_pcie,
  108. struct rt_device *dev)
  109. {
  110. rt_err_t err;
  111. struct dw_pcie *pci = plat_pcie->pci;
  112. struct dw_pcie_ep *ep = &pci->endpoint;
  113. pci->dbi_base2 = rt_dm_dev_iomap_by_name(dev, "dbi2");
  114. if (!pci->dbi_base2)
  115. {
  116. return -RT_EIO;
  117. }
  118. err = rt_dm_dev_get_address_by_name(dev, "addr_space", &ep->aspace, &ep->aspace_size);
  119. if (err)
  120. {
  121. rt_iounmap(pci->dbi_base2);
  122. return err;
  123. }
  124. ep->ops = &dw_platform_pcie_ep_ops;
  125. if ((err = dw_pcie_ep_init(ep)))
  126. {
  127. LOG_E("Failed to initialize endpoint");
  128. return err;
  129. }
  130. return RT_EOK;
  131. }
  132. static rt_err_t dw_platform_pcie_probe(struct rt_platform_device *pdev)
  133. {
  134. rt_err_t err;
  135. struct dw_pcie *pci = RT_NULL;
  136. struct dw_platform_pcie *plat_pcie;
  137. struct rt_device *dev = &pdev->parent;
  138. if (!(plat_pcie = rt_calloc(1, sizeof(*plat_pcie))))
  139. {
  140. return -RT_ENOMEM;
  141. }
  142. if (!(pci = rt_calloc(1, sizeof(*pci))))
  143. {
  144. err = -RT_ENOMEM;
  145. goto _fail;
  146. }
  147. plat_pcie->pci = pci;
  148. plat_pcie->soc_data = pdev->id->data;
  149. pci->dev = dev;
  150. pci->ops = &dw_platform_pcie_ops;
  151. pci->dbi_base = rt_dm_dev_iomap_by_name(dev, "dbi");
  152. if (!pci->dbi_base)
  153. {
  154. err = -RT_EIO;
  155. goto _fail;
  156. }
  157. dev->user_data = plat_pcie;
  158. switch (plat_pcie->soc_data->mode)
  159. {
  160. case DW_PCIE_RC_TYPE:
  161. if (!RT_KEY_ENABLED(RT_PCI_DW_HOST))
  162. {
  163. err = -RT_ENOSYS;
  164. goto _fail;
  165. }
  166. if ((err = dw_platform_add_pcie_port(plat_pcie, dev)))
  167. {
  168. goto _fail;
  169. }
  170. break;
  171. case DW_PCIE_EP_TYPE:
  172. if (!RT_KEY_ENABLED(RT_PCI_DW_EP))
  173. {
  174. err = -RT_ENOSYS;
  175. goto _fail;
  176. }
  177. if ((err = dw_platform_add_pcie_ep(plat_pcie, dev)))
  178. {
  179. goto _fail;
  180. }
  181. break;
  182. default:
  183. LOG_E("Invalid device type %d", plat_pcie->soc_data->mode);
  184. err = -RT_EINVAL;
  185. goto _fail;
  186. }
  187. return RT_EOK;
  188. _fail:
  189. if (pci)
  190. {
  191. if (pci->dbi_base)
  192. {
  193. rt_iounmap(pci->dbi_base);
  194. }
  195. rt_free(pci);
  196. }
  197. rt_free(plat_pcie);
  198. return err;
  199. }
  200. static rt_err_t dw_platform_pcie_remove(struct rt_platform_device *pdev)
  201. {
  202. struct dw_platform_pcie *plat_pcie = pdev->parent.user_data;
  203. rt_pci_host_bridge_remove(plat_pcie->pci->port.bridge);
  204. dw_pcie_host_free(&plat_pcie->pci->port);
  205. rt_iounmap(plat_pcie->pci->dbi_base);
  206. rt_free(plat_pcie->pci);
  207. rt_free(plat_pcie);
  208. return RT_EOK;
  209. }
  210. static const struct dw_dw_platform_pcie_soc_data dw_platform_pcie_rc_soc_data =
  211. {
  212. .mode = DW_PCIE_RC_TYPE,
  213. };
  214. static const struct dw_dw_platform_pcie_soc_data dw_platform_pcie_ep_soc_data =
  215. {
  216. .mode = DW_PCIE_EP_TYPE,
  217. };
  218. static const struct rt_ofw_node_id dw_platform_pcie_ofw_ids[] =
  219. {
  220. { .compatible = "snps,dw-pcie", .data = &dw_platform_pcie_rc_soc_data },
  221. { .compatible = "snps,dw-pcie-ep", .data = &dw_platform_pcie_ep_soc_data },
  222. { /* sentinel */ }
  223. };
  224. static struct rt_platform_driver dw_platform_pcie_driver =
  225. {
  226. .name = "dw-pcie",
  227. .ids = dw_platform_pcie_ofw_ids,
  228. .probe = dw_platform_pcie_probe,
  229. .remove = dw_platform_pcie_remove,
  230. };
  231. RT_PLATFORM_DRIVER_EXPORT(dw_platform_pcie_driver);