diff --git a/config/common_base b/config/common_base
index c560b73da..812cff129 100644
--- a/config/common_base
+++ b/config/common_base
@@ -805,6 +805,13 @@ CONFIG_RTE_LIBRTE_VHOST=n
 CONFIG_RTE_LIBRTE_VHOST_NUMA=n
 CONFIG_RTE_LIBRTE_VHOST_DEBUG=n
 
+#
+# Compile raw device support
+# EXPERIMENTAL: API may change without prior notice
+#
+CONFIG_RTE_LIBRTE_RAWDEV=y
+CONFIG_RTE_RAWDEV_MAX_DEVS=10
+
 #
 # Compile vhost PMD
 # To compile, CONFIG_RTE_LIBRTE_VHOST should be enabled.
diff --git a/lib/Makefile b/lib/Makefile
index 427f34b00..97080a590 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -102,4 +102,7 @@ endif
 DEPDIRS-librte_kni := librte_eal librte_mempool librte_mbuf librte_ether
 DEPDIRS-librte_kni += librte_pci
 
+DIRS-$(CONFIG_RTE_LIBRTE_RAWDEV) += librte_rawdev
+DEPDIRS-librte_rawdev := librte_eal librte_ether
+
 include $(RTE_SDK)/mk/rte.subdir.mk
diff --git a/lib/librte_rawdev/Makefile b/lib/librte_rawdev/Makefile
new file mode 100644
index 000000000..b9105b060
--- /dev/null
+++ b/lib/librte_rawdev/Makefile
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2017 NXP
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_rawdev.a
+
+# library version
+LIBABIVER := 1
+
+# build flags
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+LDLIBS += -lrte_eal
+
+# library source files
+SRCS-y += rte_rawdev.c
+
+# export include files
+SYMLINK-y-include += rte_rawdev.h
+SYMLINK-y-include += rte_rawdev_pmd.h
+
+# versioning export map
+EXPORT_MAP := rte_rawdev_version.map
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_rawdev/rte_rawdev.c b/lib/librte_rawdev/rte_rawdev.c
new file mode 100644
index 000000000..46353a4eb
--- /dev/null
+++ b/lib/librte_rawdev/rte_rawdev.c
@@ -0,0 +1,360 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2017 NXP
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_dev.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_errno.h>
+
+#include "rte_rawdev.h"
+#include "rte_rawdev_pmd.h"
+
+/* dynamic log identifier */
+int librawdev_logtype;
+
+struct rte_rawdev rte_rawdevices[RTE_RAWDEV_MAX_DEVS];
+
+struct rte_rawdev *rte_rawdevs = &rte_rawdevices[0];
+
+static struct rte_rawdev_global rawdev_globals = {
+	.nb_devs		= 0
+};
+
+struct rte_rawdev_global *rte_rawdev_globals = &rawdev_globals;
+
+/* Raw device, northbound API implementation */
+uint8_t __rte_experimental
+rte_rawdev_count(void)
+{
+	return rte_rawdev_globals->nb_devs;
+}
+
+uint16_t __rte_experimental
+rte_rawdev_get_dev_id(const char *name)
+{
+	uint16_t i;
+
+	if (!name)
+		return -EINVAL;
+
+	for (i = 0; i < rte_rawdev_globals->nb_devs; i++)
+		if ((strcmp(rte_rawdevices[i].name, name)
+				== 0) &&
+				(rte_rawdevices[i].attached ==
+						RTE_RAWDEV_ATTACHED))
+			return i;
+	return -ENODEV;
+}
+
+int __rte_experimental
+rte_rawdev_socket_id(uint16_t dev_id)
+{
+	struct rte_rawdev *dev;
+
+	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+	dev = &rte_rawdevs[dev_id];
+
+	return dev->socket_id;
+}
+
+int __rte_experimental
+rte_rawdev_info_get(uint16_t dev_id, struct rte_rawdev_info *dev_info)
+{
+	struct rte_rawdev *rawdev;
+
+	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+	RTE_FUNC_PTR_OR_ERR_RET(dev_info, -EINVAL);
+
+	if (dev_info == NULL)
+		return -EINVAL;
+
+	rawdev = &rte_rawdevs[dev_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*rawdev->dev_ops->dev_info_get, -ENOTSUP);
+	(*rawdev->dev_ops->dev_info_get)(rawdev, dev_info->dev_private);
+
+	if (dev_info) {
+
+		dev_info->driver_name = rawdev->driver_name;
+		dev_info->device = rawdev->device;
+	}
+
+	return 0;
+}
+
+int __rte_experimental
+rte_rawdev_configure(uint16_t dev_id, struct rte_rawdev_info *dev_conf)
+{
+	struct rte_rawdev *dev;
+	int diag;
+
+	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+	RTE_FUNC_PTR_OR_ERR_RET(dev_conf, -EINVAL);
+
+	dev = &rte_rawdevs[dev_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_configure, -ENOTSUP);
+
+	if (dev->started) {
+		RTE_RDEV_ERR(
+		   "device %d must be stopped to allow configuration", dev_id);
+		return -EBUSY;
+	}
+
+	/* Configure the device */
+	diag = (*dev->dev_ops->dev_configure)(dev, dev_conf->dev_private);
+	if (diag != 0)
+		RTE_RDEV_ERR("dev%d dev_configure = %d", dev_id, diag);
+	else
+		dev->attached = 1;
+
+	return diag;
+}
+
+int __rte_experimental
+rte_rawdev_queue_conf_get(uint16_t dev_id,
+			  uint16_t queue_id,
+			  rte_rawdev_obj_t queue_conf)
+{
+	struct rte_rawdev *dev;
+
+	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+	dev = &rte_rawdevs[dev_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_def_conf, -ENOTSUP);
+	(*dev->dev_ops->queue_def_conf)(dev, queue_id, queue_conf);
+	return 0;
+}
+
+int __rte_experimental
+rte_rawdev_queue_setup(uint16_t dev_id,
+		       uint16_t queue_id,
+		       rte_rawdev_obj_t queue_conf)
+{
+	struct rte_rawdev *dev;
+
+	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+	dev = &rte_rawdevs[dev_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_setup, -ENOTSUP);
+	return (*dev->dev_ops->queue_setup)(dev, queue_id, queue_conf);
+}
+
+int __rte_experimental
+rte_rawdev_queue_release(uint16_t dev_id, uint16_t queue_id)
+{
+	struct rte_rawdev *dev;
+
+	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+	dev = &rte_rawdevs[dev_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_release, -ENOTSUP);
+	return (*dev->dev_ops->queue_release)(dev, queue_id);
+}
+
+int __rte_experimental
+rte_rawdev_dump(uint16_t dev_id, FILE *f)
+{
+	struct rte_rawdev *dev;
+
+	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+	dev = &rte_rawdevs[dev_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dump, -ENOTSUP);
+	return (*dev->dev_ops->dump)(dev, f);
+}
+
+int __rte_experimental
+rte_rawdev_start(uint16_t dev_id)
+{
+	struct rte_rawdev *dev;
+	int diag;
+
+	RTE_RDEV_DEBUG("Start dev_id=%" PRIu8, dev_id);
+
+	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+	dev = &rte_rawdevs[dev_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_start, -ENOTSUP);
+
+	if (dev->started != 0) {
+		RTE_RDEV_ERR("Device with dev_id=%" PRIu8 "already started",
+			     dev_id);
+		return 0;
+	}
+
+	diag = (*dev->dev_ops->dev_start)(dev);
+	if (diag == 0)
+		dev->started = 1;
+	else
+		return diag;
+
+	return 0;
+}
+
+void __rte_experimental
+rte_rawdev_stop(uint16_t dev_id)
+{
+	struct rte_rawdev *dev;
+
+	RTE_RDEV_DEBUG("Stop dev_id=%" PRIu8, dev_id);
+
+	RTE_RAWDEV_VALID_DEVID_OR_RET(dev_id);
+	dev = &rte_rawdevs[dev_id];
+
+	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_stop);
+
+	if (dev->started == 0) {
+		RTE_RDEV_ERR("Device with dev_id=%" PRIu8 "already stopped",
+			dev_id);
+		return;
+	}
+
+	(*dev->dev_ops->dev_stop)(dev);
+	dev->started = 0;
+}
+
+int __rte_experimental
+rte_rawdev_close(uint16_t dev_id)
+{
+	struct rte_rawdev *dev;
+
+	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+	dev = &rte_rawdevs[dev_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_close, -ENOTSUP);
+	/* Device must be stopped before it can be closed */
+	if (dev->started == 1) {
+		RTE_RDEV_ERR("Device %u must be stopped before closing",
+			     dev_id);
+		return -EBUSY;
+	}
+
+	return (*dev->dev_ops->dev_close)(dev);
+}
+
+int __rte_experimental
+rte_rawdev_reset(uint16_t dev_id)
+{
+	struct rte_rawdev *dev;
+
+	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+	dev = &rte_rawdevs[dev_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_reset, -ENOTSUP);
+	/* Reset is not dependent on state of the device */
+	return (*dev->dev_ops->dev_reset)(dev);
+}
+
+static inline uint8_t
+rte_rawdev_find_free_device_index(void)
+{
+	uint16_t dev_id;
+
+	for (dev_id = 0; dev_id < RTE_RAWDEV_MAX_DEVS; dev_id++) {
+		if (rte_rawdevs[dev_id].attached ==
+				RTE_RAWDEV_DETACHED)
+			return dev_id;
+	}
+
+	return RTE_RAWDEV_MAX_DEVS;
+}
+
+struct rte_rawdev * __rte_experimental
+rte_rawdev_pmd_allocate(const char *name, size_t dev_priv_size, int socket_id)
+{
+	struct rte_rawdev *rawdev;
+	uint16_t dev_id;
+
+	if (rte_rawdev_pmd_get_named_dev(name) != NULL) {
+		RTE_RDEV_ERR("Event device with name %s already allocated!",
+			     name);
+		return NULL;
+	}
+
+	dev_id = rte_rawdev_find_free_device_index();
+	if (dev_id == RTE_RAWDEV_MAX_DEVS) {
+		RTE_RDEV_ERR("Reached maximum number of raw devices");
+		return NULL;
+	}
+
+	rawdev = &rte_rawdevs[dev_id];
+
+	rawdev->dev_private = rte_zmalloc_socket("rawdev private",
+				     dev_priv_size,
+				     RTE_CACHE_LINE_SIZE,
+				     socket_id);
+	if (!rawdev->dev_private) {
+		RTE_RDEV_ERR("Unable to allocate memory to Skeleton dev");
+		return NULL;
+	}
+
+
+	rawdev->dev_id = dev_id;
+	rawdev->socket_id = socket_id;
+	rawdev->started = 0;
+	snprintf(rawdev->name, RTE_RAWDEV_NAME_MAX_LEN, "%s", name);
+
+	rawdev->attached = RTE_RAWDEV_ATTACHED;
+	rawdev_globals.nb_devs++;
+
+	return rawdev;
+}
+
+int __rte_experimental
+rte_rawdev_pmd_release(struct rte_rawdev *rawdev)
+{
+	int ret;
+
+	if (rawdev == NULL)
+		return -EINVAL;
+
+	ret = rte_rawdev_close(rawdev->dev_id);
+	if (ret < 0)
+		return ret;
+
+	rawdev->attached = RTE_RAWDEV_DETACHED;
+	rawdev_globals.nb_devs--;
+
+	rawdev->dev_id = 0;
+	rawdev->socket_id = 0;
+	rawdev->dev_ops = NULL;
+	if (rawdev->dev_private) {
+		rte_free(rawdev->dev_private);
+		rawdev->dev_private = NULL;
+	}
+
+	return 0;
+}
+
+RTE_INIT(librawdev_init_log);
+
+static void
+librawdev_init_log(void)
+{
+	librawdev_logtype = rte_log_register("lib.rawdev");
+	if (librawdev_logtype >= 0)
+		rte_log_set_level(librawdev_logtype, RTE_LOG_INFO);
+}
diff --git a/lib/librte_rawdev/rte_rawdev.h b/lib/librte_rawdev/rte_rawdev.h
new file mode 100644
index 000000000..e13b11400
--- /dev/null
+++ b/lib/librte_rawdev/rte_rawdev.h
@@ -0,0 +1,314 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2017 NXP
+ */
+
+#ifndef _RTE_RAWDEV_H_
+#define _RTE_RAWDEV_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_common.h>
+#include <rte_memory.h>
+#include <rte_errno.h>
+
+/* Rawdevice object - essentially a void to be typecasted by implementation */
+typedef void *rte_rawdev_obj_t;
+
+/**
+ * Get the total number of raw devices that have been successfully
+ * initialised.
+ *
+ * @return
+ *   The total number of usable raw devices.
+ */
+uint8_t __rte_experimental
+rte_rawdev_count(void);
+
+/**
+ * Get the device identifier for the named raw device.
+ *
+ * @param name
+ *   Raw device name to select the raw device identifier.
+ *
+ * @return
+ *   Returns raw device identifier on success.
+ *   - <0: Failure to find named raw device.
+ */
+uint16_t __rte_experimental
+rte_rawdev_get_dev_id(const char *name);
+
+/**
+ * Return the NUMA socket to which a device is connected.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @return
+ *   The NUMA socket id to which the device is connected or
+ *   a default of zero if the socket could not be determined.
+ *   -(-EINVAL)  dev_id value is out of range.
+ */
+int __rte_experimental
+rte_rawdev_socket_id(uint16_t dev_id);
+
+/**
+ * Raw device information forward declaration
+ */
+struct rte_rawdev_info;
+
+/**
+ * Retrieve the contextual information of a raw device.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ *
+ * @param[out] dev_info
+ *   A pointer to a structure of type *rte_rawdev_info* to be filled with the
+ *   contextual information of the device.
+ *
+ * @return
+ *   - 0: Success, driver updates the contextual information of the raw device
+ *   - <0: Error code returned by the driver info get function.
+ *
+ */
+int __rte_experimental
+rte_rawdev_info_get(uint16_t dev_id, struct rte_rawdev_info *dev_info);
+
+/**
+ * Configure a raw device.
+ *
+ * This function must be invoked first before any other function in the
+ * API. This function can also be re-invoked when a device is in the
+ * stopped state.
+ *
+ * The caller may use rte_rawdev_info_get() to get the capability of each
+ * resources available for this raw device.
+ *
+ * @param dev_id
+ *   The identifier of the device to configure.
+ * @param dev_conf
+ *   The raw device configuration structure encapsulated into rte_rawdev_info
+ *   object.
+ *   It is assumed that the opaque object has enough information which the
+ *   driver/implementation can use to configure the device. It is also assumed
+ *   that once the configuration is done, a `queue_id` type field can be used
+ *   to refer to some arbitrary internal representation of a queue.
+ *
+ * @return
+ *   - 0: Success, device configured.
+ *   - <0: Error code returned by the driver configuration function.
+ */
+int __rte_experimental
+rte_rawdev_configure(uint16_t dev_id, struct rte_rawdev_info *dev_conf);
+
+
+/**
+ * Retrieve the current configuration information of a raw queue designated
+ * by its *queue_id* from the raw driver for a raw device.
+ *
+ * This function intended to be used in conjunction with rte_raw_queue_setup()
+ * where caller needs to set up the queue by overriding few default values.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param queue_id
+ *   The index of the raw queue to get the configuration information.
+ *   The value must be in the range [0, nb_raw_queues - 1]
+ *   previously supplied to rte_rawdev_configure().
+ * @param[out] queue_conf
+ *   The pointer to the default raw queue configuration data.
+ * @return
+ *   - 0: Success, driver updates the default raw queue configuration data.
+ *   - <0: Error code returned by the driver info get function.
+ *
+ * @see rte_raw_queue_setup()
+ *
+ */
+int __rte_experimental
+rte_rawdev_queue_conf_get(uint16_t dev_id,
+			  uint16_t queue_id,
+			  rte_rawdev_obj_t queue_conf);
+
+/**
+ * Allocate and set up a raw queue for a raw device.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param queue_id
+ *   The index of the raw queue to setup. The value must be in the range
+ *   [0, nb_raw_queues - 1] previously supplied to rte_rawdev_configure().
+ * @param queue_conf
+ *   The pointer to the configuration data to be used for the raw queue.
+ *   NULL value is allowed, in which case default configuration	used.
+ *
+ * @see rte_rawdev_queue_conf_get()
+ *
+ * @return
+ *   - 0: Success, raw queue correctly set up.
+ *   - <0: raw queue configuration failed
+ */
+int __rte_experimental
+rte_rawdev_queue_setup(uint16_t dev_id,
+		       uint16_t queue_id,
+		       rte_rawdev_obj_t queue_conf);
+
+/**
+ * Release and deallocate a raw queue from a raw device.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param queue_id
+ *   The index of the raw queue to release. The value must be in the range
+ *   [0, nb_raw_queues - 1] previously supplied to rte_rawdev_configure().
+ *
+ * @see rte_rawdev_queue_conf_get()
+ *
+ * @return
+ *   - 0: Success, raw queue released.
+ *   - <0: raw queue configuration failed
+ */
+int __rte_experimental
+rte_rawdev_queue_release(uint16_t dev_id, uint16_t queue_id);
+/**
+ * Get the number of raw queues on a specific raw device
+ *
+ * @param dev_id
+ *   Raw device identifier.
+ * @return
+ *   - The number of configured raw queues
+ */
+uint16_t __rte_experimental
+rte_rawdev_queue_count(uint16_t dev_id);
+
+/**
+ * Start a raw device.
+ *
+ * The device start step is the last one and consists of setting the raw
+ * queues to start accepting the raws and schedules to raw ports.
+ *
+ * On success, all basic functions exported by the API (raw enqueue,
+ * raw dequeue and so on) can be invoked.
+ *
+ * @param dev_id
+ *   Raw device identifier
+ * @return
+ *   - 0: Success, device started.
+ *   < 0: Failure
+ */
+int __rte_experimental
+rte_rawdev_start(uint16_t dev_id);
+
+/**
+ * Stop a raw device. The device can be restarted with a call to
+ * rte_rawdev_start()
+ *
+ * @param dev_id
+ *   Raw device identifier.
+ */
+void __rte_experimental
+rte_rawdev_stop(uint16_t dev_id);
+
+/**
+ * Close a raw device. The device cannot be restarted after this call.
+ *
+ * @param dev_id
+ *   Raw device identifier
+ *
+ * @return
+ *  - 0 on successfully closing device
+ *  - <0 on failure to close device
+ *  - (-EAGAIN) if device is busy
+ */
+int __rte_experimental
+rte_rawdev_close(uint16_t dev_id);
+
+/**
+ * Reset a raw device.
+ * This is different from cycle of rte_rawdev_start->rte_rawdev_stop in the
+ * sense similar to hard or soft reset.
+ *
+ * @param dev_id
+ *   Raw device identifiers
+ * @return
+ *   0 for sucessful reset,
+ *  !0 for failure in resetting
+ */
+int __rte_experimental
+rte_rawdev_reset(uint16_t dev_id);
+
+#define RTE_RAWDEV_NAME_MAX_LEN	(64)
+/**< @internal Max length of name of raw PMD */
+
+
+
+/** @internal
+ * The data structure associated with each raw device.
+ * It is a placeholder for PMD specific data, encapsulating only information
+ * related to framework.
+ */
+struct rte_rawdev {
+	/**< Socket ID where memory is allocated */
+	int socket_id;
+	/**< Device ID for this instance */
+	uint16_t dev_id;
+	/**< Functions exported by PMD */
+	const struct rte_rawdev_ops *dev_ops;
+	/**< Device info. supplied during device initialization */
+	struct rte_device *device;
+	/**< Driver info. supplied by probing */
+	const char *driver_name;
+
+	RTE_STD_C11
+	/**< Flag indicating the device is attached */
+	uint8_t attached : 1;
+	/**< Device state: STARTED(1)/STOPPED(0) */
+	uint8_t started : 1;
+
+	/**< PMD-specific private data */
+	rte_rawdev_obj_t dev_private;
+	/**< Device name */
+	char name[RTE_RAWDEV_NAME_MAX_LEN];
+} __rte_cache_aligned;
+
+/** @internal The pool of rte_rawdev structures. */
+extern struct rte_rawdev *rte_rawdevs;
+
+
+struct rte_rawdev_info {
+	/**< Name of driver handling this device */
+	const char *driver_name;
+	/**< Device encapsulation */
+	struct rte_device *device;
+	/**< Socket ID where memory is allocated */
+	int socket_id;
+	/**< PMD-specific private data */
+	rte_rawdev_obj_t dev_private;
+};
+
+struct rte_rawdev_buf {
+	/**< Opaque buffer reference */
+	void *buf_addr;
+};
+
+/**
+ * Dump internal information about *dev_id* to the FILE* provided in *f*.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ *
+ * @param f
+ *   A pointer to a file for output
+ *
+ * @return
+ *   - 0: on success
+ *   - <0: on failure.
+ */
+int __rte_experimental
+rte_rawdev_dump(uint16_t dev_id, FILE *f);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_RAWDEV_H_ */
diff --git a/lib/librte_rawdev/rte_rawdev_pmd.h b/lib/librte_rawdev/rte_rawdev_pmd.h
new file mode 100644
index 000000000..ca6e6a1c8
--- /dev/null
+++ b/lib/librte_rawdev/rte_rawdev_pmd.h
@@ -0,0 +1,352 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2017 NXP
+ */
+
+#ifndef _RTE_RAWDEV_PMD_H_
+#define _RTE_RAWDEV_PMD_H_
+
+/** @file
+ * RTE RAW PMD APIs
+ *
+ * @note
+ * Driver facing APIs for a raw device. These are not to be called directly by
+ * any application.
+ * @b EXPERIMENTAL: this API may change without prior notice
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <string.h>
+
+#include <rte_dev.h>
+#include <rte_malloc.h>
+#include <rte_log.h>
+#include <rte_common.h>
+
+#include "rte_rawdev.h"
+
+extern int librawdev_logtype;
+
+/* Logging Macros */
+#define RTE_RDEV_LOG(level, fmt, args...) \
+	rte_log(RTE_LOG_ ## level, librawdev_logtype, "%s(): " fmt "\n", \
+		__func__, ##args)
+
+#define RTE_RDEV_ERR(fmt, args...) \
+	RTE_RDEV_LOG(ERR, fmt, ## args)
+#define RTE_RDEV_DEBUG(fmt, args...) \
+	RTE_RDEV_LOG(DEBUG, fmt, ## args)
+#define RTE_RDEV_INFO(fmt, args...) \
+	RTE_RDEV_LOG(INFO, fmt, ## args)
+
+
+/* Macros to check for valid device */
+#define RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, retval) do { \
+	if (!rte_rawdev_pmd_is_valid_dev((dev_id))) { \
+		RTE_RDEV_ERR("Invalid dev_id=%d", dev_id); \
+		return retval; \
+	} \
+} while (0)
+
+#define RTE_RAWDEV_VALID_DEVID_OR_RET(dev_id) do { \
+	if (!rte_rawdev_pmd_is_valid_dev((dev_id))) { \
+		RTE_RDEV_ERR("Invalid dev_id=%d", dev_id); \
+		return; \
+	} \
+} while (0)
+
+#define RTE_RAWDEV_DETACHED  (0)
+#define RTE_RAWDEV_ATTACHED  (1)
+
+/* Global structure used for maintaining state of allocated raw devices.
+ *
+ * TODO: Can be expanded to <type of raw device>:<count> in future.
+ *       Applications should be able to select from a number of type of raw
+ *       devices which were detected or attached to this DPDK instance.
+ */
+struct rte_rawdev_global {
+	/**< Number of devices found */
+	uint16_t nb_devs;
+};
+
+extern struct rte_rawdev_global *rte_rawdev_globals;
+/** Pointer to global raw devices data structure. */
+extern struct rte_rawdev *rte_rawdevs;
+/** The pool of rte_rawdev structures. */
+
+/**
+ * Get the rte_rawdev structure device pointer for the named device.
+ *
+ * @param name
+ *   device name to select the device structure.
+ *
+ * @return
+ *   - The rte_rawdev structure pointer for the given device ID.
+ */
+static inline struct rte_rawdev *
+rte_rawdev_pmd_get_named_dev(const char *name)
+{
+	struct rte_rawdev *dev;
+	unsigned int i;
+
+	if (name == NULL)
+		return NULL;
+
+	for (i = 0; i < RTE_RAWDEV_MAX_DEVS; i++) {
+		dev = &rte_rawdevs[i];
+		if ((dev->attached == RTE_RAWDEV_ATTACHED) &&
+		   (strcmp(dev->name, name) == 0))
+			return dev;
+	}
+
+	return NULL;
+}
+
+/**
+ * Validate if the raw device index is a valid attached raw device.
+ *
+ * @param dev_id
+ *   raw device index.
+ *
+ * @return
+ *   - If the device index is valid (1) or not (0).
+ */
+static inline unsigned
+rte_rawdev_pmd_is_valid_dev(uint8_t dev_id)
+{
+	struct rte_rawdev *dev;
+
+	if (dev_id >= RTE_RAWDEV_MAX_DEVS)
+		return 0;
+
+	dev = &rte_rawdevs[dev_id];
+	if (dev->attached != RTE_RAWDEV_ATTACHED)
+		return 0;
+	else
+		return 1;
+}
+
+/**
+ * Definitions of all functions exported by a driver through the
+ * the generic structure of type *rawdev_ops* supplied in the
+ * *rte_rawdev* structure associated with a device.
+ */
+
+/**
+ * Get device information of a device.
+ *
+ * @param dev
+ *   Raw device pointer
+ * @param dev_info
+ *   Raw device information structure
+ *
+ * @return
+ *   Returns 0 on success
+ */
+typedef void (*rawdev_info_get_t)(struct rte_rawdev *dev,
+				  rte_rawdev_obj_t dev_info);
+
+/**
+ * Configure a device.
+ *
+ * @param dev
+ *   Raw device pointer
+ * @param config
+ *   Void object containing device specific configuration
+ *
+ * @return
+ *   Returns 0 on success
+ */
+typedef int (*rawdev_configure_t)(const struct rte_rawdev *dev,
+				  rte_rawdev_obj_t config);
+
+/**
+ * Start a configured device.
+ *
+ * @param dev
+ *   Raw device pointer
+ *
+ * @return
+ *   Returns 0 on success
+ */
+typedef int (*rawdev_start_t)(struct rte_rawdev *dev);
+
+/**
+ * Stop a configured device.
+ *
+ * @param dev
+ *   Raw device pointer
+ */
+typedef void (*rawdev_stop_t)(struct rte_rawdev *dev);
+
+/**
+ * Close a configured device.
+ *
+ * @param dev
+ *   Raw device pointer
+ *
+ * @return
+ * - 0 on success
+ * - (-EAGAIN) if can't close as device is busy
+ */
+typedef int (*rawdev_close_t)(struct rte_rawdev *dev);
+
+/**
+ * Reset a configured device.
+ *
+ * @param dev
+ *   Raw device pointer
+ * @return
+ *   0 for success
+ *   !0 for failure
+ */
+typedef int (*rawdev_reset_t)(struct rte_rawdev *dev);
+
+/**
+ * Retrieve the current raw queue configuration.
+ *
+ * @param dev
+ *   Raw device pointer
+ * @param queue_id
+ *   Raw device queue index
+ * @param[out] queue_conf
+ *   Raw device queue configuration structure
+ *
+ */
+typedef void (*rawdev_queue_conf_get_t)(struct rte_rawdev *dev,
+					uint16_t queue_id,
+					rte_rawdev_obj_t queue_conf);
+
+/**
+ * Setup an raw queue.
+ *
+ * @param dev
+ *   Raw device pointer
+ * @param queue_id
+ *   Rawqueue index
+ * @param queue_conf
+ *   Rawqueue configuration structure
+ *
+ * @return
+ *   Returns 0 on success.
+ */
+typedef int (*rawdev_queue_setup_t)(struct rte_rawdev *dev,
+				    uint16_t queue_id,
+				    rte_rawdev_obj_t queue_conf);
+
+/**
+ * Release resources allocated by given raw queue.
+ *
+ * @param dev
+ *   Raw device pointer
+ * @param queue_id
+ *   Raw queue index
+ *
+ */
+typedef int (*rawdev_queue_release_t)(struct rte_rawdev *dev,
+				      uint16_t queue_id);
+
+/**
+ * Dump internal information
+ *
+ * @param dev
+ *   Raw device pointer
+ * @param f
+ *   A pointer to a file for output
+ * @return
+ *   0 for success,
+ *   !0 Error
+ *
+ */
+typedef int (*rawdev_dump_t)(struct rte_rawdev *dev, FILE *f);
+
+/** Rawdevice operations function pointer table */
+struct rte_rawdev_ops {
+	/**< Get device info. */
+	rawdev_info_get_t dev_info_get;
+	/**< Configure device. */
+	rawdev_configure_t dev_configure;
+	/**< Start device. */
+	rawdev_start_t dev_start;
+	/**< Stop device. */
+	rawdev_stop_t dev_stop;
+	/**< Close device. */
+	rawdev_close_t dev_close;
+	/**< Reset device. */
+	rawdev_reset_t dev_reset;
+
+	/**< Get raw queue configuration. */
+	rawdev_queue_conf_get_t queue_def_conf;
+	/**< Set up an raw queue. */
+	rawdev_queue_setup_t queue_setup;
+	/**< Release an raw queue. */
+	rawdev_queue_release_t queue_release;
+
+	/* Dump internal information */
+	rawdev_dump_t dump;
+};
+
+/**
+ * Allocates a new rawdev slot for an raw device and returns the pointer
+ * to that slot for the driver to use.
+ *
+ * @param name
+ *   Unique identifier name for each device
+ * @dev_priv_size
+ *   Private data allocated within rte_rawdev object.
+ * @param socket_id
+ *   Socket to allocate resources on.
+ * @return
+ *   - Slot in the rte_dev_devices array for a new device;
+ */
+struct rte_rawdev * __rte_experimental
+rte_rawdev_pmd_allocate(const char *name, size_t dev_private_size,
+			int socket_id);
+
+/**
+ * Release the specified rawdev device.
+ *
+ * @param rawdev
+ * The *rawdev* pointer is the address of the *rte_rawdev* structure.
+ * @return
+ *   - 0 on success, negative on error
+ */
+int __rte_experimental
+rte_rawdev_pmd_release(struct rte_rawdev *rawdev);
+
+/**
+ * Creates a new raw device and returns the pointer to that device.
+ *
+ * @param name
+ *   Pointer to a character array containing name of the device
+ * @param dev_private_size
+ *   Size of raw PMDs private data
+ * @param socket_id
+ *   Socket to allocate resources on.
+ *
+ * @return
+ *   - Raw device pointer if device is successfully created.
+ *   - NULL if device cannot be created.
+ */
+struct rte_rawdev * __rte_experimental
+rte_rawdev_pmd_init(const char *name, size_t dev_private_size,
+		    int socket_id);
+
+/**
+ * Destroy a raw device
+ *
+ * @param name
+ *   Name of the device
+ * @return
+ *   - 0 on success, negative on error
+ */
+int __rte_experimental
+rte_rawdev_pmd_uninit(const char *name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_RAWDEV_PMD_H_ */
diff --git a/lib/librte_rawdev/rte_rawdev_version.map b/lib/librte_rawdev/rte_rawdev_version.map
new file mode 100644
index 000000000..64e60d945
--- /dev/null
+++ b/lib/librte_rawdev/rte_rawdev_version.map
@@ -0,0 +1,21 @@
+EXPERIMENTAL {
+	global:
+
+	rte_rawdev_close;
+	rte_rawdev_configure;
+	rte_rawdev_count;
+	rte_rawdev_get_dev_id;
+	rte_rawdev_info_get;
+	rte_rawdev_pmd_allocate;
+	rte_rawdev_pmd_release;
+	rte_rawdev_queue_conf_get;
+	rte_rawdev_queue_setup;
+	rte_rawdev_queue_release;
+	rte_rawdev_reset;
+	rte_rawdev_socket_id;
+	rte_rawdev_start;
+	rte_rawdev_stop;
+	rte_rawdevs;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 0169f3f5b..b201e861d 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -105,6 +105,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER)        += -lrte_reorder
 _LDLIBS-$(CONFIG_RTE_LIBRTE_SCHED)          += -lrte_sched
+_LDLIBS-$(CONFIG_RTE_LIBRTE_RAWDEV)         += -lrte_rawdev
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 _LDLIBS-$(CONFIG_RTE_LIBRTE_KNI)            += -lrte_kni
