0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/delay.h>
0012 #include <linux/device.h>
0013 #include <linux/init.h>
0014 #include <linux/io.h>
0015 #include <linux/kernel.h>
0016 #include <linux/module.h>
0017
0018 #include "../vfio_platform_private.h"
0019
0020
0021 #define RING_REGS_SIZE 0x10000
0022 #define RING_VER_MAGIC 0x76303031
0023
0024
0025 #define RING_VER 0x000
0026 #define RING_CONTROL 0x034
0027 #define RING_FLUSH_DONE 0x038
0028
0029
0030 #define CONTROL_FLUSH_SHIFT 5
0031
0032
0033 #define FLUSH_DONE_MASK 0x1
0034
0035 static int vfio_platform_bcmflexrm_shutdown(void __iomem *ring)
0036 {
0037 unsigned int timeout;
0038
0039
0040 writel_relaxed(0x0, ring + RING_CONTROL);
0041
0042
0043 timeout = 1000;
0044 writel_relaxed(BIT(CONTROL_FLUSH_SHIFT), ring + RING_CONTROL);
0045 do {
0046 if (readl_relaxed(ring + RING_FLUSH_DONE) &
0047 FLUSH_DONE_MASK)
0048 break;
0049 mdelay(1);
0050 } while (--timeout);
0051 if (!timeout)
0052 return -ETIMEDOUT;
0053
0054
0055 timeout = 1000;
0056 writel_relaxed(0x0, ring + RING_CONTROL);
0057 do {
0058 if (!(readl_relaxed(ring + RING_FLUSH_DONE) &
0059 FLUSH_DONE_MASK))
0060 break;
0061 mdelay(1);
0062 } while (--timeout);
0063 if (!timeout)
0064 return -ETIMEDOUT;
0065
0066 return 0;
0067 }
0068
0069 static int vfio_platform_bcmflexrm_reset(struct vfio_platform_device *vdev)
0070 {
0071 void __iomem *ring;
0072 int rc = 0, ret = 0, ring_num = 0;
0073 struct vfio_platform_region *reg = &vdev->regions[0];
0074
0075
0076 if (!reg->ioaddr) {
0077 reg->ioaddr = ioremap(reg->addr, reg->size);
0078 if (!reg->ioaddr)
0079 return -ENOMEM;
0080 }
0081
0082
0083 for (ring = reg->ioaddr;
0084 ring < (reg->ioaddr + reg->size); ring += RING_REGS_SIZE) {
0085 if (readl_relaxed(ring + RING_VER) == RING_VER_MAGIC) {
0086 rc = vfio_platform_bcmflexrm_shutdown(ring);
0087 if (rc) {
0088 dev_warn(vdev->device,
0089 "FlexRM ring%d shutdown error %d\n",
0090 ring_num, rc);
0091 ret |= rc;
0092 }
0093 ring_num++;
0094 }
0095 }
0096
0097 return ret;
0098 }
0099
0100 module_vfio_reset_handler("brcm,iproc-flexrm-mbox",
0101 vfio_platform_bcmflexrm_reset);
0102
0103 MODULE_LICENSE("GPL v2");
0104 MODULE_AUTHOR("Anup Patel <anup.patel@broadcom.com>");
0105 MODULE_DESCRIPTION("Reset support for Broadcom FlexRM VFIO platform device");