+
+#define NSPU_NFP_BUF(addr, base, off) \
+ (*(uint64_t *)((uint8_t *)(addr)->mem_base + ((base) | (off))))
+
+#define NSPU_HOST_BUF(base, off) (*(uint64_t *)((uint8_t *)(base) + (off)))
+
+static int
+nspu_buff_write(nspu_desc_t *desc, void *buffer, size_t size)
+{
+ uint64_t pcie_offset, pcie_window_base, pcie_window_offset;
+ uint64_t windowsz = desc->windowsz;
+ uint64_t buffaddr, j, i = 0;
+ int ret = 0;
+
+ if (size > desc->buf_size)
+ return -1;
+
+ buffaddr = desc->bufaddr;
+ windowsz = desc->windowsz;
+
+ while (i < size) {
+ /* Expansion bar reconfiguration per window size */
+ nspu_xlate(desc, buffaddr + i, &pcie_offset);
+ pcie_window_base = pcie_offset & (~(windowsz - 1));
+ pcie_window_offset = pcie_offset & (windowsz - 1);
+ for (j = pcie_window_offset; ((j < windowsz) && (i < size));
+ j += 8) {
+ NSPU_NFP_BUF(desc, pcie_window_base, j) =
+ NSPU_HOST_BUF(buffer, i);
+ i += 8;
+ }
+ }
+
+ return ret;
+}
+
+static int
+nspu_buff_read(nspu_desc_t *desc, void *buffer, size_t size)
+{
+ uint64_t pcie_offset, pcie_window_base, pcie_window_offset;
+ uint64_t windowsz, i = 0, j;
+ uint64_t buffaddr;
+ int ret = 0;
+
+ if (size > desc->buf_size)
+ return -1;
+
+ buffaddr = desc->bufaddr;
+ windowsz = desc->windowsz;
+
+ while (i < size) {
+ /* Expansion bar reconfiguration per window size */
+ nspu_xlate(desc, buffaddr + i, &pcie_offset);
+ pcie_window_base = pcie_offset & (~(windowsz - 1));
+ pcie_window_offset = pcie_offset & (windowsz - 1);
+ for (j = pcie_window_offset; ((j < windowsz) && (i < size));
+ j += 8) {
+ NSPU_HOST_BUF(buffer, i) =
+ NSPU_NFP_BUF(desc, pcie_window_base, j);
+ i += 8;
+ }
+ }
+
+ return ret;
+}
+
+static int
+nspu_command(nspu_desc_t *desc, uint16_t cmd, int read, int write,
+ void *buffer, size_t rsize, size_t wsize)
+{
+ uint64_t status, cmd_reg;
+ uint64_t offset;
+ int retry = 0;
+ int retries = 120;
+ int ret = 0;
+
+ /* Same expansion BAR is used for different things */
+ nspu_xlate(desc, NSP_BASE, &offset);
+
+ status = NSP_REG_VAL(NSP_REG_ADDR(desc, offset, NSP_STATUS));
+
+ while ((status & 0x1) && (retry < retries)) {
+ status = NSP_REG_VAL(NSP_REG_ADDR(desc, offset, NSP_STATUS));
+ retry++;
+ sleep(1);
+ }
+
+ if (retry == retries)
+ return -1;
+
+ if (write) {
+ ret = nspu_buff_write(desc, buffer, wsize);
+ if (ret)
+ return ret;
+
+ /* Expansion BAR changes when writing the buffer */
+ nspu_xlate(desc, NSP_BASE, &offset);
+ }
+
+ NSP_REG_VAL(NSP_REG_ADDR(desc, offset, NSP_COMMAND)) =
+ (uint64_t)wsize << 32 | (uint64_t)cmd << 16 | 1;
+
+ retry = 0;
+
+ cmd_reg = NSP_REG_VAL(NSP_REG_ADDR(desc, offset, NSP_COMMAND));
+ while ((cmd_reg & 0x1) && (retry < retries)) {
+ cmd_reg = NSP_REG_VAL(NSP_REG_ADDR(desc, offset, NSP_COMMAND));
+ retry++;
+ sleep(1);
+ }
+ if (retry == retries)
+ return -1;
+
+ retry = 0;
+ status = NSP_REG_VAL(NSP_REG_ADDR(desc, offset, NSP_STATUS));
+ while ((status & 0x1) && (retry < retries)) {
+ status = NSP_REG_VAL(NSP_REG_ADDR(desc, offset, NSP_STATUS));
+ retry++;
+ sleep(1);
+ }
+
+ if (retry == retries)
+ return -1;
+
+ ret = status & (0xff << 8);
+ if (ret)
+ return ret;
+
+ if (read) {
+ ret = nspu_buff_read(desc, buffer, rsize);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+int
+nfp_fw_reset(nspu_desc_t *nspu_desc)
+{
+ int res;
+
+ res = nspu_command(nspu_desc, NSP_CMD_RESET, 0, 0, 0, 0, 0);
+
+ if (res < 0)
+ RTE_LOG(INFO, PMD, "fw reset failed: error %d", res);
+
+ return res;
+}