From patchwork Sun Jul 3 11:10:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aidan MacDonald X-Patchwork-Id: 1651653 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=AxnWT9Da; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by bilbo.ozlabs.org (Postfix) with ESMTP id 4LbR6t3Vk6z9sFx for ; Sun, 3 Jul 2022 21:10:14 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232450AbiGCLKL (ORCPT ); Sun, 3 Jul 2022 07:10:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35288 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232442AbiGCLKK (ORCPT ); Sun, 3 Jul 2022 07:10:10 -0400 Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 643B49592; Sun, 3 Jul 2022 04:10:09 -0700 (PDT) Received: by mail-wr1-x432.google.com with SMTP id o4so9451400wrh.3; Sun, 03 Jul 2022 04:10:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=NnWDUihgr5jPMSJE1D1pbzPafcNF7TIIlv1psn+j5PE=; b=AxnWT9DaV8kDjN+0yTfzTMngYnTV7/tpf3lZKeUrYFmtRi/+ftl6riiJ2V9MNZnEfN stjYp7wUtd+HKeimGHxaL3uevGK6IBr3/DRNGav6roT9xcogGOlrKsw8VpuDdYp0dyEq 32+7yp9d15y9QkD9HFkGogRHCF5OrPuksZ5XTQ1D2TLK1+gExcZOurVSKw5TEhwCfNdm PvDj1ExN6FWe2ECP5d0vr3ELvDIJdSVZNqhycyx7rBjy6g66BMcIXV8HV9vefoKjdKSI P+sHrDDOw98Oda3Yz6uXwPK7AX0MDa4UtJly4hFRypfuD7F+LiEbeSpGiMZltolaGNRG 4Kfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=NnWDUihgr5jPMSJE1D1pbzPafcNF7TIIlv1psn+j5PE=; b=Vti/cTWH9a50u1fjAGGDwZFYEdWcvnlKDyxNbzVGFGPsAIMMJ7vOU4UkCRbC/5OuF4 pCtqA145ncqbEKf1IMZqPzSitnjdiszvoN+SfmEa3mNRfiy/2y0M+NIAvhoRGFExsQpL 1cGoMpB5FopabSmih9C4zXk4855ei6vGWOFrX2lZlyNhtxYswFqqHm1ews0deS/CMCvH bj4+Nf6wFkvIDPraQGY/nQZWMAPKrCCo3AAE+Sb6yVqSj2cwyJ9F0QtLWWlCQ4era4Y1 o5iyDWz51xK0ntkbUbGnflBK5wVhJcWyg1P1dqnBg3l+Ij37mACxdd96E+xDeeQwsck0 /dKQ== X-Gm-Message-State: AJIora9BFmWTv3LT0p94t2z2o43gBZiKUXmitp1uN1kpO4xsotKhofTo zFmHpxMXrGciGT61POcJZCA= X-Google-Smtp-Source: AGRyM1t9RZi4x5aFVNhvNF2/jVQYe9hEMWU/svUs9LRckjn4o3t9MZifA8VBXWznQDoxuN8pZ6SSfA== X-Received: by 2002:a5d:518a:0:b0:21a:39f4:b352 with SMTP id k10-20020a5d518a000000b0021a39f4b352mr21899873wrv.92.1656846607923; Sun, 03 Jul 2022 04:10:07 -0700 (PDT) Received: from localhost (92.40.202.9.threembb.co.uk. [92.40.202.9]) by smtp.gmail.com with ESMTPSA id p5-20020a5d59a5000000b0021d20461bbbsm16408330wrr.88.2022.07.03.04.10.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 03 Jul 2022 04:10:07 -0700 (PDT) From: Aidan MacDonald To: michael@walle.cc, linus.walleij@linaro.org, brgl@bgdev.pl Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/3] gpio: regmap: Support registers with more than one bit per GPIO Date: Sun, 3 Jul 2022 12:10:55 +0100 Message-Id: <20220703111057.23246-2-aidanmacdonald.0x0@gmail.com> In-Reply-To: <20220703111057.23246-1-aidanmacdonald.0x0@gmail.com> References: <20220703111057.23246-1-aidanmacdonald.0x0@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Some devices use a multi-bit register field to change the GPIO input/output direction. Add the ->reg_field_xlate() callback to support such devices in gpio-regmap. ->reg_field_xlate() builds on ->reg_mask_xlate() by allowing the driver to return a mask and values to describe a register field. gpio-regmap will use the mask to isolate the field and compare or update it using the values to implement GPIO level and direction get and set ops. Signed-off-by: Aidan MacDonald --- drivers/gpio/gpio-regmap.c | 73 +++++++++++++++++++++---------------- include/linux/gpio/regmap.h | 14 +++++++ 2 files changed, 56 insertions(+), 31 deletions(-) diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 6383136cbe59..9256b922c654 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -27,6 +27,10 @@ struct gpio_regmap { int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base, unsigned int offset, unsigned int *reg, unsigned int *mask); + void (*reg_field_xlate)(struct gpio_regmap *gpio, + unsigned int base, unsigned int offset, + unsigned int *reg, unsigned int *mask, + unsigned int *values); void *driver_data; }; @@ -52,10 +56,22 @@ static int gpio_regmap_simple_xlate(struct gpio_regmap *gpio, return 0; } +static void +gpio_regmap_simple_field_xlate(struct gpio_regmap *gpio, + unsigned int base, unsigned int offset, + unsigned int *reg, unsigned int *mask, + unsigned int *values) +{ + gpio->reg_mask_xlate(gpio, base, offset, reg, mask); + values[0] = 0; + values[1] = *mask; +} + static int gpio_regmap_get(struct gpio_chip *chip, unsigned int offset) { struct gpio_regmap *gpio = gpiochip_get_data(chip); unsigned int base, val, reg, mask; + unsigned int values[2]; int ret; /* we might not have an output register if we are input only */ @@ -64,15 +80,13 @@ static int gpio_regmap_get(struct gpio_chip *chip, unsigned int offset) else base = gpio_regmap_addr(gpio->reg_set_base); - ret = gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); - if (ret) - return ret; + gpio->reg_field_xlate(gpio, base, offset, ®, &mask, values); ret = regmap_read(gpio->regmap, reg, &val); if (ret) return ret; - return !!(val & mask); + return (val & mask) == values[1]; } static void gpio_regmap_set(struct gpio_chip *chip, unsigned int offset, @@ -81,12 +95,10 @@ static void gpio_regmap_set(struct gpio_chip *chip, unsigned int offset, struct gpio_regmap *gpio = gpiochip_get_data(chip); unsigned int base = gpio_regmap_addr(gpio->reg_set_base); unsigned int reg, mask; + unsigned int values[2]; - gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); - if (val) - regmap_update_bits(gpio->regmap, reg, mask, mask); - else - regmap_update_bits(gpio->regmap, reg, mask, 0); + gpio->reg_field_xlate(gpio, base, offset, ®, &mask, values); + regmap_update_bits(gpio->regmap, reg, mask, values[!!val]); } static void gpio_regmap_set_with_clear(struct gpio_chip *chip, @@ -94,14 +106,15 @@ static void gpio_regmap_set_with_clear(struct gpio_chip *chip, { struct gpio_regmap *gpio = gpiochip_get_data(chip); unsigned int base, reg, mask; + unsigned int values[2]; if (val) base = gpio_regmap_addr(gpio->reg_set_base); else base = gpio_regmap_addr(gpio->reg_clr_base); - gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); - regmap_write(gpio->regmap, reg, mask); + gpio->reg_field_xlate(gpio, base, offset, ®, &mask, values); + regmap_update_bits(gpio->regmap, reg, mask, values[1]); } static int gpio_regmap_get_direction(struct gpio_chip *chip, @@ -109,6 +122,7 @@ static int gpio_regmap_get_direction(struct gpio_chip *chip, { struct gpio_regmap *gpio = gpiochip_get_data(chip); unsigned int base, val, reg, mask; + unsigned int values[2]; int invert, ret; if (gpio->reg_dir_out_base) { @@ -121,47 +135,36 @@ static int gpio_regmap_get_direction(struct gpio_chip *chip, return -EOPNOTSUPP; } - ret = gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); - if (ret) - return ret; + gpio->reg_field_xlate(gpio, base, offset, ®, &mask, values); ret = regmap_read(gpio->regmap, reg, &val); if (ret) return ret; - if (!!(val & mask) ^ invert) - return GPIO_LINE_DIRECTION_OUT; - else + if ((val & mask) == values[invert]) return GPIO_LINE_DIRECTION_IN; + else + return GPIO_LINE_DIRECTION_OUT; } static int gpio_regmap_set_direction(struct gpio_chip *chip, unsigned int offset, bool output) { struct gpio_regmap *gpio = gpiochip_get_data(chip); - unsigned int base, val, reg, mask; - int invert, ret; + unsigned int base, reg, mask; + unsigned int values[2]; if (gpio->reg_dir_out_base) { base = gpio_regmap_addr(gpio->reg_dir_out_base); - invert = 0; } else if (gpio->reg_dir_in_base) { base = gpio_regmap_addr(gpio->reg_dir_in_base); - invert = 1; + output = !output; } else { return -EOPNOTSUPP; } - ret = gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); - if (ret) - return ret; - - if (invert) - val = output ? 0 : mask; - else - val = output ? mask : 0; - - return regmap_update_bits(gpio->regmap, reg, mask, val); + gpio->reg_field_xlate(gpio, base, offset, ®, &mask, values); + return regmap_update_bits(gpio->regmap, reg, mask, values[output]); } static int gpio_regmap_direction_input(struct gpio_chip *chip, @@ -215,6 +218,10 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config if (config->reg_dir_out_base && config->reg_dir_in_base) return ERR_PTR(-EINVAL); + /* only one of these should be provided */ + if (config->reg_field_xlate && config->reg_mask_xlate) + return ERR_PTR(-EINVAL); + gpio = kzalloc(sizeof(*gpio), GFP_KERNEL); if (!gpio) return ERR_PTR(-ENOMEM); @@ -225,6 +232,7 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config gpio->ngpio_per_reg = config->ngpio_per_reg; gpio->reg_stride = config->reg_stride; gpio->reg_mask_xlate = config->reg_mask_xlate; + gpio->reg_field_xlate = config->reg_field_xlate; gpio->reg_dat_base = config->reg_dat_base; gpio->reg_set_base = config->reg_set_base; gpio->reg_clr_base = config->reg_clr_base; @@ -242,6 +250,9 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config if (!gpio->reg_mask_xlate) gpio->reg_mask_xlate = gpio_regmap_simple_xlate; + if (!gpio->reg_field_xlate) + gpio->reg_field_xlate = gpio_regmap_simple_field_xlate; + chip = &gpio->gpio_chip; chip->parent = config->parent; chip->fwnode = config->fwnode; diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h index a9f7b7faf57b..a673dbfe88a3 100644 --- a/include/linux/gpio/regmap.h +++ b/include/linux/gpio/regmap.h @@ -37,6 +37,10 @@ struct regmap; * offset to a register/bitmask pair. If not * given the default gpio_regmap_simple_xlate() * is used. + * @reg_field_xlate: (Optional) Translates base address and GPIO offset + * to register, mask, and field values. If not given + * the default gpio_regmap_field_xlate() is used, which + * is implemented in terms of ->reg_mask_xlate. * @drvdata: (Optional) Pointer to driver specific data which is * not used by gpio-remap but is provided "as is" to the * driver callback(s). @@ -45,6 +49,12 @@ struct regmap; * register and mask pair. The base address is one of the given register * base addresses in this structure. * + * ->reg_field_xlate supports chips that have more than one bit per GPIO for + * controlling the output level or direction. In addition to the register and + * mask it should output field values for low/high level or in/out direction + * in ``values[0]`` and ``values[1]``. If ->reg_field_xlate is provided then + * it overrides any ->reg_mask_xlate callback. + * * Although all register base addresses are marked as optional, there are * several rules: * 1. if you only have @reg_dat_base set, then it is input-only @@ -81,6 +91,10 @@ struct gpio_regmap_config { int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base, unsigned int offset, unsigned int *reg, unsigned int *mask); + void (*reg_field_xlate)(struct gpio_regmap *gpio, + unsigned int base, unsigned int offset, + unsigned int *reg, unsigned int *mask, + unsigned int *values); void *drvdata; }; From patchwork Sun Jul 3 11:10:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aidan MacDonald X-Patchwork-Id: 1651654 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=mIEzhiU+; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by bilbo.ozlabs.org (Postfix) with ESMTP id 4LbR6t5vD9z9sGC for ; Sun, 3 Jul 2022 21:10:14 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232473AbiGCLKM (ORCPT ); Sun, 3 Jul 2022 07:10:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35300 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232449AbiGCLKL (ORCPT ); Sun, 3 Jul 2022 07:10:11 -0400 Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CB1C6959A; Sun, 3 Jul 2022 04:10:10 -0700 (PDT) Received: by mail-wm1-x335.google.com with SMTP id 205-20020a1c02d6000000b003a03567d5e9so5875863wmc.1; Sun, 03 Jul 2022 04:10:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=AC+2/tXKJ2KFamOafvmGavz/orcqkE8PLkh+zUIqBTY=; b=mIEzhiU+Y3RZxJo7A2cfXOnbIf7tpwWBjDrWVj3arGYnXT0iqIL8RVjIjDsyLZwrx8 Vi2vw1IWABtxEDhsqjolhv8smRt1jd2g000eKm5FY/p0339j8Pad87qMyPif0Hjd9kfX pwt+DZ5I/CahGBQ6CD27ck/fiSax69JdMdtANvHmi8PS4Jo/NrIYBOzqjdFz2oRHHxNr Mmh2G///1X7OMA6Rf9IJBoBszJcho8TKYcq9zgr/lti11V9Q6mK3Xil9dLv8NlQN46Cy 1tDEo4LV53CdCS0h9STVW+Vi3ENV7vL274+GvwUbgVSpf8rR+8aVpqthJtlDxE6FUzrr bOvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=AC+2/tXKJ2KFamOafvmGavz/orcqkE8PLkh+zUIqBTY=; b=IiL/Yu/Kydop2Jz/sLGs8AfO6HMii/z9MjpoIItfgAQTbiackSf5mcvfL814tyzCL6 AxdfBhwTqWGMV6DtTHx+Od6Q/fl4Et8FA5mtglh2ZN21cO5UEbsikVZV1e/JueUSg0xv vB56BITzTqH0sLb4BkGJflw0f1K1OPWEcXnkF+aLP02Si39uUF4kovugLCwpds0m2636 C2l3KL1KupreOQ733docRNA++fMjYq6UdCBTsmWPOJyEbnIQ+ado7as2DM+7YXawpEUp QTPCesFdUC5B6ukL8DMvZUePAF+aq4jVOq3MbXcWvcHg7DCdxBlGBuKQ/oqJI5pLFu3w hZ0w== X-Gm-Message-State: AJIora+0swbTnxs4MrZhQ3MBUpyC/qGN56WHoGCLyaKhJCFGxrhpZEfa qU2lVvuU3UepRIHEk26c54M= X-Google-Smtp-Source: AGRyM1tDuMZ/TxmS99GwHLqWoIGNj8gY/1atwR6NaW2GyAHMDNQ4b7xwdsE5GONAeI6wjyMevwfALA== X-Received: by 2002:a05:600c:35d2:b0:397:84c9:6fe8 with SMTP id r18-20020a05600c35d200b0039784c96fe8mr25294140wmq.206.1656846609395; Sun, 03 Jul 2022 04:10:09 -0700 (PDT) Received: from localhost (92.40.202.9.threembb.co.uk. [92.40.202.9]) by smtp.gmail.com with ESMTPSA id d21-20020a1c7315000000b003a02cbf862esm15944082wmb.13.2022.07.03.04.10.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 03 Jul 2022 04:10:08 -0700 (PDT) From: Aidan MacDonald To: michael@walle.cc, linus.walleij@linaro.org, brgl@bgdev.pl Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/3] gpio: regmap: Support combined GPIO and pin control drivers Date: Sun, 3 Jul 2022 12:10:56 +0100 Message-Id: <20220703111057.23246-3-aidanmacdonald.0x0@gmail.com> In-Reply-To: <20220703111057.23246-1-aidanmacdonald.0x0@gmail.com> References: <20220703111057.23246-1-aidanmacdonald.0x0@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Allow gpio-regmap to be used for the GPIO portion of a combined pin control and GPIO driver by setting the has_pinctrl flag. This flag will cause GPIO direction set ops to be implemented as calls to pinctrl_gpio_direction_input/output() instead of updating the direction set registers directly. Note that reg_dir_out/in_base is still required for implementing the GPIO chip's ->get_direction() callback. Signed-off-by: Aidan MacDonald --- drivers/gpio/gpio-regmap.c | 20 ++++++++++++++++++++ include/linux/gpio/regmap.h | 6 ++++++ 2 files changed, 26 insertions(+) diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 9256b922c654..4bc01329fb14 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -24,6 +24,8 @@ struct gpio_regmap { unsigned int reg_dir_in_base; unsigned int reg_dir_out_base; + unsigned int has_pinctrl:1; + int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base, unsigned int offset, unsigned int *reg, unsigned int *mask); @@ -170,14 +172,24 @@ static int gpio_regmap_set_direction(struct gpio_chip *chip, static int gpio_regmap_direction_input(struct gpio_chip *chip, unsigned int offset) { + struct gpio_regmap *gpio = gpiochip_get_data(chip); + + if (gpio->has_pinctrl) + return pinctrl_gpio_direction_input(chip->base + offset); + return gpio_regmap_set_direction(chip, offset, false); } static int gpio_regmap_direction_output(struct gpio_chip *chip, unsigned int offset, int value) { + struct gpio_regmap *gpio = gpiochip_get_data(chip); + gpio_regmap_set(chip, offset, value); + if (gpio->has_pinctrl) + return pinctrl_gpio_direction_output(chip->base + offset); + return gpio_regmap_set_direction(chip, offset, true); } @@ -218,6 +230,14 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config if (config->reg_dir_out_base && config->reg_dir_in_base) return ERR_PTR(-EINVAL); + /* + * we need a direction register for implementing ->get_direction + * even if ->direction_input/output is handled by pin control + */ + if (config->has_pinctrl && !(config->reg_dir_in_base || + config->reg_dir_out_base)) + return ERR_PTR(-EINVAL); + /* only one of these should be provided */ if (config->reg_field_xlate && config->reg_mask_xlate) return ERR_PTR(-EINVAL); diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h index a673dbfe88a3..47acea8cca32 100644 --- a/include/linux/gpio/regmap.h +++ b/include/linux/gpio/regmap.h @@ -33,6 +33,10 @@ struct regmap; * @ngpio_per_reg: Number of GPIOs per register * @irq_domain: (Optional) IRQ domain if the controller is * interrupt-capable + * @has_pinctrl: If set, the GPIO chip is part of a combined pin control + * and GPIO driver; use pinctrl_gpio_direction_input() and + * pinctrl_gpio_direction_output() to implement direction + * set operations. * @reg_mask_xlate: (Optional) Translates base address and GPIO * offset to a register/bitmask pair. If not * given the default gpio_regmap_simple_xlate() @@ -88,6 +92,8 @@ struct gpio_regmap_config { int ngpio_per_reg; struct irq_domain *irq_domain; + unsigned int has_pinctrl:1; + int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base, unsigned int offset, unsigned int *reg, unsigned int *mask); From patchwork Sun Jul 3 11:10:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aidan MacDonald X-Patchwork-Id: 1651655 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=ab7Rio2G; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by bilbo.ozlabs.org (Postfix) with ESMTP id 4LbR6x1Tyxz9sFw for ; Sun, 3 Jul 2022 21:10:17 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232395AbiGCLKP (ORCPT ); Sun, 3 Jul 2022 07:10:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35352 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232487AbiGCLKN (ORCPT ); Sun, 3 Jul 2022 07:10:13 -0400 Received: from mail-wr1-x433.google.com (mail-wr1-x433.google.com [IPv6:2a00:1450:4864:20::433]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CEB3C95A7; Sun, 3 Jul 2022 04:10:12 -0700 (PDT) Received: by mail-wr1-x433.google.com with SMTP id f2so4072184wrr.6; Sun, 03 Jul 2022 04:10:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=8mLa6YcJ8/LXS3JX6YxujO7pIsxppw7hodqInEX9ajw=; b=ab7Rio2GCTDvhPeqJGMtzyfo957Uh8UdAwwT9mq2XpxQHFbgq22302eaYgiX9T6e7m ZvRlEDPD/2icwrzFPQfExwkWzlnv9VYjuXYaZEm0yj0VB5ojYNlmw52+d2QzNWwDgPPe 4TASz7OEZ9z8DdADuHfKbs9FqVOVgQczhSU7FXMm80TQrSCk0c78/RvyXFdMlgOHbhV/ +1CPRpTBuKxOirpQoPyyz6CDJOGSGBcoyHQgtLYgHK0FD4x39yCC78xn2sXjRESHD52e BrdVlpuMnOuAr8sGzCA+AOqC2WNEQuHL16u+XPZWD9IMzkQjN7xNgnULUfTfYxk0Xqlu iusA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=8mLa6YcJ8/LXS3JX6YxujO7pIsxppw7hodqInEX9ajw=; b=DjCFjGYuo36sTSiJhY51iOSZ57CMO8tu6nsm2L8Jzk1y4mOiTQ/7d+OjrwR/U4JMDg 3SXUah9ma1V+9h+5kThrqZjmWJA5KEs6sEXm7TiGqKhV9GTGNmPzWj0k0mgTV6fVlR/f nSIhRIAbAX74aQ1l+GBY/S1ZKs7PPQtmrgoF65YRvp1JGs3c+bEGF0XVJpbRLAZTsUUf huRRt/EUIvH55PvoIL0ojg8nQy6n8nqKK/uIY37AVFBwv+GPsnKoyldtQ+S6IjYu5sg0 iu6C826uhAdrz1iLbEo9XeOigby4nyRWcGO4xRGxya6/VI+rzZkeQNTZXR5kxFYZhyRG RYVA== X-Gm-Message-State: AJIora/xza388Ms4p3mPvs9uvQm4XA0n0NIE18me5B/LDJq3W9Lano87 8NCp0VAc2RJcitgVFNo5Yl0= X-Google-Smtp-Source: AGRyM1twLWvI9q5JpGIybFHUO9Ryc2CLbeMQvjL8oYmSwzzh2WE/rDXDRDAae8kUIkiRSP6Q/nhC9Q== X-Received: by 2002:adf:fa8d:0:b0:21d:6a23:f627 with SMTP id h13-20020adffa8d000000b0021d6a23f627mr69498wrr.295.1656846611274; Sun, 03 Jul 2022 04:10:11 -0700 (PDT) Received: from localhost (92.40.202.9.threembb.co.uk. [92.40.202.9]) by smtp.gmail.com with ESMTPSA id v4-20020a7bcb44000000b0039746638d6esm15825418wmj.33.2022.07.03.04.10.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 03 Jul 2022 04:10:10 -0700 (PDT) From: Aidan MacDonald To: michael@walle.cc, linus.walleij@linaro.org, brgl@bgdev.pl Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/3] gpio: regmap: Support a custom ->to_irq() hook Date: Sun, 3 Jul 2022 12:10:57 +0100 Message-Id: <20220703111057.23246-4-aidanmacdonald.0x0@gmail.com> In-Reply-To: <20220703111057.23246-1-aidanmacdonald.0x0@gmail.com> References: <20220703111057.23246-1-aidanmacdonald.0x0@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Some GPIO chips require a custom to_irq() callback for mapping their IRQs, eg. because their interrupts come from a parent IRQ chip where the GPIO offset doesn't map 1-to-1 with hwirq number. Signed-off-by: Aidan MacDonald --- drivers/gpio/gpio-regmap.c | 17 +++++++++++++++++ include/linux/gpio/regmap.h | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 4bc01329fb14..d11b202e51fd 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -34,6 +34,8 @@ struct gpio_regmap { unsigned int *reg, unsigned int *mask, unsigned int *values); + int (*to_irq)(struct gpio_regmap *gpio, unsigned int offset); + void *driver_data; }; @@ -193,6 +195,13 @@ static int gpio_regmap_direction_output(struct gpio_chip *chip, return gpio_regmap_set_direction(chip, offset, true); } +static int gpio_regmap_to_irq(struct gpio_chip *chip, unsigned int offset) +{ + struct gpio_regmap *gpio = gpiochip_get_data(chip); + + return gpio->to_irq(gpio, offset); +} + void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio) { return gpio->driver_data; @@ -242,6 +251,10 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config if (config->reg_field_xlate && config->reg_mask_xlate) return ERR_PTR(-EINVAL); + /* an irq_domain will override the to_irq hook, so don't allow both */ + if (config->irq_domain && config->to_irq) + return ERR_PTR(-EINVAL); + gpio = kzalloc(sizeof(*gpio), GFP_KERNEL); if (!gpio) return ERR_PTR(-ENOMEM); @@ -253,6 +266,7 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config gpio->reg_stride = config->reg_stride; gpio->reg_mask_xlate = config->reg_mask_xlate; gpio->reg_field_xlate = config->reg_field_xlate; + gpio->to_irq = config->to_irq; gpio->reg_dat_base = config->reg_dat_base; gpio->reg_set_base = config->reg_set_base; gpio->reg_clr_base = config->reg_clr_base; @@ -302,6 +316,9 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config chip->direction_output = gpio_regmap_direction_output; } + if (gpio->to_irq) + chip->to_irq = gpio_regmap_to_irq; + ret = gpiochip_add_data(chip, gpio); if (ret < 0) goto err_free_gpio; diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h index 47acea8cca32..9755854d6747 100644 --- a/include/linux/gpio/regmap.h +++ b/include/linux/gpio/regmap.h @@ -45,6 +45,8 @@ struct regmap; * to register, mask, and field values. If not given * the default gpio_regmap_field_xlate() is used, which * is implemented in terms of ->reg_mask_xlate. + * @to_irq: (Optional) hook for supporting custom IRQ mappings, + * behaves the same as the gpio_chip to_irq hook. * @drvdata: (Optional) Pointer to driver specific data which is * not used by gpio-remap but is provided "as is" to the * driver callback(s). @@ -102,6 +104,8 @@ struct gpio_regmap_config { unsigned int *reg, unsigned int *mask, unsigned int *values); + int (*to_irq)(struct gpio_regmap *gpio, unsigned int offset); + void *drvdata; };