thunder_xcv.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. * Copyright (C) 2016 Cavium, Inc.
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of version 2 of the GNU General Public License
  6. * as published by the Free Software Foundation.
  7. */
  8. #include <linux/acpi.h>
  9. #include <linux/module.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/pci.h>
  12. #include <linux/netdevice.h>
  13. #include <linux/etherdevice.h>
  14. #include <linux/phy.h>
  15. #include <linux/of.h>
  16. #include <linux/of_mdio.h>
  17. #include <linux/of_net.h>
  18. #include "nic.h"
  19. #include "thunder_bgx.h"
  20. #define DRV_NAME "thunder-xcv"
  21. #define DRV_VERSION "1.0"
  22. /* Register offsets */
  23. #define XCV_RESET 0x00
  24. #define PORT_EN BIT_ULL(63)
  25. #define CLK_RESET BIT_ULL(15)
  26. #define DLL_RESET BIT_ULL(11)
  27. #define COMP_EN BIT_ULL(7)
  28. #define TX_PKT_RESET BIT_ULL(3)
  29. #define TX_DATA_RESET BIT_ULL(2)
  30. #define RX_PKT_RESET BIT_ULL(1)
  31. #define RX_DATA_RESET BIT_ULL(0)
  32. #define XCV_DLL_CTL 0x10
  33. #define CLKRX_BYP BIT_ULL(23)
  34. #define CLKTX_BYP BIT_ULL(15)
  35. #define XCV_COMP_CTL 0x20
  36. #define DRV_BYP BIT_ULL(63)
  37. #define XCV_CTL 0x30
  38. #define XCV_INT 0x40
  39. #define XCV_INT_W1S 0x48
  40. #define XCV_INT_ENA_W1C 0x50
  41. #define XCV_INT_ENA_W1S 0x58
  42. #define XCV_INBND_STATUS 0x80
  43. #define XCV_BATCH_CRD_RET 0x100
  44. struct xcv {
  45. void __iomem *reg_base;
  46. struct pci_dev *pdev;
  47. };
  48. static struct xcv *xcv;
  49. /* Supported devices */
  50. static const struct pci_device_id xcv_id_table[] = {
  51. { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xA056) },
  52. { 0, } /* end of table */
  53. };
  54. MODULE_AUTHOR("Cavium Inc");
  55. MODULE_DESCRIPTION("Cavium Thunder RGX/XCV Driver");
  56. MODULE_LICENSE("GPL v2");
  57. MODULE_VERSION(DRV_VERSION);
  58. MODULE_DEVICE_TABLE(pci, xcv_id_table);
  59. void xcv_init_hw(void)
  60. {
  61. u64 cfg;
  62. /* Take DLL out of reset */
  63. cfg = readq_relaxed(xcv->reg_base + XCV_RESET);
  64. cfg &= ~DLL_RESET;
  65. writeq_relaxed(cfg, xcv->reg_base + XCV_RESET);
  66. /* Take clock tree out of reset */
  67. cfg = readq_relaxed(xcv->reg_base + XCV_RESET);
  68. cfg &= ~CLK_RESET;
  69. writeq_relaxed(cfg, xcv->reg_base + XCV_RESET);
  70. /* Wait for DLL to lock */
  71. msleep(1);
  72. /* Configure DLL - enable or bypass
  73. * TX no bypass, RX bypass
  74. */
  75. cfg = readq_relaxed(xcv->reg_base + XCV_DLL_CTL);
  76. cfg &= ~0xFF03;
  77. cfg |= CLKRX_BYP;
  78. writeq_relaxed(cfg, xcv->reg_base + XCV_DLL_CTL);
  79. /* Enable compensation controller and force the
  80. * write to be visible to HW by readig back.
  81. */
  82. cfg = readq_relaxed(xcv->reg_base + XCV_RESET);
  83. cfg |= COMP_EN;
  84. writeq_relaxed(cfg, xcv->reg_base + XCV_RESET);
  85. readq_relaxed(xcv->reg_base + XCV_RESET);
  86. /* Wait for compensation state machine to lock */
  87. msleep(10);
  88. /* enable the XCV block */
  89. cfg = readq_relaxed(xcv->reg_base + XCV_RESET);
  90. cfg |= PORT_EN;
  91. writeq_relaxed(cfg, xcv->reg_base + XCV_RESET);
  92. cfg = readq_relaxed(xcv->reg_base + XCV_RESET);
  93. cfg |= CLK_RESET;
  94. writeq_relaxed(cfg, xcv->reg_base + XCV_RESET);
  95. }
  96. EXPORT_SYMBOL(xcv_init_hw);
  97. void xcv_setup_link(bool link_up, int link_speed)
  98. {
  99. u64 cfg;
  100. int speed = 2;
  101. if (!xcv) {
  102. dev_err(&xcv->pdev->dev,
  103. "XCV init not done, probe may have failed\n");
  104. return;
  105. }
  106. if (link_speed == 100)
  107. speed = 1;
  108. else if (link_speed == 10)
  109. speed = 0;
  110. if (link_up) {
  111. /* set operating speed */
  112. cfg = readq_relaxed(xcv->reg_base + XCV_CTL);
  113. cfg &= ~0x03;
  114. cfg |= speed;
  115. writeq_relaxed(cfg, xcv->reg_base + XCV_CTL);
  116. /* Reset datapaths */
  117. cfg = readq_relaxed(xcv->reg_base + XCV_RESET);
  118. cfg |= TX_DATA_RESET | RX_DATA_RESET;
  119. writeq_relaxed(cfg, xcv->reg_base + XCV_RESET);
  120. /* Enable the packet flow */
  121. cfg = readq_relaxed(xcv->reg_base + XCV_RESET);
  122. cfg |= TX_PKT_RESET | RX_PKT_RESET;
  123. writeq_relaxed(cfg, xcv->reg_base + XCV_RESET);
  124. /* Return credits to RGX */
  125. writeq_relaxed(0x01, xcv->reg_base + XCV_BATCH_CRD_RET);
  126. } else {
  127. /* Disable packet flow */
  128. cfg = readq_relaxed(xcv->reg_base + XCV_RESET);
  129. cfg &= ~(TX_PKT_RESET | RX_PKT_RESET);
  130. writeq_relaxed(cfg, xcv->reg_base + XCV_RESET);
  131. readq_relaxed(xcv->reg_base + XCV_RESET);
  132. }
  133. }
  134. EXPORT_SYMBOL(xcv_setup_link);
  135. static int xcv_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  136. {
  137. int err;
  138. struct device *dev = &pdev->dev;
  139. xcv = devm_kzalloc(dev, sizeof(struct xcv), GFP_KERNEL);
  140. if (!xcv)
  141. return -ENOMEM;
  142. xcv->pdev = pdev;
  143. pci_set_drvdata(pdev, xcv);
  144. err = pci_enable_device(pdev);
  145. if (err) {
  146. dev_err(dev, "Failed to enable PCI device\n");
  147. goto err_kfree;
  148. }
  149. err = pci_request_regions(pdev, DRV_NAME);
  150. if (err) {
  151. dev_err(dev, "PCI request regions failed 0x%x\n", err);
  152. goto err_disable_device;
  153. }
  154. /* MAP configuration registers */
  155. xcv->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0);
  156. if (!xcv->reg_base) {
  157. dev_err(dev, "XCV: Cannot map CSR memory space, aborting\n");
  158. err = -ENOMEM;
  159. goto err_release_regions;
  160. }
  161. return 0;
  162. err_release_regions:
  163. pci_release_regions(pdev);
  164. err_disable_device:
  165. pci_disable_device(pdev);
  166. err_kfree:
  167. devm_kfree(dev, xcv);
  168. xcv = NULL;
  169. return err;
  170. }
  171. static void xcv_remove(struct pci_dev *pdev)
  172. {
  173. struct device *dev = &pdev->dev;
  174. if (xcv) {
  175. devm_kfree(dev, xcv);
  176. xcv = NULL;
  177. }
  178. pci_release_regions(pdev);
  179. pci_disable_device(pdev);
  180. }
  181. static struct pci_driver xcv_driver = {
  182. .name = DRV_NAME,
  183. .id_table = xcv_id_table,
  184. .probe = xcv_probe,
  185. .remove = xcv_remove,
  186. };
  187. static int __init xcv_init_module(void)
  188. {
  189. pr_info("%s, ver %s\n", DRV_NAME, DRV_VERSION);
  190. return pci_register_driver(&xcv_driver);
  191. }
  192. static void __exit xcv_cleanup_module(void)
  193. {
  194. pci_unregister_driver(&xcv_driver);
  195. }
  196. module_init(xcv_init_module);
  197. module_exit(xcv_cleanup_module);