From patchwork Wed Aug 20 14:58:20 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Nowicki X-Patchwork-Id: 35693 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ob0-f199.google.com (mail-ob0-f199.google.com [209.85.214.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 3076420351 for ; Wed, 20 Aug 2014 14:58:34 +0000 (UTC) Received: by mail-ob0-f199.google.com with SMTP id wn1sf49665103obc.10 for ; Wed, 20 Aug 2014 07:58:33 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:sender:precedence:list-id:x-original-sender :x-original-authentication-results:mailing-list:list-post:list-help :list-archive:list-unsubscribe; bh=i1OyRUdEMqkd4QbUpdqMQ6Cj2iXkoLd03lF43Aa2vuU=; b=ZLUbnNugS2Ga9/wXtkcd6b68aCZm36mmeAM8N8RCQdXpxKJ/FwS6/QuGA24yCjqEzS LWL4aUQv9kFqaAe63vgRyRt+VR3cV72Mqj5WOZ3eT+6NT5j0QM5eXQYip69lLFWcQw0Y Dfbld9JlRa0vNjmZZwSX05FyOGtKJeFPuTkQvsvhV3/R5lqradptBdaJ/7X/1LDx0OhN 1+EQtf2/3Za2xEP+LVlIcuZZPUu2PDQKs1HxPvN9kf1u6n6mvxFAlo2GDRVs4J5ItC6L X9BbmPapMjF2ZMWRKXPuOH1O6dGM7SbnkhI1VKeSecK6K8zo0DtP08+eISXg1tUa5fBw wNVg== X-Gm-Message-State: ALoCoQkmJqN3+f1x0iqRvc8OId4JgtqhSPboQsDVM0JkdO/fNAW4EzhVrV+P5UTaDMMYs9crNYeI X-Received: by 10.182.123.163 with SMTP id mb3mr24688535obb.32.1408546713715; Wed, 20 Aug 2014 07:58:33 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.85.48 with SMTP id m45ls346387qgd.18.gmail; Wed, 20 Aug 2014 07:58:33 -0700 (PDT) X-Received: by 10.52.36.131 with SMTP id q3mr749851vdj.90.1408546713570; Wed, 20 Aug 2014 07:58:33 -0700 (PDT) Received: from mail-vc0-f169.google.com (mail-vc0-f169.google.com [209.85.220.169]) by mx.google.com with ESMTPS id cb8si10733836vcb.36.2014.08.20.07.58.33 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 20 Aug 2014 07:58:33 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.169 as permitted sender) client-ip=209.85.220.169; Received: by mail-vc0-f169.google.com with SMTP id le20so9432554vcb.0 for ; Wed, 20 Aug 2014 07:58:33 -0700 (PDT) X-Received: by 10.220.118.136 with SMTP id v8mr6768246vcq.50.1408546713466; Wed, 20 Aug 2014 07:58:33 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.45.67 with SMTP id uj3csp60141vcb; Wed, 20 Aug 2014 07:58:32 -0700 (PDT) X-Received: by 10.66.236.35 with SMTP id ur3mr53477382pac.35.1408546712480; Wed, 20 Aug 2014 07:58:32 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id ob5si25551015pbb.37.2014.08.20.07.58.20 for ; Wed, 20 Aug 2014 07:58:21 -0700 (PDT) Received-SPF: none (google.com: linux-acpi-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751421AbaHTO6N (ORCPT + 8 others); Wed, 20 Aug 2014 10:58:13 -0400 Received: from mail-wi0-f170.google.com ([209.85.212.170]:35949 "EHLO mail-wi0-f170.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750983AbaHTO6M (ORCPT ); Wed, 20 Aug 2014 10:58:12 -0400 Received: by mail-wi0-f170.google.com with SMTP id f8so6780857wiw.5 for ; Wed, 20 Aug 2014 07:58:11 -0700 (PDT) X-Received: by 10.180.212.77 with SMTP id ni13mr935922wic.42.1408546690989; Wed, 20 Aug 2014 07:58:10 -0700 (PDT) Received: from tn-HP-4.semihalf.com ([80.82.22.190]) by mx.google.com with ESMTPSA id fb12sm59157765wjc.43.2014.08.20.07.58.09 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 20 Aug 2014 07:58:10 -0700 (PDT) From: Tomasz Nowicki To: rjw@rjwysocki.net, linus.walleij@linaro.org, gnurou@gmail.com, mika.westerberg@linux.intel.com Cc: linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, linaro-acpi@lists.linaro.org, Tomasz Nowicki Subject: [PATCH] ACPI: Add GPIO-signaled event emulator. Date: Wed, 20 Aug 2014 16:58:20 +0200 Message-Id: <1408546700-19309-1-git-send-email-tomasz.nowicki@linaro.org> X-Mailer: git-send-email 1.9.1 Sender: linux-acpi-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: tomasz.nowicki@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.169 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , GPIO-signaled events is quite new thing in Linux kernel. There are not many board which can take advantage of it. However, GPIO events are very useful feature during work on ACPI subsystems. This commit emulates GPIO h/w behaviour and consists on write operation to debugfs file. GPIO device instance is still required in DSDT table along with _AEI resources and event methods. Please, see Kconfig help and driver head section for more details regarding tool usage. Signed-off-by: Tomasz Nowicki --- drivers/acpi/Kconfig | 10 ++ drivers/acpi/Makefile | 1 + drivers/acpi/gpio-acpi-evt-emu.c | 195 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 206 insertions(+) create mode 100644 drivers/acpi/gpio-acpi-evt-emu.c diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index fd54a74..8b9b74d 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -122,6 +122,16 @@ config ACPI_BUTTON To compile this driver as a module, choose M here: the module will be called button. +config ACPI_GPIO_EVT_EMULATE + bool "ACPI GPIO-signaled Events Emulation Support" + depends on DEBUG_FS + default n + help + This will enable your system to emulate GPIO-signaled event through + proc file system. User needs to trigger event method by + echo 1 > /sys/kernel/debug/acpi/events// + (where, GPIO DEVICE is a GPIO device name and PIN is a pin number). + config ACPI_VIDEO tristate "Video" depends on X86 && BACKLIGHT_CLASS_DEVICE diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 9fa20ff..24f9d8f 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -55,6 +55,7 @@ acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o ifdef CONFIG_ACPI_VIDEO acpi-y += video_detect.o endif +acpi-$(CONFIG_ACPI_GPIO_EVT_EMULATE) += gpio-acpi-evt-emu.o # These are (potentially) separate modules diff --git a/drivers/acpi/gpio-acpi-evt-emu.c b/drivers/acpi/gpio-acpi-evt-emu.c new file mode 100644 index 0000000..c39f501 --- /dev/null +++ b/drivers/acpi/gpio-acpi-evt-emu.c @@ -0,0 +1,195 @@ +/* + * Code to emulate GPIO-signaled events. + * + * The sole purpose of this module is to help with GPIO event triggering. + * Usage: + * 1. See the list of available GPIO devices and associated pins under: + * /sys/kernel/debug/acpi/events//. Only pins which are to + * be used as GPIO-signaled events will be listed (_AEI resources). + * + * 2. Trigger method corresponding to device pin number: + * $ echo 1 > /sys/kernel/debug/acpi/events// + */ + +/* + * Copyright (C) 2014, Linaro Ltd. + * Author: Tomasz Nowicki + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "acpica/accommon.h" +#include "acpica/acnamesp.h" + +#include "internal.h" + +#define _COMPONENT ACPI_SYSTEM_COMPONENT +ACPI_MODULE_NAME("gpio_acpi_evt_emu"); + +struct gpio_pin_parent_data { + acpi_handle handle; + struct dentry *debugfs_dir; + char *name; + unsigned int evt_count; +}; + +struct gpio_pin_data { + struct list_head list; + acpi_handle handle; + unsigned int pin; +}; + +static struct dentry *acpi_evt_debugfs_dir; +static LIST_HEAD(pin_data_list); + +static int gpio_evt_trigger(void *data, u64 val) +{ + struct gpio_pin_data *pin_data = (struct gpio_pin_data *)data; + int pin = pin_data->pin; + + if (ACPI_FAILURE(acpi_execute_simple_method(pin_data->handle, NULL, + pin <= 255 ? 0 : pin))) + pr_err(PREFIX "evaluating event method failed\n"); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(gpio_evt_emu_fops, NULL, gpio_evt_trigger, "%llu\n"); + +static acpi_status gpio_list_resource(struct acpi_resource *ares, void *context) +{ + struct acpi_resource_gpio *agpio = &ares->data.gpio; + struct gpio_pin_parent_data *parent_data = context; + struct dentry *pin_debugfs_dir; + struct gpio_pin_data *pin_data; + acpi_handle evt_handle; + acpi_status status; + char str_pin[5]; + char ev_name[5]; + int pin; + + if (ares->type != ACPI_RESOURCE_TYPE_GPIO) + return AE_OK; + + if (agpio->connection_type != ACPI_RESOURCE_GPIO_TYPE_INT) + return AE_OK; + + pin_data = kmalloc(sizeof(*pin_data), GFP_KERNEL); + if (!pin_data) + return AE_NO_MEMORY; + + pin = agpio->pin_table[0]; + snprintf(str_pin, 5, "%d", pin); + pin_debugfs_dir = debugfs_create_file(str_pin, S_IWUSR, + parent_data->debugfs_dir, + pin_data, + &gpio_evt_emu_fops); + if (!pin_debugfs_dir) { + status = AE_NULL_ENTRY; + goto fail; + } + + if (pin <= 255) + sprintf(ev_name, "_%c%02X", + agpio->triggering == ACPI_EDGE_SENSITIVE ? 'E' : 'L', + pin); + else + sprintf(ev_name, "_EVT"); + + status = acpi_get_handle(parent_data->handle, ev_name, &evt_handle); + if (ACPI_FAILURE(status)) { + pr_err(PREFIX "getting handle to <%s> of <%s> failed, there is no method related to 0x%02X pin\n", + ev_name, parent_data->name, pin); + goto fail; + } + + pin_data->handle = evt_handle; + pin_data->pin = pin; + list_add_tail(&pin_data->list, &pin_data_list); + + parent_data->evt_count++; + + return AE_OK; +fail: + kfree(pin_data); + return status; +} + +static acpi_status gpio_find_resource(acpi_handle handle, u32 lvl, + void *context, void **rv) +{ + struct acpi_namespace_node *node; + struct dentry *gpio_debugfs_dir; + struct gpio_pin_parent_data parent_data; + char gpio_name[5]; + + node = acpi_ns_validate_handle(handle); + if (!node) { + pr_err(PREFIX "Mapping GPIO handle to node failed\n"); + return AE_BAD_PARAMETER; + } + + snprintf(gpio_name, 5, "%s", node->name.ascii); + gpio_debugfs_dir = debugfs_create_dir(gpio_name, acpi_evt_debugfs_dir); + if (gpio_debugfs_dir == NULL) + return AE_OK; + + parent_data.debugfs_dir = gpio_debugfs_dir; + parent_data.handle = handle; + parent_data.name = gpio_name; + parent_data.evt_count = 0; + + acpi_walk_resources(handle, METHOD_NAME__AEI, gpio_list_resource, + &parent_data); + + if (!parent_data.evt_count) + debugfs_remove(gpio_debugfs_dir); + + return AE_OK; +} + +static int __init gpio_evt_emu_init(void) +{ + if (acpi_debugfs_dir == NULL) + return -ENOENT; + + acpi_evt_debugfs_dir = debugfs_create_dir("events", acpi_debugfs_dir); + if (acpi_evt_debugfs_dir == NULL) + return -ENOENT; + + acpi_get_devices(NULL, gpio_find_resource, NULL, NULL); + + return 0; +} + +static void __exit gpio_evt_emu_deinit(void) +{ + struct gpio_pin_data *pin_data, *temp; + + list_for_each_entry_safe(pin_data, temp, &pin_data_list, list) + kfree(pin_data); + + debugfs_remove_recursive(acpi_evt_debugfs_dir); +} + +module_init(gpio_evt_emu_init); +module_exit(gpio_evt_emu_deinit); + +MODULE_DESCRIPTION("GPIO-signaled events emulator"); +MODULE_LICENSE("GPL");