diff --git a/drivers/raw/ifpga/base/ifpga_defines.h b/drivers/raw/ifpga/base/ifpga_defines.h
index 9a280eb..7c8fa89 100644
--- a/drivers/raw/ifpga/base/ifpga_defines.h
+++ b/drivers/raw/ifpga/base/ifpga_defines.h
@@ -23,6 +23,7 @@
 #define FME_FEATURE_NIOS_SPI        "fme_nios_spi"
 #define FME_FEATURE_I2C_MASTER      "fme_i2c_master"
 #define FME_FEATURE_ETH_GROUP       "fme_eth_group"
+#define FME_FEATURE_PMCI            "fme_pmci"
 
 #define PORT_FEATURE_HEADER         "port_hdr"
 #define PORT_FEATURE_UAFU           "port_uafu"
@@ -91,6 +92,7 @@ enum fpga_id_type {
 #define FME_FEATURE_ID_NIOS_SPI 0xd
 #define FME_FEATURE_ID_I2C_MASTER  0xf
 #define FME_FEATURE_ID_ETH_GROUP 0x10
+#define FME_FEATURE_ID_PMCI      0x12
 
 #define PORT_FEATURE_ID_HEADER FEATURE_ID_FIU_HEADER
 #define PORT_FEATURE_ID_ERROR 0x10
@@ -266,6 +268,24 @@ struct feature_fme_bitstream_id {
 	union {
 		u64 csr;
 		struct {
+			u8 build_patch:8;
+			u8 build_minor:8;
+			u8 build_major:8;
+			u8 fvl_bypass:1;
+			u8 mac_lightweight:1;
+			u8 disagregate:1;
+			u8 lightweiht:1;
+			u8 seu:1;
+			u8 ptp:1;
+			u8 reserve:2;
+			u8 interface:4;
+			u32 afu_revision:12;
+			u8 patch:4;
+			u8 minor:4;
+			u8 major:4;
+			u8 reserved:4;
+		} v1;
+		struct {
 			u32 gitrepo_hash:32;	/* GIT repository hash */
 			/*
 			 * HSSI configuration identifier:
@@ -274,7 +294,8 @@ struct feature_fme_bitstream_id {
 			 * 2 - Ethernet
 			 */
 			u8  hssi_id:4;
-			u16 rsvd1:12;		/* Reserved */
+			u8  rsvd1:4;
+			u8  fim_type:8;
 			/* Bitstream version patch number */
 			u8  bs_verpatch:4;
 			/* Bitstream version minor number */
@@ -283,7 +304,7 @@ struct feature_fme_bitstream_id {
 			u8  bs_vermajor:4;
 			/* Bitstream version debug number */
 			u8  bs_verdebug:4;
-		};
+		} v2;
 	};
 };
 
@@ -1670,31 +1691,6 @@ struct bts_header {
 
 #define check_support(n) (n == 1 ? "support" : "no")
 
-/* bitstream id definition */
-struct fme_bitstream_id {
-	union {
-		u64 id;
-		struct {
-			u8 build_patch:8;
-			u8 build_minor:8;
-			u8 build_major:8;
-			u8 fvl_bypass:1;
-			u8 mac_lightweight:1;
-			u8 disagregate:1;
-			u8 lightweiht:1;
-			u8 seu:1;
-			u8 ptp:1;
-			u8 reserve:2;
-			u8 interface:4;
-			u32 afu_revision:12;
-			u8 patch:4;
-			u8 minor:4;
-			u8 major:4;
-			u8 reserved:4;
-		};
-	};
-};
-
 enum board_interface {
 	VC_8_10G = 0,
 	VC_4_25G = 1,
@@ -1703,10 +1699,30 @@ enum board_interface {
 	VC_2_2_25G = 4,
 };
 
+enum fim_type {
+	BASE_ADP = 0,
+	BASE_FDK,
+	BASE_X16_ADP,
+	BASE_X16_FDK,
+	FIMA_10G_ADP,
+	FIMA_25G_ADP,
+	FIMA_100G_ADP,
+	FIMB_ADP,
+	FIMC_ADP
+};
+
+enum hssi_id {
+	NO_HSSI = 0,
+	PCIE_RP,
+	ETHER_NET
+};
+
 enum pac_major {
 	VISTA_CREEK = 0,
 	RUSH_CREEK = 1,
 	DARBY_CREEK = 2,
+	LIGHTNING_CREEK = 3,
+	ARROW_CREEK = 5,
 };
 
 enum pac_minor {
@@ -1718,23 +1734,30 @@ enum pac_minor {
 struct opae_board_info {
 	enum pac_major major;
 	enum pac_minor minor;
-	enum board_interface type;
-
-	/* PAC features */
-	u8 fvl_bypass;
-	u8 mac_lightweight;
-	u8 disaggregate;
-	u8 lightweight;
-	u8 seu;
-	u8 ptp;
 
 	u32 boot_page;
 	u32 max10_version;
 	u32 nios_fw_version;
-	u32 nums_of_retimer;
-	u32 ports_per_retimer;
-	u32 nums_of_fvl;
-	u32 ports_per_fvl;
+
+	union {
+		struct {  /* N3000 specific */
+			enum board_interface type;
+			u8 fvl_bypass;
+			u8 mac_lightweight;
+			u8 disaggregate;
+			u8 lightweight;
+			u8 seu;
+			u8 ptp;
+			u32 nums_of_retimer;
+			u32 ports_per_retimer;
+			u32 nums_of_fvl;
+			u32 ports_per_fvl;
+		};
+		struct {
+			enum fim_type n6000_fim_type;
+			enum hssi_id n6000_hssi_id;
+		};
+	};
 };
 
 #pragma pack(pop)
diff --git a/drivers/raw/ifpga/base/ifpga_feature_dev.c b/drivers/raw/ifpga/base/ifpga_feature_dev.c
index dbecc7b..0a00af1 100644
--- a/drivers/raw/ifpga/base/ifpga_feature_dev.c
+++ b/drivers/raw/ifpga/base/ifpga_feature_dev.c
@@ -227,6 +227,8 @@ int port_clear_error(struct ifpga_port_hw *port)
 	&fme_i2c_master_ops),},
 	{FEATURE_DRV(FME_FEATURE_ID_ETH_GROUP, FME_FEATURE_ETH_GROUP,
 	&fme_eth_group_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_PMCI, FME_FEATURE_PMCI,
+	&fme_pmci_ops),},
 	{0, NULL, NULL}, /* end of arrary */
 };
 
diff --git a/drivers/raw/ifpga/base/ifpga_feature_dev.h b/drivers/raw/ifpga/base/ifpga_feature_dev.h
index b355d22..a637eb5 100644
--- a/drivers/raw/ifpga/base/ifpga_feature_dev.h
+++ b/drivers/raw/ifpga/base/ifpga_feature_dev.h
@@ -178,6 +178,7 @@ int do_pr(struct ifpga_hw *hw, u32 port_id, const char *buffer, u32 size,
 extern struct ifpga_feature_ops fme_i2c_master_ops;
 extern struct ifpga_feature_ops fme_eth_group_ops;
 extern struct ifpga_feature_ops fme_nios_spi_master_ops;
+extern struct ifpga_feature_ops fme_pmci_ops;
 
 int port_get_prop(struct ifpga_port_hw *port, struct feature_prop *prop);
 int port_set_prop(struct ifpga_port_hw *port, struct feature_prop *prop);
diff --git a/drivers/raw/ifpga/base/ifpga_fme.c b/drivers/raw/ifpga/base/ifpga_fme.c
index 43c7b9c..1b9a922 100644
--- a/drivers/raw/ifpga/base/ifpga_fme.c
+++ b/drivers/raw/ifpga/base/ifpga_fme.c
@@ -790,19 +790,32 @@ struct ifpga_feature_ops fme_emif_ops = {
 	.uinit = fme_emif_uinit,
 };
 
-static const char *board_type_to_string(u32 type)
-{
-	switch (type) {
-	case VC_8_10G:
-		return "VC_8x10G";
-	case VC_4_25G:
-		return "VC_4x25G";
-	case VC_2_1_25:
-		return "VC_2x1x25G";
-	case VC_4_25G_2_25G:
-		return "VC_4x25G+2x25G";
-	case VC_2_2_25G:
-		return "VC_2x2x25G";
+static const char *board_type_to_string(u32 board, u32 type)
+{
+	if (board == VISTA_CREEK) {
+		switch (type) {
+		case VC_8_10G:
+			return "8x10G";
+		case VC_4_25G:
+			return "4x25G";
+		case VC_2_1_25:
+			return "2x1x25G";
+		case VC_4_25G_2_25G:
+			return "4x25G+2x25G";
+		case VC_2_2_25G:
+			return "2x2x25G";
+		break;
+		}
+	} else {
+		switch (type) {
+		case FIMA_10G_ADP:
+			return "2x4x10G";
+		case FIMA_25G_ADP:
+			return "2x2x25G";
+		case FIMA_100G_ADP:
+			return "2x100G";
+		break;
+		}
 	}
 
 	return "unknown";
@@ -817,6 +830,12 @@ static const char *board_major_to_string(u32 major)
 		return "RUSH_CREEK";
 	case DARBY_CREEK:
 		return "DARBY_CREEK";
+	case LIGHTNING_CREEK:
+		return "LIGHTNING_CREEK";
+	case ARROW_CREEK:
+		return "ARROW_CREEK";
+	default:
+		break;
 	}
 
 	return "unknown";
@@ -859,35 +878,56 @@ static int board_type_to_info(u32 type,
 
 static int fme_get_board_interface(struct ifpga_fme_hw *fme)
 {
-	struct fme_bitstream_id id;
+	struct feature_fme_bitstream_id id;
 	struct ifpga_hw *hw;
 	u32 val;
+	const char *type = NULL;
+	int ret;
 
 	hw = fme->parent;
 	if (!hw)
 		return -ENODEV;
 
-	if (fme_hdr_get_bitstream_id(fme, &id.id))
+	if (fme_hdr_get_bitstream_id(fme, &id.csr))
 		return -EINVAL;
 
-	fme->board_info.major = id.major;
-	fme->board_info.minor = id.minor;
-	fme->board_info.type = id.interface;
-	fme->board_info.fvl_bypass = id.fvl_bypass;
-	fme->board_info.mac_lightweight = id.mac_lightweight;
-	fme->board_info.lightweight = id.lightweiht;
-	fme->board_info.disaggregate = id.disagregate;
-	fme->board_info.seu = id.seu;
-	fme->board_info.ptp = id.ptp;
+	if (id.v1.major == ARROW_CREEK) {
+		fme->board_info.major = id.v2.bs_vermajor;
+		fme->board_info.minor = id.v2.bs_verminor;
+		fme->board_info.n6000_fim_type = id.v2.fim_type;
+		fme->board_info.n6000_hssi_id = id.v2.hssi_id;
+		type = board_type_to_string(fme->board_info.major,
+				fme->board_info.n6000_fim_type);
+	} else {
+		fme->board_info.major = id.v1.major;
+		fme->board_info.minor = id.v1.minor;
+		fme->board_info.type = id.v1.interface;
+		fme->board_info.fvl_bypass = id.v1.fvl_bypass;
+		fme->board_info.mac_lightweight = id.v1.mac_lightweight;
+		fme->board_info.lightweight = id.v1.lightweiht;
+		fme->board_info.disaggregate = id.v1.disagregate;
+		fme->board_info.seu = id.v1.seu;
+		fme->board_info.ptp = id.v1.ptp;
+		type = board_type_to_string(fme->board_info.major,
+				fme->board_info.type);
+	}
 
 	dev_info(fme, "found: PCI dev: %02x:%02x:%x board: %s type: %s\n",
 			hw->pci_data->bus,
 			hw->pci_data->devid,
 			hw->pci_data->function,
 			board_major_to_string(fme->board_info.major),
-			board_type_to_string(fme->board_info.type));
+			type);
 
-	dev_info(fme, "support feature:\n"
+	ret = max10_get_fpga_load_info(fme->max10_dev, &val);
+	if (ret)
+		return ret;
+	fme->board_info.boot_page = val;
+
+	if (fme->board_info.major == VISTA_CREEK) {
+		dev_info(dev, "FPGA loaded from %s Image\n",
+			val ? "User" : "Factory");
+		dev_info(fme, "support feature:\n"
 			"fvl_bypass:%s\n"
 			"mac_lightweight:%s\n"
 			"lightweight:%s\n"
@@ -901,26 +941,29 @@ static int fme_get_board_interface(struct ifpga_fme_hw *fme)
 			check_support(fme->board_info.seu),
 			check_support(fme->board_info.ptp));
 
+		if (board_type_to_info(fme->board_info.type, &fme->board_info))
+			return -EINVAL;
 
-	if (board_type_to_info(fme->board_info.type, &fme->board_info))
-		return -EINVAL;
-
-	dev_info(fme, "get board info: nums_retimers %d ports_per_retimer %d nums_fvl %d ports_per_fvl %d\n",
+		dev_info(fme, "get board info: nums_retimers %d "
+			"ports_per_retimer %d nums_fvl %d "
+			"ports_per_fvl %d\n",
 			fme->board_info.nums_of_retimer,
 			fme->board_info.ports_per_retimer,
 			fme->board_info.nums_of_fvl,
 			fme->board_info.ports_per_fvl);
+	} else {
+		dev_info(dev, "FPGA loaded from %s Image\n",
+			val ? (val == 1 ? "User1" : "User2") : "Factory");
+	}
 
-	if (max10_sys_read(fme->max10_dev, FPGA_PAGE_INFO, &val))
-		return -EINVAL;
-	fme->board_info.boot_page = val & 0x7;
-
-	if (max10_sys_read(fme->max10_dev, MAX10_BUILD_VER, &val))
-		return -EINVAL;
+	ret = max10_get_bmc_version(fme->max10_dev, &val);
+	if (ret)
+		return ret;
 	fme->board_info.max10_version = val;
 
-	if (max10_sys_read(fme->max10_dev, NIOS2_FW_VERSION, &val))
-		return -EINVAL;
+	ret = max10_get_bmcfw_version(fme->max10_dev, &val);
+	if (ret)
+		return ret;
 	fme->board_info.nios_fw_version = val;
 
 	dev_info(fme, "max10 version 0x%x, nios fw version 0x%x\n",
@@ -983,11 +1026,25 @@ static int fme_spi_init(struct ifpga_feature *feature)
 
 	altera_spi_init(spi_master);
 
-	max10 = intel_max10_device_probe(spi_master, 0);
-	if (!max10) {
+	max10 = opae_zmalloc(sizeof(*max10));
+	if (!max10)
+		goto release_dev;
+
+	max10->spi_master = spi_master;
+	max10->type = M10_N3000;
+
+	max10->spi_tran_dev = spi_transaction_init(spi_master, 0);
+	if (!max10->spi_tran_dev) {
+		dev_err(fme, "%s spi tran init fail\n", __func__);
+		goto free_max10;
+	}
+
+	/* init the max10 device */
+	ret = intel_max10_device_init(max10);
+	if (ret) {
 		ret = -ENODEV;
 		dev_err(fme, "max10 init fail\n");
-		goto spi_fail;
+		goto release_spi_tran_dev;
 	}
 
 	fme->max10_dev = max10;
@@ -1002,17 +1059,24 @@ static int fme_spi_init(struct ifpga_feature *feature)
 
 max10_fail:
 	intel_max10_device_remove(fme->max10_dev);
-spi_fail:
+release_spi_tran_dev:
+	if (max10->spi_tran_dev)
+		spi_transaction_remove(max10->spi_tran_dev);
+free_max10:
+	opae_free(max10);
+release_dev:
 	altera_spi_release(spi_master);
-	return ret;
+	return -ENODEV;
 }
 
 static void fme_spi_uinit(struct ifpga_feature *feature)
 {
 	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
 
-	if (fme->max10_dev)
+	if (fme->max10_dev) {
 		intel_max10_device_remove(fme->max10_dev);
+		opae_free(fme->max10_dev);
+	}
 }
 
 struct ifpga_feature_ops fme_spi_master_ops = {
@@ -1157,27 +1221,37 @@ static int fme_nios_spi_init(struct ifpga_feature *feature)
 	/* 3. init the spi master*/
 	altera_spi_init(spi_master);
 
+	max10 = opae_zmalloc(sizeof(*max10));
+	if (!max10)
+		goto release_dev;
+
+	max10->spi_master = spi_master;
+	max10->type = M10_N3000;
+
+	max10->spi_tran_dev = spi_transaction_init(spi_master, 0);
+	if (!max10->spi_tran_dev) {
+		dev_err(fme, "%s spi tran init fail\n", __func__);
+		goto free_max10;
+	}
+
 	/* init the max10 device */
-	max10 = intel_max10_device_probe(spi_master, 0);
-	if (!max10) {
+	ret = intel_max10_device_init(max10);
+	if (ret) {
 		ret = -ENODEV;
 		dev_err(fme, "max10 init fail\n");
-		goto release_dev;
+		goto release_spi_tran_dev;
 	}
 
 	fme->max10_dev = max10;
-
 	max10->bus = hw->pci_data->bus;
-
 	fme_get_board_interface(fme);
-
 	mgr->sensor_list = &max10->opae_sensor_list;
 
 	/* SPI self test */
 	if (spi_self_checking(max10))
 		goto spi_fail;
 
-	ret = init_sec_mgr(fme);
+	ret = init_sec_mgr(fme, N3000BMC_SEC);
 	if (ret) {
 		dev_err(fme, "security manager init fail\n");
 		goto spi_fail;
@@ -1187,6 +1261,11 @@ static int fme_nios_spi_init(struct ifpga_feature *feature)
 
 spi_fail:
 	intel_max10_device_remove(fme->max10_dev);
+release_spi_tran_dev:
+	if (max10->spi_tran_dev)
+		spi_transaction_remove(max10->spi_tran_dev);
+free_max10:
+	opae_free(max10);
 release_dev:
 	altera_spi_release(spi_master);
 	return -ENODEV;
@@ -1197,8 +1276,10 @@ static void fme_nios_spi_uinit(struct ifpga_feature *feature)
 	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
 
 	release_sec_mgr(fme);
-	if (fme->max10_dev)
+	if (fme->max10_dev) {
 		intel_max10_device_remove(fme->max10_dev);
+		opae_free(fme->max10_dev);
+	}
 }
 
 struct ifpga_feature_ops fme_nios_spi_master_ops = {
@@ -1230,7 +1311,7 @@ static int i2c_mac_rom_test(struct altera_i2c_dev *dev)
 	}
 
 	if (memcmp(buf, read_buf, strlen(string))) {
-		dev_err(NULL, "%s test fail!\n", __func__);
+		dev_info(NULL, "%s test fail!\n", __func__);
 		return -EFAULT;
 	}
 
@@ -1499,3 +1580,81 @@ int fme_mgr_get_sensor_value(struct ifpga_fme_hw *fme,
 
 	return 0;
 }
+
+static int fme_pmci_init(struct ifpga_feature *feature)
+{
+	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
+	struct intel_max10_device *max10;
+	struct ifpga_hw *hw;
+	struct opae_manager *mgr;
+	opae_share_data *sd = NULL;
+	int ret = 0;
+
+	hw = fme->parent;
+	if (!hw)
+		return -ENODEV;
+
+	mgr = hw->adapter->mgr;
+	if (!mgr)
+		return -ENODEV;
+
+	dev_info(fme, "FME PMCI Init.\n");
+	dev_debug(fme, "FME PMCI base addr %p.\n",
+			feature->addr);
+
+	max10 = opae_zmalloc(sizeof(*max10));
+	if (!max10)
+		return -ENOMEM;
+
+	max10->type = M10_N6000;
+	max10->mmio = feature->addr;
+	if (hw->adapter && hw->adapter->shm.ptr) {
+		sd = (opae_share_data *)hw->adapter->shm.ptr;
+		max10->bmc_ops.mutex = &sd->spi_mutex;
+	} else {
+		max10->bmc_ops.mutex = NULL;
+	}
+
+	/* init the max10 device */
+	ret = intel_max10_device_init(max10);
+	if (ret) {
+		dev_err(fme, "max10 init fail\n");
+		goto free_max10;
+	}
+
+	fme->max10_dev = max10;
+	max10->bus = hw->pci_data->bus;
+	fme_get_board_interface(fme);
+	mgr->sensor_list = &max10->opae_sensor_list;
+
+	ret = init_sec_mgr(fme, N6000BMC_SEC);
+	if (ret) {
+		dev_err(fme, "security manager init fail\n");
+		goto release_max10;
+	}
+
+	return ret;
+
+release_max10:
+	intel_max10_device_remove(max10);
+free_max10:
+	opae_free(max10);
+
+	return ret;
+}
+
+static void fme_pmci_uinit(struct ifpga_feature *feature)
+{
+	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
+
+	release_sec_mgr(fme);
+	if (fme->max10_dev) {
+		intel_max10_device_remove(fme->max10_dev);
+		opae_free(fme->max10_dev);
+	}
+}
+
+struct ifpga_feature_ops fme_pmci_ops = {
+	.init = fme_pmci_init,
+	.uinit = fme_pmci_uinit,
+};
diff --git a/drivers/raw/ifpga/base/ifpga_fme_error.c b/drivers/raw/ifpga/base/ifpga_fme_error.c
index 5905eac..c5bed28 100644
--- a/drivers/raw/ifpga/base/ifpga_fme_error.c
+++ b/drivers/raw/ifpga/base/ifpga_fme_error.c
@@ -224,6 +224,8 @@ static int fme_global_error_init(struct ifpga_feature *feature)
 {
 	struct ifpga_fme_hw *fme = feature->parent;
 
+	dev_info(NULL, "FME error_module Init.\n");
+
 	fme_error_enable(fme);
 
 	if (feature->ctx_num)
diff --git a/drivers/raw/ifpga/base/ifpga_port_error.c b/drivers/raw/ifpga/base/ifpga_port_error.c
index 189f762..6c8a7d7 100644
--- a/drivers/raw/ifpga/base/ifpga_port_error.c
+++ b/drivers/raw/ifpga/base/ifpga_port_error.c
@@ -88,7 +88,7 @@ static int port_error_init(struct ifpga_feature *feature)
 {
 	struct ifpga_port_hw *port = feature->parent;
 
-	dev_info(NULL, "port error Init.\n");
+	dev_info(NULL, "port error_module Init.\n");
 
 	spinlock_lock(&port->lock);
 	port_err_mask(port, false);
diff --git a/drivers/raw/ifpga/base/ifpga_sec_mgr.c b/drivers/raw/ifpga/base/ifpga_sec_mgr.c
index 15fb5b6..557c4e3 100644
--- a/drivers/raw/ifpga/base/ifpga_sec_mgr.c
+++ b/drivers/raw/ifpga/base/ifpga_sec_mgr.c
@@ -227,7 +227,7 @@ static int n3000_bulk_write(struct intel_max10_device *dev, uint32_t addr,
 	for (i = 0; i < n; i++) {
 		p = i << 2;
 		v = *(uint32_t *)(buf + p);
-		ret = max10_reg_write(dev, addr + p, v);
+		ret = max10_sys_raw_write(dev, addr + p, v);
 		if (ret < 0) {
 			dev_err(dev,
 				"Failed to write to staging area 0x%08x [e:%d]\n",
@@ -490,7 +490,7 @@ static int n3000_reload_bmc(struct intel_max10_device *dev, int page)
 			CONFIG_SEL_S(page) | REBOOT_REQ);
 	} else {
 		val = (page == 0) ? 0x1 : 0x3;
-		ret = max10_reg_write(dev, IFPGA_DUAL_CFG_CTRL1, val);
+		ret = max10_sys_raw_write(dev, IFPGA_DUAL_CFG_CTRL1, val);
 		if (ret < 0) {
 			dev_err(dev,
 				"Failed to write to dual config1 register [e:%d]\n",
@@ -498,7 +498,7 @@ static int n3000_reload_bmc(struct intel_max10_device *dev, int page)
 			goto end;
 		}
 
-		ret = max10_reg_write(dev, IFPGA_DUAL_CFG_CTRL0, 0x1);
+		ret = max10_sys_raw_write(dev, IFPGA_DUAL_CFG_CTRL0, 0x1);
 		if (ret < 0) {
 			if (ret == -EIO) {
 				ret = 0;
@@ -584,7 +584,7 @@ static uint64_t n3000_get_hw_errinfo(struct ifpga_sec_mgr *smgr)
 	.get_hw_errinfo = n3000_get_hw_errinfo,
 };
 
-int init_sec_mgr(struct ifpga_fme_hw *fme)
+int init_sec_mgr(struct ifpga_fme_hw *fme, enum fpga_sec_type type)
 {
 	struct ifpga_hw *hw = NULL;
 	opae_share_data *sd = NULL;
@@ -621,6 +621,7 @@ int init_sec_mgr(struct ifpga_fme_hw *fme)
 
 	smgr->fme = fme;
 	smgr->max10_dev = fme->max10_dev;
+	smgr->type = type;
 
 	return 0;
 }
diff --git a/drivers/raw/ifpga/base/ifpga_sec_mgr.h b/drivers/raw/ifpga/base/ifpga_sec_mgr.h
index fbeba56..09cc038 100644
--- a/drivers/raw/ifpga/base/ifpga_sec_mgr.h
+++ b/drivers/raw/ifpga/base/ifpga_sec_mgr.h
@@ -55,6 +55,12 @@
 #define IFPGA_RSU_ERR_WEAROUT		-7
 #define IFPGA_RSU_ERR_FILE_READ		-8
 
+/* Supported fpga secure manager types */
+enum fpga_sec_type {
+	N3000BMC_SEC,
+	N6000BMC_SEC
+};
+
 struct ifpga_sec_mgr;
 
 struct ifpga_sec_ops {
@@ -80,9 +86,10 @@ struct ifpga_sec_mgr {
 	unsigned int *rsu_control;
 	unsigned int *rsu_status;
 	const struct ifpga_sec_ops *ops;
+	enum fpga_sec_type type;
 };
 
-int init_sec_mgr(struct ifpga_fme_hw *fme);
+int init_sec_mgr(struct ifpga_fme_hw *fme, enum fpga_sec_type type);
 void release_sec_mgr(struct ifpga_fme_hw *fme);
 int fpga_update_flash(struct ifpga_fme_hw *fme, const char *image,
 	uint64_t *status);
diff --git a/drivers/raw/ifpga/base/opae_hw_api.c b/drivers/raw/ifpga/base/opae_hw_api.c
index 87256fc..6b78094 100644
--- a/drivers/raw/ifpga/base/opae_hw_api.c
+++ b/drivers/raw/ifpga/base/opae_hw_api.c
@@ -831,6 +831,35 @@ int opae_manager_get_retimer_status(struct opae_manager *mgr,
 }
 
 /**
+ * opae_manager_get_sensor_list - get sensor name list
+ * @mgr: opae_manager of sensors
+ * @buf: buffer to accommodate name list separated by semicolon
+ * @size: size of buffer
+ *
+ * Return: the pointer of the opae_sensor_info
+ */
+int
+opae_mgr_get_sensor_list(struct opae_manager *mgr, char *buf, size_t size)
+{
+	struct opae_sensor_info *sensor;
+	uint32_t offset = 0;
+
+	opae_mgr_for_each_sensor(mgr, sensor) {
+		if (sensor->name) {
+			if (buf && (offset < size))
+				snprintf(buf + offset, size - offset, "%s;",
+					sensor->name);
+			offset += strlen(sensor->name) + 1;
+		}
+	}
+
+	if (buf && (offset > 0) && (offset <= size))
+		buf[offset-1] = 0;
+
+	return offset;
+}
+
+/**
  * opae_manager_get_sensor_by_id - get sensor device
  * @id: the id of the sensor
  *
diff --git a/drivers/raw/ifpga/base/opae_hw_api.h b/drivers/raw/ifpga/base/opae_hw_api.h
index fd40e09..8aead4d 100644
--- a/drivers/raw/ifpga/base/opae_hw_api.h
+++ b/drivers/raw/ifpga/base/opae_hw_api.h
@@ -93,6 +93,7 @@ int opae_manager_flash(struct opae_manager *mgr, int acc_id, const char *buf,
 		       u32 size, u64 *status);
 int opae_manager_get_eth_group_region_info(struct opae_manager *mgr,
 		u8 group_id, struct opae_eth_group_region_info *info);
+int opae_mgr_get_sensor_list(struct opae_manager *mgr, char *buf, size_t size);
 struct opae_sensor_info *opae_mgr_get_sensor_by_name(struct opae_manager *mgr,
 		const char *name);
 struct opae_sensor_info *opae_mgr_get_sensor_by_id(struct opae_manager *mgr,
diff --git a/drivers/raw/ifpga/base/opae_intel_max10.c b/drivers/raw/ifpga/base/opae_intel_max10.c
index 9d82fb0..465494a 100644
--- a/drivers/raw/ifpga/base/opae_intel_max10.c
+++ b/drivers/raw/ifpga/base/opae_intel_max10.c
@@ -4,51 +4,42 @@
 
 #include "opae_intel_max10.h"
 #include <libfdt.h>
+#include "opae_osdep.h"
 
-int max10_reg_read(struct intel_max10_device *dev,
-	unsigned int reg, unsigned int *val)
+int max10_sys_read(struct intel_max10_device *dev,
+	unsigned int offset, unsigned int *val)
 {
-	if (!dev)
+	if (!dev || !dev->ops->reg_read)
 		return -ENODEV;
 
-	dev_debug(dev, "%s: bus:0x%x, reg:0x%x\n", __func__, dev->bus, reg);
-
-	return spi_transaction_read(dev->spi_tran_dev,
-			reg, 4, (unsigned char *)val);
+	return dev->ops->reg_read(dev, dev->csr->base + offset, val);
 }
 
-int max10_reg_write(struct intel_max10_device *dev,
-	unsigned int reg, unsigned int val)
+int max10_sys_write(struct intel_max10_device *dev,
+	unsigned int offset, unsigned int val)
 {
-	unsigned int tmp = val;
-
-	if (!dev)
+	if (!dev || !dev->ops->reg_write)
 		return -ENODEV;
 
-	dev_debug(dev, "%s: bus:0x%x, reg:0x%x, val:0x%x\n", __func__,
-			dev->bus, reg, val);
-
-	return spi_transaction_write(dev->spi_tran_dev,
-			reg, 4, (unsigned char *)&tmp);
+	return dev->ops->reg_write(dev, dev->csr->base + offset, val);
 }
 
-int max10_sys_read(struct intel_max10_device *dev,
+int max10_sys_raw_read(struct intel_max10_device *dev,
 	unsigned int offset, unsigned int *val)
 {
-	if (!dev)
+	if (!dev || !dev->ops->reg_read)
 		return -ENODEV;
 
-
-	return max10_reg_read(dev, dev->base + offset, val);
+	return dev->ops->reg_read(dev, offset, val);
 }
 
-int max10_sys_write(struct intel_max10_device *dev,
+int max10_sys_raw_write(struct intel_max10_device *dev,
 	unsigned int offset, unsigned int val)
 {
-	if (!dev)
+	if (!dev || !dev->ops->reg_write)
 		return -ENODEV;
 
-	return max10_reg_write(dev, dev->base + offset, val);
+	return dev->ops->reg_write(dev, offset, val);
 }
 
 int max10_sys_update_bits(struct intel_max10_device *dev, unsigned int offset,
@@ -67,6 +58,402 @@ int max10_sys_update_bits(struct intel_max10_device *dev, unsigned int offset,
 	return max10_sys_write(dev, offset, temp);
 }
 
+static int n3000_bulk_raw_write(struct intel_max10_device *dev, uint32_t addr,
+	void *buf, uint32_t len)
+{
+	uint32_t v = 0;
+	uint32_t i = 0;
+	char *p = buf;
+	int ret = 0;
+
+	len = IFPGA_ALIGN(len, 4);
+
+	for (i = 0; i < len; i += 4) {
+		v = *(uint32_t *)(p + i);
+		ret = max10_sys_raw_write(dev, addr + i, v);
+		if (ret < 0) {
+			dev_err(dev,
+				"Failed to write to staging area 0x%08x [e:%d]\n",
+				addr + i, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int n3000_bulk_raw_read(struct intel_max10_device *dev,
+		uint32_t addr, void *buf, uint32_t len)
+{
+	u32 v, i;
+	char *p = buf;
+	int ret;
+
+	len = IFPGA_ALIGN(len, 4);
+
+	for (i = 0; i < len; i += 4) {
+		ret = max10_sys_raw_read(dev, addr + i, &v);
+		if (ret < 0) {
+			dev_err(dev,
+				"Failed to write to staging area 0x%08x [e:%d]\n",
+				addr + i, ret);
+			return ret;
+		}
+		*(u32 *)(p + i) = v;
+	}
+
+	return 0;
+}
+
+static int n3000_flash_read(struct intel_max10_device *dev,
+		u32 addr, void *buf, u32 size)
+{
+	if (!dev->raw_blk_ops.read_blk)
+		return -ENODEV;
+
+	return dev->raw_blk_ops.read_blk(dev, addr, buf, size);
+}
+
+static int n3000_flash_write(struct intel_max10_device *dev,
+		u32 addr, void *buf, u32 size)
+{
+	if (!dev->raw_blk_ops.write_blk)
+		return -ENODEV;
+
+	return dev->raw_blk_ops.write_blk(dev, addr, buf, size);
+}
+
+static u32
+pmci_get_write_space(struct intel_max10_device *dev, u32 size)
+{
+	u32 count, val;
+	int ret;
+
+	ret = opae_readl_poll_timeout(dev->mmio + PMCI_FLASH_CTRL, val,
+				GET_FIELD(PMCI_FLASH_FIFO_SPACE, val) ==
+				PMCI_FIFO_MAX_WORDS,
+				PMCI_FLASH_INT_US, PMCI_FLASH_TIMEOUT_US);
+	if (ret == -ETIMEDOUT)
+		return 0;
+
+	count = GET_FIELD(PMCI_FLASH_FIFO_SPACE, val) * 4;
+
+	return (size > count) ? count : size;
+}
+
+static void pmci_write_fifo(void __iomem *base, char *buf, size_t count)
+{
+	size_t i;
+	u32 val;
+
+	for (i = 0; i < count/4 ; i++) {
+		val = *(u32 *)(buf + i * 4);
+		writel(val, base);
+	}
+}
+
+static void pmci_read_fifo(void __iomem *base, char *buf, size_t count)
+{
+	size_t i;
+	u32 val;
+
+	for (i = 0; i < count/4; i++) {
+		val = readl(base);
+		*(u32 *)(buf + i * 4) = val;
+	}
+}
+
+static int
+__pmci_flash_bulk_write(struct intel_max10_device *dev, u32 addr,
+		void *buf, u32 size)
+{
+	UNUSED(addr);
+	u32 blk_size, n_offset = 0;
+
+	while (size) {
+		blk_size = pmci_get_write_space(dev, size);
+		if (blk_size == 0) {
+			dev_err(pmci->dev, "get FIFO available size fail\n");
+			return -EIO;
+		}
+		size -= blk_size;
+		pmci_write_fifo(dev->mmio + PMCI_FLASH_FIFO, (char *)buf + n_offset,
+				blk_size);
+		n_offset += blk_size;
+	}
+
+	return 0;
+}
+
+static int
+pmci_flash_bulk_write(struct intel_max10_device *dev, u32 addr,
+		void *buf, u32 size)
+{
+	int ret;
+
+	pthread_mutex_lock(dev->bmc_ops.mutex);
+
+	ret = __pmci_flash_bulk_write(dev, addr, buf, size);
+
+	pthread_mutex_unlock(dev->bmc_ops.mutex);
+	return ret;
+}
+
+static int
+pmci_set_flash_host_mux(struct intel_max10_device *dev, bool request)
+{
+	u32 ctrl;
+	int ret;
+
+	ret = max10_sys_update_bits(dev,
+			m10bmc_base(dev) + M10BMC_PMCI_FLASH_CTRL,
+			FLASH_HOST_REQUEST,
+			SET_FIELD(FLASH_HOST_REQUEST, request));
+	if (ret)
+		return ret;
+
+	return opae_max10_read_poll_timeout(dev, m10bmc_base(dev) + M10BMC_PMCI_FLASH_CTRL,
+			ctrl, request ? (get_flash_mux(ctrl) == FLASH_MUX_HOST) :
+			(get_flash_mux(ctrl) != FLASH_MUX_HOST),
+			PMCI_FLASH_INT_US, PMCI_FLASH_TIMEOUT_US);
+}
+
+static int
+pmci_get_mux(struct intel_max10_device *dev)
+{
+	pthread_mutex_lock(dev->bmc_ops.mutex);
+	return pmci_set_flash_host_mux(dev, true);
+}
+
+static int
+pmci_put_mux(struct intel_max10_device *dev)
+{
+	int ret;
+
+	ret = pmci_set_flash_host_mux(dev, false);
+	pthread_mutex_unlock(dev->bmc_ops.mutex);
+	return ret;
+}
+
+static int
+__pmci_flash_bulk_read(struct intel_max10_device *dev, u32 addr,
+		     void *buf, u32 size)
+{
+	u32 blk_size, offset = 0, val;
+	int ret;
+
+	while (size) {
+		blk_size = min_t(u32, size, PMCI_READ_BLOCK_SIZE);
+
+		opae_writel(addr + offset, dev->mmio + PMCI_FLASH_ADDR);
+
+		opae_writel(SET_FIELD(PMCI_FLASH_READ_COUNT, blk_size / 4)
+				| PMCI_FLASH_RD_MODE,
+			dev->mmio + PMCI_FLASH_CTRL);
+
+		ret = opae_readl_poll_timeout((dev->mmio + PMCI_FLASH_CTRL),
+				val, !(val & PMCI_FLASH_BUSY),
+				PMCI_FLASH_INT_US,
+				PMCI_FLASH_TIMEOUT_US);
+		if (ret) {
+			dev_err(dev, "%s timed out on reading flash 0x%xn",
+				__func__, val);
+			return ret;
+		}
+
+		pmci_read_fifo(dev->mmio + PMCI_FLASH_FIFO, (char *)buf + offset,
+				blk_size);
+
+		size -= blk_size;
+		offset += blk_size;
+
+		opae_writel(0, dev->mmio + PMCI_FLASH_CTRL);
+	}
+
+	return 0;
+}
+
+static int
+pmci_flash_bulk_read(struct intel_max10_device *dev, u32 addr,
+		     void *buf, u32 size)
+{
+	int ret;
+
+	ret = pmci_get_mux(dev);
+	if (ret)
+		return ret;
+
+	ret = __pmci_flash_bulk_read(dev, addr, buf, size);
+	if (ret)
+		goto fail;
+
+	return pmci_put_mux(dev);
+
+fail:
+	pmci_put_mux(dev);
+	return ret;
+}
+
+static int pmci_check_flash_address(u32 start, u32 end)
+{
+	if (start < PMCI_FLASH_START || end > PMCI_FLASH_END)
+		return -EINVAL;
+
+	return 0;
+}
+
+int opae_read_flash(struct intel_max10_device *dev, u32 addr,
+		u32 size, void *buf)
+{
+	int ret;
+
+	if (!dev->bmc_ops.check_flash_range ||
+			!dev->bmc_ops.flash_read)
+		return -ENODEV;
+
+	if (!buf)
+		return -EINVAL;
+
+	ret = dev->bmc_ops.check_flash_range(addr, addr + size);
+	if (ret)
+		return ret;
+
+	ret = dev->bmc_ops.flash_read(dev, addr, buf, size);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int max10_spi_read(struct intel_max10_device *dev,
+	unsigned int addr, unsigned int *val)
+{
+	if (!dev)
+		return -ENODEV;
+
+	dev_debug(dev, "%s: bus:0x%x, addr:0x%x\n", __func__, dev->bus, addr);
+
+	return spi_transaction_read(dev->spi_tran_dev,
+			addr, 4, (unsigned char *)val);
+}
+
+static int max10_spi_write(struct intel_max10_device *dev,
+	unsigned int addr, unsigned int val)
+{
+	unsigned int tmp = val;
+
+	if (!dev)
+		return -ENODEV;
+
+	dev_debug(dev, "%s: bus:0x%x, reg:0x%x, val:0x%x\n", __func__,
+			dev->bus, addr, val);
+
+	return spi_transaction_write(dev->spi_tran_dev,
+			addr, 4, (unsigned char *)&tmp);
+}
+
+static int indirect_bus_clr_cmd(struct intel_max10_device *dev)
+{
+	unsigned int cmd;
+	int ret;
+
+	opae_writel(0, dev->mmio + INDIRECT_CMD_OFF);
+
+	ret = opae_readl_poll_timeout((dev->mmio + INDIRECT_CMD_OFF), cmd,
+				 (!cmd), INDIRECT_INT_US, INDIRECT_TIMEOUT_US);
+
+	if (ret)
+		dev_err(dev, "%s timed out on clearing cmd 0x%x\n",
+				__func__, cmd);
+
+	return ret;
+}
+
+static int max10_indirect_reg_read(struct intel_max10_device *dev,
+	unsigned int addr, unsigned int *val)
+{
+	unsigned int cmd;
+	int ret;
+
+	if (!dev)
+		return -ENODEV;
+
+	pthread_mutex_lock(dev->bmc_ops.mutex);
+
+	cmd = opae_readl(dev->mmio + INDIRECT_CMD_OFF);
+	if (cmd)
+		dev_warn(dev, "%s non-zero cmd 0x%x\n", __func__, cmd);
+
+	opae_writel(addr, dev->mmio + INDIRECT_ADDR_OFF);
+
+	opae_writel(INDIRECT_CMD_RD, dev->mmio + INDIRECT_CMD_OFF);
+
+	ret = opae_readl_poll_timeout((dev->mmio + INDIRECT_CMD_OFF), cmd,
+				 (cmd & INDIRECT_CMD_ACK), INDIRECT_INT_US,
+				 INDIRECT_TIMEOUT_US);
+
+	*val = opae_readl(dev->mmio + INDIRECT_RD_OFF);
+
+	if (ret)
+		dev_err(dev, "%s timed out on reg 0x%x cmd 0x%x\n",
+				__func__, addr, cmd);
+
+	if (indirect_bus_clr_cmd(dev))
+		ret = -ETIME;
+
+	pthread_mutex_unlock(dev->bmc_ops.mutex);
+
+	return ret;
+}
+
+static int max10_indirect_reg_write(struct intel_max10_device *dev,
+	unsigned int addr, unsigned int val)
+{
+	unsigned int cmd;
+	int ret;
+
+	if (!dev)
+		return -ENODEV;
+
+	pthread_mutex_lock(dev->bmc_ops.mutex);
+
+	cmd = readl(dev->mmio + INDIRECT_CMD_OFF);
+
+	if (cmd)
+		dev_warn(dev, "%s non-zero cmd 0x%x\n", __func__, cmd);
+
+	opae_writel(val, dev->mmio + INDIRECT_WR_OFF);
+
+	opae_writel(addr, dev->mmio + INDIRECT_ADDR_OFF);
+
+	writel(INDIRECT_CMD_WR, dev->mmio + INDIRECT_CMD_OFF);
+
+	ret = opae_readl_poll_timeout((dev->mmio + INDIRECT_CMD_OFF), cmd,
+				 (cmd & INDIRECT_CMD_ACK), INDIRECT_INT_US,
+				 INDIRECT_TIMEOUT_US);
+
+	if (ret)
+		dev_err(dev, "%s timed out on reg 0x%x cmd 0x%x\n",
+				__func__, addr, cmd);
+
+	if (indirect_bus_clr_cmd(dev))
+		ret = -ETIME;
+
+	pthread_mutex_unlock(dev->bmc_ops.mutex);
+
+	return ret;
+}
+
+const struct m10bmc_regmap m10bmc_pmci_regmap = {
+	.reg_write = max10_indirect_reg_write,
+	.reg_read = max10_indirect_reg_read,
+};
+
+const struct m10bmc_regmap m10bmc_n3000_regmap = {
+	.reg_write = max10_spi_write,
+	.reg_read = max10_spi_read,
+};
+
 static struct max10_compatible_id max10_id_table[] = {
 	{.compatible = MAX10_PAC,},
 	{.compatible = MAX10_PAC_N3000,},
@@ -122,7 +509,7 @@ static int altera_nor_flash_read(struct intel_max10_device *dev,
 	word_len = len/4;
 
 	for (i = 0; i < word_len; i++) {
-		ret = max10_reg_read(dev, offset + i*4,
+		ret = max10_sys_raw_read(dev, offset + i*4,
 				&value);
 		if (ret)
 			return -EBUSY;
@@ -557,15 +944,13 @@ static int check_max10_version(struct intel_max10_device *dev)
 {
 	unsigned int v;
 
-	if (!max10_reg_read(dev, MAX10_SEC_BASE_ADDR + MAX10_BUILD_VER,
+	if (!max10_sys_raw_read(dev, MAX10_SEC_BASE_ADDR + MAX10_BUILD_VER,
 				&v)) {
 		if (v != 0xffffffff) {
 			dev_info(dev, "secure MAX10 detected\n");
-			dev->base = MAX10_SEC_BASE_ADDR;
 			dev->flags |= MAX10_FLAGS_SECURE;
 		} else {
 			dev_info(dev, "non-secure MAX10 detected\n");
-			dev->base = MAX10_BASE_ADDR;
 		}
 		return 0;
 	}
@@ -648,73 +1033,455 @@ static int max10_staging_area_init(struct intel_max10_device *dev)
 	return 0;
 }
 
-struct intel_max10_device *
-intel_max10_device_probe(struct altera_spi_device *spi,
-		int chipselect)
+int max10_get_fpga_load_info(struct intel_max10_device *dev, unsigned int *val)
 {
-	struct intel_max10_device *dev;
 	int ret;
-	unsigned int val;
+	unsigned int value;
 
-	dev = opae_malloc(sizeof(*dev));
-	if (!dev)
-		return NULL;
+	/* read FPGA loading information */
+	ret = max10_sys_read(dev, dev->csr->fpga_page_info, &value);
+	if (ret) {
+		dev_err(dev, "fail to get FPGA loading info\n");
+		return ret;
+	}
 
-	TAILQ_INIT(&dev->opae_sensor_list);
+	if (dev->type == M10_N3000)
+		*val = value & 0x7;
+	else if (dev->type == M10_N6000) {
+		if (!GET_FIELD(PMCI_FPGA_CONFIGED, value))
+			return -EINVAL;
+		*val = GET_FIELD(PMCI_FPGA_BOOT_PAGE, value);
+	}
 
-	dev->spi_master = spi;
+	return 0;
+}
 
-	dev->spi_tran_dev = spi_transaction_init(spi, chipselect);
-	if (!dev->spi_tran_dev) {
-		dev_err(dev, "%s spi tran init fail\n", __func__);
-		goto free_dev;
-	}
+int max10_get_bmc_version(struct intel_max10_device *dev, unsigned int *val)
+{
+	int ret;
 
-	/* check the max10 version */
-	ret = check_max10_version(dev);
-	if (ret) {
-		dev_err(dev, "Failed to find max10 hardware!\n");
-		goto free_dev;
-	}
+	ret = max10_sys_read(dev, dev->csr->build_version, val);
+	if (ret)
+		return ret;
 
-	/* load the MAX10 device table */
-	ret = init_max10_device_table(dev);
-	if (ret) {
-		dev_err(dev, "Init max10 device table fail\n");
-		goto free_dev;
-	}
+	return 0;
+}
 
-	/* init max10 devices, like sensor*/
-	if (dev->flags & MAX10_FLAGS_SECURE)
-		ret = max10_secure_hw_init(dev);
-	else
-		ret = max10_non_secure_hw_init(dev);
-	if (ret) {
-		dev_err(dev, "Failed to init max10 hardware!\n");
-		goto free_dtb;
+int max10_get_bmcfw_version(struct intel_max10_device *dev, unsigned int *val)
+{
+	int ret;
+
+	ret = max10_sys_read(dev, dev->csr->fw_version, val);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct m10bmc_csr m10bmc_spi_csr = {
+	.base = MAX10_SEC_BASE_ADDR,
+	.build_version = MAX10_BUILD_VER,
+	.fw_version = NIOS2_FW_VERSION,
+	.fpga_page_info = FPGA_PAGE_INFO,
+	.doorbell = MAX10_DOORBELL,
+	.auth_result = MAX10_AUTH_RESULT,
+};
+
+static const struct m10bmc_csr m10bmc_pmci_csr = {
+	.base = M10BMC_PMCI_SYS_BASE,
+	.build_version = M10BMC_PMCI_BUILD_VER,
+	.fw_version = NIOS2_PMCI_FW_VERSION,
+	.fpga_page_info = M10BMC_PMCI_FPGA_CONF_STS,
+	.doorbell = M10BMC_PMCI_DOORBELL,
+	.auth_result = M10BMC_PMCI_AUTH_RESULT,
+};
+
+static const struct max10_sensor_raw_data n6010bmc_temp_tbl[] = {
+	{ 0x444, 0x448, 0x44c, 0x0, 0x0, 500,
+		"FPGA E-TILE Temperature #1" },
+	{ 0x450, 0x454, 0x458, 0x0, 0x0, 500,
+		"FPGA E-TILE Temperature #2" },
+	{ 0x45c, 0x460, 0x464, 0x0, 0x0, 500,
+		"FPGA E-TILE Temperature #3" },
+	{ 0x468, 0x46c, 0x470, 0x0, 0x0, 500,
+		"FPGA E-TILE Temperature #4" },
+	{ 0x474, 0x478, 0x47c, 0x0, 0x0, 500,
+		"FPGA P-TILE Temperature" },
+	{ 0x484, 0x488, 0x48c, 0x0, 0x0, 500,
+		"FPGA FABRIC Digital Temperature#1" },
+	{ 0x490, 0x494, 0x498, 0x0, 0x0, 500,
+		"FPGA FABRIC Digital Temperature#2" },
+	{ 0x49c, 0x4a0, 0x4a4, 0x0, 0x0, 500,
+		"FPGA FABRIC Digital Temperature#3" },
+	{ 0x4a8, 0x4ac, 0x4b0, 0x0, 0x0, 500,
+		"FPGA FABRIC Digital Temperature#4" },
+	{ 0x4b4, 0x4b8, 0x4bc, 0x0, 0x0, 500,
+		"FPGA FABRIC Digital Temperature#5" },
+	{ 0x4c0, 0x4c4, 0x4c8, 0x0, 0x0, 500,
+		"FPGA FABRIC Remote Digital Temperature#1" },
+	{ 0x4cc, 0x4d0, 0x4d4, 0x0, 0x0, 500,
+		"FPGA FABRIC Remote Digital Temperature#2" },
+	{ 0x4d8, 0x4dc, 0x4e0, 0x0, 0x0, 500,
+		"FPGA FABRIC Remote Digital Temperature#3" },
+	{ 0x4e4, 0x4e8, 0x4ec, 0x0, 0x0, 500,
+		"FPGA FABRIC Remote Digital Temperature#4" },
+	{ 0x4f0, 0x4f4, 0x4f8, 0x0, 0x0, 500,
+		"Board Top Near FPGA Temperature" },
+	{ 0x4fc, 0x500, 0x504, 0x52c, 0x0, 500,
+		"Board Bottom Near CVL Temperature" },
+	{ 0x508, 0x50c, 0x510, 0x52c, 0x0, 500,
+		"Board Top East Near VRs Temperature" },
+	{ 0x514, 0x518, 0x51c, 0x52c, 0x0, 500,
+		"Columbiaville Die Temperature" },
+	{ 0x520, 0x524, 0x528, 0x52c, 0x0, 500,
+		"Board Rear Side Temperature" },
+	{ 0x530, 0x534, 0x538, 0x52c, 0x0, 500,
+		"Board Front Side Temperature" },
+	{ 0x53c, 0x540, 0x544, 0x0, 0x0, 500,
+		"QSFP1 Temperature" },
+	{ 0x548, 0x54c, 0x550, 0x0, 0x0, 500,
+		"QSFP2 Temperature" },
+	{ 0x554, 0x0, 0x0, 0x0, 0x0, 500,
+		"FPGA Core Voltage Phase 0 VR Temperature" },
+	{ 0x560, 0x0, 0x0, 0x0, 0x0, 500,
+		"FPGA Core Voltage Phase 1 VR Temperature" },
+	{ 0x56c, 0x0, 0x0, 0x0, 0x0, 500,
+		"FPGA Core Voltage Phase 2 VR Temperature" },
+	{ 0x578, 0x0, 0x0, 0x0, 0x0, 500,
+		"FPGA Core Voltage VR Controller Temperature" },
+	{ 0x584, 0x0, 0x0, 0x0, 0x0, 500,
+		"FPGA VCCH VR Temperature" },
+	{ 0x590, 0x0, 0x0, 0x0, 0x0, 500,
+		"FPGA VCC_1V2 VR Temperature" },
+	{ 0x59c, 0x0, 0x0, 0x0, 0x0, 500,
+		"FPGA VCCH, VCC_1V2 VR Controller Temperature" },
+	{ 0x5a8, 0x0, 0x0, 0x0, 0x0, 500,
+		"3V3 VR Temperature" },
+	{ 0x5b4, 0x5b8, 0x5bc, 0x0, 0x0, 500,
+		"CVL Core Voltage VR Temperature" },
+	{ 0x5c4, 0x5c8, 0x5cc, 0x5c0, 0x0, 500,
+		"FPGA P-Tile Temperature [Remote]" },
+	{ 0x5d0, 0x5d4, 0x5d8, 0x5c0, 0x0, 500,
+		"FPGA E-Tile Temperature [Remote]" },
+	{ 0x5dc, 0x5e0, 0x5e4, 0x5c0, 0x0, 500,
+		"FPGA SDM Temperature [Remote]" },
+	{ 0x5e8, 0x5ec, 0x5f0, 0x5c0, 0x0, 500,
+		"FPGA Corner Temperature [Remote]" },
+};
+
+static const struct max10_sensor_data n6010bmc_tmp_data = {
+	.type = SENSOR_TMP_NAME,
+	.number = ARRAY_SIZE(n6010bmc_temp_tbl),
+	.table = n6010bmc_temp_tbl,
+};
+
+static const struct max10_sensor_raw_data n6010bmc_in_tbl[] = {
+	{ 0x5f4, 0x0, 0x0, 0x0, 0x0, 1,
+		"Inlet 12V PCIe Rail Voltage" },
+	{ 0x60c, 0x0, 0x0, 0x0, 0x0, 1,
+		"Inlet 12V Aux Rail Voltage" },
+	{ 0x624, 0x0, 0x0, 0x0, 0x0, 1,
+		"Inlet 3V3 PCIe Rail Voltage" },
+	{ 0x63c, 0x0, 0x0, 0x0, 0x0, 1,
+		"FPGA Core Voltage Rail Voltage" },
+	{ 0x644, 0x0, 0x0, 0x0, 0x0, 1,
+		"FPGA VCCH Rail Voltage" },
+	{ 0x64c, 0x0, 0x0, 0x0, 0x0, 1,
+		"FPGA VCC_1V2 Rail Voltage" },
+	{ 0x654, 0x0, 0x0, 0x0, 0x0, 1,
+		"FPGA VCCH_GXER_1V1, VCCA_1V8 Voltage" },
+	{ 0x664, 0x0, 0x0, 0x0, 0x0, 1,
+		"FPGA VCCIO_1V2 Voltage" },
+	{ 0x674, 0x0, 0x0, 0x0, 0x0, 1,
+		"CVL Non Core Rails Inlet Voltage" },
+	{ 0x684, 0x0, 0x0, 0x0, 0x0, 1,
+		"MAX10 & Board CLK PWR 3V3 Inlet Voltage" },
+	{ 0x694, 0x0, 0x0, 0x0, 0x0, 1,
+		"CVL Core Voltage Rail Voltage" },
+	{ 0x6ac, 0x0, 0x0, 0x0, 0x0, 1,
+		"Board 3V3 VR Voltage" },
+	{ 0x6b4, 0x0, 0x0, 0x0, 0x0, 1,
+		"QSFP 3V3 Rail Voltage" },
+	{ 0x6c4, 0x0, 0x0, 0x0, 0x0, 1,
+		"QSFP (Primary) Supply Rail Voltage" },
+	{ 0x6c8, 0x0, 0x0, 0x0, 0x0, 1,
+		"QSFP (Secondary) Supply Rail Voltage" },
+	{ 0x6cc, 0x0, 0x0, 0x0, 0x0, 1,
+		"VCCCLK_GXER_2V5 Voltage" },
+	{ 0x6d0, 0x0, 0x0, 0x0, 0x0, 1,
+		"AVDDH_1V1_CVL Voltage" },
+	{ 0x6d4, 0x0, 0x0, 0x0, 0x0, 1,
+		"VDDH_1V8_CVL Voltage" },
+	{ 0x6d8, 0x0, 0x0, 0x0, 0x0, 1,
+		"VCCA_PLL Voltage" },
+	{ 0x6e0, 0x0, 0x0, 0x0, 0x0, 1,
+		"VCCRT_GXER_0V9 Voltage" },
+	{ 0x6e8, 0x0, 0x0, 0x0, 0x0, 1,
+		"VCCRT_GXEL_0V9 Voltage" },
+	{ 0x6f0, 0x0, 0x0, 0x0, 0x0, 1,
+		"VCCH_GXPL_1V8 Voltage" },
+	{ 0x6f4, 0x0, 0x0, 0x0, 0x0, 1,
+		"VCCPT_1V8 Voltage" },
+	{ 0x6fc, 0x0, 0x0, 0x0, 0x0, 1,
+		"VCC_3V3_M10 Voltage" },
+	{ 0x700, 0x0, 0x0, 0x0, 0x0, 1,
+		"VCC_1V8_M10 Voltage" },
+	{ 0x704, 0x0, 0x0, 0x0, 0x0, 1,
+		"VCC_1V2_EMIF1_2_3 Voltage" },
+	{ 0x70c, 0x0, 0x0, 0x0, 0x0, 1,
+		"VCC_1V2_EMIF4_5 Voltage" },
+	{ 0x714, 0x0, 0x0, 0x0, 0x0, 1,
+		"VCCA_1V8 Voltage" },
+	{ 0x718, 0x0, 0x0, 0x0, 0x0, 1,
+		"VCCH_GXER_1V1 Voltage" },
+	{ 0x71c, 0x0, 0x0, 0x0, 0x0, 1,
+		"AVDD_ETH_0V9_CVL Voltage" },
+	{ 0x720, 0x0, 0x0, 0x0, 0x0, 1,
+		"AVDD_PCIE_0V9_CVL Voltage" },
+};
+
+static const struct max10_sensor_data n6010bmc_in_data = {
+	.type = SENSOR_IN_NAME,
+	.number = ARRAY_SIZE(n6010bmc_in_tbl),
+	.table = n6010bmc_in_tbl,
+};
+
+static const struct max10_sensor_raw_data n6010bmc_curr_tbl[] = {
+	{ 0x600, 0x604, 0x608, 0x0, 0x0, 1,
+		"Inlet 12V PCIe Rail Current" },
+	{ 0x618, 0x61c, 0x620, 0x0, 0x0, 1,
+		"Inlet 12V Aux Rail Current" },
+	{ 0x630, 0x634, 0x638, 0x0, 0x0, 1,
+		"Inlet 3V3 PCIe Rail Current" },
+	{ 0x640, 0x0, 0x0, 0x0, 0x0, 1,
+		"FPGA Core Voltage Rail Current" },
+	{ 0x648, 0x0, 0x0, 0x0, 0x0, 1,
+		"FPGA VCCH Rail Current" },
+	{ 0x650, 0x0, 0x0, 0x0, 0x0, 1,
+		"FPGA VCC_1V2 Rail Current" },
+	{ 0x658, 0x65c, 0x660, 0x0, 0x0, 1,
+		"FPGA VCCH_GXER_1V1, VCCA_1V8 Current" },
+	{ 0x668, 0x66c, 0x670, 0x0, 0x0, 1,
+		"FPGA VCCIO_1V2 Current" },
+	{ 0x678, 0x67c, 0x680, 0x0, 0x0, 1,
+		"CVL Non Core Rails Inlet Current" },
+	{ 0x688, 0x68c, 0x680, 0x0, 0x0, 1,
+		"MAX10 & Board CLK PWR 3V3 Inlet Current" },
+	{ 0x690, 0x0, 0x0, 0x0, 0x0, 1,
+		"CVL Core Voltage Rail Current" },
+	{ 0x6b0, 0x0, 0x0, 0x0, 0x0, 1,
+		"Board 3V3 VR Current" },
+	{ 0x6b8, 0x6bc, 0x670, 0x0, 0x0, 1,
+		"QSFP 3V3 Rail Current" },
+};
+
+static const struct max10_sensor_data n6010bmc_curr_data = {
+	.type = SENSOR_CURR_NAME,
+	.number = ARRAY_SIZE(n6010bmc_curr_tbl),
+	.table = n6010bmc_curr_tbl,
+};
+
+static const struct max10_sensor_raw_data n6010bmc_power_tbl[] = {
+	{ 0x724, 0x0, 0x0, 0x0, 0x0, 1000, "Board Power" },
+};
+
+static const struct max10_sensor_data n6010bmc_power_data = {
+	.type = SENSOR_POWER_NAME,
+	.number = ARRAY_SIZE(n6010bmc_power_tbl),
+	.table = n6010bmc_power_tbl,
+};
+
+static const struct max10_sensor_board_data n6010bmc_sensor_board_data = {
+	.tables = {
+		[sensor_temp] = &n6010bmc_tmp_data,
+		[sensor_in] = &n6010bmc_in_data,
+		[sensor_curr] = &n6010bmc_curr_data,
+		[sensor_power] = &n6010bmc_power_data,
+	},
+};
+
+static int get_sensor_data(struct intel_max10_device *dev,
+		struct opae_sensor_info *sensor,
+		unsigned int *value,
+		unsigned int reg,
+		unsigned int flags)
+{
+	int ret;
+	unsigned int data;
+
+	if (!reg)
+		return 0;
+
+	ret = max10_sys_read(dev, reg, &data);
+	if (ret)
+		return ret;
+
+	if (data == SENSOR_INVALID) {
+		dev_debug(dev, "%s: sensor:%s invalid 0x%x at:%d\n",
+				__func__, sensor->name, data, reg);
+		return ret;
 	}
 
-	/* read FPGA loading information */
-	ret = max10_sys_read(dev, FPGA_PAGE_INFO, &val);
-	if (ret) {
-		dev_err(dev, "fail to get FPGA loading info\n");
-		goto release_max10_hw;
+	*value = data * sensor->multiplier;
+	sensor->flags |= flags;
+
+	return 0;
+}
+
+static int max10_parse_sensor_data(struct intel_max10_device *dev,
+		const struct max10_sensor_data *sdata)
+{
+	struct opae_sensor_info *sensor;
+	const struct max10_sensor_raw_data *raw;
+	const struct max10_sensor_raw_data *table =
+		(const struct max10_sensor_raw_data *)sdata->table;
+	unsigned int i;
+	static unsigned int sensor_id;
+	int ret = 0;
+
+	for (i = 0; i < sdata->number; i++) {
+		raw = &table[i];
+
+		sensor = opae_zmalloc(sizeof(*sensor));
+		if (!sensor) {
+			ret = -EINVAL;
+			goto free_sensor;
+		}
+
+		sensor->type = sdata->type;
+		sensor->id = sensor_id++;
+
+		if (!raw->reg_input)
+			continue;
+
+		sensor->value_reg = raw->reg_input;
+		sensor->multiplier = raw->multiplier;
+		sensor->name = raw->label;
+
+		ret = get_sensor_data(dev, sensor,
+				&sensor->high_warn,
+				raw->reg_high_warn,
+				OPAE_SENSOR_HIGH_WARN_VALID);
+		if (ret)
+			break;
+
+		ret = get_sensor_data(dev, sensor,
+				&sensor->high_fatal,
+				raw->reg_high_fatal,
+				OPAE_SENSOR_HIGH_FATAL_VALID);
+		if (ret)
+			break;
+
+		ret = get_sensor_data(dev, sensor,
+				&sensor->hysteresis,
+				raw->reg_hyst,
+				OPAE_SENSOR_HYSTERESIS_VALID);
+		if (ret)
+			break;
+
+		ret = get_sensor_data(dev, sensor,
+				&sensor->low_warn,
+				raw->reg_low_warn,
+				OPAE_SENSOR_LOW_WARN_VALID);
+		if (ret)
+			break;
+
+		sensor->flags |= OPAE_SENSOR_VALID;
+
+		TAILQ_INSERT_TAIL(&dev->opae_sensor_list, sensor, node);
+		dev_info(dev, "found valid sensor: %s\n", sensor->name);
 	}
-	dev_info(dev, "FPGA loaded from %s Image\n", val ? "User" : "Factory");
 
-	return dev;
+	return ret;
 
-release_max10_hw:
+free_sensor:
 	max10_sensor_uinit(dev);
-free_dtb:
-	if (dev->fdt_root)
-		opae_free(dev->fdt_root);
-	if (dev->spi_tran_dev)
-		spi_transaction_remove(dev->spi_tran_dev);
-free_dev:
-	opae_free(dev);
+	return ret;
+}
 
-	return NULL;
+static int max10_sensor_init_table(struct intel_max10_device *dev,
+		const struct max10_sensor_board_data *data)
+{
+	int ret = 0;
+	unsigned int i;
+	const struct max10_sensor_data *sdata;
+
+	for (i = 0; i < ARRAY_SIZE(data->tables); i++) {
+		sdata = data->tables[i];
+		if (!sdata)
+			continue;
+		ret = max10_parse_sensor_data(dev, sdata);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+int
+intel_max10_device_init(struct intel_max10_device *dev)
+{
+	int ret = 0;
+
+	TAILQ_INIT(&dev->opae_sensor_list);
+
+
+	if (dev->type == M10_N3000) {
+		dev->ops = &m10bmc_n3000_regmap;
+		dev->csr = &m10bmc_spi_csr;
+
+		dev->raw_blk_ops.write_blk = n3000_bulk_raw_write;
+		dev->raw_blk_ops.read_blk = n3000_bulk_raw_read;
+		dev->bmc_ops.flash_read = n3000_flash_read;
+		dev->bmc_ops.flash_write = n3000_flash_write;
+
+		/* check the max10 version */
+		ret = check_max10_version(dev);
+		if (ret) {
+			dev_err(dev, "Failed to find max10 hardware!\n");
+			return ret;
+		}
+
+		/* load the MAX10 device table */
+		ret = init_max10_device_table(dev);
+		if (ret) {
+			dev_err(dev, "Init max10 device table fail\n");
+			return ret;
+		}
+
+		/* init max10 devices, like sensor*/
+		if (dev->flags & MAX10_FLAGS_SECURE)
+			ret = max10_secure_hw_init(dev);
+		else
+			ret = max10_non_secure_hw_init(dev);
+		if (ret) {
+			dev_err(dev, "Failed to init max10 hardware!\n");
+			opae_free(dev->fdt_root);
+			return ret;
+		}
+	} else if (dev->type == M10_N6000) {
+		dev->ops = &m10bmc_pmci_regmap;
+		dev->csr = &m10bmc_pmci_csr;
+		dev->staging_area_size = MAX_STAGING_AREA_SIZE;
+		dev->flags |= MAX10_FLAGS_SECURE;
+
+		dev->bmc_ops.flash_read = pmci_flash_bulk_read;
+		dev->bmc_ops.flash_write = pmci_flash_bulk_write;
+		dev->bmc_ops.check_flash_range = pmci_check_flash_address;
+
+		ret = max10_sensor_init_table(dev, &n6010bmc_sensor_board_data);
+		if (ret)
+			return ret;
+
+		ret = pthread_mutex_init(&dev->bmc_ops.lock, NULL);
+		if (ret)
+			return ret;
+
+		if (!dev->bmc_ops.mutex)
+			dev->bmc_ops.mutex = &dev->bmc_ops.lock;
+	}
+
+	return ret;
 }
 
 int intel_max10_device_remove(struct intel_max10_device *dev)
@@ -722,15 +1489,14 @@ int intel_max10_device_remove(struct intel_max10_device *dev)
 	if (!dev)
 		return 0;
 
-	max10_sensor_uinit(dev);
+	pthread_mutex_destroy(&dev->bmc_ops.lock);
 
-	if (dev->spi_tran_dev)
-		spi_transaction_remove(dev->spi_tran_dev);
+	if (dev->type == M10_N3000) {
+		max10_sensor_uinit(dev);
 
-	if (dev->fdt_root)
-		opae_free(dev->fdt_root);
-
-	opae_free(dev);
+		if (dev->fdt_root)
+			opae_free(dev->fdt_root);
+	}
 
 	return 0;
 }
diff --git a/drivers/raw/ifpga/base/opae_intel_max10.h b/drivers/raw/ifpga/base/opae_intel_max10.h
index e761d7e..ead48ea 100644
--- a/drivers/raw/ifpga/base/opae_intel_max10.h
+++ b/drivers/raw/ifpga/base/opae_intel_max10.h
@@ -7,6 +7,9 @@
 
 #include "opae_osdep.h"
 #include "opae_spi.h"
+#include "ifpga_compat.h"
+
+struct intel_max10_device;
 
 struct max10_compatible_id {
 	char compatible[128];
@@ -29,6 +32,64 @@ struct max10_compatible_id {
 /** List of opae sensors */
 TAILQ_HEAD(opae_sensor_list, opae_sensor_info);
 
+/* Supported MAX10 BMC types */
+enum m10bmc_type {
+	M10_N3000,
+	M10_N6000
+};
+
+struct regmap_range {
+	unsigned int min;
+	unsigned int max;
+};
+
+struct m10bmc_regmap {
+	int (*reg_write)(struct intel_max10_device *dev,
+			unsigned int reg, unsigned int val);
+	int (*reg_read)(struct intel_max10_device *dev,
+			unsigned int reg, unsigned int *val);
+	const struct regmap_range *range;
+	int num_ranges;
+};
+
+struct m10bmc_csr {
+	unsigned int base;
+	unsigned int build_version;
+	unsigned int fw_version;
+	unsigned int fpga_page_info;
+	unsigned int doorbell;
+	unsigned int auth_result;
+};
+
+/**
+ * struct flash_raw_blk_ops - device specific operations for flash R/W
+ * @write_blk: write a block of data to flash
+ * @read_blk: read a block of data from flash
+ */
+struct flash_raw_blk_ops {
+	int (*write_blk)(struct intel_max10_device *dev, uint32_t addr,
+			void *buf, uint32_t size);
+	int (*read_blk)(struct intel_max10_device *dev, uint32_t addr,
+			void *buf, uint32_t size);
+};
+
+/**
+ * struct m10bmc_ops - device specific operations
+ * @lock: prevent concurrent flash read/write
+ * @mutex: prevent concurrent bmc read/write
+ * @flash_read: read a block of data from flash
+ * @flash_write: write a block of data to flash
+ */
+struct m10bmc_ops {
+	pthread_mutex_t lock;
+	pthread_mutex_t *mutex;
+	int (*check_flash_range)(u32 start, u32 end);
+	int (*flash_read)(struct intel_max10_device *dev, u32 addr,
+			void *buf, u32 size);
+	int (*flash_write)(struct intel_max10_device *dev, u32 addr,
+			void *buf, u32 size);
+};
+
 struct intel_max10_device {
 	unsigned int flags; /*max10 hardware capability*/
 	struct altera_spi_device *spi_master;
@@ -40,6 +101,12 @@ struct intel_max10_device {
 	struct opae_sensor_list opae_sensor_list;
 	u32 staging_area_base;
 	u32 staging_area_size;
+	enum m10bmc_type type;
+	const struct m10bmc_regmap *ops;
+	const struct m10bmc_csr *csr;
+	struct flash_raw_blk_ops raw_blk_ops;
+	struct m10bmc_ops bmc_ops;
+	u8 *mmio; /* mmio address for PMCI */
 };
 
 /* retimer speed */
@@ -87,6 +154,7 @@ struct opae_retimer_status {
 /* System Registers */
 #define MAX10_BASE_ADDR		0x300400
 #define MAX10_SEC_BASE_ADDR	0x300800
+
 /* Register offset of system registers */
 #define NIOS2_FW_VERSION	0x0
 #define MAX10_MACADDR1		0x10
@@ -151,6 +219,32 @@ struct opae_retimer_status {
 #define   SEC_STATUS_NON_INC		0x6
 #define   SEC_STATUS_ERASE_FAIL		0x7
 #define   SEC_STATUS_WEAROUT		0x8
+#define   SEC_STATUS_PMCI_SS_FAIL           0x9
+#define   SEC_STATUS_FLASH_CMD              0xa
+#define   SEC_STATUS_FACTORY_UNVERITY       0xb
+#define   SEC_STATUS_FACTORY_ACTIVE         0xc
+#define   SEC_STATUS_POWER_DOWN             0xd
+#define   SEC_STATUS_CANCELLATION           0xe
+#define   SEC_STATUS_HASH                   0xf
+#define   SEC_STATUS_FLASH_ACCESS           0x10
+#define   SEC_STATUS_SDM_PR_CERT            0x20
+#define   SEC_STATUS_SDM_PR_NIOS_BUSY       0x21
+#define   SEC_STATUS_SDM_PR_TIMEOUT         0x22
+#define   SEC_STATUS_SDM_PR_FAILED          0x23
+#define   SEC_STATUS_SDM_PR_MISMATCH        0x24
+#define   SEC_STATUS_SDM_PR_FLUSH           0x25
+#define   SEC_STATUS_SDM_SR_CERT            0x30
+#define   SEC_STATUS_SDM_SR_NIOS_BUSY       0x31
+#define   SEC_STATUS_SDM_SR_TIMEOUT         0x32
+#define   SEC_STATUS_SDM_SR_FAILED          0x33
+#define   SEC_STATUS_SDM_SR_MISMATCH        0x34
+#define   SEC_STATUS_SDM_SR_FLUSH           0x35
+#define   SEC_STATUS_SDM_KEY_CERT           0x40
+#define   SEC_STATUS_SDM_KEY_NIOS_BUSY      0x41
+#define   SEC_STATUS_SDM_KEY_TIMEOUT        0x42
+#define   SEC_STATUS_SDM_KEY_FAILED         0x43
+#define   SEC_STATUS_SDM_KEY_MISMATCH       0x44
+#define   SEC_STATUS_SDM_KEY_FLUSH          0x45
 #define   SEC_STATUS_NIOS_OK		0x80
 #define   SEC_STATUS_USER_OK		0x81
 #define   SEC_STATUS_FACTORY_OK		0x82
@@ -158,9 +252,65 @@ struct opae_retimer_status {
 #define   SEC_STATUS_FACTORY_FAIL	0x84
 #define   SEC_STATUS_NIOS_FLASH_ERR	0x85
 #define   SEC_STATUS_FPGA_FLASH_ERR	0x86
+#define   SEC_STATUS_MAX   SEC_STATUS_FPGA_FLASH_ERR
+
+/* Authentication status */
+#define SEC_AUTH_G(v)	((v) & 0xff)
+#define AUTH_STAT_PASS    0x0
+#define AUTH_STAT_B0_MAGIC   0x1
+#define AUTH_STAT_CONLEN  0x2
+#define AUTH_STAT_CONTYPE 0x3
+#define AUTH_STAT_B1_MAGIC 0x4
+#define AUTH_STAT_ROOT_MAGIC 0x5
+#define AUTH_STAT_CURVE_MAGIC 0x6
+#define AUTH_STAT_PERMISSION 0x7
+#define AUTH_STAT_KEY_ID    0x8
+#define AUTH_STAT_CSK_MAGIC 0x9
+#define AUTH_STAT_CSK_CURVE 0xa
+#define AUTH_STAT_CSK_PERMISSION 0xb
+#define AUTH_STAT_CSK_ID    0xc
+#define AUTH_STAT_CSK_SM 0xd
+#define AUTH_STAT_B0_E_MAGIC 0xe
+#define AUTH_STAT_B0_E_SIGN 0xf
+#define AUTH_STAT_RK_P      0x10
+#define AUTH_STAT_RE_SHA    0x11
+#define AUTH_STAT_CSK_SHA   0x12
+#define AUTH_STAT_B0_SHA    0x13
+#define AUTH_STAT_KEY_INV   0x14
+#define AUTH_STAT_KEY_CAN   0x15
+#define AUTH_STAT_UP_SHA    0x16
+#define AUTH_STAT_CAN_SHA   0x17
+#define AUTH_STAT_HASH      0x18
+#define AUTH_STAT_INV_ID    0x19
+#define AUTH_STAT_KEY_PROG  0x1a
+#define AUTH_STAT_INV_BC    0x1b
+#define AUTH_STAT_INV_SLOT  0x1c
+#define AUTH_STAT_IN_OP     0x1d
+#define AUTH_STAT_TIME_OUT  0X1e
+#define AUTH_STAT_SHA_TO    0x1f
+#define AUTH_STAT_CSK_TO    0x20
+#define AUTH_STAT_B0_TO     0x21
+#define AUTH_STAT_UP_TO     0x22
+#define AUTH_STAT_CAN_TO    0x23
+#define AUTH_STAT_HASH_TO   0x24
+#define AUTH_STAT_AUTH_IDLE 0xfe
+#define AUTH_STAT_GA_FAIL   0xff
+#define AUTH_STAT_S_ERR     0x8000
+#define AUTH_STAT_S_MN      0x8001
+#define AUTH_STAT_SH_CRC     0x8002
+#define AUTH_STAT_SD_CRC    0x8003
+#define AUTH_STAT_SD_LEN    0x8004
+#define AUTH_STAT_S_ID      0x8005
+#define AUTH_STAT_S_THR    0x8006
+#define AUTH_STAT_S_TO      0x8007
+#define AUTH_STAT_S_EN     0x8008
+#define AUTH_STAT_SF       0x8009
+#define AUTH_STAT_MAX    AUTH_STAT_SF
+
 #define   CONFIG_SEL		BIT(28)
 #define   CONFIG_SEL_S(v)	(((v) & 0x1) << 28)
 #define   REBOOT_REQ		BIT(29)
+#define   REBOOT_DISABLED	BIT(30)
 #define MAX10_AUTH_RESULT	0x404
 
 /* PKVL related registers, in system register region */
@@ -185,22 +335,26 @@ struct opae_retimer_status {
 #define MAX_STAGING_AREA_BASE	0xffffffff
 #define MAX_STAGING_AREA_SIZE	0x3800000
 
-int max10_reg_read(struct intel_max10_device *dev,
-	unsigned int reg, unsigned int *val);
-int max10_reg_write(struct intel_max10_device *dev,
-	unsigned int reg, unsigned int val);
+#define m10bmc_base(max10) ((max10)->csr->base)
+#define doorbell_reg(max10) ((max10)->csr->doorbell)
+#define auth_result_reg(max10) ((max10)->csr->auth_result)
+
 int max10_sys_read(struct intel_max10_device *dev,
 	unsigned int offset, unsigned int *val);
 int max10_sys_write(struct intel_max10_device *dev,
 	unsigned int offset, unsigned int val);
+int max10_sys_raw_read(struct intel_max10_device *dev,
+	unsigned int offset, unsigned int *val);
+int max10_sys_raw_write(struct intel_max10_device *dev,
+	unsigned int offset, unsigned int val);
 int max10_sys_update_bits(struct intel_max10_device *dev,
 	unsigned int offset, unsigned int msk, unsigned int val);
-struct intel_max10_device *
-intel_max10_device_probe(struct altera_spi_device *spi,
-		int chipselect);
+int max10_get_bmcfw_version(struct intel_max10_device *dev, unsigned int *val);
+int max10_get_bmc_version(struct intel_max10_device *dev, unsigned int *val);
+int max10_get_fpga_load_info(struct intel_max10_device *dev, unsigned int *val);
+int intel_max10_device_init(struct intel_max10_device *dev);
 int intel_max10_device_remove(struct intel_max10_device *dev);
 
-
 #define SENSOR_REG_VALUE 0x0
 #define SENSOR_REG_HIGH_WARN 0x1
 #define SENSOR_REG_HIGH_FATAL 0x2
@@ -254,4 +408,147 @@ struct opae_sensor_info {
 	unsigned int value_reg;
 };
 
+#define SENSOR_INVALID 0xdeadbeef
+
+struct max10_sensor_raw_data {
+	unsigned int reg_input;
+	unsigned int reg_high_warn;
+	unsigned int reg_high_fatal;
+	unsigned int reg_hyst;
+	unsigned int reg_low_warn;
+	unsigned int multiplier;
+	const char *label;
+};
+
+struct max10_sensor_data {
+	const char *type;
+	unsigned int number;
+	const struct max10_sensor_raw_data *table;
+};
+
+enum max10_sensor_types {
+	sensor_temp,
+	sensor_in,
+	sensor_curr,
+	sensor_power,
+	sensor_max,
+};
+
+#define SENSOR_TMP_NAME "Temperature"
+#define SENSOR_IN_NAME "Voltage"
+#define SENSOR_CURR_NAME "Current"
+#define SENSOR_POWER_NAME "Power"
+
+struct max10_sensor_board_data {
+	const struct max10_sensor_data *tables[sensor_max];
+};
+
+/* indirect access for PMCI */
+#define PMCI_INDIRECT_BASE 0x400
+#define INDIRECT_CMD_OFF   (PMCI_INDIRECT_BASE + 0x0)
+#define INDIRECT_CMD_RD	BIT(0)
+#define INDIRECT_CMD_WR	BIT(1)
+#define INDIRECT_CMD_ACK	BIT(2)
+
+#define INDIRECT_ADDR_OFF	 (PMCI_INDIRECT_BASE + 0x4)
+#define INDIRECT_RD_OFF	         (PMCI_INDIRECT_BASE + 0x8)
+#define INDIRECT_WR_OFF	 (PMCI_INDIRECT_BASE + 0xc)
+
+#define INDIRECT_INT_US	1
+#define INDIRECT_TIMEOUT_US	10000
+
+#define M10BMC_PMCI_SYS_BASE 0x0
+#define M10BMC_PMCI_SYS_END  0xfff
+
+#define M10BMC_PMCI_BUILD_VER   0x0
+#define NIOS2_PMCI_FW_VERSION   0x4
+
+#define M10BMC_PMCI_PWR_STATE 0xb4
+#define PMCI_PRIMARY_IMAGE_PAGE GENMASK(10, 8)
+
+#define M10BMC_PMCI_DOORBELL 0x1c0
+#define PMCI_DRBL_REBOOT_DISABLED BIT(1)
+#define M10BMC_PMCI_AUTH_RESULT 0x1c4
+
+#define M10BMC_PMCI_MAX10_RECONF 0xfc
+#define PMCI_MAX10_REBOOT_REQ BIT(0)
+#define PMCI_MAX10_REBOOT_PAGE BIT(1)
+
+#define M10BMC_PMCI_FPGA_RECONF 0xb8
+#define PMCI_FPGA_RECONF_PAGE  GENMASK(22, 20)
+#define PMCI_FPGA_RP_LOAD      BIT(23)
+
+#define PMCI_FLASH_CTRL 0x40
+#define PMCI_FLASH_WR_MODE BIT(0)
+#define PMCI_FLASH_RD_MODE BIT(1)
+#define PMCI_FLASH_BUSY    BIT(2)
+#define PMCI_FLASH_FIFO_SPACE GENMASK(13, 4)
+#define PMCI_FLASH_READ_COUNT GENMASK(25, 16)
+
+#define PMCI_FLASH_INT_US       1
+#define PMCI_FLASH_TIMEOUT_US   10000
+
+#define PMCI_FLASH_ADDR 0x44
+#define PMCI_FLASH_FIFO 0x800
+#define PMCI_READ_BLOCK_SIZE 0x800
+#define PMCI_FIFO_MAX_BYTES 0x800
+#define PMCI_FIFO_MAX_WORDS (PMCI_FIFO_MAX_BYTES / 4)
+
+#define M10BMC_PMCI_FPGA_POC	0xb0
+#define PMCI_FPGA_POC		BIT(0)
+#define PMCI_NIOS_REQ_CLEAR	BIT(1)
+#define PMCI_NIOS_STATUS	GENMASK(5, 4)
+#define NIOS_STATUS_IDLE	0
+#define NIOS_STATUS_SUCCESS	1
+#define NIOS_STATUS_FAIL	2
+#define PMCI_USER_IMAGE_PAGE	GENMASK(10, 8)
+#define POC_USER_IMAGE_1	1
+#define POC_USER_IMAGE_2	2
+#define PMCI_FACTORY_IMAGE_SEL	BIT(31)
+
+#define M10BMC_PMCI_FPGA_CONF_STS 0xa0
+#define PMCI_FPGA_BOOT_PAGE  GENMASK(2, 0)
+#define PMCI_FPGA_CONFIGED   BIT(3)
+
+#define M10BMC_PMCI_FLASH_CTRL 0x1d0
+#define FLASH_MUX_SELECTION GENMASK(2, 0)
+#define FLASH_MUX_IDLE 0
+#define FLASH_MUX_NIOS 1
+#define FLASH_MUX_HOST 2
+#define FLASH_MUX_PFL  4
+#define get_flash_mux(mux)  GET_FIELD(FLASH_MUX_SELECTION, mux)
+#define FLASH_NIOS_REQUEST BIT(4)
+#define FLASH_HOST_REQUEST BIT(5)
+
+#define M10BMC_PMCI_SDM_CTRL_STS 0x230
+#define PMCI_SDM_IMG_REQ	BIT(0)
+#define PMCI_SDM_STAT GENMASK(23, 16)
+
+#define SDM_STAT_DONE    0x0
+#define SDM_STAT_PROV    0x1
+#define SDM_STAT_BUSY    0x2
+#define SDM_STAT_INV     0x3
+#define SDM_STAT_FAIL    0x4
+#define SDM_STAT_BMC_BUSY 0x5
+#define SDM_STAT_TO      0x6
+#define SDM_STAT_DB      0x7
+#define SDM_STAT_CON_R    0x8
+#define SDM_STAT_CON_E    0x9
+#define SDM_STAT_WAIT     0xa
+#define SDM_STAT_RTO      0xb
+#define SDM_STAT_SB       0xc
+#define SDM_STAT_RE       0xd
+#define SDM_STAT_PDD     0xe
+#define SDM_STAT_ISC     0xf
+#define SDM_STAT_SIC     0x10
+#define SDM_STAT_NO_PROV  0x11
+#define SDM_STAT_CS_MIS   0x12
+#define SDM_STAT_PR_MIS   0x13
+#define SDM_STAT_MAX SDM_STAT_PR_MIS
+
+#define PMCI_FLASH_START 0x10000
+#define PMCI_FLASH_END 0xC7FFFFF
+
+int opae_read_flash(struct intel_max10_device *dev, u32 addr,
+		u32 size, void *buf);
 #endif
diff --git a/drivers/raw/ifpga/base/opae_osdep.h b/drivers/raw/ifpga/base/opae_osdep.h
index 18e6a11..033b7e0 100644
--- a/drivers/raw/ifpga/base/opae_osdep.h
+++ b/drivers/raw/ifpga/base/opae_osdep.h
@@ -79,15 +79,38 @@ struct uuid {
 #define time_before(a, b)	time_after(b, a)
 #define opae_memset(a, b, c)    memset((a), (b), (c))
 
-#define opae_readq_poll_timeout(addr, val, cond, invl, timeout)\
-({									     \
-	int wait = 0;							     \
-	for (; wait <= timeout; wait += invl) {			     \
-		(val) = opae_readq(addr);				     \
-		if (cond)                  \
-			break;						     \
-		udelay(invl);						     \
-	}								     \
-	(cond) ? 0 : -ETIMEDOUT;	  \
+#define readx_poll_timeout(op, val, cond, invl, timeout, args...) \
+({                                                                \
+	unsigned long __wait = 0;                                     \
+	unsigned long __invl = (invl);                                \
+	unsigned long __timeout = (timeout);                          \
+	for (; __wait <= __timeout; __wait += __invl) {               \
+		(val) = op(args);                                         \
+		if (cond)                                                 \
+			break;                                                \
+		udelay(__invl);                                           \
+	}                                                             \
+	(cond) ? 0 : -ETIMEDOUT;                                      \
 })
+
+#define opae_readq_poll_timeout(addr, val, cond, invl, timeout) \
+	readx_poll_timeout(opae_readq, val, cond, invl, timeout, addr)
+
+#define opae_readl_poll_timeout(addr, val, cond, invl, timeout) \
+	readx_poll_timeout(opae_readl, val, cond, invl, timeout, addr)
+
+#define opae_readw_poll_timeout(addr, val, cond, invl, timeout) \
+	readx_poll_timeout(opae_readw, val, cond, invl, timeout, addr)
+
+#define opae_readb_poll_timeout(addr, val, cond, invl, timeout) \
+	readx_poll_timeout(opae_readb, val, cond, invl, timeout, addr)
+
+#define opae_max10_read_poll_timeout(dev, addr, value, cond, invl, timeout) \
+({ \
+	int __ret, __tmp; \
+	__tmp = readx_poll_timeout(max10_sys_read, __ret, __ret || (cond), \
+			invl, timeout, (dev), (addr), &(value)); \
+	__ret?:__tmp; \
+})
+
 #endif
diff --git a/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h b/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h
index 3ff49a8..68499e6 100644
--- a/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h
+++ b/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h
@@ -39,6 +39,16 @@
 #define min(a, b) RTE_MIN(a, b)
 #define max(a, b) RTE_MAX(a, b)
 
+#define min_t(type, x, y) ({                    \
+	type __min1 = (x);                      \
+	type __min2 = (y);                      \
+	__min1 < __min2 ? __min1 : __min2; })
+
+#define max_t(type, x, y) ({                    \
+	type __max1 = (x);                      \
+	type __max2 = (y);                      \
+	__max1 > __max2 ? __max1 : __max2; })
+
 #define spinlock_t rte_spinlock_t
 #define spinlock_init(x) rte_spinlock_init(x)
 #define spinlock_lock(x) rte_spinlock_lock(x)
