]> git.droids-corp.org - dpdk.git/commitdiff
raw/ifpga/base: update flash operation interface
authorWei Huang <wei.huang@intel.com>
Fri, 17 Jun 2022 07:19:34 +0000 (03:19 -0400)
committerThomas Monjalon <thomas@monjalon.net>
Mon, 20 Jun 2022 15:33:21 +0000 (17:33 +0200)
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.huang@intel.com>
Acked-by: Tianfei Zhang <tianfei.zhang@intel.com>
Reviewed-by: Rosen Xu <rosen.xu@intel.com>
drivers/raw/ifpga/base/ifpga_api.c
drivers/raw/ifpga/base/ifpga_feature_dev.h
drivers/raw/ifpga/base/ifpga_fme.c
drivers/raw/ifpga/base/opae_hw_api.c
drivers/raw/ifpga/base/opae_hw_api.h
drivers/raw/ifpga/base/opae_intel_max10.c
drivers/raw/ifpga/base/opae_intel_max10.h
drivers/raw/ifpga/base/osdep_rte/osdep_generic.h

index f19cc262a0ad30703eba7736b2742b1bb9c490a4..098de0c0904209580183ae3cc3b6f6a20941b80f 100644 (file)
@@ -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,
index a637eb59ef90f592a5ccfd54e431754718ca0823..7a2f2e581792bd7defee9d8258cd2a9cd5c172d4 100644 (file)
@@ -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_ */
index 608a3520a361803f868cb21dac7c2c1553cbb276..25ff819955f890e31b2c2031d254557361a10bfa 100644 (file)
@@ -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);
+}
index 87256fc8b2a137a500f0dd1fc09c309d223477b0..fd083263a856d5af44603ea46347285e9fbabaf9 100644 (file)
@@ -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;
+}
index fd40e09857a0a1f5ae0a4f841249a73cf700627b..de1e98468432af962df2c442fa0916f88b362ed3 100644 (file)
@@ -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_*/
index 26f323c6a1391691764648b6bdacdd23076c360e..9c017299139c732e3cde226e8c2f5065e8573485 100644 (file)
@@ -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 @@ intel_max10_device_init(struct intel_max10_device *dev)
                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 @@ intel_max10_device_init(struct intel_max10_device *dev)
                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;
index 6a1b122a26c8200cb97af985a6d54d8bf824f541..0f3360edb6fb99494c589a04cdaed48ae1e43bf6 100644 (file)
@@ -61,10 +61,23 @@ struct m10bmc_csr {
        unsigned int auth_result;
 };
 
+/**
+ * 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
index 3ff49a89264d33f69c0dfa7eac0887398d80d24c..68499e65fbcc28eea9d4ac9a8f28b4df4f77fb49 100644 (file)
 #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)