Hi, > -----Original Message----- > From: Huang, Wei <wei.hu...@intel.com> > Sent: Friday, June 17, 2022 15:20 > 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
Reviewed-by: Rosen Xu <rosen...@intel.com>