vfio_platform_amdxgbe.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * VFIO platform driver specialized for AMD xgbe reset
  3. * reset code is inherited from AMD xgbe native driver
  4. *
  5. * Copyright (c) 2015 Linaro Ltd.
  6. * www.linaro.org
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms and conditions of the GNU General Public License,
  10. * version 2, as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope it will be useful, but WITHOUT
  13. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  15. * more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along with
  18. * this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <linux/module.h>
  21. #include <linux/kernel.h>
  22. #include <linux/init.h>
  23. #include <linux/io.h>
  24. #include <uapi/linux/mdio.h>
  25. #include <linux/delay.h>
  26. #include "vfio_platform_private.h"
  27. #define DMA_MR 0x3000
  28. #define MAC_VR 0x0110
  29. #define DMA_ISR 0x3008
  30. #define MAC_ISR 0x00b0
  31. #define PCS_MMD_SELECT 0xff
  32. #define MDIO_AN_INT 0x8002
  33. #define MDIO_AN_INTMASK 0x8001
  34. static unsigned int xmdio_read(void *ioaddr, unsigned int mmd,
  35. unsigned int reg)
  36. {
  37. unsigned int mmd_address, value;
  38. mmd_address = (mmd << 16) | ((reg) & 0xffff);
  39. iowrite32(mmd_address >> 8, ioaddr + (PCS_MMD_SELECT << 2));
  40. value = ioread32(ioaddr + ((mmd_address & 0xff) << 2));
  41. return value;
  42. }
  43. static void xmdio_write(void *ioaddr, unsigned int mmd,
  44. unsigned int reg, unsigned int value)
  45. {
  46. unsigned int mmd_address;
  47. mmd_address = (mmd << 16) | ((reg) & 0xffff);
  48. iowrite32(mmd_address >> 8, ioaddr + (PCS_MMD_SELECT << 2));
  49. iowrite32(value, ioaddr + ((mmd_address & 0xff) << 2));
  50. }
  51. static int vfio_platform_amdxgbe_reset(struct vfio_platform_device *vdev)
  52. {
  53. struct vfio_platform_region *xgmac_regs = &vdev->regions[0];
  54. struct vfio_platform_region *xpcs_regs = &vdev->regions[1];
  55. u32 dma_mr_value, pcs_value, value;
  56. unsigned int count;
  57. if (!xgmac_regs->ioaddr) {
  58. xgmac_regs->ioaddr =
  59. ioremap_nocache(xgmac_regs->addr, xgmac_regs->size);
  60. if (!xgmac_regs->ioaddr)
  61. return -ENOMEM;
  62. }
  63. if (!xpcs_regs->ioaddr) {
  64. xpcs_regs->ioaddr =
  65. ioremap_nocache(xpcs_regs->addr, xpcs_regs->size);
  66. if (!xpcs_regs->ioaddr)
  67. return -ENOMEM;
  68. }
  69. /* reset the PHY through MDIO*/
  70. pcs_value = xmdio_read(xpcs_regs->ioaddr, MDIO_MMD_PCS, MDIO_CTRL1);
  71. pcs_value |= MDIO_CTRL1_RESET;
  72. xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_PCS, MDIO_CTRL1, pcs_value);
  73. count = 50;
  74. do {
  75. msleep(20);
  76. pcs_value = xmdio_read(xpcs_regs->ioaddr, MDIO_MMD_PCS,
  77. MDIO_CTRL1);
  78. } while ((pcs_value & MDIO_CTRL1_RESET) && --count);
  79. if (pcs_value & MDIO_CTRL1_RESET)
  80. pr_warn("%s XGBE PHY reset timeout\n", __func__);
  81. /* disable auto-negotiation */
  82. value = xmdio_read(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_CTRL1);
  83. value &= ~MDIO_AN_CTRL1_ENABLE;
  84. xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_CTRL1, value);
  85. /* disable AN IRQ */
  86. xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
  87. /* clear AN IRQ */
  88. xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_AN_INT, 0);
  89. /* MAC software reset */
  90. dma_mr_value = ioread32(xgmac_regs->ioaddr + DMA_MR);
  91. dma_mr_value |= 0x1;
  92. iowrite32(dma_mr_value, xgmac_regs->ioaddr + DMA_MR);
  93. usleep_range(10, 15);
  94. count = 2000;
  95. while (--count && (ioread32(xgmac_regs->ioaddr + DMA_MR) & 1))
  96. usleep_range(500, 600);
  97. if (!count)
  98. pr_warn("%s MAC SW reset failed\n", __func__);
  99. return 0;
  100. }
  101. module_vfio_reset_handler("amd,xgbe-seattle-v1a", vfio_platform_amdxgbe_reset);
  102. MODULE_VERSION("0.1");
  103. MODULE_LICENSE("GPL v2");
  104. MODULE_AUTHOR("Eric Auger <eric.auger@linaro.org>");
  105. MODULE_DESCRIPTION("Reset support for AMD xgbe vfio platform device");