[v1,03/11] drivers/raw/ifpga_rawdev: add OPAE share code for IPN3KE

Message ID 1551338000-120348-4-git-send-email-rosen.xu@intel.com (mailing list archive)
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers
Series Add patch set for IPN3KE |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation fail Compilation issues

Commit Message

Xu, Rosen Feb. 28, 2019, 7:13 a.m. UTC
  Add OPAE share code for Intel FPGA Acceleration NIC IPN3KE.

Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com>
---
 drivers/raw/ifpga_rawdev/base/Makefile             |   7 +
 drivers/raw/ifpga_rawdev/base/ifpga_api.c          |  69 ++-
 drivers/raw/ifpga_rawdev/base/ifpga_api.h          |   1 +
 drivers/raw/ifpga_rawdev/base/ifpga_defines.h      |  86 +++-
 drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c    | 342 +++++--------
 drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.c  | 170 +++++--
 drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.h  |  62 ++-
 drivers/raw/ifpga_rawdev/base/ifpga_fme.c          | 373 ++++++++++++++
 drivers/raw/ifpga_rawdev/base/ifpga_fme_pr.c       |   2 +-
 drivers/raw/ifpga_rawdev/base/ifpga_hw.h           |  21 +-
 drivers/raw/ifpga_rawdev/base/ifpga_port.c         |  21 +
 drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.c   |  89 ++++
 drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.h   |  14 +
 drivers/raw/ifpga_rawdev/base/opae_hw_api.c        | 189 ++++++-
 drivers/raw/ifpga_rawdev/base/opae_hw_api.h        |  46 +-
 drivers/raw/ifpga_rawdev/base/opae_i2c.c           | 490 +++++++++++++++++++
 drivers/raw/ifpga_rawdev/base/opae_i2c.h           | 127 +++++
 drivers/raw/ifpga_rawdev/base/opae_intel_max10.c   | 106 ++++
 drivers/raw/ifpga_rawdev/base/opae_intel_max10.h   |  36 ++
 drivers/raw/ifpga_rawdev/base/opae_mdio.c          | 542 +++++++++++++++++++++
 drivers/raw/ifpga_rawdev/base/opae_mdio.h          |  90 ++++
 drivers/raw/ifpga_rawdev/base/opae_osdep.h         |  11 +-
 drivers/raw/ifpga_rawdev/base/opae_phy_group.c     |  88 ++++
 drivers/raw/ifpga_rawdev/base/opae_phy_group.h     |  53 ++
 drivers/raw/ifpga_rawdev/base/opae_spi.c           | 260 ++++++++++
 drivers/raw/ifpga_rawdev/base/opae_spi.h           | 120 +++++
 .../raw/ifpga_rawdev/base/opae_spi_transaction.c   | 438 +++++++++++++++++
 .../ifpga_rawdev/base/osdep_raw/osdep_generic.h    |   1 +
 .../ifpga_rawdev/base/osdep_rte/osdep_generic.h    |  10 +
 29 files changed, 3549 insertions(+), 315 deletions(-)
 create mode 100644 drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.c
 create mode 100644 drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.h
 create mode 100644 drivers/raw/ifpga_rawdev/base/opae_i2c.c
 create mode 100644 drivers/raw/ifpga_rawdev/base/opae_i2c.h
 create mode 100644 drivers/raw/ifpga_rawdev/base/opae_intel_max10.c
 create mode 100644 drivers/raw/ifpga_rawdev/base/opae_intel_max10.h
 create mode 100644 drivers/raw/ifpga_rawdev/base/opae_mdio.c
 create mode 100644 drivers/raw/ifpga_rawdev/base/opae_mdio.h
 create mode 100644 drivers/raw/ifpga_rawdev/base/opae_phy_group.c
 create mode 100644 drivers/raw/ifpga_rawdev/base/opae_phy_group.h
 create mode 100644 drivers/raw/ifpga_rawdev/base/opae_spi.c
 create mode 100644 drivers/raw/ifpga_rawdev/base/opae_spi.h
 create mode 100644 drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c
  

Comments

Ferruh Yigit March 6, 2019, 12:27 p.m. UTC | #1
On 2/28/2019 7:13 AM, Rosen Xu wrote:
> Add OPAE share code for Intel FPGA Acceleration NIC IPN3KE.

What do you think adding a file to record the version of the shared code, as it
is done in Intel NIC drivers, README file?

Also can you please add more details on what feautures has been added with this
update?

And if possible can you please split this patch into logical parts?

> 
> Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com>
> ---
>  drivers/raw/ifpga_rawdev/base/Makefile             |   7 +
>  drivers/raw/ifpga_rawdev/base/ifpga_api.c          |  69 ++-
>  drivers/raw/ifpga_rawdev/base/ifpga_api.h          |   1 +
>  drivers/raw/ifpga_rawdev/base/ifpga_defines.h      |  86 +++-
>  drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c    | 342 +++++--------
>  drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.c  | 170 +++++--
>  drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.h  |  62 ++-
>  drivers/raw/ifpga_rawdev/base/ifpga_fme.c          | 373 ++++++++++++++
>  drivers/raw/ifpga_rawdev/base/ifpga_fme_pr.c       |   2 +-
>  drivers/raw/ifpga_rawdev/base/ifpga_hw.h           |  21 +-
>  drivers/raw/ifpga_rawdev/base/ifpga_port.c         |  21 +
>  drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.c   |  89 ++++
>  drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.h   |  14 +
>  drivers/raw/ifpga_rawdev/base/opae_hw_api.c        | 189 ++++++-
>  drivers/raw/ifpga_rawdev/base/opae_hw_api.h        |  46 +-
>  drivers/raw/ifpga_rawdev/base/opae_i2c.c           | 490 +++++++++++++++++++
>  drivers/raw/ifpga_rawdev/base/opae_i2c.h           | 127 +++++
>  drivers/raw/ifpga_rawdev/base/opae_intel_max10.c   | 106 ++++
>  drivers/raw/ifpga_rawdev/base/opae_intel_max10.h   |  36 ++
>  drivers/raw/ifpga_rawdev/base/opae_mdio.c          | 542 +++++++++++++++++++++
>  drivers/raw/ifpga_rawdev/base/opae_mdio.h          |  90 ++++
>  drivers/raw/ifpga_rawdev/base/opae_osdep.h         |  11 +-
>  drivers/raw/ifpga_rawdev/base/opae_phy_group.c     |  88 ++++
>  drivers/raw/ifpga_rawdev/base/opae_phy_group.h     |  53 ++
>  drivers/raw/ifpga_rawdev/base/opae_spi.c           | 260 ++++++++++
>  drivers/raw/ifpga_rawdev/base/opae_spi.h           | 120 +++++
>  .../raw/ifpga_rawdev/base/opae_spi_transaction.c   | 438 +++++++++++++++++
>  .../ifpga_rawdev/base/osdep_raw/osdep_generic.h    |   1 +
>  .../ifpga_rawdev/base/osdep_rte/osdep_generic.h    |  10 +
>  29 files changed, 3549 insertions(+), 315 deletions(-)

<...>

> @@ -165,37 +68,35 @@ static u64 feature_id(void __iomem *start)
>  
>  static int
>  build_info_add_sub_feature(struct build_feature_devs_info *binfo,
> -			   struct feature_info *finfo, void __iomem *start)
> +		void __iomem *start, u64 fid, unsigned int size,
> +		unsigned int vec_start,
> +		unsigned int vec_cnt)
>  {
>  	struct ifpga_hw *hw = binfo->hw;
>  	struct feature *feature = NULL;

struct names are so generic 'struct feature' & 'struct feature_ops' defined in
ifpga_hw.h, they seems not added in this patch, but what do you think prefix
them via "ifpga_" in a separate patch?

<...>

> +	feature->vec_start = vec_start;
> +	feature->vec_cnt = vec_cnt;
> +
> +	dev_debug(binfo, "%s: id=0x%lx, phys_addr=0x%lx, size=%d\n",
> +			__func__, feature->id, feature->phys_addr, size);

32bit build complains about %lx usage:

.../dpdk/drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c:99:51: error: format
‘%lx’ expects argument of type ‘long unsigned int’, but argument 5 has type
‘u64’ {aka ‘long long unsigned int’} [-Werror=
format=]

<...>

> @@ -651,12 +539,19 @@ static int parse_feature(struct build_feature_devs_info *binfo,
>  		}
>  
>  		hdr = (struct feature_header *)start;
> +		header.csr = readq(hdr);
> +
> +		/*debug*/

I think can drop above comment, not adding extra information.

> +		dev_debug(binfo, "%s: address=0x%llx, val=0x%lx, header.id=0x%x, header.next_offset=0x%x, header.eol=0x%x, header.type=0x%x\n",
> +			__func__, (unsigned long long)(hdr), header.csr,

Why not use "%p" to print the address of the variable but cast it to 'unsigned
long long'?

<...>

> +static int fme_spi_init(struct feature *feature)
> +{
> +	struct feature_fme_spi *spi;
> +	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
> +	struct altera_spi_device *spi_master;
> +	struct intel_max10_device *max10;
> +	int ret = 0;
> +
> +	spi = (struct feature_fme_spi *)feature->addr;
> +
> +	dev_info(fme, "FME SPI Master (Max10) Init.\n");
> +	dev_debug(fme, "FME SPI base addr %llx.\n",
> +		 (unsigned long long)spi);

Same comment here, why not "%p", why casting the variable?

> +	dev_debug(fme, "spi param=0x%lx\n", opae_readq(feature->addr + 0x8));

.../dpdk/drivers/raw/ifpga_rawdev/base/ifpga_fme.c:774:69: error: format ‘%lx’
expects argument of type ‘long unsigned int’, but argument 4 has type ‘uint64_t’
{aka ‘long long unsigned int’} [-Werror=
format=]
  dev_debug(fme, "spi param=0x%lx\n", opae_readq(feature->addr + 0x8));
                                                                     ^

<...>

> +/**
> + * opae_manager_get_retimer_info - get retimer info like PKVL chip
> + * @mgr: opae_manager for retimer
> + * @info: info return to caller
> + *
> + * Return: 0 on success, otherwise error code
> + */
> +int opae_manager_get_retimer_info(struct opae_manager *mgr,
> +	       struct opae_retimer_info *info)
> +{
> +	if (!mgr || !mgr->network_ops)
> +		return -EINVAL;
> +
> +	//if (mgr->network_ops->get_retimer_info)
> +	//	return mgr->network_ops->get_retimer_info(mgr, info);


Please remove commented code, and for comments please prefer c89 style comments.

<...>

> @@ -0,0 +1,490 @@
> +
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2010-2018 Intel Corporation

Do you prefer to update date to 2019?

<...>

> +static void phy_indirect_write(struct phy_group_device *dev, u8 entry,
> +		u16 addr, u32 value)
> +{
> +	u64 ctrl;
> +
> +	ctrl = CMD_RD << CTRL_COMMAND_SHIFT |
> +		(entry & CTRL_PHY_NUM_MASK) << CTRL_PHY_NUM_SHIFT |
> +		(addr & CTRL_PHY_ADDR_MASK) << CTRL_PHY_ADDR_SHIFT |
> +		(value & CTRL_WRITE_DATA_MASK);

Is 32bit supported?
If so, CMD_RD is defined as 'unsigned long' which is 4bytes long in 32bit
machine. Since CTRL_COMMAND_SHIFT  is 62, the result will be different than
expected. Also there is compiler warning for it:

.../drivers/raw/ifpga_rawdev/base/opae_phy_group.c: In function
‘phy_indirect_write’:
.../drivers/raw/ifpga_rawdev/base/opae_phy_group.c:29:16: error: left shift
count >= width of type [-Werror=shift-count-overflow]
  ctrl = CMD_RD << CTRL_COMMAND_SHIFT |
                ^~

Same for similar usage is phy_indirect_read()

<...>

> +static unsigned int spi_write_bytes(struct altera_spi_device *dev, int count)
> +{
> +	unsigned int val = 0;
> +	u16 *p16;
> +	u32 *p32;
> +
> +	if (dev->txbuf) {
> +		switch (dev->data_width) {
> +		case 1:
> +			val = dev->txbuf[count];
> +			break;
> +		case 2:
> +			p16 = (u16 *)(dev->txbuf + 2*count);
> +			val = *p16;
> +			if (dev->endian == SPI_BIG_ENDIAN)
> +				val = cpu_to_be16(val);
> +			break;
> +		case 4:
> +			p32 = (u32 *)(dev->txbuf + 4*count);
> +			val = *p32;
> +			if (dev->endian == SPI_BIG_ENDIAN)
> +				val = (val);

What is the intention here? Compiler warning:

.../drivers/raw/ifpga_rawdev/base/opae_spi.c:122:9: error: explicitly assigning
value of variable of type 'unsigned int' to itself [-Werror,-Wself-assign]

<...>

> +
> +#ifdef OPAE_DEBUG

Is this DEBUG macro defined anywhere?

<...>

> +	switch (trans_type) {
> +	case SPI_TRAN_SEQ_WRITE:
> +	case SPI_TRAN_NON_SEQ_WRITE:
> +		for (i = 0; i < size; i++)
> +			*p++ = *data++;
> +
> +			ret = packet_to_byte_conver(dev, size + HEADER_LEN,
> +				      transaction, RESPONSE_LEN, response,
> +				      &valid_len);
> +			if (ret)
> +				return -EBUSY;
> +
> +			/* check the result */
> +			if (size != ((unsigned int)(response[2] & 0xff) << 8 |
> +					(unsigned int)(response[3] & 0xff)))
> +				ret = -EBUSY;
> +
> +			break;

Indentation is wrong after 'for' loop. Loops seems copying from 'data' to
'transaction' buffer, which is used later, so the logic seems correct but
indentation is misleading, it is causing a build warning:

.../dpdk/drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c: In function
‘do_transaction’:
.../dpdk/drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c:362:3: error: this
‘for’ clause does not guard... [-Werror=misleading-indentation]
   for (i = 0; i < size; i++)
   ^~~
.../dpdk/drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c:365:4: note:
...this statement, but the latter is misleadingly indented as if it were guarded
by the ‘for’
    ret = packet_to_byte_conver(dev, size + HEADER_LEN,
    ^~~
  
Zhang, Tianfei March 6, 2019, 1:59 p.m. UTC | #2
> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Wednesday, March 6, 2019 8:28 PM
> To: Xu, Rosen <rosen.xu@intel.com>; dev@dpdk.org
> Cc: Zhang, Tianfei <tianfei.zhang@intel.com>; Wei, Dan
> <dan.wei@intel.com>; Pei, Andy <andy.pei@intel.com>; Yang, Qiming
> <qiming.yang@intel.com>; Wang, Haiyue <haiyue.wang@intel.com>; Chen,
> Santos <santos.chen@intel.com>; Zhang, Zhang <zhang.zhang@intel.com>
> Subject: Re: [PATCH v1 03/11] drivers/raw/ifpga_rawdev: add OPAE share
> code for IPN3KE
> 
> On 2/28/2019 7:13 AM, Rosen Xu wrote:
> > Add OPAE share code for Intel FPGA Acceleration NIC IPN3KE.
> 
> What do you think adding a file to record the version of the shared code, as
> it is done in Intel NIC drivers, README file?
> 
> Also can you please add more details on what feautures has been added with
> this update?

Thanks, good suggestion, I will add a README file in next version.

> 
> And if possible can you please split this patch into logical parts?

Ok, is it possible split into multiple small patches for share code?if necessary, I will do it in next version.

> 
> >
> > Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com>
> > ---
> >  drivers/raw/ifpga_rawdev/base/Makefile             |   7 +
> >  drivers/raw/ifpga_rawdev/base/ifpga_api.c          |  69 ++-
> >  drivers/raw/ifpga_rawdev/base/ifpga_api.h          |   1 +
> >  drivers/raw/ifpga_rawdev/base/ifpga_defines.h      |  86 +++-
> >  drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c    | 342
> +++++--------
> >  drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.c  | 170 +++++--
> > drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.h  |  62 ++-
> >  drivers/raw/ifpga_rawdev/base/ifpga_fme.c          | 373
> ++++++++++++++
> >  drivers/raw/ifpga_rawdev/base/ifpga_fme_pr.c       |   2 +-
> >  drivers/raw/ifpga_rawdev/base/ifpga_hw.h           |  21 +-
> >  drivers/raw/ifpga_rawdev/base/ifpga_port.c         |  21 +
> >  drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.c   |  89 ++++
> >  drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.h   |  14 +
> >  drivers/raw/ifpga_rawdev/base/opae_hw_api.c        | 189 ++++++-
> >  drivers/raw/ifpga_rawdev/base/opae_hw_api.h        |  46 +-
> >  drivers/raw/ifpga_rawdev/base/opae_i2c.c           | 490
> +++++++++++++++++++
> >  drivers/raw/ifpga_rawdev/base/opae_i2c.h           | 127 +++++
> >  drivers/raw/ifpga_rawdev/base/opae_intel_max10.c   | 106 ++++
> >  drivers/raw/ifpga_rawdev/base/opae_intel_max10.h   |  36 ++
> >  drivers/raw/ifpga_rawdev/base/opae_mdio.c          | 542
> +++++++++++++++++++++
> >  drivers/raw/ifpga_rawdev/base/opae_mdio.h          |  90 ++++
> >  drivers/raw/ifpga_rawdev/base/opae_osdep.h         |  11 +-
> >  drivers/raw/ifpga_rawdev/base/opae_phy_group.c     |  88 ++++
> >  drivers/raw/ifpga_rawdev/base/opae_phy_group.h     |  53 ++
> >  drivers/raw/ifpga_rawdev/base/opae_spi.c           | 260
> ++++++++++
> >  drivers/raw/ifpga_rawdev/base/opae_spi.h           | 120 +++++
> >  .../raw/ifpga_rawdev/base/opae_spi_transaction.c   | 438
> +++++++++++++++++
> >  .../ifpga_rawdev/base/osdep_raw/osdep_generic.h    |   1 +
> >  .../ifpga_rawdev/base/osdep_rte/osdep_generic.h    |  10 +
> >  29 files changed, 3549 insertions(+), 315 deletions(-)
> 
> <...>
> 
> > @@ -165,37 +68,35 @@ static u64 feature_id(void __iomem *start)
> >
> >  static int
> >  build_info_add_sub_feature(struct build_feature_devs_info *binfo,
> > -			   struct feature_info *finfo, void __iomem *start)
> > +		void __iomem *start, u64 fid, unsigned int size,
> > +		unsigned int vec_start,
> > +		unsigned int vec_cnt)
> >  {
> >  	struct ifpga_hw *hw = binfo->hw;
> >  	struct feature *feature = NULL;
> 
> struct names are so generic 'struct feature' & 'struct feature_ops' defined in
> ifpga_hw.h, they seems not added in this patch, but what do you think prefix
> them via "ifpga_" in a separate patch?

Yes, I agree, add prefix name is better, maybe we forget that patch, will fix in next version.

> 
> <...>
> 
> > +	feature->vec_start = vec_start;
> > +	feature->vec_cnt = vec_cnt;
> > +
> > +	dev_debug(binfo, "%s: id=0x%lx, phys_addr=0x%lx, size=%d\n",
> > +			__func__, feature->id, feature->phys_addr, size);
> 
> 32bit build complains about %lx usage:
> 
> .../dpdk/drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c:99:51: error:
> format ‘%lx’ expects argument of type ‘long unsigned int’, but argument
> 5 has type ‘u64’ {aka ‘long long unsigned int’} [-Werror= format=]

In this v1 patch, we forget check the 32 bit compiler, will fix in next version.

> 
> <...>
> 
> > @@ -651,12 +539,19 @@ static int parse_feature(struct
> build_feature_devs_info *binfo,
> >  		}
> >
> >  		hdr = (struct feature_header *)start;
> > +		header.csr = readq(hdr);
> > +
> > +		/*debug*/
> 
> I think can drop above comment, not adding extra information.
> 
> > +		dev_debug(binfo, "%s: address=0x%llx, val=0x%lx, header.id=0x%x,
> header.next_offset=0x%x, header.eol=0x%x, header.type=0x%x\n",
> > +			__func__, (unsigned long long)(hdr), header.csr,
> 
> Why not use "%p" to print the address of the variable but cast it to 'unsigned
> long long'?
Will fix in next version.
> 
> <...>
> 
> > +static int fme_spi_init(struct feature *feature) {
> > +	struct feature_fme_spi *spi;
> > +	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
> > +	struct altera_spi_device *spi_master;
> > +	struct intel_max10_device *max10;
> > +	int ret = 0;
> > +
> > +	spi = (struct feature_fme_spi *)feature->addr;
> > +
> > +	dev_info(fme, "FME SPI Master (Max10) Init.\n");
> > +	dev_debug(fme, "FME SPI base addr %llx.\n",
> > +		 (unsigned long long)spi);
> 
> Same comment here, why not "%p", why casting the variable?
> 
> > +	dev_debug(fme, "spi param=0x%lx\n", opae_readq(feature->addr +
> > +0x8));
> 
> .../dpdk/drivers/raw/ifpga_rawdev/base/ifpga_fme.c:774:69: error: format
> ‘%lx’
> expects argument of type ‘long unsigned int’, but argument 4 has type
> ‘uint64_t’
> {aka ‘long long unsigned int’} [-Werror= format=]
>   dev_debug(fme, "spi param=0x%lx\n", opae_readq(feature->addr + 0x8));

Will fix in next version.
> 
> ^
> 
> <...>
> 
> > +/**
> > + * opae_manager_get_retimer_info - get retimer info like PKVL chip
> > + * @mgr: opae_manager for retimer
> > + * @info: info return to caller
> > + *
> > + * Return: 0 on success, otherwise error code  */ int
> > +opae_manager_get_retimer_info(struct opae_manager *mgr,
> > +	       struct opae_retimer_info *info) {
> > +	if (!mgr || !mgr->network_ops)
> > +		return -EINVAL;
> > +
> > +	//if (mgr->network_ops->get_retimer_info)
> > +	//	return mgr->network_ops->get_retimer_info(mgr, info);
> 
> 
> Please remove commented code, and for comments please prefer c89 style
> comments.

Will fix in next version.

> 
> <...>
> 
> > @@ -0,0 +1,490 @@
> > +
> > +/* SPDX-License-Identifier: BSD-3-Clause
> > + * Copyright(c) 2010-2018 Intel Corporation
> 
> Do you prefer to update date to 2019?

Ok.
> 
> <...>
> 
> > +static void phy_indirect_write(struct phy_group_device *dev, u8 entry,
> > +		u16 addr, u32 value)
> > +{
> > +	u64 ctrl;
> > +
> > +	ctrl = CMD_RD << CTRL_COMMAND_SHIFT |
> > +		(entry & CTRL_PHY_NUM_MASK) << CTRL_PHY_NUM_SHIFT |
> > +		(addr & CTRL_PHY_ADDR_MASK) << CTRL_PHY_ADDR_SHIFT |
> > +		(value & CTRL_WRITE_DATA_MASK);
> 
> Is 32bit supported?
> If so, CMD_RD is defined as 'unsigned long' which is 4bytes long in 32bit
> machine. Since CTRL_COMMAND_SHIFT  is 62, the result will be different
> than expected. Also there is compiler warning for it:
> 
> .../drivers/raw/ifpga_rawdev/base/opae_phy_group.c: In function
> ‘phy_indirect_write’:
> .../drivers/raw/ifpga_rawdev/base/opae_phy_group.c:29:16: error: left shift
> count >= width of type [-Werror=shift-count-overflow]
>   ctrl = CMD_RD << CTRL_COMMAND_SHIFT |
>                 ^~
> 
> Same for similar usage is phy_indirect_read()

The register is 64bit. We will fix for the 32bit compiler in next version.

> 
> <...>
> 
> > +static unsigned int spi_write_bytes(struct altera_spi_device *dev,
> > +int count) {
> > +	unsigned int val = 0;
> > +	u16 *p16;
> > +	u32 *p32;
> > +
> > +	if (dev->txbuf) {
> > +		switch (dev->data_width) {
> > +		case 1:
> > +			val = dev->txbuf[count];
> > +			break;
> > +		case 2:
> > +			p16 = (u16 *)(dev->txbuf + 2*count);
> > +			val = *p16;
> > +			if (dev->endian == SPI_BIG_ENDIAN)
> > +				val = cpu_to_be16(val);
> > +			break;
> > +		case 4:
> > +			p32 = (u32 *)(dev->txbuf + 4*count);
> > +			val = *p32;
> > +			if (dev->endian == SPI_BIG_ENDIAN)
> > +				val = (val);
> 
> What is the intention here? Compiler warning:
> 
> .../drivers/raw/ifpga_rawdev/base/opae_spi.c:122:9: error: explicitly
> assigning value of variable of type 'unsigned int' to itself
> [-Werror,-Wself-assign]

Ok, will fix in next version.
> 
> <...>
> 
> > +
> > +#ifdef OPAE_DEBUG
> 
> Is this DEBUG macro defined anywhere?
> 
> <...>
> 
> > +	switch (trans_type) {
> > +	case SPI_TRAN_SEQ_WRITE:
> > +	case SPI_TRAN_NON_SEQ_WRITE:
> > +		for (i = 0; i < size; i++)
> > +			*p++ = *data++;
> > +
> > +			ret = packet_to_byte_conver(dev, size + HEADER_LEN,
> > +				      transaction, RESPONSE_LEN, response,
> > +				      &valid_len);
> > +			if (ret)
> > +				return -EBUSY;
> > +
> > +			/* check the result */
> > +			if (size != ((unsigned int)(response[2] & 0xff) << 8 |
> > +					(unsigned int)(response[3] & 0xff)))
> > +				ret = -EBUSY;
> > +
> > +			break;
> 
> Indentation is wrong after 'for' loop. Loops seems copying from 'data' to
> 'transaction' buffer, which is used later, so the logic seems correct but
> indentation is misleading, it is causing a build warning:
> 
> .../dpdk/drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c: In
> function
> ‘do_transaction’:
> .../dpdk/drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c:362:3:
> error: this ‘for’ clause does not guard... [-Werror=misleading-indentation]
>    for (i = 0; i < size; i++)
>    ^~~
> .../dpdk/drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c:365:4:
> note:
> ...this statement, but the latter is misleadingly indented as if it were guarded
> by the ‘for’
>     ret = packet_to_byte_conver(dev, size + HEADER_LEN,
>     ^~~
Will fix in next version.

What GCC compiler are you using?
  
Ferruh Yigit March 6, 2019, 5:54 p.m. UTC | #3
On 3/6/2019 1:59 PM, Zhang, Tianfei wrote:
> 
>> -----Original Message-----
>> From: Yigit, Ferruh
>> Sent: Wednesday, March 6, 2019 8:28 PM
>> To: Xu, Rosen <rosen.xu@intel.com>; dev@dpdk.org
>> Cc: Zhang, Tianfei <tianfei.zhang@intel.com>; Wei, Dan
>> <dan.wei@intel.com>; Pei, Andy <andy.pei@intel.com>; Yang, Qiming
>> <qiming.yang@intel.com>; Wang, Haiyue <haiyue.wang@intel.com>; Chen,
>> Santos <santos.chen@intel.com>; Zhang, Zhang <zhang.zhang@intel.com>
>> Subject: Re: [PATCH v1 03/11] drivers/raw/ifpga_rawdev: add OPAE share
>> code for IPN3KE
>>
>> On 2/28/2019 7:13 AM, Rosen Xu wrote:
>>> Add OPAE share code for Intel FPGA Acceleration NIC IPN3KE.
>>
>> What do you think adding a file to record the version of the shared code, as
>> it is done in Intel NIC drivers, README file?
>>
>> Also can you please add more details on what feautures has been added with
>> this update?
> 
> Thanks, good suggestion, I will add a README file in next version.
> 
>>
>> And if possible can you please split this patch into logical parts?
> 
> Ok, is it possible split into multiple small patches for share code?if necessary, I will do it in next version.
> 
>>
>>>
>>> Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com>
>>> ---
>>>  drivers/raw/ifpga_rawdev/base/Makefile             |   7 +
>>>  drivers/raw/ifpga_rawdev/base/ifpga_api.c          |  69 ++-
>>>  drivers/raw/ifpga_rawdev/base/ifpga_api.h          |   1 +
>>>  drivers/raw/ifpga_rawdev/base/ifpga_defines.h      |  86 +++-
>>>  drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c    | 342
>> +++++--------
>>>  drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.c  | 170 +++++--
>>> drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.h  |  62 ++-
>>>  drivers/raw/ifpga_rawdev/base/ifpga_fme.c          | 373
>> ++++++++++++++
>>>  drivers/raw/ifpga_rawdev/base/ifpga_fme_pr.c       |   2 +-
>>>  drivers/raw/ifpga_rawdev/base/ifpga_hw.h           |  21 +-
>>>  drivers/raw/ifpga_rawdev/base/ifpga_port.c         |  21 +
>>>  drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.c   |  89 ++++
>>>  drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.h   |  14 +
>>>  drivers/raw/ifpga_rawdev/base/opae_hw_api.c        | 189 ++++++-
>>>  drivers/raw/ifpga_rawdev/base/opae_hw_api.h        |  46 +-
>>>  drivers/raw/ifpga_rawdev/base/opae_i2c.c           | 490
>> +++++++++++++++++++
>>>  drivers/raw/ifpga_rawdev/base/opae_i2c.h           | 127 +++++
>>>  drivers/raw/ifpga_rawdev/base/opae_intel_max10.c   | 106 ++++
>>>  drivers/raw/ifpga_rawdev/base/opae_intel_max10.h   |  36 ++
>>>  drivers/raw/ifpga_rawdev/base/opae_mdio.c          | 542
>> +++++++++++++++++++++
>>>  drivers/raw/ifpga_rawdev/base/opae_mdio.h          |  90 ++++
>>>  drivers/raw/ifpga_rawdev/base/opae_osdep.h         |  11 +-
>>>  drivers/raw/ifpga_rawdev/base/opae_phy_group.c     |  88 ++++
>>>  drivers/raw/ifpga_rawdev/base/opae_phy_group.h     |  53 ++
>>>  drivers/raw/ifpga_rawdev/base/opae_spi.c           | 260
>> ++++++++++
>>>  drivers/raw/ifpga_rawdev/base/opae_spi.h           | 120 +++++
>>>  .../raw/ifpga_rawdev/base/opae_spi_transaction.c   | 438
>> +++++++++++++++++
>>>  .../ifpga_rawdev/base/osdep_raw/osdep_generic.h    |   1 +
>>>  .../ifpga_rawdev/base/osdep_rte/osdep_generic.h    |  10 +
>>>  29 files changed, 3549 insertions(+), 315 deletions(-)
>>
>> <...>
>>
>>> @@ -165,37 +68,35 @@ static u64 feature_id(void __iomem *start)
>>>
>>>  static int
>>>  build_info_add_sub_feature(struct build_feature_devs_info *binfo,
>>> -			   struct feature_info *finfo, void __iomem *start)
>>> +		void __iomem *start, u64 fid, unsigned int size,
>>> +		unsigned int vec_start,
>>> +		unsigned int vec_cnt)
>>>  {
>>>  	struct ifpga_hw *hw = binfo->hw;
>>>  	struct feature *feature = NULL;
>>
>> struct names are so generic 'struct feature' & 'struct feature_ops' defined in
>> ifpga_hw.h, they seems not added in this patch, but what do you think prefix
>> them via "ifpga_" in a separate patch?
> 
> Yes, I agree, add prefix name is better, maybe we forget that patch, will fix in next version.
> 
>>
>> <...>
>>
>>> +	feature->vec_start = vec_start;
>>> +	feature->vec_cnt = vec_cnt;
>>> +
>>> +	dev_debug(binfo, "%s: id=0x%lx, phys_addr=0x%lx, size=%d\n",
>>> +			__func__, feature->id, feature->phys_addr, size);
>>
>> 32bit build complains about %lx usage:
>>
>> .../dpdk/drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c:99:51: error:
>> format ‘%lx’ expects argument of type ‘long unsigned int’, but argument
>> 5 has type ‘u64’ {aka ‘long long unsigned int’} [-Werror= format=]
> 
> In this v1 patch, we forget check the 32 bit compiler, will fix in next version.
> 
>>
>> <...>
>>
>>> @@ -651,12 +539,19 @@ static int parse_feature(struct
>> build_feature_devs_info *binfo,
>>>  		}
>>>
>>>  		hdr = (struct feature_header *)start;
>>> +		header.csr = readq(hdr);
>>> +
>>> +		/*debug*/
>>
>> I think can drop above comment, not adding extra information.
>>
>>> +		dev_debug(binfo, "%s: address=0x%llx, val=0x%lx, header.id=0x%x,
>> header.next_offset=0x%x, header.eol=0x%x, header.type=0x%x\n",
>>> +			__func__, (unsigned long long)(hdr), header.csr,
>>
>> Why not use "%p" to print the address of the variable but cast it to 'unsigned
>> long long'?
> Will fix in next version.
>>
>> <...>
>>
>>> +static int fme_spi_init(struct feature *feature) {
>>> +	struct feature_fme_spi *spi;
>>> +	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
>>> +	struct altera_spi_device *spi_master;
>>> +	struct intel_max10_device *max10;
>>> +	int ret = 0;
>>> +
>>> +	spi = (struct feature_fme_spi *)feature->addr;
>>> +
>>> +	dev_info(fme, "FME SPI Master (Max10) Init.\n");
>>> +	dev_debug(fme, "FME SPI base addr %llx.\n",
>>> +		 (unsigned long long)spi);
>>
>> Same comment here, why not "%p", why casting the variable?
>>
>>> +	dev_debug(fme, "spi param=0x%lx\n", opae_readq(feature->addr +
>>> +0x8));
>>
>> .../dpdk/drivers/raw/ifpga_rawdev/base/ifpga_fme.c:774:69: error: format
>> ‘%lx’
>> expects argument of type ‘long unsigned int’, but argument 4 has type
>> ‘uint64_t’
>> {aka ‘long long unsigned int’} [-Werror= format=]
>>   dev_debug(fme, "spi param=0x%lx\n", opae_readq(feature->addr + 0x8));
> 
> Will fix in next version.
>>
>> ^
>>
>> <...>
>>
>>> +/**
>>> + * opae_manager_get_retimer_info - get retimer info like PKVL chip
>>> + * @mgr: opae_manager for retimer
>>> + * @info: info return to caller
>>> + *
>>> + * Return: 0 on success, otherwise error code  */ int
>>> +opae_manager_get_retimer_info(struct opae_manager *mgr,
>>> +	       struct opae_retimer_info *info) {
>>> +	if (!mgr || !mgr->network_ops)
>>> +		return -EINVAL;
>>> +
>>> +	//if (mgr->network_ops->get_retimer_info)
>>> +	//	return mgr->network_ops->get_retimer_info(mgr, info);
>>
>>
>> Please remove commented code, and for comments please prefer c89 style
>> comments.
> 
> Will fix in next version.
> 
>>
>> <...>
>>
>>> @@ -0,0 +1,490 @@
>>> +
>>> +/* SPDX-License-Identifier: BSD-3-Clause
>>> + * Copyright(c) 2010-2018 Intel Corporation
>>
>> Do you prefer to update date to 2019?
> 
> Ok.
>>
>> <...>
>>
>>> +static void phy_indirect_write(struct phy_group_device *dev, u8 entry,
>>> +		u16 addr, u32 value)
>>> +{
>>> +	u64 ctrl;
>>> +
>>> +	ctrl = CMD_RD << CTRL_COMMAND_SHIFT |
>>> +		(entry & CTRL_PHY_NUM_MASK) << CTRL_PHY_NUM_SHIFT |
>>> +		(addr & CTRL_PHY_ADDR_MASK) << CTRL_PHY_ADDR_SHIFT |
>>> +		(value & CTRL_WRITE_DATA_MASK);
>>
>> Is 32bit supported?
>> If so, CMD_RD is defined as 'unsigned long' which is 4bytes long in 32bit
>> machine. Since CTRL_COMMAND_SHIFT  is 62, the result will be different
>> than expected. Also there is compiler warning for it:
>>
>> .../drivers/raw/ifpga_rawdev/base/opae_phy_group.c: In function
>> ‘phy_indirect_write’:
>> .../drivers/raw/ifpga_rawdev/base/opae_phy_group.c:29:16: error: left shift
>> count >= width of type [-Werror=shift-count-overflow]
>>   ctrl = CMD_RD << CTRL_COMMAND_SHIFT |
>>                 ^~
>>
>> Same for similar usage is phy_indirect_read()
> 
> The register is 64bit. We will fix for the 32bit compiler in next version.
> 
>>
>> <...>
>>
>>> +static unsigned int spi_write_bytes(struct altera_spi_device *dev,
>>> +int count) {
>>> +	unsigned int val = 0;
>>> +	u16 *p16;
>>> +	u32 *p32;
>>> +
>>> +	if (dev->txbuf) {
>>> +		switch (dev->data_width) {
>>> +		case 1:
>>> +			val = dev->txbuf[count];
>>> +			break;
>>> +		case 2:
>>> +			p16 = (u16 *)(dev->txbuf + 2*count);
>>> +			val = *p16;
>>> +			if (dev->endian == SPI_BIG_ENDIAN)
>>> +				val = cpu_to_be16(val);
>>> +			break;
>>> +		case 4:
>>> +			p32 = (u32 *)(dev->txbuf + 4*count);
>>> +			val = *p32;
>>> +			if (dev->endian == SPI_BIG_ENDIAN)
>>> +				val = (val);
>>
>> What is the intention here? Compiler warning:
>>
>> .../drivers/raw/ifpga_rawdev/base/opae_spi.c:122:9: error: explicitly
>> assigning value of variable of type 'unsigned int' to itself
>> [-Werror,-Wself-assign]
> 
> Ok, will fix in next version.
>>
>> <...>
>>
>>> +
>>> +#ifdef OPAE_DEBUG
>>
>> Is this DEBUG macro defined anywhere?
>>
>> <...>
>>
>>> +	switch (trans_type) {
>>> +	case SPI_TRAN_SEQ_WRITE:
>>> +	case SPI_TRAN_NON_SEQ_WRITE:
>>> +		for (i = 0; i < size; i++)
>>> +			*p++ = *data++;
>>> +
>>> +			ret = packet_to_byte_conver(dev, size + HEADER_LEN,
>>> +				      transaction, RESPONSE_LEN, response,
>>> +				      &valid_len);
>>> +			if (ret)
>>> +				return -EBUSY;
>>> +
>>> +			/* check the result */
>>> +			if (size != ((unsigned int)(response[2] & 0xff) << 8 |
>>> +					(unsigned int)(response[3] & 0xff)))
>>> +				ret = -EBUSY;
>>> +
>>> +			break;
>>
>> Indentation is wrong after 'for' loop. Loops seems copying from 'data' to
>> 'transaction' buffer, which is used later, so the logic seems correct but
>> indentation is misleading, it is causing a build warning:
>>
>> .../dpdk/drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c: In
>> function
>> ‘do_transaction’:
>> .../dpdk/drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c:362:3:
>> error: this ‘for’ clause does not guard... [-Werror=misleading-indentation]
>>    for (i = 0; i < size; i++)
>>    ^~~
>> .../dpdk/drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c:365:4:
>> note:
>> ...this statement, but the latter is misleadingly indented as if it were guarded
>> by the ‘for’
>>     ret = packet_to_byte_conver(dev, size + HEADER_LEN,
>>     ^~~
> Will fix in next version.
> 
> What GCC compiler are you using?

gcc (GCC) 8.2.1 20181215 (Red Hat 8.2.1-6)
clang version 7.0.1 (Fedora 7.0.1-2.fc29)
icc (ICC) 19.0.2.187 20190117

the build errors I put are from one of the above ones, since there were many
errors I didn't filter which error is specific to which compiler.
  
Zhang, Tianfei March 6, 2019, 11:59 p.m. UTC | #4
> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Thursday, March 7, 2019 1:55 AM
> To: Zhang, Tianfei <tianfei.zhang@intel.com>; Xu, Rosen
> <rosen.xu@intel.com>; dev@dpdk.org
> Cc: Wei, Dan <dan.wei@intel.com>; Pei, Andy <andy.pei@intel.com>; Yang,
> Qiming <qiming.yang@intel.com>; Wang, Haiyue <haiyue.wang@intel.com>;
> Chen, Santos <santos.chen@intel.com>; Zhang, Zhang
> <zhang.zhang@intel.com>
> Subject: Re: [PATCH v1 03/11] drivers/raw/ifpga_rawdev: add OPAE share
> code for IPN3KE
> 
> On 3/6/2019 1:59 PM, Zhang, Tianfei wrote:
> >
> >> -----Original Message-----
> >> From: Yigit, Ferruh
> >> Sent: Wednesday, March 6, 2019 8:28 PM
> >> To: Xu, Rosen <rosen.xu@intel.com>; dev@dpdk.org
> >> Cc: Zhang, Tianfei <tianfei.zhang@intel.com>; Wei, Dan
> >> <dan.wei@intel.com>; Pei, Andy <andy.pei@intel.com>; Yang, Qiming
> >> <qiming.yang@intel.com>; Wang, Haiyue <haiyue.wang@intel.com>;
> Chen,
> >> Santos <santos.chen@intel.com>; Zhang, Zhang
> <zhang.zhang@intel.com>
> >> Subject: Re: [PATCH v1 03/11] drivers/raw/ifpga_rawdev: add OPAE
> >> share code for IPN3KE
> >>
> >> On 2/28/2019 7:13 AM, Rosen Xu wrote:
> >>> Add OPAE share code for Intel FPGA Acceleration NIC IPN3KE.
> >>
> >> What do you think adding a file to record the version of the shared
> >> code, as it is done in Intel NIC drivers, README file?
> >>
> >> Also can you please add more details on what feautures has been added
> >> with this update?
> >
> > Thanks, good suggestion, I will add a README file in next version.
> >
> >>
> >> And if possible can you please split this patch into logical parts?
> >
> > Ok, is it possible split into multiple small patches for share code?if
> necessary, I will do it in next version.
> >
> >>
> >>>
> >>> Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com>
> >>> ---
> >>>  drivers/raw/ifpga_rawdev/base/Makefile             |   7 +
> >>>  drivers/raw/ifpga_rawdev/base/ifpga_api.c          |  69 ++-
> >>>  drivers/raw/ifpga_rawdev/base/ifpga_api.h          |   1 +
> >>>  drivers/raw/ifpga_rawdev/base/ifpga_defines.h      |  86 +++-
> >>>  drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c    | 342
> >> +++++--------
> >>>  drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.c  | 170 +++++--
> >>> drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.h  |  62 ++-
> >>>  drivers/raw/ifpga_rawdev/base/ifpga_fme.c          | 373
> >> ++++++++++++++
> >>>  drivers/raw/ifpga_rawdev/base/ifpga_fme_pr.c       |   2 +-
> >>>  drivers/raw/ifpga_rawdev/base/ifpga_hw.h           |  21 +-
> >>>  drivers/raw/ifpga_rawdev/base/ifpga_port.c         |  21 +
> >>>  drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.c   |  89 ++++
> >>>  drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.h   |  14 +
> >>>  drivers/raw/ifpga_rawdev/base/opae_hw_api.c        | 189
> ++++++-
> >>>  drivers/raw/ifpga_rawdev/base/opae_hw_api.h        |  46 +-
> >>>  drivers/raw/ifpga_rawdev/base/opae_i2c.c           | 490
> >> +++++++++++++++++++
> >>>  drivers/raw/ifpga_rawdev/base/opae_i2c.h           | 127 +++++
> >>>  drivers/raw/ifpga_rawdev/base/opae_intel_max10.c   | 106 ++++
> >>>  drivers/raw/ifpga_rawdev/base/opae_intel_max10.h   |  36 ++
> >>>  drivers/raw/ifpga_rawdev/base/opae_mdio.c          | 542
> >> +++++++++++++++++++++
> >>>  drivers/raw/ifpga_rawdev/base/opae_mdio.h          |  90 ++++
> >>>  drivers/raw/ifpga_rawdev/base/opae_osdep.h         |  11 +-
> >>>  drivers/raw/ifpga_rawdev/base/opae_phy_group.c     |  88 ++++
> >>>  drivers/raw/ifpga_rawdev/base/opae_phy_group.h     |  53 ++
> >>>  drivers/raw/ifpga_rawdev/base/opae_spi.c           | 260
> >> ++++++++++
> >>>  drivers/raw/ifpga_rawdev/base/opae_spi.h           | 120 +++++
> >>>  .../raw/ifpga_rawdev/base/opae_spi_transaction.c   | 438
> >> +++++++++++++++++
> >>>  .../ifpga_rawdev/base/osdep_raw/osdep_generic.h    |   1 +
> >>>  .../ifpga_rawdev/base/osdep_rte/osdep_generic.h    |  10 +
> >>>  29 files changed, 3549 insertions(+), 315 deletions(-)
> >>
> >> <...>
> >>
> >>> @@ -165,37 +68,35 @@ static u64 feature_id(void __iomem *start)
> >>>
> >>>  static int
> >>>  build_info_add_sub_feature(struct build_feature_devs_info *binfo,
> >>> -			   struct feature_info *finfo, void __iomem *start)
> >>> +		void __iomem *start, u64 fid, unsigned int size,
> >>> +		unsigned int vec_start,
> >>> +		unsigned int vec_cnt)
> >>>  {
> >>>  	struct ifpga_hw *hw = binfo->hw;
> >>>  	struct feature *feature = NULL;
> >>
> >> struct names are so generic 'struct feature' & 'struct feature_ops'
> >> defined in ifpga_hw.h, they seems not added in this patch, but what
> >> do you think prefix them via "ifpga_" in a separate patch?
> >
> > Yes, I agree, add prefix name is better, maybe we forget that patch, will fix
> in next version.
> >
> >>
> >> <...>
> >>
> >>> +	feature->vec_start = vec_start;
> >>> +	feature->vec_cnt = vec_cnt;
> >>> +
> >>> +	dev_debug(binfo, "%s: id=0x%lx, phys_addr=0x%lx, size=%d\n",
> >>> +			__func__, feature->id, feature->phys_addr, size);
> >>
> >> 32bit build complains about %lx usage:
> >>
> >> .../dpdk/drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c:99:51: error:
> >> format ‘%lx’ expects argument of type ‘long unsigned int’, but
> >> argument
> >> 5 has type ‘u64’ {aka ‘long long unsigned int’} [-Werror= format=]
> >
> > In this v1 patch, we forget check the 32 bit compiler, will fix in next version.
> >
> >>
> >> <...>
> >>
> >>> @@ -651,12 +539,19 @@ static int parse_feature(struct
> >> build_feature_devs_info *binfo,
> >>>  		}
> >>>
> >>>  		hdr = (struct feature_header *)start;
> >>> +		header.csr = readq(hdr);
> >>> +
> >>> +		/*debug*/
> >>
> >> I think can drop above comment, not adding extra information.
> >>
> >>> +		dev_debug(binfo, "%s: address=0x%llx, val=0x%lx,
> header.id=0x%x,
> >> header.next_offset=0x%x, header.eol=0x%x, header.type=0x%x\n",
> >>> +			__func__, (unsigned long long)(hdr), header.csr,
> >>
> >> Why not use "%p" to print the address of the variable but cast it to
> >> 'unsigned long long'?
> > Will fix in next version.
> >>
> >> <...>
> >>
> >>> +static int fme_spi_init(struct feature *feature) {
> >>> +	struct feature_fme_spi *spi;
> >>> +	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw
> *)feature->parent;
> >>> +	struct altera_spi_device *spi_master;
> >>> +	struct intel_max10_device *max10;
> >>> +	int ret = 0;
> >>> +
> >>> +	spi = (struct feature_fme_spi *)feature->addr;
> >>> +
> >>> +	dev_info(fme, "FME SPI Master (Max10) Init.\n");
> >>> +	dev_debug(fme, "FME SPI base addr %llx.\n",
> >>> +		 (unsigned long long)spi);
> >>
> >> Same comment here, why not "%p", why casting the variable?
> >>
> >>> +	dev_debug(fme, "spi param=0x%lx\n", opae_readq(feature->addr
> +
> >>> +0x8));
> >>
> >> .../dpdk/drivers/raw/ifpga_rawdev/base/ifpga_fme.c:774:69: error:
> >> format ‘%lx’
> >> expects argument of type ‘long unsigned int’, but argument 4 has type
> >> ‘uint64_t’
> >> {aka ‘long long unsigned int’} [-Werror= format=]
> >>   dev_debug(fme, "spi param=0x%lx\n", opae_readq(feature->addr +
> >> 0x8));
> >
> > Will fix in next version.
> >>
> >> ^
> >>
> >> <...>
> >>
> >>> +/**
> >>> + * opae_manager_get_retimer_info - get retimer info like PKVL chip
> >>> + * @mgr: opae_manager for retimer
> >>> + * @info: info return to caller
> >>> + *
> >>> + * Return: 0 on success, otherwise error code  */ int
> >>> +opae_manager_get_retimer_info(struct opae_manager *mgr,
> >>> +	       struct opae_retimer_info *info) {
> >>> +	if (!mgr || !mgr->network_ops)
> >>> +		return -EINVAL;
> >>> +
> >>> +	//if (mgr->network_ops->get_retimer_info)
> >>> +	//	return mgr->network_ops->get_retimer_info(mgr, info);
> >>
> >>
> >> Please remove commented code, and for comments please prefer c89
> >> style comments.
> >
> > Will fix in next version.
> >
> >>
> >> <...>
> >>
> >>> @@ -0,0 +1,490 @@
> >>> +
> >>> +/* SPDX-License-Identifier: BSD-3-Clause
> >>> + * Copyright(c) 2010-2018 Intel Corporation
> >>
> >> Do you prefer to update date to 2019?
> >
> > Ok.
> >>
> >> <...>
> >>
> >>> +static void phy_indirect_write(struct phy_group_device *dev, u8 entry,
> >>> +		u16 addr, u32 value)
> >>> +{
> >>> +	u64 ctrl;
> >>> +
> >>> +	ctrl = CMD_RD << CTRL_COMMAND_SHIFT |
> >>> +		(entry & CTRL_PHY_NUM_MASK) << CTRL_PHY_NUM_SHIFT |
> >>> +		(addr & CTRL_PHY_ADDR_MASK) << CTRL_PHY_ADDR_SHIFT |
> >>> +		(value & CTRL_WRITE_DATA_MASK);
> >>
> >> Is 32bit supported?
> >> If so, CMD_RD is defined as 'unsigned long' which is 4bytes long in
> >> 32bit machine. Since CTRL_COMMAND_SHIFT  is 62, the result will be
> >> different than expected. Also there is compiler warning for it:
> >>
> >> .../drivers/raw/ifpga_rawdev/base/opae_phy_group.c: In function
> >> ‘phy_indirect_write’:
> >> .../drivers/raw/ifpga_rawdev/base/opae_phy_group.c:29:16: error: left
> >> shift count >= width of type [-Werror=shift-count-overflow]
> >>   ctrl = CMD_RD << CTRL_COMMAND_SHIFT |
> >>                 ^~
> >>
> >> Same for similar usage is phy_indirect_read()
> >
> > The register is 64bit. We will fix for the 32bit compiler in next version.
> >
> >>
> >> <...>
> >>
> >>> +static unsigned int spi_write_bytes(struct altera_spi_device *dev,
> >>> +int count) {
> >>> +	unsigned int val = 0;
> >>> +	u16 *p16;
> >>> +	u32 *p32;
> >>> +
> >>> +	if (dev->txbuf) {
> >>> +		switch (dev->data_width) {
> >>> +		case 1:
> >>> +			val = dev->txbuf[count];
> >>> +			break;
> >>> +		case 2:
> >>> +			p16 = (u16 *)(dev->txbuf + 2*count);
> >>> +			val = *p16;
> >>> +			if (dev->endian == SPI_BIG_ENDIAN)
> >>> +				val = cpu_to_be16(val);
> >>> +			break;
> >>> +		case 4:
> >>> +			p32 = (u32 *)(dev->txbuf + 4*count);
> >>> +			val = *p32;
> >>> +			if (dev->endian == SPI_BIG_ENDIAN)
> >>> +				val = (val);
> >>
> >> What is the intention here? Compiler warning:
> >>
> >> .../drivers/raw/ifpga_rawdev/base/opae_spi.c:122:9: error: explicitly
> >> assigning value of variable of type 'unsigned int' to itself
> >> [-Werror,-Wself-assign]
> >
> > Ok, will fix in next version.
> >>
> >> <...>
> >>
> >>> +
> >>> +#ifdef OPAE_DEBUG
> >>
> >> Is this DEBUG macro defined anywhere?
> >>
> >> <...>
> >>
> >>> +	switch (trans_type) {
> >>> +	case SPI_TRAN_SEQ_WRITE:
> >>> +	case SPI_TRAN_NON_SEQ_WRITE:
> >>> +		for (i = 0; i < size; i++)
> >>> +			*p++ = *data++;
> >>> +
> >>> +			ret = packet_to_byte_conver(dev, size + HEADER_LEN,
> >>> +				      transaction, RESPONSE_LEN, response,
> >>> +				      &valid_len);
> >>> +			if (ret)
> >>> +				return -EBUSY;
> >>> +
> >>> +			/* check the result */
> >>> +			if (size != ((unsigned int)(response[2] & 0xff) << 8 |
> >>> +					(unsigned int)(response[3] & 0xff)))
> >>> +				ret = -EBUSY;
> >>> +
> >>> +			break;
> >>
> >> Indentation is wrong after 'for' loop. Loops seems copying from
> >> 'data' to 'transaction' buffer, which is used later, so the logic
> >> seems correct but indentation is misleading, it is causing a build warning:
> >>
> >> .../dpdk/drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c: In
> >> function
> >> ‘do_transaction’:
> >> .../dpdk/drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c:362:3:
> >> error: this ‘for’ clause does not guard...
> [-Werror=misleading-indentation]
> >>    for (i = 0; i < size; i++)
> >>    ^~~
> >> .../dpdk/drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c:365:4:
> >> note:
> >> ...this statement, but the latter is misleadingly indented as if it
> >> were guarded by the ‘for’
> >>     ret = packet_to_byte_conver(dev, size + HEADER_LEN,
> >>     ^~~
> > Will fix in next version.
> >
> > What GCC compiler are you using?
> 
> gcc (GCC) 8.2.1 20181215 (Red Hat 8.2.1-6) clang version 7.0.1 (Fedora
> 7.0.1-2.fc29) icc (ICC) 19.0.2.187 20190117
> 
> the build errors I put are from one of the above ones, since there were many
> errors I didn't filter which error is specific to which compiler.
Thanks, we will clean our code for all of compilers in next version.
>
  

Patch

diff --git a/drivers/raw/ifpga_rawdev/base/Makefile b/drivers/raw/ifpga_rawdev/base/Makefile
index d79da72..c77e751 100644
--- a/drivers/raw/ifpga_rawdev/base/Makefile
+++ b/drivers/raw/ifpga_rawdev/base/Makefile
@@ -22,5 +22,12 @@  SRCS-y += opae_hw_api.c
 SRCS-y += opae_ifpga_hw_api.c
 SRCS-y += opae_debug.c
 SRCS-y += ifpga_fme_pr.c
+SRCS-y += opae_spi.c
+SRCS-y += opae_spi_transaction.c
+SRCS-y += opae_mdio.c
+SRCS-y += opae_i2c.c
+SRCS-y += opae_at24_eeprom.c
+SRCS-y += opae_phy_group.c
+SRCS-y += opae_intel_max10.c
 
 SRCS-y += $(wildcard $(SRCDIR)/base/$(OSDEP)/*.c)
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_api.c b/drivers/raw/ifpga_rawdev/base/ifpga_api.c
index 540e171..0fd8de1 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_api.c
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_api.c
@@ -170,7 +170,6 @@  struct opae_accelerator_ops ifpga_acc_ops = {
 };
 
 /* Bridge APIs */
-
 static int ifpga_br_reset(struct opae_bridge *br)
 {
 	struct ifpga_port_hw *port = br->data;
@@ -196,13 +195,79 @@  struct opae_manager_ops ifpga_mgr_ops = {
 	.flash = ifpga_mgr_flash,
 };
 
+static int ifpga_mgr_read_mac_rom(struct opae_manager *mgr, int offset,
+		void *buf, int size)
+{
+	struct ifpga_fme_hw *fme = mgr->data;
+
+	return fme_mgr_read_mac_rom(fme, offset, buf, size);
+}
+
+static int ifpga_mgr_write_mac_rom(struct opae_manager *mgr, int offset,
+		void *buf, int size)
+{
+	struct ifpga_fme_hw *fme = mgr->data;
+
+	return fme_mgr_write_mac_rom(fme, offset, buf, size);
+}
+
+static int ifpga_mgr_read_phy_reg(struct opae_manager *mgr, int phy_group,
+		u8 entry, u16 reg, u32 *value)
+{
+	struct ifpga_fme_hw *fme = mgr->data;
+
+	return fme_mgr_read_phy_reg(fme, phy_group, entry, reg, value);
+}
+
+static int ifpga_mgr_write_phy_reg(struct opae_manager *mgr, int phy_group,
+		u8 entry, u16 reg, u32 value)
+{
+	struct ifpga_fme_hw *fme = mgr->data;
+
+	return fme_mgr_write_phy_reg(fme, phy_group, entry, reg, value);
+}
+
+static int ifpga_mgr_get_retimer_info(struct opae_manager *mgr,
+		struct opae_retimer_info *info)
+{
+	struct ifpga_fme_hw *fme = mgr->data;
+
+	return fme_mgr_get_retimer_info(fme, info);
+}
+
+static int ifpga_mgr_set_retimer_speed(struct opae_manager *mgr, int speed)
+{
+	struct ifpga_fme_hw *fme = mgr->data;
+
+	return fme_mgr_set_retimer_speed(fme, speed);
+}
+
+static int ifpga_mgr_get_retimer_status(struct opae_manager *mgr, int port,
+		struct opae_retimer_status *status)
+{
+	struct ifpga_fme_hw *fme = mgr->data;
+
+	return fme_mgr_get_retimer_status(fme, port, status);
+}
+
+/* Network APIs in FME */
+struct opae_manager_networking_ops ifpga_mgr_network_ops = {
+	.read_mac_rom = ifpga_mgr_read_mac_rom,
+	.write_mac_rom = ifpga_mgr_write_mac_rom,
+	.read_phy_reg = ifpga_mgr_read_phy_reg,
+	.write_phy_reg = ifpga_mgr_write_phy_reg,
+	.get_retimer_info = ifpga_mgr_get_retimer_info,
+	.set_retimer_speed = ifpga_mgr_set_retimer_speed,
+	.get_retimer_status = ifpga_mgr_get_retimer_status,
+};
+
 /* Adapter APIs */
 static int ifpga_adapter_enumerate(struct opae_adapter *adapter)
 {
 	struct ifpga_hw *hw = malloc(sizeof(*hw));
 
 	if (hw) {
-		memset(hw, 0, sizeof(*hw));
+		opae_memset(hw, 0, sizeof(*hw));
 		hw->pci_data = adapter->data;
 		hw->adapter = adapter;
 		if (ifpga_bus_enumerate(hw))
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_api.h b/drivers/raw/ifpga_rawdev/base/ifpga_api.h
index dae7ca1..4a24769 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_api.h
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_api.h
@@ -12,6 +12,7 @@ 
 extern struct opae_manager_ops ifpga_mgr_ops;
 extern struct opae_bridge_ops ifpga_br_ops;
 extern struct opae_accelerator_ops ifpga_acc_ops;
+extern struct opae_manager_networking_ops ifpga_mgr_network_ops;
 
 /* common APIs */
 int ifpga_get_prop(struct ifpga_hw *hw, u32 fiu_id, u32 port_id,
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_defines.h b/drivers/raw/ifpga_rawdev/base/ifpga_defines.h
index aa02527..cbd97fe 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_defines.h
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_defines.h
@@ -15,9 +15,13 @@ 
 #define FME_FEATURE_GLOBAL_IPERF    "fme_iperf"
 #define FME_FEATURE_GLOBAL_ERR      "fme_error"
 #define FME_FEATURE_PR_MGMT         "fme_pr"
+#define FME_FEATURE_EMIF_MGMT       "fme_emif"
 #define FME_FEATURE_HSSI_ETH        "fme_hssi"
 #define FME_FEATURE_GLOBAL_DPERF    "fme_dperf"
 #define FME_FEATURE_QSPI_FLASH	    "fme_qspi_flash"
+#define FME_FEATURE_MAX10_SPI       "fme_max10_spi"
+#define FME_FEATURE_I2C_MASTER      "fme_i2c_master"
+#define FME_FEATURE_PHY_GROUP       "fme_phy_group"
 
 #define PORT_FEATURE_HEADER         "port_hdr"
 #define PORT_FEATURE_UAFU           "port_uafu"
@@ -42,6 +46,9 @@ 
 #define FME_HSSI_ETH_REVISION		0
 #define FME_GLOBAL_DPERF_REVISION	0
 #define FME_QSPI_REVISION		0
+#define FME_MAX10_SPI                   0
+#define FME_I2C_MASTER                  0
+#define FME_PHY_GROUP                   0
 
 #define PORT_HEADER_REVISION		0
 /* UAFU's header info depends on the downloaded GBS */
@@ -59,7 +66,8 @@ 
 #define FEATURE_FIU_ID_FME	0x0
 #define FEATURE_FIU_ID_PORT	0x1
 
-#define FEATURE_ID_HEADER	0x0
+/* Reserved 0xfe for Header, 0xff for AFU*/
+#define FEATURE_ID_FIU_HEADER	0xfe
 #define FEATURE_ID_AFU		0xff
 
 enum fpga_id_type {
@@ -68,31 +76,26 @@  enum fpga_id_type {
 	FPGA_ID_MAX,
 };
 
-enum fme_feature_id {
-	FME_FEATURE_ID_HEADER = 0x0,
-
-	FME_FEATURE_ID_THERMAL_MGMT	= 0x1,
-	FME_FEATURE_ID_POWER_MGMT = 0x2,
-	FME_FEATURE_ID_GLOBAL_IPERF = 0x3,
-	FME_FEATURE_ID_GLOBAL_ERR = 0x4,
-	FME_FEATURE_ID_PR_MGMT = 0x5,
-	FME_FEATURE_ID_HSSI_ETH = 0x6,
-	FME_FEATURE_ID_GLOBAL_DPERF = 0x7,
-	FME_FEATURE_ID_QSPI_FLASH = 0x8,
-
-	/* one for fme header. */
-	FME_FEATURE_ID_MAX = 0x9,
-};
-
-enum port_feature_id {
-	PORT_FEATURE_ID_HEADER = 0x0,
-	PORT_FEATURE_ID_ERROR = 0x1,
-	PORT_FEATURE_ID_UMSG = 0x2,
-	PORT_FEATURE_ID_UINT = 0x3,
-	PORT_FEATURE_ID_STP = 0x4,
-	PORT_FEATURE_ID_UAFU = 0x5,
-	PORT_FEATURE_ID_MAX = 0x6,
-};
+#define FME_FEATURE_ID_HEADER FEATURE_ID_FIU_HEADER
+#define FME_FEATURE_ID_THERMAL_MGMT 0x1
+#define FME_FEATURE_ID_POWER_MGMT 0x2
+#define FME_FEATURE_ID_GLOBAL_IPERF 0x3
+#define FME_FEATURE_ID_GLOBAL_ERR 0x4
+#define FME_FEATURE_ID_PR_MGMT 0x5
+#define FME_FEATURE_ID_HSSI_ETH 0x6
+#define FME_FEATURE_ID_GLOBAL_DPERF 0x7
+#define FME_FEATURE_ID_QSPI_FLASH 0x8
+#define FME_FEATURE_ID_EMIF_MGMT  0x9
+#define FME_FEATURE_ID_MAX10_SPI  0xe
+#define FME_FEATURE_ID_I2C_MASTER  0xf
+#define FME_FEATURE_ID_PHY_GROUP 0x10
+
+#define PORT_FEATURE_ID_HEADER FEATURE_ID_FIU_HEADER
+#define PORT_FEATURE_ID_ERROR 0x10
+#define PORT_FEATURE_ID_UMSG 0x12
+#define PORT_FEATURE_ID_UINT 0x13
+#define PORT_FEATURE_ID_STP 0x14
+#define PORT_FEATURE_ID_UAFU FEATURE_ID_AFU
 
 /*
  * All headers and structures must be byte-packed to match the spec.
@@ -1303,6 +1306,37 @@  struct feature_fme_hssi {
 	struct feature_fme_hssi_eth_stat	hssi_status;
 };
 
+/*FME SPI Master for VC*/
+struct feature_fme_spi {
+	struct feature_header header;
+	u64 reg[4];
+};
+
+/* FME I2C Master */
+struct feature_fme_i2c {
+	struct feature_header header;
+	u64 reg[4];
+};
+
+struct feature_fme_phy_group_info {
+	union {
+		u64 info;
+		struct {
+			u8 group_index:8;
+			u8 number:8;
+			u8 speed:8;
+			u8 direction:1;
+			u64 rsvd:39;
+		};
+	};
+};
+
+/* FME PHY Group */
+struct feature_fme_phy_group {
+	struct feature_header header;
+	struct feature_fme_phy_group_info phy_info;
+};
+
 #define PORT_ERR_MASK		0xfff0703ff001f
 struct feature_port_err_key {
 	union {
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c b/drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c
index 848e518..0a206cb 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c
@@ -28,121 +28,24 @@  struct build_feature_devs_info {
 	struct ifpga_hw *hw;
 };
 
-struct feature_info {
-	const char *name;
-	u32 resource_size;
-	int feature_index;
-	int revision_id;
-	unsigned int vec_start;
-	unsigned int vec_cnt;
-
-	struct feature_ops *ops;
-};
+static int feature_revision(void __iomem *start)
+{
+	struct feature_header header;
 
-/* indexed by fme feature IDs which are defined in 'enum fme_feature_id'. */
-static struct feature_info fme_features[] = {
-	{
-		.name = FME_FEATURE_HEADER,
-		.resource_size = sizeof(struct feature_fme_header),
-		.feature_index = FME_FEATURE_ID_HEADER,
-		.revision_id = FME_HEADER_REVISION,
-		.ops = &fme_hdr_ops,
-	},
-	{
-		.name = FME_FEATURE_THERMAL_MGMT,
-		.resource_size = sizeof(struct feature_fme_thermal),
-		.feature_index = FME_FEATURE_ID_THERMAL_MGMT,
-		.revision_id = FME_THERMAL_MGMT_REVISION,
-		.ops = &fme_thermal_mgmt_ops,
-	},
-	{
-		.name = FME_FEATURE_POWER_MGMT,
-		.resource_size = sizeof(struct feature_fme_power),
-		.feature_index = FME_FEATURE_ID_POWER_MGMT,
-		.revision_id = FME_POWER_MGMT_REVISION,
-		.ops = &fme_power_mgmt_ops,
-	},
-	{
-		.name = FME_FEATURE_GLOBAL_IPERF,
-		.resource_size = sizeof(struct feature_fme_iperf),
-		.feature_index = FME_FEATURE_ID_GLOBAL_IPERF,
-		.revision_id = FME_GLOBAL_IPERF_REVISION,
-		.ops = &fme_global_iperf_ops,
-	},
-	{
-		.name = FME_FEATURE_GLOBAL_ERR,
-		.resource_size = sizeof(struct feature_fme_err),
-		.feature_index = FME_FEATURE_ID_GLOBAL_ERR,
-		.revision_id = FME_GLOBAL_ERR_REVISION,
-		.ops = &fme_global_err_ops,
-	},
-	{
-		.name = FME_FEATURE_PR_MGMT,
-		.resource_size = sizeof(struct feature_fme_pr),
-		.feature_index = FME_FEATURE_ID_PR_MGMT,
-		.revision_id = FME_PR_MGMT_REVISION,
-		.ops = &fme_pr_mgmt_ops,
-	},
-	{
-		.name = FME_FEATURE_HSSI_ETH,
-		.resource_size = sizeof(struct feature_fme_hssi),
-		.feature_index = FME_FEATURE_ID_HSSI_ETH,
-		.revision_id = FME_HSSI_ETH_REVISION
-	},
-	{
-		.name = FME_FEATURE_GLOBAL_DPERF,
-		.resource_size = sizeof(struct feature_fme_dperf),
-		.feature_index = FME_FEATURE_ID_GLOBAL_DPERF,
-		.revision_id = FME_GLOBAL_DPERF_REVISION,
-		.ops = &fme_global_dperf_ops,
-	}
-};
+	header.csr = readq(start);
 
-static struct feature_info port_features[] = {
-	{
-		.name = PORT_FEATURE_HEADER,
-		.resource_size = sizeof(struct feature_port_header),
-		.feature_index = PORT_FEATURE_ID_HEADER,
-		.revision_id = PORT_HEADER_REVISION,
-		.ops = &ifpga_rawdev_port_hdr_ops,
-	},
-	{
-		.name = PORT_FEATURE_ERR,
-		.resource_size = sizeof(struct feature_port_error),
-		.feature_index = PORT_FEATURE_ID_ERROR,
-		.revision_id = PORT_ERR_REVISION,
-		.ops = &ifpga_rawdev_port_error_ops,
-	},
-	{
-		.name = PORT_FEATURE_UMSG,
-		.resource_size = sizeof(struct feature_port_umsg),
-		.feature_index = PORT_FEATURE_ID_UMSG,
-		.revision_id = PORT_UMSG_REVISION,
-	},
-	{
-		.name = PORT_FEATURE_UINT,
-		.resource_size = sizeof(struct feature_port_uint),
-		.feature_index = PORT_FEATURE_ID_UINT,
-		.revision_id = PORT_UINT_REVISION,
-		.ops = &ifpga_rawdev_port_uint_ops,
-	},
-	{
-		.name = PORT_FEATURE_STP,
-		.resource_size = PORT_FEATURE_STP_REGION_SIZE,
-		.feature_index = PORT_FEATURE_ID_STP,
-		.revision_id = PORT_STP_REVISION,
-		.ops = &ifpga_rawdev_port_stp_ops,
-	},
-	{
-		.name = PORT_FEATURE_UAFU,
-		/* UAFU feature size should be read from PORT_CAP.MMIOSIZE.
-		 * Will set uafu feature size while parse port device.
-		 */
-		.resource_size = 0,
-		.feature_index = PORT_FEATURE_ID_UAFU,
-		.revision_id = PORT_UAFU_REVISION
-	},
-};
+	return header.revision;
+}
+
+static u32 feature_size(void __iomem *start)
+{
+	struct feature_header header;
+
+	header.csr = readq(start);
+
+	/*the size of private feature is 4KB aligned*/
+	return header.next_header_offset ? header.next_header_offset:4096;
+}
 
 static u64 feature_id(void __iomem *start)
 {
@@ -152,7 +55,7 @@  static u64 feature_id(void __iomem *start)
 
 	switch (header.type) {
 	case FEATURE_TYPE_FIU:
-		return FEATURE_ID_HEADER;
+		return FEATURE_ID_FIU_HEADER;
 	case FEATURE_TYPE_PRIVATE:
 		return header.id;
 	case FEATURE_TYPE_AFU:
@@ -165,37 +68,35 @@  static u64 feature_id(void __iomem *start)
 
 static int
 build_info_add_sub_feature(struct build_feature_devs_info *binfo,
-			   struct feature_info *finfo, void __iomem *start)
+		void __iomem *start, u64 fid, unsigned int size,
+		unsigned int vec_start,
+		unsigned int vec_cnt)
 {
 	struct ifpga_hw *hw = binfo->hw;
 	struct feature *feature = NULL;
-	int feature_idx = finfo->feature_index;
-	unsigned int vec_start = finfo->vec_start;
-	unsigned int vec_cnt = finfo->vec_cnt;
 	struct feature_irq_ctx *ctx = NULL;
 	int port_id, ret = 0;
 	unsigned int i;
 
-	if (binfo->current_type == FME_ID) {
-		feature = &hw->fme.sub_feature[feature_idx];
-		feature->parent = &hw->fme;
-	} else if (binfo->current_type == PORT_ID) {
-		port_id = binfo->current_port_id;
-		feature = &hw->port[port_id].sub_feature[feature_idx];
-		feature->parent = &hw->port[port_id];
-	} else {
-		return -EFAULT;
-	}
+	fid = fid?fid:feature_id(start);
+	size = size?size:feature_size(start);
+
+	feature = opae_malloc(sizeof(struct feature));
+	if (!feature)
+		return -ENOMEM;
 
 	feature->state = IFPGA_FEATURE_ATTACHED;
 	feature->addr = start;
-	feature->id = feature_id(start);
-	feature->size = finfo->resource_size;
-	feature->name = finfo->name;
-	feature->revision = finfo->revision_id;
-	feature->ops = finfo->ops;
+	feature->id = fid;
+	feature->size = size;
+	feature->revision = feature_revision(start);
 	feature->phys_addr = binfo->phys_addr +
 				((u8 *)start - (u8 *)binfo->ioaddr);
+	feature->vec_start = vec_start;
+	feature->vec_cnt = vec_cnt;
+
+	dev_debug(binfo, "%s: id=0x%lx, phys_addr=0x%lx, size=%d\n",
+			__func__, feature->id, feature->phys_addr, size);
 
 	if (vec_cnt) {
 		if (vec_start + vec_cnt <= vec_start)
@@ -215,22 +116,32 @@  static u64 feature_id(void __iomem *start)
 	feature->ctx_num = vec_cnt;
 	feature->vfio_dev_fd = binfo->pci_data->vfio_dev_fd;
 
+	if (binfo->current_type == FME_ID) {
+		feature->parent = &hw->fme;
+		feature->type = FEATURE_FME_TYPE;
+		feature->name = get_fme_feature_name(fid);
+		TAILQ_INSERT_TAIL(&hw->fme.feature_list, feature, next);
+	} else if (binfo->current_type == PORT_ID) {
+		port_id = binfo->current_port_id;
+		feature->parent = &hw->port[port_id];
+		feature->type = FEATURE_PORT_TYPE;
+		feature->name = get_port_feature_name(fid);
+		TAILQ_INSERT_TAIL(&hw->port[port_id].feature_list,
+				feature, next);
+	} else {
+		return -EFAULT;
+	}
 	return ret;
 }
 
 static int
 create_feature_instance(struct build_feature_devs_info *binfo,
-			void __iomem *start, struct feature_info *finfo)
+			void __iomem *start, u64 fid,
+			unsigned int size, unsigned int vec_start,
+			unsigned int vec_cnt)
 {
-	struct feature_header *hdr = start;
-
-	if (finfo->revision_id != SKIP_REVISION_CHECK &&
-	    hdr->revision > finfo->revision_id) {
-		dev_err(binfo, "feature %s revision :default:%x, now at:%x, mis-match.\n",
-			finfo->name, finfo->revision_id, hdr->revision);
-	}
-
-	return build_info_add_sub_feature(binfo, finfo, start);
+	return build_info_add_sub_feature(binfo, start, fid, size, vec_start,
+			vec_cnt);
 }
 
 /*
@@ -249,31 +160,31 @@  static bool feature_is_UAFU(struct build_feature_devs_info *binfo)
 static int parse_feature_port_uafu(struct build_feature_devs_info *binfo,
 				   struct feature_header *hdr)
 {
-	enum port_feature_id id = PORT_FEATURE_ID_UAFU;
+	u64 id = PORT_FEATURE_ID_UAFU;
 	struct ifpga_afu_info *info;
 	void *start = (void *)hdr;
+	struct feature_port_header *port_hdr = binfo->ioaddr;
+	struct feature_port_capability capability;
 	int ret;
+	int size;
 
-	if (port_features[id].resource_size) {
-		ret = create_feature_instance(binfo, hdr, &port_features[id]);
-	} else {
-		dev_err(binfo, "the uafu feature header is mis-configured.\n");
-		ret = -EINVAL;
-	}
+	capability.csr = readq(&port_hdr->capability);
+
+	size = capability.mmio_size << 10;
 
+	ret = create_feature_instance(binfo, hdr, id, size, 0, 0);
 	if (ret)
 		return ret;
 
 	/* FIXME: need to figure out a better name */
-	info = malloc(sizeof(*info));
+	info = opae_malloc(sizeof(*info));
 	if (!info)
 		return -ENOMEM;
 
 	info->region[0].addr = start;
 	info->region[0].phys_addr = binfo->phys_addr +
 			(uint8_t *)start - (uint8_t *)binfo->ioaddr;
-	info->region[0].len = port_features[id].resource_size;
-	port_features[id].resource_size = 0;
+	info->region[0].len = size;
 	info->num_regions = 1;
 
 	binfo->acc_info = info;
@@ -320,6 +231,8 @@  static int build_info_commit_dev(struct build_feature_devs_info *binfo)
 	struct opae_manager *mgr;
 	struct opae_bridge *br;
 	struct opae_accelerator *acc;
+	struct ifpga_port_hw *port;
+	struct feature *feature;
 
 	if (!binfo->fiu)
 		return 0;
@@ -337,7 +250,11 @@  static int build_info_commit_dev(struct build_feature_devs_info *binfo)
 		br->id = binfo->current_port_id;
 
 		/* update irq info */
-		info->num_irqs = port_features[PORT_FEATURE_ID_UINT].vec_cnt;
+		port = &hw->port[binfo->current_port_id];
+		feature = get_feature_by_id(&port->feature_list,
+				PORT_FEATURE_ID_UINT);
+		if (feature)
+			info->num_irqs = feature->vec_cnt;
 
 		acc = opae_accelerator_alloc(hw->adapter->name,
 					     &ifpga_acc_ops, info);
@@ -353,7 +270,7 @@  static int build_info_commit_dev(struct build_feature_devs_info *binfo)
 
 	} else if (binfo->current_type == FME_ID) {
 		mgr = opae_manager_alloc(hw->adapter->name, &ifpga_mgr_ops,
-					 binfo->fiu);
+					&ifpga_mgr_network_ops, binfo->fiu);
 		if (!mgr)
 			return -ENOMEM;
 
@@ -402,10 +319,10 @@  static int parse_feature_fme(struct build_feature_devs_info *binfo,
 	/* Update FME states */
 	fme->state = IFPGA_FME_IMPLEMENTED;
 	fme->parent = hw;
+	TAILQ_INIT(&fme->feature_list);
 	spinlock_init(&fme->lock);
 
-	return create_feature_instance(binfo, start,
-				       &fme_features[FME_FEATURE_ID_HEADER]);
+	return create_feature_instance(binfo, start, 0, 0, 0, 0);
 }
 
 static int parse_feature_port(struct build_feature_devs_info *binfo,
@@ -433,29 +350,19 @@  static int parse_feature_port(struct build_feature_devs_info *binfo,
 	port->parent = hw;
 	port->state = IFPGA_PORT_ATTACHED;
 	spinlock_init(&port->lock);
+	TAILQ_INIT(&port->feature_list);
 
-	return create_feature_instance(binfo, start,
-				      &port_features[PORT_FEATURE_ID_HEADER]);
+	return create_feature_instance(binfo, start, 0, 0, 0, 0);
 }
 
 static void enable_port_uafu(struct build_feature_devs_info *binfo,
 			     void __iomem *start)
 {
-	enum port_feature_id id = PORT_FEATURE_ID_UAFU;
-	struct feature_port_header *port_hdr;
-	struct feature_port_capability capability;
 	struct ifpga_port_hw *port = &binfo->hw->port[binfo->current_port_id];
 
-	port_hdr = (struct feature_port_header *)start;
-	capability.csr = readq(&port_hdr->capability);
-	port_features[id].resource_size = (capability.mmio_size << 10);
-
-	/*
-	 * From spec, to Enable UAFU, we should reset related port,
-	 * or the whole mmio space in this UAFU will be invalid
-	 */
-	if (port_features[id].resource_size)
-		fpga_port_reset(port);
+	UNUSED(start);
+
+	fpga_port_reset(port);
 }
 
 static int parse_feature_fiu(struct build_feature_devs_info *binfo,
@@ -505,44 +412,45 @@  static int parse_feature_fiu(struct build_feature_devs_info *binfo,
 }
 
 static void parse_feature_irqs(struct build_feature_devs_info *binfo,
-			       void __iomem *start, struct feature_info *finfo)
+		void __iomem *start, unsigned int *vec_start,
+		unsigned int *vec_cnt)
 {
-	finfo->vec_start = 0;
-	finfo->vec_cnt = 0;
-
 	UNUSED(binfo);
+	u64 id;
+
+	id = feature_id(start);
 
-	if (!strcmp(finfo->name, PORT_FEATURE_UINT)) {
+	if (id == PORT_FEATURE_ID_UINT) {
 		struct feature_port_uint *port_uint = start;
 		struct feature_port_uint_cap uint_cap;
 
 		uint_cap.csr = readq(&port_uint->capability);
 		if (uint_cap.intr_num) {
-			finfo->vec_start = uint_cap.first_vec_num;
-			finfo->vec_cnt = uint_cap.intr_num;
+			*vec_start = uint_cap.first_vec_num;
+			*vec_cnt = uint_cap.intr_num;
 		} else {
 			dev_debug(binfo, "UAFU doesn't support interrupt\n");
 		}
-	} else if (!strcmp(finfo->name, PORT_FEATURE_ERR)) {
+	} else if (id == PORT_FEATURE_ID_ERROR) {
 		struct feature_port_error *port_err = start;
 		struct feature_port_err_capability port_err_cap;
 
 		port_err_cap.csr = readq(&port_err->error_capability);
 		if (port_err_cap.support_intr) {
-			finfo->vec_start = port_err_cap.intr_vector_num;
-			finfo->vec_cnt = 1;
+			*vec_start = port_err_cap.intr_vector_num;
+			*vec_cnt = 1;
 		} else {
 			dev_debug(&binfo, "Port error doesn't support interrupt\n");
 		}
 
-	} else if (!strcmp(finfo->name, FME_FEATURE_GLOBAL_ERR)) {
+	} else if (id == FME_FEATURE_ID_GLOBAL_ERR) {
 		struct feature_fme_err *fme_err = start;
 		struct feature_fme_error_capability fme_err_cap;
 
 		fme_err_cap.csr = readq(&fme_err->fme_err_capability);
 		if (fme_err_cap.support_intr) {
-			finfo->vec_start = fme_err_cap.intr_vector_num;
-			finfo->vec_cnt = 1;
+			*vec_start = fme_err_cap.intr_vector_num;
+			*vec_cnt = 1;
 		} else {
 			dev_debug(&binfo, "FME error doesn't support interrupt\n");
 		}
@@ -552,43 +460,23 @@  static void parse_feature_irqs(struct build_feature_devs_info *binfo,
 static int parse_feature_fme_private(struct build_feature_devs_info *binfo,
 				     struct feature_header *hdr)
 {
-	struct feature_header header;
-
-	header.csr = readq(hdr);
-
-	if (header.id >= ARRAY_SIZE(fme_features)) {
-		dev_err(binfo, "FME feature id %x is not supported yet.\n",
-			header.id);
-		return 0;
-	}
+	unsigned int vec_start = 0;
+	unsigned int vec_cnt = 0;
 
-	parse_feature_irqs(binfo, hdr, &fme_features[header.id]);
+	parse_feature_irqs(binfo, hdr, &vec_start, &vec_cnt);
 
-	return create_feature_instance(binfo, hdr, &fme_features[header.id]);
+	return create_feature_instance(binfo, hdr, 0, 0, vec_start, vec_cnt);
 }
 
 static int parse_feature_port_private(struct build_feature_devs_info *binfo,
 				      struct feature_header *hdr)
 {
-	struct feature_header header;
-	enum port_feature_id id;
+	unsigned int vec_start = 0;
+	unsigned int vec_cnt = 0;
 
-	header.csr = readq(hdr);
-	/*
-	 * the region of port feature id is [0x10, 0x13], + 1 to reserve 0
-	 * which is dedicated for port-hdr.
-	 */
-	id = (header.id & 0x000f) + 1;
-
-	if (id >= ARRAY_SIZE(port_features)) {
-		dev_err(binfo, "Port feature id %x is not supported yet.\n",
-			header.id);
-		return 0;
-	}
-
-	parse_feature_irqs(binfo, hdr, &port_features[id]);
+	parse_feature_irqs(binfo, hdr, &vec_start, &vec_cnt);
 
-	return create_feature_instance(binfo, hdr, &port_features[id]);
+	return create_feature_instance(binfo, hdr, 0, 0, vec_start, vec_cnt);
 }
 
 static int parse_feature_private(struct build_feature_devs_info *binfo,
@@ -651,12 +539,19 @@  static int parse_feature(struct build_feature_devs_info *binfo,
 		}
 
 		hdr = (struct feature_header *)start;
+		header.csr = readq(hdr);
+
+		/*debug*/
+		dev_debug(binfo, "%s: address=0x%llx, val=0x%lx, header.id=0x%x, header.next_offset=0x%x, header.eol=0x%x, header.type=0x%x\n",
+			__func__, (unsigned long long)(hdr), header.csr,
+			header.id, header.next_header_offset,
+			header.end_of_list, header.type);
+
 		ret = parse_feature(binfo, hdr);
 		if (ret)
 			return ret;
 
-		header.csr = readq(hdr);
-		if (!header.next_header_offset)
+		if (header.end_of_list || !header.next_header_offset)
 			break;
 	}
 
@@ -746,13 +641,12 @@  static void ifpga_print_device_feature_list(struct ifpga_hw *hw)
 	struct ifpga_fme_hw *fme = &hw->fme;
 	struct ifpga_port_hw *port;
 	struct feature *feature;
-	int i, j;
+	int i;
 
 	dev_info(hw, "found fme_device, is in PF: %s\n",
 		 is_ifpga_hw_pf(hw) ? "yes" : "no");
 
-	for (i = 0; i < FME_FEATURE_ID_MAX; i++) {
-		feature = &fme->sub_feature[i];
+	ifpga_for_each_fme_feature(fme, feature) {
 		if (feature->state != IFPGA_FEATURE_ATTACHED)
 			continue;
 
@@ -760,6 +654,7 @@  static void ifpga_print_device_feature_list(struct ifpga_hw *hw)
 			 feature->name, feature->addr,
 			 feature->addr + feature->size - 1,
 			 (unsigned long)feature->phys_addr);
+
 	}
 
 	for (i = 0; i < MAX_FPGA_PORT_NUM; i++) {
@@ -770,8 +665,7 @@  static void ifpga_print_device_feature_list(struct ifpga_hw *hw)
 
 		dev_info(hw, "port device: %d\n", port->port_id);
 
-		for (j = 0; j < PORT_FEATURE_ID_MAX; j++) {
-			feature = &port->sub_feature[j];
+		ifpga_for_each_port_feature(port, feature) {
 			if (feature->state != IFPGA_FEATURE_ATTACHED)
 				continue;
 
@@ -782,6 +676,7 @@  static void ifpga_print_device_feature_list(struct ifpga_hw *hw)
 				 feature->size - 1,
 				 (unsigned long)feature->phys_addr);
 		}
+
 	}
 }
 
@@ -812,10 +707,13 @@  int ifpga_bus_enumerate(struct ifpga_hw *hw)
 int ifpga_bus_init(struct ifpga_hw *hw)
 {
 	int i;
+	struct ifpga_port_hw *port;
 
 	fme_hw_init(&hw->fme);
-	for (i = 0; i < MAX_FPGA_PORT_NUM; i++)
-		port_hw_init(&hw->port[i]);
+	for (i = 0; i < MAX_FPGA_PORT_NUM; i++) {
+		port = &hw->port[i];
+		port_hw_init(port);
+	}
 
 	return 0;
 }
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.c b/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.c
index be7ac9e..88465d6 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.c
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.c
@@ -70,6 +70,9 @@  int fpga_get_afu_uuid(struct ifpga_port_hw *port, struct uuid *uuid)
 	struct feature_port_header *port_hdr;
 	u64 guidl, guidh;
 
+	if (!uuid)
+		return -EINVAL;
+
 	port_hdr = get_port_feature_ioaddr_by_index(port, PORT_FEATURE_ID_UAFU);
 
 	spinlock_lock(&port->lock);
@@ -77,8 +80,8 @@  int fpga_get_afu_uuid(struct ifpga_port_hw *port, struct uuid *uuid)
 	guidh = readq(&port_hdr->afu_header.guid.b[8]);
 	spinlock_unlock(&port->lock);
 
-	memcpy(uuid->b, &guidl, sizeof(u64));
-	memcpy(uuid->b + 8, &guidh, sizeof(u64));
+	opae_memcpy(uuid->b, &guidl, sizeof(u64));
+	opae_memcpy(uuid->b + 8, &guidh, sizeof(u64));
 
 	return 0;
 }
@@ -177,77 +180,152 @@  int port_clear_error(struct ifpga_port_hw *port)
 	return port_err_clear(port, error.csr);
 }
 
-void fme_hw_uinit(struct ifpga_fme_hw *fme)
+static struct feature_driver fme_feature_drvs[] = {
+	{FEATURE_DRV(FME_FEATURE_ID_HEADER, FME_FEATURE_HEADER,
+			&fme_hdr_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_THERMAL_MGMT, FME_FEATURE_THERMAL_MGMT,
+			&fme_thermal_mgmt_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_POWER_MGMT, FME_FEATURE_POWER_MGMT,
+			&fme_power_mgmt_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_GLOBAL_ERR, FME_FEATURE_GLOBAL_ERR,
+			&fme_global_err_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_PR_MGMT, FME_FEATURE_PR_MGMT,
+			&fme_pr_mgmt_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_GLOBAL_DPERF, FME_FEATURE_GLOBAL_DPERF,
+			&fme_global_dperf_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_HSSI_ETH, FME_FEATURE_HSSI_ETH,
+	&fme_hssi_eth_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_EMIF_MGMT, FME_FEATURE_EMIF_MGMT,
+	&fme_emif_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_MAX10_SPI, FME_FEATURE_MAX10_SPI,
+	&fme_spi_master_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_I2C_MASTER, FME_FEATURE_I2C_MASTER,
+	&fme_i2c_master_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_PHY_GROUP, FME_FEATURE_PHY_GROUP,
+	&fme_phy_group_ops),},
+	{0, NULL, NULL}, /* end of arrary */
+};
+
+static struct feature_driver port_feature_drvs[] = {
+	{FEATURE_DRV(PORT_FEATURE_ID_HEADER, PORT_FEATURE_HEADER,
+			&ifpga_rawdev_port_hdr_ops)},
+	{FEATURE_DRV(PORT_FEATURE_ID_ERROR, PORT_FEATURE_ERR,
+			&ifpga_rawdev_port_error_ops)},
+	{FEATURE_DRV(PORT_FEATURE_ID_UINT, PORT_FEATURE_UINT,
+			&ifpga_rawdev_port_uint_ops)},
+	{FEATURE_DRV(PORT_FEATURE_ID_STP, PORT_FEATURE_STP,
+			&ifpga_rawdev_port_stp_ops)},
+	{FEATURE_DRV(PORT_FEATURE_ID_UAFU, PORT_FEATURE_UAFU,
+			&ifpga_rawdev_port_afu_ops)},
+	{0, NULL, NULL}, /* end of array */
+};
+
+const char *get_fme_feature_name(unsigned int id)
 {
-	struct feature *feature;
-	int i;
+	struct feature_driver *drv = fme_feature_drvs;
 
-	if (fme->state != IFPGA_FME_IMPLEMENTED)
-		return;
+	while (drv->name) {
+		if (drv->id == id)
+			return drv->name;
 
-	for (i = 0; i < FME_FEATURE_ID_MAX; i++) {
-		feature = &fme->sub_feature[i];
-		if (feature->state == IFPGA_FEATURE_ATTACHED &&
-		    feature->ops && feature->ops->uinit)
-			feature->ops->uinit(feature);
+		drv++;
 	}
+
+	return NULL;
 }
 
-int fme_hw_init(struct ifpga_fme_hw *fme)
+const char *get_port_feature_name(unsigned int id)
+{
+	struct feature_driver *drv = port_feature_drvs;
+
+	while (drv->name) {
+		if (drv->id == id)
+			return drv->name;
+
+		drv++;
+	}
+
+	return NULL;
+}
+
+static void feature_uinit(struct ifpga_feature_list *list)
 {
 	struct feature *feature;
-	int i, ret;
 
-	if (fme->state != IFPGA_FME_IMPLEMENTED)
-		return -EINVAL;
+	TAILQ_FOREACH(feature, list, next) {
+		if (feature->state != IFPGA_FEATURE_ATTACHED)
+			continue;
+		if (feature->ops && feature->ops->uinit)
+			feature->ops->uinit(feature);
+	}
+}
 
-	for (i = 0; i < FME_FEATURE_ID_MAX; i++) {
-		feature = &fme->sub_feature[i];
-		if (feature->state == IFPGA_FEATURE_ATTACHED &&
-		    feature->ops && feature->ops->init) {
-			ret = feature->ops->init(feature);
-			if (ret) {
-				fme_hw_uinit(fme);
-				return ret;
+static int feature_init(struct feature_driver *drv,
+		struct ifpga_feature_list *list)
+{
+	struct feature *feature;
+	int ret;
+
+	while (drv->ops) {
+		TAILQ_FOREACH(feature, list, next) {
+			if (feature->state != IFPGA_FEATURE_ATTACHED)
+				continue;
+			if (feature->id == drv->id) {
+				feature->ops = drv->ops;
+				feature->name = drv->name;
+				if (feature->ops->init) {
+					ret = feature->ops->init(feature);
+					if (ret)
+						goto error;
+				}
 			}
 		}
+		drv++;
 	}
 
 	return 0;
+error:
+	feature_uinit(list);
+	return ret;
 }
 
-void port_hw_uinit(struct ifpga_port_hw *port)
+int fme_hw_init(struct ifpga_fme_hw *fme)
 {
-	struct feature *feature;
-	int i;
+	int ret;
 
-	for (i = 0; i < PORT_FEATURE_ID_MAX; i++) {
-		feature = &port->sub_feature[i];
-		if (feature->state == IFPGA_FEATURE_ATTACHED &&
-		    feature->ops && feature->ops->uinit)
-			feature->ops->uinit(feature);
-	}
+	if (fme->state != IFPGA_FME_IMPLEMENTED)
+		return -ENODEV;
+
+	ret = feature_init(fme_feature_drvs, &fme->feature_list);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+void fme_hw_uinit(struct ifpga_fme_hw *fme)
+{
+	feature_uinit(&fme->feature_list);
+}
+
+void port_hw_uinit(struct ifpga_port_hw *port)
+{
+	feature_uinit(&port->feature_list);
 }
 
 int port_hw_init(struct ifpga_port_hw *port)
 {
-	struct feature *feature;
-	int i, ret;
+	int ret;
 
 	if (port->state == IFPGA_PORT_UNUSED)
 		return 0;
 
-	for (i = 0; i < PORT_FEATURE_ID_MAX; i++) {
-		feature = &port->sub_feature[i];
-		if (feature->ops && feature->ops->init) {
-			ret = feature->ops->init(feature);
-			if (ret) {
-				port_hw_uinit(port);
-				return ret;
-			}
-		}
-	}
+	ret = feature_init(port_feature_drvs, &port->feature_list);
+	if (ret)
+		goto error;
 
 	return 0;
+error:
+	port_hw_uinit(port);
+	return ret;
 }
-
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.h b/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.h
index 4391f2f..067e9aa 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.h
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.h
@@ -7,6 +7,18 @@ 
 
 #include "ifpga_hw.h"
 
+struct feature_driver {
+	u64 id;
+	const char *name;
+	struct feature_ops *ops;
+};
+
+/**
+ * FEATURE_DRV - macro used to describe a specific feature driver
+ */
+#define FEATURE_DRV(n, s, p) \
+	.id = (n), .name = (s), .ops = (p)
+
 static inline struct ifpga_port_hw *
 get_port(struct ifpga_hw *hw, u32 port_id)
 {
@@ -17,12 +29,10 @@ 
 }
 
 #define ifpga_for_each_fme_feature(hw, feature)		\
-	for ((feature) = (hw)->sub_feature;			\
-	   (feature) < (hw)->sub_feature + (FME_FEATURE_ID_MAX); (feature)++)
+	TAILQ_FOREACH(feature, &hw->feature_list, next)
 
-#define ifpga_for_each_port_feature(hw, feature)		\
-	for ((feature) = (hw)->sub_feature;			\
-	   (feature) < (hw)->sub_feature + (PORT_FEATURE_ID_MAX); (feature)++)
+#define ifpga_for_each_port_feature(port, feature)		\
+	TAILQ_FOREACH(feature, &port->feature_list, next)
 
 static inline struct feature *
 get_fme_feature_by_id(struct ifpga_fme_hw *fme, u64 id)
@@ -50,16 +60,32 @@ 
 	return NULL;
 }
 
+static inline struct feature *
+get_feature_by_id(struct ifpga_feature_list *list, u64 id)
+{
+	struct feature *feature;
+
+	TAILQ_FOREACH(feature, list, next)
+		if (feature->id == id)
+			return feature;
+
+	return NULL;
+}
+
 static inline void  *
 get_fme_feature_ioaddr_by_index(struct ifpga_fme_hw *fme, int index)
 {
-	return fme->sub_feature[index].addr;
+	struct feature *feature = get_feature_by_id(&fme->feature_list, index);
+
+	return feature ? feature->addr : NULL;
 }
 
 static inline void  *
 get_port_feature_ioaddr_by_index(struct ifpga_port_hw *port, int index)
 {
-	return port->sub_feature[index].addr;
+	struct feature *feature = get_feature_by_id(&port->feature_list, index);
+
+	return feature ? feature->addr : NULL;
 }
 
 static inline bool
@@ -143,6 +169,11 @@  int do_pr(struct ifpga_hw *hw, u32 port_id, void *buffer, u32 size,
 extern struct feature_ops fme_pr_mgmt_ops;
 extern struct feature_ops fme_global_iperf_ops;
 extern struct feature_ops fme_global_dperf_ops;
+extern struct feature_ops fme_hssi_eth_ops;
+extern struct feature_ops fme_emif_ops;
+extern struct feature_ops fme_spi_master_ops;
+extern struct feature_ops fme_i2c_master_ops;
+extern struct feature_ops fme_phy_group_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);
@@ -155,14 +186,31 @@  struct fpga_uafu_irq_set {
 };
 
 int port_set_irq(struct ifpga_port_hw *port, u32 feature_id, void *irq_set);
+const char *get_fme_feature_name(unsigned int id);
+const char *get_port_feature_name(unsigned int id);
 
 extern struct feature_ops ifpga_rawdev_port_hdr_ops;
 extern struct feature_ops ifpga_rawdev_port_error_ops;
 extern struct feature_ops ifpga_rawdev_port_stp_ops;
 extern struct feature_ops ifpga_rawdev_port_uint_ops;
+extern struct feature_ops ifpga_rawdev_port_afu_ops;
 
 /* help functions for feature ops */
 int fpga_msix_set_block(struct feature *feature, unsigned int start,
 			unsigned int count, s32 *fds);
 
+/* FME network function ops*/
+int fme_mgr_read_mac_rom(struct ifpga_fme_hw *fme, int offset,
+		void *buf, int size);
+int fme_mgr_write_mac_rom(struct ifpga_fme_hw *fme, int offset,
+		void *buf, int size);
+int fme_mgr_read_phy_reg(struct ifpga_fme_hw *fme, int phy_group,
+		u8 entry, u16 reg, u32 *value);
+int fme_mgr_write_phy_reg(struct ifpga_fme_hw *fme, int phy_group,
+		u8 entry, u16 reg, u32 value);
+int fme_mgr_get_retimer_info(struct ifpga_fme_hw *fme,
+		struct opae_retimer_info *info);
+int fme_mgr_set_retimer_speed(struct ifpga_fme_hw *fme, int speed);
+int fme_mgr_get_retimer_status(struct ifpga_fme_hw *fme, int port,
+		struct opae_retimer_status *status);
 #endif /* _IFPGA_FEATURE_DEV_H_ */
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_fme.c b/drivers/raw/ifpga_rawdev/base/ifpga_fme.c
index 4be60c0..df87b5f 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_fme.c
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_fme.c
@@ -3,6 +3,12 @@ 
  */
 
 #include "ifpga_feature_dev.h"
+#include "opae_i2c.h"
+#include "opae_spi.h"
+#include "opae_at24_eeprom.h"
+#include "opae_phy_group.h"
+#include "opae_intel_max10.h"
+#include "opae_mdio.h"
 
 #define PWR_THRESHOLD_MAX       0x7F
 
@@ -732,3 +738,370 @@  struct feature_ops fme_power_mgmt_ops = {
 	.get_prop = fme_power_mgmt_get_prop,
 	.set_prop = fme_power_mgmt_set_prop,
 };
+
+static int spi_self_checking(void)
+{
+	u32 val;
+	int ret;
+
+	ret = max10_reg_read(0x30043c, &val);
+	if (ret)
+		return -EIO;
+
+	if (val != 0x87654321) {
+		dev_err(NULL, "Read MAX10 test register fail: 0x%x\n", val);
+		return -EIO;
+	}
+
+	dev_info(NULL, "Read MAX10 test register success, SPI self-test done\n");
+
+	return 0;
+}
+
+static int fme_spi_init(struct feature *feature)
+{
+	struct feature_fme_spi *spi;
+	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
+	struct altera_spi_device *spi_master;
+	struct intel_max10_device *max10;
+	int ret = 0;
+
+	spi = (struct feature_fme_spi *)feature->addr;
+
+	dev_info(fme, "FME SPI Master (Max10) Init.\n");
+	dev_debug(fme, "FME SPI base addr %llx.\n",
+		 (unsigned long long)spi);
+	dev_debug(fme, "spi param=0x%lx\n", opae_readq(feature->addr + 0x8));
+
+	spi_master = altera_spi_init(feature->addr);
+	if (!spi_master)
+		return -ENODEV;
+
+	max10 = intel_max10_device_probe(spi_master, 0);
+	if (!max10) {
+		ret = -ENODEV;
+		dev_err(fme, "max10 init fail\n");
+		goto spi_fail;
+	}
+
+	fme->max10_dev = max10;
+
+	/* SPI self test */
+	if (spi_self_checking())
+		return -EIO;
+
+	return ret;
+
+spi_fail:
+	altera_spi_release(spi_master);
+	return ret;
+}
+
+static void fme_spi_uinit(struct feature *feature)
+{
+	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
+
+	if (fme->max10_dev)
+		intel_max10_device_remove(fme->max10_dev);
+}
+
+struct feature_ops fme_spi_master_ops = {
+	.init = fme_spi_init,
+	.uinit = fme_spi_uinit,
+
+};
+
+static int i2c_mac_rom_test(struct altera_i2c_dev *dev)
+{
+	char buf[20];
+	int ret;
+	char read_buf[20] = {0,};
+	const char *string = "1a2b3c4d5e";
+	unsigned int i;
+
+	opae_memcpy(buf, string, strlen(string));
+
+	printf("data writing into mac rom:\n");
+	for (i = 0; i < strlen(string); i++)
+		printf("%x ", *((char *)buf+i));
+	printf("\n");
+
+	ret = at24_eeprom_write(dev, AT24512_SLAVE_ADDR, 0,
+			(u8 *)buf, strlen(string));
+	if (ret < 0)
+		printf("write i2c error:%d\n", ret);
+
+	ret = at24_eeprom_read(dev, AT24512_SLAVE_ADDR, 0,
+			(u8 *)read_buf, strlen(string));
+	if (ret < 0)
+		printf("read i2c error:%d\n", ret);
+
+	printf("read from mac rom\n");
+	for (i = 0; i < strlen(string); i++)
+		printf("%x ", *((char *)read_buf+i));
+	printf("\n");
+
+	if (!memcmp(buf, read_buf, strlen(string))) {
+		printf("%s test success!\n", __func__);
+		return -EFAULT;
+	}
+
+	printf("%s test fail\n", __func__);
+
+	return 0;
+}
+
+static int fme_i2c_init(struct feature *feature)
+{
+	struct feature_fme_i2c *i2c;
+	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
+
+	i2c = (struct feature_fme_i2c *)feature->addr;
+
+	dev_info(NULL, "FME I2C Master Init.\n");
+
+	fme->i2c_master = altera_i2c_probe(i2c);
+	if (!fme->i2c_master)
+		return -ENODEV;
+
+	if (i2c_mac_rom_test(fme->i2c_master))
+		return -ENODEV;
+
+	return 0;
+}
+
+static void fme_i2c_uninit(struct feature *feature)
+{
+	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
+
+	altera_i2c_remove(fme->i2c_master);
+}
+
+struct feature_ops fme_i2c_master_ops = {
+	.init = fme_i2c_init,
+	.uinit = fme_i2c_uninit,
+};
+
+static int fme_phy_group_init(struct feature *feature)
+{
+	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
+	struct phy_group_device *dev;
+
+	dev = (struct phy_group_device *)phy_group_probe(feature->addr);
+	if (!dev)
+		return -ENODEV;
+
+	fme->phy_dev[dev->group_index] = dev;
+
+	dev_info(NULL, "FME PHY Group %d Init.\n", dev->group_index);
+	dev_info(NULL, "FME PHY Group register base address %llx.\n",
+			(unsigned long long)dev->base);
+
+	return 0;
+}
+
+static void fme_phy_group_uinit(struct feature *feature)
+{
+	UNUSED(feature);
+}
+
+struct feature_ops fme_phy_group_ops = {
+	.init = fme_phy_group_init,
+	.uinit = fme_phy_group_uinit,
+};
+
+static int fme_hssi_eth_init(struct feature *feature)
+{
+	UNUSED(feature);
+	return 0;
+}
+
+static void fme_hssi_eth_uinit(struct feature *feature)
+{
+	UNUSED(feature);
+}
+
+struct feature_ops fme_hssi_eth_ops = {
+	.init = fme_hssi_eth_init,
+	.uinit = fme_hssi_eth_uinit,
+};
+
+static int fme_emif_init(struct feature *feature)
+{
+	UNUSED(feature);
+	return 0;
+}
+
+static void fme_emif_uinit(struct feature *feature)
+{
+	UNUSED(feature);
+}
+
+struct feature_ops fme_emif_ops = {
+	.init = fme_emif_init,
+	.uinit = fme_emif_uinit,
+};
+
+static int fme_check_retimter_ports(struct ifpga_fme_hw *fme, int port)
+{
+	struct intel_max10_device *dev;
+	int ports;
+
+	dev = (struct intel_max10_device *)fme->max10_dev;
+	if (!dev)
+		return -ENODEV;
+
+	ports = dev->num_retimer * dev->num_port;
+
+	if (port > ports || port < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+int fme_mgr_read_mac_rom(struct ifpga_fme_hw *fme, int offset,
+		void *buf, int size)
+{
+	struct altera_i2c_dev *dev;
+
+	dev = fme->i2c_master;
+	if (!dev)
+		return -ENODEV;
+
+	if (fme_check_retimter_ports(fme, offset/size))
+		return -EINVAL;
+
+	return at24_eeprom_read(dev, AT24512_SLAVE_ADDR, offset, buf, size);
+}
+
+int fme_mgr_write_mac_rom(struct ifpga_fme_hw *fme, int offset,
+		void *buf, int size)
+{
+	struct altera_i2c_dev *dev;
+
+	dev = fme->i2c_master;
+	if (!dev)
+		return -ENODEV;
+
+	if (fme_check_retimter_ports(fme, offset/size))
+		return -EINVAL;
+
+	return at24_eeprom_write(dev, AT24512_SLAVE_ADDR, offset, buf, size);
+}
+
+int fme_mgr_read_phy_reg(struct ifpga_fme_hw *fme, int phy_group,
+		u8 entry, u16 reg, u32 *value)
+{
+	struct phy_group_device *dev;
+
+	if (phy_group > (MAX_PHY_GROUP_DEVICES - 1))
+		return -EINVAL;
+
+	dev = (struct phy_group_device *)fme->phy_dev[phy_group];
+	if (!dev)
+		return -ENODEV;
+
+	if (entry > dev->entries)
+		return -EINVAL;
+
+
+	return phy_group_read_reg(dev, entry, reg, value);
+}
+
+int fme_mgr_write_phy_reg(struct ifpga_fme_hw *fme, int phy_group,
+		u8 entry, u16 reg, u32 value)
+{
+	struct phy_group_device *dev;
+
+	if (phy_group > (MAX_PHY_GROUP_DEVICES - 1))
+		return -EINVAL;
+
+	dev = (struct phy_group_device *)fme->phy_dev[phy_group];
+	if (!dev)
+		return -ENODEV;
+
+	return phy_group_write_reg(dev, entry, reg, value);
+}
+
+int fme_mgr_get_retimer_info(struct ifpga_fme_hw *fme,
+		struct opae_retimer_info *info)
+{
+	struct intel_max10_device *dev;
+
+	dev = (struct intel_max10_device *)fme->max10_dev;
+	if (!dev)
+		return -ENODEV;
+
+	info->num_retimer = dev->num_retimer;
+	info->num_port = dev->num_port;
+
+	return 0;
+}
+
+int fme_mgr_set_retimer_speed(struct ifpga_fme_hw *fme, int speed)
+{
+	struct intel_max10_device *dev;
+	int i, j, num;
+	int ret = 0;
+
+	dev = (struct intel_max10_device *)fme->max10_dev;
+	if (!dev)
+		return -ENODEV;
+
+	num = dev->num_retimer < INTEL_MAX10_MAX_MDIO_DEVS ?
+		dev->num_retimer : INTEL_MAX10_MAX_MDIO_DEVS;
+
+	for (i = 0; i < num; i++)
+		for (j = 0; j < dev->num_port; j++) {
+			ret = pkvl_set_speed_mode(dev->mdio[i], j, speed);
+			if (ret) {
+				printf("pkvl_%d set port_%d speed %d fail\n",
+						i, j, speed);
+				break;
+			}
+		}
+
+	return ret;
+}
+
+int fme_mgr_get_retimer_status(struct ifpga_fme_hw *fme, int port,
+		struct opae_retimer_status *status)
+{
+	struct intel_max10_device *dev;
+	struct altera_mdio_dev *mdio;
+	int ports;
+	int ret;
+
+	dev = (struct intel_max10_device *)fme->max10_dev;
+	if (!dev)
+		return -ENODEV;
+
+	ports = dev->num_retimer * dev->num_port;
+
+	if (port > ports || port < 0)
+		return -EINVAL;
+
+	mdio = dev->mdio[port/dev->num_port];
+	port = port % dev->num_port;
+
+	ret = pkvl_get_port_speed_status(mdio, port, &status->speed);
+	if (ret)
+		goto error;
+
+	ret = pkvl_get_port_line_link_status(mdio, port, &status->line_link);
+	if (ret)
+		goto error;
+
+	ret = pkvl_get_port_host_link_status(mdio, port, &status->host_link);
+	if (ret)
+		goto error;
+
+	dev_info(NULL, "get retimer status: pkvl:%d, port:%d, speed:%d, line:%d, host:%d\n",
+			mdio->index, port, status->speed,
+			status->line_link, status->host_link);
+
+	return 0;
+
+error:
+	return ret;
+}
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_fme_pr.c b/drivers/raw/ifpga_rawdev/base/ifpga_fme_pr.c
index ec0beeb..8890f4b 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_fme_pr.c
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_fme_pr.c
@@ -257,7 +257,7 @@  static int fme_pr(struct ifpga_hw *hw, u32 port_id, void *buffer, u32 size,
 		return -EINVAL;
 	}
 
-	memset(&info, 0, sizeof(struct fpga_pr_info));
+	opae_memset(&info, 0, sizeof(struct fpga_pr_info));
 	info.flags = FPGA_MGR_PARTIAL_RECONFIG;
 	info.port_id = port_id;
 
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_hw.h b/drivers/raw/ifpga_rawdev/base/ifpga_hw.h
index a20520c..6ac54c6 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_hw.h
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_hw.h
@@ -7,19 +7,30 @@ 
 
 #include "ifpga_defines.h"
 #include "opae_ifpga_hw_api.h"
+#include "opae_phy_group.h"
+
+/** List of private feateues */
+TAILQ_HEAD(ifpga_feature_list, feature);
 
 enum ifpga_feature_state {
 	IFPGA_FEATURE_UNUSED = 0,
 	IFPGA_FEATURE_ATTACHED,
 };
 
+enum feature_type {
+	FEATURE_FME_TYPE = 0,
+	FEATURE_PORT_TYPE,
+};
+
 struct feature_irq_ctx {
 	int eventfd;
 	int idx;
 };
 
 struct feature {
+	TAILQ_ENTRY(feature)next;
 	enum ifpga_feature_state state;
+	enum feature_type type;
 	const char *name;
 	u64 id;
 	u8 *addr;
@@ -34,6 +45,8 @@  struct feature {
 	void *parent;		/* to parent hw data structure */
 
 	struct feature_ops *ops;/* callback to this private feature */
+	unsigned int vec_start;
+	unsigned int vec_cnt;
 };
 
 struct feature_ops {
@@ -52,7 +65,7 @@  enum ifpga_fme_state {
 struct ifpga_fme_hw {
 	enum ifpga_fme_state state;
 
-	struct feature sub_feature[FME_FEATURE_ID_MAX];
+	struct ifpga_feature_list feature_list;
 	spinlock_t lock;	/* protect hardware access */
 
 	void *parent;		/* pointer to ifpga_hw */
@@ -67,6 +80,10 @@  struct ifpga_fme_hw {
 	u32 cache_size;
 
 	u32 capability;
+
+	void *i2c_master; /* I2C Master device */
+	void *max10_dev; /* MAX10 device */
+	void *phy_dev[MAX_PHY_GROUP_DEVICES];
 };
 
 enum ifpga_port_state {
@@ -78,7 +95,7 @@  enum ifpga_port_state {
 struct ifpga_port_hw {
 	enum ifpga_port_state state;
 
-	struct feature sub_feature[PORT_FEATURE_ID_MAX];
+	struct ifpga_feature_list feature_list;
 	spinlock_t lock;	/* protect access to hw */
 
 	void *parent;		/* pointer to ifpga_hw */
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_port.c b/drivers/raw/ifpga_rawdev/base/ifpga_port.c
index 8b5668d..4628783 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_port.c
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_port.c
@@ -386,3 +386,24 @@  struct feature_ops ifpga_rawdev_port_uint_ops = {
 	.init = port_uint_init,
 	.uinit = port_uint_uinit,
 };
+
+static int port_afu_init(struct feature *feature)
+{
+	UNUSED(feature);
+
+	dev_info(NULL, "PORT AFU Init.\n");
+
+	return 0;
+}
+
+static void port_afu_uinit(struct feature *feature)
+{
+	UNUSED(feature);
+
+	dev_info(NULL, "PORT AFU UInit.\n");
+}
+
+struct feature_ops ifpga_rawdev_port_afu_ops = {
+	.init = port_afu_init,
+	.uinit = port_afu_uinit,
+};
diff --git a/drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.c b/drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.c
new file mode 100644
index 0000000..cc4901a
--- /dev/null
+++ b/drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.c
@@ -0,0 +1,89 @@ 
+
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+#include "opae_osdep.h"
+#include "opae_i2c.h"
+#include "opae_at24_eeprom.h"
+
+#define AT24_READ_RETRY 10
+
+static int at24_eeprom_read_and_try(struct altera_i2c_dev *dev,
+		unsigned int slave_addr,
+		u32 offset, u8 *buf, u32 len)
+{
+	int i;
+	int ret = 0;
+
+	for (i = 0; i < AT24_READ_RETRY; i++) {
+		ret = i2c_read16(dev, slave_addr, offset,
+				buf, len);
+		if (ret == 0)
+			break;
+
+		opae_udelay(100);
+	}
+
+	return ret;
+}
+
+int at24_eeprom_read(struct altera_i2c_dev *dev, unsigned int slave_addr,
+		u32 offset, u8 *buf, int count)
+{
+	int len;
+	int status;
+	int read_count = 0;
+
+	if (!count)
+		return count;
+
+	if (count > AT24C512_IO_LIMIT)
+		len = AT24C512_IO_LIMIT;
+	else
+		len = count;
+
+	while (count) {
+		status = at24_eeprom_read_and_try(dev, slave_addr, offset,
+				buf, len);
+		if (status)
+			break;
+
+		buf += len;
+		offset += len;
+		count -= len;
+		read_count += len;
+	}
+
+	return read_count;
+}
+
+int at24_eeprom_write(struct altera_i2c_dev *dev, unsigned int slave_addr,
+		u32 offset, u8 *buf, int count)
+{
+	int len;
+	int status;
+	int write_count = 0;
+
+	if (!count)
+		return count;
+
+	if (count > AT24C512_PAGE_SIZE)
+		len = AT24C512_PAGE_SIZE;
+	else
+		len = count;
+
+	while (count) {
+		status = i2c_write16(dev, slave_addr, offset, buf, len);
+		if (status)
+			break;
+
+		buf += len;
+		offset += len;
+		count -= len;
+		write_count += len;
+	}
+
+	return write_count;
+}
+
diff --git a/drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.h b/drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.h
new file mode 100644
index 0000000..4aa0ee2
--- /dev/null
+++ b/drivers/raw/ifpga_rawdev/base/opae_at24_eeprom.h
@@ -0,0 +1,14 @@ 
+
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+#define AT24C512_PAGE_SIZE 128
+#define AT24C512_IO_LIMIT  128
+
+#define AT24512_SLAVE_ADDR 0x51
+
+int at24_eeprom_read(struct altera_i2c_dev *dev, unsigned int slave_addr,
+		u32 offset, u8 *buf, int count);
+int at24_eeprom_write(struct altera_i2c_dev *dev, unsigned int slave_addr,
+		u32 offset, u8 *buf, int count);
diff --git a/drivers/raw/ifpga_rawdev/base/opae_hw_api.c b/drivers/raw/ifpga_rawdev/base/opae_hw_api.c
index 1541b67..c04bff2 100644
--- a/drivers/raw/ifpga_rawdev/base/opae_hw_api.c
+++ b/drivers/raw/ifpga_rawdev/base/opae_hw_api.c
@@ -210,12 +210,14 @@  int opae_acc_get_uuid(struct opae_accelerator *acc,
  * opae_manager_alloc - alloc opae_manager data structure
  * @name: manager name.
  * @ops: ops of this manager.
+ * @network_ops: ops of network management.
  * @data: private data of this manager.
  *
  * Return: opae_manager on success, otherwise NULL.
  */
 struct opae_manager *
-opae_manager_alloc(const char *name, struct opae_manager_ops *ops, void *data)
+opae_manager_alloc(const char *name, struct opae_manager_ops *ops,
+		struct opae_manager_networking_ops *network_ops, void *data)
 {
 	struct opae_manager *mgr = opae_zmalloc(sizeof(*mgr));
 
@@ -224,6 +226,7 @@  struct opae_manager *
 
 	mgr->name = name;
 	mgr->ops = ops;
+	mgr->network_ops = network_ops;
 	mgr->data = data;
 
 	opae_log("%s %p\n", __func__, mgr);
@@ -304,7 +307,7 @@  static struct opae_adapter_ops *match_ops(struct opae_adapter *adapter)
 
 /**
  * opae_adapter_init - init opae_adapter data structure
- * @adapter: pointer of opae_adapter data structure
+ * @adpdate: pointer of opae_adater data structure
  * @name: adapter name.
  * @data: private data of this adapter.
  *
@@ -325,6 +328,26 @@  int opae_adapter_init(struct opae_adapter *adapter,
 }
 
 /**
+ * opae_adapter_alloc - alloc opae_adapter data structure
+ * @name: adapter name.
+ * @data: private data of this adapter.
+ *
+ * Return: opae_adapter on success, otherwise NULL.
+ */
+struct opae_adapter *opae_adapter_alloc(const char *name, void *data)
+{
+	struct opae_adapter *adapter = opae_zmalloc(sizeof(*adapter));
+
+	if (!adapter)
+		return NULL;
+
+	if (opae_adapter_init(adapter, name, data))
+		return NULL;
+
+	return adapter;
+}
+
+/**
  * opae_adapter_enumerate - enumerate this adapter
  * @adapter: adapter to enumerate.
  *
@@ -341,7 +364,7 @@  int opae_adapter_enumerate(struct opae_adapter *adapter)
 		ret = adapter->ops->enumerate(adapter);
 
 	if (!ret)
-		opae_adapter_dump(adapter, 1);
+		opae_adapter_dump(adapter, 0);
 
 	return ret;
 }
@@ -379,3 +402,163 @@  struct opae_accelerator *
 
 	return NULL;
 }
+
+/**
+ * opae_manager_read_mac_rom - read the content of the MAC ROM
+ * @mgr: opae_manager for MAC ROM
+ * @port: the port number of retimer
+ * @addr: buffer of the MAC address
+ *
+ * Return: return the bytes of read successfully
+ */
+int opae_manager_read_mac_rom(struct opae_manager *mgr, int port,
+		struct opae_ether_addr *addr)
+{
+	if (!mgr || !mgr->network_ops)
+		return -EINVAL;
+
+	if (mgr->network_ops->read_mac_rom)
+		return mgr->network_ops->read_mac_rom(mgr,
+				port * sizeof(struct opae_ether_addr),
+				addr, sizeof(struct opae_ether_addr));
+
+	return -ENOENT;
+}
+
+/**
+ * opae_manager_write_mac_rom - write data into MAC ROM
+ * @mgr: opae_manager for MAC ROM
+ * @port: the port number of the retimer
+ * @addr: data of the MAC address
+ *
+ * Return: return written bytes
+ */
+int opae_manager_write_mac_rom(struct opae_manager *mgr, int port,
+		struct opae_ether_addr *addr)
+{
+	if (!mgr || !mgr->network_ops)
+		return -EINVAL;
+
+	if (mgr->network_ops && mgr->network_ops->write_mac_rom)
+		return mgr->network_ops->write_mac_rom(mgr,
+				port * sizeof(struct opae_ether_addr),
+				addr, sizeof(struct opae_ether_addr));
+
+	return -ENOENT;
+}
+
+/**
+ * opae_manager_read_phy_reg - read phy register
+ * @mgr: opae_manager for PHY
+ * @phy_group: PHY group index
+ * @entry: PHY entries
+ * @reg: register address in PHY group
+ * @val: register value
+ *
+ * Return: 0 on success, otherwise error code
+ */
+int opae_manager_read_phy_reg(struct opae_manager *mgr, int phy_group,
+		u8 entry, u32 reg, u32 *val)
+{
+	if (!mgr || !mgr->network_ops)
+		return -EINVAL;
+
+	if (mgr->network_ops->read_phy_reg)
+		return mgr->network_ops->read_phy_reg(mgr, phy_group,
+				entry, reg, val);
+
+	return -ENOENT;
+}
+
+/**
+ * opae_manager_write_phy_reg - write PHY group register
+ * @mgr: opae_manager for PHY Group
+ * @phy_group: PHY Group index
+ * @entry: PHY Group entries
+ * @reg: register address of PHY Group
+ * @val: data will write to register
+ *
+ * Return: 0 on success, otherwise error code
+ */
+int opae_manager_write_phy_reg(struct opae_manager *mgr, int phy_group,
+		u8 entry, u32 reg, u32 val)
+{
+	if (!mgr || !mgr->network_ops)
+		return -EINVAL;
+
+	if (mgr->network_ops->write_phy_reg)
+		return mgr->network_ops->write_phy_reg(mgr, phy_group,
+				entry, reg, val);
+
+	return -ENOENT;
+}
+
+/**
+ * opae_manager_get_retimer_info - get retimer info like PKVL chip
+ * @mgr: opae_manager for retimer
+ * @info: info return to caller
+ *
+ * Return: 0 on success, otherwise error code
+ */
+int opae_manager_get_retimer_info(struct opae_manager *mgr,
+	       struct opae_retimer_info *info)
+{
+	if (!mgr || !mgr->network_ops)
+		return -EINVAL;
+
+	//if (mgr->network_ops->get_retimer_info)
+	//	return mgr->network_ops->get_retimer_info(mgr, info);
+
+	//return -ENOENT;
+	info->num_retimer = 4;
+	info->num_port = 8;
+	info->support_speed = MXD_10GB;
+
+	return 0;
+}
+
+/**
+ * opae_manager_set_retimer_speed - configure the speed of retimer,
+ * like 10GB or 25GB
+ * @mgr: opae_manager of MDIO
+ * @speed: the speed of retimer
+ *
+ * Return: 0 on success, otherwise error code
+ */
+int opae_manager_set_retimer_speed(struct opae_manager *mgr, int speed)
+{
+	if (!mgr || !mgr->network_ops)
+		return -EINVAL;
+
+	//if (mgr->network_ops->set_retimer_speed)
+	//	return mgr->network_ops->set_retimer_speed(mgr, speed);
+	UNUSED(speed);
+
+	return 0;
+}
+
+/**
+ * opae_manager_get_retimer_status - get retimer status
+ * @mgr: opae_manager of retimer
+ * @status: status of retimer
+ *
+ * Return: 0 on success, otherwise error code
+ */
+int opae_manager_get_retimer_status(struct opae_manager *mgr,
+		int port, struct opae_retimer_status *status)
+{
+	if (!mgr || !mgr->network_ops)
+		return -EINVAL;
+
+	//if (mgr->network_ops->get_retimer_status)
+	//	return mgr->network_ops->get_retimer_status(mgr,
+	//			port, status);
+
+	//return -ENOENT;
+	UNUSED(port);
+	status->speed = MXD_10GB;
+	status->line_link = 1;
+	status->host_link = 1;
+
+	return 0;
+}
diff --git a/drivers/raw/ifpga_rawdev/base/opae_hw_api.h b/drivers/raw/ifpga_rawdev/base/opae_hw_api.h
index 332e0f3..0bfe5cc 100644
--- a/drivers/raw/ifpga_rawdev/base/opae_hw_api.h
+++ b/drivers/raw/ifpga_rawdev/base/opae_hw_api.h
@@ -11,6 +11,7 @@ 
 #include <sys/queue.h>
 
 #include "opae_osdep.h"
+#include "opae_mdio.h"
 
 #ifndef PCI_MAX_RESOURCE
 #define PCI_MAX_RESOURCE 6
@@ -25,6 +26,7 @@  enum opae_adapter_type {
 
 /* OPAE Manager Data Structure */
 struct opae_manager_ops;
+struct opae_manager_networking_ops;
 
 /*
  * opae_manager has pointer to its parent adapter, as it could be able to manage
@@ -35,6 +37,7 @@  struct opae_manager {
 	const char *name;
 	struct opae_adapter *adapter;
 	struct opae_manager_ops *ops;
+	struct opae_manager_networking_ops *network_ops;
 	void *data;
 };
 
@@ -44,9 +47,27 @@  struct opae_manager_ops {
 		     u32 size, u64 *status);
 };
 
+/* networking management ops in FME */
+struct opae_manager_networking_ops {
+	int (*read_mac_rom)(struct opae_manager *mgr, int offset, void *buf,
+			int size);
+	int (*write_mac_rom)(struct opae_manager *mgr, int offset, void *buf,
+			int size);
+	int (*read_phy_reg)(struct opae_manager *mgr, int phy_group,
+			u8 entry, u16 reg, u32 *value);
+	int (*write_phy_reg)(struct opae_manager *mgr, int phy_group,
+			u8 entry, u16 reg, u32 value);
+	int (*get_retimer_info)(struct opae_manager *mgr,
+			struct opae_retimer_info *info);
+	int (*set_retimer_speed)(struct opae_manager *mgr, int speed);
+	int (*get_retimer_status)(struct opae_manager *mgr, int port,
+			struct opae_retimer_status *status);
+};
+
 /* OPAE Manager APIs */
 struct opae_manager *
-opae_manager_alloc(const char *name, struct opae_manager_ops *ops, void *data);
+opae_manager_alloc(const char *name, struct opae_manager_ops *ops,
+		struct opae_manager_networking_ops *network_ops, void *data);
 #define opae_manager_free(mgr) opae_free(mgr)
 int opae_manager_flash(struct opae_manager *mgr, int acc_id, void *buf,
 		       u32 size, u64 *status);
@@ -227,6 +248,7 @@  struct opae_adapter {
 
 int opae_adapter_init(struct opae_adapter *adapter,
 		const char *name, void *data);
+struct opae_adapter *opae_adapter_alloc(const char *name, void *data);
 #define opae_adapter_free(adapter) opae_free(adapter)
 
 int opae_adapter_enumerate(struct opae_adapter *adapter);
@@ -251,4 +273,26 @@  static inline void opae_adapter_remove_acc(struct opae_adapter *adapter,
 {
 	TAILQ_REMOVE(&adapter->acc_list, acc, node);
 }
+
+/* OPAE vBNG network datastruct */
+#define OPAE_ETHER_ADDR_LEN 6
+
+struct opae_ether_addr {
+	unsigned char addr_bytes[OPAE_ETHER_ADDR_LEN];
+} __attribute__((__packed__));
+
+/* OPAE vBNG network API*/
+int opae_manager_read_mac_rom(struct opae_manager *mgr, int port,
+		struct opae_ether_addr *addr);
+int opae_manager_write_mac_rom(struct opae_manager *mgr, int port,
+		struct opae_ether_addr *addr);
+int opae_manager_read_phy_reg(struct opae_manager *mgr, int phy_group,
+		u8 entry, u32 reg, u32 *value);
+int opae_manager_write_phy_reg(struct opae_manager *mgr, int phy_group,
+		u8 entry, u32 reg, u32 value);
+int opae_manager_get_retimer_info(struct opae_manager *mgr,
+		struct opae_retimer_info *info);
+int opae_manager_set_retimer_speed(struct opae_manager *mgr, int speed);
+int opae_manager_get_retimer_status(struct opae_manager *mgr, int port,
+		struct opae_retimer_status *status);
 #endif /* _OPAE_HW_API_H_*/
diff --git a/drivers/raw/ifpga_rawdev/base/opae_i2c.c b/drivers/raw/ifpga_rawdev/base/opae_i2c.c
new file mode 100644
index 0000000..415afab
--- /dev/null
+++ b/drivers/raw/ifpga_rawdev/base/opae_i2c.c
@@ -0,0 +1,490 @@ 
+
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+#include "opae_osdep.h"
+#include "opae_i2c.h"
+
+static int i2c_transfer(struct altera_i2c_dev *dev,
+		struct i2c_msg *msg, int num)
+{
+	int ret, try;
+
+	for (ret = 0, try = 0; try < I2C_XFER_RETRY; try++) {
+		ret = dev->xfer(dev, msg, num);
+		if (ret != -EAGAIN)
+			break;
+	}
+
+	return ret;
+}
+
+/**
+ * i2c read function
+ */
+int i2c_read(struct altera_i2c_dev *dev, int flags, unsigned int slave_addr,
+		u32 offset, u8 *buf, u32 count)
+{
+	u8 msgbuf[2];
+	int i = 0;
+
+	if (flags & I2C_FLAG_ADDR16)
+		msgbuf[i++] = offset >> 8;
+
+	msgbuf[i++] = offset;
+
+	struct i2c_msg msg[2] = {
+		{
+			.addr = slave_addr,
+			.flags = 0,
+			.len = i,
+			.buf = msgbuf,
+		},
+		{
+			.addr = slave_addr,
+			.flags = I2C_M_RD,
+			.len = count,
+			.buf = buf,
+		},
+	};
+
+	if (!dev->xfer)
+		return -ENODEV;
+
+	return i2c_transfer(dev, msg, 2);
+}
+
+int i2c_write(struct altera_i2c_dev *dev, int flags, unsigned int slave_addr,
+		u32 offset, u8 *buffer, int len)
+{
+	struct i2c_msg msg;
+	u8 *buf;
+	int ret;
+	int i = 0;
+
+	if (!dev->xfer)
+		return -ENODEV;
+
+	buf = opae_malloc(I2C_MAX_OFFSET_LEN + len);
+	if (!buf)
+		return -ENOMEM;
+
+	msg.addr = slave_addr;
+	msg.flags = 0;
+	msg.buf = buf;
+
+	if (flags & I2C_FLAG_ADDR16)
+		msg.buf[i++] = offset >> 8;
+
+	msg.buf[i++] = offset;
+	opae_memcpy(&msg.buf[i], buffer, len);
+	msg.len = i + len;
+
+	ret = i2c_transfer(dev, &msg, 1);
+
+	opae_free(buf);
+	return ret;
+}
+
+int i2c_read8(struct altera_i2c_dev *dev, unsigned int slave_addr, u32 offset,
+		u8 *buf, u32 count)
+{
+	return i2c_read(dev, 0, slave_addr, offset, buf, count);
+}
+
+int i2c_read16(struct altera_i2c_dev *dev, unsigned int slave_addr, u32 offset,
+		u8 *buf, u32 count)
+{
+	return i2c_read(dev, I2C_FLAG_ADDR16, slave_addr, offset,
+			buf, count);
+}
+
+int i2c_write8(struct altera_i2c_dev *dev, unsigned int slave_addr, u32 offset,
+		u8 *buf, u32 count)
+{
+	return i2c_write(dev, 0, slave_addr, offset, buf, count);
+}
+
+int i2c_write16(struct altera_i2c_dev *dev, unsigned int slave_addr, u32 offset,
+		u8 *buf, u32 count)
+{
+	return i2c_write(dev, I2C_FLAG_ADDR16, slave_addr, offset,
+			buf, count);
+}
+
+static void i2c_indirect_write(struct altera_i2c_dev *dev, u32 reg,
+		u32 value)
+{
+	u64 ctrl;
+
+	ctrl = I2C_CTRL_W | (reg >> 2);
+
+	opae_writeq(value & I2C_WRITE_DATA_MASK, dev->base + I2C_WRITE);
+	opae_writeq(ctrl, dev->base + I2C_CTRL);
+}
+
+static u32 i2c_indirect_read(struct altera_i2c_dev *dev, u32 reg)
+{
+	u64 tmp;
+	u64 ctrl;
+	u32 value;
+
+	ctrl = I2C_CTRL_R | (reg >> 2);
+	opae_writeq(ctrl, dev->base + I2C_CTRL);
+
+	/* FIXME: Read one more time to avoid HW timing issue. */
+	tmp = opae_readq(dev->base + I2C_READ);
+	tmp = opae_readq(dev->base + I2C_READ);
+
+	value = tmp & I2C_READ_DATA_MASK;
+
+	return value;
+}
+
+static void altera_i2c_transfer(struct altera_i2c_dev *dev, u32 data)
+{
+	/*send STOP on last byte*/
+	if (dev->msg_len == 1)
+		data |= ALTERA_I2C_TFR_CMD_STO;
+	if (dev->msg_len > 0)
+		i2c_indirect_write(dev, ALTERA_I2C_TFR_CMD, data);
+}
+
+static void altera_i2c_disable(struct altera_i2c_dev *dev)
+{
+	u32 val = i2c_indirect_read(dev, ALTERA_I2C_CTRL);
+
+	i2c_indirect_write(dev, ALTERA_I2C_CTRL, val&~ALTERA_I2C_CTRL_EN);
+}
+
+static void altera_i2c_enable(struct altera_i2c_dev *dev)
+{
+	u32 val = i2c_indirect_read(dev, ALTERA_I2C_CTRL);
+
+	i2c_indirect_write(dev, ALTERA_I2C_CTRL, val | ALTERA_I2C_CTRL_EN);
+}
+
+static void altera_i2c_reset(struct altera_i2c_dev *dev)
+{
+	altera_i2c_disable(dev);
+	altera_i2c_enable(dev);
+}
+
+static int altera_i2c_wait_core_idle(struct altera_i2c_dev *dev)
+{
+	int retry = 0;
+
+	while (i2c_indirect_read(dev, ALTERA_I2C_STATUS)
+			& ALTERA_I2C_STAT_CORE) {
+		if (retry++ > ALTERA_I2C_TIMEOUT_US) {
+			dev_err(dev, "timeout: Core Status not IDLE...\n");
+			return -EBUSY;
+		}
+		udelay(1);
+	}
+
+	return 0;
+}
+
+static void altera_i2c_enable_interrupt(struct altera_i2c_dev *dev,
+		u32 mask, bool enable)
+{
+	u32 status;
+
+	status = i2c_indirect_read(dev, ALTERA_I2C_ISER);
+	if (enable)
+		dev->isr_mask = status | mask;
+	else
+		dev->isr_mask = status&~mask;
+
+	i2c_indirect_write(dev, ALTERA_I2C_ISER, dev->isr_mask);
+}
+
+static void altera_i2c_interrupt_clear(struct altera_i2c_dev *dev, u32 mask)
+{
+	u32 int_en;
+
+	int_en = i2c_indirect_read(dev, ALTERA_I2C_ISR);
+
+	i2c_indirect_write(dev, ALTERA_I2C_ISR, int_en | mask);
+}
+
+static void altera_i2c_read_rx_fifo(struct altera_i2c_dev *dev)
+{
+	size_t rx_avail;
+	size_t bytes;
+
+	rx_avail = i2c_indirect_read(dev, ALTERA_I2C_RX_FIFO_LVL);
+	bytes = min(rx_avail, dev->msg_len);
+
+	while (bytes-- > 0) {
+		*dev->buf++ = i2c_indirect_read(dev, ALTERA_I2C_RX_DATA);
+		dev->msg_len--;
+		altera_i2c_transfer(dev, 0);
+	}
+}
+
+static void altera_i2c_stop(struct altera_i2c_dev *dev)
+{
+	i2c_indirect_write(dev, ALTERA_I2C_TFR_CMD, ALTERA_I2C_TFR_CMD_STO);
+}
+
+static int altera_i2c_fill_tx_fifo(struct altera_i2c_dev *dev)
+{
+	size_t tx_avail;
+	int bytes;
+	int ret;
+
+	tx_avail = dev->fifo_size -
+		i2c_indirect_read(dev, ALTERA_I2C_TC_FIFO_LVL);
+	bytes = min(tx_avail, dev->msg_len);
+	ret = dev->msg_len - bytes;
+
+	while (bytes-- > 0) {
+		altera_i2c_transfer(dev, *dev->buf++);
+		dev->msg_len--;
+	}
+
+	return ret;
+}
+
+static u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg)
+{
+	return (msg->addr << 1) | (msg->flags & I2C_M_RD ? 1 : 0);
+}
+
+static int altera_i2c_wait_complete(struct altera_i2c_dev *dev,
+		u32 *status)
+{
+	int retry = 0;
+
+	while (!((*status = i2c_indirect_read(dev, ALTERA_I2C_ISR))
+				& dev->isr_mask)) {
+		if (retry++ > ALTERA_I2C_TIMEOUT_US)
+			return -EBUSY;
+
+		udelay(1000);
+	}
+
+	return 0;
+}
+
+static bool altera_handle_i2c_status(struct altera_i2c_dev *dev, u32 status)
+{
+	bool read, finish = false;
+	int ret;
+
+	read = (dev->msg->flags & I2C_M_RD) != 0;
+
+	if (status & ALTERA_I2C_ISR_ARB) {
+		altera_i2c_interrupt_clear(dev, ALTERA_I2C_ISR_ARB);
+		dev->msg_err = -EAGAIN;
+		finish = true;
+	} else if (status & ALTERA_I2C_ISR_NACK) {
+		dev_debug(dev, "could not get ACK\n");
+		dev->msg_err = -ENXIO;
+		altera_i2c_interrupt_clear(dev, ALTERA_I2C_ISR_NACK);
+		altera_i2c_stop(dev);
+		finish = true;
+	} else if (read && (status & ALTERA_I2C_ISR_RXOF)) {
+		/* RX FIFO Overflow */
+		altera_i2c_read_rx_fifo(dev);
+		altera_i2c_interrupt_clear(dev, ALTERA_I2C_ISER_RXOF_EN);
+		altera_i2c_stop(dev);
+		dev_err(dev, "error: RX FIFO overflow\n");
+		finish = true;
+	} else if (read && (status & ALTERA_I2C_ISR_RXRDY)) {
+		altera_i2c_read_rx_fifo(dev);
+		altera_i2c_interrupt_clear(dev, ALTERA_I2C_ISR_RXRDY);
+		if (!dev->msg_len)
+			finish = true;
+	} else if (!read && (status & ALTERA_I2C_ISR_TXRDY)) {
+		altera_i2c_interrupt_clear(dev, ALTERA_I2C_ISR_TXRDY);
+		if (dev->msg_len > 0)
+			altera_i2c_fill_tx_fifo(dev);
+		else
+			finish = true;
+	} else {
+		dev_err(dev, "unexpected status:0x%x\n", status);
+		altera_i2c_interrupt_clear(dev, ALTERA_I2C_ALL_IRQ);
+	}
+
+	if (finish) {
+		ret = altera_i2c_wait_core_idle(dev);
+		if (ret)
+			dev_err(dev, "message timeout\n");
+
+		altera_i2c_enable_interrupt(dev, ALTERA_I2C_ALL_IRQ, false);
+		altera_i2c_interrupt_clear(dev, ALTERA_I2C_ALL_IRQ);
+		dev_debug(dev, "message done\n");
+	}
+
+	return finish;
+}
+
+static bool altera_i2c_poll_status(struct altera_i2c_dev *dev)
+{
+	u32 status;
+	bool finish = false;
+	int i = 0;
+
+	do {
+		if (altera_i2c_wait_complete(dev, &status)) {
+			dev_err(dev, "altera i2c wait complete timeout, status=0x%x\n",
+					status);
+			return -EBUSY;
+		}
+
+		finish = altera_handle_i2c_status(dev, status);
+
+		if (i++ > I2C_XFER_RETRY)
+			break;
+
+	} while (!finish);
+
+	return finish;
+}
+
+static int altera_i2c_xfer_msg(struct altera_i2c_dev *dev,
+		struct i2c_msg *msg)
+{
+	u32 int_mask = ALTERA_I2C_ISR_RXOF |
+		ALTERA_I2C_ISR_ARB | ALTERA_I2C_ISR_NACK;
+	u8 addr = i2c_8bit_addr_from_msg(msg);
+	bool finish;
+
+	dev->msg = msg;
+	dev->msg_len = msg->len;
+	dev->buf = msg->buf;
+	dev->msg_err = 0;
+	altera_i2c_enable(dev);
+
+	/*make sure RX FIFO is emtry*/
+	do {
+		i2c_indirect_read(dev, ALTERA_I2C_RX_DATA);
+	} while (i2c_indirect_read(dev, ALTERA_I2C_RX_FIFO_LVL));
+
+	i2c_indirect_write(dev, ALTERA_I2C_TFR_CMD_RW_D,
+			ALTERA_I2C_TFR_CMD_STA | addr);
+
+	/*enable irq*/
+	if (msg->flags & I2C_M_RD) {
+		int_mask |= ALTERA_I2C_ISR_RXOF | ALTERA_I2C_ISR_RXRDY;
+		/* in polling mode, we should set this ISR register? */
+		altera_i2c_enable_interrupt(dev, int_mask, true);
+		altera_i2c_transfer(dev, 0);
+	} else {
+		int_mask |= ALTERA_I2C_ISR_TXRDY;
+		altera_i2c_enable_interrupt(dev, int_mask, true);
+		altera_i2c_fill_tx_fifo(dev);
+	}
+
+	finish = altera_i2c_poll_status(dev);
+	if (!finish) {
+		dev->msg_err = -ETIMEDOUT;
+		dev_err(dev, "%s: i2c transfer error\n", __func__);
+	}
+
+	altera_i2c_enable_interrupt(dev, int_mask, false);
+
+	if (i2c_indirect_read(dev, ALTERA_I2C_STATUS) & ALTERA_I2C_STAT_CORE)
+		dev_info(dev, "core not idle...\n");
+
+	altera_i2c_disable(dev);
+
+	return dev->msg_err;
+}
+
+static int altera_i2c_xfer(struct altera_i2c_dev *dev,
+		struct i2c_msg *msg, int num)
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < num; i++, msg++) {
+		ret = altera_i2c_xfer_msg(dev, msg);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+static void altera_i2c_hardware_init(struct altera_i2c_dev *dev)
+{
+	u32 divisor = dev->i2c_clk / dev->bus_clk_rate;
+	u32 clk_mhz = dev->i2c_clk / 1000000;
+	u32 tmp = (ALTERA_I2C_THRESHOLD << ALTERA_I2C_CTRL_RXT_SHFT) |
+		  (ALTERA_I2C_THRESHOLD << ALTERA_I2C_CTRL_TCT_SHFT);
+	u32 t_high, t_low;
+
+	if (dev->bus_clk_rate <= 100000) {
+		tmp &= ~ALTERA_I2C_CTRL_BSPEED;
+		/*standard mode SCL 50/50*/
+		t_high = divisor*1/2;
+		t_low = divisor*1/2;
+	} else {
+		tmp |= ALTERA_I2C_CTRL_BSPEED;
+		/*Fast mode SCL 33/66*/
+		t_high = divisor*1/3;
+		t_low = divisor*2/3;
+	}
+
+	i2c_indirect_write(dev, ALTERA_I2C_CTRL, tmp);
+
+	dev_info(dev, "%s: rate=%uHz per_clk=%uMHz -> ratio=1:%u\n",
+		__func__, dev->bus_clk_rate, clk_mhz, divisor);
+
+	/*reset the i2c*/
+	altera_i2c_reset(dev);
+
+	/*Set SCL high Time*/
+	i2c_indirect_write(dev, ALTERA_I2C_SCL_HIGH, t_high);
+	/*Set SCL low time*/
+	i2c_indirect_write(dev, ALTERA_I2C_SCL_LOW, t_low);
+	/*Set SDA Hold time, 300ms*/
+	i2c_indirect_write(dev, ALTERA_I2C_SDA_HOLD, (300*clk_mhz)/1000);
+
+	altera_i2c_enable_interrupt(dev, ALTERA_I2C_ALL_IRQ, false);
+}
+
+struct altera_i2c_dev *altera_i2c_probe(void *base)
+{
+	struct altera_i2c_dev *dev;
+
+	dev = opae_malloc(sizeof(*dev));
+	if (!dev)
+		return NULL;
+
+	dev->base = (u8 *)base;
+	dev->i2c_param.info = opae_readq(dev->base + I2C_PARAM);
+
+	if (dev->i2c_param.devid != 0xEE011) {
+		dev_err(dev, "find a invalid i2c master\n");
+		return NULL;
+	}
+
+	dev->fifo_size = dev->i2c_param.fifo_depth;
+
+	if (dev->i2c_param.max_req == ALTERA_I2C_100KHZ)
+		dev->bus_clk_rate = 100000;
+	else if (dev->i2c_param.max_req == ALTERA_I2C_400KHZ)
+		/* i2c bus clk 400KHz*/
+		dev->bus_clk_rate = 400000;
+
+	/* i2c input clock for vista creek is 100MHz */
+	dev->i2c_clk = dev->i2c_param.ref_clk * 1000000;
+	dev->xfer = altera_i2c_xfer;
+
+	altera_i2c_hardware_init(dev);
+
+	return dev;
+}
+
+int altera_i2c_remove(struct altera_i2c_dev *dev)
+{
+	altera_i2c_disable(dev);
+
+	return 0;
+}
diff --git a/drivers/raw/ifpga_rawdev/base/opae_i2c.h b/drivers/raw/ifpga_rawdev/base/opae_i2c.h
new file mode 100644
index 0000000..36f5927
--- /dev/null
+++ b/drivers/raw/ifpga_rawdev/base/opae_i2c.h
@@ -0,0 +1,127 @@ 
+
+#ifndef _OPAE_I2C_H
+#define _OPAE_I2C_H
+
+#include "opae_osdep.h"
+
+#define ALTERA_I2C_TFR_CMD	0x00	/* Transfer Command register */
+#define ALTERA_I2C_TFR_CMD_STA	BIT(9)	/* send START before byte */
+#define ALTERA_I2C_TFR_CMD_STO	BIT(8)	/* send STOP after byte */
+#define ALTERA_I2C_TFR_CMD_RW_D	BIT(0)	/* Direction of transfer */
+#define ALTERA_I2C_RX_DATA	0x04	/* RX data FIFO register */
+#define ALTERA_I2C_CTRL		0x8	/* Control register */
+#define ALTERA_I2C_CTRL_RXT_SHFT	4	/* RX FIFO Threshold */
+#define ALTERA_I2C_CTRL_TCT_SHFT	2	/* TFER CMD FIFO Threshold */
+#define ALTERA_I2C_CTRL_BSPEED	BIT(1)	/* Bus Speed */
+#define ALTERA_I2C_CTRL_EN	BIT(0)	/* Enable Core */
+#define ALTERA_I2C_ISER		0xc	/* Interrupt Status Enable register */
+#define ALTERA_I2C_ISER_RXOF_EN	BIT(4)	/* Enable RX OVERFLOW IRQ */
+#define ALTERA_I2C_ISER_ARB_EN	BIT(3)	/* Enable ARB LOST IRQ */
+#define ALTERA_I2C_ISER_NACK_EN	BIT(2)	/* Enable NACK DET IRQ */
+#define ALTERA_I2C_ISER_RXRDY_EN	BIT(1)	/* Enable RX Ready IRQ */
+#define ALTERA_I2C_ISER_TXRDY_EN	BIT(0)	/* Enable TX Ready IRQ */
+#define ALTERA_I2C_ISR		0x10	/* Interrupt Status register */
+#define ALTERA_I2C_ISR_RXOF		BIT(4)	/* RX OVERFLOW */
+#define ALTERA_I2C_ISR_ARB		BIT(3)	/* ARB LOST */
+#define ALTERA_I2C_ISR_NACK		BIT(2)	/* NACK DET */
+#define ALTERA_I2C_ISR_RXRDY		BIT(1)	/* RX Ready */
+#define ALTERA_I2C_ISR_TXRDY		BIT(0)	/* TX Ready */
+#define ALTERA_I2C_STATUS	0x14	/* Status register */
+#define ALTERA_I2C_STAT_CORE		BIT(0)	/* Core Status */
+#define ALTERA_I2C_TC_FIFO_LVL	0x18   /* Transfer FIFO LVL register */
+#define ALTERA_I2C_RX_FIFO_LVL	0x1c	/* Receive FIFO LVL register */
+#define ALTERA_I2C_SCL_LOW	0x20	/* SCL low count register */
+#define ALTERA_I2C_SCL_HIGH	0x24	/* SCL high count register */
+#define ALTERA_I2C_SDA_HOLD	0x28	/* SDA hold count register */
+
+#define ALTERA_I2C_ALL_IRQ	(ALTERA_I2C_ISR_RXOF | ALTERA_I2C_ISR_ARB | \
+				 ALTERA_I2C_ISR_NACK | ALTERA_I2C_ISR_RXRDY | \
+				 ALTERA_I2C_ISR_TXRDY)
+
+#define ALTERA_I2C_THRESHOLD	0
+#define ALTERA_I2C_DFLT_FIFO_SZ	8
+#define ALTERA_I2C_TIMEOUT_US  250000 /* 250ms */
+
+#define I2C_PARAM 0x8
+#define I2C_CTRL  0x10
+#define I2C_CTRL_R    BIT_ULL(9)
+#define I2C_CTRL_W    BIT_ULL(8)
+#define I2C_CTRL_ADDR_MASK GENMASK_ULL(3, 0)
+#define I2C_READ 0x18
+#define I2C_READ_DATA_VALID BIT_ULL(32)
+#define I2C_READ_DATA_MASK GENMASK_ULL(31, 0)
+#define I2C_WRITE 0x20
+#define I2C_WRITE_DATA_MASK GENMASK_ULL(31, 0)
+
+#define ALTERA_I2C_100KHZ  0
+#define ALTERA_I2C_400KHZ  1
+
+/* i2c slave using 16bit address */
+#define I2C_FLAG_ADDR16  1
+
+#define I2C_XFER_RETRY 10
+
+struct i2c_core_param {
+	union {
+		u64 info;
+		struct {
+			u16 fifo_depth:9;
+			u8 interface:1;
+			/*reference clock of I2C core in MHz*/
+			u32 ref_clk:10;
+			/*Max I2C interface freq*/
+			u8 max_req:4;
+			u64 devid:32;
+			/* number of MAC address*/
+			u8 nu_macs:8;
+		};
+	};
+};
+
+struct altera_i2c_dev {
+	u8 *base;
+	struct i2c_core_param i2c_param;
+	u32 fifo_size;
+	u32 bus_clk_rate; /* i2c bus clock */
+	u32 i2c_clk; /* i2c input clock */
+	struct i2c_msg *msg;
+	size_t msg_len;
+	int msg_err;
+	u32 isr_mask;
+	u8 *buf;
+	int (*xfer)(struct altera_i2c_dev *dev, struct i2c_msg *msg, int num);
+};
+
+/**
+ * struct i2c_msg: an I2C message
+ */
+struct i2c_msg {
+	unsigned int addr;
+	unsigned int flags;
+	unsigned int len;
+	u8 *buf;
+};
+
+#define I2C_MAX_OFFSET_LEN 4
+
+enum i2c_msg_flags {
+	I2C_M_TEN = 0x0010, /*ten-bit chip address*/
+	I2C_M_RD  = 0x0001, /*read data*/
+	I2C_M_STOP = 0x8000, /*send stop after this message*/
+};
+
+struct altera_i2c_dev *altera_i2c_probe(void *base);
+int altera_i2c_remove(struct altera_i2c_dev *dev);
+int i2c_read(struct altera_i2c_dev *dev, int flags, unsigned int slave_addr,
+		u32 offset, u8 *buf, u32 count);
+int i2c_write(struct altera_i2c_dev *dev, int flags, unsigned int slave_addr,
+		u32 offset, u8 *buffer, int len);
+int i2c_read8(struct altera_i2c_dev *dev, unsigned int slave_addr, u32 offset,
+		u8 *buf, u32 count);
+int i2c_read16(struct altera_i2c_dev *dev, unsigned int slave_addr, u32 offset,
+		u8 *buf, u32 count);
+int i2c_write8(struct altera_i2c_dev *dev, unsigned int slave_addr, u32 offset,
+		u8 *buf, u32 count);
+int i2c_write16(struct altera_i2c_dev *dev, unsigned int slave_addr, u32 offset,
+		u8 *buf, u32 count);
+#endif
diff --git a/drivers/raw/ifpga_rawdev/base/opae_intel_max10.c b/drivers/raw/ifpga_rawdev/base/opae_intel_max10.c
new file mode 100644
index 0000000..37292f4
--- /dev/null
+++ b/drivers/raw/ifpga_rawdev/base/opae_intel_max10.c
@@ -0,0 +1,106 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+#include "opae_intel_max10.h"
+
+static struct intel_max10_device *g_max10;
+
+int max10_reg_read(unsigned int reg, unsigned int *val)
+{
+	if (!g_max10)
+		return -ENODEV;
+
+	return spi_transaction_read(g_max10->spi_tran_dev,
+			reg, 4, (unsigned char *)val);
+}
+
+int max10_reg_write(unsigned int reg, unsigned int val)
+{
+	if (!g_max10)
+		return -ENODEV;
+
+	return spi_transaction_write(g_max10->spi_tran_dev,
+			reg, 4, (unsigned char *)&val);
+}
+
+struct resource mdio_resource[INTEL_MAX10_MAX_MDIO_DEVS] = {
+	{
+		.start = 0x200100,
+		.end = 0x2001ff,
+	},
+	{
+		.start = 0x200200,
+		.end = 0x2002ff,
+	},
+};
+
+struct intel_max10_device *
+intel_max10_device_probe(struct altera_spi_device *spi,
+		int chipselect)
+{
+	struct intel_max10_device *dev;
+	int i;
+
+	dev = opae_malloc(sizeof(*dev));
+	if (!dev)
+		return NULL;
+
+	dev->spi_master = spi;
+
+	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;
+	}
+
+	g_max10 = dev;
+
+	for (i = 0; i < INTEL_MAX10_MAX_MDIO_DEVS; i++) {
+		dev->mdio[i] = altera_mdio_probe(i, mdio_resource[i].start,
+				mdio_resource[i].end, dev->spi_tran_dev);
+		if (!dev->mdio[i]) {
+			dev_err(dev, "%s mido init fail\n", __func__);
+			goto mdio_fail;
+		}
+	}
+
+	/* FIXME: should read this info from MAX10 device table */
+	dev->num_retimer = INTEL_MAX10_MAX_MDIO_DEVS;
+	dev->num_port = PKVL_NUMBER_PORTS;
+
+	return dev;
+
+mdio_fail:
+	for (i = 0; i < INTEL_MAX10_MAX_MDIO_DEVS; i++)
+		if (dev->mdio[i])
+			opae_free(dev->mdio[i]);
+
+	spi_transaction_remove(dev->spi_tran_dev);
+free_dev:
+	g_max10 = NULL;
+	opae_free(dev);
+
+	return NULL;
+}
+
+int intel_max10_device_remove(struct intel_max10_device *dev)
+{
+	int i;
+
+	if (!dev)
+		return 0;
+
+	if (dev->spi_tran_dev)
+		spi_transaction_remove(dev->spi_tran_dev);
+
+	for (i = 0; i < INTEL_MAX10_MAX_MDIO_DEVS; i++)
+		if (dev->mdio[i])
+			altera_mdio_release(dev->mdio[i]);
+
+	g_max10 = NULL;
+
+	opae_free(dev);
+
+	return 0;
+}
diff --git a/drivers/raw/ifpga_rawdev/base/opae_intel_max10.h b/drivers/raw/ifpga_rawdev/base/opae_intel_max10.h
new file mode 100644
index 0000000..b212825
--- /dev/null
+++ b/drivers/raw/ifpga_rawdev/base/opae_intel_max10.h
@@ -0,0 +1,36 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _OPAE_INTEL_MAX10_H_
+#define _OPAE_INTEL_MAX10_H_
+
+#include "opae_osdep.h"
+#include "opae_spi.h"
+#include "opae_mdio.h"
+
+#define INTEL_MAX10_MAX_MDIO_DEVS 2
+#define PKVL_NUMBER_PORTS  4
+
+struct intel_max10_device {
+	struct altera_spi_device *spi_master;
+	struct spi_transaction_dev *spi_tran_dev;
+	struct altera_mdio_dev *mdio[INTEL_MAX10_MAX_MDIO_DEVS];
+	int num_retimer; /* number of retimer */
+	int num_port;   /* number of ports in retimer */
+};
+
+struct resource {
+	u32 start;
+	u32 end;
+	u32 flags;
+};
+
+int max10_reg_read(unsigned int reg, unsigned int *val);
+int max10_reg_write(unsigned int reg, unsigned int val);
+struct intel_max10_device *
+intel_max10_device_probe(struct altera_spi_device *spi,
+		int chipselect);
+int intel_max10_device_remove(struct intel_max10_device *dev);
+
+#endif
diff --git a/drivers/raw/ifpga_rawdev/base/opae_mdio.c b/drivers/raw/ifpga_rawdev/base/opae_mdio.c
new file mode 100644
index 0000000..6eb093b
--- /dev/null
+++ b/drivers/raw/ifpga_rawdev/base/opae_mdio.c
@@ -0,0 +1,542 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include "opae_osdep.h"
+#include "opae_spi.h"
+#include "opae_mdio.h"
+#include "opae_intel_max10.h"
+
+#define PHY_MAX_ADDR 32
+#define MAX_NUM_IDS  8
+#define MDIO_PHYSID1 2
+#define MDIO_PHYSID2 3
+#define MDIO_DEVS2   6
+#define MDIO_DEVS1   5
+
+static int max10_mdio_reg_read(struct altera_mdio_dev *dev,
+		unsigned int reg, unsigned int *val)
+{
+	struct spi_transaction_dev *spi_tran_dev =
+		dev->sub_dev;
+
+	if (!spi_tran_dev)
+		return -ENODEV;
+
+	return spi_transaction_read(spi_tran_dev,
+			reg, 4, (unsigned char *)val);
+}
+
+int altera_mdio_read(struct altera_mdio_dev *dev, u32 dev_addr,
+		u32 port_addr, u32 reg, u32 *value)
+{
+	int ret;
+	struct altera_mdio_addr mdio_addr = {.csr = 0};
+
+	if (!dev)
+		return -ENODEV;
+
+	mdio_addr.devad = dev_addr;
+	mdio_addr.prtad = port_addr;
+	mdio_addr.regad = reg;
+
+	dev_debug(dev, "%s reg=0x%x, dev:%x, port:%x, reg:0x%x\n", __func__,
+			mdio_addr.csr, dev_addr, port_addr, reg);
+
+	ret = max10_reg_write(dev->start + ALTERA_MDIO_ADDRESS_OFST,
+			mdio_addr.csr);
+	if (ret)
+		return -EIO;
+
+	return max10_mdio_reg_read(dev, dev->start + ALTERA_MDIO_DATA_OFST,
+			value);
+}
+
+int altera_mdio_write(struct altera_mdio_dev *dev, u32 dev_addr,
+		u32 port_addr, u32 reg, u32 value)
+{
+	int ret;
+	struct altera_mdio_addr mdio_addr = {.csr = 0};
+
+	if (!dev)
+		return -ENODEV;
+
+	mdio_addr.devad = dev_addr;
+	mdio_addr.prtad = port_addr;
+	mdio_addr.regad = reg;
+
+	ret = max10_reg_write(dev->start + ALTERA_MDIO_ADDRESS_OFST,
+			mdio_addr.csr);
+	if (ret)
+		return -EIO;
+
+	return max10_reg_write(dev->start + ALTERA_MDIO_DATA_OFST,
+			value);
+}
+
+int pkvl_reg_read(struct altera_mdio_dev *dev, u32 dev_addr,
+		u32 reg, u32 *val)
+{
+	int port_id = dev->port_id;
+
+	if (port_id < 0)
+		return -ENODEV;
+
+	return altera_mdio_read(dev, dev_addr, port_id, reg, val);
+}
+
+int pkvl_reg_write(struct altera_mdio_dev *dev, u32 dev_addr,
+		u32 reg, u32 val)
+{
+	int port_id = dev->port_id;
+
+	if (port_id < 0)
+		return -ENODEV;
+
+	return altera_mdio_write(dev, dev_addr, port_id, reg, val);
+}
+
+static int pkvl_reg_set_mask(struct altera_mdio_dev *dev, u32 dev_addr,
+		u32 reg, u32 mask, u32 val)
+{
+	int ret;
+	u32 v;
+
+	ret = pkvl_reg_read(dev, dev_addr, reg, &v);
+	if (ret)
+		return -EIO;
+
+	v = (v&~mask) | (val & mask);
+
+	return pkvl_reg_write(dev, dev_addr, reg, v);
+}
+
+static int get_phy_package_id(struct altera_mdio_dev *dev,
+		int addr, int dev_addr, int *id)
+{
+	int ret;
+	u32 val = 0;
+
+	ret = altera_mdio_read(dev, dev_addr, addr, MDIO_DEVS2, &val);
+	if (ret)
+		return -EIO;
+
+	*id = (val & 0xffff) << 16;
+
+	ret = altera_mdio_read(dev, dev_addr, addr, MDIO_DEVS1, &val);
+	if (ret)
+		return -EIO;
+
+	*id |= (val & 0xffff);
+
+	return 0;
+}
+
+static int get_phy_device_id(struct altera_mdio_dev *dev,
+		int addr, int dev_addr, int *id)
+{
+	int ret;
+	u32 val = 0;
+
+	ret = altera_mdio_read(dev, dev_addr, addr, MDIO_PHYSID1, &val);
+	if (ret)
+		return -EIO;
+
+	*id = (val & 0xffff) << 16;
+
+	ret = altera_mdio_read(dev, dev_addr, addr, MDIO_PHYSID2, &val);
+	if (ret)
+		return -EIO;
+
+	*id |= (val & 0xffff);
+
+	return 0;
+}
+
+static int get_phy_c45_ids(struct altera_mdio_dev *dev,
+		int addr, int *phy_id, int *device_id)
+{
+	int i;
+	int ret;
+	int id;
+
+	for (i = 1; i < MAX_NUM_IDS; i++) {
+		ret = get_phy_package_id(dev, addr, i, phy_id);
+		if (ret)
+			return -EIO;
+
+		if ((*phy_id & 0x1fffffff) != 0x1fffffff)
+			break;
+	}
+
+	ret = get_phy_device_id(dev, addr, 1, &id);
+	if (ret)
+		return -EIO;
+
+	*device_id = id;
+
+	return 0;
+}
+
+static int mdio_phy_scan(struct altera_mdio_dev *dev, int *port_id,
+		int *phy_id, int *device_id)
+{
+	int i;
+	int ret;
+
+	for (i = 0; i < PHY_MAX_ADDR; i++) {
+		ret = get_phy_c45_ids(dev, i, phy_id, device_id);
+		if (ret)
+			return -EIO;
+
+		if ((*phy_id & 0x1fffffff) != 0x1fffffff) {
+			*port_id = i;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+#define PKVL_READ pkvl_reg_read
+#define PKVL_WRITE pkvl_reg_write
+#define PKVL_SET_MASK pkvl_reg_set_mask
+
+static int pkvl_check_smbus_cmd(struct altera_mdio_dev *dev)
+{
+	int retry = 0;
+	u32 val;
+
+	for (retry = 0; retry < 10; retry++) {
+		PKVL_READ(dev, 31, 0xf443, &val);
+		if ((val & 0x3) == 0)
+			break;
+		opae_udelay(1);
+	}
+
+	if (val & 0x3) {
+		dev_err(dev, "pkvl execute indirect smbus cmd fail\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int pkvl_execute_smbus_cmd(struct altera_mdio_dev *dev)
+{
+	int ret;
+
+	ret = pkvl_check_smbus_cmd(dev);
+	if (ret)
+		return ret;
+
+	PKVL_WRITE(dev, 31, 0xf443, 0x1);
+
+	ret = pkvl_check_smbus_cmd(dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int pkvl_indirect_smbus_set(struct altera_mdio_dev *dev,
+		u32 addr, u32 reg, u32 hv, u32 lv, u32 *v)
+{
+	int ret;
+
+	PKVL_WRITE(dev, 31, 0xf441, 0x21);
+	PKVL_WRITE(dev, 31, 0xf442,
+			((addr & 0xff) << 8) | (reg & 0xff));
+	PKVL_WRITE(dev, 31, 0xf445, hv);
+	PKVL_WRITE(dev, 31, 0xf444, lv);
+	PKVL_WRITE(dev, 31, 0xf440, 0);
+
+	ret = pkvl_execute_smbus_cmd(dev);
+	if (ret)
+		return ret;
+
+	PKVL_READ(dev, 31, 0xf446, v);
+	PKVL_WRITE(dev, 31, 0xf443, 0);
+
+	return 0;
+}
+
+static int pkvl_serdes_intr_set(struct altera_mdio_dev *dev,
+		u32 reg, u32 hv, u32 lv)
+{
+	u32 addr;
+	u32 v;
+	int ret;
+
+	addr = (reg & 0xff00) >> 8;
+
+	ret = pkvl_indirect_smbus_set(dev, addr, 0x3, hv, lv, &v);
+	if (ret)
+		return ret;
+
+	if ((v & 0x7) != 1) {
+		dev_err(dev, "%s(0x%x, 0x%x, 0x%x) fail\n",
+				__func__, reg, hv, lv);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+#define PKVL_SERDES_SET pkvl_serdes_intr_set
+
+static int pkvl_set_line_side_mode(struct altera_mdio_dev *dev,
+		int port, int mode)
+{
+	u32 val = 0;
+
+	/* check PKVL exist */
+	PKVL_READ(dev, 1, 0, &val);
+	if (val == 0 || val == 0xffff) {
+		dev_err(dev, "reading reg 0x0 from PKVL fail\n");
+		return -ENODEV;
+	}
+
+	PKVL_WRITE(dev, 31, 0xf003, 0);
+	PKVL_WRITE(dev, 3, 0x2000 + 0x200*port,
+			0x2040);
+	PKVL_SET_MASK(dev, 7, 0x200*port, 1<<12, 0);
+	PKVL_SET_MASK(dev, 7, 0x11+0x200*port,
+			0xf3a0, 0);
+	PKVL_SET_MASK(dev, 7, 0x8014+0x200*port,
+			0x330, 0);
+	PKVL_WRITE(dev, 7, 0x12+0x200*port, 0);
+	PKVL_WRITE(dev, 7, 0x8015+0x200*port, 0);
+	PKVL_SET_MASK(dev, 3, 0xf0ba, 0x8000 | (0x800<<port),
+			0x8000);
+	PKVL_SET_MASK(dev, 3, 0xf0a6, 0x8000 | (0x800<<port),
+			0x8000);
+	PKVL_WRITE(dev, 3, 0xf378, 0);
+	PKVL_WRITE(dev, 3, 0xf258 + 0x80 * port, 0);
+	PKVL_WRITE(dev, 3, 0xf259 + 0x80 * port, 0);
+	PKVL_WRITE(dev, 3, 0xf25a + 0x80 * port, 0);
+	PKVL_WRITE(dev, 3, 0xf25b + 0x80 * port, 0);
+	PKVL_SET_MASK(dev, 3, 0xf26f + 0x80 * port,
+			3<<14, 0);
+
+	PKVL_SET_MASK(dev, 3, 0xf060, 1<<2, 0);
+	PKVL_WRITE(dev, 3, 0xf053, 0);
+	PKVL_WRITE(dev, 3, 0xf056, 0);
+	PKVL_WRITE(dev, 3, 0xf059, 0);
+	PKVL_WRITE(dev, 7, 0x8200, 0);
+	PKVL_WRITE(dev, 7, 0x8400, 0);
+	PKVL_WRITE(dev, 7, 0x8600, 0);
+	PKVL_WRITE(dev, 3, 0xf0e7, 0);
+
+	if (mode == MXD_10GB) {
+		PKVL_SET_MASK(dev, 3, 0xf25c + 0x80 * port,
+				0x2, 0x2);
+		PKVL_WRITE(dev, 3, 0xf220 + 0x80 * port, 0x1918);
+		PKVL_WRITE(dev, 3, 0xf221 + 0x80 * port, 0x1819);
+		PKVL_WRITE(dev, 3, 0xf230 + 0x80 * port, 0x7);
+		PKVL_WRITE(dev, 3, 0xf231 + 0x80 * port, 0xaff);
+		PKVL_WRITE(dev, 3, 0xf232 + 0x80 * port, 0);
+		PKVL_WRITE(dev, 3, 0xf250 + 0x80 * port, 0x1111);
+		PKVL_WRITE(dev, 3, 0xf251 + 0x80 * port, 0x1111);
+		PKVL_SET_MASK(dev, 3, 0xf258 + 0x80 * port,
+				0x7, 0x7);
+	}
+
+	PKVL_SET_MASK(dev, 3, 0xf25c + 0x80 * port, 0x2, 0x2);
+	PKVL_WRITE(dev, 3, 0xf22b + 0x80 * port, 0x1918);
+	PKVL_WRITE(dev, 3, 0xf246 + 0x80 * port, 0x4033);
+	PKVL_WRITE(dev, 3, 0xf247 + 0x80 * port, 0x4820);
+	PKVL_WRITE(dev, 3, 0xf255 + 0x80 * port, 0x1100);
+	PKVL_SET_MASK(dev, 3, 0xf259 + 0x80 * port, 0xc0,
+			0xc0);
+
+	if (port == 0) {
+		if (mode == MXD_10GB) {
+			PKVL_SERDES_SET(dev, 0x503, 0x3d, 0x9004);
+			PKVL_SERDES_SET(dev, 0x503, 0x3d, 0x9800);
+			PKVL_SERDES_SET(dev, 0x503, 0x3d, 0xa002);
+			PKVL_SERDES_SET(dev, 0x503, 0x3d, 0xa800);
+			PKVL_SERDES_SET(dev, 0x503, 0x3d, 0xb012);
+			PKVL_SERDES_SET(dev, 0x503, 0x3d, 0xb800);
+		} else if (mode == MXD_25GB) {
+			PKVL_SERDES_SET(dev, 0x503, 0x3d, 0x9800);
+			PKVL_SERDES_SET(dev, 0x503, 0x3d, 0xa809);
+			PKVL_SERDES_SET(dev, 0x503, 0x3d, 0xb800);
+		}
+	}
+
+	/* last step */
+	PKVL_WRITE(dev, 3, 0xf000 + port, 0x8020 | mode);
+	PKVL_READ(dev, 3, 0xf000 + port, &val);
+	dev_info(dev, "PKVL:%d port:%d line side mode : 0x%x\n",
+			dev->index, port, val);
+	return 0;
+}
+
+static int pkvl_set_host_side_mode(struct altera_mdio_dev *dev,
+		int port, int mode)
+{
+	u32 val = 0;
+
+	PKVL_WRITE(dev, 4, 0x2000 + 0x200 * port, 0x2040);
+	PKVL_SET_MASK(dev, 7, 0x1000 + 0x200 * port,
+			1<<12, 0);
+	PKVL_SET_MASK(dev, 7, 0x1011 + 0x200 * port,
+			0xf3a0, 0);
+	PKVL_SET_MASK(dev, 7, 0x9014 + 0x200 * port,
+			0x330, 0);
+	PKVL_WRITE(dev, 7, 0x1012 + 0x200 * port, 0);
+	PKVL_WRITE(dev, 7, 0x9015 + 0x200 * port, 0);
+	PKVL_SET_MASK(dev, 4, 0xf0ba, 0x8000 | (0x800 << port),
+			0x8000);
+	PKVL_SET_MASK(dev, 4, 0xf0a6, 0x8000 | (0x800 << port),
+			0x8000);
+	PKVL_WRITE(dev, 4, 0xf378, 0);
+	PKVL_WRITE(dev, 4, 0xf258 + 0x80 * port, 0);
+	PKVL_WRITE(dev, 4, 0xf259 + 0x80 * port, 0);
+	PKVL_WRITE(dev, 4, 0xf25a + 0x80 * port, 0);
+	PKVL_WRITE(dev, 4, 0xf25b + 0x80 * port, 0);
+	PKVL_SET_MASK(dev, 4, 0xf26f + 0x80 * port,
+			3<<14, 0);
+	PKVL_SET_MASK(dev, 4, 0xf060, 1<<2, 0);
+	PKVL_WRITE(dev, 4, 0xf053, 0);
+	PKVL_WRITE(dev, 4, 0xf056, 0);
+	PKVL_WRITE(dev, 4, 0xf059, 0);
+	PKVL_WRITE(dev, 7, 0x9200, 0);
+	PKVL_WRITE(dev, 7, 0x9400, 0);
+	PKVL_WRITE(dev, 7, 0x9600, 0);
+	PKVL_WRITE(dev, 4, 0xf0e7, 0);
+
+	if (mode == MXD_10GB) {
+		PKVL_SET_MASK(dev, 4, 0xf25c + 0x80 * port,
+				0x2, 0x2);
+		PKVL_WRITE(dev, 4, 0xf220 + 0x80 * port, 0x1918);
+		PKVL_WRITE(dev, 4, 0xf221 + 0x80 * port, 0x1819);
+		PKVL_WRITE(dev, 4, 0xf230 + 0x80 * port, 0x7);
+		PKVL_WRITE(dev, 4, 0xf231 + 0x80 * port, 0xaff);
+		PKVL_WRITE(dev, 4, 0xf232 + 0x80 * port, 0);
+		PKVL_WRITE(dev, 4, 0xf250 + 0x80 * port, 0x1111);
+		PKVL_WRITE(dev, 4, 0xf251 + 0x80 * port, 0x1111);
+		PKVL_SET_MASK(dev, 4, 0xf258 + 0x80 * port,
+				0x7, 0x7);
+	}
+
+	PKVL_SET_MASK(dev, 4, 0xf25c + 0x80 * port, 0x2, 0x2);
+	PKVL_WRITE(dev, 4, 0xf22b + 0x80 * port, 0x1918);
+	PKVL_WRITE(dev, 4, 0xf246 + 0x80 * port, 0x4033);
+	PKVL_WRITE(dev, 4, 0xf247 + 0x80 * port, 0x4820);
+	PKVL_WRITE(dev, 4, 0xf255 + 0x80 * port, 0x1100);
+	PKVL_SET_MASK(dev, 4, 0xf259 + 0x80 * port, 0xc0, 0xc0);
+
+	PKVL_SERDES_SET(dev, 0x103 + 0x100 * port, 0x3d, 0x9004);
+	PKVL_SERDES_SET(dev, 0x103 + 0x100 * port, 0x3d, 0xa002);
+	PKVL_SERDES_SET(dev, 0x103 + 0x100 * port, 0x3d, 0xb012);
+
+	PKVL_WRITE(dev, 4, 0xf000 + port, 0x8020 | mode);
+	PKVL_READ(dev, 4, 0xf000 + port, &val);
+
+	dev_info(dev, "PKVL:%d port:%d host side mode:0x%x\n",
+			dev->index, port, val);
+
+	return 0;
+}
+
+int pkvl_set_speed_mode(struct altera_mdio_dev *dev, int port, int mode)
+{
+	int ret;
+
+	ret = pkvl_set_line_side_mode(dev, port, mode);
+	if (ret)
+		return ret;
+
+	return pkvl_set_host_side_mode(dev, port, mode);
+}
+
+int pkvl_get_port_speed_status(struct altera_mdio_dev *dev,
+		int port, unsigned int *speed)
+{
+	int ret;
+
+	ret = pkvl_reg_read(dev, 4, 0xf000 + port, speed);
+	if (ret)
+		return ret;
+
+	*speed = *speed & 0x7;
+
+	return 0;
+}
+
+int pkvl_get_port_line_link_status(struct altera_mdio_dev *dev,
+		int port, unsigned int *link)
+{
+	int ret;
+
+	ret = pkvl_reg_read(dev, 3, 0xa002 + 0x200 * port, link);
+	if (ret)
+		return ret;
+
+	*link = (*link & (1<<2)) ? 1:0;
+
+	return 0;
+}
+
+int pkvl_get_port_host_link_status(struct altera_mdio_dev *dev,
+		int port, unsigned int *link)
+{
+	int ret;
+
+	ret = pkvl_reg_read(dev, 4, 0xa002 + 0x200 * port, link);
+	if (ret)
+		return ret;
+
+	*link = (*link & (1<<2)) ? 1:0;
+
+	return 0;
+}
+
+static struct altera_mdio_dev *altera_spi_mdio_init(int index, u32 start,
+		u32 end, void *sub_dev)
+{
+	struct altera_mdio_dev *dev;
+	int ret;
+	int port_id = 0;
+	int phy_id = 0;
+	int device_id = 0;
+
+	dev = opae_malloc(sizeof(*dev));
+	if (!dev)
+		return NULL;
+
+	dev->sub_dev = sub_dev;
+	dev->start = start;
+	dev->end = end;
+	dev->port_id = -1;
+	dev->index = index;
+
+	ret = mdio_phy_scan(dev, &port_id, &phy_id, &device_id);
+	if (ret) {
+		dev_err(dev, "Cannot found Phy Device on MIDO Bus\n");
+		opae_free(dev);
+		return NULL;
+	}
+
+	dev->port_id = port_id;
+	dev->phy_device_id = device_id;
+
+	dev_info(dev, "Found MDIO Phy Device %d, port_id=%d, phy_id=0x%x, device_id=0x%x\n",
+			index, port_id, phy_id, device_id);
+
+	return dev;
+}
+
+struct altera_mdio_dev *altera_mdio_probe(int index, u32 start, u32 end,
+		void *sub_dev)
+{
+	return altera_spi_mdio_init(index, start, end, sub_dev);
+}
+
+void altera_mdio_release(struct altera_mdio_dev *dev)
+{
+	if (dev)
+		opae_free(dev);
+}
diff --git a/drivers/raw/ifpga_rawdev/base/opae_mdio.h b/drivers/raw/ifpga_rawdev/base/opae_mdio.h
new file mode 100644
index 0000000..8c868d6
--- /dev/null
+++ b/drivers/raw/ifpga_rawdev/base/opae_mdio.h
@@ -0,0 +1,90 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _OPAE_MDIO_H_
+#define _OPAE_MDIO_H_
+
+#include "opae_osdep.h"
+
+/* retimer speed */
+enum retimer_speed {
+	MXD_1GB = 0,
+	MXD_2_5GB,
+	MXD_5GB,
+	MXD_10GB,
+	MXD_25GB,
+	MXD_40GB,
+	MXD_100GB,
+	MXD_SPEED_UNKNOWN,
+};
+
+/* retimer info */
+struct opae_retimer_info {
+	int num_retimer;
+	int num_port;
+	enum retimer_speed support_speed;
+};
+
+/* retimer status*/
+struct opae_retimer_status {
+	enum retimer_speed speed;
+	unsigned int line_link;
+	unsigned int host_link;
+};
+
+/**
+ * read MDIO need about 62us delay, SPI keep
+ * reading before get valid data, so we let
+ * SPI master read more than 100 bytes
+ */
+#define MDIO_READ_DELAY 100
+
+/* register offset definition */
+#define ALTERA_MDIO_DATA_OFST            0x80
+#define ALTERA_MDIO_ADDRESS_OFST         0x84
+
+struct altera_mdio_dev;
+
+struct altera_mdio_dev {
+	void *sub_dev;   /* sub dev link to spi tran device*/
+	u32 start;  /* start address*/
+	u32 end;    /* end of address */
+	int index;
+	int port_id;
+	int phy_device_id;
+};
+
+struct altera_mdio_addr {
+	union {
+		unsigned int csr;
+		struct{
+			u8 devad:5;
+			u8 rsvd1:3;
+			u8 prtad:5;
+			u8 rsvd2:3;
+			u16 regad:16;
+		};
+	};
+};
+
+/* function declaration */
+struct altera_mdio_dev *altera_mdio_probe(int index, u32 start,
+		u32 end, void *sub_dev);
+void altera_mdio_release(struct altera_mdio_dev *dev);
+int altera_mdio_read(struct altera_mdio_dev *dev, u32 dev_addr,
+		u32 port_id, u32 reg, u32 *value);
+int altera_mdio_write(struct altera_mdio_dev *dev, u32 dev_addr,
+		u32 port_id, u32 reg, u32 value);
+int pkvl_reg_read(struct altera_mdio_dev *dev, u32 dev_addr,
+		u32 reg, u32 *value);
+int pkvl_reg_write(struct altera_mdio_dev *dev, u32 dev_addr,
+		u32 reg, u32 value);
+int pkvl_set_speed_mode(struct altera_mdio_dev *dev, int port, int mode);
+int pkvl_get_port_speed_status(struct altera_mdio_dev *dev,
+		int port, unsigned int *speed);
+int pkvl_get_port_line_link_status(struct altera_mdio_dev *dev,
+		int port, unsigned int *link);
+int pkvl_get_port_host_link_status(struct altera_mdio_dev *dev,
+		int port, unsigned int *link);
+#endif /* _OPAE_MDIO_H_ */
diff --git a/drivers/raw/ifpga_rawdev/base/opae_osdep.h b/drivers/raw/ifpga_rawdev/base/opae_osdep.h
index 90f54f7..6fb8f08 100644
--- a/drivers/raw/ifpga_rawdev/base/opae_osdep.h
+++ b/drivers/raw/ifpga_rawdev/base/opae_osdep.h
@@ -5,6 +5,8 @@ 
 #ifndef _OPAE_OSDEP_H
 #define _OPAE_OSDEP_H
 
+//#define OPAE_DEBUG
+
 #include <string.h>
 #include <stdbool.h>
 
@@ -35,6 +37,7 @@  struct uuid {
 #ifndef BIT
 #define BIT(a) (1UL << (a))
 #endif /* BIT */
+#define U64_C(x) x ## ULL
 #ifndef BIT_ULL
 #define BIT_ULL(a) (1ULL << (a))
 #endif /* BIT_ULL */
@@ -52,12 +55,7 @@  struct uuid {
 #define dev_err(x, args...) dev_printf(ERR, args)
 #define dev_info(x, args...) dev_printf(INFO, args)
 #define dev_warn(x, args...) dev_printf(WARNING, args)
-
-#ifdef OPAE_DEBUG
 #define dev_debug(x, args...) dev_printf(DEBUG, args)
-#else
-#define dev_debug(x, args...) do { } while (0)
-#endif
 
 #define pr_err(y, args...) dev_err(0, y, ##args)
 #define pr_warn(y, args...) dev_warn(0, y, ##args)
@@ -75,5 +73,8 @@  struct uuid {
 #define udelay(x) opae_udelay(x)
 #define msleep(x) opae_udelay(1000 * (x))
 #define usleep_range(min, max) msleep(DIV_ROUND_UP(min, 1000))
+#define time_after(a, b)	((long)((b) - (a)) < 0)
+#define time_before(a, b)	time_after(b, a)
+#define opae_memset(a, b, c)    memset((a), (b), (c))
 
 #endif
diff --git a/drivers/raw/ifpga_rawdev/base/opae_phy_group.c b/drivers/raw/ifpga_rawdev/base/opae_phy_group.c
new file mode 100644
index 0000000..9234129
--- /dev/null
+++ b/drivers/raw/ifpga_rawdev/base/opae_phy_group.c
@@ -0,0 +1,88 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+#include "opae_osdep.h"
+#include "opae_phy_group.h"
+
+static int phy_indirect_wait(struct phy_group_device *dev)
+{
+	int retry = 0;
+	u64 val;
+
+	while (!((val = opae_readq(dev->base + PHY_GROUP_STAT)) &
+				STAT_DATA_VALID)) {
+		if (retry++ > 1000)
+			return -EBUSY;
+
+		udelay(1);
+	}
+
+	return 0;
+}
+
+static void phy_indirect_write(struct phy_group_device *dev, u8 entry,
+		u16 addr, u32 value)
+{
+	u64 ctrl;
+
+	ctrl = CMD_RD << CTRL_COMMAND_SHIFT |
+		(entry & CTRL_PHY_NUM_MASK) << CTRL_PHY_NUM_SHIFT |
+		(addr & CTRL_PHY_ADDR_MASK) << CTRL_PHY_ADDR_SHIFT |
+		(value & CTRL_WRITE_DATA_MASK);
+
+	opae_writeq(ctrl, dev->base + PHY_GROUP_CTRL);
+}
+
+static int phy_indirect_read(struct phy_group_device *dev, u8 entry, u16 addr,
+		u32 *value)
+{
+	u64 tmp;
+	u64 ctrl = 0;
+
+	ctrl = CMD_RD << CTRL_COMMAND_SHIFT |
+		(entry & CTRL_PHY_NUM_MASK) << CTRL_PHY_NUM_SHIFT |
+		(addr & CTRL_PHY_ADDR_MASK) << CTRL_PHY_ADDR_SHIFT;
+	opae_writeq(ctrl, dev->base + PHY_GROUP_CTRL);
+
+	if (phy_indirect_wait(dev))
+		return -ETIMEDOUT;
+
+	tmp = opae_readq(dev->base + PHY_GROUP_STAT);
+	*value = tmp & STAT_READ_DATA_MASK;
+
+	return 0;
+}
+
+int phy_group_read_reg(struct phy_group_device *dev, u8 entry,
+		u16 addr, u32 *value)
+{
+	return phy_indirect_read(dev, entry, addr, value);
+}
+
+int phy_group_write_reg(struct phy_group_device *dev, u8 entry,
+		u16 addr, u32 value)
+{
+	phy_indirect_write(dev, entry, addr, value);
+
+	return 0;
+}
+
+struct phy_group_device *phy_group_probe(void *base)
+{
+	struct phy_group_device *dev;
+
+	dev = opae_malloc(sizeof(*dev));
+	if (!dev)
+		return NULL;
+
+	dev->base = (u8 *)base;
+
+	dev->info.info = opae_readq(dev->base + PHY_GROUP_INFO);
+	dev->group_index = dev->info.group_number;
+	dev->entries = dev->info.num_phys;
+	dev->speed = dev->info.speed;
+	dev->entry_size = PHY_GROUP_ENTRY_SIZE;
+
+	return dev;
+}
diff --git a/drivers/raw/ifpga_rawdev/base/opae_phy_group.h b/drivers/raw/ifpga_rawdev/base/opae_phy_group.h
new file mode 100644
index 0000000..d4def6d
--- /dev/null
+++ b/drivers/raw/ifpga_rawdev/base/opae_phy_group.h
@@ -0,0 +1,53 @@ 
+#ifndef _OPAE_PHY_MAC_H
+#define _OPAE_PHY_MAC_H
+
+#include "opae_osdep.h"
+
+#define MAX_PHY_GROUP_DEVICES  8
+#define PHY_GROUP_ENTRY_SIZE 0x1000
+
+#define PHY_GROUP_INFO 0x8
+#define PHY_GROUP_CTRL 0x10
+#define CTRL_COMMAND_SHIFT 62
+#define CMD_RD 0x1UL
+#define CMD_WR 0x2UL
+#define CTRL_PHY_NUM_SHIFT 43
+#define CTRL_PHY_NUM_MASK GENMASK_ULL(45, 43)
+#define CTRL_RESET BIT_ULL(42)
+#define CTRL_PHY_ADDR_SHIFT 32
+#define CTRL_PHY_ADDR_MASK GENMASK_ULL(41, 32)
+#define CTRL_WRITE_DATA_MASK GENMASK_ULL(31, 0)
+#define PHY_GROUP_STAT 0x18
+#define STAT_DATA_VALID BIT_ULL(32)
+#define STAT_READ_DATA_MASK GENMASK_ULL(31, 0)
+
+struct phy_group_info {
+	union {
+		u64 info;
+		struct {
+			u8 group_number:8;
+			u8 num_phys:8;
+			u8 speed:8;
+			u8 direction:1;
+			u64 resvd:39;
+		};
+	};
+};
+
+struct phy_group_device {
+	u8 *base;
+	struct phy_group_info info;
+	u32 group_index;
+	u32 entries;
+	u32 speed;
+	u32 entry_size;
+	u32 flags;
+};
+
+struct phy_group_device *phy_group_probe(void *base);
+int phy_group_write_reg(struct phy_group_device *dev,
+		u8 entry, u16 addr, u32 value);
+int phy_group_read_reg(struct phy_group_device *dev,
+		u8 entry, u16 addr, u32 *value);
+
+#endif
diff --git a/drivers/raw/ifpga_rawdev/base/opae_spi.c b/drivers/raw/ifpga_rawdev/base/opae_spi.c
new file mode 100644
index 0000000..d21aece
--- /dev/null
+++ b/drivers/raw/ifpga_rawdev/base/opae_spi.c
@@ -0,0 +1,260 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+#include "opae_osdep.h"
+#include "opae_spi.h"
+
+static void spi_indirect_write(struct altera_spi_device *dev, u32 reg,
+		u32 value)
+{
+	u64 ctrl;
+
+	opae_writeq(value & WRITE_DATA_MASK, dev->regs + SPI_WRITE);
+
+	ctrl = CTRL_W | (reg >> 2);
+	opae_writeq(ctrl, dev->regs + SPI_CTRL);
+}
+
+static u32 spi_indirect_read(struct altera_spi_device *dev, u32 reg)
+{
+	u64 tmp;
+	u64 ctrl;
+	u32 value;
+
+	ctrl = CTRL_R | (reg >> 2);
+	opae_writeq(ctrl, dev->regs + SPI_CTRL);
+
+	/**
+	 *  FIXME: Read one more time to avoid HW timing issue. This is
+	 *  a short term workaround solution, and must be removed once
+	 *  hardware fixing is done.
+	 */
+	tmp = opae_readq(dev->regs + SPI_READ);
+	tmp = opae_readq(dev->regs + SPI_READ);
+
+	value = (u32)tmp;
+
+	return value;
+}
+
+void spi_cs_activate(struct altera_spi_device *dev, unsigned int chip_select)
+{
+	spi_indirect_write(dev, ALTERA_SPI_SLAVE_SEL, 1 << chip_select);
+	spi_indirect_write(dev, ALTERA_SPI_CONTROL, ALTERA_SPI_CONTROL_SSO_MSK);
+}
+
+void spi_cs_deactivate(struct altera_spi_device *dev)
+{
+	spi_indirect_write(dev, ALTERA_SPI_CONTROL, 0);
+}
+
+static void spi_flush_rx(struct altera_spi_device *dev)
+{
+	if (spi_indirect_read(dev, ALTERA_SPI_STATUS) &
+			ALTERA_SPI_STATUS_RRDY_MSK)
+		spi_indirect_read(dev, ALTERA_SPI_RXDATA);
+}
+
+int spi_read(struct altera_spi_device *dev, unsigned int bytes, void *buffer)
+{
+	char data;
+	char *rxbuf = buffer;
+
+	if (bytes <= 0 || !rxbuf)
+		return -EINVAL;
+
+	/* empty read buffer */
+	spi_flush_rx(dev);
+
+	while (bytes--) {
+		while (!(spi_indirect_read(dev, ALTERA_SPI_STATUS) &
+				ALTERA_SPI_STATUS_RRDY_MSK))
+			;
+		data = spi_indirect_read(dev, ALTERA_SPI_RXDATA);
+		if (buffer)
+			*rxbuf++ = data;
+	}
+
+	return 0;
+}
+
+int spi_write(struct altera_spi_device *dev, unsigned int bytes, void *buffer)
+{
+	unsigned char data;
+	char *txbuf = buffer;
+
+	if (bytes <= 0 || !txbuf)
+		return -EINVAL;
+
+	while (bytes--) {
+		while (!(spi_indirect_read(dev, ALTERA_SPI_STATUS) &
+				ALTERA_SPI_STATUS_TRDY_MSK))
+			;
+		data = *txbuf++;
+		spi_indirect_write(dev, ALTERA_SPI_TXDATA, data);
+	}
+
+	return 0;
+}
+
+static unsigned int spi_write_bytes(struct altera_spi_device *dev, int count)
+{
+	unsigned int val = 0;
+	u16 *p16;
+	u32 *p32;
+
+	if (dev->txbuf) {
+		switch (dev->data_width) {
+		case 1:
+			val = dev->txbuf[count];
+			break;
+		case 2:
+			p16 = (u16 *)(dev->txbuf + 2*count);
+			val = *p16;
+			if (dev->endian == SPI_BIG_ENDIAN)
+				val = cpu_to_be16(val);
+			break;
+		case 4:
+			p32 = (u32 *)(dev->txbuf + 4*count);
+			val = *p32;
+			if (dev->endian == SPI_BIG_ENDIAN)
+				val = (val);
+			break;
+		}
+	}
+
+	return val;
+}
+
+static void spi_fill_readbuffer(struct altera_spi_device *dev,
+		unsigned int value, int count)
+{
+	u16 *p16;
+	u32 *p32;
+
+	if (dev->rxbuf) {
+		switch (dev->data_width) {
+		case 1:
+			dev->rxbuf[count] = value;
+			break;
+		case 2:
+			p16 = (u16 *)(dev->rxbuf + 2*count);
+			if (dev->endian == SPI_BIG_ENDIAN)
+				*p16 = cpu_to_be16((u16)value);
+			else
+				*p16 = (u16)value;
+			break;
+		case 4:
+			p32 = (u32 *)(dev->rxbuf + 4*count);
+			if (dev->endian == SPI_BIG_ENDIAN)
+				*p32 = cpu_to_be32(value);
+			else
+				*p32 = value;
+			break;
+		}
+	}
+}
+
+static int spi_txrx(struct altera_spi_device *dev)
+{
+	unsigned int count = 0;
+	unsigned int rxd;
+	unsigned int tx_data;
+	unsigned int status;
+	int retry = 0;
+
+	while (count < dev->len) {
+		tx_data = spi_write_bytes(dev, count);
+		spi_indirect_write(dev, ALTERA_SPI_TXDATA, tx_data);
+
+		while (1) {
+			status = spi_indirect_read(dev, ALTERA_SPI_STATUS);
+			if (status & ALTERA_SPI_STATUS_RRDY_MSK)
+				break;
+			if (retry++ > SPI_MAX_RETRY) {
+				dev_err(dev, "%s, read timeout\n", __func__);
+				return -EBUSY;
+			}
+		}
+
+		rxd = spi_indirect_read(dev, ALTERA_SPI_RXDATA);
+		spi_fill_readbuffer(dev, rxd, count);
+
+		count++;
+	}
+
+	return 0;
+}
+
+int spi_command(struct altera_spi_device *dev, unsigned int chip_select,
+		unsigned int wlen, void *wdata,
+		unsigned int rlen, void *rdata)
+{
+	if (((wlen > 0) && !wdata) || ((rlen > 0) && !rdata)) {
+		dev_err(dev, "error on spi command checking\n");
+		return -EINVAL;
+	}
+
+	wlen = wlen / dev->data_width;
+	rlen = rlen / dev->data_width;
+
+	/* flush rx buffer */
+	spi_flush_rx(dev);
+
+	// TODO: GET MUTEX LOCK
+	spi_cs_activate(dev, chip_select);
+	if (wlen) {
+		dev->txbuf = wdata;
+		dev->rxbuf = rdata;
+		dev->len = wlen;
+		spi_txrx(dev);
+	}
+	if (rlen) {
+		dev->rxbuf = rdata;
+		dev->txbuf = NULL;
+		dev->len = rlen;
+		spi_txrx(dev);
+	}
+	spi_cs_deactivate(dev);
+	// TODO: RELEASE MUTEX LOCK
+	return 0;
+}
+
+struct altera_spi_device *altera_spi_init(void *base)
+{
+	struct altera_spi_device *spi_dev =
+		opae_malloc(sizeof(struct altera_spi_device));
+
+	if (!spi_dev)
+		return NULL;
+
+	spi_dev->regs = base;
+
+	spi_dev->spi_param.info = opae_readq(spi_dev->regs + SPI_CORE_PARAM);
+
+	spi_dev->data_width = spi_dev->spi_param.data_width / 8;
+	spi_dev->endian = spi_dev->spi_param.endian;
+	spi_dev->num_chipselect = spi_dev->spi_param.num_chipselect;
+	dev_info(spi_dev, "spi param: type=%d, data width:%d, endian:%d, clock_polarity=%d, clock=%dMHz, chips=%d, cpha=%d\n",
+			spi_dev->spi_param.type,
+			spi_dev->data_width, spi_dev->endian,
+			spi_dev->spi_param.clock_polarity,
+			spi_dev->spi_param.clock,
+			spi_dev->num_chipselect,
+			spi_dev->spi_param.clock_phase);
+
+	/* clear */
+	spi_indirect_write(spi_dev, ALTERA_SPI_CONTROL, 0);
+	spi_indirect_write(spi_dev, ALTERA_SPI_STATUS, 0);
+	/* flush rxdata */
+	spi_flush_rx(spi_dev);
+
+	return spi_dev;
+}
+
+void altera_spi_release(struct altera_spi_device *dev)
+{
+	if (dev)
+		opae_free(dev);
+}
diff --git a/drivers/raw/ifpga_rawdev/base/opae_spi.h b/drivers/raw/ifpga_rawdev/base/opae_spi.h
new file mode 100644
index 0000000..d93ff09
--- /dev/null
+++ b/drivers/raw/ifpga_rawdev/base/opae_spi.h
@@ -0,0 +1,120 @@ 
+#ifndef _OPAE_SPI_H
+#define _OPAE_SPI_H
+
+#include "opae_osdep.h"
+
+#define ALTERA_SPI_RXDATA	0
+#define ALTERA_SPI_TXDATA	4
+#define ALTERA_SPI_STATUS	8
+#define ALTERA_SPI_CONTROL	12
+#define ALTERA_SPI_SLAVE_SEL	20
+
+#define ALTERA_SPI_STATUS_ROE_MSK	0x8
+#define ALTERA_SPI_STATUS_TOE_MSK	0x10
+#define ALTERA_SPI_STATUS_TMT_MSK	0x20
+#define ALTERA_SPI_STATUS_TRDY_MSK	0x40
+#define ALTERA_SPI_STATUS_RRDY_MSK	0x80
+#define ALTERA_SPI_STATUS_E_MSK		0x100
+
+#define ALTERA_SPI_CONTROL_IROE_MSK	0x8
+#define ALTERA_SPI_CONTROL_ITOE_MSK	0x10
+#define ALTERA_SPI_CONTROL_ITRDY_MSK	0x40
+#define ALTERA_SPI_CONTROL_IRRDY_MSK	0x80
+#define ALTERA_SPI_CONTROL_IE_MSK	0x100
+#define ALTERA_SPI_CONTROL_SSO_MSK	0x400
+
+#define SPI_CORE_PARAM 0x8
+#define SPI_CTRL 0x10
+#define CTRL_R    BIT_ULL(9)
+#define CTRL_W    BIT_ULL(8)
+#define CTRL_ADDR_MASK GENMASK_ULL(2, 0)
+#define SPI_READ 0x18
+#define READ_DATA_VALID BIT_ULL(32)
+#define READ_DATA_MASK GENMASK_ULL(31, 0)
+#define SPI_WRITE 0x20
+#define WRITE_DATA_MASK GENMASK_ULL(31, 0)
+
+#define SPI_MAX_RETRY 100000
+
+struct spi_core_param {
+	union {
+		u64 info;
+		struct {
+			u8 type:1;
+			u8 endian:1;
+			u8 data_width:6;
+			u8 num_chipselect:6;
+			u8 clock_polarity:1;
+			u8 clock_phase:1;
+			u8 stages:2;
+			u8 resvd:4;
+			u16 clock:10;
+			u16 peripheral_id:16;
+			u8 controller_type:1;
+			u16 resvd1:15;
+		};
+	};
+};
+
+struct altera_spi_device {
+	u8 *regs;
+	struct spi_core_param spi_param;
+	int data_width; /* how many bytes for data width */
+	int endian;
+	#define SPI_BIG_ENDIAN  0
+	#define SPI_LITTLE_ENDIAN 1
+	int num_chipselect;
+	unsigned char *rxbuf;
+	unsigned char *txbuf;
+	unsigned int len;
+};
+
+#define HEADER_LEN 8
+#define RESPONSE_LEN 4
+#define SPI_TRANSACTION_MAX_LEN 1024
+#define TRAN_SEND_MAX_LEN (SPI_TRANSACTION_MAX_LEN + HEADER_LEN)
+#define TRAN_RESP_MAX_LEN SPI_TRANSACTION_MAX_LEN
+#define PACKET_SEND_MAX_LEN (2*TRAN_SEND_MAX_LEN + 4)
+#define PACKET_RESP_MAX_LEN (2*TRAN_RESP_MAX_LEN + 4)
+#define BYTES_SEND_MAX_LEN  (2*PACKET_SEND_MAX_LEN)
+#define BYTES_RESP_MAX_LEN (2*PACKET_RESP_MAX_LEN)
+
+struct spi_tran_buffer {
+	unsigned char tran_send[TRAN_SEND_MAX_LEN];
+	unsigned char tran_resp[TRAN_RESP_MAX_LEN];
+	unsigned char packet_send[PACKET_SEND_MAX_LEN];
+	unsigned char packet_resp[PACKET_RESP_MAX_LEN];
+	unsigned char bytes_send[BYTES_SEND_MAX_LEN];
+	unsigned char bytes_resp[2*BYTES_RESP_MAX_LEN];
+};
+
+struct spi_transaction_dev {
+	struct altera_spi_device *dev;
+	int chipselect;
+	struct spi_tran_buffer *buffer;
+};
+
+struct spi_tran_header {
+	u8 trans_type;
+	u8 reserve;
+	u16 size;
+	u32 addr;
+};
+
+int spi_write(struct altera_spi_device *dev, unsigned int bytes, void *buffer);
+int spi_read(struct altera_spi_device *dev, unsigned int bytes,
+		void *buffer);
+int spi_command(struct altera_spi_device *dev, unsigned int chip_select,
+		unsigned int wlen, void *wdata, unsigned int rlen, void *rdata);
+void spi_cs_deactivate(struct altera_spi_device *dev);
+void spi_cs_activate(struct altera_spi_device *dev, unsigned int chip_select);
+struct altera_spi_device *altera_spi_init(void *base);
+void altera_spi_release(struct altera_spi_device *dev);
+int spi_transaction_read(struct spi_transaction_dev *dev, unsigned int addr,
+		unsigned int size, unsigned char *data);
+int spi_transaction_write(struct spi_transaction_dev *dev, unsigned int addr,
+		unsigned int size, unsigned char *data);
+struct spi_transaction_dev *spi_transaction_init(struct altera_spi_device *dev,
+		int chipselect);
+void spi_transaction_remove(struct spi_transaction_dev *dev);
+#endif
diff --git a/drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c b/drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c
new file mode 100644
index 0000000..d781b62
--- /dev/null
+++ b/drivers/raw/ifpga_rawdev/base/opae_spi_transaction.c
@@ -0,0 +1,438 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+#include "opae_spi.h"
+#include "ifpga_compat.h"
+
+/*transaction opcodes*/
+#define SPI_TRAN_SEQ_WRITE 0x04 /* SPI transaction sequential write */
+#define SPI_TRAN_SEQ_READ  0x14 /* SPI transaction sequential read */
+#define SPI_TRAN_NON_SEQ_WRITE 0x00 /* SPI transaction non-sequential write */
+#define SPI_TRAN_NON_SEQ_READ  0x10 /* SPI transaction non-sequential read*/
+
+/*specail packet characters*/
+#define SPI_PACKET_SOP     0x7a
+#define SPI_PACKET_EOP     0x7b
+#define SPI_PACKET_CHANNEL 0x7c
+#define SPI_PACKET_ESC     0x7d
+
+/*special byte characters*/
+#define SPI_BYTE_IDLE 0x4a
+#define SPI_BYTE_ESC  0x4d
+
+#define SPI_REG_BYTES 4
+
+#define INIT_SPI_TRAN_HEADER(trans_type, size, address) \
+({ \
+	header.trans_type = trans_type; \
+	header.reserve = 0; \
+	header.size = cpu_to_be16(size); \
+	header.addr = cpu_to_be32(addr); \
+})
+
+#ifdef OPAE_DEBUG
+static void print_buffer(const char *string, void *buffer, int len)
+{
+	int i;
+	unsigned char *p = buffer;
+
+	printf("%s print buffer, len=%d\n", string, len);
+
+	for (i = 0; i < len; i++)
+		printf("%x ", *(p+i));
+	printf("\n");
+}
+#else
+static void print_buffer(const char *string, void *buffer, int len)
+{
+	UNUSED(string);
+	UNUSED(buffer);
+	UNUSED(len);
+}
+#endif
+
+static unsigned char xor_20(unsigned char val)
+{
+	return val^0x20;
+}
+
+static void reorder_phy_data(u8 bits_per_word,
+		void *buf, unsigned int len)
+{
+	unsigned int count = len / (bits_per_word/8);
+	u32 *p;
+
+	if (bits_per_word == 32) {
+		p = (u32 *)buf;
+		while (count--) {
+			*p = cpu_to_be32(*p);
+			p++;
+		}
+	}
+}
+
+enum {
+	SPI_FOUND_SOP,
+	SPI_FOUND_EOP,
+	SPI_NOT_FOUND,
+};
+
+static int resp_find_sop_eop(unsigned char *resp, unsigned int len,
+		int flags)
+{
+	int ret = SPI_NOT_FOUND;
+
+	unsigned char *b = resp;
+
+	/* find SOP */
+	if (flags != SPI_FOUND_SOP) {
+		while (b < resp + len && *b != SPI_PACKET_SOP)
+			b++;
+
+		if (*b != SPI_PACKET_SOP)
+			goto done;
+
+		ret = SPI_FOUND_SOP;
+	}
+
+	/* find EOP */
+	while (b < resp + len && *b != SPI_PACKET_EOP)
+		b++;
+
+	if (*b != SPI_PACKET_EOP)
+		goto done;
+
+	ret = SPI_FOUND_EOP;
+
+done:
+	return ret;
+}
+
+static int byte_to_core_convert(struct spi_transaction_dev *dev,
+		unsigned int send_len, unsigned char *send_data,
+		unsigned int resp_len, unsigned char *resp_data,
+		unsigned int *valid_resp_len)
+{
+	unsigned int i;
+	int ret = 0;
+	unsigned char *send_packet = dev->buffer->bytes_send;
+	unsigned char *resp_packet = dev->buffer->bytes_resp;
+	unsigned char *p;
+	unsigned char current_byte;
+	unsigned char *tx_buffer;
+	unsigned int tx_len = 0;
+	unsigned char *rx_buffer;
+	unsigned int rx_len = 0;
+	int retry = 0;
+	int spi_flags;
+	unsigned int resp_max_len = 2 * resp_len;
+
+	print_buffer("before bytes:", send_data, send_len);
+
+	p = send_packet;
+
+	for (i = 0; i < send_len; i++) {
+		current_byte = send_data[i];
+		switch (current_byte) {
+		case SPI_BYTE_IDLE:
+			*p++ = SPI_BYTE_IDLE;
+			*p++ = xor_20(current_byte);
+			break;
+		case SPI_BYTE_ESC:
+			*p++ = SPI_BYTE_ESC;
+			*p++ = xor_20(current_byte);
+			break;
+		default:
+			*p++ = current_byte;
+			break;
+		}
+	}
+
+	print_buffer("before spi:", send_packet, p-send_packet);
+
+	reorder_phy_data(32, send_packet, p - send_packet);
+
+	print_buffer("after order to spi:", send_packet, p-send_packet);
+
+	/* call spi */
+	tx_buffer = send_packet;
+	tx_len = p - send_packet;
+	rx_buffer = resp_packet;
+	rx_len = resp_max_len;
+	spi_flags = SPI_NOT_FOUND;
+
+read_again:
+	ret = spi_command(dev->dev, dev->chipselect, tx_len, tx_buffer,
+			rx_len, rx_buffer);
+	if (ret)
+		return -EBUSY;
+
+	print_buffer("read from spi:", rx_buffer, rx_len);
+
+	/* look for SOP firstly*/
+	ret = resp_find_sop_eop(rx_buffer, rx_len - 1, spi_flags);
+	if (ret != SPI_FOUND_EOP) {
+		tx_buffer = NULL;
+		tx_len = 0;
+		if (retry++ > 10) {
+			dev_err(NULL, "cannot found valid data from SPI\n");
+			return -EBUSY;
+		}
+
+		if (ret == SPI_FOUND_SOP) {
+			rx_buffer += rx_len;
+			resp_max_len += rx_len;
+		}
+
+		spi_flags = ret;
+		goto read_again;
+	}
+
+	print_buffer("found valid data:", resp_packet, resp_max_len);
+
+	/* analyze response packet */
+	i = 0;
+	p = resp_data;
+	while (i < resp_max_len) {
+		current_byte = resp_packet[i];
+		switch (current_byte) {
+		case SPI_BYTE_IDLE:
+			i++;
+			break;
+		case SPI_BYTE_ESC:
+			i++;
+			current_byte = resp_packet[i];
+			*p++ = xor_20(current_byte);
+			i++;
+			break;
+		default:
+			*p++ = current_byte;
+			i++;
+			break;
+		}
+	}
+
+	/* receive "4a" means the SPI is idle, not valid data */
+	*valid_resp_len = p - resp_data;
+	if (*valid_resp_len == 0) {
+		dev_err(NULL, "error: repond package without valid data\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int packet_to_byte_conver(struct spi_transaction_dev *dev,
+		unsigned int send_len, unsigned char *send_buf,
+		unsigned int resp_len, unsigned char *resp_buf,
+		unsigned int *valid)
+{
+	int ret = 0;
+	unsigned int i;
+	unsigned char current_byte;
+	unsigned int resp_max_len;
+	unsigned char *send_packet = dev->buffer->packet_send;
+	unsigned char *resp_packet = dev->buffer->packet_resp;
+	unsigned char *p;
+	unsigned int valid_resp_len = 0;
+
+	print_buffer("before packet:", send_buf, send_len);
+
+	resp_max_len = 2 * resp_len + 4;
+
+	p = send_packet;
+
+	/* SOP header */
+	*p++ = SPI_PACKET_SOP;
+
+	*p++ = SPI_PACKET_CHANNEL;
+	*p++ = 0;
+
+	/* append the data into a packet */
+	for (i = 0; i < send_len; i++) {
+		current_byte = send_buf[i];
+
+		/* EOP for last byte */
+		if (i == send_len - 1)
+			*p++ = SPI_PACKET_EOP;
+
+		switch (current_byte) {
+		case SPI_PACKET_SOP:
+		case SPI_PACKET_EOP:
+		case SPI_PACKET_CHANNEL:
+		case SPI_PACKET_ESC:
+			*p++ = SPI_PACKET_ESC;
+			*p++ = xor_20(current_byte);
+			break;
+		default:
+			*p++ = current_byte;
+		}
+	}
+
+	ret = byte_to_core_convert(dev, p - send_packet,
+			send_packet, resp_max_len, resp_packet,
+			&valid_resp_len);
+	if (ret)
+		return -EBUSY;
+
+	print_buffer("after byte conver:", resp_packet, valid_resp_len);
+
+	/* analyze the response packet */
+	p = resp_buf;
+
+	/* look for SOP */
+	for (i = 0; i < valid_resp_len; i++) {
+		if (resp_packet[i] == SPI_PACKET_SOP)
+			break;
+	}
+
+	if (i == valid_resp_len) {
+		dev_err(NULL, "error on analyze response packet 0x%x\n",
+				resp_packet[i]);
+		return -EINVAL;
+	}
+
+	i++;
+
+	/* continue parsing data after SOP */
+	while (i < valid_resp_len) {
+		current_byte = resp_packet[i];
+
+		switch (current_byte) {
+		case SPI_PACKET_ESC:
+		case SPI_PACKET_CHANNEL:
+		case SPI_PACKET_SOP:
+			i++;
+			current_byte = resp_packet[i];
+			*p++ = xor_20(current_byte);
+			i++;
+			break;
+		case SPI_PACKET_EOP:
+			i++;
+			current_byte = resp_packet[i];
+			if (current_byte == SPI_PACKET_ESC ||
+					current_byte == SPI_PACKET_CHANNEL ||
+					current_byte == SPI_PACKET_SOP) {
+				i++;
+				current_byte = resp_packet[i];
+				*p++ = xor_20(current_byte);
+			} else
+				*p++ = current_byte;
+			i = valid_resp_len;
+			break;
+		default:
+			*p++ = current_byte;
+			i++;
+		}
+
+	}
+
+	*valid = p - resp_buf;
+
+	print_buffer("after packet:", resp_buf, *valid);
+
+	return ret;
+}
+
+static int do_transaction(struct spi_transaction_dev *dev, unsigned int addr,
+		unsigned int size, unsigned char *data,
+		unsigned int trans_type)
+{
+
+	struct spi_tran_header header;
+	unsigned char *transaction = dev->buffer->tran_send;
+	unsigned char *response = dev->buffer->tran_resp;
+	unsigned char *p;
+	int ret = 0;
+	unsigned int i;
+	unsigned int valid_len = 0;
+
+	/* make transacation header */
+	INIT_SPI_TRAN_HEADER(trans_type, size, addr);
+
+	/* fill the header */
+	p = transaction;
+	opae_memcpy(p, &header, sizeof(struct spi_tran_header));
+	p = p + sizeof(struct spi_tran_header);
+
+	switch (trans_type) {
+	case SPI_TRAN_SEQ_WRITE:
+	case SPI_TRAN_NON_SEQ_WRITE:
+		for (i = 0; i < size; i++)
+			*p++ = *data++;
+
+			ret = packet_to_byte_conver(dev, size + HEADER_LEN,
+				      transaction, RESPONSE_LEN, response,
+				      &valid_len);
+			if (ret)
+				return -EBUSY;
+
+			/* check the result */
+			if (size != ((unsigned int)(response[2] & 0xff) << 8 |
+					(unsigned int)(response[3] & 0xff)))
+				ret = -EBUSY;
+
+			break;
+	case SPI_TRAN_SEQ_READ:
+	case SPI_TRAN_NON_SEQ_READ:
+		ret = packet_to_byte_conver(dev, HEADER_LEN,
+				transaction, size, response,
+				&valid_len);
+		if (ret || valid_len != size)
+			return -EBUSY;
+
+		for (i = 0; i < size; i++)
+			*data++ = *response++;
+
+		ret = 0;
+		break;
+	}
+
+	return ret;
+}
+
+int spi_transaction_read(struct spi_transaction_dev *dev, unsigned int addr,
+		unsigned int size, unsigned char *data)
+{
+	return do_transaction(dev, addr, size, data,
+			(size > SPI_REG_BYTES) ?
+			SPI_TRAN_SEQ_READ : SPI_TRAN_NON_SEQ_READ);
+}
+
+int spi_transaction_write(struct spi_transaction_dev *dev, unsigned int addr,
+		unsigned int size, unsigned char *data)
+{
+	return do_transaction(dev, addr, size, data,
+			(size > SPI_REG_BYTES) ?
+			SPI_TRAN_SEQ_WRITE : SPI_TRAN_NON_SEQ_WRITE);
+}
+
+struct spi_transaction_dev *spi_transaction_init(struct altera_spi_device *dev,
+		int chipselect)
+{
+	struct spi_transaction_dev *spi_tran_dev;
+
+	spi_tran_dev = opae_malloc(sizeof(struct spi_transaction_dev));
+	if (!spi_tran_dev)
+		return NULL;
+
+	spi_tran_dev->dev = dev;
+	spi_tran_dev->chipselect = chipselect;
+
+	spi_tran_dev->buffer = opae_malloc(sizeof(struct spi_tran_buffer));
+	if (!spi_tran_dev->buffer) {
+		opae_free(spi_tran_dev);
+		return NULL;
+	}
+
+	return spi_tran_dev;
+}
+
+void spi_transaction_remove(struct spi_transaction_dev *dev)
+{
+	if (dev && dev->buffer)
+		opae_free(dev->buffer);
+	if (dev)
+		opae_free(dev);
+}
diff --git a/drivers/raw/ifpga_rawdev/base/osdep_raw/osdep_generic.h b/drivers/raw/ifpga_rawdev/base/osdep_raw/osdep_generic.h
index 895a1d8..6769109 100644
--- a/drivers/raw/ifpga_rawdev/base/osdep_raw/osdep_generic.h
+++ b/drivers/raw/ifpga_rawdev/base/osdep_raw/osdep_generic.h
@@ -71,5 +71,6 @@  static inline void opae_writeq(uint64_t value, volatile void *addr)
 }
 
 #define opae_free(addr) free(addr)
+#define opae_memcpy(a, b, c) memcpy((a), (b), (c))
 
 #endif
diff --git a/drivers/raw/ifpga_rawdev/base/osdep_rte/osdep_generic.h b/drivers/raw/ifpga_rawdev/base/osdep_rte/osdep_generic.h
index 76902e2..cd5b7c9 100644
--- a/drivers/raw/ifpga_rawdev/base/osdep_rte/osdep_generic.h
+++ b/drivers/raw/ifpga_rawdev/base/osdep_rte/osdep_generic.h
@@ -11,6 +11,8 @@ 
 #include <rte_log.h>
 #include <rte_io.h>
 #include <rte_malloc.h>
+#include <rte_byteorder.h>
+#include <rte_memcpy.h>
 
 #define dev_printf(level, fmt, args...) \
 	RTE_LOG(level, PMD, "osdep_rte: " fmt, ## args)
@@ -42,4 +44,12 @@ 
 #define spinlock_lock(x) rte_spinlock_lock(x)
 #define spinlock_unlock(x) rte_spinlock_unlock(x)
 
+#define cpu_to_be16(o) rte_cpu_to_be_16(o)
+#define cpu_to_be32(o) rte_cpu_to_be_32(o)
+#define cpu_to_be64(o) rte_cpu_to_be_64(o)
+#define cpu_to_le16(o) rte_cpu_to_le_16(o)
+#define cpu_to_le32(o) rte_cpu_to_le_32(o)
+#define cpu_to_le64(o) rte_cpu_to_le_64(o)
+
+#define opae_memcpy(a, b, c) rte_memcpy((a), (b), (c))
 #endif