From patchwork Mon Feb 6 12:10:41 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 724473 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3vH5sh3MYTz9s3s for ; Mon, 6 Feb 2017 23:11:04 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.b="t9BSpFxi"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752014AbdBFMK6 (ORCPT ); Mon, 6 Feb 2017 07:10:58 -0500 Received: from mail-wr0-f173.google.com ([209.85.128.173]:33015 "EHLO mail-wr0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752000AbdBFMKz (ORCPT ); Mon, 6 Feb 2017 07:10:55 -0500 Received: by mail-wr0-f173.google.com with SMTP id i10so22070691wrb.0 for ; Mon, 06 Feb 2017 04:10:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Lxnxkc4wkLvuGRn/b1V9nM+lu3C0Gp7LNoLSoWx1Z1Y=; b=t9BSpFxiGZ08W07gDX05CgvcoV32hoDzBZDgUtyePHGx5DXuYA2KhB3rPjepnNTUD2 rStRQXppbxyQSHT8OwiaWU2IIkWHbYCclMr9orD9I4T7HDGoo35e/S4Qts+LrNzITVIU n0tla3o3UbV7Q+6qwy0MZzfwOIBG8sn+cdcC4mOJ9TQ9xmJhKs6SD2sdQzpWg+51IfyC M2IEIcK2As6x/LypZSlz72AbmDyGw8GqixEmy/kdRVlEdNw6yaozpfkug2eNYqUMBL7c 61ZGGVQoNr48mgE/CEkTUmRPCwYQfIVbq4s/oWi+6gsSkczojEogZEf+YM71kq6wfP3X M0yQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Lxnxkc4wkLvuGRn/b1V9nM+lu3C0Gp7LNoLSoWx1Z1Y=; b=aWYa1Sh7qgOeF57clqyRYOE7d2eJxe4eAMgutgrzcSpHw+qNnBY0tqVkFiDJcCXNew OJ63+yCUKO29HIy7YF/p8ZyXyhwxeLKkbn6YMnceq2OY2oTYei8IaSsJiLpmHfFQFu14 g6ua/tlxiHuKLUFasuEC/iQRNRJp+FueolJUkNsvrJMxXIDGnpiguIs2EMpwkpaw+rZB 2DhylibkYQWvNmHX/9GJDq02263fygNP7IuIxjEqdROfwroTsmgcHcRpbkeqWRhH/W7v a1ivdlXM7CXM3DKwnLwn3qCq8sgONIooLMjU/45dW7tcfqdGSzbl/ldzUGwKjfPo+KBm Z3Dw== X-Gm-Message-State: AIkVDXI2E/GCedzAdfd78pQoHi5ZMT57BWBmH93yLdJuGL+irIQKoNmQGJctAvVs+PW5BzyI X-Received: by 10.223.170.221 with SMTP id i29mr11566902wrc.131.1486383052984; Mon, 06 Feb 2017 04:10:52 -0800 (PST) Received: from localhost.localdomain ([90.63.244.31]) by smtp.gmail.com with ESMTPSA id g5sm1178532wrd.0.2017.02.06.04.10.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 06 Feb 2017 04:10:52 -0800 (PST) From: Bartosz Golaszewski To: Linus Walleij , Alexandre Courbot , Bamvor Jian Zhang , Thomas Gleixner Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Bartosz Golaszewski Subject: [PATCH v2 7/7] gpio: mockup: implement event injecting over debugfs Date: Mon, 6 Feb 2017 13:10:41 +0100 Message-Id: <1486383041-16758-8-git-send-email-bgolaszewski@baylibre.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1486383041-16758-1-git-send-email-bgolaszewski@baylibre.com> References: <1486383041-16758-1-git-send-email-bgolaszewski@baylibre.com> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Create a debugfs directory for every mockup chip and a single file for every line. Writing (0 or 1) to these files allows the user to inject line events (falling or rising edge respectively). Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-mockup.c | 115 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index 7d82d35..449918b 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -19,6 +19,10 @@ #include #include #include +#include +#include + +#include "gpiolib.h" #define GPIO_MOCKUP_NAME "gpio-mockup" #define GPIO_MOCKUP_MAX_GC 10 @@ -47,6 +51,13 @@ struct gpio_mockup_chip { struct gpio_chip gc; struct gpio_mockup_line_status *lines; struct gpio_mockup_irq_context irq_ctx; + struct dentry *dbg_dir; +}; + +struct gpio_mockup_dbgfs_private { + struct gpio_mockup_chip *chip; + struct gpio_desc *desc; + int offset; }; static int gpio_mockup_ranges[GPIO_MOCKUP_MAX_GC << 1]; @@ -58,6 +69,7 @@ module_param_named(gpio_mockup_named_lines, gpio_mockup_named_lines, bool, 0400); static const char gpio_mockup_name_start = 'A'; +static struct dentry *gpio_mockup_dbg_dir; static int gpio_mockup_get(struct gpio_chip *gc, unsigned int offset) { @@ -175,6 +187,94 @@ static int gpio_mockup_irqchip_setup(struct device *dev, return 0; } +static ssize_t gpio_mockup_event_write(struct file *file, + const char __user *usr_buf, + size_t size, loff_t *ppos) +{ + struct gpio_mockup_dbgfs_private *priv; + struct gpio_mockup_chip *chip; + struct seq_file *sfile; + struct gpio_desc *desc; + struct gpio_chip *gc; + int status, val; + char buf; + + sfile = file->private_data; + priv = sfile->private; + desc = priv->desc; + chip = priv->chip; + gc = &chip->gc; + + status = copy_from_user(&buf, usr_buf, 1); + if (status) + return status; + + if (buf == '0') + val = 0; + else if (buf == '1') + val = 1; + else + return -EINVAL; + + gpiod_set_value_cansleep(desc, val); + priv->chip->irq_ctx.irq = gc->irq_base + priv->offset; + irq_work_queue(&priv->chip->irq_ctx.work); + + return size; +} + +static int gpio_mockup_event_open(struct inode *inode, struct file *file) +{ + return single_open(file, NULL, inode->i_private); +} + +static const struct file_operations gpio_mockup_event_ops = { + .owner = THIS_MODULE, + .open = gpio_mockup_event_open, + .write = gpio_mockup_event_write, + .llseek = no_llseek, +}; + +static void gpio_mockup_debugfs_setup(struct device *dev, + struct gpio_mockup_chip *chip) +{ + struct gpio_mockup_dbgfs_private *priv; + struct dentry *evfile; + struct gpio_chip *gc; + char *name; + int i; + + gc = &chip->gc; + + chip->dbg_dir = debugfs_create_dir(gc->label, gpio_mockup_dbg_dir); + if (!chip->dbg_dir) + goto err; + + for (i = 0; i < gc->ngpio; i++) { + name = devm_kasprintf(dev, GFP_KERNEL, "%d", i); + if (!name) + goto err; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + goto err; + + priv->chip = chip; + priv->offset = i; + priv->desc = &gc->gpiodev->descs[i]; + + evfile = debugfs_create_file(name, 0200, chip->dbg_dir, priv, + &gpio_mockup_event_ops); + if (!evfile) + goto err; + } + + return; + +err: + dev_err(dev, "error creating debugfs directory\n"); +} + static int gpio_mockup_add(struct device *dev, struct gpio_mockup_chip *chip, const char *name, int base, int ngpio) @@ -209,7 +309,14 @@ static int gpio_mockup_add(struct device *dev, if (ret) return ret; - return devm_gpiochip_add_data(dev, &chip->gc, chip); + ret = devm_gpiochip_add_data(dev, &chip->gc, chip); + if (ret) + return ret; + + if (gpio_mockup_dbg_dir) + gpio_mockup_debugfs_setup(dev, chip); + + return 0; } static int gpio_mockup_probe(struct platform_device *pdev) @@ -277,6 +384,11 @@ static int __init mock_device_init(void) { int err; + gpio_mockup_dbg_dir = debugfs_create_dir("gpio-mockup-event", NULL); + if (!gpio_mockup_dbg_dir) + pr_err("%s: error creating debugfs directory\n", + GPIO_MOCKUP_NAME); + pdev = platform_device_alloc(GPIO_MOCKUP_NAME, -1); if (!pdev) return -ENOMEM; @@ -298,6 +410,7 @@ static int __init mock_device_init(void) static void __exit mock_device_exit(void) { + debugfs_remove_recursive(gpio_mockup_dbg_dir); platform_driver_unregister(&gpio_mockup_driver); platform_device_unregister(pdev); }