From nobody Sun Apr 28 04:44:26 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5D3EFC4321E for ; Fri, 2 Dec 2022 16:27:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234130AbiLBQ1f (ORCPT ); Fri, 2 Dec 2022 11:27:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43608 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234007AbiLBQ1Y (ORCPT ); Fri, 2 Dec 2022 11:27:24 -0500 Received: from mail-qt1-x82f.google.com (mail-qt1-x82f.google.com [IPv6:2607:f8b0:4864:20::82f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1DC5655A2 for ; Fri, 2 Dec 2022 08:27:24 -0800 (PST) Received: by mail-qt1-x82f.google.com with SMTP id h24so5813874qta.9 for ; Fri, 02 Dec 2022 08:27:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Ri0mZ2K/fUhEx8zLPRzENIukosBulaHGjs8vpkuOJm0=; b=u9/IyqiIL4+3wr3eFH2hBBO25RhLAtMp9B6DjxpaiYYJ42wVb1aUP2KMzEPlTr4ho3 pCbWaiaZIVkvfR0KZTG4zicCMfiLAuqZFHQ0CEAyA6v731ac5oeKyOBrFQ5eF2R1EB2Q SLO0rqB4UwNrrYQDo/iUeczHNO2u9m9WgL4lMiR/lgP0UI6xZQs6u/io8FUGpPE1VmIn e9lnQeFyiZcChVgJTVFPdGeUysysNtSWhmt0WYxYwRxWSIrVJ9MoKDx0TDTOCTI2Agum MgUy3HtgMfs6ioE/Y03IjNgAEFwGs1FzJMT3454Di8hLRqYw0IQ2ZH3qWFzZtyGvPQmg uDfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Ri0mZ2K/fUhEx8zLPRzENIukosBulaHGjs8vpkuOJm0=; b=z0vkhPvcOyr6qI2b68urkzgOgdVSp9Go0jmFnqcXKqdc3qmiPnNXHekFQaf+jY3s2R AVMQBzZYAHQEFX2FLdcScz+TXp3B7M2Gin7OKnMMK7vw9T5B7+Ot2BrUWcQ2EKpSeRMP Hu0tNbk50PDblo0S2S6wzTmwCoq6gGem+cv2sIDNxhvTWRVlFIOHwikpEbqZNlp9bqsE GFrwCon6QM9fgllAWa7n/IE4Rd3sppuF2gH+PtfIvF8dBp+Z9Jxs8EBhvp2A6+VvjEAe 7lkg5d3+1+eH6gkRVNtFwz//87VoK0BNu8oyRU56px0GH2FD5sPK2OnfSxvOL6Tpuw86 uMoQ== X-Gm-Message-State: ANoB5plUnsIy1pkvAJ5hTSl30EYLD1PY87wsy69OvwIKhSaCGt5yJHRg v9iLuK46d1xMmVjqTp/Jh51SLQ== X-Google-Smtp-Source: AA0mqf75+ua2+xbTdtzxvzDbcyWX4xX7g6LJ3BGTqTcP5c6wP8WcuYJSKvQyI7Y8Vv9OtE+ftknEjw== X-Received: by 2002:ae9:f111:0:b0:6fc:94f7:6cf6 with SMTP id k17-20020ae9f111000000b006fc94f76cf6mr14926054qkg.517.1669998443211; Fri, 02 Dec 2022 08:27:23 -0800 (PST) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id fp38-20020a05622a50a600b00343057845f7sm4391887qtb.20.2022.12.02.08.27.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Dec 2022 08:27:22 -0800 (PST) From: William Breathitt Gray To: linus.walleij@linaro.org, brgl@bgdev.pl Cc: andriy.shevchenko@linux.intel.com, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, michael@walle.cc, broonie@kernel.org, William Breathitt Gray Subject: [PATCH v4 1/9] gpio: regmap: Always set gpio_chip get_direction Date: Fri, 2 Dec 2022 11:27:07 -0500 Message-Id: <2bb8b9e88b8713fcb415e9ac40ecf31e43daee71.1669996867.git.william.gray@linaro.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" If you only have reg_dat_base set, then it is input-only; if you only have reg_set_base set, then it is output-only. Thus, we can always set gpio_chip get_direction to gpio_regmap_get_direction and return GPIO_LINE_DIRECTION_IN/GPIO_LINE_DIRECTION_OUT given the respective register base addresses configuration. Reviewed-by: Andy Shevchenko Acked-by: Michael Walle Signed-off-by: William Breathitt Gray --- drivers/gpio/gpio-regmap.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 6383136cbe59..f907c9c19fce 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -111,6 +111,11 @@ static int gpio_regmap_get_direction(struct gpio_chip = *chip, unsigned int base, val, reg, mask; int invert, ret; =20 + if (gpio->reg_dat_base && !gpio->reg_set_base) + return GPIO_LINE_DIRECTION_IN; + if (gpio->reg_set_base && !gpio->reg_dat_base) + return GPIO_LINE_DIRECTION_OUT; + if (gpio->reg_dir_out_base) { base =3D gpio_regmap_addr(gpio->reg_dir_out_base); invert =3D 0; @@ -265,8 +270,8 @@ struct gpio_regmap *gpio_regmap_register(const struct g= pio_regmap_config *config else if (gpio->reg_set_base) chip->set =3D gpio_regmap_set; =20 + chip->get_direction =3D gpio_regmap_get_direction; if (gpio->reg_dir_in_base || gpio->reg_dir_out_base) { - chip->get_direction =3D gpio_regmap_get_direction; chip->direction_input =3D gpio_regmap_direction_input; chip->direction_output =3D gpio_regmap_direction_output; } --=20 2.38.1 From nobody Sun Apr 28 04:44:26 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CBA35C4321E for ; Fri, 2 Dec 2022 16:27:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234117AbiLBQ1b (ORCPT ); Fri, 2 Dec 2022 11:27:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43618 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234014AbiLBQ1Z (ORCPT ); Fri, 2 Dec 2022 11:27:25 -0500 Received: from mail-qt1-x82c.google.com (mail-qt1-x82c.google.com [IPv6:2607:f8b0:4864:20::82c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 67E52D11B for ; Fri, 2 Dec 2022 08:27:24 -0800 (PST) Received: by mail-qt1-x82c.google.com with SMTP id cg5so5820733qtb.12 for ; Fri, 02 Dec 2022 08:27:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KoWGIAjBhBK2abs/14cO4LLdz54XLj1GMrifUXlELoM=; b=k5wr7gsqxn626Vjan8gsweRHiUDe47XdXpDt/HSf5/uMNpca+G5vcDB7m4TXLhmZoN 3vD0vJcVkfaXhjl60L+kdnnDbNHJQBZjqvy91gr8lcLrIArd7n86286nqnXcje6xRiK0 yFacApcTCW0/Q7o0qCVxweIBMDmOglBHg2/fQb9St6M5Zsa0/XamgNTnftEbsMgxjf/f snmqOUtfkCxNOyd3qIUx/iiA6CGGgj8eEGNuWsNjgPP+i9JrYtjsKxUl6aBG05nZtJ4q nsEyNQ9zv1EUsA9cIJlQl5z+GqF9Ufgf9iU8fFyHw1kqYCIx3rt/5NrHYLHFI6zcH15E Iafg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=KoWGIAjBhBK2abs/14cO4LLdz54XLj1GMrifUXlELoM=; b=dxd5TLdTPR4AkrpC6uzHIkWq1wMYQyQUkYnNvJylxaqcnKUvbXpW81Iv6ot5iN+9ft sY3BwyFumrRsEL+44P5CxMKbHXS4u3QMfhnN3tbqTu+ghoE+K4L/gWqoLNVcDBWgMpIa 1uMHDLyJXNDRDeyn9MHNFPqJVa+qX2+f36GR40Z8yTHJO6EN02LxI584F/F006ztzGzL YUC9geUbJAN0bKAtIfka9MpFDknOBYAJ/85nJzp41oGuHlv/ZmvP1ItD0OMDb3YAYWC7 pzbExoFGj1dn/XS6T5JNxbeaorRxIz9rxi2XTax9S1252JH3rX7mmI1hulknKdu6aRJd 3fOg== X-Gm-Message-State: ANoB5pkmwglHhwcOrmDnJCXdX3FkdomTkIe5fXVhe+1yaDDazs7VruZ1 hxD0mHLvI8IgQMQpgAj/MnRseg== X-Google-Smtp-Source: AA0mqf5MffTw9tu2sOga5fyCyXD/Qyyo6deNh0mKD4gq5ZR8aRjce4vJdPhXsOOHM2SbMX2jM0WNcg== X-Received: by 2002:a05:620a:201c:b0:6ce:51a0:a80e with SMTP id c28-20020a05620a201c00b006ce51a0a80emr62516530qka.591.1669998444018; Fri, 02 Dec 2022 08:27:24 -0800 (PST) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id fp38-20020a05622a50a600b00343057845f7sm4391887qtb.20.2022.12.02.08.27.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Dec 2022 08:27:23 -0800 (PST) From: William Breathitt Gray To: linus.walleij@linaro.org, brgl@bgdev.pl Cc: andriy.shevchenko@linux.intel.com, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, michael@walle.cc, broonie@kernel.org, William Breathitt Gray Subject: [PATCH v4 2/9] regmap-irq: Add handle_mask_sync() callback Date: Fri, 2 Dec 2022 11:27:08 -0500 Message-Id: <0dcd938f410bdbb0a011bec51c4b5b26882ca10a.1669996867.git.william.gray@linaro.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Provide a public callback handle_mask_sync() that drivers can use when they have more complex IRQ masking logic. The default implementation is regmap_irq_handle_mask_sync(), used if the chip doesn't provide its own callback. Signed-off-by: William Breathitt Gray --- drivers/base/regmap/regmap-irq.c | 44 ++++++++++++++++++++++---------- include/linux/regmap.h | 5 ++++ 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-= irq.c index 4ef9488d05cd..968681fa8d09 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -115,12 +115,20 @@ static void regmap_irq_sync_unlock(struct irq_data *d= ata) */ for (i =3D 0; i < d->chip->num_regs; i++) { if (d->mask_base) { - reg =3D d->get_irq_reg(d, d->mask_base, i); - ret =3D regmap_update_bits(d->map, reg, - d->mask_buf_def[i], d->mask_buf[i]); - if (ret) - dev_err(d->map->dev, "Failed to sync masks in %x\n", - reg); + if (d->chip->handle_mask_sync) + d->chip->handle_mask_sync(d->map, i, + d->mask_buf_def[i], + d->mask_buf[i], + d->chip->irq_drv_data); + else { + reg =3D d->get_irq_reg(d, d->mask_base, i); + ret =3D regmap_update_bits(d->map, reg, + d->mask_buf_def[i], + d->mask_buf[i]); + if (ret) + dev_err(d->map->dev, "Failed to sync masks in %x\n", + reg); + } } =20 if (d->unmask_base) { @@ -917,13 +925,23 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *= fwnode, d->mask_buf[i] =3D d->mask_buf_def[i]; =20 if (d->mask_base) { - reg =3D d->get_irq_reg(d, d->mask_base, i); - ret =3D regmap_update_bits(d->map, reg, - d->mask_buf_def[i], d->mask_buf[i]); - if (ret) { - dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", - reg, ret); - goto err_alloc; + if (chip->handle_mask_sync) { + ret =3D chip->handle_mask_sync(d->map, i, + d->mask_buf_def[i], + d->mask_buf[i], + chip->irq_drv_data); + if (ret) + goto err_alloc; + } else { + reg =3D d->get_irq_reg(d, d->mask_base, i); + ret =3D regmap_update_bits(d->map, reg, + d->mask_buf_def[i], + d->mask_buf[i]); + if (ret) { + dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", + reg, ret); + goto err_alloc; + } } } =20 diff --git a/include/linux/regmap.h b/include/linux/regmap.h index ca3434dca3a0..cc07645501af 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -1542,6 +1542,8 @@ struct regmap_irq_chip_data; * before regmap_irq_handler process the interrupts. * @handle_post_irq: Driver specific callback to handle interrupt from dev= ice * after handling the interrupts in regmap_irq_handler(). + * @handle_mask_sync: Callback used to handle IRQ mask syncs. The index wi= ll be + * in the range [0, num_regs) * @set_type_virt: Driver specific callback to extend regmap_irq_set_typ= e() * and configure virt regs. Deprecated, use @set_type_config * callback and config registers instead. @@ -1603,6 +1605,9 @@ struct regmap_irq_chip { =20 int (*handle_pre_irq)(void *irq_drv_data); int (*handle_post_irq)(void *irq_drv_data); + int (*handle_mask_sync)(struct regmap *map, int index, + unsigned int mask_buf_def, + unsigned int mask_buf, void *irq_drv_data); int (*set_type_virt)(unsigned int **buf, unsigned int type, unsigned long hwirq, int reg); int (*set_type_config)(unsigned int **buf, unsigned int type, --=20 2.38.1 From nobody Sun Apr 28 04:44:26 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 81A9AC4321E for ; Fri, 2 Dec 2022 16:27:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234136AbiLBQ1i (ORCPT ); Fri, 2 Dec 2022 11:27:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43634 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234070AbiLBQ11 (ORCPT ); Fri, 2 Dec 2022 11:27:27 -0500 Received: from mail-qt1-x835.google.com (mail-qt1-x835.google.com [IPv6:2607:f8b0:4864:20::835]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D7A025F5A for ; Fri, 2 Dec 2022 08:27:25 -0800 (PST) Received: by mail-qt1-x835.google.com with SMTP id a27so5822890qtw.10 for ; Fri, 02 Dec 2022 08:27:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=UKtlFXr176GJYCzoa4Vyjc+Z42gzySzS09ojrolPXIA=; b=e/z/hOLnU+Bpqaj/AKDp7maZZH23+zf/WlC78dTvzOQr5sibcw0uP5vZj8Fitoqqgf S58NsewSZz3Js2lmnUHzgbhD8FmOCRNI9JLV8wZ9uplMeLePpOmGGbvhngB0T04wGpNo 7Ey40FzTDLcdo0XDTg8offbDL9psBRh+orF5dGm0v0mll3Qm317DmmFcwy7vBS6/fchk 4mnL5Gmkd+QfEdf8s4ycgCzAunQyy0b2caaXun9G7EtZ43iO0v8DyIZFbUag9NeFfVwZ 4HvsF1O7UfO659O8kdm7/ooKKrMjQCGAXTTYv0xUjSmxN2HsptSmfDTjhWWe5b//WGYZ G8XQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=UKtlFXr176GJYCzoa4Vyjc+Z42gzySzS09ojrolPXIA=; b=cB2otvCM9oosubLnYxqZlgdrT9/gNH4xk0Ja5B0MKA4s7JbnjiNSQPIuaAy+brPgX6 Gd/M0GRjOmbkKg0ea5jSpKn6j3ei1379iwSz+J3q11zso/RgYomeJ87VK93pmUoH/qpT BTCEpFrvycGJgvEYfM5nIE6pgpQx9rs92xeoz+E0DjJoMXm1kwFAdAMeUscFxwL6pSvb zrERUPxAyFE38wSumyduVo1STfYjUTSJFMYcbsGLsiA5ZurQpduwFTpJAxN9J6eH4yzA bZFtl0S/D7FUG1SyL9jKGQDYee3Tr8ryqCyXT20cOxP61twrODgfq0xHNkM71wA6Jmip bgsw== X-Gm-Message-State: ANoB5plKKLQZwxrYJtJ4uXDY1ay90P21UGXPyfegkPVNiqmlL6nFsNEe 1nr8yNTZFJc7h4BWHFgEckqUqA== X-Google-Smtp-Source: AA0mqf6FsERuh+PRNH0PmM+rTEv3s5EKgxtrEykmUH1NvSkmR9Wjs0YbkFEpd2Fu9v+1yRQBzDbehg== X-Received: by 2002:a37:2dc7:0:b0:6ce:2d77:92d0 with SMTP id t190-20020a372dc7000000b006ce2d7792d0mr63426075qkh.713.1669998444937; Fri, 02 Dec 2022 08:27:24 -0800 (PST) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id fp38-20020a05622a50a600b00343057845f7sm4391887qtb.20.2022.12.02.08.27.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Dec 2022 08:27:24 -0800 (PST) From: William Breathitt Gray To: linus.walleij@linaro.org, brgl@bgdev.pl Cc: andriy.shevchenko@linux.intel.com, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, michael@walle.cc, broonie@kernel.org, William Breathitt Gray Subject: [PATCH v4 3/9] gpio: 104-dio-48e: Migrate to the regmap-irq API Date: Fri, 2 Dec 2022 11:27:09 -0500 Message-Id: X-Mailer: git-send-email 2.38.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The regmap API supports IO port accessors so we can take advantage of regmap abstractions rather than handling access to the device registers directly in the driver. For the 104-dio-48e we have the following IRQ registers (0xB and 0xF): Base Address +B (Write): Enable Interrupt Base Address +B (Read): Disable Interrupt Base Address +F (Read/Write): Clear Interrupt Any write to 0xB will enable interrupts, while any read will disable interrupts. Interrupts are cleared by a read or any write to 0xF. There's no IRQ status register, so software has to assume that if an interrupt is raised then it was for the 104-DIO-48E device. Signed-off-by: William Breathitt Gray Reviewed-by: Andy Shevchenko --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-104-dio-48e.c | 268 +++++++++++++++----------------- 2 files changed, 127 insertions(+), 142 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index ec7cfd4f52b1..b62bef4e563d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -845,6 +845,7 @@ config GPIO_104_DIO_48E tristate "ACCES 104-DIO-48E GPIO support" depends on PC104 select ISA_BUS_API + select REGMAP_IRQ select GPIOLIB_IRQCHIP select GPIO_I8255 help diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48= e.c index 7b8829c8e423..4c3660d5dea5 100644 --- a/drivers/gpio/gpio-104-dio-48e.c +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -8,17 +8,15 @@ */ #include #include -#include +#include #include -#include #include -#include -#include +#include #include #include #include #include -#include +#include #include =20 #include "gpio-i8255.h" @@ -38,46 +36,30 @@ static unsigned int num_irq; module_param_hw_array(irq, uint, irq, &num_irq, 0); MODULE_PARM_DESC(irq, "ACCES 104-DIO-48E interrupt line numbers"); =20 +#define DIO48E_ENABLE_INTERRUPT 0xB +#define DIO48E_DISABLE_INTERRUPT DIO48E_ENABLE_INTERRUPT +#define DIO48E_CLEAR_INTERRUPT 0xF + #define DIO48E_NUM_PPI 2 =20 /** * struct dio48e_reg - device register structure * @ppi: Programmable Peripheral Interface groups - * @enable_buffer: Enable/Disable Buffer groups - * @unused1: Unused - * @enable_interrupt: Write: Enable Interrupt - * Read: Disable Interrupt - * @unused2: Unused - * @enable_counter: Write: Enable Counter/Timer Addressing - * Read: Disable Counter/Timer Addressing - * @unused3: Unused - * @clear_interrupt: Clear Interrupt */ struct dio48e_reg { struct i8255 ppi[DIO48E_NUM_PPI]; - u8 enable_buffer[DIO48E_NUM_PPI]; - u8 unused1; - u8 enable_interrupt; - u8 unused2; - u8 enable_counter; - u8 unused3; - u8 clear_interrupt; }; =20 /** * struct dio48e_gpio - GPIO device private data structure * @chip: instance of the gpio_chip * @ppi_state: PPI device states - * @lock: synchronization lock to prevent I/O race conditions * @reg: I/O address offset for the device registers - * @irq_mask: I/O bits affected by interrupts */ struct dio48e_gpio { struct gpio_chip chip; struct i8255_state ppi_state[DIO48E_NUM_PPI]; - raw_spinlock_t lock; struct dio48e_reg __iomem *reg; - unsigned char irq_mask; }; =20 static int dio48e_gpio_get_direction(struct gpio_chip *chip, unsigned int = offset) @@ -144,106 +126,90 @@ static void dio48e_gpio_set_multiple(struct gpio_chi= p *chip, bits, chip->ngpio); } =20 -static void dio48e_irq_ack(struct irq_data *data) -{ -} - -static void dio48e_irq_mask(struct irq_data *data) -{ - struct gpio_chip *chip =3D irq_data_get_irq_chip_data(data); - struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(chip); - const unsigned long offset =3D irqd_to_hwirq(data); - unsigned long flags; - - /* only bit 3 on each respective Port C supports interrupts */ - if (offset !=3D 19 && offset !=3D 43) - return; - - raw_spin_lock_irqsave(&dio48egpio->lock, flags); - - if (offset =3D=3D 19) - dio48egpio->irq_mask &=3D ~BIT(0); - else - dio48egpio->irq_mask &=3D ~BIT(1); - gpiochip_disable_irq(chip, offset); - - if (!dio48egpio->irq_mask) - /* disable interrupts */ - ioread8(&dio48egpio->reg->enable_interrupt); - - raw_spin_unlock_irqrestore(&dio48egpio->lock, flags); -} - -static void dio48e_irq_unmask(struct irq_data *data) -{ - struct gpio_chip *chip =3D irq_data_get_irq_chip_data(data); - struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(chip); - const unsigned long offset =3D irqd_to_hwirq(data); - unsigned long flags; - - /* only bit 3 on each respective Port C supports interrupts */ - if (offset !=3D 19 && offset !=3D 43) - return; - - raw_spin_lock_irqsave(&dio48egpio->lock, flags); +static const struct regmap_range dio48e_wr_ranges[] =3D { + regmap_reg_range(0x0, 0x9), regmap_reg_range(0xB, 0xB), + regmap_reg_range(0xD, 0xD), regmap_reg_range(0xF, 0xF), +}; +static const struct regmap_range dio48e_rd_ranges[] =3D { + regmap_reg_range(0x0, 0x2), regmap_reg_range(0x4, 0x6), + regmap_reg_range(0xB, 0xB), regmap_reg_range(0xD, 0xD), + regmap_reg_range(0xF, 0xF), +}; +static const struct regmap_range dio48e_volatile_ranges[] =3D { + i8255_volatile_regmap_range(0x0), i8255_volatile_regmap_range(0x4), + regmap_reg_range(0xB, 0xB), regmap_reg_range(0xD, 0xD), + regmap_reg_range(0xF, 0xF), +}; +static const struct regmap_range dio48e_precious_ranges[] =3D { + regmap_reg_range(0xB, 0xB), regmap_reg_range(0xD, 0xD), + regmap_reg_range(0xF, 0xF), +}; +static const struct regmap_access_table dio48e_wr_table =3D { + .yes_ranges =3D dio48e_wr_ranges, + .n_yes_ranges =3D ARRAY_SIZE(dio48e_wr_ranges), +}; +static const struct regmap_access_table dio48e_rd_table =3D { + .yes_ranges =3D dio48e_rd_ranges, + .n_yes_ranges =3D ARRAY_SIZE(dio48e_rd_ranges), +}; +static const struct regmap_access_table dio48e_volatile_table =3D { + .yes_ranges =3D dio48e_volatile_ranges, + .n_yes_ranges =3D ARRAY_SIZE(dio48e_volatile_ranges), +}; +static const struct regmap_access_table dio48e_precious_table =3D { + .yes_ranges =3D dio48e_precious_ranges, + .n_yes_ranges =3D ARRAY_SIZE(dio48e_precious_ranges), +}; +static const struct regmap_config dio48e_regmap_config =3D { + .reg_bits =3D 8, + .reg_stride =3D 1, + .val_bits =3D 8, + .io_port =3D true, + .max_register =3D 0xF, + .wr_table =3D &dio48e_wr_table, + .rd_table =3D &dio48e_rd_table, + .volatile_table =3D &dio48e_volatile_table, + .precious_table =3D &dio48e_precious_table, + .cache_type =3D REGCACHE_FLAT, +}; =20 - if (!dio48egpio->irq_mask) { - /* enable interrupts */ - iowrite8(0x00, &dio48egpio->reg->clear_interrupt); - iowrite8(0x00, &dio48egpio->reg->enable_interrupt); +/* only bit 3 on each respective Port C supports interrupts */ +#define DIO48E_REGMAP_IRQ(_ppi) \ + [19 + (_ppi) * 24] =3D { \ + .mask =3D BIT(_ppi), \ + .type =3D { .types_supported =3D IRQ_TYPE_EDGE_RISING }, \ } =20 - gpiochip_enable_irq(chip, offset); - if (offset =3D=3D 19) - dio48egpio->irq_mask |=3D BIT(0); - else - dio48egpio->irq_mask |=3D BIT(1); - - raw_spin_unlock_irqrestore(&dio48egpio->lock, flags); -} - -static int dio48e_irq_set_type(struct irq_data *data, unsigned int flow_ty= pe) -{ - const unsigned long offset =3D irqd_to_hwirq(data); - - /* only bit 3 on each respective Port C supports interrupts */ - if (offset !=3D 19 && offset !=3D 43) - return -EINVAL; - - if (flow_type !=3D IRQ_TYPE_NONE && flow_type !=3D IRQ_TYPE_EDGE_RISING) - return -EINVAL; - - return 0; -} - -static const struct irq_chip dio48e_irqchip =3D { - .name =3D "104-dio-48e", - .irq_ack =3D dio48e_irq_ack, - .irq_mask =3D dio48e_irq_mask, - .irq_unmask =3D dio48e_irq_unmask, - .irq_set_type =3D dio48e_irq_set_type, - .flags =3D IRQCHIP_IMMUTABLE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, +static const struct regmap_irq dio48e_regmap_irqs[] =3D { + DIO48E_REGMAP_IRQ(0), DIO48E_REGMAP_IRQ(1), }; =20 -static irqreturn_t dio48e_irq_handler(int irq, void *dev_id) +static int dio48e_handle_mask_sync(struct regmap *const map, const int ind= ex, + const unsigned int mask_buf_def, + const unsigned int mask_buf, + void *const irq_drv_data) { - struct dio48e_gpio *const dio48egpio =3D dev_id; - struct gpio_chip *const chip =3D &dio48egpio->chip; - const unsigned long irq_mask =3D dio48egpio->irq_mask; - unsigned long gpio; + unsigned int *const irq_mask =3D irq_drv_data; + const unsigned int prev_mask =3D *irq_mask; + const unsigned int all_masked =3D 0x3; + unsigned int val; =20 - for_each_set_bit(gpio, &irq_mask, 2) - generic_handle_domain_irq(chip->irq.domain, - 19 + gpio*24); + /* exit early if no change since the previous mask */ + if (mask_buf =3D=3D prev_mask) + return 0; =20 - raw_spin_lock(&dio48egpio->lock); + /* remember the current mask for the next mask sync */ + *irq_mask =3D mask_buf; =20 - iowrite8(0x00, &dio48egpio->reg->clear_interrupt); + /* if all previously masked, enable interrupts when unmasking */ + if (prev_mask =3D=3D all_masked) + return regmap_write(map, DIO48E_ENABLE_INTERRUPT, 0x00); =20 - raw_spin_unlock(&dio48egpio->lock); + /* if all are currently masked, disable interrupts */ + if (mask_buf =3D=3D all_masked) + return regmap_read(map, DIO48E_DISABLE_INTERRUPT, &val); =20 - return IRQ_HANDLED; + return 0; } =20 #define DIO48E_NGPIO 48 @@ -266,14 +232,12 @@ static const char *dio48e_names[DIO48E_NGPIO] =3D { "PPI Group 1 Port C 5", "PPI Group 1 Port C 6", "PPI Group 1 Port C 7" }; =20 -static int dio48e_irq_init_hw(struct gpio_chip *gc) +static int dio48e_irq_init_hw(struct regmap *const map) { - struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(gc); + unsigned int val; =20 /* Disable IRQ by default */ - ioread8(&dio48egpio->reg->enable_interrupt); - - return 0; + return regmap_read(map, DIO48E_DISABLE_INTERRUPT, &val); } =20 static void dio48e_init_ppi(struct i8255 __iomem *const ppi, @@ -295,8 +259,12 @@ static int dio48e_probe(struct device *dev, unsigned i= nt id) { struct dio48e_gpio *dio48egpio; const char *const name =3D dev_name(dev); - struct gpio_irq_chip *girq; + void __iomem *regs; + struct regmap *map; int err; + struct regmap_irq_chip *chip; + unsigned int irq_mask; + struct regmap_irq_chip_data *chip_data; =20 dio48egpio =3D devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL); if (!dio48egpio) @@ -308,9 +276,43 @@ static int dio48e_probe(struct device *dev, unsigned i= nt id) return -EBUSY; } =20 - dio48egpio->reg =3D devm_ioport_map(dev, base[id], DIO48E_EXTENT); - if (!dio48egpio->reg) + regs =3D devm_ioport_map(dev, base[id], DIO48E_EXTENT); + if (!regs) return -ENOMEM; + dio48egpio->reg =3D regs; + + map =3D devm_regmap_init_mmio(dev, regs, &dio48e_regmap_config); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), + "Unable to initialize register map\n"); + + chip =3D devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->irq_drv_data =3D devm_kzalloc(dev, sizeof(irq_mask), GFP_KERNEL); + if (!chip->irq_drv_data) + return -ENOMEM; + + chip->name =3D name; + /* No IRQ status register so use CLEAR_INTERRUPT register instead */ + chip->status_base =3D DIO48E_CLEAR_INTERRUPT; + chip->mask_base =3D DIO48E_ENABLE_INTERRUPT; + chip->clear_on_unmask =3D true; + chip->status_invert =3D true; + chip->num_regs =3D 1; + chip->irqs =3D dio48e_regmap_irqs; + chip->num_irqs =3D ARRAY_SIZE(dio48e_regmap_irqs); + chip->handle_mask_sync =3D dio48e_handle_mask_sync; + + /* Initialize to prevent spurious interrupts before we're ready */ + err =3D dio48e_irq_init_hw(map); + if (err) + return err; + + err =3D devm_regmap_add_irq_chip(dev, map, irq[id], 0, 0, chip, &chip_dat= a); + if (err) + return dev_err_probe(dev, err, "IRQ registration failed\n"); =20 dio48egpio->chip.label =3D name; dio48egpio->chip.parent =3D dev; @@ -326,18 +328,6 @@ static int dio48e_probe(struct device *dev, unsigned i= nt id) dio48egpio->chip.set =3D dio48e_gpio_set; dio48egpio->chip.set_multiple =3D dio48e_gpio_set_multiple; =20 - girq =3D &dio48egpio->chip.irq; - gpio_irq_chip_set_chip(girq, &dio48e_irqchip); - /* This will let us handle the parent IRQ in the driver */ - girq->parent_handler =3D NULL; - girq->num_parents =3D 0; - girq->parents =3D NULL; - girq->default_type =3D IRQ_TYPE_NONE; - girq->handler =3D handle_edge_irq; - girq->init_hw =3D dio48e_irq_init_hw; - - raw_spin_lock_init(&dio48egpio->lock); - i8255_state_init(dio48egpio->ppi_state, DIO48E_NUM_PPI); dio48e_init_ppi(dio48egpio->reg->ppi, dio48egpio->ppi_state); =20 @@ -347,14 +337,8 @@ static int dio48e_probe(struct device *dev, unsigned i= nt id) return err; } =20 - err =3D devm_request_irq(dev, irq[id], dio48e_irq_handler, 0, name, - dio48egpio); - if (err) { - dev_err(dev, "IRQ handler registering failed (%d)\n", err); - return err; - } - - return 0; + return gpiochip_irqchip_add_domain(&dio48egpio->chip, + regmap_irq_get_domain(chip_data)); } =20 static struct isa_driver dio48e_driver =3D { --=20 2.38.1 From nobody Sun Apr 28 04:44:26 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6B09BC47089 for ; Fri, 2 Dec 2022 16:27:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234141AbiLBQ1k (ORCPT ); Fri, 2 Dec 2022 11:27:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43658 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234083AbiLBQ12 (ORCPT ); Fri, 2 Dec 2022 11:27:28 -0500 Received: from mail-qt1-x829.google.com (mail-qt1-x829.google.com [IPv6:2607:f8b0:4864:20::829]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D48EF55A2 for ; Fri, 2 Dec 2022 08:27:26 -0800 (PST) Received: by mail-qt1-x829.google.com with SMTP id a27so5822967qtw.10 for ; Fri, 02 Dec 2022 08:27:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=TqC2qQi/m5/bMJ/IGRccY1o0CwWxGaNKxplVl7YEMaw=; b=wPPUf/BHvj30vXef1lm0dCJkD7yMNhgG2baLoK/EHeIgFd4T0Uhrm4FwCK52WA2rql GsNTvwSl3ewCLeDfPuLbP2A5pQ+RdqnoFLqqbsDYCGBhbJjI1eAUNqeGMlfPxvOv8y1b bNnor8sLxEkEQtLE6sUSPitHDZF+c1OIZvgrTfXJS9nYNfy7EmNBYicn3PXZ8Ct7K51j OZu7/9eV8zAmtyjWWuJep570zduIxLd5ilYL0BUMYjlsQb0hQo2pcSkSM9Bc1m0DMGz5 sKOTO1of9ku5Qq9qoE2mxFJudM1ZTcBY7w3RajHAsusGmOMlZhgk3dsga+z5qIoszlmV 14YQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=TqC2qQi/m5/bMJ/IGRccY1o0CwWxGaNKxplVl7YEMaw=; b=P54hoUV5cjkdfAc6r4nS78MSvYjv6XyEvp1VFMtPJBMd1Ifpe4a81LBy8PTeH4D/6n LAx5A8EUpKFQmErsO0vAOoZu1rSTKI7pOH8v3xNKAyU8axpybl/3M3jHBiNqB1sWfKVY XF21RLniEMMCHO7mEvURjoKtmWsasAYCD23MdzQUXoV5jI+F8WXwHtbjWXSOTU7lUI8R wAC3i4Gs6Zf6le1Ft7YwLQdzj+p1tVi4t82xFELvQW1MsijxWygNXiIhoGTXlPExZdrf QCTtMP2PtAr1S/Vy6+vxriT2ZqQ6KyjQojj2LYqZkzaCOgIM+1idc2ELCRwzBCZqEyeq tZYw== X-Gm-Message-State: ANoB5pkNk83soc4bOS9H5u/+jLxBJTMD8J1HhJdyQ+2O/6pkMNBP+3tQ H3IEvpP0f5XWFvIHZ2HhykthkQ== X-Google-Smtp-Source: AA0mqf5nUbbBG7b2QOept4qBOv9VyVG+IdOWD0nL/8G5FOaZebJG34AXSk2bWu8XKq1NNO5ph25lsw== X-Received: by 2002:a05:620a:22a2:b0:6fa:2ec7:3e0 with SMTP id p2-20020a05620a22a200b006fa2ec703e0mr47349417qkh.392.1669998445892; Fri, 02 Dec 2022 08:27:25 -0800 (PST) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id fp38-20020a05622a50a600b00343057845f7sm4391887qtb.20.2022.12.02.08.27.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Dec 2022 08:27:25 -0800 (PST) From: William Breathitt Gray To: linus.walleij@linaro.org, brgl@bgdev.pl Cc: andriy.shevchenko@linux.intel.com, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, michael@walle.cc, broonie@kernel.org, William Breathitt Gray Subject: [PATCH v4 4/9] gpio: 104-idi-48: Migrate to the regmap-irq API Date: Fri, 2 Dec 2022 11:27:10 -0500 Message-Id: X-Mailer: git-send-email 2.38.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The regmap API supports IO port accessors so we can take advantage of regmap abstractions rather than handling access to the device registers directly in the driver. For the 104-idi-48, we get an IRQ register with some status information and basic masking, but it's broken down by banks rather than individual GPIO. There are six banks (8 GPIO lines each) that correspond to the lower six bits of the IRQ register (bits 0-5): Base Address + 7 (Read): IRQ Status Register/IRQ Clear Bit 0-5: Respective Bank IRQ Statuses Bit 6: IRQ Status (Active Low) Bit 7: IRQ Enable Status Base Address + 7 (Write): IRQ Enable/Disable Bit 0-5: Respective Bank IRQ Enable/Disable Signed-off-by: William Breathitt Gray Reviewed-by: Andy Shevchenko --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-104-idi-48.c | 249 ++++++++++++--------------------- 2 files changed, 92 insertions(+), 158 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b62bef4e563d..6892979e511a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -871,6 +871,7 @@ config GPIO_104_IDI_48 tristate "ACCES 104-IDI-48 GPIO support" depends on PC104 select ISA_BUS_API + select REGMAP_IRQ select GPIOLIB_IRQCHIP select GPIO_I8255 help diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c index c5e231fde1af..f936e3e0ff12 100644 --- a/drivers/gpio/gpio-104-idi-48.c +++ b/drivers/gpio/gpio-104-idi-48.c @@ -8,17 +8,16 @@ */ #include #include -#include +#include #include -#include -#include #include -#include +#include +#include #include #include #include #include -#include +#include #include =20 #include "gpio-i8255.h" @@ -38,6 +37,9 @@ static unsigned int num_irq; module_param_hw_array(irq, uint, irq, &num_irq, 0); MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers"); =20 +#define IDI48_IRQ_STATUS 0x7 +#define IDI48_IRQ_ENABLE IDI48_IRQ_STATUS + /** * struct idi_48_reg - device register structure * @port0: Port 0 Inputs @@ -56,17 +58,11 @@ struct idi_48_reg { /** * struct idi_48_gpio - GPIO device private data structure * @chip: instance of the gpio_chip - * @lock: synchronization lock to prevent I/O race conditions - * @irq_mask: input bits affected by interrupts * @reg: I/O address offset for the device registers - * @cos_enb: Change-Of-State IRQ enable boundaries mask */ struct idi_48_gpio { struct gpio_chip chip; - spinlock_t lock; - unsigned char irq_mask[6]; struct idi_48_reg __iomem *reg; - unsigned char cos_enb; }; =20 static int idi_48_gpio_get_direction(struct gpio_chip *chip, unsigned int = offset) @@ -98,125 +94,65 @@ static int idi_48_gpio_get_multiple(struct gpio_chip *= chip, unsigned long *mask, return 0; } =20 -static void idi_48_irq_ack(struct irq_data *data) -{ -} - -static void idi_48_irq_mask(struct irq_data *data) -{ - struct gpio_chip *chip =3D irq_data_get_irq_chip_data(data); - struct idi_48_gpio *const idi48gpio =3D gpiochip_get_data(chip); - const unsigned int offset =3D irqd_to_hwirq(data); - const unsigned long boundary =3D offset / 8; - const unsigned long mask =3D BIT(offset % 8); - unsigned long flags; - - spin_lock_irqsave(&idi48gpio->lock, flags); - - idi48gpio->irq_mask[boundary] &=3D ~mask; - gpiochip_disable_irq(chip, offset); - - /* Exit early if there are still input lines with IRQ unmasked */ - if (idi48gpio->irq_mask[boundary]) - goto exit; - - idi48gpio->cos_enb &=3D ~BIT(boundary); - - iowrite8(idi48gpio->cos_enb, &idi48gpio->reg->irq); - -exit: - spin_unlock_irqrestore(&idi48gpio->lock, flags); -} - -static void idi_48_irq_unmask(struct irq_data *data) -{ - struct gpio_chip *chip =3D irq_data_get_irq_chip_data(data); - struct idi_48_gpio *const idi48gpio =3D gpiochip_get_data(chip); - const unsigned int offset =3D irqd_to_hwirq(data); - const unsigned long boundary =3D offset / 8; - const unsigned long mask =3D BIT(offset % 8); - unsigned int prev_irq_mask; - unsigned long flags; - - spin_lock_irqsave(&idi48gpio->lock, flags); - - prev_irq_mask =3D idi48gpio->irq_mask[boundary]; - - gpiochip_enable_irq(chip, offset); - idi48gpio->irq_mask[boundary] |=3D mask; - - /* Exit early if IRQ was already unmasked for this boundary */ - if (prev_irq_mask) - goto exit; - - idi48gpio->cos_enb |=3D BIT(boundary); - - iowrite8(idi48gpio->cos_enb, &idi48gpio->reg->irq); - -exit: - spin_unlock_irqrestore(&idi48gpio->lock, flags); -} - -static int idi_48_irq_set_type(struct irq_data *data, unsigned int flow_ty= pe) -{ - /* The only valid irq types are none and both-edges */ - if (flow_type !=3D IRQ_TYPE_NONE && - (flow_type & IRQ_TYPE_EDGE_BOTH) !=3D IRQ_TYPE_EDGE_BOTH) - return -EINVAL; - - return 0; -} - -static const struct irq_chip idi_48_irqchip =3D { - .name =3D "104-idi-48", - .irq_ack =3D idi_48_irq_ack, - .irq_mask =3D idi_48_irq_mask, - .irq_unmask =3D idi_48_irq_unmask, - .irq_set_type =3D idi_48_irq_set_type, - .flags =3D IRQCHIP_IMMUTABLE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, +static const struct regmap_range idi_48_wr_ranges[] =3D { + regmap_reg_range(0x0, 0x6), +}; +static const struct regmap_range idi_48_rd_ranges[] =3D { + regmap_reg_range(0x0, 0x2), regmap_reg_range(0x4, 0x7), +}; +static const struct regmap_range idi_48_precious_ranges[] =3D { + regmap_reg_range(0x7, 0x7), +}; +static const struct regmap_access_table idi_48_wr_table =3D { + .no_ranges =3D idi_48_wr_ranges, + .n_no_ranges =3D ARRAY_SIZE(idi_48_wr_ranges), +}; +static const struct regmap_access_table idi_48_rd_table =3D { + .yes_ranges =3D idi_48_rd_ranges, + .n_yes_ranges =3D ARRAY_SIZE(idi_48_rd_ranges), +}; +static const struct regmap_access_table idi_48_precious_table =3D { + .yes_ranges =3D idi_48_precious_ranges, + .n_yes_ranges =3D ARRAY_SIZE(idi_48_precious_ranges), +}; +static const struct regmap_config idi48_regmap_config =3D { + .reg_bits =3D 8, + .reg_stride =3D 1, + .val_bits =3D 8, + .io_port =3D true, + .max_register =3D 0x6, + .wr_table =3D &idi_48_wr_table, + .rd_table =3D &idi_48_rd_table, + .precious_table =3D &idi_48_precious_table, }; =20 -static irqreturn_t idi_48_irq_handler(int irq, void *dev_id) -{ - struct idi_48_gpio *const idi48gpio =3D dev_id; - unsigned long cos_status; - unsigned long boundary; - unsigned long irq_mask; - unsigned long bit_num; - unsigned long gpio; - struct gpio_chip *const chip =3D &idi48gpio->chip; - - spin_lock(&idi48gpio->lock); - - cos_status =3D ioread8(&idi48gpio->reg->irq); - - /* IRQ Status (bit 6) is active low (0 =3D IRQ generated by device) */ - if (cos_status & BIT(6)) { - spin_unlock(&idi48gpio->lock); - return IRQ_NONE; - } - - /* Bit 0-5 indicate which Change-Of-State boundary triggered the IRQ */ - cos_status &=3D 0x3F; - - for_each_set_bit(boundary, &cos_status, 6) { - irq_mask =3D idi48gpio->irq_mask[boundary]; - - for_each_set_bit(bit_num, &irq_mask, 8) { - gpio =3D bit_num + boundary * 8; +#define IDI48_NGPIO 48 =20 - generic_handle_domain_irq(chip->irq.domain, - gpio); - } +#define IDI48_REGMAP_IRQ(_id) \ + [_id] =3D { \ + .mask =3D BIT((_id) / 8), \ + .type =3D { .types_supported =3D IRQ_TYPE_EDGE_BOTH }, \ } =20 - spin_unlock(&idi48gpio->lock); - - return IRQ_HANDLED; -} +static const struct regmap_irq idi48_regmap_irqs[IDI48_NGPIO] =3D { + IDI48_REGMAP_IRQ(0), IDI48_REGMAP_IRQ(1), IDI48_REGMAP_IRQ(2), /* 0-2 */ + IDI48_REGMAP_IRQ(3), IDI48_REGMAP_IRQ(4), IDI48_REGMAP_IRQ(5), /* 3-5 */ + IDI48_REGMAP_IRQ(6), IDI48_REGMAP_IRQ(7), IDI48_REGMAP_IRQ(8), /* 6-8 */ + IDI48_REGMAP_IRQ(9), IDI48_REGMAP_IRQ(10), IDI48_REGMAP_IRQ(11), /* 9-11 = */ + IDI48_REGMAP_IRQ(12), IDI48_REGMAP_IRQ(13), IDI48_REGMAP_IRQ(14), /* 12-1= 4 */ + IDI48_REGMAP_IRQ(15), IDI48_REGMAP_IRQ(16), IDI48_REGMAP_IRQ(17), /* 15-1= 7 */ + IDI48_REGMAP_IRQ(18), IDI48_REGMAP_IRQ(19), IDI48_REGMAP_IRQ(20), /* 18-2= 0 */ + IDI48_REGMAP_IRQ(21), IDI48_REGMAP_IRQ(22), IDI48_REGMAP_IRQ(23), /* 21-2= 3 */ + IDI48_REGMAP_IRQ(24), IDI48_REGMAP_IRQ(25), IDI48_REGMAP_IRQ(26), /* 24-2= 6 */ + IDI48_REGMAP_IRQ(27), IDI48_REGMAP_IRQ(28), IDI48_REGMAP_IRQ(29), /* 27-2= 9 */ + IDI48_REGMAP_IRQ(30), IDI48_REGMAP_IRQ(31), IDI48_REGMAP_IRQ(32), /* 30-3= 2 */ + IDI48_REGMAP_IRQ(33), IDI48_REGMAP_IRQ(34), IDI48_REGMAP_IRQ(35), /* 33-3= 5 */ + IDI48_REGMAP_IRQ(36), IDI48_REGMAP_IRQ(37), IDI48_REGMAP_IRQ(38), /* 36-3= 8 */ + IDI48_REGMAP_IRQ(39), IDI48_REGMAP_IRQ(40), IDI48_REGMAP_IRQ(41), /* 39-4= 1 */ + IDI48_REGMAP_IRQ(42), IDI48_REGMAP_IRQ(43), IDI48_REGMAP_IRQ(44), /* 42-4= 4 */ + IDI48_REGMAP_IRQ(45), IDI48_REGMAP_IRQ(46), IDI48_REGMAP_IRQ(47), /* 45-4= 7 */ +}; =20 -#define IDI48_NGPIO 48 static const char *idi48_names[IDI48_NGPIO] =3D { "Bit 0 A", "Bit 1 A", "Bit 2 A", "Bit 3 A", "Bit 4 A", "Bit 5 A", "Bit 6 A", "Bit 7 A", "Bit 8 A", "Bit 9 A", "Bit 10 A", "Bit 11 A", @@ -228,22 +164,14 @@ static const char *idi48_names[IDI48_NGPIO] =3D { "Bit 18 B", "Bit 19 B", "Bit 20 B", "Bit 21 B", "Bit 22 B", "Bit 23 B" }; =20 -static int idi_48_irq_init_hw(struct gpio_chip *gc) -{ - struct idi_48_gpio *const idi48gpio =3D gpiochip_get_data(gc); - - /* Disable IRQ by default */ - iowrite8(0, &idi48gpio->reg->irq); - ioread8(&idi48gpio->reg->irq); - - return 0; -} - static int idi_48_probe(struct device *dev, unsigned int id) { struct idi_48_gpio *idi48gpio; const char *const name =3D dev_name(dev); - struct gpio_irq_chip *girq; + void __iomem *regs; + struct regmap *map; + struct regmap_irq_chip *chip; + struct regmap_irq_chip_data *chip_data; int err; =20 idi48gpio =3D devm_kzalloc(dev, sizeof(*idi48gpio), GFP_KERNEL); @@ -256,9 +184,32 @@ static int idi_48_probe(struct device *dev, unsigned i= nt id) return -EBUSY; } =20 - idi48gpio->reg =3D devm_ioport_map(dev, base[id], IDI_48_EXTENT); - if (!idi48gpio->reg) + regs =3D devm_ioport_map(dev, base[id], IDI_48_EXTENT); + if (!regs) return -ENOMEM; + idi48gpio->reg =3D regs; + + map =3D devm_regmap_init_mmio(dev, regs, &idi48_regmap_config); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), + "Unable to initialize register map\n"); + + chip =3D devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->name =3D name; + chip->status_base =3D IDI48_IRQ_STATUS; + chip->unmask_base =3D IDI48_IRQ_ENABLE; + chip->clear_on_unmask =3D true; + chip->num_regs =3D 1; + chip->irqs =3D idi48_regmap_irqs; + chip->num_irqs =3D ARRAY_SIZE(idi48_regmap_irqs); + + err =3D devm_regmap_add_irq_chip(dev, map, irq[id], IRQF_SHARED, 0, chip, + &chip_data); + if (err) + return dev_err_probe(dev, err, "IRQ registration failed\n"); =20 idi48gpio->chip.label =3D name; idi48gpio->chip.parent =3D dev; @@ -271,32 +222,14 @@ static int idi_48_probe(struct device *dev, unsigned = int id) idi48gpio->chip.get =3D idi_48_gpio_get; idi48gpio->chip.get_multiple =3D idi_48_gpio_get_multiple; =20 - girq =3D &idi48gpio->chip.irq; - gpio_irq_chip_set_chip(girq, &idi_48_irqchip); - /* This will let us handle the parent IRQ in the driver */ - girq->parent_handler =3D NULL; - girq->num_parents =3D 0; - girq->parents =3D NULL; - girq->default_type =3D IRQ_TYPE_NONE; - girq->handler =3D handle_edge_irq; - girq->init_hw =3D idi_48_irq_init_hw; - - spin_lock_init(&idi48gpio->lock); - err =3D devm_gpiochip_add_data(dev, &idi48gpio->chip, idi48gpio); if (err) { dev_err(dev, "GPIO registering failed (%d)\n", err); return err; } =20 - err =3D devm_request_irq(dev, irq[id], idi_48_irq_handler, IRQF_SHARED, - name, idi48gpio); - if (err) { - dev_err(dev, "IRQ handler registering failed (%d)\n", err); - return err; - } - - return 0; + return gpiochip_irqchip_add_domain(&idi48gpio->chip, + regmap_irq_get_domain(chip_data)); } =20 static struct isa_driver idi_48_driver =3D { --=20 2.38.1 From nobody Sun Apr 28 04:44:26 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 546A7C4321E for ; Fri, 2 Dec 2022 16:27:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234146AbiLBQ1o (ORCPT ); Fri, 2 Dec 2022 11:27:44 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43666 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234085AbiLBQ13 (ORCPT ); Fri, 2 Dec 2022 11:27:29 -0500 Received: from mail-qt1-x835.google.com (mail-qt1-x835.google.com [IPv6:2607:f8b0:4864:20::835]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4D8AF5FCE for ; Fri, 2 Dec 2022 08:27:27 -0800 (PST) Received: by mail-qt1-x835.google.com with SMTP id a27so5823035qtw.10 for ; Fri, 02 Dec 2022 08:27:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=eeTGikJOduCR4hf+ZAFaYh/6mZCP5jhCR6ZyAwRbPx0=; b=KfAdsDX5Oim7j7iDc2Qtb5FSZAq2Y2GwYl2jIapLVSaUE2NW9hOWHgL72X6JxQuAUv jFiFjmLx7jQQkbGMawQ6F8MeFHcVxBiF5P5opjvauPwKk65WeKm/yqY7K52KFCSIvB54 Uq+4ATmo19kgrXYQ7ChdPqkDT4jIifgLX6hyxlMel3/W11hv3w1cH6fZjrpHjurqYT7E TlSBD4A8G3d+Z9m8rez7mMVtsS6+KF4xHjTfjBDZNbEiXG20JC28NIcqS30BF7Jop6gA 2HR/HLriRJ0tzoo3EnUpIBK6kuyaI6ezNqXww6qleLJhnGSi/Euek4m4VSuQVijpjQXU wJ+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=eeTGikJOduCR4hf+ZAFaYh/6mZCP5jhCR6ZyAwRbPx0=; b=MzOMsQ6Ej+yVUj31bsJG8zz5HMhdD7yyy08dhHDjuS8CyyQ/0oiWgPV+mq0ozyjKu6 PiuXRtRYoI9H9muMBysmMfVIzfLx/2U6r76/qIWpGOLMACAPYtrMCoZkJVUyxkuaFlXF VZZqNC8cv04e4qBJ/JKEqTqp2goFcHm8sY4z/MeMzDt85osb74Xs5ukqfdZK5BwkOm8M PprMvKsUv9RZhsHWK08+iBH40bfhYnEeDDZMaqo3NmhD8YxC6iHwLiKWX+GZ5Gfva62p giQFiTEsDbahn5OzEw1KFYSsKul2/7JQnom5oAs1TbGN8HtQEjv2Ey8DBKUMRt+CRYLi FpDA== X-Gm-Message-State: ANoB5pkjE3nGCJrXTtT/YhUPN1XQg9YniPHPmS7UT/JP4+9Lhxk4G3u6 m2sFbJQuVzek0l7dV0HFGTs9nQ== X-Google-Smtp-Source: AA0mqf46NZfcvR3CKAekWzD3uPdtD3kxgo9sjdw33nfKk8v5tYQMYnp0n+75jz9JQdY9VtwcsYjJKg== X-Received: by 2002:ac8:1189:0:b0:3a5:2766:552a with SMTP id d9-20020ac81189000000b003a52766552amr53216893qtj.79.1669998446908; Fri, 02 Dec 2022 08:27:26 -0800 (PST) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id fp38-20020a05622a50a600b00343057845f7sm4391887qtb.20.2022.12.02.08.27.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Dec 2022 08:27:26 -0800 (PST) From: William Breathitt Gray To: linus.walleij@linaro.org, brgl@bgdev.pl Cc: andriy.shevchenko@linux.intel.com, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, michael@walle.cc, broonie@kernel.org, William Breathitt Gray Subject: [PATCH v4 5/9] gpio: 104-idi-48: Migrate to gpio-regmap API Date: Fri, 2 Dec 2022 11:27:11 -0500 Message-Id: <57cc57fcbe2fd94d4492d0dac7fba7beec071618.1669996867.git.william.gray@linaro.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The regmap API supports IO port accessors so we can take advantage of regmap abstractions rather than handling access to the device registers directly in the driver. Despite the underlying interface being based on i8255, it is simpler to use the gpio-regmap API directly because the 104-IDI-48 device features only input signals. Therefore, the dependence on the i8255 GPIO library is removed in this patch. Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Signed-off-by: William Breathitt Gray --- drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-104-idi-48.c | 97 +++++++--------------------------- 2 files changed, 21 insertions(+), 78 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 6892979e511a..dd34039fc31b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -873,7 +873,7 @@ config GPIO_104_IDI_48 select ISA_BUS_API select REGMAP_IRQ select GPIOLIB_IRQCHIP - select GPIO_I8255 + select GPIO_REGMAP help Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A, 104-IDI-48AC, 104-IDI-48B, 104-IDI-48BC). The base port addresses for diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c index f936e3e0ff12..ca2175b84e24 100644 --- a/drivers/gpio/gpio-104-idi-48.c +++ b/drivers/gpio/gpio-104-idi-48.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -20,10 +20,6 @@ #include #include =20 -#include "gpio-i8255.h" - -MODULE_IMPORT_NS(I8255); - #define IDI_48_EXTENT 8 #define MAX_NUM_IDI_48 max_num_isa_dev(IDI_48_EXTENT) =20 @@ -40,56 +36,17 @@ MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line = numbers"); #define IDI48_IRQ_STATUS 0x7 #define IDI48_IRQ_ENABLE IDI48_IRQ_STATUS =20 -/** - * struct idi_48_reg - device register structure - * @port0: Port 0 Inputs - * @unused: Unused - * @port1: Port 1 Inputs - * @irq: Read: IRQ Status Register/IRQ Clear - * Write: IRQ Enable/Disable - */ -struct idi_48_reg { - u8 port0[3]; - u8 unused; - u8 port1[3]; - u8 irq; -}; - -/** - * struct idi_48_gpio - GPIO device private data structure - * @chip: instance of the gpio_chip - * @reg: I/O address offset for the device registers - */ -struct idi_48_gpio { - struct gpio_chip chip; - struct idi_48_reg __iomem *reg; -}; - -static int idi_48_gpio_get_direction(struct gpio_chip *chip, unsigned int = offset) -{ - return GPIO_LINE_DIRECTION_IN; -} - -static int idi_48_gpio_direction_input(struct gpio_chip *chip, unsigned in= t offset) +static int idi_48_reg_mask_xlate(struct gpio_regmap *gpio, unsigned int ba= se, + unsigned int offset, unsigned int *reg, + unsigned int *mask) { - return 0; -} - -static int idi_48_gpio_get(struct gpio_chip *chip, unsigned int offset) -{ - struct idi_48_gpio *const idi48gpio =3D gpiochip_get_data(chip); - void __iomem *const ppi =3D idi48gpio->reg; + const unsigned int line =3D offset % 8; + const unsigned int stride =3D offset / 8; + const unsigned int port =3D (stride / 3) * 4; + const unsigned int port_stride =3D stride % 3; =20 - return i8255_get(ppi, offset); -} - -static int idi_48_gpio_get_multiple(struct gpio_chip *chip, unsigned long = *mask, - unsigned long *bits) -{ - struct idi_48_gpio *const idi48gpio =3D gpiochip_get_data(chip); - void __iomem *const ppi =3D idi48gpio->reg; - - i8255_get_multiple(ppi, mask, bits, chip->ngpio); + *reg =3D base + port + port_stride; + *mask =3D BIT(line); =20 return 0; } @@ -166,18 +123,14 @@ static const char *idi48_names[IDI48_NGPIO] =3D { =20 static int idi_48_probe(struct device *dev, unsigned int id) { - struct idi_48_gpio *idi48gpio; const char *const name =3D dev_name(dev); + struct gpio_regmap_config config =3D {}; void __iomem *regs; struct regmap *map; struct regmap_irq_chip *chip; struct regmap_irq_chip_data *chip_data; int err; =20 - idi48gpio =3D devm_kzalloc(dev, sizeof(*idi48gpio), GFP_KERNEL); - if (!idi48gpio) - return -ENOMEM; - if (!devm_request_region(dev, base[id], IDI_48_EXTENT, name)) { dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", base[id], base[id] + IDI_48_EXTENT); @@ -187,7 +140,6 @@ static int idi_48_probe(struct device *dev, unsigned in= t id) regs =3D devm_ioport_map(dev, base[id], IDI_48_EXTENT); if (!regs) return -ENOMEM; - idi48gpio->reg =3D regs; =20 map =3D devm_regmap_init_mmio(dev, regs, &idi48_regmap_config); if (IS_ERR(map)) @@ -211,25 +163,16 @@ static int idi_48_probe(struct device *dev, unsigned = int id) if (err) return dev_err_probe(dev, err, "IRQ registration failed\n"); =20 - idi48gpio->chip.label =3D name; - idi48gpio->chip.parent =3D dev; - idi48gpio->chip.owner =3D THIS_MODULE; - idi48gpio->chip.base =3D -1; - idi48gpio->chip.ngpio =3D IDI48_NGPIO; - idi48gpio->chip.names =3D idi48_names; - idi48gpio->chip.get_direction =3D idi_48_gpio_get_direction; - idi48gpio->chip.direction_input =3D idi_48_gpio_direction_input; - idi48gpio->chip.get =3D idi_48_gpio_get; - idi48gpio->chip.get_multiple =3D idi_48_gpio_get_multiple; - - err =3D devm_gpiochip_add_data(dev, &idi48gpio->chip, idi48gpio); - if (err) { - dev_err(dev, "GPIO registering failed (%d)\n", err); - return err; - } + config.parent =3D dev; + config.regmap =3D map; + config.ngpio =3D IDI48_NGPIO; + config.names =3D idi48_names; + config.reg_dat_base =3D GPIO_REGMAP_ADDR(0x0); + config.ngpio_per_reg =3D 8; + config.reg_mask_xlate =3D idi_48_reg_mask_xlate; + config.irq_domain =3D regmap_irq_get_domain(chip_data); =20 - return gpiochip_irqchip_add_domain(&idi48gpio->chip, - regmap_irq_get_domain(chip_data)); + return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &config)); } =20 static struct isa_driver idi_48_driver =3D { --=20 2.38.1 From nobody Sun Apr 28 04:44:26 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 59954C4321E for ; Fri, 2 Dec 2022 16:27:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234049AbiLBQ14 (ORCPT ); Fri, 2 Dec 2022 11:27:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43696 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234115AbiLBQ1a (ORCPT ); Fri, 2 Dec 2022 11:27:30 -0500 Received: from mail-qv1-xf2a.google.com (mail-qv1-xf2a.google.com [IPv6:2607:f8b0:4864:20::f2a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C5D54958C for ; Fri, 2 Dec 2022 08:27:28 -0800 (PST) Received: by mail-qv1-xf2a.google.com with SMTP id h10so3729247qvq.7 for ; Fri, 02 Dec 2022 08:27:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=n2fGQz6WADOFjPUw7W8r0ikI69NwntloV79RPj8vaEU=; b=WJrQ06MzS/WeUmjVWnk88ZPzRQmU+OMm1/JtDGft/KsxT0ardnsPpLArr57UZAXQcE Bmt+bdcM6M97+ZRamWMNGoc2sGd/z4sCqk7Qf3BwOlDyHduHB4c3p82wDr6R3NWHkhEa 3scu1uIcqauIlmttDE8sDpzVDOixe+9qtK5vDpFkRr8cYAgoJwst6ez3adBwGwdOEWnL GhiAWakd+hKVCbGw0PqCBlpXgz8cTDzAPmK0SqnGe2mu8IwGSMCI1t96xwUyQ5s+DQ4v OEzOjpexBz0PvmrZGZfACv3T+PodDoiC6r+KYOd0+G9Xt+n1ryFFAkCxfnxIibi3RJwL QyDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=n2fGQz6WADOFjPUw7W8r0ikI69NwntloV79RPj8vaEU=; b=QkeUCrNff6jUI8J8Qugr9RmgypI85qgaKCtFiELRM59O4kaoR4PmvmPHutoB2gNIwo /4waeCsYkQNwcsZ6SpSEr/JWb4Fb+OIO4tJ5NpgSLb9G8UJREkNgoAwnjWSSRV38hIAI y9P5Z7HQtNBQkMH61/vpTiLL4c68WT8K5IQ5Zbk/osw/+1x7KyeMVWD3TShHqLeEsan+ 6Rgx8dNysgKZ39Sm3gFZfs7VzJyum8hONiK4BgHkiXEa8NnCnuFx4oOqT0lz6eji75M1 iSicKnBI5D2E1rZIUKTS8VG7EWcDGocm03Jmv7Vv5kQS2XbcoO/rqLYoC9oBGbKLL3TD 0b1Q== X-Gm-Message-State: ANoB5pli5fbvF8bXZ+WCHhPFQFoUFw4aOuLkOiNKH+mCpkNksWTWYAbZ uet29rxfVvbmcTEVCBGJJWB1Dg== X-Google-Smtp-Source: AA0mqf51GexLqPS5C0l/WL4rlAs7x3VEKnEWlThWhTO6PKI+g11G++MCyUQ60W7pUq4EDUvtwQ8FOw== X-Received: by 2002:ad4:4e85:0:b0:4c6:fa37:1d16 with SMTP id dy5-20020ad44e85000000b004c6fa371d16mr25444288qvb.106.1669998447912; Fri, 02 Dec 2022 08:27:27 -0800 (PST) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id fp38-20020a05622a50a600b00343057845f7sm4391887qtb.20.2022.12.02.08.27.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Dec 2022 08:27:27 -0800 (PST) From: William Breathitt Gray To: linus.walleij@linaro.org, brgl@bgdev.pl Cc: andriy.shevchenko@linux.intel.com, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, michael@walle.cc, broonie@kernel.org, William Breathitt Gray Subject: [PATCH v4 6/9] gpio: i8255: Migrate to gpio-regmap API Date: Fri, 2 Dec 2022 11:27:12 -0500 Message-Id: X-Mailer: git-send-email 2.38.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The regmap API supports IO port accessors so we can take advantage of regmap abstractions rather than handling access to the device registers directly in the driver. By leveraging the gpio-regmap API, the i8255 library is reduced to simply a devm_i8255_regmap_register() function, a configuration structure struct i8255_regmap_config, and a helper macro i8255_volatile_regmap_range() provided to simplify volatile PPI register hinting for the regmap. Legacy functions and code will be removed once all consumers have migrated to the new i8255 library interface. Suggested-by: Andy Shevchenko Signed-off-by: William Breathitt Gray Reviewed-by: Andy Shevchenko --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-i8255.c | 119 ++++++++++++++++++++++++++++++++++---- drivers/gpio/gpio-i8255.h | 28 +++++++++ 3 files changed, 136 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index dd34039fc31b..88dfdc62992f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -831,6 +831,7 @@ menu "Port-mapped I/O GPIO drivers" =20 config GPIO_I8255 tristate + select GPIO_REGMAP help Enables support for the i8255 interface library functions. The i8255 interface library provides functions to facilitate communication with diff --git a/drivers/gpio/gpio-i8255.c b/drivers/gpio/gpio-i8255.c index 9b97db418df1..9ecb2e9b97f9 100644 --- a/drivers/gpio/gpio-i8255.c +++ b/drivers/gpio/gpio-i8255.c @@ -4,23 +4,31 @@ * Copyright (C) 2022 William Breathitt Gray */ #include +#include #include #include +#include #include #include +#include #include #include =20 #include "gpio-i8255.h" =20 +#define I8255_NGPIO 24 +#define I8255_NGPIO_PER_REG 8 #define I8255_CONTROL_PORTC_LOWER_DIRECTION BIT(0) #define I8255_CONTROL_PORTB_DIRECTION BIT(1) #define I8255_CONTROL_PORTC_UPPER_DIRECTION BIT(3) #define I8255_CONTROL_PORTA_DIRECTION BIT(4) #define I8255_CONTROL_MODE_SET BIT(7) -#define I8255_PORTA 0 -#define I8255_PORTB 1 -#define I8255_PORTC 2 +#define I8255_PORTA 0x0 +#define I8255_PORTB 0x1 +#define I8255_PORTC 0x2 +#define I8255_CONTROL 0x3 +#define I8255_REG_DAT_BASE I8255_PORTA +#define I8255_REG_DIR_IN_BASE I8255_CONTROL =20 static int i8255_get_port(struct i8255 __iomem *const ppi, const unsigned long io_port, const unsigned long mask) @@ -31,20 +39,19 @@ static int i8255_get_port(struct i8255 __iomem *const p= pi, return ioread8(&ppi[bank].port[ppi_port]) & mask; } =20 -static u8 i8255_direction_mask(const unsigned long offset) +static int i8255_direction_mask(const unsigned int offset) { - const unsigned long port_offset =3D offset % 8; - const unsigned long io_port =3D offset / 8; - const unsigned long ppi_port =3D io_port % 3; + const unsigned int stride =3D offset / I8255_NGPIO_PER_REG; + const unsigned int line =3D offset % I8255_NGPIO_PER_REG; =20 - switch (ppi_port) { + switch (stride) { case I8255_PORTA: return I8255_CONTROL_PORTA_DIRECTION; case I8255_PORTB: return I8255_CONTROL_PORTB_DIRECTION; case I8255_PORTC: /* Port C can be configured by nibble */ - if (port_offset >=3D 4) + if (line >=3D 4) return I8255_CONTROL_PORTC_UPPER_DIRECTION; return I8255_CONTROL_PORTC_LOWER_DIRECTION; default: @@ -53,6 +60,49 @@ static u8 i8255_direction_mask(const unsigned long offse= t) } } =20 +static int i8255_ppi_init(struct regmap *const map, const unsigned int bas= e) +{ + int err; + + /* Configure all ports to MODE 0 output mode */ + err =3D regmap_write(map, base + I8255_CONTROL, I8255_CONTROL_MODE_SET); + if (err) + return err; + + /* Initialize all GPIO to output 0 */ + err =3D regmap_write(map, base + I8255_PORTA, 0x00); + if (err) + return err; + err =3D regmap_write(map, base + I8255_PORTB, 0x00); + if (err) + return err; + return regmap_write(map, base + I8255_PORTC, 0x00); +} + +static int i8255_reg_mask_xlate(struct gpio_regmap *gpio, unsigned int bas= e, + unsigned int offset, unsigned int *reg, + unsigned int *mask) +{ + const unsigned int ppi =3D offset / I8255_NGPIO; + const unsigned int ppi_offset =3D offset % I8255_NGPIO; + const unsigned int stride =3D ppi_offset / I8255_NGPIO_PER_REG; + const unsigned int line =3D ppi_offset % I8255_NGPIO_PER_REG; + + switch (base) { + case I8255_REG_DAT_BASE: + *reg =3D base + stride + ppi * 4; + *mask =3D BIT(line); + return 0; + case I8255_REG_DIR_IN_BASE: + *reg =3D base + ppi * 4; + *mask =3D i8255_direction_mask(ppi_offset); + return 0; + default: + /* Should never reach this path */ + return -EINVAL; + } +} + static void i8255_set_port(struct i8255 __iomem *const ppi, struct i8255_state *const state, const unsigned long io_port, @@ -93,7 +143,7 @@ void i8255_direction_input(struct i8255 __iomem *const p= pi, spin_lock_irqsave(&state[bank].lock, flags); =20 state[bank].control_state |=3D I8255_CONTROL_MODE_SET; - state[bank].control_state |=3D i8255_direction_mask(offset); + state[bank].control_state |=3D i8255_direction_mask(offset % 24); =20 iowrite8(state[bank].control_state, &ppi[bank].control); =20 @@ -125,7 +175,7 @@ void i8255_direction_output(struct i8255 __iomem *const= ppi, spin_lock_irqsave(&state[bank].lock, flags); =20 state[bank].control_state |=3D I8255_CONTROL_MODE_SET; - state[bank].control_state &=3D ~i8255_direction_mask(offset); + state[bank].control_state &=3D ~i8255_direction_mask(offset % 24); =20 iowrite8(state[bank].control_state, &ppi[bank].control); =20 @@ -165,7 +215,7 @@ int i8255_get_direction(const struct i8255_state *const= state, const unsigned long io_port =3D offset / 8; const unsigned long bank =3D io_port / 3; =20 - return !!(state[bank].control_state & i8255_direction_mask(offset)); + return !!(state[bank].control_state & i8255_direction_mask(offset % 24)); } EXPORT_SYMBOL_NS_GPL(i8255_get_direction, I8255); =20 @@ -282,6 +332,51 @@ void i8255_state_init(struct i8255_state *const state, } EXPORT_SYMBOL_NS_GPL(i8255_state_init, I8255); =20 +/** + * devm_i8255_regmap_register - Register an i8255 GPIO controller + * @dev: device that is registering this i8255 GPIO device + * @config: configuration for i8255_regmap_config + * + * Registers an Intel 8255 Programmable Peripheral Interface GPIO controll= er. + * Returns 0 on success and negative error number on failure. + */ +int devm_i8255_regmap_register(struct device *const dev, + const struct i8255_regmap_config *const config) +{ + struct gpio_regmap_config gpio_config =3D {0}; + unsigned long i; + int err; + + if (!config->parent) + return -EINVAL; + + if (!config->map) + return -EINVAL; + + if (!config->num_ppi) + return -EINVAL; + + for (i =3D 0; i < config->num_ppi; i++) { + err =3D i8255_ppi_init(config->map, i * 4); + if (err) + return err; + } + + gpio_config.parent =3D config->parent; + gpio_config.regmap =3D config->map; + gpio_config.ngpio =3D I8255_NGPIO * config->num_ppi; + gpio_config.names =3D config->names; + gpio_config.reg_dat_base =3D GPIO_REGMAP_ADDR(I8255_REG_DAT_BASE); + gpio_config.reg_set_base =3D GPIO_REGMAP_ADDR(I8255_REG_DAT_BASE); + gpio_config.reg_dir_in_base =3D GPIO_REGMAP_ADDR(I8255_REG_DIR_IN_BASE); + gpio_config.ngpio_per_reg =3D I8255_NGPIO_PER_REG; + gpio_config.irq_domain =3D config->domain; + gpio_config.reg_mask_xlate =3D i8255_reg_mask_xlate; + + return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config)); +} +EXPORT_SYMBOL_NS_GPL(devm_i8255_regmap_register, I8255); + MODULE_AUTHOR("William Breathitt Gray"); MODULE_DESCRIPTION("Intel 8255 Programmable Peripheral Interface"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-i8255.h b/drivers/gpio/gpio-i8255.h index d9084aae9446..3daa0b145890 100644 --- a/drivers/gpio/gpio-i8255.h +++ b/drivers/gpio/gpio-i8255.h @@ -26,6 +26,34 @@ struct i8255_state { u8 control_state; }; =20 +struct device; +struct irq_domain; +struct regmap; + +#define i8255_volatile_regmap_range(_base) regmap_reg_range(_base, _base += 0x2) + +/** + * struct i8255_regmap_config - Configuration for the register map of an i= 8255 + * @parent: parent device + * @map: regmap for the i8255 + * @num_ppi: number of i8255 Programmable Peripheral Interface + * @names: (optional) array of names for gpios + * @domain: (optional) IRQ domain if the controller is interrupt-capable + * + * Note: The regmap is expected to have cache enabled and i8255 control + * registers not marked as volatile. + */ +struct i8255_regmap_config { + struct device *parent; + struct regmap *map; + int num_ppi; + const char *const *names; + struct irq_domain *domain; +}; + +int devm_i8255_regmap_register(struct device *dev, + const struct i8255_regmap_config *config); + void i8255_direction_input(struct i8255 __iomem *ppi, struct i8255_state *= state, unsigned long offset); void i8255_direction_output(struct i8255 __iomem *ppi, --=20 2.38.1 From nobody Sun Apr 28 04:44:26 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4ADC0C4321E for ; Fri, 2 Dec 2022 16:28:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234197AbiLBQ2O (ORCPT ); Fri, 2 Dec 2022 11:28:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44004 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234127AbiLBQ1e (ORCPT ); Fri, 2 Dec 2022 11:27:34 -0500 Received: from mail-qt1-x835.google.com (mail-qt1-x835.google.com [IPv6:2607:f8b0:4864:20::835]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B7C8FDEB7 for ; Fri, 2 Dec 2022 08:27:29 -0800 (PST) Received: by mail-qt1-x835.google.com with SMTP id e15so5848148qts.1 for ; Fri, 02 Dec 2022 08:27:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JVwqscrh+zjqG/ZfukKo8keg+szpeWy+C9UuL6rL5R4=; b=GNQMFw3IVBrZxWuDo2MS7jmEP2HXHWzNMZZn19+jhbPqk/YZ36Cz0q7hNFFhvokUnL W42uVjdVI5BLX4KiIMuBxsKIEFJuy0NHVZo/+hXNrqRPYg6Ltt/M0qk6f2vtS57dVj3R pjuGgkUlFlA1sGwnDjFYhadL8uLx62c0SLirU08imILEjLJWr4C67ulchV8iPdMD1Eg2 xS3ATRESbdYdL1QTbdA/k5woVrf3Nh8nOUGje+m5/g7gTcTaykLo+u1xBQhdFxGGoPCj dElmRPbKiHUaepWYupQluGEb4OnCO7cGYRcZcBp/yq96M0T3q1SB0M7BH1vF/DPO6SVN Iijw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JVwqscrh+zjqG/ZfukKo8keg+szpeWy+C9UuL6rL5R4=; b=yq8ekUyaw/r+uZ9HyXck1DHYiaII466r1c/plUk3EzhudHttq2qaJ6zP01iFQJi4rQ Kk9Q4QOegkfQcBS+yFeIXb5kpmfxGGnDDD/SxiWxlPY33zUKLwo61sUtnTWM9hdoy6ok 071l8/UqpJzaqiUeDIWTYslNZ627XiAQhIBWyscz9eYRvmQ1UUMezqnyVokzFYd8Z8ba fMeoBI7kkEnOuIshGgEV+uCNGQ4IDpAHzdXv2iZRLdl70gzbFBKu0YtSEmTqL83K2TNI OFLkmI+yvWioCI1Q7ypswsIYqQnrX2Emh+zUBrdcfPdsmBDEyjCsHXCk5jdC3/k9g1ik 3gcg== X-Gm-Message-State: ANoB5pnjcCSeRrUUseiedqdebQzDWYj++WFGyq7ymTtaNWS5uzSHW3my MbDOSlW8VY11O23U0yI5N1p7qA== X-Google-Smtp-Source: AA0mqf66Ffp92DU3hZ9EW6PqdDgVytipumz2Jq+L5AvlajYl9Rxt02V+2Ae+i4Vk3ry2mrfeADrN6w== X-Received: by 2002:ac8:4b55:0:b0:3a4:fcde:734b with SMTP id e21-20020ac84b55000000b003a4fcde734bmr67393401qts.238.1669998448864; Fri, 02 Dec 2022 08:27:28 -0800 (PST) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id fp38-20020a05622a50a600b00343057845f7sm4391887qtb.20.2022.12.02.08.27.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Dec 2022 08:27:28 -0800 (PST) From: William Breathitt Gray To: linus.walleij@linaro.org, brgl@bgdev.pl Cc: andriy.shevchenko@linux.intel.com, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, michael@walle.cc, broonie@kernel.org, William Breathitt Gray Subject: [PATCH v4 7/9] gpio: 104-dio-48e: Migrate to regmap API Date: Fri, 2 Dec 2022 11:27:13 -0500 Message-Id: X-Mailer: git-send-email 2.38.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The regmap API supports IO port accessors so we can take advantage of regmap abstractions rather than handling access to the device registers directly in the driver. The 104-dio-48e module is migrated to the new i8255 library interface leveraging the gpio-regmap API. Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Signed-off-by: William Breathitt Gray --- drivers/gpio/gpio-104-dio-48e.c | 137 ++------------------------------ 1 file changed, 7 insertions(+), 130 deletions(-) diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48= e.c index 4c3660d5dea5..31ae98a277a4 100644 --- a/drivers/gpio/gpio-104-dio-48e.c +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -42,90 +41,6 @@ MODULE_PARM_DESC(irq, "ACCES 104-DIO-48E interrupt line = numbers"); =20 #define DIO48E_NUM_PPI 2 =20 -/** - * struct dio48e_reg - device register structure - * @ppi: Programmable Peripheral Interface groups - */ -struct dio48e_reg { - struct i8255 ppi[DIO48E_NUM_PPI]; -}; - -/** - * struct dio48e_gpio - GPIO device private data structure - * @chip: instance of the gpio_chip - * @ppi_state: PPI device states - * @reg: I/O address offset for the device registers - */ -struct dio48e_gpio { - struct gpio_chip chip; - struct i8255_state ppi_state[DIO48E_NUM_PPI]; - struct dio48e_reg __iomem *reg; -}; - -static int dio48e_gpio_get_direction(struct gpio_chip *chip, unsigned int = offset) -{ - struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(chip); - - if (i8255_get_direction(dio48egpio->ppi_state, offset)) - return GPIO_LINE_DIRECTION_IN; - - return GPIO_LINE_DIRECTION_OUT; -} - -static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned in= t offset) -{ - struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(chip); - - i8255_direction_input(dio48egpio->reg->ppi, dio48egpio->ppi_state, - offset); - - return 0; -} - -static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned i= nt offset, - int value) -{ - struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(chip); - - i8255_direction_output(dio48egpio->reg->ppi, dio48egpio->ppi_state, - offset, value); - - return 0; -} - -static int dio48e_gpio_get(struct gpio_chip *chip, unsigned int offset) -{ - struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(chip); - - return i8255_get(dio48egpio->reg->ppi, offset); -} - -static int dio48e_gpio_get_multiple(struct gpio_chip *chip, unsigned long = *mask, - unsigned long *bits) -{ - struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(chip); - - i8255_get_multiple(dio48egpio->reg->ppi, mask, bits, chip->ngpio); - - return 0; -} - -static void dio48e_gpio_set(struct gpio_chip *chip, unsigned int offset, i= nt value) -{ - struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(chip); - - i8255_set(dio48egpio->reg->ppi, dio48egpio->ppi_state, offset, value); -} - -static void dio48e_gpio_set_multiple(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) -{ - struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(chip); - - i8255_set_multiple(dio48egpio->reg->ppi, dio48egpio->ppi_state, mask, - bits, chip->ngpio); -} - static const struct regmap_range dio48e_wr_ranges[] =3D { regmap_reg_range(0x0, 0x9), regmap_reg_range(0xB, 0xB), regmap_reg_range(0xD, 0xD), regmap_reg_range(0xF, 0xF), @@ -240,25 +155,10 @@ static int dio48e_irq_init_hw(struct regmap *const ma= p) return regmap_read(map, DIO48E_DISABLE_INTERRUPT, &val); } =20 -static void dio48e_init_ppi(struct i8255 __iomem *const ppi, - struct i8255_state *const ppi_state) -{ - const unsigned long ngpio =3D 24; - const unsigned long mask =3D GENMASK(ngpio - 1, 0); - const unsigned long bits =3D 0; - unsigned long i; - - /* Initialize all GPIO to output 0 */ - for (i =3D 0; i < DIO48E_NUM_PPI; i++) { - i8255_mode0_output(&ppi[i]); - i8255_set_multiple(&ppi[i], &ppi_state[i], &mask, &bits, ngpio); - } -} - static int dio48e_probe(struct device *dev, unsigned int id) { - struct dio48e_gpio *dio48egpio; const char *const name =3D dev_name(dev); + struct i8255_regmap_config config =3D {}; void __iomem *regs; struct regmap *map; int err; @@ -266,10 +166,6 @@ static int dio48e_probe(struct device *dev, unsigned i= nt id) unsigned int irq_mask; struct regmap_irq_chip_data *chip_data; =20 - dio48egpio =3D devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL); - if (!dio48egpio) - return -ENOMEM; - if (!devm_request_region(dev, base[id], DIO48E_EXTENT, name)) { dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", base[id], base[id] + DIO48E_EXTENT); @@ -279,7 +175,6 @@ static int dio48e_probe(struct device *dev, unsigned in= t id) regs =3D devm_ioport_map(dev, base[id], DIO48E_EXTENT); if (!regs) return -ENOMEM; - dio48egpio->reg =3D regs; =20 map =3D devm_regmap_init_mmio(dev, regs, &dio48e_regmap_config); if (IS_ERR(map)) @@ -314,31 +209,13 @@ static int dio48e_probe(struct device *dev, unsigned = int id) if (err) return dev_err_probe(dev, err, "IRQ registration failed\n"); =20 - dio48egpio->chip.label =3D name; - dio48egpio->chip.parent =3D dev; - dio48egpio->chip.owner =3D THIS_MODULE; - dio48egpio->chip.base =3D -1; - dio48egpio->chip.ngpio =3D DIO48E_NGPIO; - dio48egpio->chip.names =3D dio48e_names; - dio48egpio->chip.get_direction =3D dio48e_gpio_get_direction; - dio48egpio->chip.direction_input =3D dio48e_gpio_direction_input; - dio48egpio->chip.direction_output =3D dio48e_gpio_direction_output; - dio48egpio->chip.get =3D dio48e_gpio_get; - dio48egpio->chip.get_multiple =3D dio48e_gpio_get_multiple; - dio48egpio->chip.set =3D dio48e_gpio_set; - dio48egpio->chip.set_multiple =3D dio48e_gpio_set_multiple; - - i8255_state_init(dio48egpio->ppi_state, DIO48E_NUM_PPI); - dio48e_init_ppi(dio48egpio->reg->ppi, dio48egpio->ppi_state); - - err =3D devm_gpiochip_add_data(dev, &dio48egpio->chip, dio48egpio); - if (err) { - dev_err(dev, "GPIO registering failed (%d)\n", err); - return err; - } + config.parent =3D dev; + config.map =3D map; + config.num_ppi =3D DIO48E_NUM_PPI; + config.names =3D dio48e_names; + config.domain =3D regmap_irq_get_domain(chip_data); =20 - return gpiochip_irqchip_add_domain(&dio48egpio->chip, - regmap_irq_get_domain(chip_data)); + return devm_i8255_regmap_register(dev, &config); } =20 static struct isa_driver dio48e_driver =3D { --=20 2.38.1 From nobody Sun Apr 28 04:44:26 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94870C4321E for ; Fri, 2 Dec 2022 16:28:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234183AbiLBQ2K (ORCPT ); Fri, 2 Dec 2022 11:28:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44006 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234126AbiLBQ1e (ORCPT ); Fri, 2 Dec 2022 11:27:34 -0500 Received: from mail-qv1-xf2e.google.com (mail-qv1-xf2e.google.com [IPv6:2607:f8b0:4864:20::f2e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8CDECDEE4 for ; Fri, 2 Dec 2022 08:27:30 -0800 (PST) Received: by mail-qv1-xf2e.google.com with SMTP id o12so3744656qvn.3 for ; Fri, 02 Dec 2022 08:27:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=mrsAlc2c8LXGp7WQkoKW27oUacFsP+5WvZ7Q3a50qLY=; b=InlSDr9iWrec+0Nv5Bkx+gAGnOJWGHWuV1OvjAV/RbNYsalnb0hMJCayLSkAVxwbiH FhsAiTA9aWtQALoofevhmY3pkCxPre09rqTHiEJawvU8kjq69k3BLWvU8IwmqEmwIWzb rBwIH7gPWXBjF0zU3aqY9m+XOkhjsenEGnNoituXM5rBMTJ09hO2delHbaB3wKQUR/AK U5sKrjxBolB7nVhsYs6jaRYtSiWSlPB7lt12DHn+kDPJS6KZhakW2af+VEfxOHa3rI4b 8I3bNC1qCKlY7/njqOH8m3MMzfU637IYS6gGHymr5hg5n8PgjplWRekoX1N+7IuYK6Vp bRPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=mrsAlc2c8LXGp7WQkoKW27oUacFsP+5WvZ7Q3a50qLY=; b=TAG0Ivf28d1lMYqFfb0Y4vzbApN20h6SpJVChxE0yfZOvyXzFlCnMdrzF3XhT6gsjm blb9hqS8nfafalCAGK/wy/saTVyQfTfSvFSLp+lo8/uUXB0nQdrBhTIcp9HefWBConl5 8l73vgbVr/Gn13iun9Y27DmmhVJmdmHdkz0txmAkNJYoEC+OcMHXWkWYRSLMh0bYVzZl TOnqv5mZkvwR3+fvs2piwZn34ufPlCsqDX1CZctAgSi0yDLDoCCd4WT9+b6UwFZ24ZvP v1EMexm6vGzhwjk6MGFxJwA9D3u+ml6Tnm9LBoP8pM+iRPxERZLNyaMiZAUa5souvP+8 FsGw== X-Gm-Message-State: ANoB5pkf6GxCmkewSTMc36qDw2xqj4QYK7Wi1G+VXbLR+mhr70QigUVk T7tAeclXcZdUFCMoa/wwOXS1zw== X-Google-Smtp-Source: AA0mqf5uU3PmQe9GzMiXN9bPa5FAR55Vv4Nhou7L6Wj9asjL6YTyg8XAh+5VdPCfoXjlVXgUggvFTg== X-Received: by 2002:a0c:c3cc:0:b0:4c6:a05d:f67e with SMTP id p12-20020a0cc3cc000000b004c6a05df67emr48148268qvi.4.1669998449691; Fri, 02 Dec 2022 08:27:29 -0800 (PST) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id fp38-20020a05622a50a600b00343057845f7sm4391887qtb.20.2022.12.02.08.27.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Dec 2022 08:27:29 -0800 (PST) From: William Breathitt Gray To: linus.walleij@linaro.org, brgl@bgdev.pl Cc: andriy.shevchenko@linux.intel.com, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, michael@walle.cc, broonie@kernel.org, William Breathitt Gray Subject: [PATCH v4 8/9] gpio: gpio-mm: Migrate to regmap API Date: Fri, 2 Dec 2022 11:27:14 -0500 Message-Id: <02e772baa38e25b5e7d3fe439d172afc8623485e.1669996867.git.william.gray@linaro.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The regmap API supports IO port accessors so we can take advantage of regmap abstractions rather than handling access to the device registers directly in the driver. The gpio-mm module is migrated to the new i8255 library interface leveraging the gpio-regmap API. Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Signed-off-by: William Breathitt Gray --- drivers/gpio/gpio-gpio-mm.c | 154 +++++++----------------------------- 1 file changed, 30 insertions(+), 124 deletions(-) diff --git a/drivers/gpio/gpio-gpio-mm.c b/drivers/gpio/gpio-gpio-mm.c index 2689671b6b01..43d823a56e59 100644 --- a/drivers/gpio/gpio-gpio-mm.c +++ b/drivers/gpio/gpio-gpio-mm.c @@ -8,13 +8,13 @@ */ #include #include -#include -#include #include #include #include #include #include +#include +#include =20 #include "gpio-i8255.h" =20 @@ -30,83 +30,22 @@ MODULE_PARM_DESC(base, "Diamond Systems GPIO-MM base ad= dresses"); =20 #define GPIOMM_NUM_PPI 2 =20 -/** - * struct gpiomm_gpio - GPIO device private data structure - * @chip: instance of the gpio_chip - * @ppi_state: Programmable Peripheral Interface group states - * @ppi: Programmable Peripheral Interface groups - */ -struct gpiomm_gpio { - struct gpio_chip chip; - struct i8255_state ppi_state[GPIOMM_NUM_PPI]; - struct i8255 __iomem *ppi; +static const struct regmap_range gpiomm_volatile_ranges[] =3D { + i8255_volatile_regmap_range(0x0), i8255_volatile_regmap_range(0x4), +}; +static const struct regmap_access_table gpiomm_volatile_table =3D { + .yes_ranges =3D gpiomm_volatile_ranges, + .n_yes_ranges =3D ARRAY_SIZE(gpiomm_volatile_ranges), +}; +static const struct regmap_config gpiomm_regmap_config =3D { + .reg_bits =3D 8, + .reg_stride =3D 1, + .val_bits =3D 8, + .io_port =3D true, + .max_register =3D 0x7, + .volatile_table =3D &gpiomm_volatile_table, + .cache_type =3D REGCACHE_FLAT, }; - -static int gpiomm_gpio_get_direction(struct gpio_chip *chip, - unsigned int offset) -{ - struct gpiomm_gpio *const gpiommgpio =3D gpiochip_get_data(chip); - - if (i8255_get_direction(gpiommgpio->ppi_state, offset)) - return GPIO_LINE_DIRECTION_IN; - - return GPIO_LINE_DIRECTION_OUT; -} - -static int gpiomm_gpio_direction_input(struct gpio_chip *chip, - unsigned int offset) -{ - struct gpiomm_gpio *const gpiommgpio =3D gpiochip_get_data(chip); - - i8255_direction_input(gpiommgpio->ppi, gpiommgpio->ppi_state, offset); - - return 0; -} - -static int gpiomm_gpio_direction_output(struct gpio_chip *chip, - unsigned int offset, int value) -{ - struct gpiomm_gpio *const gpiommgpio =3D gpiochip_get_data(chip); - - i8255_direction_output(gpiommgpio->ppi, gpiommgpio->ppi_state, offset, - value); - - return 0; -} - -static int gpiomm_gpio_get(struct gpio_chip *chip, unsigned int offset) -{ - struct gpiomm_gpio *const gpiommgpio =3D gpiochip_get_data(chip); - - return i8255_get(gpiommgpio->ppi, offset); -} - -static int gpiomm_gpio_get_multiple(struct gpio_chip *chip, unsigned long = *mask, - unsigned long *bits) -{ - struct gpiomm_gpio *const gpiommgpio =3D gpiochip_get_data(chip); - - i8255_get_multiple(gpiommgpio->ppi, mask, bits, chip->ngpio); - - return 0; -} - -static void gpiomm_gpio_set(struct gpio_chip *chip, unsigned int offset, - int value) -{ - struct gpiomm_gpio *const gpiommgpio =3D gpiochip_get_data(chip); - - i8255_set(gpiommgpio->ppi, gpiommgpio->ppi_state, offset, value); -} - -static void gpiomm_gpio_set_multiple(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) -{ - struct gpiomm_gpio *const gpiommgpio =3D gpiochip_get_data(chip); - - i8255_set_multiple(gpiommgpio->ppi, gpiommgpio->ppi_state, mask, bits, - chip->ngpio); -} =20 #define GPIOMM_NGPIO 48 static const char *gpiomm_names[GPIOMM_NGPIO] =3D { @@ -120,30 +59,11 @@ static const char *gpiomm_names[GPIOMM_NGPIO] =3D { "Port 2C2", "Port 2C3", "Port 2C4", "Port 2C5", "Port 2C6", "Port 2C7", }; =20 -static void gpiomm_init_dio(struct i8255 __iomem *const ppi, - struct i8255_state *const ppi_state) -{ - const unsigned long ngpio =3D 24; - const unsigned long mask =3D GENMASK(ngpio - 1, 0); - const unsigned long bits =3D 0; - unsigned long i; - - /* Initialize all GPIO to output 0 */ - for (i =3D 0; i < GPIOMM_NUM_PPI; i++) { - i8255_mode0_output(&ppi[i]); - i8255_set_multiple(&ppi[i], &ppi_state[i], &mask, &bits, ngpio); - } -} - static int gpiomm_probe(struct device *dev, unsigned int id) { - struct gpiomm_gpio *gpiommgpio; const char *const name =3D dev_name(dev); - int err; - - gpiommgpio =3D devm_kzalloc(dev, sizeof(*gpiommgpio), GFP_KERNEL); - if (!gpiommgpio) - return -ENOMEM; + struct i8255_regmap_config config =3D {}; + void __iomem *regs; =20 if (!devm_request_region(dev, base[id], GPIOMM_EXTENT, name)) { dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", @@ -151,34 +71,20 @@ static int gpiomm_probe(struct device *dev, unsigned i= nt id) return -EBUSY; } =20 - gpiommgpio->ppi =3D devm_ioport_map(dev, base[id], GPIOMM_EXTENT); - if (!gpiommgpio->ppi) + regs =3D devm_ioport_map(dev, base[id], GPIOMM_EXTENT); + if (!regs) return -ENOMEM; =20 - gpiommgpio->chip.label =3D name; - gpiommgpio->chip.parent =3D dev; - gpiommgpio->chip.owner =3D THIS_MODULE; - gpiommgpio->chip.base =3D -1; - gpiommgpio->chip.ngpio =3D GPIOMM_NGPIO; - gpiommgpio->chip.names =3D gpiomm_names; - gpiommgpio->chip.get_direction =3D gpiomm_gpio_get_direction; - gpiommgpio->chip.direction_input =3D gpiomm_gpio_direction_input; - gpiommgpio->chip.direction_output =3D gpiomm_gpio_direction_output; - gpiommgpio->chip.get =3D gpiomm_gpio_get; - gpiommgpio->chip.get_multiple =3D gpiomm_gpio_get_multiple; - gpiommgpio->chip.set =3D gpiomm_gpio_set; - gpiommgpio->chip.set_multiple =3D gpiomm_gpio_set_multiple; - - i8255_state_init(gpiommgpio->ppi_state, GPIOMM_NUM_PPI); - gpiomm_init_dio(gpiommgpio->ppi, gpiommgpio->ppi_state); - - err =3D devm_gpiochip_add_data(dev, &gpiommgpio->chip, gpiommgpio); - if (err) { - dev_err(dev, "GPIO registering failed (%d)\n", err); - return err; - } + config.map =3D devm_regmap_init_mmio(dev, regs, &gpiomm_regmap_config); + if (IS_ERR(config.map)) + return dev_err_probe(dev, PTR_ERR(config.map), + "Unable to initialize register map\n"); + + config.parent =3D dev; + config.num_ppi =3D GPIOMM_NUM_PPI; + config.names =3D gpiomm_names; =20 - return 0; + return devm_i8255_regmap_register(dev, &config); } =20 static struct isa_driver gpiomm_driver =3D { --=20 2.38.1 From nobody Sun Apr 28 04:44:26 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6FED4C4708E for ; Fri, 2 Dec 2022 16:28:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233798AbiLBQ2U (ORCPT ); Fri, 2 Dec 2022 11:28:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44018 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234129AbiLBQ1e (ORCPT ); Fri, 2 Dec 2022 11:27:34 -0500 Received: from mail-qv1-xf32.google.com (mail-qv1-xf32.google.com [IPv6:2607:f8b0:4864:20::f32]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B1FACEE00 for ; Fri, 2 Dec 2022 08:27:31 -0800 (PST) Received: by mail-qv1-xf32.google.com with SMTP id p12so3730935qvu.5 for ; Fri, 02 Dec 2022 08:27:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dIOIvFeXi/+DuXzCtwKMgaypAC1l5I+Malp46WLaEVA=; b=f7P+RRAIpgdnMYRSr6RJfXTc54UNimWbhbfZZp68jCV8Ub2eY8cxXFsCsYz2Vk8tlg 0VOD+TjWBUaKJD5GrbdmJ20dgpt6H8UkbbO6ivxvy0bxVzUa6vC0bu7E/lVvUG4jz7II 9XMdxqDOkth4n+Np6KuLXXNwKjIKY9UfqNJR8y1P20JBwEQRoGiLBaJDnlGH/GO5Ly5w wD2fdZ2/CQTnP/ZR0Dw5dvPiMDjVUShZNwRfdadJQzczAdX5W0OnIgzoDvs/FFTepW2Q +OrJSqk2Tj5nlweaRqXfTK9ccz7xwNf+SegVa3qY095JKA/mCL3mImy2j5BENCicGye5 dF8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dIOIvFeXi/+DuXzCtwKMgaypAC1l5I+Malp46WLaEVA=; b=MoVS+lokytieLACaA3DxV1StZSPTRaZQEbBQiKAfAp8pgl2vt+l7+mjDZXTSbkVsmE mSoQOJwgnQdpwSjb3XYQkqSOyDP5Jg2L1D/0Z4uZQfBYuY/hvZ4XOLYqyJqcthcZuDcK MG+f4iszFFmZMiBvIUTdOwpivFJ8E4Yvy7Y9n3pQYOgINofIB8JQHWgbRoBNLE1Iz3zu UfIPhrHd/geRKnrLWF41TgToDEyKotX8kg7KFz+Gb2QsdTmMVruOhw6Bt9r1Hq2Op7Dt XVxktVjMRlMHcwhuT/fGe2FlTn1AkDQWJ1RHY2oxgJfVvDgKe/FWWzoaXcq7VuVtSbcM Xkug== X-Gm-Message-State: ANoB5pmELNVt2P9BE8xJL3bEzRdclGjlpRN0BX+FqdGkhvtPKpjpLfXx jdtamHQlMwIA9jMpIEe0auXBcw== X-Google-Smtp-Source: AA0mqf6j7nkmY48uGhxKtNMIjHc56ZciJ6RbnPH4GaxjMbK2bnkp4Cmv3t5zmhKoWz2xyJ/OMa4hIA== X-Received: by 2002:ad4:43c5:0:b0:4c6:a5c3:3a7c with SMTP id o5-20020ad443c5000000b004c6a5c33a7cmr49163227qvs.63.1669998450685; Fri, 02 Dec 2022 08:27:30 -0800 (PST) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id fp38-20020a05622a50a600b00343057845f7sm4391887qtb.20.2022.12.02.08.27.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Dec 2022 08:27:30 -0800 (PST) From: William Breathitt Gray To: linus.walleij@linaro.org, brgl@bgdev.pl Cc: andriy.shevchenko@linux.intel.com, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, michael@walle.cc, broonie@kernel.org, William Breathitt Gray Subject: [PATCH v4 9/9] gpio: i8255: Remove unused legacy interface Date: Fri, 2 Dec 2022 11:27:15 -0500 Message-Id: <783e505384fe9953eda2dfe8f08544bc090ca284.1669996867.git.william.gray@linaro.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" All i8255 library consumers have migrated to the new interface leveraging the gpio-regmap API. Legacy interface functions and code are removed as no longer needed. Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Signed-off-by: William Breathitt Gray --- drivers/gpio/gpio-i8255.c | 243 +------------------------------------- drivers/gpio/gpio-i8255.h | 40 ------- 2 files changed, 1 insertion(+), 282 deletions(-) diff --git a/drivers/gpio/gpio-i8255.c b/drivers/gpio/gpio-i8255.c index 9ecb2e9b97f9..64ab80fc4a1e 100644 --- a/drivers/gpio/gpio-i8255.c +++ b/drivers/gpio/gpio-i8255.c @@ -3,16 +3,13 @@ * Intel 8255 Programmable Peripheral Interface * Copyright (C) 2022 William Breathitt Gray */ -#include +#include #include #include #include #include -#include #include #include -#include -#include =20 #include "gpio-i8255.h" =20 @@ -30,15 +27,6 @@ #define I8255_REG_DAT_BASE I8255_PORTA #define I8255_REG_DIR_IN_BASE I8255_CONTROL =20 -static int i8255_get_port(struct i8255 __iomem *const ppi, - const unsigned long io_port, const unsigned long mask) -{ - const unsigned long bank =3D io_port / 3; - const unsigned long ppi_port =3D io_port % 3; - - return ioread8(&ppi[bank].port[ppi_port]) & mask; -} - static int i8255_direction_mask(const unsigned int offset) { const unsigned int stride =3D offset / I8255_NGPIO_PER_REG; @@ -103,235 +91,6 @@ static int i8255_reg_mask_xlate(struct gpio_regmap *gp= io, unsigned int base, } } =20 -static void i8255_set_port(struct i8255 __iomem *const ppi, - struct i8255_state *const state, - const unsigned long io_port, - const unsigned long mask, const unsigned long bits) -{ - const unsigned long bank =3D io_port / 3; - const unsigned long ppi_port =3D io_port % 3; - unsigned long flags; - unsigned long out_state; - - spin_lock_irqsave(&state[bank].lock, flags); - - out_state =3D ioread8(&ppi[bank].port[ppi_port]); - out_state =3D (out_state & ~mask) | (bits & mask); - iowrite8(out_state, &ppi[bank].port[ppi_port]); - - spin_unlock_irqrestore(&state[bank].lock, flags); -} - -/** - * i8255_direction_input - configure signal offset as input - * @ppi: Intel 8255 Programmable Peripheral Interface banks - * @state: devices states of the respective PPI banks - * @offset: signal offset to configure as input - * - * Configures a signal @offset as input for the respective Intel 8255 - * Programmable Peripheral Interface (@ppi) banks. The @state control_state - * values are updated to reflect the new configuration. - */ -void i8255_direction_input(struct i8255 __iomem *const ppi, - struct i8255_state *const state, - const unsigned long offset) -{ - const unsigned long io_port =3D offset / 8; - const unsigned long bank =3D io_port / 3; - unsigned long flags; - - spin_lock_irqsave(&state[bank].lock, flags); - - state[bank].control_state |=3D I8255_CONTROL_MODE_SET; - state[bank].control_state |=3D i8255_direction_mask(offset % 24); - - iowrite8(state[bank].control_state, &ppi[bank].control); - - spin_unlock_irqrestore(&state[bank].lock, flags); -} -EXPORT_SYMBOL_NS_GPL(i8255_direction_input, I8255); - -/** - * i8255_direction_output - configure signal offset as output - * @ppi: Intel 8255 Programmable Peripheral Interface banks - * @state: devices states of the respective PPI banks - * @offset: signal offset to configure as output - * @value: signal value to output - * - * Configures a signal @offset as output for the respective Intel 8255 - * Programmable Peripheral Interface (@ppi) banks and sets the respective = signal - * output to the desired @value. The @state control_state values are updat= ed to - * reflect the new configuration. - */ -void i8255_direction_output(struct i8255 __iomem *const ppi, - struct i8255_state *const state, - const unsigned long offset, - const unsigned long value) -{ - const unsigned long io_port =3D offset / 8; - const unsigned long bank =3D io_port / 3; - unsigned long flags; - - spin_lock_irqsave(&state[bank].lock, flags); - - state[bank].control_state |=3D I8255_CONTROL_MODE_SET; - state[bank].control_state &=3D ~i8255_direction_mask(offset % 24); - - iowrite8(state[bank].control_state, &ppi[bank].control); - - spin_unlock_irqrestore(&state[bank].lock, flags); - - i8255_set(ppi, state, offset, value); -} -EXPORT_SYMBOL_NS_GPL(i8255_direction_output, I8255); - -/** - * i8255_get - get signal value at signal offset - * @ppi: Intel 8255 Programmable Peripheral Interface banks - * @offset: offset of signal to get - * - * Returns the signal value (0=3Dlow, 1=3Dhigh) for the signal at @offset = for the - * respective Intel 8255 Programmable Peripheral Interface (@ppi) banks. - */ -int i8255_get(struct i8255 __iomem *const ppi, const unsigned long offset) -{ - const unsigned long io_port =3D offset / 8; - const unsigned long offset_mask =3D BIT(offset % 8); - - return !!i8255_get_port(ppi, io_port, offset_mask); -} -EXPORT_SYMBOL_NS_GPL(i8255_get, I8255); - -/** - * i8255_get_direction - get the I/O direction for a signal offset - * @state: devices states of the respective PPI banks - * @offset: offset of signal to get direction - * - * Returns the signal direction (0=3Doutput, 1=3Dinput) for the signal at = @offset. - */ -int i8255_get_direction(const struct i8255_state *const state, - const unsigned long offset) -{ - const unsigned long io_port =3D offset / 8; - const unsigned long bank =3D io_port / 3; - - return !!(state[bank].control_state & i8255_direction_mask(offset % 24)); -} -EXPORT_SYMBOL_NS_GPL(i8255_get_direction, I8255); - -/** - * i8255_get_multiple - get multiple signal values at multiple signal offs= ets - * @ppi: Intel 8255 Programmable Peripheral Interface banks - * @mask: mask of signals to get - * @bits: bitmap to store signal values - * @ngpio: number of GPIO signals of the respective PPI banks - * - * Stores in @bits the values (0=3Dlow, 1=3Dhigh) for the signals defined = by @mask - * for the respective Intel 8255 Programmable Peripheral Interface (@ppi) = banks. - */ -void i8255_get_multiple(struct i8255 __iomem *const ppi, - const unsigned long *const mask, - unsigned long *const bits, const unsigned long ngpio) -{ - unsigned long offset; - unsigned long port_mask; - unsigned long io_port; - unsigned long port_state; - - bitmap_zero(bits, ngpio); - - for_each_set_clump8(offset, port_mask, mask, ngpio) { - io_port =3D offset / 8; - port_state =3D i8255_get_port(ppi, io_port, port_mask); - - bitmap_set_value8(bits, port_state, offset); - } -} -EXPORT_SYMBOL_NS_GPL(i8255_get_multiple, I8255); - -/** - * i8255_mode0_output - configure all PPI ports to MODE 0 output mode - * @ppi: Intel 8255 Programmable Peripheral Interface bank - * - * Configures all Intel 8255 Programmable Peripheral Interface (@ppi) port= s to - * MODE 0 (Basic Input/Output) output mode. - */ -void i8255_mode0_output(struct i8255 __iomem *const ppi) -{ - iowrite8(I8255_CONTROL_MODE_SET, &ppi->control); -} -EXPORT_SYMBOL_NS_GPL(i8255_mode0_output, I8255); - -/** - * i8255_set - set signal value at signal offset - * @ppi: Intel 8255 Programmable Peripheral Interface banks - * @state: devices states of the respective PPI banks - * @offset: offset of signal to set - * @value: value of signal to set - * - * Assigns output @value for the signal at @offset for the respective Inte= l 8255 - * Programmable Peripheral Interface (@ppi) banks. - */ -void i8255_set(struct i8255 __iomem *const ppi, struct i8255_state *const = state, - const unsigned long offset, const unsigned long value) -{ - const unsigned long io_port =3D offset / 8; - const unsigned long port_offset =3D offset % 8; - const unsigned long mask =3D BIT(port_offset); - const unsigned long bits =3D value << port_offset; - - i8255_set_port(ppi, state, io_port, mask, bits); -} -EXPORT_SYMBOL_NS_GPL(i8255_set, I8255); - -/** - * i8255_set_multiple - set signal values at multiple signal offsets - * @ppi: Intel 8255 Programmable Peripheral Interface banks - * @state: devices states of the respective PPI banks - * @mask: mask of signals to set - * @bits: bitmap of signal output values - * @ngpio: number of GPIO signals of the respective PPI banks - * - * Assigns output values defined by @bits for the signals defined by @mask= for - * the respective Intel 8255 Programmable Peripheral Interface (@ppi) bank= s. - */ -void i8255_set_multiple(struct i8255 __iomem *const ppi, - struct i8255_state *const state, - const unsigned long *const mask, - const unsigned long *const bits, - const unsigned long ngpio) -{ - unsigned long offset; - unsigned long port_mask; - unsigned long io_port; - unsigned long value; - - for_each_set_clump8(offset, port_mask, mask, ngpio) { - io_port =3D offset / 8; - value =3D bitmap_get_value8(bits, offset); - i8255_set_port(ppi, state, io_port, port_mask, value); - } -} -EXPORT_SYMBOL_NS_GPL(i8255_set_multiple, I8255); - -/** - * i8255_state_init - initialize i8255_state structure - * @state: devices states of the respective PPI banks - * @nbanks: number of Intel 8255 Programmable Peripheral Interface banks - * - * Initializes the @state of each Intel 8255 Programmable Peripheral Inter= face - * bank for use in i8255 library functions. - */ -void i8255_state_init(struct i8255_state *const state, - const unsigned long nbanks) -{ - unsigned long bank; - - for (bank =3D 0; bank < nbanks; bank++) - spin_lock_init(&state[bank].lock); -} -EXPORT_SYMBOL_NS_GPL(i8255_state_init, I8255); - /** * devm_i8255_regmap_register - Register an i8255 GPIO controller * @dev: device that is registering this i8255 GPIO device diff --git a/drivers/gpio/gpio-i8255.h b/drivers/gpio/gpio-i8255.h index 3daa0b145890..9dcf639b94df 100644 --- a/drivers/gpio/gpio-i8255.h +++ b/drivers/gpio/gpio-i8255.h @@ -3,29 +3,6 @@ #ifndef _I8255_H_ #define _I8255_H_ =20 -#include -#include - -/** - * struct i8255 - Intel 8255 register structure - * @port: Port A, B, and C - * @control: Control register - */ -struct i8255 { - u8 port[3]; - u8 control; -}; - -/** - * struct i8255_state - Intel 8255 state structure - * @lock: synchronization lock for accessing device state - * @control_state: Control register state - */ -struct i8255_state { - spinlock_t lock; - u8 control_state; -}; - struct device; struct irq_domain; struct regmap; @@ -54,21 +31,4 @@ struct i8255_regmap_config { int devm_i8255_regmap_register(struct device *dev, const struct i8255_regmap_config *config); =20 -void i8255_direction_input(struct i8255 __iomem *ppi, struct i8255_state *= state, - unsigned long offset); -void i8255_direction_output(struct i8255 __iomem *ppi, - struct i8255_state *state, unsigned long offset, - unsigned long value); -int i8255_get(struct i8255 __iomem *ppi, unsigned long offset); -int i8255_get_direction(const struct i8255_state *state, unsigned long off= set); -void i8255_get_multiple(struct i8255 __iomem *ppi, const unsigned long *ma= sk, - unsigned long *bits, unsigned long ngpio); -void i8255_mode0_output(struct i8255 __iomem *const ppi); -void i8255_set(struct i8255 __iomem *ppi, struct i8255_state *state, - unsigned long offset, unsigned long value); -void i8255_set_multiple(struct i8255 __iomem *ppi, struct i8255_state *sta= te, - const unsigned long *mask, const unsigned long *bits, - unsigned long ngpio); -void i8255_state_init(struct i8255_state *const state, unsigned long nbank= s); - #endif /* _I8255_H_ */ --=20 2.38.1