From patchwork Fri Oct 12 19:11:23 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roland Stigge X-Patchwork-Id: 1588071 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 9864B3FC1A for ; Fri, 12 Oct 2012 19:14:18 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TMkev-0000On-EO; Fri, 12 Oct 2012 19:12:33 +0000 Received: from mail.work-microwave.de ([62.245.205.51] helo=work-microwave.de) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TMke7-0000FV-CQ for linux-arm-kernel@lists.infradead.org; Fri, 12 Oct 2012 19:11:44 +0000 Received: from rst-pc1.lan.work-microwave.de ([192.168.11.78]) (authenticated bits=0) by mail.work-microwave.de with ESMTP id q9CJBePg008896 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 12 Oct 2012 20:11:40 +0100 Received: by rst-pc1.lan.work-microwave.de (Postfix, from userid 1000) id 03F96AE06B; Fri, 12 Oct 2012 21:11:39 +0200 (CEST) From: Roland Stigge To: grant.likely@secretlab.ca, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, w.sang@pengutronix.de, jbe@pengutronix.de, plagnioj@jcrosoft.com, highguy@gmail.com, broonie@opensource.wolfsonmicro.com Subject: [PATCH RFC 4/6 v3] gpio-max730x: Add block GPIO API Date: Fri, 12 Oct 2012 21:11:23 +0200 Message-Id: <1350069085-13283-5-git-send-email-stigge@antcom.de> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1350069085-13283-1-git-send-email-stigge@antcom.de> References: <1350069085-13283-1-git-send-email-stigge@antcom.de> X-FEAS-SYSTEM-WL: rst@work-microwave.de, 192.168.11.78 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -4.0 (----) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-4.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.1 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Roland Stigge X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org This patch adds block GPIO API support to the MAX730x driver. Due to hardware constraints in this chip, simultaneous access to GPIO lines can only be done in groups of 8: GPIOs 0-7, 8-15, 16-23, 24-27. However, setting and clearing will be done at once. Signed-off-by: Roland Stigge --- drivers/gpio/gpio-max730x.c | 60 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) --- linux-2.6.orig/drivers/gpio/gpio-max730x.c +++ linux-2.6/drivers/gpio/gpio-max730x.c @@ -146,6 +146,43 @@ static int max7301_get(struct gpio_chip return level; } +static unsigned max7301_get_block(struct gpio_chip *chip, unsigned mask) +{ + struct max7301 *ts = container_of(chip, struct max7301, chip); + int i, j; + unsigned result = 0; + + for (i = 0; i < 4; i++) { + if ((mask >> (i * 8)) & 0xFF) { /* i/o only if necessary */ + u8 in_level = ts->read(ts->dev, 0x44 + i * 8); + u8 in_mask = 0; + u8 out_level = (ts->out_level >> (i * 8 + 4)) & 0xFF; + u8 out_mask = 0; + + for (j = 0; j < 8; j++) { + int offset = 4 + i * 8 + j; + int config = (ts->port_config[offset >> 2] >> + ((offset & 3) << 1)) & + PIN_CONFIG_MASK; + + switch (config) { + case PIN_CONFIG_OUT: + out_mask |= BIT(j); + break; + case PIN_CONFIG_IN_WO_PULLUP: + case PIN_CONFIG_IN_PULLUP: + in_mask |= BIT(j); + } + } + + result |= ((unsigned)(in_level & in_mask) | + (out_level & out_mask)) << (i * 8); + } + } + + return result & mask; +} + static void max7301_set(struct gpio_chip *chip, unsigned offset, int value) { struct max7301 *ts = container_of(chip, struct max7301, chip); @@ -160,6 +197,27 @@ static void max7301_set(struct gpio_chip mutex_unlock(&ts->lock); } +static +void max7301_set_block(struct gpio_chip *chip, unsigned mask, unsigned values) +{ + struct max7301 *ts = container_of(chip, struct max7301, chip); + unsigned changes; + int i; + + mutex_lock(&ts->lock); + + changes = (ts->out_level ^ (values << 4)) & (mask << 4); + ts->out_level ^= changes; + + for (i = 0; i < 4; i++) { + if ((changes >> (i * 8 + 4)) & 0xFF) /* i/o only on change */ + ts->write(ts->dev, 0x44 + i * 8, + (ts->out_level >> (i * 8 + 4)) & 0xFF); + } + + mutex_unlock(&ts->lock); +} + int __devinit __max730x_probe(struct max7301 *ts) { struct device *dev = ts->dev; @@ -183,8 +241,10 @@ int __devinit __max730x_probe(struct max ts->chip.direction_input = max7301_direction_input; ts->chip.get = max7301_get; + ts->chip.get_block = max7301_get_block; ts->chip.direction_output = max7301_direction_output; ts->chip.set = max7301_set; + ts->chip.set_block = max7301_set_block; ts->chip.base = pdata->base; ts->chip.ngpio = PIN_NUMBER;