root/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xmdio_read
  2. xmdio_write
  3. vfio_platform_amdxgbe_reset

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * VFIO platform driver specialized for AMD xgbe reset
   4  * reset code is inherited from AMD xgbe native driver
   5  *
   6  * Copyright (c) 2015 Linaro Ltd.
   7  *              www.linaro.org
   8  */
   9 
  10 #include <linux/module.h>
  11 #include <linux/kernel.h>
  12 #include <linux/init.h>
  13 #include <linux/io.h>
  14 #include <uapi/linux/mdio.h>
  15 #include <linux/delay.h>
  16 
  17 #include "../vfio_platform_private.h"
  18 
  19 #define DMA_MR                  0x3000
  20 #define MAC_VR                  0x0110
  21 #define DMA_ISR                 0x3008
  22 #define MAC_ISR                 0x00b0
  23 #define PCS_MMD_SELECT          0xff
  24 #define MDIO_AN_INT             0x8002
  25 #define MDIO_AN_INTMASK         0x8001
  26 
  27 static unsigned int xmdio_read(void *ioaddr, unsigned int mmd,
  28                                unsigned int reg)
  29 {
  30         unsigned int mmd_address, value;
  31 
  32         mmd_address = (mmd << 16) | ((reg) & 0xffff);
  33         iowrite32(mmd_address >> 8, ioaddr + (PCS_MMD_SELECT << 2));
  34         value = ioread32(ioaddr + ((mmd_address & 0xff) << 2));
  35         return value;
  36 }
  37 
  38 static void xmdio_write(void *ioaddr, unsigned int mmd,
  39                         unsigned int reg, unsigned int value)
  40 {
  41         unsigned int mmd_address;
  42 
  43         mmd_address = (mmd << 16) | ((reg) & 0xffff);
  44         iowrite32(mmd_address >> 8, ioaddr + (PCS_MMD_SELECT << 2));
  45         iowrite32(value, ioaddr + ((mmd_address & 0xff) << 2));
  46 }
  47 
  48 static int vfio_platform_amdxgbe_reset(struct vfio_platform_device *vdev)
  49 {
  50         struct vfio_platform_region *xgmac_regs = &vdev->regions[0];
  51         struct vfio_platform_region *xpcs_regs = &vdev->regions[1];
  52         u32 dma_mr_value, pcs_value, value;
  53         unsigned int count;
  54 
  55         if (!xgmac_regs->ioaddr) {
  56                 xgmac_regs->ioaddr =
  57                         ioremap_nocache(xgmac_regs->addr, xgmac_regs->size);
  58                 if (!xgmac_regs->ioaddr)
  59                         return -ENOMEM;
  60         }
  61         if (!xpcs_regs->ioaddr) {
  62                 xpcs_regs->ioaddr =
  63                         ioremap_nocache(xpcs_regs->addr, xpcs_regs->size);
  64                 if (!xpcs_regs->ioaddr)
  65                         return -ENOMEM;
  66         }
  67 
  68         /* reset the PHY through MDIO*/
  69         pcs_value = xmdio_read(xpcs_regs->ioaddr, MDIO_MMD_PCS, MDIO_CTRL1);
  70         pcs_value |= MDIO_CTRL1_RESET;
  71         xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_PCS, MDIO_CTRL1, pcs_value);
  72 
  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 
  80         if (pcs_value & MDIO_CTRL1_RESET)
  81                 dev_warn(vdev->device, "%s: XGBE PHY reset timeout\n",
  82                          __func__);
  83 
  84         /* disable auto-negotiation */
  85         value = xmdio_read(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_CTRL1);
  86         value &= ~MDIO_AN_CTRL1_ENABLE;
  87         xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_CTRL1, value);
  88 
  89         /* disable AN IRQ */
  90         xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
  91 
  92         /* clear AN IRQ */
  93         xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_AN_INT, 0);
  94 
  95         /* MAC software reset */
  96         dma_mr_value = ioread32(xgmac_regs->ioaddr + DMA_MR);
  97         dma_mr_value |= 0x1;
  98         iowrite32(dma_mr_value, xgmac_regs->ioaddr + DMA_MR);
  99 
 100         usleep_range(10, 15);
 101 
 102         count = 2000;
 103         while (--count && (ioread32(xgmac_regs->ioaddr + DMA_MR) & 1))
 104                 usleep_range(500, 600);
 105 
 106         if (!count)
 107                 dev_warn(vdev->device, "%s: MAC SW reset failed\n", __func__);
 108 
 109         return 0;
 110 }
 111 
 112 module_vfio_reset_handler("amd,xgbe-seattle-v1a", vfio_platform_amdxgbe_reset);
 113 
 114 MODULE_VERSION("0.1");
 115 MODULE_LICENSE("GPL v2");
 116 MODULE_AUTHOR("Eric Auger <eric.auger@linaro.org>");
 117 MODULE_DESCRIPTION("Reset support for AMD xgbe vfio platform device");

/* [<][>][^][v][top][bottom][index][help] */