From patchwork Wed Jan 14 14:46:38 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rojhalat Ibrahim X-Patchwork-Id: 428987 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 0151214027C for ; Thu, 15 Jan 2015 01:46:42 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753223AbbANOql (ORCPT ); Wed, 14 Jan 2015 09:46:41 -0500 Received: from mail-out.m-online.net ([212.18.0.9]:54079 "EHLO mail-out.m-online.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753192AbbANOqk (ORCPT ); Wed, 14 Jan 2015 09:46:40 -0500 Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 3kMs1B5l5jz3hjRk; Wed, 14 Jan 2015 15:46:38 +0100 (CET) Received: from mail.dmz.schenk (host-82-135-47-202.customer.m-online.net [82.135.47.202]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPS id 3kMs1B4fnmzvh2K; Wed, 14 Jan 2015 15:46:38 +0100 (CET) Received: from gwhaus.rt.schenk (gwhaus.rt.schenk [172.22.0.4]) by mail.dmz.schenk (Postfix) with SMTP id 5A41B16117C; Wed, 14 Jan 2015 15:46:38 +0100 (CET) Received: from pcimr.localnet (pcimr.rt.schenk [172.22.10.20]) by gwhaus.rt.schenk (Postfix) with ESMTP id 42157240716; Wed, 14 Jan 2015 15:46:38 +0100 (CET) From: Rojhalat Ibrahim To: "linux-gpio@vger.kernel.org" Cc: Linus Walleij , Alexandre Courbot Subject: [PATCH][v2] gpio-generic: add bgpio_set_multiple functions Date: Wed, 14 Jan 2015 15:46:38 +0100 Message-ID: <3218650.3Kg56DKAcg@pcimr> User-Agent: KMail/4.14.3 (Linux/3.13.6; KDE/4.14.3; x86_64; ; ) MIME-Version: 1.0 Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Add set_multiple functions to the generic driver for memory-mapped GPIO controllers to improve performance when setting multiple outputs simultaneously. Signed-off-by: Rojhalat Ibrahim --- v2: refactor to reduce duplicate code drivers/gpio/gpio-generic.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) -- 2.0.5 -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c index 16f6115..b92a690 100644 --- a/drivers/gpio/gpio-generic.c +++ b/drivers/gpio/gpio-generic.c @@ -190,6 +190,79 @@ static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) spin_unlock_irqrestore(&bgc->lock, flags); } +static void bgpio_multiple_get_masks(struct bgpio_chip *bgc, + unsigned long *mask, unsigned long *bits, + unsigned long *set_mask, + unsigned long *clear_mask) +{ + int i; + + *set_mask = 0; + *clear_mask = 0; + + for (i = 0; i < bgc->bits; i++) { + if (*mask == 0) + break; + if (__test_and_clear_bit(i, mask)) { + if (test_bit(i, bits)) + *set_mask |= bgc->pin2mask(bgc, i); + else + *clear_mask |= bgc->pin2mask(bgc, i); + } + } +} + +static void bgpio_set_multiple_single_reg(struct bgpio_chip *bgc, + unsigned long *mask, + unsigned long *bits, + void __iomem *reg) +{ + unsigned long flags; + unsigned long set_mask, clear_mask; + + spin_lock_irqsave(&bgc->lock, flags); + + bgpio_multiple_get_masks(bgc, mask, bits, &set_mask, &clear_mask); + + bgc->data |= set_mask; + bgc->data &= ~clear_mask; + + bgc->write_reg(reg, bgc->data); + + spin_unlock_irqrestore(&bgc->lock, flags); +} + +static void bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits) +{ + struct bgpio_chip *bgc = to_bgpio_chip(gc); + + bgpio_set_multiple_single_reg(bgc, mask, bits, bgc->reg_dat); +} + +static void bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits) +{ + struct bgpio_chip *bgc = to_bgpio_chip(gc); + + bgpio_set_multiple_single_reg(bgc, mask, bits, bgc->reg_set); +} + +static void bgpio_set_multiple_with_clear(struct gpio_chip *gc, + unsigned long *mask, + unsigned long *bits) +{ + struct bgpio_chip *bgc = to_bgpio_chip(gc); + unsigned long set_mask, clear_mask; + + bgpio_multiple_get_masks(bgc, mask, bits, &set_mask, &clear_mask); + + if (set_mask) + bgc->write_reg(bgc->reg_set, set_mask); + if (clear_mask) + bgc->write_reg(bgc->reg_clr, clear_mask); +} + static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) { return 0; @@ -354,11 +427,14 @@ static int bgpio_setup_io(struct bgpio_chip *bgc, bgc->reg_set = set; bgc->reg_clr = clr; bgc->gc.set = bgpio_set_with_clear; + bgc->gc.set_multiple = bgpio_set_multiple_with_clear; } else if (set && !clr) { bgc->reg_set = set; bgc->gc.set = bgpio_set_set; + bgc->gc.set_multiple = bgpio_set_multiple_set; } else { bgc->gc.set = bgpio_set; + bgc->gc.set_multiple = bgpio_set_multiple; } bgc->gc.get = bgpio_get;