diff --git a/MAINTAINERS b/MAINTAINERS
index 3cd402b34..7c2d7ff1b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1099,6 +1099,13 @@ F: drivers/crypto/zuc/
 F: doc/guides/cryptodevs/zuc.rst
 F: doc/guides/cryptodevs/features/zuc.ini
 
+Broadcom FlexSparc
+M: Vikas Gupta  <vikas.gupta@@broadcom.com>
+M: Raveendra Padasalagi <raveendra.padasalagi@broadcom.com>
+M: Ajit Khaparde <ajit.khaparde@broadcom.com>
+F: drivers/crypto/bcmfs/
+F: doc/guides/cryptodevs/bcmfs.rst
+F: doc/guides/cryptodevs/features/bcmfs.ini
 
 Compression Drivers
 -------------------
diff --git a/config/common_base b/config/common_base
index f7a8824f5..21daadcdd 100644
--- a/config/common_base
+++ b/config/common_base
@@ -705,6 +705,11 @@ CONFIG_RTE_LIBRTE_PMD_MVSAM_CRYPTO=n
 #
 CONFIG_RTE_LIBRTE_PMD_NITROX=y
 
+#
+# Compile PMD for Broadcom crypto device
+#
+CONFIG_RTE_LIBRTE_PMD_BCMFS=y
+
 #
 # Compile generic security library
 #
diff --git a/doc/guides/cryptodevs/bcmfs.rst b/doc/guides/cryptodevs/bcmfs.rst
new file mode 100644
index 000000000..752ce028a
--- /dev/null
+++ b/doc/guides/cryptodevs/bcmfs.rst
@@ -0,0 +1,26 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(C) 2020 Broadcom
+
+Broadcom FlexSparc Crypto Poll Mode Driver
+==========================================
+
+The FlexSparc crypto poll mode driver provides support for offloading
+cryptographic operations to the Broadcom SoCs having FlexSparc4/FlexSparc5 unit.
+Detailed information about SoCs can be found in
+
+* https://www.broadcom.com/
+
+Installation
+------------
+
+For compiling the Broadcom FlexSparc crypto PMD, please check if the
+CONFIG_RTE_LIBRTE_PMD_BCMFS setting is set to `y` in config/common_base file.
+
+* ``CONFIG_RTE_LIBRTE_PMD_BCMFS=y``
+
+Initialization
+--------------
+BCMFS crypto PMD depend upon the devices present in the path
+/sys/bus/platform/devices/fs<version>/<dev_name> on the platform.
+Each cryptodev PMD instance can be attached to the nodes present
+in the mentioned path.
diff --git a/doc/guides/cryptodevs/index.rst b/doc/guides/cryptodevs/index.rst
index a67ed5a28..5d7e028bd 100644
--- a/doc/guides/cryptodevs/index.rst
+++ b/doc/guides/cryptodevs/index.rst
@@ -29,3 +29,4 @@ Crypto Device Drivers
     qat
     virtio
     zuc
+    bcmfs
diff --git a/drivers/crypto/bcmfs/Makefile b/drivers/crypto/bcmfs/Makefile
new file mode 100644
index 000000000..781ee6efa
--- /dev/null
+++ b/drivers/crypto/bcmfs/Makefile
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(C) 2020 Broadcom
+# All rights reserved.
+#
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_bcmfs.a
+
+CFLAGS += $(WERROR_FLAGS)
+CFLAGS += -I$(RTE_SDK)/drivers/crypto/bcmfs
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-y += bcmfs_logs.c
+SRCS-y += bcmfs_device.c
+
+LDLIBS += -lrte_eal -lrte_bus_vdev
+
+EXPORT_MAP := rte_pmd_bcmfs_version.map
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/crypto/bcmfs/bcmfs_device.c b/drivers/crypto/bcmfs/bcmfs_device.c
new file mode 100644
index 000000000..47c776de6
--- /dev/null
+++ b/drivers/crypto/bcmfs/bcmfs_device.c
@@ -0,0 +1,256 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Broadcom.
+ * All rights reserved.
+ */
+
+#include <dirent.h>
+#include <stdbool.h>
+#include <sys/queue.h>
+
+#include <rte_string_fns.h>
+
+#include "bcmfs_device.h"
+#include "bcmfs_logs.h"
+
+struct bcmfs_device_attr {
+	const char name[BCMFS_MAX_PATH_LEN];
+	const char suffix[BCMFS_DEV_NAME_LEN];
+	const enum bcmfs_device_type type;
+	const uint32_t offset;
+	const uint32_t version;
+};
+
+/* BCMFS supported devices */
+static struct bcmfs_device_attr dev_table[] = {
+	{
+		.name = "fs4",
+		.suffix = "crypto_mbox",
+		.type = BCMFS_SYM_FS4,
+		.offset = 0,
+		.version = 0x76303031
+	},
+	{
+		.name = "fs5",
+		.suffix = "mbox",
+		.type = BCMFS_SYM_FS5,
+		.offset = 0,
+		.version = 0x76303032
+	},
+	{
+		/* sentinel */
+	}
+};
+
+TAILQ_HEAD(fsdev_list, bcmfs_device);
+static struct fsdev_list fsdev_list = TAILQ_HEAD_INITIALIZER(fsdev_list);
+
+static struct bcmfs_device *
+fsdev_allocate_one_dev(struct rte_vdev_device *vdev,
+		       char *dirpath,
+		       char *devname,
+		       enum bcmfs_device_type dev_type __rte_unused)
+{
+	struct bcmfs_device *fsdev;
+
+	fsdev = calloc(1, sizeof(*fsdev));
+	if (!fsdev)
+		return NULL;
+
+	if (strlen(dirpath) > sizeof(fsdev->dirname)) {
+		BCMFS_LOG(ERR, "dir path name is too long");
+		goto cleanup;
+	}
+
+	if (strlen(devname) > sizeof(fsdev->name)) {
+		BCMFS_LOG(ERR, "devname is too long");
+		goto cleanup;
+	}
+
+	strcpy(fsdev->dirname, dirpath);
+	strcpy(fsdev->name, devname);
+
+	fsdev->vdev = vdev;
+
+	TAILQ_INSERT_TAIL(&fsdev_list, fsdev, next);
+
+	return fsdev;
+
+cleanup:
+	free(fsdev);
+
+	return NULL;
+}
+
+static struct bcmfs_device *
+find_fsdev(struct rte_vdev_device *vdev)
+{
+	struct bcmfs_device *fsdev;
+
+	TAILQ_FOREACH(fsdev, &fsdev_list, next)
+		if (fsdev->vdev == vdev)
+			return fsdev;
+
+	return NULL;
+}
+
+static void
+fsdev_release(struct bcmfs_device *fsdev)
+{
+	if (fsdev == NULL)
+		return;
+
+	TAILQ_REMOVE(&fsdev_list, fsdev, next);
+	free(fsdev);
+}
+
+static int
+cmprator(const void *a, const void *b)
+{
+	return (*(const unsigned int *)a - *(const unsigned int *)b);
+}
+
+static int
+fsdev_find_all_devs(const char *path, const char *search,
+		    uint32_t *devs)
+{
+	DIR *dir;
+	struct dirent *entry;
+	int count = 0;
+	char addr[BCMFS_MAX_NODES][BCMFS_MAX_PATH_LEN];
+	int i;
+
+	dir = opendir(path);
+	if (dir == NULL) {
+		BCMFS_LOG(ERR, "Unable to open directory");
+		return 0;
+	}
+
+	while ((entry = readdir(dir)) != NULL) {
+		if (strstr(entry->d_name, search)) {
+			strlcpy(addr[count], entry->d_name,
+				BCMFS_MAX_PATH_LEN);
+			count++;
+		}
+	}
+
+	closedir(dir);
+
+	for (i = 0 ; i < count; i++)
+		devs[i] = (uint32_t)strtoul(addr[i], NULL, 16);
+	/* sort the devices based on IO addresses */
+	qsort(devs, count, sizeof(uint32_t), cmprator);
+
+	return count;
+}
+
+static bool
+fsdev_find_sub_dir(char *path, const char *search, char *output)
+{
+	DIR *dir;
+	struct dirent *entry;
+
+	dir = opendir(path);
+	if (dir == NULL) {
+		BCMFS_LOG(ERR, "Unable to open directory");
+		return -ENODEV;
+	}
+
+	while ((entry = readdir(dir)) != NULL) {
+		if (!strcmp(entry->d_name, search)) {
+			strlcpy(output, entry->d_name, BCMFS_MAX_PATH_LEN);
+			closedir(dir);
+			return true;
+		}
+	}
+
+	closedir(dir);
+
+	return false;
+}
+
+
+static int
+bcmfs_vdev_probe(struct rte_vdev_device *vdev)
+{
+	struct bcmfs_device *fsdev;
+	char top_dirpath[BCMFS_MAX_PATH_LEN];
+	char sub_dirpath[BCMFS_MAX_PATH_LEN];
+	char out_dirpath[BCMFS_MAX_PATH_LEN];
+	char out_dirname[BCMFS_MAX_PATH_LEN];
+	uint32_t fsdev_dev[BCMFS_MAX_NODES];
+	enum bcmfs_device_type dtype;
+	int i = 0;
+	int dev_idx;
+	int count = 0;
+	bool found = false;
+
+	sprintf(top_dirpath, "%s", SYSFS_BCM_PLTFORM_DEVICES);
+	while (strlen(dev_table[i].name)) {
+		found = fsdev_find_sub_dir(top_dirpath,
+					   dev_table[i].name,
+					   sub_dirpath);
+		if (found)
+			break;
+		i++;
+	}
+	if (!found) {
+		BCMFS_LOG(ERR, "No supported bcmfs dev found");
+		return -ENODEV;
+	}
+
+	dev_idx = i;
+	dtype = dev_table[i].type;
+
+	snprintf(out_dirpath, sizeof(out_dirpath), "%s/%s",
+		 top_dirpath, sub_dirpath);
+	count = fsdev_find_all_devs(out_dirpath,
+				    dev_table[dev_idx].suffix,
+				    fsdev_dev);
+	if (!count) {
+		BCMFS_LOG(ERR, "No supported bcmfs dev found");
+		return -ENODEV;
+	}
+
+	i = 0;
+	while (count) {
+		/* format the device name present in the patch */
+		snprintf(out_dirname, sizeof(out_dirname), "%x.%s",
+			 fsdev_dev[i], dev_table[dev_idx].suffix);
+		fsdev = fsdev_allocate_one_dev(vdev, out_dirpath,
+					       out_dirname, dtype);
+		if (!fsdev) {
+			count--;
+			i++;
+			continue;
+		}
+		break;
+	}
+	if (fsdev == NULL) {
+		BCMFS_LOG(ERR, "All supported devs busy");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int
+bcmfs_vdev_remove(struct rte_vdev_device *vdev)
+{
+	struct bcmfs_device *fsdev;
+
+	fsdev = find_fsdev(vdev);
+	if (fsdev == NULL)
+		return -ENODEV;
+
+	fsdev_release(fsdev);
+	return 0;
+}
+
+/* Register with vdev */
+static struct rte_vdev_driver rte_bcmfs_pmd = {
+	.probe = bcmfs_vdev_probe,
+	.remove = bcmfs_vdev_remove
+};
+
+RTE_PMD_REGISTER_VDEV(bcmfs_pmd,
+		      rte_bcmfs_pmd);
diff --git a/drivers/crypto/bcmfs/bcmfs_device.h b/drivers/crypto/bcmfs/bcmfs_device.h
new file mode 100644
index 000000000..4b0c6d3ca
--- /dev/null
+++ b/drivers/crypto/bcmfs/bcmfs_device.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Broadcom.
+ * All rights reserved.
+ */
+
+#ifndef _BCMFS_DEV_H_
+#define _BCMFS_DEV_H_
+
+#include <sys/queue.h>
+
+#include <rte_bus_vdev.h>
+
+#include "bcmfs_logs.h"
+
+/* max number of dev nodes */
+#define BCMFS_MAX_NODES		4
+#define BCMFS_MAX_PATH_LEN	512
+#define BCMFS_DEV_NAME_LEN	64
+
+/* Path for BCM-Platform device directory */
+#define SYSFS_BCM_PLTFORM_DEVICES    "/sys/bus/platform/devices"
+
+/* Supported devices */
+enum bcmfs_device_type {
+	BCMFS_SYM_FS4,
+	BCMFS_SYM_FS5,
+	BCMFS_UNKNOWN
+};
+
+struct bcmfs_device {
+	TAILQ_ENTRY(bcmfs_device) next;
+	/* Directoy path for vfio */
+	char dirname[BCMFS_MAX_PATH_LEN];
+	/* BCMFS device name */
+	char name[BCMFS_DEV_NAME_LEN];
+	/* Parent vdev */
+	struct rte_vdev_device *vdev;
+};
+
+#endif /* _BCMFS_DEV_H_ */
diff --git a/drivers/crypto/bcmfs/bcmfs_logs.c b/drivers/crypto/bcmfs/bcmfs_logs.c
new file mode 100644
index 000000000..86f4ff3b5
--- /dev/null
+++ b/drivers/crypto/bcmfs/bcmfs_logs.c
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Broadcom
+ * All rights reserved.
+ */
+
+#include <rte_log.h>
+#include <rte_hexdump.h>
+
+#include "bcmfs_logs.h"
+
+int bcmfs_conf_logtype;
+int bcmfs_dp_logtype;
+
+int
+bcmfs_hexdump_log(uint32_t level, uint32_t logtype, const char *title,
+		const void *buf, unsigned int len)
+{
+	if (level > rte_log_get_global_level())
+		return 0;
+	if (level > (uint32_t)(rte_log_get_level(logtype)))
+		return 0;
+
+	rte_hexdump(rte_log_get_stream(), title, buf, len);
+	return 0;
+}
+
+RTE_INIT(bcmfs_device_init_log)
+{
+	/* Configuration and general logs */
+	bcmfs_conf_logtype = rte_log_register("pmd.bcmfs_config");
+	if (bcmfs_conf_logtype >= 0)
+		rte_log_set_level(bcmfs_conf_logtype, RTE_LOG_NOTICE);
+
+	/* data-path logs */
+	bcmfs_dp_logtype = rte_log_register("pmd.bcmfs_fp");
+	if (bcmfs_dp_logtype >= 0)
+		rte_log_set_level(bcmfs_dp_logtype, RTE_LOG_NOTICE);
+}
diff --git a/drivers/crypto/bcmfs/bcmfs_logs.h b/drivers/crypto/bcmfs/bcmfs_logs.h
new file mode 100644
index 000000000..c03a49b75
--- /dev/null
+++ b/drivers/crypto/bcmfs/bcmfs_logs.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Broadcom
+ * All rights reserved.
+ */
+
+#ifndef _BCMFS_LOGS_H_
+#define _BCMFS_LOGS_H_
+
+#include <rte_log.h>
+
+extern int bcmfs_conf_logtype;
+extern int bcmfs_dp_logtype;
+
+#define BCMFS_LOG(level, fmt, args...)		\
+	rte_log(RTE_LOG_ ## level, bcmfs_conf_logtype,		\
+		"%s(): " fmt "\n", __func__, ## args)
+
+#define BCMFS_DP_LOG(level, fmt, args...)		\
+	rte_log(RTE_LOG_ ## level, bcmfs_dp_logtype,		\
+		"%s(): " fmt "\n", __func__, ## args)
+
+#define BCMFS_DP_HEXDUMP_LOG(level, title, buf, len)	\
+	bcmfs_hexdump_log(RTE_LOG_ ## level, bcmfs_dp_logtype, title, buf, len)
+
+/**
+ * bcmfs_hexdump_log Dump out memory in a special hex dump format.
+ *
+ * The message will be sent to the stream used by the rte_log infrastructure.
+ */
+int
+bcmfs_hexdump_log(uint32_t level, uint32_t logtype, const char *heading,
+		  const void *buf, unsigned int len);
+
+#endif /* _BCMFS_LOGS_H_ */
diff --git a/drivers/crypto/bcmfs/meson.build b/drivers/crypto/bcmfs/meson.build
new file mode 100644
index 000000000..a4bdd8ee5
--- /dev/null
+++ b/drivers/crypto/bcmfs/meson.build
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(C) 2020 Broadcom
+# All rights reserved.
+#
+
+deps += ['eal', 'bus_vdev']
+sources = files(
+		'bcmfs_logs.c',
+		'bcmfs_device.c'
+		)
diff --git a/drivers/crypto/bcmfs/rte_pmd_bcmfs_version.map b/drivers/crypto/bcmfs/rte_pmd_bcmfs_version.map
new file mode 100644
index 000000000..299ae632d
--- /dev/null
+++ b/drivers/crypto/bcmfs/rte_pmd_bcmfs_version.map
@@ -0,0 +1,3 @@
+DPDK_21.0 {
+	local: *;
+};
diff --git a/drivers/crypto/meson.build b/drivers/crypto/meson.build
index a2423507a..8e06d0533 100644
--- a/drivers/crypto/meson.build
+++ b/drivers/crypto/meson.build
@@ -23,7 +23,8 @@ drivers = ['aesni_gcm',
 	   'scheduler',
 	   'snow3g',
 	   'virtio',
-	   'zuc']
+	   'zuc',
+	   'bcmfs']
 
 std_deps = ['cryptodev'] # cryptodev pulls in all other needed deps
 config_flag_fmt = 'RTE_LIBRTE_@0@_PMD'
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 0ce8cf541..5e268f8c0 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -308,6 +308,7 @@ ifeq ($(CONFIG_RTE_LIBRTE_SECURITY),y)
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_CAAM_JR)   += -lrte_pmd_caam_jr
 endif # CONFIG_RTE_LIBRTE_SECURITY
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_VIRTIO_CRYPTO) += -lrte_pmd_virtio_crypto
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BCMFS)      += -lrte_pmd_bcmfs
 endif # CONFIG_RTE_LIBRTE_CRYPTODEV
 
 ifeq ($(CONFIG_RTE_LIBRTE_COMPRESSDEV),y)
