diff --git a/platform/linux-keystone2/Makefile.am b/platform/linux-keystone2/Makefile.am
index a6ee070..296062b 100644
--- a/platform/linux-keystone2/Makefile.am
+++ b/platform/linux-keystone2/Makefile.am
@@ -61,6 +61,7 @@ odpplatinclude_HEADERS = \
 		  $(srcdir)/include/odp/plat/align.h \
 		  $(srcdir)/include/odp/plat/debug.h \
 		  $(srcdir)/include/odp/plat/mcsdk_tune.h \
+		  $(srcdir)/include/odp/plat/osal.h \
 		  $(srcdir)/include/odp/plat/state.h \
 		  $(srcdir)/include/odp/plat/ti_mcsdk.h \
 		  $(linux_generic_srcdir)/include/odp/plat/atomic_types.h \
diff --git a/platform/linux-keystone2/include/odp/plat/osal.h b/platform/linux-keystone2/include/odp/plat/osal.h
new file mode 100644
index 0000000..05704e9
--- /dev/null
+++ b/platform/linux-keystone2/include/odp/plat/osal.h
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2014, Linaro Limited
+ * Copyright (c) 2014, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef ODP_PLAT_OSAL_H_
+#define ODP_PLAT_OSAL_H_
+
+#include <odp/plat/ti_mcsdk.h>
+#include <odp/plat/debug.h>
+
+typedef uintptr_t odp_pa_t;
+
+static inline odp_pa_t _odp_mem_virt_to_phys(void *virt)
+{
+	odp_pa_t phys = (odp_pa_t)hplib_mVMVirtToPhy(virt);
+	ODP_ASSERT(virt ? !!phys : !phys, "Failed virt to phys conversion");
+	return phys;
+}
+
+static inline void *_odp_mem_phys_to_virt(odp_pa_t phys)
+{
+	void *virt = hplib_mVMPhyToVirt((void *)phys);
+	ODP_ASSERT(phys ? !!virt : !virt, "Failed phys to virt conversion");
+	return hplib_mVMPhyToVirt((void *)phys);
+}
+
+#ifdef ODP_DEBUG
+static inline void _odp_mem_verify_phys(odp_pa_t phys)
+{
+	void *virt = hplib_mVMPhyToVirt((void *)phys);
+	ODP_ASSERT(phys ? !!virt : !virt, "Wrong physical address");
+}
+
+static inline void _odp_mem_verify_virt(void *virt)
+{
+	odp_pa_t phys = (odp_pa_t)hplib_mVMVirtToPhy(virt);
+	ODP_ASSERT(virt ? !!phys : !phys, "Wrong virtual address");
+}
+#else
+static inline void _odp_mem_verify_phys(odp_pa_t phys) {};
+static inline void _odp_mem_verify_virt(void *virt) {};
+#endif
+
+/*
+ * Original buffer info
+ */
+static inline void _cppi_desc_orig_info(Cppi_HostDesc *desc,
+					odp_pa_t *buf_addr,
+					uint32_t *buf_len)
+{
+	Cppi_getOriginalBufInfo(Cppi_DescType_HOST,
+				(Cppi_Desc *)desc,
+				(uint8_t **)buf_addr,
+				buf_len);
+}
+
+static inline void _cppi_desc_orig_info_set(Cppi_HostDesc *desc,
+					    odp_pa_t buf_addr,
+					    uint32_t buf_len)
+{
+	Cppi_setOriginalBufInfo(Cppi_DescType_HOST,
+				(Cppi_Desc *)desc,
+				(void *)buf_addr,
+				buf_len);
+}
+
+/** Read original buffer pointer. Assume physical address is read. */
+static inline odp_pa_t _cppi_desc_orig_ptr(Cppi_HostDesc *desc)
+{
+	odp_pa_t buf_addr = desc->origBuffPtr;
+	_odp_mem_verify_phys(buf_addr);
+	return buf_addr;
+}
+
+/** Set original buffer pointer. Assume physical address is stored. */
+static inline void _cppi_desc_orig_ptr_set(Cppi_HostDesc *desc,
+					   odp_pa_t buf_addr)
+{
+	_odp_mem_verify_phys(buf_addr);
+	desc->origBuffPtr = (uint32_t)buf_addr;
+}
+
+/** Read buffer pointer. Assume virtual address is read. */
+static inline uint8_t *_cppi_desc_orig_vptr(Cppi_HostDesc *desc)
+{
+	uint8_t *buf_addr = (uint8_t *)desc->origBuffPtr;
+	_odp_mem_verify_virt(buf_addr);
+	return buf_addr;
+}
+
+/** Set buffer pointer. Assume virtual address is stored. */
+static inline void _cppi_desc_orig_vptr_set(Cppi_HostDesc *desc,
+					    void *buf_addr)
+{
+	_odp_mem_verify_virt(buf_addr);
+	desc->origBuffPtr = (uint32_t)buf_addr;
+}
+
+static inline uint32_t _cppi_desc_orig_len(Cppi_HostDesc *desc)
+{
+	return CSL_FEXTR(desc->origBufferLen, 21, 0);
+}
+
+static inline void _cppi_desc_orig_len_set(Cppi_HostDesc *desc,
+					   uint32_t buf_len)
+{
+	CSL_FINSR(desc->origBufferLen, 21, 0, buf_len);
+}
+
+
+/*
+ * Current buffer info
+ */
+static inline void _cppi_desc_buf_info_set(Cppi_HostDesc *desc,
+					   odp_pa_t buf_addr,
+					   uint32_t buf_size)
+{
+	Cppi_setData(Cppi_DescType_HOST,
+		     (Cppi_Desc *)desc,
+		     (uint8_t *)buf_addr,
+		     buf_size);
+}
+
+/** Read buffer pointer. Assume physical address is read. */
+static inline odp_pa_t _cppi_desc_buf_ptr(Cppi_HostDesc *desc)
+{
+	odp_pa_t buf_addr = desc->buffPtr;
+	_odp_mem_verify_phys(buf_addr);
+	return buf_addr;
+}
+
+/** Set buffer pointer. Assume physical address is stored. */
+static inline void _cppi_desc_buf_ptr_set(Cppi_HostDesc *desc,
+					   odp_pa_t buf_addr)
+{
+	_odp_mem_verify_phys(buf_addr);
+	desc->buffPtr = buf_addr;
+}
+
+/** Read buffer pointer. Assume virtual address is read. */
+static inline uint8_t *_cppi_desc_buf_vptr(Cppi_HostDesc *desc)
+{
+	uint8_t *buf_addr = (uint8_t *)desc->buffPtr;
+	_odp_mem_verify_virt(buf_addr);
+	return buf_addr;
+}
+
+/** Set buffer pointer. Assume virtual address is stored. */
+static inline void _cppi_desc_buf_vptr_set(Cppi_HostDesc *desc,
+					   uint8_t *buf_addr)
+{
+	_odp_mem_verify_virt(buf_addr);
+	ODP_ASSERT(_odp_mem_virt_to_phys(buf_addr) != 0,
+		   "Not a correct virtual address");
+	desc->buffPtr = (uint32_t)buf_addr;
+}
+
+static inline uint32_t _cppi_desc_buf_len(Cppi_HostDesc *desc)
+{
+	return desc->buffLen;
+}
+
+static inline void _cppi_desc_buf_len_set(Cppi_HostDesc *desc,
+					  uint32_t buf_len)
+{
+	desc->buffLen = buf_len;
+}
+
+
+/*
+ * Packet info
+ */
+static inline uint32_t _cppi_desc_pkt_len(Cppi_HostDesc *desc)
+{
+	return Cppi_getPacketLen(Cppi_DescType_HOST, (Cppi_Desc *)desc);
+}
+
+static inline void _cppi_desc_pkt_len_set(Cppi_HostDesc *desc,
+					     uint32_t pktlen)
+{
+	Cppi_setPacketLen(Cppi_DescType_HOST, (Cppi_Desc *)desc, pktlen);
+}
+
+static inline odp_pa_t _cppi_desc_next(Cppi_HostDesc *desc)
+{
+	odp_pa_t next_desc = (odp_pa_t)Cppi_getNextBD(Cppi_DescType_HOST,
+						      (Cppi_Desc *)desc);
+	_odp_mem_verify_phys(next_desc);
+	return next_desc;
+}
+
+static inline Cppi_HostDesc *_cppi_desc_vnext(Cppi_HostDesc *desc)
+{
+	Cppi_HostDesc *next_desc = (Cppi_HostDesc *)
+			Cppi_getNextBD(Cppi_DescType_HOST, (Cppi_Desc *)desc);
+	_odp_mem_verify_virt(next_desc);
+	return next_desc;
+}
+
+static inline void _cppi_desc_next_set(Cppi_HostDesc *desc,
+				       odp_pa_t next_desc)
+{
+	_odp_mem_verify_phys(next_desc);
+	Cppi_linkNextBD(Cppi_DescType_HOST, (Cppi_Desc *)desc,
+			(Cppi_Desc *)next_desc);
+}
+
+static inline void _cppi_desc_vnext_set(Cppi_HostDesc *desc,
+					Cppi_HostDesc *next_desc)
+{
+	_odp_mem_verify_virt(next_desc);
+	Cppi_linkNextBD(Cppi_DescType_HOST, (Cppi_Desc *)desc,
+			(Cppi_Desc *)next_desc);
+}
+/*
+ * Metadata in CPPI descriptor
+ */
+static inline void _cppi_desc_pool_id_set(Cppi_HostDesc *desc, uint8_t pool_id)
+{
+	Cppi_setOrigBufferpooIndex(Cppi_DescType_HOST,
+				   (Cppi_Desc *)desc, pool_id);
+}
+
+static inline uint8_t _cppi_desc_pool_id(Cppi_HostDesc *desc)
+{
+	return Cppi_getOrigBufferpooIndex(Cppi_DescType_HOST,
+					  (Cppi_Desc *)desc);
+}
+
+static inline void _cppi_desc_pkt_type_set(Cppi_HostDesc *desc, uint8_t type)
+{
+	Cppi_setPacketType(Cppi_DescType_HOST, (Cppi_Desc *)desc, type);
+}
+
+static inline uint8_t _cppi_desc_pkt_type(Cppi_HostDesc *desc)
+{
+	return Cppi_getPacketType(Cppi_DescType_HOST, (Cppi_Desc *)desc);
+}
+
+/*
+ * Helpers
+ */
+static inline uint32_t _cppi_desc_orig_len_total(Cppi_HostDesc *desc)
+{
+	uint32_t len = 0;
+	while (desc) {
+		len += _cppi_desc_orig_len(desc);
+		desc = _cppi_desc_vnext(desc);
+	}
+	return len;
+}
+
+static inline uint32_t _cppi_desc_num_bufs(Cppi_HostDesc *desc)
+{
+	uint32_t num = 0;
+	while (desc) {
+		num++;
+		desc = _cppi_desc_vnext(desc);
+	}
+	return num;
+}
+
+static inline Cppi_HostDesc *_cppi_desc_last(Cppi_HostDesc *desc)
+{
+	while (_cppi_desc_vnext(desc))
+		desc = _cppi_desc_vnext(desc);
+	return desc;
+}
+
+static inline uint8_t *_cppi_desc_orig_end(Cppi_HostDesc *desc)
+{
+	return _cppi_desc_orig_vptr(desc) + _cppi_desc_orig_len(desc);
+}
+
+static inline uint8_t *_cppi_desc_buf_end(Cppi_HostDesc *desc)
+{
+	return _cppi_desc_buf_vptr(desc) + _cppi_desc_buf_len(desc);
+}
+
+/* Returns descriptor which contains data offset */
+static inline
+Cppi_HostDesc *_cppi_desc_offset(Cppi_HostDesc *desc, uint32_t *offset)
+{
+	uint32_t data_len = _cppi_desc_buf_len(desc);
+	uint32_t off = *offset;
+
+	while (off >= data_len) {
+		off -= data_len;
+		desc = _cppi_desc_vnext(desc);
+		ODP_ASSERT(desc, "Not enough descriptors");
+		data_len = _cppi_desc_buf_len(desc);
+	}
+
+	*offset = off;
+	return desc;
+}
+
+static inline void _cppi_desc_shift_vptr(Cppi_HostDesc *desc, int32_t offset)
+{
+	_cppi_desc_buf_vptr_set(desc, _cppi_desc_buf_vptr(desc) + offset);
+	_cppi_desc_buf_len_set(desc, _cppi_desc_buf_len(desc) - offset);
+	_cppi_desc_pkt_len_set(desc, _cppi_desc_pkt_len(desc) - offset);
+}
+
+
+#endif /* ODP_TI_MCSDK_H_ */
