diff --git a/arch/arm/imx-common/Makefile b/arch/arm/imx-common/Makefile
index e7190c3..8563150 100644
--- a/arch/arm/imx-common/Makefile
+++ b/arch/arm/imx-common/Makefile
@@ -22,6 +22,7 @@ ifeq ($(SOC),$(filter $(SOC),mx7))
 obj-y 	+= cpu.o
 obj-$(CONFIG_SYS_I2C_MXC) += i2c-mxv7.o
 obj-$(CONFIG_SYSCOUNTER_TIMER) += syscounter.o
+obj-$(CONFIG_CMD_MFGPROT) += cmd_mfgprot.o
 endif
 ifeq ($(SOC),$(filter $(SOC),mx6 mx7))
 obj-y 	+= cache.o init.o
diff --git a/arch/arm/imx-common/cmd_mfgprot.c b/arch/arm/imx-common/cmd_mfgprot.c
new file mode 100644
index 0000000..83e95d3
--- /dev/null
+++ b/arch/arm/imx-common/cmd_mfgprot.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2016 NXP Semiconductors.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * Command for manufacturing protection
+ */
+
+#include <common.h>
+#include <command.h>
+#include <environment.h>
+#include <malloc.h>
+#include <asm/byteorder.h>
+#include <linux/compiler.h>
+#include <fsl_sec.h>
+#include <asm/arch/clock.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * do_mfgprot() - Handle the "mfgprogt" command-line command
+ * @cmdtp:  Command data struct pointer
+ * @flag:   Command flag
+ * @argc:   Command-line argument count
+ * @argv:   Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int do_mfgprot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	uint32_t sel;
+	int ret = 0;
+
+	u32 jr_size = 4;
+	u32 out_jr_size = sec_in32(CONFIG_SYS_FSL_JR0_ADDR + 0x102c);
+	if (out_jr_size != jr_size) {
+		hab_caam_clock_enable(1);
+		sec_init();
+	}
+
+	sel = simple_strtoul(argv[1], NULL, 10);
+	switch (sel) {
+	case 0:
+		ret = gen_mppubk();
+		break;
+	case 1:
+		ret = sign_mppubk();
+		break;
+	}
+	return ret;
+}
+
+/***************************************************/
+static char mfgprot_help_text[] =
+	"mp 0: prints out the public key for MP\n"
+	"mp 1: prints out an exmple signature for MP\n";
+
+U_BOOT_CMD(
+	mfgprot, 2, 1, do_mfgprot,
+	"Manufacturing Protection\n",
+	mfgprot_help_text
+);
diff --git a/drivers/crypto/fsl/Makefile b/drivers/crypto/fsl/Makefile
index fd736cf..6d6903b 100644
--- a/drivers/crypto/fsl/Makefile
+++ b/drivers/crypto/fsl/Makefile
@@ -8,3 +8,7 @@ obj-y += sec.o
 obj-$(CONFIG_FSL_CAAM) += jr.o fsl_hash.o jobdesc.o error.o
 obj-$(CONFIG_CMD_BLOB)$(CONFIG_CMD_DEKBLOB) += fsl_blob.o
 obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o
+
+ifdef CONFIG_MX7
+obj-$(CONFIG_CMD_MFGPROT) += fsl_mfgprot.o
+endif
diff --git a/drivers/crypto/fsl/fsl_mfgprot.c b/drivers/crypto/fsl/fsl_mfgprot.c
new file mode 100644
index 0000000..967dbc4
--- /dev/null
+++ b/drivers/crypto/fsl/fsl_mfgprot.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <fsl_sec.h>
+#include <asm-generic/errno.h>
+#include "jobdesc.h"
+#include "desc.h"
+#include "jr.h"
+
+
+/** Job Descriptor Header command - add length in words */
+#define HAB_ENG_CAAM_CMD_JOBHDR			0xB0800000UL
+#define HAB_ENG_CAAM_CMD_JOBHDR_START_SHIFT	16 /**< START INDEX field */
+#define HAB_ENG_CAAM_CMD_JOBHDR_START_WIDTH	6 /**< START INDEX field */
+
+#define HAB_MASK(LBL)	\
+	((((uint32_t)1 << (LBL##_WIDTH)) - 1) << (LBL##_SHIFT))
+
+#define HAB_INSERT_BITS(val, LBL)	\
+	(((uint32_t)(val) << LBL##_SHIFT) & HAB_MASK(LBL))
+
+/** @name MPPUBK protocol data block
+ *  @{
+ */
+#define HAB_ENG_CAAM_MPPUBK_SGF		(1UL<<31)	/**< Message SG flag */
+#define HAB_ENG_CAAM_MPPUBK_CSEL_SHIFT	17		/**< Curve selection */
+#define HAB_ENG_CAAM_MPPUBK_CSEL_WIDTH	4		/**< Curve selection */
+#define HAB_ENG_CAAM_MPPUBK_CSEL_P256	0x3		/**< P-256 */
+#define HAB_ENG_CAAM_MPPUBK_CSEL_P384	0x4		/**< P-384 */
+#define HAB_ENG_CAAM_MPPUBK_CSEL_P521	0x5		/**< P-521 */
+
+/** Size of MFG descriptor */
+#define MFG_PUBK_DSC_WORDS 4
+#define MFG_SIGN_DSC_WORDS 8
+
+/** Size of MFG protocol data block */
+#define MFG_PUBK_PDB_WORDS 2
+#define MFG_SIGN_PDB_WORDS 6
+
+/** Security level index in #mfg_curve */
+#define MFG_SEC_LVL_256 0
+#define MFG_SEC_LVL_384 1
+#define MFG_SEC_LVL_521 2
+
+/** PROTOCOL MPPubKGen command */
+#define HAB_ENG_CAAM_CMD_PROTOCOL_MPPUBK	0x86140000UL
+#define HAB_ENG_CAAM_CMD_PROTOCOL_MPSIGN	0x86150000UL
+
+#define HAB_ENG_MFG_PUBK_BYTES	64
+#define HAB_ENG_MFG_SIGN_BYTES	4
+#define HAB_ENG_MFG_PRVK_BYTES	32
+#define HAB_MES_RESP_DGST_BYTES	32
+
+void mfg_build_sign_dsc(u32 *dsc_ptr, u8 *m, u8 *dgst, u8 *c, u8 *d)
+{
+	u32 *dsc = dsc_ptr;
+	*dsc++ = (HAB_ENG_CAAM_CMD_JOBHDR
+		  | HAB_INSERT_BITS(
+				MFG_SIGN_PDB_WORDS + 1,
+				HAB_ENG_CAAM_CMD_JOBHDR_START)
+		  | MFG_SIGN_DSC_WORDS);
+
+	/*** MFG PubK PDB ***/
+	/* Curve */
+	*dsc++ = HAB_INSERT_BITS(HAB_ENG_CAAM_MPPUBK_CSEL_P256,
+				 HAB_ENG_CAAM_MPPUBK_CSEL);
+	/* Message Pointer */
+	*dsc++ = (dma_addr_t)m;
+
+	/* mes-resp Pointer */
+	*dsc++ = (dma_addr_t)dgst;
+
+	/* C Pointer */
+	*dsc++ = (dma_addr_t)c;
+
+	/* d Pointer */
+	*dsc++ = (dma_addr_t)d;
+
+	/* Message Size */
+	*dsc++ = HAB_ENG_MFG_SIGN_BYTES;
+
+	/* MP PubK generate key command */
+	*dsc = HAB_ENG_CAAM_CMD_PROTOCOL_MPSIGN;
+}
+
+void mfg_build_pubk_dsc(u32 *dsc_ptr, u8 *dst)
+{
+	u32 *dsc = dsc_ptr;
+	*dsc++ = (HAB_ENG_CAAM_CMD_JOBHDR
+		 | HAB_INSERT_BITS(
+			MFG_PUBK_PDB_WORDS + 1,
+			HAB_ENG_CAAM_CMD_JOBHDR_START)
+		 | MFG_PUBK_DSC_WORDS);
+
+	/*** MFG PubK PDB ***/
+	/* Curve */
+	*dsc++ = HAB_INSERT_BITS(HAB_ENG_CAAM_MPPUBK_CSEL_P256,
+				 HAB_ENG_CAAM_MPPUBK_CSEL);
+	/* Message Pointer */
+	*dsc++ = (dma_addr_t)dst;
+
+	/* MP PubK generate key command */
+	*dsc = HAB_ENG_CAAM_CMD_PROTOCOL_MPPUBK;
+}
+
+int gen_mppubk(void)
+{
+	int ret;
+	int size, i;
+
+	u32 *dsc;
+	uint32_t dst_addr;
+	u8 *dst;
+
+	/****************************************************************
+	 * Allocation & Initialization
+	 ****************************************************************/
+	ret = 0;
+
+	/* Memory addresses for output */
+	dst_addr = 0x80100000;
+	dst = map_sysmem(dst_addr, HAB_ENG_MFG_PUBK_BYTES);
+	memset(dst, 0, HAB_ENG_MFG_PUBK_BYTES);
+
+	/****************************************************************
+	 * Job Descriptor initialization
+	 ****************************************************************/
+	dsc = memalign(ARCH_DMA_MINALIGN,
+			sizeof(uint32_t) * MFG_PUBK_DSC_WORDS);
+	if (!dsc) {
+		debug("Not enough memory for descriptor allocation\n");
+		return -ENOMEM;
+	}
+
+	mfg_build_pubk_dsc(dsc, dst);
+
+	size = roundup(sizeof(uint32_t) * MFG_PUBK_DSC_WORDS,
+			ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)dsc, (unsigned long)dsc + size);
+
+	size = roundup(HAB_ENG_MFG_PUBK_BYTES, ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)dst, (unsigned long)dst + size);
+
+	/****************************************************************
+	 * Execute Job Descriptor
+	 ****************************************************************/
+	puts("\nGenerating Manufacturing Protection Public Key\n");
+
+	ret = run_descriptor_jr(dsc);
+	if (ret) {
+		debug("Error in public key generation %d\n", ret);
+	   goto err;
+	}
+
+	size = roundup(HAB_ENG_MFG_PUBK_BYTES, ARCH_DMA_MINALIGN);
+	invalidate_dcache_range((unsigned long)dst, (unsigned long)dst+size);
+
+	/****************************************************************
+	 * Output results
+	 ****************************************************************/
+	puts("Public key:\n");
+	for (i = 0; i < HAB_ENG_MFG_PUBK_BYTES; i++)
+		printf("%02X", ((u8 *)dst)[i]);
+	printf("\n");
+
+err:
+	free(dsc);
+	return ret;
+}
+
+int sign_mppubk(void)
+{
+	int ret;
+	int size, i;
+	int data_size;
+
+	uint32_t dgst_addr, c_addr, d_addr;
+	u32 *dsc;
+	u8 *m, *dgst, *c, *d;
+
+	/****************************************************************
+	 * Allocation & Initialization
+	 ****************************************************************/
+	ret = 0;
+
+	/* Data to be signed */
+	data_size = 4;
+	m = memalign(ARCH_DMA_MINALIGN, data_size);
+	memset(m, 0, data_size);
+	m[0] = 0x42;
+	m[1] = 0x45;
+	m[2] = 0x45;
+	m[3] = 0x46;
+
+	/* Memory addresses for output */
+	dgst_addr = 0x80100000;
+	c_addr = 0x80101000;
+	d_addr = 0x80102000;
+
+	dgst = map_sysmem(dgst_addr, HAB_MES_RESP_DGST_BYTES);
+	c = map_sysmem(c_addr, HAB_ENG_MFG_PRVK_BYTES);
+	d = map_sysmem(d_addr, HAB_ENG_MFG_PRVK_BYTES);
+
+	memset(dgst, 0, HAB_MES_RESP_DGST_BYTES);
+	memset(d, 0, HAB_ENG_MFG_PRVK_BYTES);
+	memset(c, 0, HAB_ENG_MFG_PRVK_BYTES);
+
+	/****************************************************************
+	 * Job Descriptor initialization
+	 ****************************************************************/
+	dsc = memalign(ARCH_DMA_MINALIGN,
+			sizeof(uint32_t) * MFG_SIGN_DSC_WORDS);
+	if (!dsc) {
+		debug("Not enough memory for descriptor allocation\n");
+		return -ENOMEM;
+	}
+
+	mfg_build_sign_dsc(dsc, m, dgst, c, d);
+
+	size = roundup(sizeof(uint32_t) * MFG_SIGN_DSC_WORDS,
+			ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)dsc, (unsigned long)dsc + size);
+
+	size = roundup(data_size, ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)m, (unsigned long)m + size);
+
+	size = roundup(HAB_MES_RESP_DGST_BYTES, ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)dgst, (unsigned long)dgst + size);
+
+	size = roundup(HAB_ENG_MFG_PRVK_BYTES, ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)c, (unsigned long)c + size);
+	flush_dcache_range((unsigned long)d, (unsigned long)d + size);
+
+	/****************************************************************
+	 * Execute Job Descriptor
+	 ****************************************************************/
+	puts("\nSiging message with Manufacturing Protection Public Key\n");
+
+	ret = run_descriptor_jr(dsc);
+	if (ret) {
+		debug("Error in public key generation %d\n", ret);
+	   goto err;
+	}
+
+	size = roundup(HAB_MES_RESP_DGST_BYTES, ARCH_DMA_MINALIGN);
+	invalidate_dcache_range((unsigned long)dgst, (unsigned long)dgst+size);
+
+	size = roundup(HAB_ENG_MFG_PRVK_BYTES, ARCH_DMA_MINALIGN);
+	invalidate_dcache_range((unsigned long)c, (unsigned long)c+size);
+	invalidate_dcache_range((unsigned long)d, (unsigned long)d+size);
+
+	/****************************************************************
+	 * Output results
+	 ****************************************************************/
+	puts("Message: ");
+	for (i = 0; i < data_size; i++)
+		printf("%02X ", ((uint8_t *)m)[i]);
+	printf("\n");
+
+	puts("Message Representative Digest(SHA-256):\n");
+	for (i = 0; i < HAB_MES_RESP_DGST_BYTES; i++)
+		printf("%02X", ((uint8_t *)dgst)[i]);
+	printf("\n");
+
+	puts("Signature:\n");
+	puts("D:\n");
+	for (i = 0; i < HAB_ENG_MFG_PRVK_BYTES; i++)
+		printf("%02X", ((uint8_t *)c)[i]);
+	printf("\n");
+
+	puts("d:\n");
+	for (i = 0; i < HAB_ENG_MFG_PRVK_BYTES; i++)
+		printf("%02X", ((uint8_t *)d)[i]);
+	printf("\n");
+
+err:
+	free(dsc);
+	return ret;
+}
diff --git a/include/fsl_sec.h b/include/fsl_sec.h
index 2ddced3..3b22651 100644
--- a/include/fsl_sec.h
+++ b/include/fsl_sec.h
@@ -284,6 +284,18 @@ int sec_init(void);
  */
 int blob_dek(const u8 *src, u8 *dst, u8 len);
 
+/*
+ * gen_mpubk:
+ * Generates example of public key for manufacturing protection
+ */
+int gen_mppubk(void);
+
+/*
+ * sign_mpubk:
+ * Generates example of manufacturing protection signature of
+ * sample data.
+ */
+int sign_mppubk(void);
 #endif
 
 #endif /* __FSL_SEC_H */
