ctucanfd_pci.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*******************************************************************************
  3. *
  4. * CTU CAN FD IP Core
  5. *
  6. * Copyright (C) 2015-2018 Ondrej Ille <[email protected]> FEE CTU
  7. * Copyright (C) 2018-2021 Ondrej Ille <[email protected]> self-funded
  8. * Copyright (C) 2018-2019 Martin Jerabek <[email protected]> FEE CTU
  9. * Copyright (C) 2018-2022 Pavel Pisa <[email protected]> FEE CTU/self-funded
  10. *
  11. * Project advisors:
  12. * Jiri Novak <[email protected]>
  13. * Pavel Pisa <[email protected]>
  14. *
  15. * Department of Measurement (http://meas.fel.cvut.cz/)
  16. * Faculty of Electrical Engineering (http://www.fel.cvut.cz)
  17. * Czech Technical University (http://www.cvut.cz/)
  18. ******************************************************************************/
  19. #include <linux/module.h>
  20. #include <linux/pci.h>
  21. #include "ctucanfd.h"
  22. #ifndef PCI_DEVICE_DATA
  23. #define PCI_DEVICE_DATA(vend, dev, data) \
  24. .vendor = PCI_VENDOR_ID_##vend, \
  25. .device = PCI_DEVICE_ID_##vend##_##dev, \
  26. .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, 0, 0, \
  27. .driver_data = (kernel_ulong_t)(data)
  28. #endif
  29. #ifndef PCI_VENDOR_ID_TEDIA
  30. #define PCI_VENDOR_ID_TEDIA 0x1760
  31. #endif
  32. #ifndef PCI_DEVICE_ID_TEDIA_CTUCAN_VER21
  33. #define PCI_DEVICE_ID_TEDIA_CTUCAN_VER21 0xff00
  34. #endif
  35. #define CTUCAN_BAR0_CTUCAN_ID 0x0000
  36. #define CTUCAN_BAR0_CRA_BASE 0x4000
  37. #define CYCLONE_IV_CRA_A2P_IE (0x0050)
  38. #define CTUCAN_WITHOUT_CTUCAN_ID 0
  39. #define CTUCAN_WITH_CTUCAN_ID 1
  40. struct ctucan_pci_board_data {
  41. void __iomem *bar0_base;
  42. void __iomem *cra_base;
  43. void __iomem *bar1_base;
  44. struct list_head ndev_list_head;
  45. int use_msi;
  46. };
  47. static struct ctucan_pci_board_data *ctucan_pci_get_bdata(struct pci_dev *pdev)
  48. {
  49. return (struct ctucan_pci_board_data *)pci_get_drvdata(pdev);
  50. }
  51. static void ctucan_pci_set_drvdata(struct device *dev,
  52. struct net_device *ndev)
  53. {
  54. struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
  55. struct ctucan_priv *priv = netdev_priv(ndev);
  56. struct ctucan_pci_board_data *bdata = ctucan_pci_get_bdata(pdev);
  57. list_add(&priv->peers_on_pdev, &bdata->ndev_list_head);
  58. priv->irq_flags = IRQF_SHARED;
  59. }
  60. /**
  61. * ctucan_pci_probe - PCI registration call
  62. * @pdev: Handle to the pci device structure
  63. * @ent: Pointer to the entry from ctucan_pci_tbl
  64. *
  65. * This function does all the memory allocation and registration for the CAN
  66. * device.
  67. *
  68. * Return: 0 on success and failure value on error
  69. */
  70. static int ctucan_pci_probe(struct pci_dev *pdev,
  71. const struct pci_device_id *ent)
  72. {
  73. struct device *dev = &pdev->dev;
  74. unsigned long driver_data = ent->driver_data;
  75. struct ctucan_pci_board_data *bdata;
  76. void __iomem *addr;
  77. void __iomem *cra_addr;
  78. void __iomem *bar0_base;
  79. u32 cra_a2p_ie;
  80. u32 ctucan_id = 0;
  81. int ret;
  82. unsigned int ntxbufs;
  83. unsigned int num_cores = 1;
  84. unsigned int core_i = 0;
  85. int irq;
  86. int msi_ok = 0;
  87. ret = pci_enable_device(pdev);
  88. if (ret) {
  89. dev_err(dev, "pci_enable_device FAILED\n");
  90. goto err;
  91. }
  92. ret = pci_request_regions(pdev, KBUILD_MODNAME);
  93. if (ret) {
  94. dev_err(dev, "pci_request_regions FAILED\n");
  95. goto err_disable_device;
  96. }
  97. ret = pci_enable_msi(pdev);
  98. if (!ret) {
  99. dev_info(dev, "MSI enabled\n");
  100. pci_set_master(pdev);
  101. msi_ok = 1;
  102. }
  103. dev_info(dev, "ctucan BAR0 0x%08llx 0x%08llx\n",
  104. (long long)pci_resource_start(pdev, 0),
  105. (long long)pci_resource_len(pdev, 0));
  106. dev_info(dev, "ctucan BAR1 0x%08llx 0x%08llx\n",
  107. (long long)pci_resource_start(pdev, 1),
  108. (long long)pci_resource_len(pdev, 1));
  109. addr = pci_iomap(pdev, 1, pci_resource_len(pdev, 1));
  110. if (!addr) {
  111. dev_err(dev, "PCI BAR 1 cannot be mapped\n");
  112. ret = -ENOMEM;
  113. goto err_release_regions;
  114. }
  115. /* Cyclone IV PCI Express Control Registers Area */
  116. bar0_base = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
  117. if (!bar0_base) {
  118. dev_err(dev, "PCI BAR 0 cannot be mapped\n");
  119. ret = -EIO;
  120. goto err_pci_iounmap_bar1;
  121. }
  122. if (driver_data == CTUCAN_WITHOUT_CTUCAN_ID) {
  123. cra_addr = bar0_base;
  124. num_cores = 2;
  125. } else {
  126. cra_addr = bar0_base + CTUCAN_BAR0_CRA_BASE;
  127. ctucan_id = ioread32(bar0_base + CTUCAN_BAR0_CTUCAN_ID);
  128. dev_info(dev, "ctucan_id 0x%08lx\n", (unsigned long)ctucan_id);
  129. num_cores = ctucan_id & 0xf;
  130. }
  131. irq = pdev->irq;
  132. ntxbufs = 4;
  133. bdata = kzalloc(sizeof(*bdata), GFP_KERNEL);
  134. if (!bdata) {
  135. ret = -ENOMEM;
  136. goto err_pci_iounmap_bar0;
  137. }
  138. INIT_LIST_HEAD(&bdata->ndev_list_head);
  139. bdata->bar0_base = bar0_base;
  140. bdata->cra_base = cra_addr;
  141. bdata->bar1_base = addr;
  142. bdata->use_msi = msi_ok;
  143. pci_set_drvdata(pdev, bdata);
  144. ret = ctucan_probe_common(dev, addr, irq, ntxbufs, 100000000,
  145. 0, ctucan_pci_set_drvdata);
  146. if (ret < 0)
  147. goto err_free_board;
  148. core_i++;
  149. while (core_i < num_cores) {
  150. addr += 0x4000;
  151. ret = ctucan_probe_common(dev, addr, irq, ntxbufs, 100000000,
  152. 0, ctucan_pci_set_drvdata);
  153. if (ret < 0) {
  154. dev_info(dev, "CTU CAN FD core %d initialization failed\n",
  155. core_i);
  156. break;
  157. }
  158. core_i++;
  159. }
  160. /* enable interrupt in
  161. * Avalon-MM to PCI Express Interrupt Enable Register
  162. */
  163. cra_a2p_ie = ioread32(cra_addr + CYCLONE_IV_CRA_A2P_IE);
  164. dev_info(dev, "cra_a2p_ie 0x%08x\n", cra_a2p_ie);
  165. cra_a2p_ie |= 1;
  166. iowrite32(cra_a2p_ie, cra_addr + CYCLONE_IV_CRA_A2P_IE);
  167. cra_a2p_ie = ioread32(cra_addr + CYCLONE_IV_CRA_A2P_IE);
  168. dev_info(dev, "cra_a2p_ie 0x%08x\n", cra_a2p_ie);
  169. return 0;
  170. err_free_board:
  171. pci_set_drvdata(pdev, NULL);
  172. kfree(bdata);
  173. err_pci_iounmap_bar0:
  174. pci_iounmap(pdev, cra_addr);
  175. err_pci_iounmap_bar1:
  176. pci_iounmap(pdev, addr);
  177. err_release_regions:
  178. if (msi_ok) {
  179. pci_disable_msi(pdev);
  180. pci_clear_master(pdev);
  181. }
  182. pci_release_regions(pdev);
  183. err_disable_device:
  184. pci_disable_device(pdev);
  185. err:
  186. return ret;
  187. }
  188. /**
  189. * ctucan_pci_remove - Unregister the device after releasing the resources
  190. * @pdev: Handle to the pci device structure
  191. *
  192. * This function frees all the resources allocated to the device.
  193. * Return: 0 always
  194. */
  195. static void ctucan_pci_remove(struct pci_dev *pdev)
  196. {
  197. struct net_device *ndev;
  198. struct ctucan_priv *priv = NULL;
  199. struct ctucan_pci_board_data *bdata = ctucan_pci_get_bdata(pdev);
  200. dev_dbg(&pdev->dev, "ctucan_remove");
  201. if (!bdata) {
  202. dev_err(&pdev->dev, "%s: no list of devices\n", __func__);
  203. return;
  204. }
  205. /* disable interrupt in
  206. * Avalon-MM to PCI Express Interrupt Enable Register
  207. */
  208. if (bdata->cra_base)
  209. iowrite32(0, bdata->cra_base + CYCLONE_IV_CRA_A2P_IE);
  210. while ((priv = list_first_entry_or_null(&bdata->ndev_list_head, struct ctucan_priv,
  211. peers_on_pdev)) != NULL) {
  212. ndev = priv->can.dev;
  213. unregister_candev(ndev);
  214. netif_napi_del(&priv->napi);
  215. list_del_init(&priv->peers_on_pdev);
  216. free_candev(ndev);
  217. }
  218. pci_iounmap(pdev, bdata->bar1_base);
  219. if (bdata->use_msi) {
  220. pci_disable_msi(pdev);
  221. pci_clear_master(pdev);
  222. }
  223. pci_release_regions(pdev);
  224. pci_disable_device(pdev);
  225. pci_iounmap(pdev, bdata->bar0_base);
  226. pci_set_drvdata(pdev, NULL);
  227. kfree(bdata);
  228. }
  229. static SIMPLE_DEV_PM_OPS(ctucan_pci_pm_ops, ctucan_suspend, ctucan_resume);
  230. static const struct pci_device_id ctucan_pci_tbl[] = {
  231. {PCI_DEVICE_DATA(TEDIA, CTUCAN_VER21,
  232. CTUCAN_WITH_CTUCAN_ID)},
  233. {},
  234. };
  235. static struct pci_driver ctucan_pci_driver = {
  236. .name = KBUILD_MODNAME,
  237. .id_table = ctucan_pci_tbl,
  238. .probe = ctucan_pci_probe,
  239. .remove = ctucan_pci_remove,
  240. .driver.pm = &ctucan_pci_pm_ops,
  241. };
  242. module_pci_driver(ctucan_pci_driver);
  243. MODULE_LICENSE("GPL");
  244. MODULE_AUTHOR("Pavel Pisa <[email protected]>");
  245. MODULE_DESCRIPTION("CTU CAN FD for PCI bus");