From patchwork Thu Nov 3 21:27:28 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Moritz Fischer X-Patchwork-Id: 691026 Return-Path: X-Original-To: incoming-imx@patchwork.ozlabs.org Delivered-To: patchwork-incoming-imx@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2001:1868:205::9]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3t8yn7367vz9t10 for ; Fri, 4 Nov 2016 08:30:35 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=ettus-com.20150623.gappssmtp.com header.i=@ettus-com.20150623.gappssmtp.com header.b=EYJYOgUf; dkim-atps=neutral Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1c2PYq-0007iA-OD; Thu, 03 Nov 2016 21:28:36 +0000 Received: from mail-yw0-x22f.google.com ([2607:f8b0:4002:c05::22f]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1c2PYl-0007dn-L7 for linux-arm-kernel@lists.infradead.org; Thu, 03 Nov 2016 21:28:33 +0000 Received: by mail-yw0-x22f.google.com with SMTP id l124so67077847ywb.3 for ; Thu, 03 Nov 2016 14:28:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ettus-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=6EOjv5NeSe8tj67X3K50zWwNS4IdRZ/2Xl6Yko1motE=; b=EYJYOgUfEqDLP61tfspmoX9gQ+mRSVd38j8YWQ1n9cubnHlFh1k8y1kohvUgA2Raau ld587FNBo8FRfExTHLXvRStakcG7KgZn3H8ArflnuQFsiiYrdgsLWcqpEC4z8PavVL8f 9JBccgwlOZEQPXWY1Bb/06XKi2vzDZn+pClnr8o10kPLccLCYGwSzNfWO59+GGtky/wF +sbk2vn0FbcPMJHJITrukx5/zOK7I1+8/JTv3wkR2/7qdPP0JgggYTicR8P4FQA7DaM0 pdO8yByAcvS3dVok3QuNjrRQc0ooejY+9L7Rqpnoh6QRrwfLkWkv5eb8dW2TEWZwR/wM jhEw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=6EOjv5NeSe8tj67X3K50zWwNS4IdRZ/2Xl6Yko1motE=; b=Q/t0SS7hbBdSMIMjFVnmfIpMGbzEZk0mrcJiZivaQPYtKVk1uRyeoBVT5SIlY9Dxxa PIwT2Qv5KA3r7MQRX0NmqyXy493RJI0nM5ol5IpVMrmArCq4b8JVMLdbD/228eaaQvPr i/rUroetfz8xTu8djqfcG1KspdDH2XC7RHfAeEWxramshMQ2jby80Y16C4WlhWVC9zlS Bf3FaVR/cWtM2SZvkFZOzlNs/l6MkDeZVaMF13HyWZUgfZHzoi06RewOAP11aIOB1taa Z+p2q6bcHLdFE4sVDF1VQjOi1QwILV8dJ0abudtI+MvFokLIflGSUhiQmQshBCxYT3Yj epJA== X-Gm-Message-State: ABUngvcIAb0rlkGK+qoCO4/zZ7mnwnXtnQLCmaZaYnLzHfgE7KmC8KzM1RyGkcBDRUnRObLY X-Received: by 10.36.118.82 with SMTP id z79mr39750itb.74.1478208489866; Thu, 03 Nov 2016 14:28:09 -0700 (PDT) Received: from archbook.ni.corp.natinst.com ([198.233.217.214]) by smtp.gmail.com with ESMTPSA id q6sm3507417ioe.12.2016.11.03.14.28.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 03 Nov 2016 14:28:09 -0700 (PDT) From: Moritz Fischer To: atull@opensource.altera.com Subject: [RFC] fpga mgr: Introduce FPGA capabilities Date: Thu, 3 Nov 2016 15:27:28 -0600 Message-Id: <20161103212728.9908-1-moritz.fischer@ettus.com> X-Mailer: git-send-email 2.10.0 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20161103_142831_871142_A78134C1 X-CRM114-Status: GOOD ( 18.10 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [2607:f8b0:4002:c05:0:0:0:22f listed in] [list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Moritz Fischer , linux-kernel@vger.kernel.org, Michal Simek , linux-arm-kernel@lists.infradead.org, delicious.quinoa@gmail.com, =?UTF-8?q?S=C3=B6ren=20Brinkmann?= , moritz.fischer.private@gmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org List-Id: linux-imx-kernel.lists.patchwork.ozlabs.org Add FPGA capabilities as a way to express the capabilities of a given FPGA manager. Removes code duplication by comparing the low-level driver's capabilities at the framework level rather than having each driver check for supported operations in the write_init() callback. This allows for extending with additional capabilities, similar to the the dmaengine framework's implementation. Signed-off-by: Moritz Fischer Cc: Alan Tull Cc: Michal Simek Cc: Sören Brinkmann Cc: linux-kernel@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org --- Hi all, this is another RFC (this one is against mainline) implementing fpga capabilities to centralize the checks for different operations. If we agree this is the way forward, I'll rebase it on top of Alan's series once that went in (and add potential drivers we added by then. Cheers, Moritz PS: I'm not sure if the checkpatch warning is a false positive ... --- drivers/fpga/fpga-mgr.c | 14 +++++++++++++ drivers/fpga/socfpga.c | 10 +++++----- drivers/fpga/zynq-fpga.c | 7 ++++++- include/linux/fpga/fpga-mgr.h | 46 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 70 insertions(+), 7 deletions(-) diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index 953dc91..21c508a 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -49,6 +49,18 @@ int fpga_mgr_buf_load(struct fpga_manager *mgr, u32 flags, const char *buf, struct device *dev = &mgr->dev; int ret; + if (flags & FPGA_MGR_PARTIAL_RECONFIG && + !fpga_mgr_has_cap(FPGA_MGR_CAP_PARTIAL_RECONF, mgr->caps)) { + dev_err(dev, "Partial reconfiguration not supported\n"); + return -ENOTSUPP; + } + + if (flags & FPGA_MGR_FULL_RECONFIG && + !fpga_mgr_has_cap(FPGA_MGR_CAP_FULL_RECONF, mgr->caps)) { + dev_err(dev, "Full reconfiguration not supported\n"); + return -ENOTSUPP; + } + /* * Call the low level driver's write_init function. This will do the * device-specific things to get the FPGA into the state where it is @@ -245,12 +257,14 @@ EXPORT_SYMBOL_GPL(fpga_mgr_put); * @dev: fpga manager device from pdev * @name: fpga manager name * @mops: pointer to structure of fpga manager ops + * @caps: fpga manager capabilites * @priv: fpga manager private data * * Return: 0 on success, negative error code otherwise. */ int fpga_mgr_register(struct device *dev, const char *name, const struct fpga_manager_ops *mops, + fpga_mgr_cap_mask_t caps, void *priv) { struct fpga_manager *mgr; diff --git a/drivers/fpga/socfpga.c b/drivers/fpga/socfpga.c index 27d2ff2..fd9760c 100644 --- a/drivers/fpga/socfpga.c +++ b/drivers/fpga/socfpga.c @@ -413,10 +413,6 @@ static int socfpga_fpga_ops_configure_init(struct fpga_manager *mgr, u32 flags, struct socfpga_fpga_priv *priv = mgr->priv; int ret; - if (flags & FPGA_MGR_PARTIAL_RECONFIG) { - dev_err(&mgr->dev, "Partial reconfiguration not supported.\n"); - return -EINVAL; - } /* Steps 1 - 5: Reset the FPGA */ ret = socfpga_fpga_reset(mgr); if (ret) @@ -555,6 +551,7 @@ static int socfpga_fpga_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct socfpga_fpga_priv *priv; struct resource *res; + fpga_mgr_cap_mask_t caps; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -580,8 +577,11 @@ static int socfpga_fpga_probe(struct platform_device *pdev) if (ret) return ret; + fpga_mgr_cap_zero(&caps); + fpga_mgr_cap_set(FPGA_MGR_CAP_FULL_RECONF, caps); + return fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager", - &socfpga_fpga_ops, priv); + &socfpga_fpga_ops, caps, priv); } static int socfpga_fpga_remove(struct platform_device *pdev) diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c index c2fb412..1d37ff0 100644 --- a/drivers/fpga/zynq-fpga.c +++ b/drivers/fpga/zynq-fpga.c @@ -410,6 +410,7 @@ static int zynq_fpga_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct zynq_fpga_priv *priv; struct resource *res; + fpga_mgr_cap_mask_t caps; int err; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -461,9 +462,13 @@ static int zynq_fpga_probe(struct platform_device *pdev) zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK); clk_disable(priv->clk); + fpga_mgr_cap_zero(&caps); + fpga_mgr_cap_set(FPGA_MGR_CAP_FULL_RECONF, caps); + fpga_mgr_cap_set(FPGA_MGR_CAP_PARTIAL_RECONF, caps); + err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager", - &zynq_fpga_ops, priv); + &zynq_fpga_ops, caps, priv); if (err) { dev_err(dev, "unable to register FPGA manager"); clk_unprepare(priv->clk); diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h index 0940bf4..a0bf750 100644 --- a/include/linux/fpga/fpga-mgr.h +++ b/include/linux/fpga/fpga-mgr.h @@ -67,6 +67,47 @@ enum fpga_mgr_states { * FPGA_MGR_PARTIAL_RECONFIG: do partial reconfiguration if supported */ #define FPGA_MGR_PARTIAL_RECONFIG BIT(0) +#define FPGA_MGR_FULL_RECONFIG BIT(1) + +enum fpga_manager_capability { + FPGA_MGR_CAP_PARTIAL_RECONF, + FPGA_MGR_CAP_FULL_RECONF, + +/* last capability type for creation of the capabilities mask */ + FPGA_MGR_CAP_END, +}; + +typedef struct { DECLARE_BITMAP(bits, FPGA_MGR_CAP_END); } fpga_mgr_cap_mask_t; + +#define fpga_mgr_has_cap(cap, mask) __fpga_mgr_has_cap((cap), &(mask)) +static inline int __fpga_mgr_has_cap(enum fpga_manager_capability cap, + fpga_mgr_cap_mask_t *mask) +{ + return test_bit(cap, mask->bits); +} + +#define fpga_mgr_cap_zero(mask) __fpga_mgr_cap_zero(mask) +static inline void __fpga_mgr_cap_zero(fpga_mgr_cap_mask_t *mask) +{ + bitmap_zero(mask->bits, FPGA_MGR_CAP_END); +} + +#define fpga_mgr_cap_clear(cap, mask) __fpga_mgr_cap_clear((cap), &(mask)) +static inline void __fpga_mgr_cap_clear(enum fpga_manager_capability cap, + fpga_mgr_cap_mask_t *mask) + +{ + clear_bit(cap, mask->bits); +} + +#define fpga_mgr_cap_set(cap, mask) __fpga_mgr_cap_set((cap), &(mask)) +static inline void __fpga_mgr_cap_set(enum fpga_manager_capability cap, + fpga_mgr_cap_mask_t *mask) + +{ + set_bit(cap, mask->bits); +} + /** * struct fpga_manager_ops - ops for low level fpga manager drivers @@ -105,6 +146,7 @@ struct fpga_manager { enum fpga_mgr_states state; const struct fpga_manager_ops *mops; void *priv; + fpga_mgr_cap_mask_t caps; }; #define to_fpga_manager(d) container_of(d, struct fpga_manager, dev) @@ -120,7 +162,9 @@ struct fpga_manager *of_fpga_mgr_get(struct device_node *node); void fpga_mgr_put(struct fpga_manager *mgr); int fpga_mgr_register(struct device *dev, const char *name, - const struct fpga_manager_ops *mops, void *priv); + const struct fpga_manager_ops *mops, + fpga_mgr_cap_mask_t caps, + void *priv); void fpga_mgr_unregister(struct device *dev);