From patchwork Wed Feb 21 19:50:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Charles Perry X-Patchwork-Id: 204411 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:693c:2685:b0:108:e6aa:91d0 with SMTP id mn5csp1265812dyc; Wed, 21 Feb 2024 12:01:35 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCUX2sI7dnuPZzXtLws1r5M6ReXQMS6Q5lFwlu7YtA7zjzNiSwUrKVfB4QTubEd1OIF8JCfoVkJP26B77OjnKjy9575uZA== X-Google-Smtp-Source: AGHT+IFGknYr/6ldCBh6UorWL/doB4FFqEIqZsjJaDXGTNWvoZumdkNvTurm61YHX/VRaITlKC2P X-Received: by 2002:a05:6a00:290a:b0:6e4:77b3:71a with SMTP id cg10-20020a056a00290a00b006e477b3071amr7498855pfb.13.1708545694537; Wed, 21 Feb 2024 12:01:34 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708545694; cv=pass; d=google.com; s=arc-20160816; b=0LlbER1PSbPEUkpPiMlcLvH1Ge1XBhfP1GxXJZBGaUcPOtwWBjs6RmG7VNDi6PZzSL udvHg5403MdN81yjXff1Cw+MuYm9xjWYLThQk8GHaprL3xk1SeiIYB2hcoPe3fnIgh2r oMKpzHoJmWEyBkcJc7zzDmSy6G5lAv0yDfu8WK31xFQg86YDBGV9ijFu58EZN9MmDw/m 0hL/+a3oyhqCGHCyuqzgQczGO/CopvlwCk8NcF8iwch/Mow9EmQ9Z3PuGvp76X4jAEVO qzKRU00QKpH5YlzybMObaDuHY3ogi+I2qH3/nnIYUBzB4csF5opoNUsfK1CFjnWrpEFW JkCQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature:dkim-filter; bh=wblcgkvxFKNoIBmJlLw5uhCpCh2AOHqRl6jZojMqhfQ=; fh=X4QAQfkJoHBoTjypDfqSMHAFutuwOQvRiEbCzpU4yFA=; b=kbBVrvB3poOvs7WXMI5NAVOUDCilEKqIZpVrq0Dd3phjy1OxsLDLKmMJmT1SLAyrtd Pr381rk+y7WIalPO80WI5IlKyOlaMbf/CgtONLhyww5wwF+eVJVMx74jmO9f8oIKiylv LeEP5avR/DFgu1xbrkDsgUa2MZOR5sSsrR58nvfQYrLOhwKm2KAyK5o6bQRFA3YFYWJA jvG30uazDjegVqLsD02Tnh/J2cLvPk9oxmbJvklNpOtSOIG+qjPEnX86yoFVmYRxOw+K u5wB+jpgpVjpkx8pDDejU8MobHmnSRSKV1AlGsvSkBWQzp+dU8vAnOWo/Xxu/8TQqS36 dbsw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=LaRCFxj0; arc=pass (i=1 spf=pass spfdomain=savoirfairelinux.com dkim=pass dkdomain=savoirfairelinux.com); spf=pass (google.com: domain of linux-kernel+bounces-75434-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-75434-ouuuleilei=gmail.com@vger.kernel.org" Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id bn16-20020a056a02031000b005ceea21d9ccsi8845738pgb.771.2024.02.21.12.01.34 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Feb 2024 12:01:34 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-75434-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) client-ip=139.178.88.99; Authentication-Results: mx.google.com; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=LaRCFxj0; arc=pass (i=1 spf=pass spfdomain=savoirfairelinux.com dkim=pass dkdomain=savoirfairelinux.com); spf=pass (google.com: domain of linux-kernel+bounces-75434-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-75434-ouuuleilei=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 55F682822AD for ; Wed, 21 Feb 2024 20:01:34 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 216801420B8; Wed, 21 Feb 2024 19:52:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=savoirfairelinux.com header.i=@savoirfairelinux.com header.b="LaRCFxj0" Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D9CF3134CD4; Wed, 21 Feb 2024 19:52:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=208.88.110.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708545140; cv=none; b=jzW7iamL3pdrGzJVg2tC1aqapvjTuVUkXOYQIFjEjbpaE4G2sVg3RHvXDL8+J3uiMn/ZXyBWg/OP2RVKHhgiIZ+RpdO8JKUJ7FwsC03INFqu3FEqceH87upfkdzUBd2hnD1LpBLQXzz7QAMCzsWQohSqRwN2aijSG3KdEvQDdZ8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708545140; c=relaxed/simple; bh=U9ISTnvY2x0O1yNDgNt7SO01HJoEd3Ht+CK0RGK26aw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BoJYEavvzBGn26pOofMTUOyxyKFeY0ys4vobZ/GZvpmx0N0wknAwcbdYrU9Jn+Toga56hBAUNIv5wttbGWJ56NGhIURGF0ngwkRE0+O1/yRSnEzNCEZUTyjclbEEmojHQ8yIeSEjkAFUl91+gYO4yo5GQ9hztbjD62rewqhTbTA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=savoirfairelinux.com; spf=pass smtp.mailfrom=savoirfairelinux.com; dkim=pass (2048-bit key) header.d=savoirfairelinux.com header.i=@savoirfairelinux.com header.b=LaRCFxj0; arc=none smtp.client-ip=208.88.110.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=savoirfairelinux.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=savoirfairelinux.com Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 9F8B79C4BEA; Wed, 21 Feb 2024 14:52:10 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id DdOALsJcIl7t; Wed, 21 Feb 2024 14:52:07 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 83FC19C4BD8; Wed, 21 Feb 2024 14:52:07 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com 83FC19C4BD8 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1708545127; bh=wblcgkvxFKNoIBmJlLw5uhCpCh2AOHqRl6jZojMqhfQ=; h=From:To:Date:Message-ID:MIME-Version; b=LaRCFxj0ULkhMPPmlr1SKm3VkK/mwZBBBXGs52L27pdQe8JTMxrOUBHcJFyUU2aNT OzrkMw93Nm5FMAGXkID85b4654CJNvaALQ/LP8QibIoEu3fZI/SHYnKRKEDD91EbsS G8QXYJHjwnD96OErYS0gjnbds5zlKFhdScpBdKwO969MOx9pRDo+6fg6JqxdfvAuW6 rUk5C89GRXpRXv7DQFYdGaMXXldxbNyQa2RoqDyABGeNhUm/Ff0NrTT/ZzVP5YR05f KPu07P/fy3JQJuSd+0a+ElwJVFhl+vHjaXk8iqK3Rht/W1+byQ1UH4ZjHDw1Y1JHCM 5LulxutvyipKQ== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id QwHaBiIn-5r3; Wed, 21 Feb 2024 14:52:07 -0500 (EST) Received: from pcperry.mtl.sfl (unknown [192.168.51.254]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 5B0A99C4B59; Wed, 21 Feb 2024 14:52:07 -0500 (EST) From: Charles Perry To: mdf@kernel.org Cc: avandiver@markem-imaje.com, bcody@markem-imaje.com, Charles Perry , Wu Hao , Xu Yilun , Tom Rix , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michal Simek , linux-fpga@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v4 1/3] fpga: xilinx-spi: extract a common driver core Date: Wed, 21 Feb 2024 14:50:47 -0500 Message-ID: <20240221195058.1281973-2-charles.perry@savoirfairelinux.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240221195058.1281973-1-charles.perry@savoirfairelinux.com> References: <20240221195058.1281973-1-charles.perry@savoirfairelinux.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791540010168892355 X-GMAIL-MSGID: 1791540010168892355 Factor out the gpio handshaking (using PROGRAM_B, INIT_B and DONE) protocol in xilinx-core so that it can be reused for another driver. This commit does not change anything functionally to xilinx-spi. xilinx-core expects drivers to provide a single operation: * ->write(const char* buf, size_t count): write to the device As well as a struct device* for resource management. Signed-off-by: Charles Perry --- drivers/fpga/Kconfig | 4 + drivers/fpga/Makefile | 1 + drivers/fpga/xilinx-core.c | 208 ++++++++++++++++++++++++++++++++++++ drivers/fpga/xilinx-core.h | 28 +++++ drivers/fpga/xilinx-spi.c | 212 +++---------------------------------- 5 files changed, 254 insertions(+), 199 deletions(-) create mode 100644 drivers/fpga/xilinx-core.c create mode 100644 drivers/fpga/xilinx-core.h diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 2f689ac4ba3a3..d27a1ebf40838 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -64,9 +64,13 @@ config FPGA_MGR_STRATIX10_SOC help FPGA manager driver support for the Intel Stratix10 SoC. +config FPGA_MGR_XILINX_CORE + tristate + config FPGA_MGR_XILINX_SPI tristate "Xilinx Configuration over Slave Serial (SPI)" depends on SPI + select FPGA_MGR_XILINX_CORE help FPGA manager driver support for Xilinx FPGA configuration over slave serial interface. diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 352a2612623e0..7ec795b6a5a70 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o obj-$(CONFIG_FPGA_MGR_STRATIX10_SOC) += stratix10-soc.o obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o +obj-$(CONFIG_FPGA_MGR_XILINX_CORE) += xilinx-core.o obj-$(CONFIG_FPGA_MGR_XILINX_SPI) += xilinx-spi.o obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o obj-$(CONFIG_FPGA_MGR_ZYNQMP_FPGA) += zynqmp-fpga.o diff --git a/drivers/fpga/xilinx-core.c b/drivers/fpga/xilinx-core.c new file mode 100644 index 0000000000000..597e8b7a530b7 --- /dev/null +++ b/drivers/fpga/xilinx-core.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Common parts of the Xilinx Spartan6 and 7 Series FPGA manager drivers. + * + * Copyright (C) 2017 DENX Software Engineering + * + * Anatolij Gustschin + */ + +#include "xilinx-core.h" + +#include +#include +#include +#include + +static int get_done_gpio(struct fpga_manager *mgr) +{ + struct xilinx_fpga_core *core = mgr->priv; + int ret; + + ret = gpiod_get_value(core->done); + if (ret < 0) + dev_err(&mgr->dev, "Error reading DONE (%d)\n", ret); + + return ret; +} + +static enum fpga_mgr_states xilinx_core_state(struct fpga_manager *mgr) +{ + if (!get_done_gpio(mgr)) + return FPGA_MGR_STATE_RESET; + + return FPGA_MGR_STATE_UNKNOWN; +} + +/** + * wait_for_init_b - wait for the INIT_B pin to have a given state, or wait + * a given delay if the pin is unavailable + * + * @mgr: The FPGA manager object + * @value: Value INIT_B to wait for (1 = asserted = low) + * @alt_udelay: Delay to wait if the INIT_B GPIO is not available + * + * Returns 0 when the INIT_B GPIO reached the given state or -ETIMEDOUT if + * too much time passed waiting for that. If no INIT_B GPIO is available + * then always return 0. + */ +static int wait_for_init_b(struct fpga_manager *mgr, int value, + unsigned long alt_udelay) +{ + struct xilinx_fpga_core *core = mgr->priv; + unsigned long timeout = jiffies + msecs_to_jiffies(1000); + + if (core->init_b) { + while (time_before(jiffies, timeout)) { + int ret = gpiod_get_value(core->init_b); + + if (ret == value) + return 0; + + if (ret < 0) { + dev_err(&mgr->dev, + "Error reading INIT_B (%d)\n", ret); + return ret; + } + + usleep_range(100, 400); + } + + dev_err(&mgr->dev, "Timeout waiting for INIT_B to %s\n", + value ? "assert" : "deassert"); + return -ETIMEDOUT; + } + + udelay(alt_udelay); + + return 0; +} + +static int xilinx_core_write_init(struct fpga_manager *mgr, + struct fpga_image_info *info, const char *buf, + size_t count) +{ + struct xilinx_fpga_core *core = mgr->priv; + int err; + + if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) { + dev_err(&mgr->dev, "Partial reconfiguration not supported\n"); + return -EINVAL; + } + + gpiod_set_value(core->prog_b, 1); + + err = wait_for_init_b(mgr, 1, 1); /* min is 500 ns */ + if (err) { + gpiod_set_value(core->prog_b, 0); + return err; + } + + gpiod_set_value(core->prog_b, 0); + + err = wait_for_init_b(mgr, 0, 0); + if (err) + return err; + + if (get_done_gpio(mgr)) { + dev_err(&mgr->dev, "Unexpected DONE pin state...\n"); + return -EIO; + } + + /* program latency */ + usleep_range(7500, 7600); + return 0; +} + +static int xilinx_core_write(struct fpga_manager *mgr, const char *buf, + size_t count) +{ + struct xilinx_fpga_core *core = mgr->priv; + + return core->write(core, buf, count); +} + +static int xilinx_core_write_complete(struct fpga_manager *mgr, + struct fpga_image_info *info) +{ + struct xilinx_fpga_core *core = mgr->priv; + unsigned long timeout = + jiffies + usecs_to_jiffies(info->config_complete_timeout_us); + bool expired = false; + int done; + int ret; + const char padding[1] = { 0xff }; + + /* + * This loop is carefully written such that if the driver is + * scheduled out for more than 'timeout', we still check for DONE + * before giving up and we apply 8 extra CCLK cycles in all cases. + */ + while (!expired) { + expired = time_after(jiffies, timeout); + + done = get_done_gpio(mgr); + if (done < 0) + return done; + + ret = core->write(core, padding, 1); + if (ret) + return ret; + + if (done) + return 0; + } + + if (core->init_b) { + ret = gpiod_get_value(core->init_b); + + if (ret < 0) { + dev_err(&mgr->dev, "Error reading INIT_B (%d)\n", ret); + return ret; + } + + dev_err(&mgr->dev, + ret ? "CRC error or invalid device\n" : + "Missing sync word or incomplete bitstream\n"); + } else { + dev_err(&mgr->dev, "Timeout after config data transfer\n"); + } + + return -ETIMEDOUT; +} + +static const struct fpga_manager_ops xilinx_core_ops = { + .state = xilinx_core_state, + .write_init = xilinx_core_write_init, + .write = xilinx_core_write, + .write_complete = xilinx_core_write_complete, +}; + +int xilinx_core_probe(struct xilinx_fpga_core *core) +{ + struct fpga_manager *mgr; + + if (!core || !core->dev || !core->write) + return -EINVAL; + + /* PROGRAM_B is active low */ + core->prog_b = devm_gpiod_get(core->dev, "prog_b", GPIOD_OUT_LOW); + if (IS_ERR(core->prog_b)) + return dev_err_probe(core->dev, PTR_ERR(core->prog_b), + "Failed to get PROGRAM_B gpio\n"); + + core->init_b = devm_gpiod_get_optional(core->dev, "init-b", GPIOD_IN); + if (IS_ERR(core->init_b)) + return dev_err_probe(core->dev, PTR_ERR(core->init_b), + "Failed to get INIT_B gpio\n"); + + core->done = devm_gpiod_get(core->dev, "done", GPIOD_IN); + if (IS_ERR(core->done)) + return dev_err_probe(core->dev, PTR_ERR(core->done), + "Failed to get DONE gpio\n"); + + mgr = devm_fpga_mgr_register(core->dev, + "Xilinx Slave Serial FPGA Manager", + &xilinx_core_ops, core); + return PTR_ERR_OR_ZERO(mgr); +} diff --git a/drivers/fpga/xilinx-core.h b/drivers/fpga/xilinx-core.h new file mode 100644 index 0000000000000..bea190287b403 --- /dev/null +++ b/drivers/fpga/xilinx-core.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __XILINX_CORE_H +#define __XILINX_CORE_H + +#include + +/** + * struct xilinx_fpga_core - interface between the driver and the core manager + * of Xilinx 7 Series FPGA manager + * @dev: device node, must be set by the driver + * @write: write callback of the driver, must be set by the driver + * @prog_b: PROGRAM_B gpio, handled by the core manager + * @init_b: INIT_B gpio, handled by the core manager + * @done: DONE gpio, handled by the core manager + */ +struct xilinx_fpga_core { + struct device *dev; + int (*write)(struct xilinx_fpga_core *core, const char *buf, + size_t count); + struct gpio_desc *prog_b; + struct gpio_desc *init_b; + struct gpio_desc *done; +}; + +int xilinx_core_probe(struct xilinx_fpga_core *core); + +#endif /* __XILINX_CORE_H */ diff --git a/drivers/fpga/xilinx-spi.c b/drivers/fpga/xilinx-spi.c index e1a227e7ff2ae..12f401502a53a 100644 --- a/drivers/fpga/xilinx-spi.c +++ b/drivers/fpga/xilinx-spi.c @@ -10,127 +10,24 @@ * the slave serial configuration interface. */ -#include -#include -#include -#include +#include "xilinx-core.h" + #include #include #include #include -#include struct xilinx_spi_conf { + struct xilinx_fpga_core core; struct spi_device *spi; - struct gpio_desc *prog_b; - struct gpio_desc *init_b; - struct gpio_desc *done; }; -static int get_done_gpio(struct fpga_manager *mgr) -{ - struct xilinx_spi_conf *conf = mgr->priv; - int ret; - - ret = gpiod_get_value(conf->done); - - if (ret < 0) - dev_err(&mgr->dev, "Error reading DONE (%d)\n", ret); - - return ret; -} - -static enum fpga_mgr_states xilinx_spi_state(struct fpga_manager *mgr) -{ - if (!get_done_gpio(mgr)) - return FPGA_MGR_STATE_RESET; - - return FPGA_MGR_STATE_UNKNOWN; -} - -/** - * wait_for_init_b - wait for the INIT_B pin to have a given state, or wait - * a given delay if the pin is unavailable - * - * @mgr: The FPGA manager object - * @value: Value INIT_B to wait for (1 = asserted = low) - * @alt_udelay: Delay to wait if the INIT_B GPIO is not available - * - * Returns 0 when the INIT_B GPIO reached the given state or -ETIMEDOUT if - * too much time passed waiting for that. If no INIT_B GPIO is available - * then always return 0. - */ -static int wait_for_init_b(struct fpga_manager *mgr, int value, - unsigned long alt_udelay) -{ - struct xilinx_spi_conf *conf = mgr->priv; - unsigned long timeout = jiffies + msecs_to_jiffies(1000); - - if (conf->init_b) { - while (time_before(jiffies, timeout)) { - int ret = gpiod_get_value(conf->init_b); - - if (ret == value) - return 0; - - if (ret < 0) { - dev_err(&mgr->dev, "Error reading INIT_B (%d)\n", ret); - return ret; - } - - usleep_range(100, 400); - } - - dev_err(&mgr->dev, "Timeout waiting for INIT_B to %s\n", - value ? "assert" : "deassert"); - return -ETIMEDOUT; - } - - udelay(alt_udelay); - - return 0; -} - -static int xilinx_spi_write_init(struct fpga_manager *mgr, - struct fpga_image_info *info, - const char *buf, size_t count) -{ - struct xilinx_spi_conf *conf = mgr->priv; - int err; - - if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) { - dev_err(&mgr->dev, "Partial reconfiguration not supported\n"); - return -EINVAL; - } - - gpiod_set_value(conf->prog_b, 1); - - err = wait_for_init_b(mgr, 1, 1); /* min is 500 ns */ - if (err) { - gpiod_set_value(conf->prog_b, 0); - return err; - } - - gpiod_set_value(conf->prog_b, 0); +#define to_xilinx_spi_conf(obj) container_of(obj, struct xilinx_spi_conf, core) - err = wait_for_init_b(mgr, 0, 0); - if (err) - return err; - - if (get_done_gpio(mgr)) { - dev_err(&mgr->dev, "Unexpected DONE pin state...\n"); - return -EIO; - } - - /* program latency */ - usleep_range(7500, 7600); - return 0; -} - -static int xilinx_spi_write(struct fpga_manager *mgr, const char *buf, +static int xilinx_spi_write(struct xilinx_fpga_core *core, const char *buf, size_t count) { - struct xilinx_spi_conf *conf = mgr->priv; + struct xilinx_spi_conf *conf = to_xilinx_spi_conf(core); const char *fw_data = buf; const char *fw_data_end = fw_data + count; @@ -143,7 +40,7 @@ static int xilinx_spi_write(struct fpga_manager *mgr, const char *buf, ret = spi_write(conf->spi, fw_data, stride); if (ret) { - dev_err(&mgr->dev, "SPI error in firmware write: %d\n", + dev_err(core->dev, "SPI error in firmware write: %d\n", ret); return ret; } @@ -153,109 +50,26 @@ static int xilinx_spi_write(struct fpga_manager *mgr, const char *buf, return 0; } -static int xilinx_spi_apply_cclk_cycles(struct xilinx_spi_conf *conf) -{ - struct spi_device *spi = conf->spi; - const u8 din_data[1] = { 0xff }; - int ret; - - ret = spi_write(conf->spi, din_data, sizeof(din_data)); - if (ret) - dev_err(&spi->dev, "applying CCLK cycles failed: %d\n", ret); - - return ret; -} - -static int xilinx_spi_write_complete(struct fpga_manager *mgr, - struct fpga_image_info *info) -{ - struct xilinx_spi_conf *conf = mgr->priv; - unsigned long timeout = jiffies + usecs_to_jiffies(info->config_complete_timeout_us); - bool expired = false; - int done; - int ret; - - /* - * This loop is carefully written such that if the driver is - * scheduled out for more than 'timeout', we still check for DONE - * before giving up and we apply 8 extra CCLK cycles in all cases. - */ - while (!expired) { - expired = time_after(jiffies, timeout); - - done = get_done_gpio(mgr); - if (done < 0) - return done; - - ret = xilinx_spi_apply_cclk_cycles(conf); - if (ret) - return ret; - - if (done) - return 0; - } - - if (conf->init_b) { - ret = gpiod_get_value(conf->init_b); - - if (ret < 0) { - dev_err(&mgr->dev, "Error reading INIT_B (%d)\n", ret); - return ret; - } - - dev_err(&mgr->dev, - ret ? "CRC error or invalid device\n" - : "Missing sync word or incomplete bitstream\n"); - } else { - dev_err(&mgr->dev, "Timeout after config data transfer\n"); - } - - return -ETIMEDOUT; -} - -static const struct fpga_manager_ops xilinx_spi_ops = { - .state = xilinx_spi_state, - .write_init = xilinx_spi_write_init, - .write = xilinx_spi_write, - .write_complete = xilinx_spi_write_complete, -}; - static int xilinx_spi_probe(struct spi_device *spi) { struct xilinx_spi_conf *conf; - struct fpga_manager *mgr; conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL); if (!conf) return -ENOMEM; + conf->core.dev = &spi->dev; + conf->core.write = xilinx_spi_write; conf->spi = spi; - /* PROGRAM_B is active low */ - conf->prog_b = devm_gpiod_get(&spi->dev, "prog_b", GPIOD_OUT_LOW); - if (IS_ERR(conf->prog_b)) - return dev_err_probe(&spi->dev, PTR_ERR(conf->prog_b), - "Failed to get PROGRAM_B gpio\n"); - - conf->init_b = devm_gpiod_get_optional(&spi->dev, "init-b", GPIOD_IN); - if (IS_ERR(conf->init_b)) - return dev_err_probe(&spi->dev, PTR_ERR(conf->init_b), - "Failed to get INIT_B gpio\n"); - - conf->done = devm_gpiod_get(&spi->dev, "done", GPIOD_IN); - if (IS_ERR(conf->done)) - return dev_err_probe(&spi->dev, PTR_ERR(conf->done), - "Failed to get DONE gpio\n"); - - mgr = devm_fpga_mgr_register(&spi->dev, - "Xilinx Slave Serial FPGA Manager", - &xilinx_spi_ops, conf); - return PTR_ERR_OR_ZERO(mgr); + return xilinx_core_probe(&conf->core); } #ifdef CONFIG_OF static const struct of_device_id xlnx_spi_of_match[] = { - { .compatible = "xlnx,fpga-slave-serial", }, + { + .compatible = "xlnx,fpga-slave-serial", + }, {} }; MODULE_DEVICE_TABLE(of, xlnx_spi_of_match); From patchwork Wed Feb 21 19:50:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Charles Perry X-Patchwork-Id: 204423 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:693c:2685:b0:108:e6aa:91d0 with SMTP id mn5csp1279215dyc; Wed, 21 Feb 2024 12:26:40 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCVKjYkVdS34ht6Ml8UX2lCz91Qo5hR9w+LNkYnUeRwDxJV0T8o8Fnl56P2qJhLsvkPtY7+B196WgvLFnK2zwmkyX6j9oQ== X-Google-Smtp-Source: AGHT+IGILH1l6imSsbVkhrGDtl+30L2FhoYGjTc0QWZZo60Fc0uRWR5t874ZqbvLoSd25UjFCiXm X-Received: by 2002:a17:90a:bd8e:b0:299:10a9:bbb with SMTP id z14-20020a17090abd8e00b0029910a90bbbmr13311603pjr.9.1708547199837; Wed, 21 Feb 2024 12:26:39 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708547199; cv=pass; d=google.com; s=arc-20160816; b=YjxjLmRLeVIjIUqg3h+O/88yI3qr+9P1kZwD8XP1u+RYxcRE81P89YrH8/qPN7UH0R bFQXPTVfu9ROdm23CTae9z9K+HSdfrkBm+YaJ6dxatBLZFWqX9BtB178waZhCPK+oS6h agpUPXvJgBhiEbPoSPqGh1633MctH5MiqxHPiTWG/U9kHnRj3QWOD1+Kzx4DKih3tq+9 nTEzX88heyL5+tlU0pR6T91qh1BVB0X3uhblFmy8BFiprtNKiKLd2mlVHh8jt/DqfGAo CZ3EPOfh0MZjaxFIaVmKqLT7Ge2IyrHrMLKkYYzkAoEsFUA23YExAjSUJLuWuoWA2406 2UnA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature:dkim-filter; bh=V0AloincpFNxqN8jxOVAcKyVY2ydGA1teB3GeWFAsDs=; fh=X4QAQfkJoHBoTjypDfqSMHAFutuwOQvRiEbCzpU4yFA=; b=lWKyFWrGiCOlLh3OYaxR5BG52o3nuleHiD8p5foxQxGwb2Czz3QURMe2kE0RqKdMS1 bz28tn3DxuHFBJTXJdU9ZWXMDengJmm+9R3pZPOpR65As9Up2eCuuPTTJnDWJU6nMdoO QIGun4ap9x9lwulnf3dKGzCdyPj/32v0ChlOZEbSvR2FbFHGw23+7xCZGSXwl0CuYpvd DV3MFoM2kd8sbKkwZMt6m8gr+o5R1je0y3WvQJVVA4vq+z7Thl6FSoWkqL4hkOFc8nB8 ja2PokWcKPvyMGcG6/ZusVeBNyPl3lchum051syxMJddXni1bvmYInP5VAU/PefRrhCi aNSg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b="v/ihWQHy"; arc=pass (i=1 spf=pass spfdomain=savoirfairelinux.com dkim=pass dkdomain=savoirfairelinux.com); spf=pass (google.com: domain of linux-kernel+bounces-75433-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-75433-ouuuleilei=gmail.com@vger.kernel.org" Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [2604:1380:40f1:3f00::1]) by mx.google.com with ESMTPS id p5-20020a17090a868500b002935f38dcf1si2091917pjn.181.2024.02.21.12.26.39 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Feb 2024 12:26:39 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-75433-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) client-ip=2604:1380:40f1:3f00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b="v/ihWQHy"; arc=pass (i=1 spf=pass spfdomain=savoirfairelinux.com dkim=pass dkdomain=savoirfairelinux.com); spf=pass (google.com: domain of linux-kernel+bounces-75433-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-75433-ouuuleilei=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id A9D4DB241F8 for ; Wed, 21 Feb 2024 20:01:24 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 5EC001353FD; Wed, 21 Feb 2024 19:52:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=savoirfairelinux.com header.i=@savoirfairelinux.com header.b="v/ihWQHy" Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BE108134723; Wed, 21 Feb 2024 19:52:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=208.88.110.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708545138; cv=none; b=XA28kC/44cuTzNHYnM9oNeEJU18rZR7ejPiBXgRdMLruULvyXtdRloDzGWnzuPsZ8aBYxetwTF2XjXPrLqBCiCZXpoRnKeIh8KwfnCQsbS6ZeBiCvOUqk7zczRR1TMzqHgSbPmvSapbyERKglj0O5o9dYaGN1s+rlQPiSYZevTA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708545138; c=relaxed/simple; bh=LlqHcE0YwJZlGexpmnxq7XZsurHwrFWJoYOL08Ka9UE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=k3aaZMzf50nQtHvuyQjZGYFlY2q85tM+S5CTLaDM2BLV3eTpRRlDhEbftn3E/bF+3sGsGO6WkODqeD5StMJFRh5HRXPVFgWqHOC/sva2x/SOBrllSYYvi5bKSu+FWG7zAuiHSHdikKUBm2OliIYY0HzZoTaqU6jITMxTS1NvZ+Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=savoirfairelinux.com; spf=pass smtp.mailfrom=savoirfairelinux.com; dkim=pass (2048-bit key) header.d=savoirfairelinux.com header.i=@savoirfairelinux.com header.b=v/ihWQHy; arc=none smtp.client-ip=208.88.110.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=savoirfairelinux.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=savoirfairelinux.com Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 5CF1D9C4B59; Wed, 21 Feb 2024 14:52:10 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id 1HRkwdxDnQeV; Wed, 21 Feb 2024 14:52:09 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 74C559C4BEA; Wed, 21 Feb 2024 14:52:09 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com 74C559C4BEA DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1708545129; bh=V0AloincpFNxqN8jxOVAcKyVY2ydGA1teB3GeWFAsDs=; h=From:To:Date:Message-ID:MIME-Version; b=v/ihWQHyJwFqRDMtxygel1LYabD9lGZMscCI8GwNTwWtL5RAixkb9KbDSUombzccV y299zfvVl9+wzPZJqYT3UUQdSKyz/Zdb6zm0S7xpb3DcTwW/3nYfCrrQ7eKMITj1wc DkA1seyufzumAlMEsh/A4X3DLUulQcxKMnyRueri/CB4vh2ohgtmk15gK217pz5UoW oIEDjjSN1YWqS90abXGCeksd7HWxTlJfE2k8C6JG4kTXLVCYB5FAz/bKg5Dtui1fGX Hut0BZ26g4q7NrXBEW2OV9C+2fHYqIIzafcayiw6umLcLBqHdHmXkyB/bEeB4lunNd l7+8fHW18nCMg== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id inHxOnZgcdKg; Wed, 21 Feb 2024 14:52:09 -0500 (EST) Received: from pcperry.mtl.sfl (unknown [192.168.51.254]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 503609C4B59; Wed, 21 Feb 2024 14:52:09 -0500 (EST) From: Charles Perry To: mdf@kernel.org Cc: avandiver@markem-imaje.com, bcody@markem-imaje.com, Charles Perry , Wu Hao , Xu Yilun , Tom Rix , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michal Simek , linux-fpga@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v4 2/3] dt-bindings: fpga: xlnx,fpga-selectmap: add DT schema Date: Wed, 21 Feb 2024 14:50:48 -0500 Message-ID: <20240221195058.1281973-3-charles.perry@savoirfairelinux.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240221195058.1281973-1-charles.perry@savoirfairelinux.com> References: <20240221195058.1281973-1-charles.perry@savoirfairelinux.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791541588275568543 X-GMAIL-MSGID: 1791541588275568543 Document the SelectMAP interface of Xilinx 7 series FPGA. Signed-off-by: Charles Perry --- .../bindings/fpga/xlnx,fpga-selectmap.yaml | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 Documentation/devicetree/bindings/fpga/xlnx,fpga-selectmap.yaml diff --git a/Documentation/devicetree/bindings/fpga/xlnx,fpga-selectmap.yaml b/Documentation/devicetree/bindings/fpga/xlnx,fpga-selectmap.yaml new file mode 100644 index 0000000000000..08a5e92781657 --- /dev/null +++ b/Documentation/devicetree/bindings/fpga/xlnx,fpga-selectmap.yaml @@ -0,0 +1,86 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/fpga/xlnx,fpga-selectmap.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Xilinx SelectMAP FPGA interface + +maintainers: + - Charles Perry + +description: | + Xilinx 7 Series FPGAs support a method of loading the bitstream over a + parallel port named the SelectMAP interface in the documentation. Only + the x8 mode is supported where data is loaded at one byte per rising edge of + the clock, with the MSB of each byte presented to the D0 pin. + + Datasheets: + https://www.xilinx.com/support/documentation/user_guides/ug470_7Series_Config.pdf + +allOf: + - $ref: /schemas/memory-controllers/mc-peripheral-props.yaml# + +properties: + compatible: + enum: + - xlnx,fpga-xc7s-selectmap + - xlnx,fpga-xc7a-selectmap + - xlnx,fpga-xc7k-selectmap + - xlnx,fpga-xc7v-selectmap + + reg: + description: + At least 1 byte of memory mapped IO + maxItems: 1 + + prog_b-gpios: + description: + config pin (referred to as PROGRAM_B in the manual) + maxItems: 1 + + done-gpios: + description: + config status pin (referred to as DONE in the manual) + maxItems: 1 + + init-b-gpios: + description: + initialization status and configuration error pin + (referred to as INIT_B in the manual) + maxItems: 1 + + csi-gpios: + description: + chip select pin (referred to as CSI_B in the manual) + Optional gpio for if the bus controller does not provide a chip select. + maxItems: 1 + + rdwr-gpios: + description: + read/write select pin (referred to as RDWR_B in the manual) + Optional gpio for if the bus controller does not provide this pin. + maxItems: 1 + +required: + - compatible + - reg + - prog_b-gpios + - done-gpios + - init-b-gpios + +unevaluatedProperties: false + +examples: + - | + #include + fpga-mgr@8000000 { + compatible = "xlnx,fpga-xc7s-selectmap"; + reg = <0x8000000 0x4>; + prog_b-gpios = <&gpio5 5 GPIO_ACTIVE_LOW>; + init-b-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>; + done-gpios = <&gpio2 30 GPIO_ACTIVE_HIGH>; + csi-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>; + rdwr-gpios = <&gpio3 10 GPIO_ACTIVE_LOW>; + }; +... From patchwork Wed Feb 21 19:50:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Charles Perry X-Patchwork-Id: 204410 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:693c:2685:b0:108:e6aa:91d0 with SMTP id mn5csp1265480dyc; Wed, 21 Feb 2024 12:01:11 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCV2UqbcMakxERK+tZ49SAP56CO+Gm+ldHjpsb/RSLa3n/xczZs/Clqc0fQaV45KOf5QzJY+RNsAMXB2elb1PJaApvl7DQ== X-Google-Smtp-Source: AGHT+IG+gLdcGUYnPvf0E2U+HGnVZ7Tta+/yMjNtfOwroC05gD6ujIp9BBMl5tOVeP/fc4EvWMZS X-Received: by 2002:a25:1643:0:b0:dcc:1449:71ea with SMTP id 64-20020a251643000000b00dcc144971eamr321224ybw.50.1708545670766; Wed, 21 Feb 2024 12:01:10 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708545670; cv=pass; d=google.com; s=arc-20160816; b=0h0AcG+2hZ4Zhc+sAlghaczYLSAi7kalMyCTEYC7BcRKfTfj3Vzle9vXtXKLkj0t00 afayvRB2l+MKQN/kwCbDSTUbQTnrnHd4BJU2+hQZqUzxj38FaLAmxelEwi0NeZnD8i5A 0PtVoym9cGtUHl0lNaibgngSU+toWtN2o60IhLOe1fKdVoSogcmREzd2myoMpD8FA8mA NC9nwsgdoDDbpw7OCOMtwZxomT83DF1jDGulpGvPRdHBEiPRZQ4AwUEWIIecO1kWFYOE 9sjJ5C6Ov19EntK3f5N4fkTEuZQgg13eaik9SgMzGEH4UADztoM0o24iQWKMdNFiiyH6 B5Eg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature:dkim-filter; bh=ly1997o8a0kUOAeldUVP9gf71MeRB6+Tnu3YuBit5iE=; fh=X4QAQfkJoHBoTjypDfqSMHAFutuwOQvRiEbCzpU4yFA=; b=kn7/KqfCyVz4IMM2u3pIBUbu74lmlwG8V6ShfzArzV4JC6CuvnAjYJQ9logTkLmazy NOn8g0s6jONuO+0BRIFiuDFxamia3wPeUPhKT2IwL+09hUSisptrXf5JIFV+nU7dAYmv wYFH57kLsSjGA2XaCFL3+1CBttWTYG9qKh4IfktftNuOPuEiZhyaLF31rMO5FRHJjVzV BMDsLBJ/GGYsWvWZOTrwlMviAnEdYFJkBgJ8DtzoitjVSEuhREHYk2EisZ1+CIEu58+c PTiMOolkY54kUNB3xN7u1UKBUexgQDhxN9QukGa9PTxwduRjdGXOWAiyFpYcyzhc832m 6m3Q==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=cHFOniY0; arc=pass (i=1 spf=pass spfdomain=savoirfairelinux.com dkim=pass dkdomain=savoirfairelinux.com); spf=pass (google.com: domain of linux-kernel+bounces-75432-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-75432-ouuuleilei=gmail.com@vger.kernel.org" Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [147.75.199.223]) by mx.google.com with ESMTPS id f3-20020a05620a408300b007872a3c1871si12847468qko.437.2024.02.21.12.01.10 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Feb 2024 12:01:10 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-75432-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) client-ip=147.75.199.223; Authentication-Results: mx.google.com; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=cHFOniY0; arc=pass (i=1 spf=pass spfdomain=savoirfairelinux.com dkim=pass dkdomain=savoirfairelinux.com); spf=pass (google.com: domain of linux-kernel+bounces-75432-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-75432-ouuuleilei=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 572961C21C02 for ; Wed, 21 Feb 2024 20:01:10 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9FE43135A59; Wed, 21 Feb 2024 19:52:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=savoirfairelinux.com header.i=@savoirfairelinux.com header.b="cHFOniY0" Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D292186130; Wed, 21 Feb 2024 19:52:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=208.88.110.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708545136; cv=none; b=kWmvzFgiGFH4Lh2st2NVBd59MtjC5o320/nhLzkWn2tldleLVXAfI6TrSJigRKzWLrEUWeLy2vqXDNKj1KqMcn8BONgk+gr6oWhiB1JF3kj7G0yw14ppRvu8Up3/QDP/cWXoy/bTA2B61/Ymoe5I4fvvx9QUsE5JXvKyKkGICiw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708545136; c=relaxed/simple; bh=NR5SjOtitKYacXAEEruvJ6JXFK2gpzJixBo6UISsrYc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tnlncYln82yXOTI0dMCjk5APDGjNWdglWeSYqCTuHY79RKRlKrtrbqflA43ncSZMVr+z5/g84qn/5blvX1Uw0wTI8R4ZryQvXxtiLK8Z7p69AxWqdRGGCoNf4UgiMcFr19Ed0rGB3KXb1BLGjHsjAJ4pM+8MLujz8JQF6P8bdgE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=savoirfairelinux.com; spf=pass smtp.mailfrom=savoirfairelinux.com; dkim=pass (2048-bit key) header.d=savoirfairelinux.com header.i=@savoirfairelinux.com header.b=cHFOniY0; arc=none smtp.client-ip=208.88.110.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=savoirfairelinux.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=savoirfairelinux.com Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id AA2C09C4BD8; Wed, 21 Feb 2024 14:52:12 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id cFCGRLPkRvWD; Wed, 21 Feb 2024 14:52:11 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 6CDC39C4BE8; Wed, 21 Feb 2024 14:52:11 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com 6CDC39C4BE8 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1708545131; bh=ly1997o8a0kUOAeldUVP9gf71MeRB6+Tnu3YuBit5iE=; h=From:To:Date:Message-ID:MIME-Version; b=cHFOniY08786Xn1+A44yHKrzrwGhSu742BX1wi/PYKm6OEreBci/ayqmuoEkb5xN+ PQA3CwjhzM8DFnhInwD8l6LNHduMx07oyknCAUhaP2WMr3wqlkA43RYcYghlpQbQpQ U56ALZQTxF+RzuFldWlckDUQFwI1C8JFVk43j/EugPWBi2iYdsqhTwwP7VI45+LSBO +wTWxJtMl2jPR8N7ejT8d94K300O/5yeKrgf1Cr7f7SBFVlv9Ot+1UcFhngNr73B1D H3vfG8K1g8796kCsRH1RBDJ99ExfUu3tbwIPBLk0hMd9U996DlrsmIYyLZns7apoAj dg7alOL/1NB3Q== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id cx5z08vs187s; Wed, 21 Feb 2024 14:52:11 -0500 (EST) Received: from pcperry.mtl.sfl (unknown [192.168.51.254]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 489079C4BD8; Wed, 21 Feb 2024 14:52:11 -0500 (EST) From: Charles Perry To: mdf@kernel.org Cc: avandiver@markem-imaje.com, bcody@markem-imaje.com, Charles Perry , Wu Hao , Xu Yilun , Tom Rix , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michal Simek , linux-fpga@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v4 3/3] fpga: xilinx-selectmap: add new driver Date: Wed, 21 Feb 2024 14:50:49 -0500 Message-ID: <20240221195058.1281973-4-charles.perry@savoirfairelinux.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240221195058.1281973-1-charles.perry@savoirfairelinux.com> References: <20240221195058.1281973-1-charles.perry@savoirfairelinux.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791539976296194793 X-GMAIL-MSGID: 1791539985428776857 Xilinx 7 series FPGA can be programmed using a parallel port named the SelectMAP interface in the datasheet. This interface is compatible with the i.MX6 EIM bus controller but other types of external memory mapped parallel bus might work. xilinx-selectmap currently only supports the x8 mode where data is loaded at one byte per rising edge of the clock, with the MSb of each byte presented to the D0 pin. Signed-off-by: Charles Perry --- drivers/fpga/Kconfig | 8 +++ drivers/fpga/Makefile | 1 + drivers/fpga/xilinx-selectmap.c | 97 +++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 drivers/fpga/xilinx-selectmap.c diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index d27a1ebf40838..37b35f58f0dfb 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -67,6 +67,14 @@ config FPGA_MGR_STRATIX10_SOC config FPGA_MGR_XILINX_CORE tristate +config FPGA_MGR_XILINX_SELECTMAP + tristate "Xilinx Configuration over SelectMAP" + depends on HAS_IOMEM + select FPGA_MGR_XILINX_CORE + help + FPGA manager driver support for Xilinx FPGA configuration + over SelectMAP interface. + config FPGA_MGR_XILINX_SPI tristate "Xilinx Configuration over Slave Serial (SPI)" depends on SPI diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 7ec795b6a5a70..aeb89bb13517e 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o obj-$(CONFIG_FPGA_MGR_STRATIX10_SOC) += stratix10-soc.o obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o obj-$(CONFIG_FPGA_MGR_XILINX_CORE) += xilinx-core.o +obj-$(CONFIG_FPGA_MGR_XILINX_SELECTMAP) += xilinx-selectmap.o obj-$(CONFIG_FPGA_MGR_XILINX_SPI) += xilinx-spi.o obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o obj-$(CONFIG_FPGA_MGR_ZYNQMP_FPGA) += zynqmp-fpga.o diff --git a/drivers/fpga/xilinx-selectmap.c b/drivers/fpga/xilinx-selectmap.c new file mode 100644 index 0000000000000..b63f4623f8b2c --- /dev/null +++ b/drivers/fpga/xilinx-selectmap.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Xilinx Spartan6 and 7 Series SelectMAP interface driver + * + * (C) 2024 Charles Perry + * + * Manage Xilinx FPGA firmware loaded over the SelectMAP configuration + * interface. + */ + +#include "xilinx-core.h" + +#include +#include +#include +#include +#include +#include + +struct xilinx_selectmap_conf { + struct xilinx_fpga_core core; + void __iomem *base; +}; + +#define to_xilinx_selectmap_conf(obj) \ + container_of(obj, struct xilinx_selectmap_conf, core) + +static int xilinx_selectmap_write(struct xilinx_fpga_core *core, + const char *buf, size_t count) +{ + struct xilinx_selectmap_conf *conf = to_xilinx_selectmap_conf(core); + u32 i; + + for (i = 0; i < count; ++i) + writeb(buf[i], conf->base); + + return 0; +} + +static int xilinx_selectmap_probe(struct platform_device *pdev) +{ + struct xilinx_selectmap_conf *conf; + struct resource *r; + void __iomem *base; + struct gpio_desc *csi_b; + struct gpio_desc *rdwr_b; + + conf = devm_kzalloc(&pdev->dev, sizeof(*conf), GFP_KERNEL); + if (!conf) + return -ENOMEM; + + conf->core.dev = &pdev->dev; + conf->core.write = xilinx_selectmap_write; + + base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); + if (IS_ERR(base)) + return dev_err_probe(&pdev->dev, PTR_ERR(base), + "ioremap error\n"); + conf->base = base; + + /* CSI_B is active low */ + csi_b = devm_gpiod_get_optional(&pdev->dev, "csi", GPIOD_OUT_HIGH); + if (IS_ERR(csi_b)) + return dev_err_probe(&pdev->dev, PTR_ERR(csi_b), + "Failed to get CSI_B gpio\n"); + + /* RDWR_B is active low */ + rdwr_b = devm_gpiod_get_optional(&pdev->dev, "rdwr", GPIOD_OUT_HIGH); + if (IS_ERR(rdwr_b)) + return dev_err_probe(&pdev->dev, PTR_ERR(rdwr_b), + "Failed to get RDWR_B gpio\n"); + + return xilinx_core_probe(&conf->core); +} + +static const struct of_device_id xlnx_selectmap_of_match[] = { + { .compatible = "xlnx,fpga-xc7s-selectmap", }, // Spartan-7 + { .compatible = "xlnx,fpga-xc7a-selectmap", }, // Artix-7 + { .compatible = "xlnx,fpga-xc7k-selectmap", }, // Kintex-7 + { .compatible = "xlnx,fpga-xc7v-selectmap", }, // Virtex-7 + {}, +}; +MODULE_DEVICE_TABLE(of, xlnx_selectmap_of_match); + +static struct platform_driver xilinx_selectmap_driver = { + .driver = { + .name = "xilinx-selectmap", + .of_match_table = xlnx_selectmap_of_match, + }, + .probe = xilinx_selectmap_probe, +}; + +module_platform_driver(xilinx_selectmap_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Charles Perry "); +MODULE_DESCRIPTION("Load Xilinx FPGA firmware over SelectMap");