From patchwork Wed Sep 5 08:40:55 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 1406831 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 49F0CDF264 for ; Wed, 5 Sep 2012 08:45:39 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1T9BBZ-0000YG-5r; Wed, 05 Sep 2012 08:42:09 +0000 Received: from mail.free-electrons.com ([88.190.12.23]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1T9BAs-0000Jn-Cm for linux-arm-kernel@lists.infradead.org; Wed, 05 Sep 2012 08:41:27 +0000 Received: by mail.free-electrons.com (Postfix, from userid 106) id 9B7EC17D; Wed, 5 Sep 2012 10:41:24 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.free-electrons.com X-Spam-Level: X-Spam-Status: No, score=-3.2 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00 shortcircuit=no autolearn=ham version=3.3.1 Received: from localhost (col31-4-88-188-83-94.fbx.proxad.net [88.188.83.94]) by mail.free-electrons.com (Postfix) with ESMTPSA id 901A71B3; Wed, 5 Sep 2012 10:41:07 +0200 (CEST) From: Maxime Ripard To: linux-arm-kernel@lists.infradead.org, shawn.guo@linaro.org, grant.likely@secretlab.ca, linus.walleij@linaro.org Subject: [PATCH 6/8] gpio: 74x164: Add support for daisy-chaining Date: Wed, 5 Sep 2012 10:40:55 +0200 Message-Id: <1346834457-6257-6-git-send-email-maxime.ripard@free-electrons.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1346834457-6257-1-git-send-email-maxime.ripard@free-electrons.com> References: <1346834457-6257-1-git-send-email-maxime.ripard@free-electrons.com> X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.1 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.1 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -0.2 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: brian@crystalfontz.com 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 These types of shift registers can be daisy-chained, each new value sent while the output pin is kept low will make the previous value shift to the next register in the chain. This patch add support for chained shift registers, through the registers-number dt property. Signed-off-by: Maxime Ripard --- drivers/gpio/gpio-74x164.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index ff8d3d8..79b3e10 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -19,9 +19,10 @@ struct gen_74x164_chip { struct spi_device *spi; + u8 *buffer; struct gpio_chip gpio_chip; struct mutex lock; - u8 port_config; + u32 registers; int chip_select; }; @@ -32,23 +33,31 @@ static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc) static int __gen_74x164_write_config(struct gen_74x164_chip *chip) { - int ret; + int i, ret; gpio_set_value(chip->chip_select, 0); - ret = spi_write(chip->spi, - &chip->port_config, sizeof(chip->port_config)); + + for (i = chip->registers - 1; i >= 0; i--) { + ret = spi_write(chip->spi, + chip->buffer + i, sizeof(u8)); + if (ret) + return ret; + } + gpio_set_value(chip->chip_select, 1); - return ret; + return 0; } static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset) { struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc); + u8 bank = offset / 8; + u8 pin = offset % 8; int ret; mutex_lock(&chip->lock); - ret = (chip->port_config >> offset) & 0x1; + ret = (*(chip->buffer + bank) >> pin) & 0x1; mutex_unlock(&chip->lock); return ret; @@ -58,12 +67,14 @@ static void gen_74x164_set_value(struct gpio_chip *gc, unsigned offset, int val) { struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc); + u8 bank = offset / 8; + u8 pin = offset % 8; mutex_lock(&chip->lock); if (val) - chip->port_config |= (1 << offset); + *(chip->buffer + bank) |= (1 << pin); else - chip->port_config &= ~(1 << offset); + *(chip->buffer + bank) &= ~(1 << pin); __gen_74x164_write_config(chip); mutex_unlock(&chip->lock); @@ -110,7 +121,20 @@ static int __devinit gen_74x164_probe(struct spi_device *spi) chip->gpio_chip.get = gen_74x164_get_value; chip->gpio_chip.set = gen_74x164_set_value; chip->gpio_chip.base = -1; - chip->gpio_chip.ngpio = 8; + + if (of_property_read_u32(spi->dev.of_node, "registers-number", &chip->registers)) { + dev_err(&spi->dev, "Missing registers-number property in the DT.\n"); + ret = -EINVAL; + goto exit_destroy; + } + + chip->gpio_chip.ngpio = 8 * chip->registers; + chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL); + if (!chip->buffer) { + ret = -ENOMEM; + goto exit_destroy; + } + chip->gpio_chip.can_sleep = 1; chip->gpio_chip.dev = &spi->dev; chip->gpio_chip.owner = THIS_MODULE;