From patchwork Fri Oct 20 15:10:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 116506 Delivered-To: patch@linaro.org Received: by 10.140.22.164 with SMTP id 33csp1799113qgn; Fri, 20 Oct 2017 08:12:39 -0700 (PDT) X-Received: by 10.84.178.4 with SMTP id y4mr4529345plb.142.1508512359200; Fri, 20 Oct 2017 08:12:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1508512359; cv=none; d=google.com; s=arc-20160816; b=XlNQadfKGhBnni7OW+puBvveqfHRBq+es3CW2WUPRi1IJ49bgXRoyb2wEIOW9sALDn 4NcMyhllstUmDU2kaCNCWc6W1NCLD4kyIzZquUKCe6d2xYHP8Iwiq7jOM6L6j6yL4w2R 3wl0pVmksQnd3dwm30GNIltl0txjXqphGXDx8IbYusTF1SEYSQYQCeWhP6Df/RSfH51E nVt30dPeAO4FlRnut5LmOIZzUWNzLMvEEg+G8gip3SBoS8nD7pWFouyGChg2UWjZPLap QLbqotC/6xK8dRqwJ/6vtWBcBxgBLn1X5GbaUrclgEZbwKLmgKcwOi0R5yu23K93TI/+ en4Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=6Im32Gvr2HMViuitfS57HwZbxvZ1cBLs71MBzSJnlzA=; b=YSvGje6xQFkJLv2sf7kPb40OYey4lBH4Ns6arm5LzHtbXIVljkg0BEIxNogDyG6Aiy YAZ9lJIcwZt0r4i6MDzUr7DtsiFJUMI91MNT/iITWGmBcLcx5A0j3bxL7HJb2jJCU5n/ Vs+6wTiD6ATxHfI4ZPEwIqAKNOGdmW3pYzp4CJdkdazU6exkV0hYeR6B1EyBGnHd/5nB 4RTYJBCHFtXIadW9QEosL6jLKufuqBLcs6YdOIet08THwQ8CHUgmXEvQe81kJrDHQ0UG dWp66PpyeOzsRWy37FjkUxUHlPe+coO7yTl70r5XAxv179p8tIEmxR18anvgVSJn/Vzk VGBg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=kRxRp+3f; spf=pass (google.com: best guess record for domain of linux-gpio-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-gpio-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j73si819333pge.369.2017.10.20.08.12.38; Fri, 20 Oct 2017 08:12:39 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-gpio-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=kRxRp+3f; spf=pass (google.com: best guess record for domain of linux-gpio-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-gpio-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751857AbdJTPMi (ORCPT + 6 others); Fri, 20 Oct 2017 11:12:38 -0400 Received: from mail-lf0-f65.google.com ([209.85.215.65]:49105 "EHLO mail-lf0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751618AbdJTPMh (ORCPT ); Fri, 20 Oct 2017 11:12:37 -0400 Received: by mail-lf0-f65.google.com with SMTP id a69so13566868lfe.5 for ; Fri, 20 Oct 2017 08:12:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=pbMQUOtCMyjAnHuoWigtbyPHfEk07/xMba3RJu+vqns=; b=kRxRp+3fUbXSG+r/JVoh6iuE8KCmCXs3XUg39rS+r4dpkh6xFhIVG8Xj8eDrbS7+r9 vzbNDk68UPsvdB/QotYRSzBK700c3chfvqxpSKeYea3FYSjauc92ORigyeCxYj8cTpuN YScgrXY10ftG6iOJNONCok+vDtAIEtqYtabAs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=pbMQUOtCMyjAnHuoWigtbyPHfEk07/xMba3RJu+vqns=; b=ooBiqVSu0D1JRltq6a4972N2ghBgr30TCyCqzSkhN0Bu8sobBjTkeRY91WY0tUNz/+ vf+vWVkewTNyPT3RdfF93sPErr6U4JG5zxdEFXtOZp+0QL2C88fsJ9xLalqNb7wEhq90 GiN1F8S0FulYNo1rgSzjhVtiBIo6E6lVPEBun1FxPCsqlGbdl35lrJZdBbQeyPml2dmU 5OPOuPJMwb5uBWQrePFUP/XRw1GDIAocr38amrWZ1X4IQ3H3Sv/wWAInWo0seN4EIXUX wv5YLIj0xOBUkeYWZaSfrrjrW8W3EEOAkuPBkbyrkfkEhO2V+8RgrDW3GNz/kLczogye cDgg== X-Gm-Message-State: AMCzsaVAiiiPsXb+Kw06PuyWJZUdr6kre2flvXOFaDtrPFA0fv7rX+D9 K+sUQeUYwHQ0u5VFnlHdTS1mCYx/j4k= X-Google-Smtp-Source: ABhQp+QeCayGT2Bi36erYzJZIbOi0kH4qP0W2AhbKb56l87bafbL9gP9AsRXru7dzTu6QezY/wV9xA== X-Received: by 10.25.16.28 with SMTP id f28mr1921900lfi.133.1508512355829; Fri, 20 Oct 2017 08:12:35 -0700 (PDT) Received: from localhost.localdomain (c-5f7c71d5.014-348-6c756e10.cust.bredbandsbolaget.se. [213.113.124.95]) by smtp.gmail.com with ESMTPSA id 18sm285189ljo.29.2017.10.20.08.12.34 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 20 Oct 2017 08:12:35 -0700 (PDT) From: Linus Walleij To: linux-gpio@vger.kernel.org Cc: Linus Walleij , Anton Vorontsov , Lukas Wunner Subject: [PATCH v3] gpio-mmio: Use the new .get_multiple() callback Date: Fri, 20 Oct 2017 17:10:30 +0200 Message-Id: <20171020151030.25094-1-linus.walleij@linaro.org> X-Mailer: git-send-email 2.13.6 Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org It is possible to read all lines of a generic MMIO GPIO chip with a single register read so support this if we are in native endianness. Add an especially quirky callback to read multiple lines for the variants that require you to read values from the output registers if and only if the line is set as output. We managed to do that with a maximum of two register reads, and just one read if the requested lines are all input or all output. Cc: Anton Vorontsov Cc: Lukas Wunner Signed-off-by: Linus Walleij --- ChangeLog v2->v3: - Check the right big endianness flag: we want special handling for BE bitorder, not for BE byteorder. - Implement a .get_multiple() solution for big-endian bit order if there is a single register to read all bits. - Rebase on top of pin2mask() cleanups. ChangeLog v1->v2: - Only assign the functions for multiple get if we are in native endianness. Else each bit needs to be processed differently after read and it will be a mess. Likely the old get functions are better in this case. - Directly write into *bits in both functions. --- drivers/gpio/gpio-mmio.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 3 deletions(-) -- 2.13.6 -- 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-mmio.c b/drivers/gpio/gpio-mmio.c index 63bb48878de1..f9042bcc27a4 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c @@ -143,11 +143,78 @@ static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio) return !!(gc->read_reg(gc->reg_dat) & pinmask); } +/* + * This assumes that the bits in the GPIO register are in native endianness. + * We only assign the function pointer if we have that. + */ +static int bgpio_get_set_multiple(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits) +{ + unsigned long get_mask = 0; + unsigned long set_mask = 0; + int bit = 0; + + while ((bit = find_next_bit(mask, gc->ngpio, bit)) != gc->ngpio) { + if (gc->bgpio_dir & BIT(bit)) + set_mask |= BIT(bit); + else + get_mask |= BIT(bit); + } + + if (set_mask) + *bits |= gc->read_reg(gc->reg_set) & set_mask; + if (get_mask) + *bits |= gc->read_reg(gc->reg_dat) & get_mask; + + return 0; +} + static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) { return !!(gc->read_reg(gc->reg_dat) & bgpio_line2mask(gc, gpio)); } +/* + * This only works if the bits in the GPIO register are in native endianness. + * It is dirt simple and fast in this case. (Also the most common case.) + */ +static int bgpio_get_multiple(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits) +{ + + *bits = gc->read_reg(gc->reg_dat) & *mask; + return 0; +} + +/* + * With big endian mirrored bit order it becomes more tedious. + */ +static int bgpio_get_multiple_be(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits) +{ + unsigned long readmask = 0; + unsigned long val; + int bit; + + /* Create a mirrored mask */ + bit = 0; + while ((bit = find_next_bit(mask, gc->ngpio, bit)) != gc->ngpio) + readmask |= bgpio_line2mask(gc, bit); + + /* Read the register */ + val = gc->read_reg(gc->reg_dat) & readmask; + + /* + * Mirror the result into the "bits" result, this will give line 0 + * in bit 0 ... line 31 in bit 31 for a 32bit register. + */ + bit = 0; + while ((bit = find_next_bit(&val, gc->ngpio, bit)) != gc->ngpio) + *bits |= bgpio_line2mask(gc, bit); + + return 0; +} + static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val) { } @@ -455,10 +522,24 @@ static int bgpio_setup_io(struct gpio_chip *gc, } if (!(flags & BGPIOF_UNREADABLE_REG_SET) && - (flags & BGPIOF_READ_OUTPUT_REG_SET)) + (flags & BGPIOF_READ_OUTPUT_REG_SET)) { gc->get = bgpio_get_set; - else + if (!gc->be_bits) + gc->get_multiple = bgpio_get_set_multiple; + /* + * We deliberately avoid assigning the ->get_multiple() call + * for big endian mirrored registers which are ALSO reflecting + * their value in the set register when used as output. It is + * simply too much complexity, let the GPIO core fall back to + * reading each line individually in that fringe case. + */ + } else { gc->get = bgpio_get; + if (gc->be_bits) + gc->get_multiple = bgpio_get_multiple_be; + else + gc->get_multiple = bgpio_get_multiple; + } return 0; } @@ -519,12 +600,12 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev, gc->base = -1; gc->ngpio = gc->bgpio_bits; gc->request = bgpio_request; + gc->be_bits = !!(flags & BGPIOF_BIG_ENDIAN); ret = bgpio_setup_io(gc, dat, set, clr, flags); if (ret) return ret; - gc->be_bits = !!(flags & BGPIOF_BIG_ENDIAN); ret = bgpio_setup_accessors(dev, gc, flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER); if (ret) return ret;