Commit e2588341 authored by Anup Patel's avatar Anup Patel Committed by Alex Williamson
Browse files

vfio: platform: reset: Add Broadcom FlexRM reset module



This patch adds Broadcom FlexRM low-level reset for
VFIO platform.

It will do the following:
1. Disable/Deactivate each FlexRM ring
2. Flush each FlexRM ring

The cleanup sequence for FlexRM rings is adapted from
Broadcom FlexRM mailbox driver.

Signed-off-by: default avatarAnup Patel <anup.patel@broadcom.com>
Reviewed-by: default avatarOza Oza <oza.oza@broadcom.com>
Reviewed-by: default avatarScott Branden <scott.branden@broadcom.com>
Reviewed-by: default avatarEric Auger <eric.auger@redhat.com>
Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent 79d40370
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -13,3 +13,12 @@ config VFIO_PLATFORM_AMDXGBE_RESET
	  Enables the VFIO platform driver to handle reset for AMD XGBE
	  Enables the VFIO platform driver to handle reset for AMD XGBE


	  If you don't know what to do here, say N.
	  If you don't know what to do here, say N.

config VFIO_PLATFORM_BCMFLEXRM_RESET
	tristate "VFIO support for Broadcom FlexRM reset"
	depends on VFIO_PLATFORM && (ARCH_BCM_IPROC || COMPILE_TEST)
	default ARCH_BCM_IPROC
	help
	  Enables the VFIO platform driver to handle reset for Broadcom FlexRM

	  If you don't know what to do here, say N.
+1 −0
Original line number Original line Diff line number Diff line
@@ -5,3 +5,4 @@ ccflags-y += -Idrivers/vfio/platform


obj-$(CONFIG_VFIO_PLATFORM_CALXEDAXGMAC_RESET) += vfio-platform-calxedaxgmac.o
obj-$(CONFIG_VFIO_PLATFORM_CALXEDAXGMAC_RESET) += vfio-platform-calxedaxgmac.o
obj-$(CONFIG_VFIO_PLATFORM_AMDXGBE_RESET) += vfio-platform-amdxgbe.o
obj-$(CONFIG_VFIO_PLATFORM_AMDXGBE_RESET) += vfio-platform-amdxgbe.o
obj-$(CONFIG_VFIO_PLATFORM_BCMFLEXRM_RESET) += vfio_platform_bcmflexrm.o
+113 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2017 Broadcom
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation version 2.
 *
 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
 * kind, whether express or implied; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

/*
 * This driver provides reset support for Broadcom FlexRM ring manager
 * to VFIO platform.
 */

#include <linux/delay.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>

#include "vfio_platform_private.h"

/* FlexRM configuration */
#define RING_REGS_SIZE					0x10000
#define RING_VER_MAGIC					0x76303031

/* Per-Ring register offsets */
#define RING_VER					0x000
#define RING_CONTROL					0x034
#define RING_FLUSH_DONE					0x038

/* Register RING_CONTROL fields */
#define CONTROL_FLUSH_SHIFT				5

/* Register RING_FLUSH_DONE fields */
#define FLUSH_DONE_MASK					0x1

static int vfio_platform_bcmflexrm_shutdown(void __iomem *ring)
{
	unsigned int timeout;

	/* Disable/inactivate ring */
	writel_relaxed(0x0, ring + RING_CONTROL);

	/* Set ring flush state */
	timeout = 1000; /* timeout of 1s */
	writel_relaxed(BIT(CONTROL_FLUSH_SHIFT), ring + RING_CONTROL);
	do {
		if (readl_relaxed(ring + RING_FLUSH_DONE) &
		    FLUSH_DONE_MASK)
			break;
		mdelay(1);
	} while (--timeout);
	if (!timeout)
		return -ETIMEDOUT;

	/* Clear ring flush state */
	timeout = 1000; /* timeout of 1s */
	writel_relaxed(0x0, ring + RING_CONTROL);
	do {
		if (!(readl_relaxed(ring + RING_FLUSH_DONE) &
		      FLUSH_DONE_MASK))
			break;
		mdelay(1);
	} while (--timeout);
	if (!timeout)
		return -ETIMEDOUT;

	return 0;
}

static int vfio_platform_bcmflexrm_reset(struct vfio_platform_device *vdev)
{
	void __iomem *ring;
	int rc = 0, ret = 0, ring_num = 0;
	struct vfio_platform_region *reg = &vdev->regions[0];

	/* Map FlexRM ring registers if not mapped */
	if (!reg->ioaddr) {
		reg->ioaddr = ioremap_nocache(reg->addr, reg->size);
		if (!reg->ioaddr)
			return -ENOMEM;
	}

	/* Discover and shutdown each FlexRM ring */
	for (ring = reg->ioaddr;
	     ring < (reg->ioaddr + reg->size); ring += RING_REGS_SIZE) {
		if (readl_relaxed(ring + RING_VER) == RING_VER_MAGIC) {
			rc = vfio_platform_bcmflexrm_shutdown(ring);
			if (rc) {
				dev_warn(vdev->device,
					 "FlexRM ring%d shutdown error %d\n",
					 ring_num, rc);
				ret |= rc;
			}
			ring_num++;
		}
	}

	return ret;
}

module_vfio_reset_handler("brcm,iproc-flexrm-mbox",
			  vfio_platform_bcmflexrm_reset);

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Anup Patel <anup.patel@broadcom.com>");
MODULE_DESCRIPTION("Reset support for Broadcom FlexRM VFIO platform device");