From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 22115A0093; Fri, 17 Jun 2022 09:12:13 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 5CB3742B6E; Fri, 17 Jun 2022 09:11:56 +0200 (CEST) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mails.dpdk.org (Postfix) with ESMTP id 10DF24282A; Fri, 17 Jun 2022 09:11:53 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1655449914; x=1686985914; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=FX3awFiyyQtv2/ykeaiV6xg60TxhVthD3Fv7xfeDEFc=; b=LrZ1gNFsuVGLRuMuU0h5ChcmaEkjRHt+mRw0LXb115O21vbfGhroBXyd 7/4/9JyX4c5KlFBaDe13m6VPibtUUEW0GQaBD8vv+6ijG7QlH0NG9blbQ GWAAki6Z6y2xVi4J9f7yU08LIJ86fpwUc1UWlNZWgUlaoiKV3wmBQbiMI gAtC+LofOxV7hMwf79ujdNq2e013s/fhsEzgOI+iETAOmWS+hyCY9hHNF jeXQPf6MmwfMtqud4s17+shPNIJlq5/QdTa9bATzMXoufEqp+bqq0SkHZ zKu6B7EQmCd9+HWoCc7HqvFPmED0hy1NRbVoDUZIqbUDABrsIz/bIuXuz g==; X-IronPort-AV: E=McAfee;i="6400,9594,10380"; a="278236424" X-IronPort-AV: E=Sophos;i="5.92,306,1650956400"; d="scan'208";a="278236424" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2022 00:11:53 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,306,1650956400"; d="scan'208";a="912502496" Received: from unknown (HELO zj-fpga-amt.sh.intel.com) ([10.238.175.102]) by fmsmga005.fm.intel.com with ESMTP; 17 Jun 2022 00:11:51 -0700 From: Wei Huang To: dev@dpdk.org, thomas@monjalon.net, nipun.gupta@nxp.com, hemant.agrawal@nxp.com Cc: stable@dpdk.org, rosen.xu@intel.com, tianfei.zhang@intel.com, qi.z.zhang@intel.com, Wei Huang Subject: [PATCH v3 3/4] raw/ifpga/base: update flash operation interface Date: Fri, 17 Jun 2022 03:19:34 -0400 Message-Id: <1655450375-10739-4-git-send-email-wei.huang@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1655450375-10739-1-git-send-email-wei.huang@intel.com> References: <1654827900-10023-1-git-send-email-wei.huang@intel.com> <1655450375-10739-1-git-send-email-wei.huang@intel.com> X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org 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 --- 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