From a0906012699dded6ca1525c30ba86738f90587a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Sat, 22 Aug 2026 16:05:35 +0200 Subject: [PATCH 1/6] fpga: dfl: Drop #include for MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit None of the c files that #include drivers/fpga/dfl.h (either directly or via drivers/fpga/dfl-afu.h) actually need . There is drivers/fpga/dfl-pci.c using pci_device_id, which is provided by and drivers/fpga/dfl.c using dfl_device_id which is already provided by . No other structs traditionally defined in are used by these drivers. So the #include can just be dropped. Signed-off-by: Uwe Kleine-König (The Capable Hub) Reviewed-by: Xu Yilun Link: https://lore.kernel.org/r/799c3ffa64d758ffb74f84da492d978a517ff1ba.1787407491.git.ukleinek@kernel.org Signed-off-by: Xu Yilun --- drivers/fpga/dfl.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/fpga/dfl.h b/drivers/fpga/dfl.h index 9549f63b00eb..9a65617bb870 100644 --- a/drivers/fpga/dfl.h +++ b/drivers/fpga/dfl.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include From 4e3ca7189455e17295fc7c4966c18379dea786a1 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Wed, 9 Sep 2026 13:21:54 +0200 Subject: [PATCH 2/6] fpga: xilinx-selectmap: control CSI_B and RDWR_B during configuration The driver requests the optional CSI_B and RDWR_B GPIOs with GPIOD_OUT_HIGH and never touches them again. That flag carries a logical value, so both signals end up asserted from probe on, whatever polarity the device tree states, and they stay asserted for the lifetime of the device. Neither signal belongs to the driver's lifetime. CSI_B (Chip Select) selects the device on the SelectMAP port, RDWR_B (Read/Write) selects the transfer direction, so both belong to the data transfer. A device that is never deselected never lets go of the port, and a port pinned to write mode cannot be read back. Keep the two descriptors in the driver private data, request them deasserted, and assert them only around the configuration data transfer. RDWR_B is asserted first, UG470 describes in chapter "SelectMAP ABORT" that changing it while the device is selected aborts the configuration on the next CCLK. Signed-off-by: Heiko Schocher Reviewed-by: Xu Yilun Link: https://lore.kernel.org/r/20260909112200.13256-1-hs@nabladev.com Signed-off-by: Xu Yilun --- drivers/fpga/xilinx-selectmap.c | 39 +++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/drivers/fpga/xilinx-selectmap.c b/drivers/fpga/xilinx-selectmap.c index d0cbb5fdfe3a..ff167b23fded 100644 --- a/drivers/fpga/xilinx-selectmap.c +++ b/drivers/fpga/xilinx-selectmap.c @@ -19,6 +19,8 @@ struct xilinx_selectmap_conf { struct xilinx_fpga_core core; void __iomem *base; + struct gpio_desc *csi_b; + struct gpio_desc *rdwr_b; }; #define to_xilinx_selectmap_conf(obj) \ @@ -30,16 +32,28 @@ static int xilinx_selectmap_write(struct xilinx_fpga_core *core, struct xilinx_selectmap_conf *conf = to_xilinx_selectmap_conf(core); size_t i; + /* + * Select this device and put its SelectMAP port into write mode. + * + * RDWR_B is set before CSI_B. UG470 describes in chapter + * "SelectMAP ABORT" that changing RDWR_B while the device is + * selected aborts the configuration on the next CCLK. + */ + gpiod_set_value(conf->rdwr_b, 1); + gpiod_set_value(conf->csi_b, 1); + for (i = 0; i < count; ++i) writeb(buf[i], conf->base); + gpiod_set_value(conf->csi_b, 0); + gpiod_set_value(conf->rdwr_b, 0); + return 0; } static int xilinx_selectmap_probe(struct platform_device *pdev) { struct xilinx_selectmap_conf *conf; - struct gpio_desc *gpio; void __iomem *base; conf = devm_kzalloc(&pdev->dev, sizeof(*conf), GFP_KERNEL); @@ -55,16 +69,23 @@ static int xilinx_selectmap_probe(struct platform_device *pdev) "ioremap error\n"); conf->base = base; - /* CSI_B is active low */ - gpio = devm_gpiod_get_optional(&pdev->dev, "csi", GPIOD_OUT_HIGH); - if (IS_ERR(gpio)) - return dev_err_probe(&pdev->dev, PTR_ERR(gpio), + /* + * Request both signals deasserted, so a device sharing the SelectMAP + * bus with others stays off that bus until its bitstream is written. + * + * The value in the gpiod flags is logical, gpiolib drives the line + * high for GPIOD_OUT_LOW when the firmware describes it active low. + */ + conf->csi_b = devm_gpiod_get_optional(&pdev->dev, "csi", + GPIOD_OUT_LOW); + if (IS_ERR(conf->csi_b)) + return dev_err_probe(&pdev->dev, PTR_ERR(conf->csi_b), "Failed to get CSI_B gpio\n"); - /* RDWR_B is active low */ - gpio = devm_gpiod_get_optional(&pdev->dev, "rdwr", GPIOD_OUT_HIGH); - if (IS_ERR(gpio)) - return dev_err_probe(&pdev->dev, PTR_ERR(gpio), + conf->rdwr_b = devm_gpiod_get_optional(&pdev->dev, "rdwr", + GPIOD_OUT_LOW); + if (IS_ERR(conf->rdwr_b)) + return dev_err_probe(&pdev->dev, PTR_ERR(conf->rdwr_b), "Failed to get RDWR_B gpio\n"); return xilinx_core_probe(&conf->core); From 00bef46869c047278f25149f4c4ee716de13f368 Mon Sep 17 00:00:00 2001 From: Hemanth Selam Date: Thu, 10 Sep 2026 10:15:45 +0530 Subject: [PATCH 3/6] fpga: fix typo in s10_ops_write() comment The comment reads "reuse it to send more data or free if if all data has been sent". The first "if" is not a repetition, it should be "it", to match the "reuse it" earlier in the same sentence. Only touches a comment, no code changes. Assisted-by: Cursor:claude-opus-5 Signed-off-by: Hemanth Selam Reviewed-by: Xu Yilun Link: https://lore.kernel.org/r/20260910044545.50261-1-hemanth.selam@gmail.com Signed-off-by: Xu Yilun --- drivers/fpga/stratix10-soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/fpga/stratix10-soc.c b/drivers/fpga/stratix10-soc.c index b8ec2e6f615f..5aed560050c2 100644 --- a/drivers/fpga/stratix10-soc.c +++ b/drivers/fpga/stratix10-soc.c @@ -286,7 +286,7 @@ static int s10_ops_write(struct fpga_manager *mgr, const char *buf, /* * Loop waiting for buffers to be returned. When a buffer is returned, - * reuse it to send more data or free if if all data has been sent. + * reuse it to send more data or free it if all data has been sent. */ while (count > 0 || s10_free_buffer_count(mgr) != NUM_SVC_BUFS) { reinit_completion(&priv->status_return_completion); From ac02245b0ca28388ba16273f2fa683c90da2e5dc Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Sat, 12 Sep 2026 12:09:37 +0200 Subject: [PATCH 4/6] fpga: Fix of_fpga_mgr_get() reference in fpga_mgr_lock() docs The fpga_mgr_lock() comment lists of_fpga_mgr_put() as a source of a manager pointer. The helper which obtains that pointer is of_fpga_mgr_get(). Correct the reference. Fixes: ebf877a51ad7 ("fpga: mgr: separate getting/locking FPGA manager") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Karl Mehltretter Reviewed-by: Xu Yilun Link: https://lore.kernel.org/r/20260912100937.86316-1-kmehltretter@gmail.com Signed-off-by: Xu Yilun --- drivers/fpga/fpga-mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index 2672070ced02..5a0b7780b335 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -744,7 +744,7 @@ EXPORT_SYMBOL_GPL(fpga_mgr_put); * @mgr: fpga manager * * Given a pointer to FPGA Manager (from fpga_mgr_get() or - * of_fpga_mgr_put()) attempt to get the mutex. The user should call + * of_fpga_mgr_get()) attempt to get the mutex. The user should call * fpga_mgr_lock() and verify that it returns 0 before attempting to * program the FPGA. Likewise, the user should call fpga_mgr_unlock * when done programming the FPGA. From 0dcfad56e527a0816f77b94d17ebf98130f1ae21 Mon Sep 17 00:00:00 2001 From: Nazim Amirul Date: Tue, 22 Sep 2026 22:32:32 -0700 Subject: [PATCH 5/6] fpga: altera-cvp: Add helper to disable CvP mode Factor out the clearing of CVP_MODE and HIP_CLK_SEL in VSE_CVP_MODE_CTRL into altera_cvp_disable_cvp_mode() and use it for STEP 17 in altera_cvp_write_complete(). No functional change. This prepares for reusing the helper in the teardown recovery path. Signed-off-by: Nazim Amirul Reviewed-by: Xu Yilun Link: https://lore.kernel.org/r/20260923053233.10890-2-muhammad.nazim.amirul.nazle.asmade@altera.com Signed-off-by: Xu Yilun --- drivers/fpga/altera-cvp.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c index 070c025ee215..99aa078e94cf 100644 --- a/drivers/fpga/altera-cvp.c +++ b/drivers/fpga/altera-cvp.c @@ -280,6 +280,16 @@ static int altera_cvp_send_block(struct altera_cvp_conf *conf, return 0; } +static void altera_cvp_disable_cvp_mode(struct altera_cvp_conf *conf) +{ + u32 val; + + altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val); + val &= ~VSE_CVP_MODE_CTRL_HIP_CLK_SEL; + val &= ~VSE_CVP_MODE_CTRL_CVP_MODE; + altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val); +} + static int altera_cvp_teardown(struct fpga_manager *mgr, struct fpga_image_info *info) { @@ -498,10 +508,7 @@ static int altera_cvp_write_complete(struct fpga_manager *mgr, } /* STEP 17 - reset CVP_MODE and HIP_CLK_SEL bit */ - altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val); - val &= ~VSE_CVP_MODE_CTRL_HIP_CLK_SEL; - val &= ~VSE_CVP_MODE_CTRL_CVP_MODE; - altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val); + altera_cvp_disable_cvp_mode(conf); /* STEP 18 - poll PLD_CLK_IN_USE and USER_MODE bits */ mask = VSE_CVP_STATUS_PLD_CLK_IN_USE | VSE_CVP_STATUS_USERMODE; From 093da48782df3d50953c520626b345ca70af8cbd Mon Sep 17 00:00:00 2001 From: Nazim Amirul Date: Tue, 22 Sep 2026 22:32:33 -0700 Subject: [PATCH 6/6] fpga: altera-cvp: Retry teardown and reset CVP state on failure The driver polls CFG_RDY for 0 as notification that the endpoint has finished teardown and a new session can start safely. After a bad bitstream that poll can time out: CFG_RDY may stay stuck when HIP_CLK_SEL=0 if the device has already left usermode before the poll. Retrying teardown alone is not enough. Exit CvP mode and switch the HIP clock that feeds CFG_RDY so CVP_STATUS becomes responsive again, then try the teardown once more. Introduce altera_cvp_recovery() to wrap this cleanup and single retry. Signed-off-by: Nazim Amirul Reviewed-by: Xu Yilun Link: https://lore.kernel.org/r/20260923053233.10890-3-muhammad.nazim.amirul.nazle.asmade@altera.com Signed-off-by: Xu Yilun --- drivers/fpga/altera-cvp.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c index 99aa078e94cf..507e29d3a79f 100644 --- a/drivers/fpga/altera-cvp.c +++ b/drivers/fpga/altera-cvp.c @@ -318,7 +318,29 @@ static int altera_cvp_teardown(struct fpga_manager *mgr, ret = altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, 0, conf->priv->poll_time_us); if (ret) - dev_err(&mgr->dev, "CFG_RDY == 0 timeout\n"); + dev_warn(&mgr->dev, "CFG_RDY == 0 timeout\n"); + + return ret; +} + +static int altera_cvp_recovery(struct fpga_manager *mgr, + struct fpga_image_info *info) +{ + struct altera_cvp_conf *conf = mgr->priv; + int ret; + + ret = altera_cvp_teardown(mgr, info); + if (ret) { + /* + * CVP_STATUS may get stuck if the device left user mode + * before the poll. Exit CvP mode to switch back the clock + * feeding CVP_STATUS, then try the teardown again. + */ + altera_cvp_disable_cvp_mode(conf); + ret = altera_cvp_teardown(mgr, info); + if (ret) + dev_err(&mgr->dev, "Tear-down failed\n"); + } return ret; } @@ -355,7 +377,7 @@ static int altera_cvp_write_init(struct fpga_manager *mgr, if (val & VSE_CVP_STATUS_CFG_RDY) { dev_warn(&mgr->dev, "CvP already started, tear down first\n"); - ret = altera_cvp_teardown(mgr, info); + ret = altera_cvp_recovery(mgr, info); if (ret) return ret; } @@ -496,7 +518,7 @@ static int altera_cvp_write_complete(struct fpga_manager *mgr, u32 mask, val; int ret; - ret = altera_cvp_teardown(mgr, info); + ret = altera_cvp_recovery(mgr, info); if (ret) return ret;