linux/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2017 Broadcom
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU General Public License as
   6 * published by the Free Software Foundation version 2.
   7 *
   8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
   9 * kind, whether express or implied; without even the implied warranty
  10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 */
  13
  14/*
  15 * This driver provides reset support for Broadcom FlexRM ring manager
  16 * to VFIO platform.
  17 */
  18
  19#include <linux/delay.h>
  20#include <linux/device.h>
  21#include <linux/init.h>
  22#include <linux/io.h>
  23#include <linux/kernel.h>
  24#include <linux/module.h>
  25
  26#include "../vfio_platform_private.h"
  27
  28/* FlexRM configuration */
  29#define RING_REGS_SIZE                                  0x10000
  30#define RING_VER_MAGIC                                  0x76303031
  31
  32/* Per-Ring register offsets */
  33#define RING_VER                                        0x000
  34#define RING_CONTROL                                    0x034
  35#define RING_FLUSH_DONE                                 0x038
  36
  37/* Register RING_CONTROL fields */
  38#define CONTROL_FLUSH_SHIFT                             5
  39
  40/* Register RING_FLUSH_DONE fields */
  41#define FLUSH_DONE_MASK                                 0x1
  42
  43static int vfio_platform_bcmflexrm_shutdown(void __iomem *ring)
  44{
  45        unsigned int timeout;
  46
  47        /* Disable/inactivate ring */
  48        writel_relaxed(0x0, ring + RING_CONTROL);
  49
  50        /* Set ring flush state */
  51        timeout = 1000; /* timeout of 1s */
  52        writel_relaxed(BIT(CONTROL_FLUSH_SHIFT), ring + RING_CONTROL);
  53        do {
  54                if (readl_relaxed(ring + RING_FLUSH_DONE) &
  55                    FLUSH_DONE_MASK)
  56                        break;
  57                mdelay(1);
  58        } while (--timeout);
  59        if (!timeout)
  60                return -ETIMEDOUT;
  61
  62        /* Clear ring flush state */
  63        timeout = 1000; /* timeout of 1s */
  64        writel_relaxed(0x0, ring + RING_CONTROL);
  65        do {
  66                if (!(readl_relaxed(ring + RING_FLUSH_DONE) &
  67                      FLUSH_DONE_MASK))
  68                        break;
  69                mdelay(1);
  70        } while (--timeout);
  71        if (!timeout)
  72                return -ETIMEDOUT;
  73
  74        return 0;
  75}
  76
  77static int vfio_platform_bcmflexrm_reset(struct vfio_platform_device *vdev)
  78{
  79        void __iomem *ring;
  80        int rc = 0, ret = 0, ring_num = 0;
  81        struct vfio_platform_region *reg = &vdev->regions[0];
  82
  83        /* Map FlexRM ring registers if not mapped */
  84        if (!reg->ioaddr) {
  85                reg->ioaddr = ioremap_nocache(reg->addr, reg->size);
  86                if (!reg->ioaddr)
  87                        return -ENOMEM;
  88        }
  89
  90        /* Discover and shutdown each FlexRM ring */
  91        for (ring = reg->ioaddr;
  92             ring < (reg->ioaddr + reg->size); ring += RING_REGS_SIZE) {
  93                if (readl_relaxed(ring + RING_VER) == RING_VER_MAGIC) {
  94                        rc = vfio_platform_bcmflexrm_shutdown(ring);
  95                        if (rc) {
  96                                dev_warn(vdev->device,
  97                                         "FlexRM ring%d shutdown error %d\n",
  98                                         ring_num, rc);
  99                                ret |= rc;
 100                        }
 101                        ring_num++;
 102                }
 103        }
 104
 105        return ret;
 106}
 107
 108module_vfio_reset_handler("brcm,iproc-flexrm-mbox",
 109                          vfio_platform_bcmflexrm_reset);
 110
 111MODULE_LICENSE("GPL v2");
 112MODULE_AUTHOR("Anup Patel <anup.patel@broadcom.com>");
 113MODULE_DESCRIPTION("Reset support for Broadcom FlexRM VFIO platform device");
 114