[v3,1/4] raw/ifpga/base: add PMCI base driver

Message ID 1655450375-10739-2-git-send-email-wei.huang@intel.com (mailing list archive)
State Accepted, archived
Delegated to: Thomas Monjalon
Headers
Series introduce PMCI driver |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Wei Huang June 17, 2022, 7:19 a.m. UTC
  PMCI (Platform Management Control Interface) is a new module in FPGA,
which is designed to cooperate with BMC chip to fulfill board management
functions.
This base driver implements interfaces to access registers of BMC chip.

Signed-off-by: Wei Huang <wei.huang@intel.com>
---
v2: fix typo. 'spi_master' is not misspelled and is not introduced
    in this patch
---
v3: split PMCI driver into several patches
---
 drivers/raw/ifpga/base/ifpga_defines.h     |   2 +
 drivers/raw/ifpga/base/ifpga_feature_dev.c |   2 +
 drivers/raw/ifpga/base/ifpga_feature_dev.h |   1 +
 drivers/raw/ifpga/base/ifpga_fme.c         | 142 ++++++++++++--
 drivers/raw/ifpga/base/opae_intel_max10.c  | 297 ++++++++++++++++++++---------
 drivers/raw/ifpga/base/opae_intel_max10.h  | 229 +++++++++++++++++++++-
 drivers/raw/ifpga/base/opae_osdep.h        |  43 ++++-
 7 files changed, 597 insertions(+), 119 deletions(-)
  

Comments

Zhang, Tianfei June 17, 2022, 8:57 a.m. UTC | #1
> -----Original Message-----
> From: Huang, Wei <wei.huang@intel.com>
> Sent: Friday, June 17, 2022 3:20 PM
> To: dev@dpdk.org; thomas@monjalon.net; nipun.gupta@nxp.com;
> hemant.agrawal@nxp.com
> Cc: stable@dpdk.org; Xu, Rosen <rosen.xu@intel.com>; Zhang, Tianfei
> <tianfei.zhang@intel.com>; Zhang, Qi Z <qi.z.zhang@intel.com>; Huang, Wei
> <wei.huang@intel.com>
> Subject: [PATCH v3 1/4] raw/ifpga/base: add PMCI base driver
> 
> PMCI (Platform Management Control Interface) is a new module in FPGA, which
> is designed to cooperate with BMC chip to fulfill board management functions.
> This base driver implements interfaces to access registers of BMC chip.
> 
> Signed-off-by: Wei Huang <wei.huang@intel.com>
> ---
> v2: fix typo. 'spi_master' is not misspelled and is not introduced
>     in this patch
> ---
> v3: split PMCI driver into several patches
> ---
>  drivers/raw/ifpga/base/ifpga_defines.h     |   2 +
>  drivers/raw/ifpga/base/ifpga_feature_dev.c |   2 +
>  drivers/raw/ifpga/base/ifpga_feature_dev.h |   1 +
>  drivers/raw/ifpga/base/ifpga_fme.c         | 142 ++++++++++++--
>  drivers/raw/ifpga/base/opae_intel_max10.c  | 297 ++++++++++++++++++++----
> -----  drivers/raw/ifpga/base/opae_intel_max10.h  | 229
> +++++++++++++++++++++-
>  drivers/raw/ifpga/base/opae_osdep.h        |  43 ++++-
>  7 files changed, 597 insertions(+), 119 deletions(-)
> 
> diff --git a/drivers/raw/ifpga/base/ifpga_defines.h
> b/drivers/raw/ifpga/base/ifpga_defines.h
> index 9a280eb..f84ed1d 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 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..4d089d2 100644
> --- a/drivers/raw/ifpga/base/ifpga_fme.c
> +++ b/drivers/raw/ifpga/base/ifpga_fme.c
> @@ -983,11 +983,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,7 +1016,12 @@ 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;
>  }
> @@ -1011,8 +1030,10 @@ 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,20 +1178,30 @@
> 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 */
> @@ -1187,6 +1218,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 +1233,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 +1268,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 +1537,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);
> +	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/opae_intel_max10.c
> b/drivers/raw/ifpga/base/opae_intel_max10.c
> index 9d82fb0..901a258 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_reg_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_reg_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,135 @@ int max10_sys_update_bits(struct intel_max10_device
> *dev, unsigned int offset,
>  	return max10_sys_write(dev, offset, temp);  }
> 
> +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,},
> @@ -561,11 +681,9 @@ static int check_max10_version(struct
> intel_max10_device *dev)
>  				&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 +766,75 @@ 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)
> -{
> -	struct intel_max10_device *dev;
> -	int ret;
> -	unsigned int val;
> +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,
> +};
> 
> -	dev = opae_malloc(sizeof(*dev));
> -	if (!dev)
> -		return NULL;
> +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, };
> 
> -	TAILQ_INIT(&dev->opae_sensor_list);
> +int
> +intel_max10_device_init(struct intel_max10_device *dev) {
> +	int ret = 0;
> 
> -	dev->spi_master = spi;
> +	TAILQ_INIT(&dev->opae_sensor_list);
> 
> -	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;
> -	}
> 
> -	/* check the max10 version */
> -	ret = check_max10_version(dev);
> -	if (ret) {
> -		dev_err(dev, "Failed to find max10 hardware!\n");
> -		goto free_dev;
> -	}
> +	if (dev->type == M10_N3000) {
> +		dev->ops = &m10bmc_n3000_regmap;
> +		dev->csr = &m10bmc_spi_csr;
> 
> -	/* 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;
> -	}
> +		/* check the max10 version */
> +		ret = check_max10_version(dev);
> +		if (ret) {
> +			dev_err(dev, "Failed to find max10 hardware!\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");
> -		goto free_dtb;
> -	}
> +		/* load the MAX10 device table */
> +		ret = init_max10_device_table(dev);
> +		if (ret) {
> +			dev_err(dev, "Init max10 device table fail\n");
> +			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;
> -	}
> -	dev_info(dev, "FPGA loaded from %s Image\n", val ? "User" : "Factory");
> +		/* 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;
> 
> -	return dev;
> +		ret = pthread_mutex_init(&dev->bmc_ops.lock, NULL);
> +		if (ret)
> +			return ret;
> 
> -release_max10_hw:
> -	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);
> +		if (!dev->bmc_ops.mutex)
> +			dev->bmc_ops.mutex = &dev->bmc_ops.lock;
> +	}
> 
> -	return NULL;
> +	return ret;
>  }
> 
>  int intel_max10_device_remove(struct intel_max10_device *dev) @@ -722,15
> +842,14 @@ int intel_max10_device_remove(struct intel_max10_device *dev)
>  	if (!dev)
>  		return 0;
> 
> -	max10_sensor_uinit(dev);
> -
> -	if (dev->spi_tran_dev)
> -		spi_transaction_remove(dev->spi_tran_dev);
> +	pthread_mutex_destroy(&dev->bmc_ops.lock);
> 
> -	if (dev->fdt_root)
> -		opae_free(dev->fdt_root);
> +	if (dev->type == M10_N3000) {
> +		max10_sensor_uinit(dev);
> 
> -	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..0d31196 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,52 @@ 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 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 +89,11 @@ 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 m10bmc_ops bmc_ops;
> +	u8 *mmio; /* mmio address for PMCI */
>  };
> 
>  /* retimer speed */
> @@ -87,6 +141,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 +206,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 +239,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,19 +322,21 @@
> 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_reg_read(struct intel_max10_device *dev,
> +	unsigned int offset, unsigned int *val); int max10_reg_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 intel_max10_device_init(struct intel_max10_device *dev);
>  int intel_max10_device_remove(struct intel_max10_device *dev);
> 
> 
> @@ -254,4 +393,80 @@ struct opae_sensor_info {
>  	unsigned int value_reg;
>  };
> 
> +/* 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 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_CONFIGURED
> +BIT(3)
> +
> +#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
>  #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
> --
> 1.8.3.1

It looks good for me.
Acked-by: Tianfei Zhang <tianfei.zhang@intel.com>
  
Xu, Rosen June 17, 2022, 2:41 p.m. UTC | #2
Hi,

> -----Original Message-----
> From: Huang, Wei <wei.huang@intel.com>
> Sent: Friday, June 17, 2022 15:20
> To: dev@dpdk.org; thomas@monjalon.net; nipun.gupta@nxp.com;
> hemant.agrawal@nxp.com
> Cc: stable@dpdk.org; Xu, Rosen <rosen.xu@intel.com>; Zhang, Tianfei
> <tianfei.zhang@intel.com>; Zhang, Qi Z <qi.z.zhang@intel.com>; Huang, Wei
> <wei.huang@intel.com>
> Subject: [PATCH v3 1/4] raw/ifpga/base: add PMCI base driver
> 
> PMCI (Platform Management Control Interface) is a new module in FPGA,
> which is designed to cooperate with BMC chip to fulfill board management
> functions.
> This base driver implements interfaces to access registers of BMC chip.
> 
> Signed-off-by: Wei Huang <wei.huang@intel.com>
> ---
> v2: fix typo. 'spi_master' is not misspelled and is not introduced
>     in this patch
> ---
> v3: split PMCI driver into several patches
> ---
>  drivers/raw/ifpga/base/ifpga_defines.h     |   2 +
>  drivers/raw/ifpga/base/ifpga_feature_dev.c |   2 +
>  drivers/raw/ifpga/base/ifpga_feature_dev.h |   1 +
>  drivers/raw/ifpga/base/ifpga_fme.c         | 142 ++++++++++++--
>  drivers/raw/ifpga/base/opae_intel_max10.c  | 297
> ++++++++++++++++++++---------
> drivers/raw/ifpga/base/opae_intel_max10.h  | 229
> +++++++++++++++++++++-
>  drivers/raw/ifpga/base/opae_osdep.h        |  43 ++++-
>  7 files changed, 597 insertions(+), 119 deletions(-)
> 
> diff --git a/drivers/raw/ifpga/base/ifpga_defines.h
> b/drivers/raw/ifpga/base/ifpga_defines.h
> index 9a280eb..f84ed1d 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 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..4d089d2 100644
> --- a/drivers/raw/ifpga/base/ifpga_fme.c
> +++ b/drivers/raw/ifpga/base/ifpga_fme.c
> @@ -983,11 +983,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,7 +1016,12 @@ 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;
>  }
> @@ -1011,8 +1030,10 @@ 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,20 +1178,30
> @@ 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 */
> @@ -1187,6 +1218,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 +1233,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 +1268,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 +1537,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);
> +	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/opae_intel_max10.c
> b/drivers/raw/ifpga/base/opae_intel_max10.c
> index 9d82fb0..901a258 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_reg_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_reg_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,135 @@ int max10_sys_update_bits(struct
> intel_max10_device *dev, unsigned int offset,
>  	return max10_sys_write(dev, offset, temp);  }
> 
> +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,},
> @@ -561,11 +681,9 @@ static int check_max10_version(struct
> intel_max10_device *dev)
>  				&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 +766,75 @@ 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)
> -{
> -	struct intel_max10_device *dev;
> -	int ret;
> -	unsigned int val;
> +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,
> +};
> 
> -	dev = opae_malloc(sizeof(*dev));
> -	if (!dev)
> -		return NULL;
> +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, };
> 
> -	TAILQ_INIT(&dev->opae_sensor_list);
> +int
> +intel_max10_device_init(struct intel_max10_device *dev) {
> +	int ret = 0;
> 
> -	dev->spi_master = spi;
> +	TAILQ_INIT(&dev->opae_sensor_list);
> 
> -	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;
> -	}
> 
> -	/* check the max10 version */
> -	ret = check_max10_version(dev);
> -	if (ret) {
> -		dev_err(dev, "Failed to find max10 hardware!\n");
> -		goto free_dev;
> -	}
> +	if (dev->type == M10_N3000) {
> +		dev->ops = &m10bmc_n3000_regmap;
> +		dev->csr = &m10bmc_spi_csr;
> 
> -	/* 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;
> -	}
> +		/* check the max10 version */
> +		ret = check_max10_version(dev);
> +		if (ret) {
> +			dev_err(dev, "Failed to find max10 hardware!\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");
> -		goto free_dtb;
> -	}
> +		/* load the MAX10 device table */
> +		ret = init_max10_device_table(dev);
> +		if (ret) {
> +			dev_err(dev, "Init max10 device table fail\n");
> +			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;
> -	}
> -	dev_info(dev, "FPGA loaded from %s Image\n", val ? "User" :
> "Factory");
> +		/* 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;
> 
> -	return dev;
> +		ret = pthread_mutex_init(&dev->bmc_ops.lock, NULL);
> +		if (ret)
> +			return ret;
> 
> -release_max10_hw:
> -	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);
> +		if (!dev->bmc_ops.mutex)
> +			dev->bmc_ops.mutex = &dev->bmc_ops.lock;
> +	}
> 
> -	return NULL;
> +	return ret;
>  }
> 
>  int intel_max10_device_remove(struct intel_max10_device *dev) @@ -
> 722,15 +842,14 @@ int intel_max10_device_remove(struct
> intel_max10_device *dev)
>  	if (!dev)
>  		return 0;
> 
> -	max10_sensor_uinit(dev);
> -
> -	if (dev->spi_tran_dev)
> -		spi_transaction_remove(dev->spi_tran_dev);
> +	pthread_mutex_destroy(&dev->bmc_ops.lock);
> 
> -	if (dev->fdt_root)
> -		opae_free(dev->fdt_root);
> +	if (dev->type == M10_N3000) {
> +		max10_sensor_uinit(dev);
> 
> -	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..0d31196 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,52 @@ 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 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 +89,11 @@ 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 m10bmc_ops bmc_ops;
> +	u8 *mmio; /* mmio address for PMCI */
>  };
> 
>  /* retimer speed */
> @@ -87,6 +141,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 +206,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 +239,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,19 +322,21
> @@ 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_reg_read(struct intel_max10_device *dev,
> +	unsigned int offset, unsigned int *val); int max10_reg_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 intel_max10_device_init(struct intel_max10_device *dev);
>  int intel_max10_device_remove(struct intel_max10_device *dev);
> 
> 
> @@ -254,4 +393,80 @@ struct opae_sensor_info {
>  	unsigned int value_reg;
>  };
> 
> +/* 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 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_CONFIGURED
> +BIT(3)
> +
> +#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
>  #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
> --
> 1.8.3.1

Reviewed-by: Rosen Xu <rosen.xu@intel.com>
  

Patch

diff --git a/drivers/raw/ifpga/base/ifpga_defines.h b/drivers/raw/ifpga/base/ifpga_defines.h
index 9a280eb..f84ed1d 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
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..4d089d2 100644
--- a/drivers/raw/ifpga/base/ifpga_fme.c
+++ b/drivers/raw/ifpga/base/ifpga_fme.c
@@ -983,11 +983,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,7 +1016,12 @@  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;
 }
@@ -1011,8 +1030,10 @@  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,20 +1178,30 @@  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 */
@@ -1187,6 +1218,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 +1233,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 +1268,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 +1537,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);
+	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/opae_intel_max10.c b/drivers/raw/ifpga/base/opae_intel_max10.c
index 9d82fb0..901a258 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_reg_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_reg_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,135 @@  int max10_sys_update_bits(struct intel_max10_device *dev, unsigned int offset,
 	return max10_sys_write(dev, offset, temp);
 }
 
+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,},
@@ -561,11 +681,9 @@  static int check_max10_version(struct intel_max10_device *dev)
 				&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 +766,75 @@  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)
-{
-	struct intel_max10_device *dev;
-	int ret;
-	unsigned int val;
+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,
+};
 
-	dev = opae_malloc(sizeof(*dev));
-	if (!dev)
-		return NULL;
+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,
+};
 
-	TAILQ_INIT(&dev->opae_sensor_list);
+int
+intel_max10_device_init(struct intel_max10_device *dev)
+{
+	int ret = 0;
 
-	dev->spi_master = spi;
+	TAILQ_INIT(&dev->opae_sensor_list);
 
-	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;
-	}
 
-	/* check the max10 version */
-	ret = check_max10_version(dev);
-	if (ret) {
-		dev_err(dev, "Failed to find max10 hardware!\n");
-		goto free_dev;
-	}
+	if (dev->type == M10_N3000) {
+		dev->ops = &m10bmc_n3000_regmap;
+		dev->csr = &m10bmc_spi_csr;
 
-	/* 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;
-	}
+		/* check the max10 version */
+		ret = check_max10_version(dev);
+		if (ret) {
+			dev_err(dev, "Failed to find max10 hardware!\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");
-		goto free_dtb;
-	}
+		/* load the MAX10 device table */
+		ret = init_max10_device_table(dev);
+		if (ret) {
+			dev_err(dev, "Init max10 device table fail\n");
+			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;
-	}
-	dev_info(dev, "FPGA loaded from %s Image\n", val ? "User" : "Factory");
+		/* 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;
 
-	return dev;
+		ret = pthread_mutex_init(&dev->bmc_ops.lock, NULL);
+		if (ret)
+			return ret;
 
-release_max10_hw:
-	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);
+		if (!dev->bmc_ops.mutex)
+			dev->bmc_ops.mutex = &dev->bmc_ops.lock;
+	}
 
-	return NULL;
+	return ret;
 }
 
 int intel_max10_device_remove(struct intel_max10_device *dev)
@@ -722,15 +842,14 @@  int intel_max10_device_remove(struct intel_max10_device *dev)
 	if (!dev)
 		return 0;
 
-	max10_sensor_uinit(dev);
-
-	if (dev->spi_tran_dev)
-		spi_transaction_remove(dev->spi_tran_dev);
+	pthread_mutex_destroy(&dev->bmc_ops.lock);
 
-	if (dev->fdt_root)
-		opae_free(dev->fdt_root);
+	if (dev->type == M10_N3000) {
+		max10_sensor_uinit(dev);
 
-	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..0d31196 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,52 @@  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 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 +89,11 @@  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 m10bmc_ops bmc_ops;
+	u8 *mmio; /* mmio address for PMCI */
 };
 
 /* retimer speed */
@@ -87,6 +141,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 +206,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 +239,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,19 +322,21 @@  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_reg_read(struct intel_max10_device *dev,
+	unsigned int offset, unsigned int *val);
+int max10_reg_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 intel_max10_device_init(struct intel_max10_device *dev);
 int intel_max10_device_remove(struct intel_max10_device *dev);
 
 
@@ -254,4 +393,80 @@  struct opae_sensor_info {
 	unsigned int value_reg;
 };
 
+/* 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 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_CONFIGURED  BIT(3)
+
+#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
 #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