diff --git a/drivers/crypto/cpt/Makefile b/drivers/crypto/cpt/Makefile
index b2d950d..40ec9e2 100644
--- a/drivers/crypto/cpt/Makefile
+++ b/drivers/crypto/cpt/Makefile
@@ -23,7 +23,14 @@ CFLAGS += -O3
 #CFLAGS += -DAUTH_SOFT_COMPUTE_IPAD_OPAD
 #CFLAGS += -DCPT_DEBUG
 
-SRCS-$(CONFIG_RTE_LIBRTE_PMD_CPT) +=
+# PMD code
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_CPT) += cpt_pmd_cryptodev.c
+
+# Base code
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_CPT) += cpt_device.c
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_CPT) += cpt_ops.c
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_CPT) += cpt8xxx_device.c
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_CPT) += cpt_vf_mbox.c
 
 # export include files
 SYMLINK-y-include +=
diff --git a/drivers/crypto/cpt/cpt_pmd_cryptodev.c b/drivers/crypto/cpt/cpt_pmd_cryptodev.c
new file mode 100644
index 0000000..addddd8
--- /dev/null
+++ b/drivers/crypto/cpt/cpt_pmd_cryptodev.c
@@ -0,0 +1,270 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#include <rte_common.h>
+#include <rte_dev.h>
+#include <rte_pci.h>
+#include <rte_crypto.h>
+#include <rte_cryptodev.h>
+#include <rte_cryptodev_pmd.h>
+#include <rte_alarm.h>
+#include <rte_bus_pci.h>
+
+#include "base/cpt_device.h"
+#include "cpt_pmd_logs.h"
+
+#define CSP_INTR_POLL_INTERVAL_MS 50
+
+static int global_init_done;
+uint8_t cryptodev_cpt_driver_id;
+struct rte_mempool *cpt_meta_pool;
+int cpt_op_mlen;
+int cpt_op_sb_mlen;
+
+static void
+cpt_pmd_alarm_cb(void *arg)
+{
+	struct cpt_vf *cptvf = arg;
+	cptvf_poll_misc(cptvf);
+	rte_eal_alarm_set(CSP_INTR_POLL_INTERVAL_MS * 1000,
+			  cpt_pmd_alarm_cb, cptvf);
+}
+
+static int
+cpt_pmd_periodic_alarm_start(void *arg)
+{
+	return rte_eal_alarm_set(CSP_INTR_POLL_INTERVAL_MS * 1000,
+				 cpt_pmd_alarm_cb, arg);
+}
+
+static int
+cpt_pmd_periodic_alarm_stop(void *arg)
+{
+	return rte_eal_alarm_cancel(cpt_pmd_alarm_cb, arg);
+}
+
+static struct rte_cryptodev_ops cptvf_ops = {
+	/* Device related operations */
+	.dev_configure = NULL,
+	.dev_start = NULL,
+	.dev_stop = NULL,
+	.dev_close = NULL,
+	.dev_infos_get = NULL,
+
+	.stats_get = NULL,
+	.stats_reset = NULL,
+	.queue_pair_setup = NULL,
+	.queue_pair_release = NULL,
+	.queue_pair_start = NULL,
+	.queue_pair_stop = NULL,
+	.queue_pair_count = NULL,
+
+	/* Crypto related operations */
+	.session_get_size = NULL,
+	.session_configure = NULL,
+	.session_clear = NULL
+};
+
+static int init_global_resources(void)
+{
+	/* In future consider rte_security and asym. 4B extra for app use */
+	cpt_op_mlen = cpt_fc_get_op_meta_len() + 4 * sizeof(uint64_t);
+	cpt_meta_pool = rte_mempool_create("cpt_metabuf-pool", 4096 * 16,
+					   cpt_op_mlen, 512, 0,
+					   NULL, NULL, NULL, NULL,
+					   SOCKET_ID_ANY, 0);
+	if (!cpt_meta_pool) {
+		PMD_DRV_LOG(ERR, "cpt metabuf pool not created\n");
+		return -ENOMEM;
+	}
+	cpt_op_sb_mlen = cpt_fc_get_op_sb_meta_len() + 4 * sizeof(uint64_t);
+
+	return 0;
+}
+
+static int
+cptvf_dev_init(struct rte_pci_driver *c_drv __rte_unused,
+		 struct rte_cryptodev *c_dev)
+{
+	struct rte_pci_device *pdev = RTE_DEV_TO_PCI(c_dev->device);
+	struct cpt_vf *cptvf = c_dev->data->dev_private;
+	void *reg_base;
+	char dev_name[32];
+	int ret;
+
+	PMD_DRV_LOG(DEBUG, ">>>");
+
+	if (pdev->mem_resource[0].phys_addr == 0ULL)
+		return -EIO;
+
+	/* for secondary processes, we don't initialise any further as primary
+	 * has already done this work.
+	 */
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return 0;
+
+	snprintf(dev_name, 32, "%02x:%02x.%x",
+			pdev->addr.bus, pdev->addr.devid, pdev->addr.function);
+	PMD_DRV_LOG(DEBUG, "Found CPT device %s", dev_name);
+
+	reg_base = pdev->mem_resource[0].addr;
+	if (!reg_base) {
+		PMD_DRV_LOG(ERR, "Failed to map BAR0 of %s", dev_name);
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	ret = cptvf_init_device(cptvf, pdev, reg_base, dev_name, 0);
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Failed to init cptvf %s", dev_name);
+		return -EIO;
+	}
+
+	/* Start off timer for mailbox interrupts */
+	cpt_pmd_periodic_alarm_start(cptvf);
+	/* TODO Do we really need this to poll for mbox ?? */
+	/* cptvf_enable_mbox_interrupts(cptvf); */
+
+	if (!global_init_done) {
+		/* cpt_set_debug_level(debug); */
+		ret = init_global_resources();
+		if (ret)
+			goto init_fail;
+		global_init_done = 1;
+	}
+
+	c_dev->dev_ops = &cptvf_ops;
+
+	c_dev->enqueue_burst = NULL;
+	c_dev->dequeue_burst = NULL;
+
+	c_dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_HW_ACCELERATED |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
+
+	return 0;
+
+init_fail:
+	cpt_pmd_periodic_alarm_stop(cptvf);
+	cptvf_deinit_device(cptvf);
+	return ret;
+
+fail:
+	return ret;
+}
+
+static int
+rte_cptdev_pci_probe(struct rte_pci_driver *pci_drv,
+			struct rte_pci_device *pci_dev)
+{
+	struct rte_cryptodev *cryptodev;
+
+	char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
+
+	int retval;
+
+	if (pci_drv == NULL)
+		return -ENODEV;
+
+	rte_pci_device_name(&pci_dev->addr, cryptodev_name,
+			sizeof(cryptodev_name));
+
+	cryptodev = rte_cryptodev_pmd_allocate(cryptodev_name, rte_socket_id());
+	if (cryptodev == NULL)
+		return -ENOMEM;
+
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		cryptodev->data->dev_private =
+				rte_zmalloc_socket(
+						"cryptodev private structure",
+						sizeof(struct cpt_vf),
+						RTE_CACHE_LINE_SIZE,
+						rte_socket_id());
+
+		if (cryptodev->data->dev_private == NULL)
+			rte_panic("Cannot allocate memzone for private "
+					"device data");
+	}
+
+	cryptodev->device = &pci_dev->device;
+	cryptodev->device->driver = &pci_drv->driver;
+	cryptodev->driver_id = cryptodev_cpt_driver_id;
+
+	/* init user callbacks */
+	TAILQ_INIT(&(cryptodev->link_intr_cbs));
+
+	/* Invoke PMD device initialization function */
+	retval = cptvf_dev_init(pci_drv, cryptodev);
+	if (retval == 0)
+		return 0;
+
+	PMD_DRV_LOG(ERR, "driver %s: crypto_dev_init(vendor_id=0x%x device_id="
+			"0x%x) failed", pci_drv->driver.name,
+			(unsigned int) pci_dev->id.vendor_id,
+			(unsigned int) pci_dev->id.device_id);
+
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+		rte_free(cryptodev->data->dev_private);
+
+	cryptodev->attached = RTE_CRYPTODEV_DETACHED;
+
+	return -ENXIO;
+}
+
+static int
+rte_cptdev_pci_remove(struct rte_pci_device *pci_dev)
+{
+	struct rte_cryptodev *cryptodev;
+	char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
+
+	if (pci_dev == NULL)
+		return -EINVAL;
+
+	rte_pci_device_name(&pci_dev->addr, cryptodev_name,
+			sizeof(cryptodev_name));
+
+	cryptodev = rte_cryptodev_pmd_get_named_dev(cryptodev_name);
+	if (cryptodev == NULL)
+		return -ENODEV;
+
+	if (pci_dev->driver == NULL)
+		return -ENODEV;
+
+	/* free crypto device */
+	rte_cryptodev_pmd_release_device(cryptodev);
+
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+		rte_free(cryptodev->data->dev_private);
+
+	cryptodev->device = NULL;
+	cryptodev->device->driver = NULL;
+	cryptodev->data = NULL;
+
+	return 0;
+}
+static struct rte_pci_id pci_id_cpt_table[] = {
+	{
+		RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, CPT_81XX_PCI_VF_DEVICE_ID),
+	},
+	/* sentinel */
+	{
+	.device_id = 0
+	},
+};
+
+static struct rte_pci_driver cptvf_pmd = {
+		.id_table = pci_id_cpt_table,
+		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
+		.probe = rte_cptdev_pci_probe,
+		.remove = rte_cptdev_pci_remove,
+};
+static struct cryptodev_driver cpt_crypto_drv;
+
+#define CRYPTODEV_NAME_CPT_SYM_PMD	crypto_cpt
+/* Cavium CPT Symmetric Crypto PMD device name */
+
+RTE_PMD_REGISTER_PCI(CRYPTODEV_NAME_CPT_SYM_PMD, cptvf_pmd);
+RTE_PMD_REGISTER_PCI_TABLE(CRYPTODEV_NAME_CPT_SYM_PMD, pci_id_cpt_table);
+RTE_PMD_REGISTER_CRYPTO_DRIVER(cpt_crypto_drv, cptvf_pmd.driver,
+		cryptodev_cpt_driver_id);
diff --git a/drivers/crypto/cpt/cpt_pmd_logs.h b/drivers/crypto/cpt/cpt_pmd_logs.h
new file mode 100644
index 0000000..d245d62
--- /dev/null
+++ b/drivers/crypto/cpt/cpt_pmd_logs.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#ifndef _CPT_PMD_LOGS_H_
+#define _CPT_PMD_LOGS_H_
+
+#include <rte_log.h>
+
+#define PMD_DRV_LOG_RAW(level, fmt, args...) \
+		rte_log(RTE_LOG_ ## level, RTE_LOGTYPE_PMD, \
+			"PMD: %s(): " fmt "\n", __func__, ##args)
+
+#ifdef RTE_LIBRTE_PMD_CPT_DEBUG_INIT
+
+#define PMD_INIT_FUNC_TRACE() PMD_DRV_LOG_RAW(DEBUG, " >>")
+#define PMD_DRV_LOG(level, args...) \
+	PMD_DRV_LOG_RAW(level, ##args)
+#else
+
+#define PMD_DRV_LOG(...)  do { } while (0)
+#define PMD_INIT_FUNC_TRACE() do { } while (0)
+#endif
+
+#ifdef RTE_LIBRTE_PMD_CPT_DEBUG_RX
+
+#define CPT_DEBUG
+#define CPTVF_STRICT_PARAM_CHECK
+#define PMD_RX_LOG(level, args...) \
+	PMD_DRV_LOG_RAW(level, ##args)
+#else
+
+#define PMD_RX_LOG(...)  do { } while (0)
+#endif
+
+#ifdef RTE_LIBRTE_PMD_CPT_DEBUG_TX
+
+#define CPT_DEBUG
+#define CPTVF_STRICT_PARAM_CHECK
+
+#define PMD_TX_LOG(level, args...) \
+	PMD_DRV_LOG_RAW(level, ##args)
+#else
+
+#define PMD_TX_LOG(...)  do { } while (0)
+#endif
+
+#define PRINT printf
+
+#endif
