Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2017 Broadcom
0004  */
0005 
0006 /*
0007  * This driver provides reset support for Broadcom FlexRM ring manager
0008  * to VFIO platform.
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 /* FlexRM configuration */
0021 #define RING_REGS_SIZE                  0x10000
0022 #define RING_VER_MAGIC                  0x76303031
0023 
0024 /* Per-Ring register offsets */
0025 #define RING_VER                    0x000
0026 #define RING_CONTROL                    0x034
0027 #define RING_FLUSH_DONE                 0x038
0028 
0029 /* Register RING_CONTROL fields */
0030 #define CONTROL_FLUSH_SHIFT             5
0031 
0032 /* Register RING_FLUSH_DONE fields */
0033 #define FLUSH_DONE_MASK                 0x1
0034 
0035 static int vfio_platform_bcmflexrm_shutdown(void __iomem *ring)
0036 {
0037     unsigned int timeout;
0038 
0039     /* Disable/inactivate ring */
0040     writel_relaxed(0x0, ring + RING_CONTROL);
0041 
0042     /* Set ring flush state */
0043     timeout = 1000; /* timeout of 1s */
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     /* Clear ring flush state */
0055     timeout = 1000; /* timeout of 1s */
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     /* Map FlexRM ring registers if not mapped */
0076     if (!reg->ioaddr) {
0077         reg->ioaddr = ioremap(reg->addr, reg->size);
0078         if (!reg->ioaddr)
0079             return -ENOMEM;
0080     }
0081 
0082     /* Discover and shutdown each FlexRM ring */
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");