> -----Original Message-----
> From: Huang, Wei <wei.hu...@intel.com>
> Sent: Friday, June 17, 2022 3:20 PM
> To: dev@dpdk.org; tho...@monjalon.net; nipun.gu...@nxp.com;
> hemant.agra...@nxp.com
> Cc: sta...@dpdk.org; Xu, Rosen <rosen...@intel.com>; Zhang, Tianfei
> <tianfei.zh...@intel.com>; Zhang, Qi Z <qi.z.zh...@intel.com>; Huang, Wei
> <wei.hu...@intel.com>
> Subject: [PATCH v3 3/4] raw/ifpga/base: update flash operation interface
>
> In N6000 ADP platform, SPI protocol, master and QSPI flash are transparent to
> host software. The SPI master implemented in PMCI automatically converts the
> mailbox commands to the SPI protocol required by SPI slave.
> That means flash operation is different from old platform, new interfaces are
> introduced to adapt these changes.
>
> Signed-off-by: Wei Huang <wei.hu...@intel.com>
> ---
> drivers/raw/ifpga/base/ifpga_api.c | 9 +
> drivers/raw/ifpga/base/ifpga_feature_dev.h | 2 +
> drivers/raw/ifpga/base/ifpga_fme.c | 8 +
> drivers/raw/ifpga/base/opae_hw_api.c | 20 ++
> drivers/raw/ifpga/base/opae_hw_api.h | 2 +
> drivers/raw/ifpga/base/opae_intel_max10.c | 282
> +++++++++++++++++++++++
> drivers/raw/ifpga/base/opae_intel_max10.h | 46 ++++
> drivers/raw/ifpga/base/osdep_rte/osdep_generic.h | 10 +
> 8 files changed, 379 insertions(+)
>
> diff --git a/drivers/raw/ifpga/base/ifpga_api.c
> b/drivers/raw/ifpga/base/ifpga_api.c
> index f19cc26..098de0c 100644
> --- a/drivers/raw/ifpga/base/ifpga_api.c
> +++ b/drivers/raw/ifpga/base/ifpga_api.c
> @@ -268,6 +268,14 @@ static int ifpga_mgr_reload(struct opae_manager
> *mgr, int type, int page)
> return fpga_reload(fme, type, page);
> }
>
> +static int ifpga_mgr_read_flash(struct opae_manager *mgr, u32 address,
> + u32 size, void *buf)
> +{
> + struct ifpga_fme_hw *fme = mgr->data;
> +
> + return fme_mgr_read_flash(fme, address, size, buf); }
> +
> struct opae_manager_ops ifpga_mgr_ops = {
> .flash = ifpga_mgr_flash,
> .get_eth_group_region_info = ifpga_mgr_get_eth_group_region_info,
> @@ -277,6 +285,7 @@ struct opae_manager_ops ifpga_mgr_ops = {
> .update_flash = ifpga_mgr_update_flash,
> .stop_flash_update = ifpga_mgr_stop_flash_update,
> .reload = ifpga_mgr_reload,
> + .read_flash = ifpga_mgr_read_flash
> };
>
> static int ifpga_mgr_read_mac_rom(struct opae_manager *mgr, int offset, diff
> --git a/drivers/raw/ifpga/base/ifpga_feature_dev.h
> b/drivers/raw/ifpga/base/ifpga_feature_dev.h
> index a637eb5..7a2f2e5 100644
> --- a/drivers/raw/ifpga/base/ifpga_feature_dev.h
> +++ b/drivers/raw/ifpga/base/ifpga_feature_dev.h
> @@ -223,4 +223,6 @@ int fme_mgr_get_retimer_status(struct ifpga_fme_hw
> *fme, int fme_mgr_get_sensor_value(struct ifpga_fme_hw *fme,
> struct opae_sensor_info *sensor,
> unsigned int *value);
> +int fme_mgr_read_flash(struct ifpga_fme_hw *fme, u32 address,
> + u32 size, void *buf);
> #endif /* _IFPGA_FEATURE_DEV_H_ */
> diff --git a/drivers/raw/ifpga/base/ifpga_fme.c
> b/drivers/raw/ifpga/base/ifpga_fme.c
> index 608a352..25ff819 100644
> --- a/drivers/raw/ifpga/base/ifpga_fme.c
> +++ b/drivers/raw/ifpga/base/ifpga_fme.c
> @@ -1658,3 +1658,11 @@ struct ifpga_feature_ops fme_pmci_ops = {
> .init = fme_pmci_init,
> .uinit = fme_pmci_uinit,
> };
> +
> +int fme_mgr_read_flash(struct ifpga_fme_hw *fme, u32 address,
> + u32 size, void *buf)
> +{
> + struct intel_max10_device *max10 = fme->max10_dev;
> +
> + return opae_read_flash(max10, address, size, buf); }
> diff --git a/drivers/raw/ifpga/base/opae_hw_api.c
> b/drivers/raw/ifpga/base/opae_hw_api.c
> index 87256fc..fd08326 100644
> --- a/drivers/raw/ifpga/base/opae_hw_api.c
> +++ b/drivers/raw/ifpga/base/opae_hw_api.c
> @@ -1041,3 +1041,23 @@ int opae_mgr_reload(struct opae_manager *mgr,
> int type, int page)
>
> return -ENOENT;
> }
> +/**
> + * opae_mgr_read_flash - read flash content
> + * @mgr: targeted manager
> + * @address: the start address of flash
> + * @size: the size of flash
> + * @buf: the read buffer
> + *
> + * Return: 0 on success, otherwise error code.
> + */
> +int opae_mgr_read_flash(struct opae_manager *mgr, u32 address,
> + u32 size, void *buf)
> +{
> + if (!mgr)
> + return -EINVAL;
> +
> + if (mgr->ops && mgr->ops->read_flash)
> + return mgr->ops->read_flash(mgr, address, size, buf);
> +
> + return -ENOENT;
> +}
> diff --git a/drivers/raw/ifpga/base/opae_hw_api.h
> b/drivers/raw/ifpga/base/opae_hw_api.h
> index fd40e09..de1e984 100644
> --- a/drivers/raw/ifpga/base/opae_hw_api.h
> +++ b/drivers/raw/ifpga/base/opae_hw_api.h
> @@ -60,6 +60,7 @@ struct opae_manager_ops {
> u64 *status);
> int (*stop_flash_update)(struct opae_manager *mgr, int force);
> int (*reload)(struct opae_manager *mgr, int type, int page);
> + int (*read_flash)(struct opae_manager *mgr, u32 address, u32 size,
> +void *buf);
> };
>
> /* networking management ops in FME */
> @@ -368,4 +369,5 @@ int opae_mgr_update_flash(struct opae_manager *mgr,
> const char *image,
> uint64_t *status);
> int opae_mgr_stop_flash_update(struct opae_manager *mgr, int force); int
> opae_mgr_reload(struct opae_manager *mgr, int type, int page);
> +int opae_mgr_read_flash(struct opae_manager *mgr, u32 address, u32
> +size, void *buf);
> #endif /* _OPAE_HW_API_H_*/
> diff --git a/drivers/raw/ifpga/base/opae_intel_max10.c
> b/drivers/raw/ifpga/base/opae_intel_max10.c
> index 26f323c..9c01729 100644
> --- a/drivers/raw/ifpga/base/opae_intel_max10.c
> +++ b/drivers/raw/ifpga/base/opae_intel_max10.c
> @@ -58,6 +58,279 @@ int max10_sys_update_bits(struct intel_max10_device
> *dev, unsigned int offset,
> return max10_sys_write(dev, offset, temp); }
>
> +static int n3000_bulk_raw_write(struct intel_max10_device *dev, uint32_t
> addr,
> + void *buf, uint32_t len)
> +{
> + uint32_t v = 0;
> + uint32_t i = 0;
> + char *p = buf;
> + int ret = 0;
> +
> + len = IFPGA_ALIGN(len, 4);
> +
> + for (i = 0; i < len; i += 4) {
> + v = *(uint32_t *)(p + i);
> + ret = max10_reg_write(dev, addr + i, v);
> + if (ret < 0) {
> + dev_err(dev,
> + "Failed to write to staging area 0x%08x
> [e:%d]\n",
> + addr + i, ret);
> + return ret;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int n3000_bulk_raw_read(struct intel_max10_device *dev,
> + uint32_t addr, void *buf, uint32_t len) {
> + u32 v, i;
> + char *p = buf;
> + int ret;
> +
> + len = IFPGA_ALIGN(len, 4);
> +
> + for (i = 0; i < len; i += 4) {
> + ret = max10_reg_read(dev, addr + i, &v);
> + if (ret < 0) {
> + dev_err(dev,
> + "Failed to write to staging area 0x%08x
> [e:%d]\n",
> + addr + i, ret);
> + return ret;
> + }
> + *(u32 *)(p + i) = v;
> + }
> +
> + return 0;
> +}
> +
> +static int n3000_flash_read(struct intel_max10_device *dev,
> + u32 addr, void *buf, u32 size)
> +{
> + if (!dev->raw_blk_ops.read_blk)
> + return -ENODEV;
> +
> + return dev->raw_blk_ops.read_blk(dev, addr, buf, size); }
> +
> +static int n3000_flash_write(struct intel_max10_device *dev,
> + u32 addr, void *buf, u32 size)
> +{
> + if (!dev->raw_blk_ops.write_blk)
> + return -ENODEV;
> +
> + return dev->raw_blk_ops.write_blk(dev, addr, buf, size); }
> +
> +static u32
> +pmci_get_write_space(struct intel_max10_device *dev, u32 size) {
> + u32 count, val;
> + int ret;
> +
> + ret = opae_readl_poll_timeout(dev->mmio + PMCI_FLASH_CTRL, val,
> + GET_FIELD(PMCI_FLASH_FIFO_SPACE, val) ==
> + PMCI_FIFO_MAX_WORDS,
> + PMCI_FLASH_INT_US,
> PMCI_FLASH_TIMEOUT_US);
> + if (ret == -ETIMEDOUT)
> + return 0;
> +
> + count = GET_FIELD(PMCI_FLASH_FIFO_SPACE, val) * 4;
> +
> + return (size > count) ? count : size;
> +}
> +
> +static void pmci_write_fifo(void __iomem *base, char *buf, size_t
> +count) {
> + size_t i;
> + u32 val;
> +
> + for (i = 0; i < count/4 ; i++) {
> + val = *(u32 *)(buf + i * 4);
> + writel(val, base);
> + }
> +}
> +
> +static void pmci_read_fifo(void __iomem *base, char *buf, size_t count)
> +{
> + size_t i;
> + u32 val;
> +
> + for (i = 0; i < count/4; i++) {
> + val = readl(base);
> + *(u32 *)(buf + i * 4) = val;
> + }
> +}
> +
> +static int
> +__pmci_flash_bulk_write(struct intel_max10_device *dev, u32 addr,
> + void *buf, u32 size)
> +{
> + UNUSED(addr);
> + u32 blk_size, n_offset = 0;
> +
> + while (size) {
> + blk_size = pmci_get_write_space(dev, size);
> + if (blk_size == 0) {
> + dev_err(pmci->dev, "get FIFO available size fail\n");
> + return -EIO;
> + }
> + size -= blk_size;
> + pmci_write_fifo(dev->mmio + PMCI_FLASH_FIFO, (char *)buf +
> n_offset,
> + blk_size);
> + n_offset += blk_size;
> + }
> +
> + return 0;
> +}
> +
> +static int
> +pmci_flash_bulk_write(struct intel_max10_device *dev, u32 addr,
> + void *buf, u32 size)
> +{
> + int ret;
> +
> + pthread_mutex_lock(dev->bmc_ops.mutex);
> +
> + ret = __pmci_flash_bulk_write(dev, addr, buf, size);
> +
> + pthread_mutex_unlock(dev->bmc_ops.mutex);
> + return ret;
> +}
> +
> +static int
> +pmci_set_flash_host_mux(struct intel_max10_device *dev, bool request) {
> + u32 ctrl;
> + int ret;
> +
> + ret = max10_sys_update_bits(dev,
> + m10bmc_base(dev) + M10BMC_PMCI_FLASH_CTRL,
> + FLASH_HOST_REQUEST,
> + SET_FIELD(FLASH_HOST_REQUEST, request));
> + if (ret)
> + return ret;
> +
> + return opae_max10_read_poll_timeout(dev, m10bmc_base(dev) +
> M10BMC_PMCI_FLASH_CTRL,
> + ctrl, request ? (get_flash_mux(ctrl) ==
> FLASH_MUX_HOST) :
> + (get_flash_mux(ctrl) != FLASH_MUX_HOST),
> + PMCI_FLASH_INT_US, PMCI_FLASH_TIMEOUT_US); }
> +
> +static int
> +pmci_get_mux(struct intel_max10_device *dev) {
> + pthread_mutex_lock(dev->bmc_ops.mutex);
> + return pmci_set_flash_host_mux(dev, true); }
> +
> +static int
> +pmci_put_mux(struct intel_max10_device *dev) {
> + int ret;
> +
> + ret = pmci_set_flash_host_mux(dev, false);
> + pthread_mutex_unlock(dev->bmc_ops.mutex);
> + return ret;
> +}
> +
> +static int
> +__pmci_flash_bulk_read(struct intel_max10_device *dev, u32 addr,
> + void *buf, u32 size)
> +{
> + u32 blk_size, offset = 0, val;
> + int ret;
> +
> + while (size) {
> + blk_size = min_t(u32, size, PMCI_READ_BLOCK_SIZE);
> +
> + opae_writel(addr + offset, dev->mmio + PMCI_FLASH_ADDR);
> +
> + opae_writel(SET_FIELD(PMCI_FLASH_READ_COUNT, blk_size /
> 4)
> + | PMCI_FLASH_RD_MODE,
> + dev->mmio + PMCI_FLASH_CTRL);
> +
> + ret = opae_readl_poll_timeout((dev->mmio +
> PMCI_FLASH_CTRL),
> + val, !(val & PMCI_FLASH_BUSY),
> + PMCI_FLASH_INT_US,
> + PMCI_FLASH_TIMEOUT_US);
> + if (ret) {
> + dev_err(dev, "%s timed out on reading flash 0x%xn",
> + __func__, val);
> + return ret;
> + }
> +
> + pmci_read_fifo(dev->mmio + PMCI_FLASH_FIFO, (char *)buf +
> offset,
> + blk_size);
> +
> + size -= blk_size;
> + offset += blk_size;
> +
> + opae_writel(0, dev->mmio + PMCI_FLASH_CTRL);
> + }
> +
> + return 0;
> +}
> +
> +static int
> +pmci_flash_bulk_read(struct intel_max10_device *dev, u32 addr,
> + void *buf, u32 size)
> +{
> + int ret;
> +
> + ret = pmci_get_mux(dev);
> + if (ret)
> + goto fail;
> +
> + ret = __pmci_flash_bulk_read(dev, addr, buf, size);
> + if (ret)
> + goto fail;
> +
> + return pmci_put_mux(dev);
> +
> +fail:
> + pmci_put_mux(dev);
> + return ret;
> +}
> +
> +static int pmci_check_flash_address(u32 start, u32 end) {
> + if (start < PMCI_FLASH_START || end > PMCI_FLASH_END)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +int opae_read_flash(struct intel_max10_device *dev, u32 addr,
> + u32 size, void *buf)
> +{
> + int ret;
> +
> + if (!dev->bmc_ops.flash_read)
> + return -ENODEV;
> +
> + if (!buf)
> + return -EINVAL;
> +
> + if (dev->bmc_ops.check_flash_range) {
> + ret = dev->bmc_ops.check_flash_range(addr, addr + size);
> + if (ret)
> + return ret;
> + } else {
> + u32 top_addr = dev->staging_area_base + dev-
> >staging_area_size;
> + if ((addr < dev->staging_area_base) ||
> + ((addr + size) >= top_addr))
> + return -EINVAL;
> + }
> +
> + ret = dev->bmc_ops.flash_read(dev, addr, buf, size);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +
> static int max10_spi_read(struct intel_max10_device *dev,
> unsigned int addr, unsigned int *val)
> {
> @@ -841,6 +1114,11 @@ int max10_get_bmcfw_version(struct
> intel_max10_device *dev, unsigned int *val)
> dev->ops = &m10bmc_n3000_regmap;
> dev->csr = &m10bmc_spi_csr;
>
> + dev->raw_blk_ops.write_blk = n3000_bulk_raw_write;
> + dev->raw_blk_ops.read_blk = n3000_bulk_raw_read;
> + dev->bmc_ops.flash_read = n3000_flash_read;
> + dev->bmc_ops.flash_write = n3000_flash_write;
> +
> /* check the max10 version */
> ret = check_max10_version(dev);
> if (ret) {
> @@ -871,6 +1149,10 @@ int max10_get_bmcfw_version(struct
> intel_max10_device *dev, unsigned int *val)
> dev->staging_area_size = MAX_STAGING_AREA_SIZE;
> dev->flags |= MAX10_FLAGS_SECURE;
>
> + dev->bmc_ops.flash_read = pmci_flash_bulk_read;
> + dev->bmc_ops.flash_write = pmci_flash_bulk_write;
> + dev->bmc_ops.check_flash_range = pmci_check_flash_address;
> +
> ret = pthread_mutex_init(&dev->bmc_ops.lock, NULL);
> if (ret)
> return ret;
> diff --git a/drivers/raw/ifpga/base/opae_intel_max10.h
> b/drivers/raw/ifpga/base/opae_intel_max10.h
> index 6a1b122..0f3360e 100644
> --- a/drivers/raw/ifpga/base/opae_intel_max10.h
> +++ b/drivers/raw/ifpga/base/opae_intel_max10.h
> @@ -62,9 +62,22 @@ struct m10bmc_csr {
> };
>
> /**
> + * struct flash_raw_blk_ops - device specific operations for flash R/W
> + * @write_blk: write a block of data to flash
> + * @read_blk: read a block of data from flash */ struct
> +flash_raw_blk_ops {
> + int (*write_blk)(struct intel_max10_device *dev, uint32_t addr,
> + void *buf, uint32_t size);
> + int (*read_blk)(struct intel_max10_device *dev, uint32_t addr,
> + void *buf, uint32_t size);
> +};
> +
> +/**
> * struct m10bmc_ops - device specific operations
> * @lock: prevent concurrent flash read/write
> * @mutex: prevent concurrent bmc read/write
> + * @check_flash_range: validate flash address
> * @flash_read: read a block of data from flash
> * @flash_write: write a block of data to flash
> */
> @@ -92,6 +105,7 @@ struct intel_max10_device {
> enum m10bmc_type type;
> const struct m10bmc_regmap *ops;
> const struct m10bmc_csr *csr;
> + struct flash_raw_blk_ops raw_blk_ops;
> struct m10bmc_ops bmc_ops;
> u8 *mmio; /* mmio address for PMCI */
> };
> @@ -431,6 +445,22 @@ struct opae_sensor_info { #define
> PMCI_FPGA_RECONF_PAGE GENMASK(22, 20)
> #define PMCI_FPGA_RP_LOAD BIT(23)
>
> +#define PMCI_FLASH_CTRL 0x40
> +#define PMCI_FLASH_WR_MODE BIT(0)
> +#define PMCI_FLASH_RD_MODE BIT(1)
> +#define PMCI_FLASH_BUSY BIT(2)
> +#define PMCI_FLASH_FIFO_SPACE GENMASK(13, 4) #define
> +PMCI_FLASH_READ_COUNT GENMASK(25, 16)
> +
> +#define PMCI_FLASH_INT_US 1
> +#define PMCI_FLASH_TIMEOUT_US 10000
> +
> +#define PMCI_FLASH_ADDR 0x44
> +#define PMCI_FLASH_FIFO 0x800
> +#define PMCI_READ_BLOCK_SIZE 0x800
> +#define PMCI_FIFO_MAX_BYTES 0x800
> +#define PMCI_FIFO_MAX_WORDS (PMCI_FIFO_MAX_BYTES / 4)
> +
> #define M10BMC_PMCI_FPGA_POC 0xb0
> #define PMCI_FPGA_POC BIT(0)
> #define PMCI_NIOS_REQ_CLEAR BIT(1)
> @@ -447,6 +477,16 @@ struct opae_sensor_info { #define
> PMCI_FPGA_BOOT_PAGE GENMASK(2, 0) #define PMCI_FPGA_CONFIGURED
> BIT(3)
>
> +#define M10BMC_PMCI_FLASH_CTRL 0x1d0
> +#define FLASH_MUX_SELECTION GENMASK(2, 0) #define FLASH_MUX_IDLE 0
> +#define FLASH_MUX_NIOS 1 #define FLASH_MUX_HOST 2 #define
> FLASH_MUX_PFL
> +4 #define get_flash_mux(mux) GET_FIELD(FLASH_MUX_SELECTION, mux)
> +#define FLASH_NIOS_REQUEST BIT(4) #define FLASH_HOST_REQUEST BIT(5)
> +
> #define M10BMC_PMCI_SDM_CTRL_STS 0x230
> #define PMCI_SDM_IMG_REQ BIT(0)
> #define PMCI_SDM_STAT GENMASK(23, 16)
> @@ -472,4 +512,10 @@ struct opae_sensor_info {
> #define SDM_STAT_CS_MIS 0x12
> #define SDM_STAT_PR_MIS 0x13
> #define SDM_STAT_MAX SDM_STAT_PR_MIS
> +
> +#define PMCI_FLASH_START 0x10000
> +#define PMCI_FLASH_END 0xC7FFFFF
> +
> +int opae_read_flash(struct intel_max10_device *dev, u32 addr,
> + u32 size, void *buf);
> #endif
> diff --git a/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h
> b/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h
> index 3ff49a8..68499e6 100644
> --- a/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h
> +++ b/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h
> @@ -39,6 +39,16 @@
> #define min(a, b) RTE_MIN(a, b)
> #define max(a, b) RTE_MAX(a, b)
>
> +#define min_t(type, x, y) ({ \
> + type __min1 = (x); \
> + type __min2 = (y); \
> + __min1 < __min2 ? __min1 : __min2; })
> +
> +#define max_t(type, x, y) ({ \
> + type __max1 = (x); \
> + type __max2 = (y); \
> + __max1 > __max2 ? __max1 : __max2; })
> +
> #define spinlock_t rte_spinlock_t
> #define spinlock_init(x) rte_spinlock_init(x) #define spinlock_lock(x)
> rte_spinlock_lock(x)
> --
> 1.8.3.1
It looks good for me.
Acked-by: Tianfei Zhang <tianfei.zh...@intel.com>