Re: [PATCH V4 XRT Alveo 14/20] fpga: xrt: ICAP platform driver

2021-04-06 Thread Lizhi Hou

Hi Tom,


On 04/06/2021 06:50 AM, Tom Rix wrote:



On 3/23/21 10:29 PM, Lizhi Hou wrote:

ICAP stands for Hardware Internal Configuration Access Port. ICAP is
discovered by walking firmware metadata. A platform device node will be

by walking the firmware

Sure.

created for it. FPGA bitstream is written to hardware through ICAP.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
  drivers/fpga/xrt/include/xleaf/icap.h |  27 ++
  drivers/fpga/xrt/lib/xleaf/icap.c | 344 ++
  2 files changed, 371 insertions(+)
  create mode 100644 drivers/fpga/xrt/include/xleaf/icap.h
  create mode 100644 drivers/fpga/xrt/lib/xleaf/icap.c

diff --git a/drivers/fpga/xrt/include/xleaf/icap.h 
b/drivers/fpga/xrt/include/xleaf/icap.h

new file mode 100644
index ..96d39a8934fa
--- /dev/null
+++ b/drivers/fpga/xrt/include/xleaf/icap.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *   Lizhi Hou 
+ */
+
+#ifndef _XRT_ICAP_H_
+#define _XRT_ICAP_H_
+
+#include "xleaf.h"
+
+/*
+ * ICAP driver leaf calls.
+ */
+enum xrt_icap_leaf_cmd {
+ XRT_ICAP_WRITE = XRT_XLEAF_CUSTOM_BASE, /* See comments in 
xleaf.h */

+ XRT_ICAP_GET_IDCODE,

ok

+};
+
+struct xrt_icap_wr {
+ void*xiiw_bit_data;
+ u32 xiiw_data_len;
+};
+
+#endif   /* _XRT_ICAP_H_ */
diff --git a/drivers/fpga/xrt/lib/xleaf/icap.c 
b/drivers/fpga/xrt/lib/xleaf/icap.c

new file mode 100644
index ..13db2b759138
--- /dev/null
+++ b/drivers/fpga/xrt/lib/xleaf/icap.c
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo FPGA ICAP Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *  Lizhi Hou
+ *  Sonal Santan 
+ *  Max Zhen 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "metadata.h"
+#include "xleaf.h"
+#include "xleaf/icap.h"
+#include "xclbin-helper.h"
+
+#define XRT_ICAP "xrt_icap"
+
+#define ICAP_ERR(icap, fmt, arg...)  \
+ xrt_err((icap)->pdev, fmt "\n", ##arg)
+#define ICAP_WARN(icap, fmt, arg...) \
+ xrt_warn((icap)->pdev, fmt "\n", ##arg)
+#define ICAP_INFO(icap, fmt, arg...) \
+ xrt_info((icap)->pdev, fmt "\n", ##arg)
+#define ICAP_DBG(icap, fmt, arg...)  \
+ xrt_dbg((icap)->pdev, fmt "\n", ##arg)
+
+/*
+ * AXI-HWICAP IP register layout. Please see
+ * 
https://www.xilinx.com/support/documentation/ip_documentation/axi_hwicap/v3_0/pg134-axi-hwicap.pdf

url works, looks good

+ */
+#define ICAP_REG_GIER0x1C
+#define ICAP_REG_ISR 0x20
+#define ICAP_REG_IER 0x28
+#define ICAP_REG_WF  0x100
+#define ICAP_REG_RF  0x104
+#define ICAP_REG_SZ  0x108
+#define ICAP_REG_CR  0x10C
+#define ICAP_REG_SR  0x110
+#define ICAP_REG_WFV 0x114
+#define ICAP_REG_RFO 0x118
+#define ICAP_REG_ASR 0x11C
+
+#define ICAP_STATUS_EOS  0x4
+#define ICAP_STATUS_DONE 0x1
+
+/*
+ * Canned command sequence to obtain IDCODE of the FPGA
+ */
+static const u32 idcode_stream[] = {
+ /* dummy word */
+ cpu_to_be32(0x),
+ /* sync word */
+ cpu_to_be32(0xaa995566),
+ /* NOP word */
+ cpu_to_be32(0x2000),
+ /* NOP word */
+ cpu_to_be32(0x2000),
+ /* ID code */
+ cpu_to_be32(0x28018001),
+ /* NOP word */
+ cpu_to_be32(0x2000),
+ /* NOP word */
+ cpu_to_be32(0x2000),
+};
+
+static const struct regmap_config icap_regmap_config = {

ok

+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 0x1000,
+};
+
+struct icap {
+ struct platform_device  *pdev;
+ struct regmap   *regmap;
+ struct mutexicap_lock; /* icap dev lock */
+

whitespace, remove extra nl

Sure.

Thanks,
Lizhi

+ u32 idcode;
+};
+
+static int wait_for_done(const struct icap *icap)
+{
+ int i = 0;
+ int ret;
+ u32 w;
+
+ for (i = 0; i < 10; i++) {
+ /*
+  * it requires few micro seconds for ICAP to process 
incoming data.

+  * Polling every 5us for 10 times would be good enough.

ok

+  */
+ udelay(5);
+ ret = regmap_read(icap->regmap, ICAP_REG_SR, );
+ if (ret)
+ return ret;
+ ICAP_INFO(icap, "XHWICAP_SR: %x", w);
+ if (w & (ICAP_STATUS_EOS | ICAP_STATUS_DONE))

ok

+ return 0;
+ }
+
+ ICAP_ERR(icap, "bitstream download timeout");
+ return -ETIMEDOUT;
+}
+
+static int icap_write(const struct icap *icap, const u32 *word_buf, 
int size)

+{
+ u32 value = 0;
+ int ret;
+ int i;
+
+ for (i = 0; i < size; i++) {
+ value = be32_to_cpu(word_buf[i]);
+ ret = regmap_write(icap->regmap, ICAP_REG_WF, value);
+ if (ret)
+ return ret;
+ }
+
+ ret = 

Re: [PATCH V4 XRT Alveo 14/20] fpga: xrt: ICAP platform driver

2021-04-06 Thread Tom Rix



On 3/23/21 10:29 PM, Lizhi Hou wrote:

ICAP stands for Hardware Internal Configuration Access Port. ICAP is
discovered by walking firmware metadata. A platform device node will be

by walking the firmware

created for it. FPGA bitstream is written to hardware through ICAP.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
  drivers/fpga/xrt/include/xleaf/icap.h |  27 ++
  drivers/fpga/xrt/lib/xleaf/icap.c | 344 ++
  2 files changed, 371 insertions(+)
  create mode 100644 drivers/fpga/xrt/include/xleaf/icap.h
  create mode 100644 drivers/fpga/xrt/lib/xleaf/icap.c

diff --git a/drivers/fpga/xrt/include/xleaf/icap.h 
b/drivers/fpga/xrt/include/xleaf/icap.h
new file mode 100644
index ..96d39a8934fa
--- /dev/null
+++ b/drivers/fpga/xrt/include/xleaf/icap.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Lizhi Hou 
+ */
+
+#ifndef _XRT_ICAP_H_
+#define _XRT_ICAP_H_
+
+#include "xleaf.h"
+
+/*
+ * ICAP driver leaf calls.
+ */
+enum xrt_icap_leaf_cmd {
+   XRT_ICAP_WRITE = XRT_XLEAF_CUSTOM_BASE, /* See comments in xleaf.h */
+   XRT_ICAP_GET_IDCODE,

ok

+};
+
+struct xrt_icap_wr {
+   void*xiiw_bit_data;
+   u32 xiiw_data_len;
+};
+
+#endif /* _XRT_ICAP_H_ */
diff --git a/drivers/fpga/xrt/lib/xleaf/icap.c 
b/drivers/fpga/xrt/lib/xleaf/icap.c
new file mode 100644
index ..13db2b759138
--- /dev/null
+++ b/drivers/fpga/xrt/lib/xleaf/icap.c
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo FPGA ICAP Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *  Lizhi Hou
+ *  Sonal Santan 
+ *  Max Zhen 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "metadata.h"
+#include "xleaf.h"
+#include "xleaf/icap.h"
+#include "xclbin-helper.h"
+
+#define XRT_ICAP "xrt_icap"
+
+#define ICAP_ERR(icap, fmt, arg...)\
+   xrt_err((icap)->pdev, fmt "\n", ##arg)
+#define ICAP_WARN(icap, fmt, arg...)   \
+   xrt_warn((icap)->pdev, fmt "\n", ##arg)
+#define ICAP_INFO(icap, fmt, arg...)   \
+   xrt_info((icap)->pdev, fmt "\n", ##arg)
+#define ICAP_DBG(icap, fmt, arg...)\
+   xrt_dbg((icap)->pdev, fmt "\n", ##arg)
+
+/*
+ * AXI-HWICAP IP register layout. Please see
+ * 
https://www.xilinx.com/support/documentation/ip_documentation/axi_hwicap/v3_0/pg134-axi-hwicap.pdf

url works, looks good

+ */
+#define ICAP_REG_GIER  0x1C
+#define ICAP_REG_ISR   0x20
+#define ICAP_REG_IER   0x28
+#define ICAP_REG_WF0x100
+#define ICAP_REG_RF0x104
+#define ICAP_REG_SZ0x108
+#define ICAP_REG_CR0x10C
+#define ICAP_REG_SR0x110
+#define ICAP_REG_WFV   0x114
+#define ICAP_REG_RFO   0x118
+#define ICAP_REG_ASR   0x11C
+
+#define ICAP_STATUS_EOS0x4
+#define ICAP_STATUS_DONE   0x1
+
+/*
+ * Canned command sequence to obtain IDCODE of the FPGA
+ */
+static const u32 idcode_stream[] = {
+   /* dummy word */
+   cpu_to_be32(0x),
+   /* sync word */
+   cpu_to_be32(0xaa995566),
+   /* NOP word */
+   cpu_to_be32(0x2000),
+   /* NOP word */
+   cpu_to_be32(0x2000),
+   /* ID code */
+   cpu_to_be32(0x28018001),
+   /* NOP word */
+   cpu_to_be32(0x2000),
+   /* NOP word */
+   cpu_to_be32(0x2000),
+};
+
+static const struct regmap_config icap_regmap_config = {

ok

+   .reg_bits = 32,
+   .val_bits = 32,
+   .reg_stride = 4,
+   .max_register = 0x1000,
+};
+
+struct icap {
+   struct platform_device  *pdev;
+   struct regmap   *regmap;
+   struct mutexicap_lock; /* icap dev lock */
+

whitespace, remove extra nl

+   u32 idcode;
+};
+
+static int wait_for_done(const struct icap *icap)
+{
+   int i = 0;
+   int ret;
+   u32 w;
+
+   for (i = 0; i < 10; i++) {
+   /*
+* it requires few micro seconds for ICAP to process incoming 
data.
+* Polling every 5us for 10 times would be good enough.

ok

+*/
+   udelay(5);
+   ret = regmap_read(icap->regmap, ICAP_REG_SR, );
+   if (ret)
+   return ret;
+   ICAP_INFO(icap, "XHWICAP_SR: %x", w);
+   if (w & (ICAP_STATUS_EOS | ICAP_STATUS_DONE))

ok

+   return 0;
+   }
+
+   ICAP_ERR(icap, "bitstream download timeout");
+   return -ETIMEDOUT;
+}
+
+static int icap_write(const struct icap *icap, const u32 *word_buf, int size)
+{
+   u32 value = 0;
+   int ret;
+   int i;
+
+   for (i = 0; i < size; i++) {
+   value = be32_to_cpu(word_buf[i]);
+   ret = regmap_write(icap->regmap, ICAP_REG_WF, value);
+   if (ret)
+   

[PATCH V4 XRT Alveo 14/20] fpga: xrt: ICAP platform driver

2021-03-23 Thread Lizhi Hou
ICAP stands for Hardware Internal Configuration Access Port. ICAP is
discovered by walking firmware metadata. A platform device node will be
created for it. FPGA bitstream is written to hardware through ICAP.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/include/xleaf/icap.h |  27 ++
 drivers/fpga/xrt/lib/xleaf/icap.c | 344 ++
 2 files changed, 371 insertions(+)
 create mode 100644 drivers/fpga/xrt/include/xleaf/icap.h
 create mode 100644 drivers/fpga/xrt/lib/xleaf/icap.c

diff --git a/drivers/fpga/xrt/include/xleaf/icap.h 
b/drivers/fpga/xrt/include/xleaf/icap.h
new file mode 100644
index ..96d39a8934fa
--- /dev/null
+++ b/drivers/fpga/xrt/include/xleaf/icap.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Lizhi Hou 
+ */
+
+#ifndef _XRT_ICAP_H_
+#define _XRT_ICAP_H_
+
+#include "xleaf.h"
+
+/*
+ * ICAP driver leaf calls.
+ */
+enum xrt_icap_leaf_cmd {
+   XRT_ICAP_WRITE = XRT_XLEAF_CUSTOM_BASE, /* See comments in xleaf.h */
+   XRT_ICAP_GET_IDCODE,
+};
+
+struct xrt_icap_wr {
+   void*xiiw_bit_data;
+   u32 xiiw_data_len;
+};
+
+#endif /* _XRT_ICAP_H_ */
diff --git a/drivers/fpga/xrt/lib/xleaf/icap.c 
b/drivers/fpga/xrt/lib/xleaf/icap.c
new file mode 100644
index ..13db2b759138
--- /dev/null
+++ b/drivers/fpga/xrt/lib/xleaf/icap.c
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo FPGA ICAP Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *  Lizhi Hou
+ *  Sonal Santan 
+ *  Max Zhen 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "metadata.h"
+#include "xleaf.h"
+#include "xleaf/icap.h"
+#include "xclbin-helper.h"
+
+#define XRT_ICAP "xrt_icap"
+
+#define ICAP_ERR(icap, fmt, arg...)\
+   xrt_err((icap)->pdev, fmt "\n", ##arg)
+#define ICAP_WARN(icap, fmt, arg...)   \
+   xrt_warn((icap)->pdev, fmt "\n", ##arg)
+#define ICAP_INFO(icap, fmt, arg...)   \
+   xrt_info((icap)->pdev, fmt "\n", ##arg)
+#define ICAP_DBG(icap, fmt, arg...)\
+   xrt_dbg((icap)->pdev, fmt "\n", ##arg)
+
+/*
+ * AXI-HWICAP IP register layout. Please see
+ * 
https://www.xilinx.com/support/documentation/ip_documentation/axi_hwicap/v3_0/pg134-axi-hwicap.pdf
+ */
+#define ICAP_REG_GIER  0x1C
+#define ICAP_REG_ISR   0x20
+#define ICAP_REG_IER   0x28
+#define ICAP_REG_WF0x100
+#define ICAP_REG_RF0x104
+#define ICAP_REG_SZ0x108
+#define ICAP_REG_CR0x10C
+#define ICAP_REG_SR0x110
+#define ICAP_REG_WFV   0x114
+#define ICAP_REG_RFO   0x118
+#define ICAP_REG_ASR   0x11C
+
+#define ICAP_STATUS_EOS0x4
+#define ICAP_STATUS_DONE   0x1
+
+/*
+ * Canned command sequence to obtain IDCODE of the FPGA
+ */
+static const u32 idcode_stream[] = {
+   /* dummy word */
+   cpu_to_be32(0x),
+   /* sync word */
+   cpu_to_be32(0xaa995566),
+   /* NOP word */
+   cpu_to_be32(0x2000),
+   /* NOP word */
+   cpu_to_be32(0x2000),
+   /* ID code */
+   cpu_to_be32(0x28018001),
+   /* NOP word */
+   cpu_to_be32(0x2000),
+   /* NOP word */
+   cpu_to_be32(0x2000),
+};
+
+static const struct regmap_config icap_regmap_config = {
+   .reg_bits = 32,
+   .val_bits = 32,
+   .reg_stride = 4,
+   .max_register = 0x1000,
+};
+
+struct icap {
+   struct platform_device  *pdev;
+   struct regmap   *regmap;
+   struct mutexicap_lock; /* icap dev lock */
+
+   u32 idcode;
+};
+
+static int wait_for_done(const struct icap *icap)
+{
+   int i = 0;
+   int ret;
+   u32 w;
+
+   for (i = 0; i < 10; i++) {
+   /*
+* it requires few micro seconds for ICAP to process incoming 
data.
+* Polling every 5us for 10 times would be good enough.
+*/
+   udelay(5);
+   ret = regmap_read(icap->regmap, ICAP_REG_SR, );
+   if (ret)
+   return ret;
+   ICAP_INFO(icap, "XHWICAP_SR: %x", w);
+   if (w & (ICAP_STATUS_EOS | ICAP_STATUS_DONE))
+   return 0;
+   }
+
+   ICAP_ERR(icap, "bitstream download timeout");
+   return -ETIMEDOUT;
+}
+
+static int icap_write(const struct icap *icap, const u32 *word_buf, int size)
+{
+   u32 value = 0;
+   int ret;
+   int i;
+
+   for (i = 0; i < size; i++) {
+   value = be32_to_cpu(word_buf[i]);
+   ret = regmap_write(icap->regmap, ICAP_REG_WF, value);
+   if (ret)
+   return ret;
+   }
+
+   ret = regmap_write(icap->regmap, ICAP_REG_CR, 0x1);
+   if (ret)
+   return ret;
+
+