From patchwork Fri Jan 30 10:46:04 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 44034 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f197.google.com (mail-wi0-f197.google.com [209.85.212.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 08E7620CA8 for ; Fri, 30 Jan 2015 10:46:31 +0000 (UTC) Received: by mail-wi0-f197.google.com with SMTP id n3sf3547wiv.0 for ; Fri, 30 Jan 2015 02:46:28 -0800 (PST) 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=GmBD0iGxz/hTNw0wI08+MSNfoAjUtdAZygemcixW0ks=; b=Kgb7VtW5roRJwaz0Sov3IsV4G7nzLWIx7rR3iCmHX+sICOX+7aGSlzapSqyKuMvDFq 1fa8J3YitNFizCiGAEgQWoPgU8/dqJBtEXOdT5se0gq6dLMTUhgt/9+6e+VpOguD7xOf QZ/xlCChnEyfNIVDLhVMxLEk4t/3TA245t7am4mlGFATS70mLbUW+VN+9Nj7twVVk4Fa zECQfJFPieWiSDM8KxffXkwJBTVpHoo2Z+CvcU0YU4bS+onTx+xXG7DVO6RINl0Km15S 5yzLn9gXw93/h8J2aOKAOJwaC5Cou6kYkYczsWdIvxU6PEF+P/HrSISg6zdkBRsNUqE9 7cMw== X-Gm-Message-State: ALoCoQlETO3Acu8qk1U/Jkgjy+gT3C+RGugdb/asN+98n2F6EdxvexURxK3z/WteUPx0fsXrXSXd X-Received: by 10.194.142.174 with SMTP id rx14mr731301wjb.4.1422614778375; Fri, 30 Jan 2015 02:46:18 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.42.175 with SMTP id p15ls346055lal.58.gmail; Fri, 30 Jan 2015 02:46:18 -0800 (PST) X-Received: by 10.112.130.65 with SMTP id oc1mr5762849lbb.7.1422614778206; Fri, 30 Jan 2015 02:46:18 -0800 (PST) Received: from mail-lb0-f169.google.com (mail-lb0-f169.google.com. [209.85.217.169]) by mx.google.com with ESMTPS id xp1si8219583lbb.14.2015.01.30.02.46.17 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 30 Jan 2015 02:46:17 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.169 as permitted sender) client-ip=209.85.217.169; Received: by mail-lb0-f169.google.com with SMTP id f15so35698731lbj.0 for ; Fri, 30 Jan 2015 02:46:17 -0800 (PST) X-Received: by 10.112.173.202 with SMTP id bm10mr5851920lbc.24.1422614777766; Fri, 30 Jan 2015 02:46:17 -0800 (PST) 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.112.35.133 with SMTP id h5csp239484lbj; Fri, 30 Jan 2015 02:46:16 -0800 (PST) X-Received: by 10.68.135.226 with SMTP id pv2mr8158429pbb.48.1422614775801; Fri, 30 Jan 2015 02:46:15 -0800 (PST) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id qn10si13166490pdb.256.2015.01.30.02.46.15 for ; Fri, 30 Jan 2015 02:46:15 -0800 (PST) Received-SPF: none (google.com: linux-gpio-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 S1760186AbbA3KqM (ORCPT ); Fri, 30 Jan 2015 05:46:12 -0500 Received: from mail-la0-f50.google.com ([209.85.215.50]:38932 "EHLO mail-la0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1760059AbbA3KqL (ORCPT ); Fri, 30 Jan 2015 05:46:11 -0500 Received: by mail-la0-f50.google.com with SMTP id hs14so22877586lab.9 for ; Fri, 30 Jan 2015 02:46:09 -0800 (PST) X-Received: by 10.112.163.229 with SMTP id yl5mr5822970lbb.60.1422614769335; Fri, 30 Jan 2015 02:46:09 -0800 (PST) Received: from localhost.localdomain ([85.235.11.236]) by mx.google.com with ESMTPSA id h3sm648806lab.36.2015.01.30.02.46.07 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 30 Jan 2015 02:46:08 -0800 (PST) From: Linus Walleij To: linux-gpio@vger.kernel.org Cc: Alexandre Courbot , Linus Walleij , Semen Protsenko , Mans Rullgard Subject: [PATCH 2/2] gpio: max732x: convert to GPIOLIB_IRQCHIP Date: Fri, 30 Jan 2015 11:46:04 +0100 Message-Id: <1422614764-5430-1-git-send-email-linus.walleij@linaro.org> X-Mailer: git-send-email 1.9.3 Sender: linux-gpio-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-gpio@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: linus.walleij@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.217.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: , Take a sweep to bring the irq support for the MAX732x expanders into the gpiolib core to cut down on duplicated code. Only compile tested! I need some feedback from people using this expander with interrupts to tell me if things go right or wrong when I do this. Cc: Semen Protsenko Cc: Mans Rullgard Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-max732x.c | 134 ++++++++++++++------------------------------ 2 files changed, 43 insertions(+), 93 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index ae5cb4d517c6..d0c9399a17b3 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -543,7 +543,6 @@ config GPIO_MAX7300 config GPIO_MAX732X tristate "MAX7319, MAX7320-7327 I2C Port Expanders" depends on I2C - select IRQ_DOMAIN help Say yes here to support the MAX7319, MAX7320-7327 series of I2C Port Expanders. Each IO port on these chips has a fixed role of @@ -563,6 +562,7 @@ config GPIO_MAX732X config GPIO_MAX732X_IRQ bool "Interrupt controller support for MAX732x" depends on GPIO_MAX732X=y + select GPIOLIB_IRQCHIP help Say yes here to enable the max732x to be used as an interrupt controller. It requires the driver to be built in the kernel. diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index a095b2393fe9..0fa4543c5e02 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -4,6 +4,7 @@ * Copyright (C) 2007 Marvell International Ltd. * Copyright (C) 2008 Jack Ren * Copyright (C) 2008 Eric Miao + * Copyright (C) 2015 Linus Walleij * * Derived from drivers/gpio/pca953x.c * @@ -16,10 +17,8 @@ #include #include #include -#include +#include #include -#include -#include #include #include #include @@ -150,9 +149,7 @@ struct max732x_chip { uint8_t reg_out[2]; #ifdef CONFIG_GPIO_MAX732X_IRQ - struct irq_domain *irq_domain; struct mutex irq_lock; - int irq_base; uint8_t irq_mask; uint8_t irq_mask_cur; uint8_t irq_trig_raise; @@ -356,35 +353,26 @@ static void max732x_irq_update_mask(struct max732x_chip *chip) mutex_unlock(&chip->lock); } -static int max732x_gpio_to_irq(struct gpio_chip *gc, unsigned off) -{ - struct max732x_chip *chip = to_max732x(gc); - - if (chip->irq_domain) { - return irq_create_mapping(chip->irq_domain, - chip->irq_base + off); - } else { - return -ENXIO; - } -} - static void max732x_irq_mask(struct irq_data *d) { - struct max732x_chip *chip = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct max732x_chip *chip = to_max732x(gc); chip->irq_mask_cur &= ~(1 << d->hwirq); } static void max732x_irq_unmask(struct irq_data *d) { - struct max732x_chip *chip = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct max732x_chip *chip = to_max732x(gc); chip->irq_mask_cur |= 1 << d->hwirq; } static void max732x_irq_bus_lock(struct irq_data *d) { - struct max732x_chip *chip = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct max732x_chip *chip = to_max732x(gc); mutex_lock(&chip->irq_lock); chip->irq_mask_cur = chip->irq_mask; @@ -392,7 +380,8 @@ static void max732x_irq_bus_lock(struct irq_data *d) static void max732x_irq_bus_sync_unlock(struct irq_data *d) { - struct max732x_chip *chip = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct max732x_chip *chip = to_max732x(gc); uint16_t new_irqs; uint16_t level; @@ -410,7 +399,8 @@ static void max732x_irq_bus_sync_unlock(struct irq_data *d) static int max732x_irq_set_type(struct irq_data *d, unsigned int type) { - struct max732x_chip *chip = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct max732x_chip *chip = to_max732x(gc); uint16_t off = d->hwirq; uint16_t mask = 1 << off; @@ -492,7 +482,8 @@ static irqreturn_t max732x_irq_handler(int irq, void *devid) do { level = __ffs(pending); - handle_nested_irq(irq_find_mapping(chip->irq_domain, level)); + handle_nested_irq(irq_find_mapping(chip->gpio_chip.irqdomain, + level)); pending &= ~(1 << level); } while (pending); @@ -500,86 +491,50 @@ static irqreturn_t max732x_irq_handler(int irq, void *devid) return IRQ_HANDLED; } -static int max732x_irq_map(struct irq_domain *h, unsigned int virq, - irq_hw_number_t hw) -{ - struct max732x_chip *chip = h->host_data; - - if (!(chip->dir_input & (1 << hw))) { - dev_err(&chip->client->dev, - "Attempt to map output line as IRQ line: %lu\n", - hw); - return -EPERM; - } - - irq_set_chip_data(virq, chip); - irq_set_chip_and_handler(virq, &max732x_irq_chip, - handle_edge_irq); - irq_set_nested_thread(virq, 1); -#ifdef CONFIG_ARM - /* ARM needs us to explicitly flag the IRQ as valid - * and will set them noprobe when we do so. */ - set_irq_flags(virq, IRQF_VALID); -#else - irq_set_noprobe(virq); -#endif - - return 0; -} - -static struct irq_domain_ops max732x_irq_domain_ops = { - .map = max732x_irq_map, - .xlate = irq_domain_xlate_twocell, -}; - -static void max732x_irq_teardown(struct max732x_chip *chip) -{ - if (chip->client->irq && chip->irq_domain) - irq_domain_remove(chip->irq_domain); -} - static int max732x_irq_setup(struct max732x_chip *chip, const struct i2c_device_id *id) { struct i2c_client *client = chip->client; struct max732x_platform_data *pdata = dev_get_platdata(&client->dev); int has_irq = max732x_features[id->driver_data] >> 32; + int irq_base = 0; int ret; if (((pdata && pdata->irq_base) || client->irq) && has_irq != INT_NONE) { if (pdata) - chip->irq_base = pdata->irq_base; + irq_base = pdata->irq_base; chip->irq_features = has_irq; mutex_init(&chip->irq_lock); - chip->irq_domain = irq_domain_add_simple(client->dev.of_node, - chip->gpio_chip.ngpio, chip->irq_base, - &max732x_irq_domain_ops, chip); - if (!chip->irq_domain) { - dev_err(&client->dev, "Failed to create IRQ domain\n"); - return -ENOMEM; - } - - ret = request_threaded_irq(client->irq, - NULL, - max732x_irq_handler, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - dev_name(&client->dev), chip); + ret = devm_request_threaded_irq(&client->dev, + client->irq, + NULL, + max732x_irq_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + dev_name(&client->dev), chip); if (ret) { dev_err(&client->dev, "failed to request irq %d\n", client->irq); - goto out_failed; + return ret; } - - chip->gpio_chip.to_irq = max732x_gpio_to_irq; + ret = gpiochip_irqchip_add(&chip->gpio_chip, + &max732x_irq_chip, + irq_base, + handle_edge_irq, + IRQ_TYPE_NONE); + if (ret) { + dev_err(&client->dev, + "could not connect irqchip to gpiochip\n"); + return ret; + } + gpiochip_set_chained_irqchip(&chip->gpio_chip, + &max732x_irq_chip, + client->irq, + NULL); } return 0; - -out_failed: - max732x_irq_teardown(chip); - return ret; } #else /* CONFIG_GPIO_MAX732X_IRQ */ @@ -595,10 +550,6 @@ static int max732x_irq_setup(struct max732x_chip *chip, return 0; } - -static void max732x_irq_teardown(struct max732x_chip *chip) -{ -} #endif static int max732x_setup_gpio(struct max732x_chip *chip, @@ -730,13 +681,15 @@ static int max732x_probe(struct i2c_client *client, if (nr_port > 8) max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]); - ret = max732x_irq_setup(chip, id); + ret = gpiochip_add(&chip->gpio_chip); if (ret) goto out_failed; - ret = gpiochip_add(&chip->gpio_chip); - if (ret) + ret = max732x_irq_setup(chip, id); + if (ret) { + gpiochip_remove(&chip->gpio_chip); goto out_failed; + } if (pdata && pdata->setup) { ret = pdata->setup(client, chip->gpio_chip.base, @@ -751,7 +704,6 @@ static int max732x_probe(struct i2c_client *client, out_failed: if (chip->client_dummy) i2c_unregister_device(chip->client_dummy); - max732x_irq_teardown(chip); return ret; } @@ -774,8 +726,6 @@ static int max732x_remove(struct i2c_client *client) gpiochip_remove(&chip->gpio_chip); - max732x_irq_teardown(chip); - /* unregister any dummy i2c_client */ if (chip->client_dummy) i2c_unregister_device(chip->client_dummy);