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. pr_err("XCV init not done, probe may have failed\n");
  103. return;
  104. }
  105. if (link_speed == 100)
  106. speed = 1;
  107. else if (link_speed == 10)
  108. speed = 0;
  109. if (link_up) {
  110. /* set operating speed */
  111. cfg = readq_relaxed(xcv->reg_base + XCV_CTL);
  112. cfg &= ~0x03;
  113. cfg |= speed;
  114. writeq_relaxed(cfg, xcv->reg_base + XCV_CTL);
  115. /* Reset datapaths */
  116. cfg = readq_relaxed(xcv->reg_base + XCV_RESET);
  117. cfg |= TX_DATA_RESET | RX_DATA_RESET;
  118. writeq_relaxed(cfg, xcv->reg_base + XCV_RESET);
  119. /* Enable the packet flow */
  120. cfg = readq_relaxed(xcv->reg_base + XCV_RESET);
  121. cfg |= TX_PKT_RESET | RX_PKT_RESET;
  122. writeq_relaxed(cfg, xcv->reg_base + XCV_RESET);
  123. /* Return credits to RGX */
  124. writeq_relaxed(0x01, xcv->reg_base + XCV_BATCH_CRD_RET);
  125. } else {
  126. /* Disable packet flow */
  127. cfg = readq_relaxed(xcv->reg_base + XCV_RESET);
  128. cfg &= ~(TX_PKT_RESET | RX_PKT_RESET);
  129. writeq_relaxed(cfg, xcv->reg_base + XCV_RESET);
  130. readq_relaxed(xcv->reg_base + XCV_RESET);
  131. }
  132. }
  133. EXPORT_SYMBOL(xcv_setup_link);
  134. static int xcv_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  135. {
  136. int err;
  137. struct device *dev = &pdev->dev;
  138. xcv = devm_kzalloc(dev, sizeof(struct xcv), GFP_KERNEL);
  139. if (!xcv)
  140. return -ENOMEM;
  141. xcv->pdev = pdev;
  142. pci_set_drvdata(pdev, xcv);
  143. err = pci_enable_device(pdev);
  144. if (err) {
  145. dev_err(dev, "Failed to enable PCI device\n");
  146. goto err_kfree;
  147. }
  148. err = pci_request_regions(pdev, DRV_NAME);
  149. if (err) {
  150. dev_err(dev, "PCI request regions failed 0x%x\n", err);
  151. goto err_disable_device;
  152. }
  153. /* MAP configuration registers */
  154. xcv->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0);
  155. if (!xcv->reg_base) {
  156. dev_err(dev, "XCV: Cannot map CSR memory space, aborting\n");
  157. err = -ENOMEM;
  158. goto err_release_regions;
  159. }
  160. return 0;
  161. err_release_regions:
  162. pci_release_regions(pdev);
  163. err_disable_device:
  164. pci_disable_device(pdev);
  165. err_kfree:
  166. devm_kfree(dev, xcv);
  167. xcv = NULL;
  168. return err;
  169. }
  170. static void xcv_remove(struct pci_dev *pdev)
  171. {
  172. struct device *dev = &pdev->dev;
  173. if (xcv) {
  174. devm_kfree(dev, xcv);
  175. xcv = NULL;
  176. }
  177. pci_release_regions(pdev);
  178. pci_disable_device(pdev);
  179. }
  180. static struct pci_driver xcv_driver = {
  181. .name = DRV_NAME,
  182. .id_table = xcv_id_table,
  183. .probe = xcv_probe,
  184. .remove = xcv_remove,
  185. };
  186. static int __init xcv_init_module(void)
  187. {
  188. pr_info("%s, ver %s\n", DRV_NAME, DRV_VERSION);
  189. return pci_register_driver(&xcv_driver);
  190. }
  191. static void __exit xcv_cleanup_module(void)
  192. {
  193. pci_unregister_driver(&xcv_driver);
  194. }
  195. module_init(xcv_init_module);
  196. module_exit(xcv_cleanup_module);