From nobody Sun May 5 08:49:09 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 84C72C6FD20 for ; Fri, 24 Mar 2023 21:46:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231979AbjCXVqB (ORCPT ); Fri, 24 Mar 2023 17:46:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51318 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231960AbjCXVp6 (ORCPT ); Fri, 24 Mar 2023 17:45:58 -0400 Received: from mail-yb1-xb32.google.com (mail-yb1-xb32.google.com [IPv6:2607:f8b0:4864:20::b32]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 274EA1C581 for ; Fri, 24 Mar 2023 14:45:57 -0700 (PDT) Received: by mail-yb1-xb32.google.com with SMTP id cf7so3956755ybb.5 for ; Fri, 24 Mar 2023 14:45:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1679694356; 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=LZdBhp0oeApEibQPfgEYkuiWL+IeMBDDZnt81gygm0g=; b=u907RkXp/9s1j9PAoSoguQiT28X3bvIBd7jdNtZUbIcuE7HfsSJkzd0pHQyylzh8Er 8KO10riFyiLLtfgwsCeGMeWufactT2nOjdEhleu3/PvuKjcU4g17k/zgGXXvLTgduexC JX9TEsXcq5AiDX4jUHc1q33UukblznBp6iRdQ7bO91+gBlS4GUYcDDwWP7pOWz3+nMdh 7cDm9MU7CseP4jev+X940nC8xSRZRm4AnOaPVoMhBFT8VJs8ERNMiDM3oxThcOlmLFjO v11ptv5/Q46/e97eIXaPY4PaobQyyp0q0wiXh9su94VWKxhx9CKIqvsqm7D8lImtDVKL JKXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679694356; 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=LZdBhp0oeApEibQPfgEYkuiWL+IeMBDDZnt81gygm0g=; b=vktIxhs4j5jBXdUlwGV2Zz+05yqvQcDNKV+1bUnxgl38fjaJPxnfCRjFgvpLP2LUIp hRJAjuIQMQkfjYryaZ7MGvqePH048jB6kgz+uZLaLVoMPCL7jRSw+kpMg2ZBQwhW7t3x CB23Gl6hrllPxfUNQGIlHaUgmAj7mZt5AFl1qHt/Ywo+Q/f47akBjcUwLEQj4rgcen2w e/9d4AHX1N3cLPFBkWhiGg3vooiKowFAWDrKrJaMesaOeVa27sd5WoFMZ5TlGFQ1z19r LSnsuKcmR4ZZZ3sJwzgMAknZ4cHTNlM2NjG8stAGGJRKisN6VBwTmfSO+nF8n2DjME9L WCHw== X-Gm-Message-State: AAQBX9fvF2wi3iP1zUuyIVzdJ/6fTC+v/qjg2KY7wLYyFAJaaSx2NOiL QksYRziJLsLFD0Uqk0rZmM8QyA== X-Google-Smtp-Source: AKy350aFyjKjeapV5BDDhhUfNT7yY6vHmjM4QMCa4+gGlGtxn0AuzHPmeA79MMROg/b7y+owjn0NqQ== X-Received: by 2002:a25:d8b:0:b0:b6c:423d:ab18 with SMTP id 133-20020a250d8b000000b00b6c423dab18mr3583099ybn.7.1679694356298; Fri, 24 Mar 2023 14:45:56 -0700 (PDT) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id p8-20020a254208000000b00b7767ca7476sm705313yba.19.2023.03.24.14.45.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Mar 2023 14:45:56 -0700 (PDT) From: William Breathitt Gray To: Linus Walleij , Bartosz Golaszewski Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Andy Shevchenko , William Breathitt Gray Subject: [PATCH v3 1/4] gpio: idio-16: Migrate to the regmap API Date: Fri, 24 Mar 2023 17:45:41 -0400 Message-Id: X-Mailer: git-send-email 2.39.2 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 regmap API, the idio-16 library is reduced to simply a devm_idio_16_regmap_register() function and a configuration structure struct idio_16_regmap_config. Legacy functions and code will be removed once all consumers have migrated to the new idio-16 library interface. For IDIO-16 devices we have the following IRQ registers: Base Address +1 (Write): Clear Interrupt Base Address +2 (Read): Enable Interrupt Base Address +2 (Write): Disable Interrupt An interrupt is asserted whenever a change-of-state is detected on any of the inputs. Any write to 0x2 will disable interrupts, while any read will enable interrupts. Interrupts are cleared by a write to 0x1. For 104-IDIO-16 devices, there is no IRQ status register, so software has to assume that if an interrupt is raised then it was for the 104-IDIO-16 device. For PCI-IDIO-16 devices, there is an additional IRQ register: Base Address +6 (Read): Interrupt Status Interrupt status can be read from 0x6 where bit 2 set indicates that an IRQ has been generated. Signed-off-by: William Breathitt Gray --- Changes in v3: - Refactor for map parameter removal from handle_mask_sync(); e.g. declare struct idio_16_data and utilize for irq_drv_data, inline data->map in idio_16_handle_mask_sync(), etc - Cleanups and line wrapping to 100 characters rather than 80 - Change dev_err_probe() to dev_err(); devm_idio_16_regmap_register() is technically not a probe() callback - Drop superfluous comment line in struct idio_16_state drivers/gpio/Kconfig | 3 + drivers/gpio/gpio-idio-16.c | 160 ++++++++++++++++++++++++++++++++++++ drivers/gpio/gpio-idio-16.h | 26 ++++++ 3 files changed, 189 insertions(+) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 68f58b0ba79f..415b86cfd1a9 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -111,6 +111,9 @@ config GPIO_MAX730X =20 config GPIO_IDIO_16 tristate + select REGMAP_IRQ + select GPIOLIB_IRQCHIP + select GPIO_REGMAP help Enables support for the idio-16 library functions. The idio-16 library provides functions to facilitate communication with devices within the diff --git a/drivers/gpio/gpio-idio-16.c b/drivers/gpio/gpio-idio-16.c index 13315242d220..e8507f16b1c2 100644 --- a/drivers/gpio/gpio-idio-16.c +++ b/drivers/gpio/gpio-idio-16.c @@ -4,9 +4,13 @@ * Copyright (C) 2022 William Breathitt Gray */ #include +#include +#include #include +#include #include #include +#include #include #include =20 @@ -14,6 +18,162 @@ =20 #define DEFAULT_SYMBOL_NAMESPACE GPIO_IDIO_16 =20 +#define IDIO_16_DAT_BASE 0x0 +#define IDIO_16_OUT_BASE IDIO_16_DAT_BASE +#define IDIO_16_IN_BASE (IDIO_16_DAT_BASE + 1) +#define IDIO_16_CLEAR_INTERRUPT 0x1 +#define IDIO_16_ENABLE_IRQ 0x2 +#define IDIO_16_DEACTIVATE_INPUT_FILTERS 0x3 +#define IDIO_16_DISABLE_IRQ IDIO_16_ENABLE_IRQ +#define IDIO_16_INTERRUPT_STATUS 0x6 + +#define IDIO_16_NGPIO 32 +#define IDIO_16_NGPIO_PER_REG 8 +#define IDIO_16_REG_STRIDE 4 + +struct idio_16_data { + struct regmap *map; + unsigned int irq_mask; +}; + +static int idio_16_handle_mask_sync(const int index, const unsigned int ma= sk_buf_def, + const unsigned int mask_buf, void *const irq_drv_data) +{ + struct idio_16_data *const data =3D irq_drv_data; + const unsigned int prev_mask =3D data->irq_mask; + int err; + unsigned int val; + + /* exit early if no change since the previous mask */ + if (mask_buf =3D=3D prev_mask) + return 0; + + /* remember the current mask for the next mask sync */ + data->irq_mask =3D mask_buf; + + /* if all previously masked, enable interrupts when unmasking */ + if (prev_mask =3D=3D mask_buf_def) { + err =3D regmap_write(data->map, IDIO_16_CLEAR_INTERRUPT, 0x00); + if (err) + return err; + return regmap_read(data->map, IDIO_16_ENABLE_IRQ, &val); + } + + /* if all are currently masked, disable interrupts */ + if (mask_buf =3D=3D mask_buf_def) + return regmap_write(data->map, IDIO_16_DISABLE_IRQ, 0x00); + + return 0; +} + +static int idio_16_reg_mask_xlate(struct gpio_regmap *const gpio, const un= signed int base, + const unsigned int offset, unsigned int *const reg, + unsigned int *const mask) +{ + unsigned int stride; + + if (base !=3D IDIO_16_DAT_BASE) + /* Should never reach this path */ + return -EINVAL; + + /* Input lines start at GPIO 16 */ + if (offset < 16) { + stride =3D offset / IDIO_16_NGPIO_PER_REG; + *reg =3D IDIO_16_OUT_BASE + stride * IDIO_16_REG_STRIDE; + } else { + stride =3D (offset - 16) / IDIO_16_NGPIO_PER_REG; + *reg =3D IDIO_16_IN_BASE + stride * IDIO_16_REG_STRIDE; + } + + *mask =3D BIT(offset % IDIO_16_NGPIO_PER_REG); + + return 0; +} + +static const char *idio_16_names[IDIO_16_NGPIO] =3D { + "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7", "OUT8", "= OUT9", "OUT10", + "OUT11", "OUT12", "OUT13", "OUT14", "OUT15", "IIN0", "IIN1", "IIN2", "IIN= 3", "IIN4", "IIN5", + "IIN6", "IIN7", "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN1= 4", "IIN15", +}; + +/** + * devm_idio_16_regmap_register - Register an IDIO-16 GPIO device + * @dev: device that is registering this IDIO-16 GPIO device + * @config: configuration for idio_16_regmap_config + * + * Registers an IDIO-16 GPIO device. Returns 0 on success and negative err= or number on failure. + */ +int devm_idio_16_regmap_register(struct device *const dev, + const struct idio_16_regmap_config *const config) +{ + struct gpio_regmap_config gpio_config =3D {}; + int err; + struct idio_16_data *data; + struct regmap_irq_chip *chip; + struct regmap_irq_chip_data *chip_data; + + if (!config->parent) + return -EINVAL; + + if (!config->map) + return -EINVAL; + + if (!config->regmap_irqs) + return -EINVAL; + + data =3D devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + data->map =3D config->map; + + chip =3D devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->name =3D dev_name(dev); + chip->status_base =3D IDIO_16_INTERRUPT_STATUS; + chip->mask_base =3D IDIO_16_ENABLE_IRQ; + chip->ack_base =3D IDIO_16_CLEAR_INTERRUPT; + chip->no_status =3D config->no_status; + chip->num_regs =3D 1; + chip->irqs =3D config->regmap_irqs; + chip->num_irqs =3D config->num_regmap_irqs; + chip->handle_mask_sync =3D idio_16_handle_mask_sync; + chip->irq_drv_data =3D data; + + /* Disable IRQ to prevent spurious interrupts before we're ready */ + err =3D regmap_write(data->map, IDIO_16_DISABLE_IRQ, 0x00); + if (err) + return err; + + err =3D devm_regmap_add_irq_chip(dev, data->map, config->irq, 0, 0, chip,= &chip_data); + if (err) { + dev_err(dev, "IRQ registration failed (%d)\n", err); + return err; + } + + if (config->filters) { + /* Deactivate input filters */ + err =3D regmap_write(data->map, IDIO_16_DEACTIVATE_INPUT_FILTERS, 0x00); + if (err) + return err; + } + + gpio_config.parent =3D config->parent; + gpio_config.regmap =3D data->map; + gpio_config.ngpio =3D IDIO_16_NGPIO; + gpio_config.names =3D idio_16_names; + gpio_config.reg_dat_base =3D GPIO_REGMAP_ADDR(IDIO_16_DAT_BASE); + gpio_config.reg_set_base =3D GPIO_REGMAP_ADDR(IDIO_16_DAT_BASE); + gpio_config.ngpio_per_reg =3D IDIO_16_NGPIO_PER_REG; + gpio_config.reg_stride =3D IDIO_16_REG_STRIDE; + gpio_config.irq_domain =3D regmap_irq_get_domain(chip_data); + gpio_config.reg_mask_xlate =3D idio_16_reg_mask_xlate; + + return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config)); +} +EXPORT_SYMBOL_GPL(devm_idio_16_regmap_register); + /** * idio_16_get - get signal value at signal offset * @reg: ACCES IDIO-16 device registers diff --git a/drivers/gpio/gpio-idio-16.h b/drivers/gpio/gpio-idio-16.h index 928f8251a2bd..255bd8504ed7 100644 --- a/drivers/gpio/gpio-idio-16.h +++ b/drivers/gpio/gpio-idio-16.h @@ -6,6 +6,30 @@ #include #include =20 +struct device; +struct regmap; +struct regmap_irq; + +/** + * struct idio_16_regmap_config - Configuration for the IDIO-16 register m= ap + * @parent: parent device + * @map: regmap for the IDIO-16 device + * @regmap_irqs: descriptors for individual IRQs + * @num_regmap_irqs: number of IRQ descriptors + * @irq: IRQ number for the IDIO-16 device + * @no_status: device has no status register + * @filters: device has input filters + */ +struct idio_16_regmap_config { + struct device *parent; + struct regmap *map; + const struct regmap_irq *regmap_irqs; + int num_regmap_irqs; + unsigned int irq; + bool no_status; + bool filters; +}; + /** * struct idio_16 - IDIO-16 registers structure * @out0_7: Read: FET Drive Outputs 0-7 @@ -68,4 +92,6 @@ void idio_16_set_multiple(struct idio_16 __iomem *reg, const unsigned long *mask, const unsigned long *bits); void idio_16_state_init(struct idio_16_state *state); =20 +int devm_idio_16_regmap_register(struct device *dev, const struct idio_16_= regmap_config *config); + #endif /* _IDIO_16_H_ */ --=20 2.39.2 From nobody Sun May 5 08:49:09 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 4F27CC6FD1C for ; Fri, 24 Mar 2023 21:46:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232080AbjCXVqE (ORCPT ); Fri, 24 Mar 2023 17:46:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51400 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232002AbjCXVqB (ORCPT ); Fri, 24 Mar 2023 17:46:01 -0400 Received: from mail-yb1-xb2e.google.com (mail-yb1-xb2e.google.com [IPv6:2607:f8b0:4864:20::b2e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 00EAA1C33A for ; Fri, 24 Mar 2023 14:45:57 -0700 (PDT) Received: by mail-yb1-xb2e.google.com with SMTP id p15so3921802ybl.9 for ; Fri, 24 Mar 2023 14:45:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1679694357; 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=NhmXNOq7XP7BPxMEhOWOTS1ygrMX6GQr7Mmi9Rfruhs=; b=R6bYFSPHOy4K0FW3Wz+4kFH51SnTkvcQzS8DyBJCbKi6lL1p+k78HyTLwtYO4NRWZX zD+2K74UPv/MDOQnyLof6m4npRVLgzZEcPZxkfvDfdNStzXeypFQBFzB5JwwNr+CLU/p VYu/yYYLrNfb4H0ipsmITsguc8kVnvhbqVyXFwDvR5AzJ3f4Ku/tmpm9ShGk6EMA0H6B kdnPwrvi0VNikutxhFEMzB3EgGeRumiA9V18SdK75X2wD1SsX5mDFQl0TjieKauHdnjt bE7wLf6idTRMfIjkGktj11XB/R/+JMzZNLxeCtpvp8KCaLWeUNtSUoPHP+0yZGQUut0V watQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679694357; 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=NhmXNOq7XP7BPxMEhOWOTS1ygrMX6GQr7Mmi9Rfruhs=; b=tD6IsKuoPKoVxoM6ob2o7o6Ai9/MNSepbnnjw+MMKh8VslaSZebcfytRXONeX2ieQz t/x6LNyDdJUWQEPOVTaZY9LTKxe8OVK7RF0wTSjubhy85pcMfxFk1srsK8kgSX/g16bm Qt+hSuZ6w20fqYHMyyR0185GX0ozzDr2xXQJPuq/PSh/FimJq+I7LOUd4ojuzOVCZgLT q11Mr6scUq8IVpYxU5yyJ1L192/yxmcgKtOjmkZ7LD6BbiRhSMqcI87RbKyoxSSLX9Qj tTDPqoLfZRGMSsEY/UFwDQJ3B4KIFUpRp+95LxqNIHHG+nOacb/Lki1wg91P6SGNKimI sUsQ== X-Gm-Message-State: AAQBX9fLu7yBf1YFDrkkfZ8q64Wy8gCH3d7EiaUV8aTGwHtDhR2ehywl sLp05+jSt5OMDKfK6t7oQHE4cw== X-Google-Smtp-Source: AKy350ZRlCEZ6ajtAdlPqufzSVBJd84gf+Rlh/BPcMrbmAC49bqBBnx7OYN8vGgZfZN4SyP5+dGoLw== X-Received: by 2002:a25:c0c7:0:b0:a30:38fb:a099 with SMTP id c190-20020a25c0c7000000b00a3038fba099mr3923551ybf.53.1679694357133; Fri, 24 Mar 2023 14:45:57 -0700 (PDT) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id p8-20020a254208000000b00b7767ca7476sm705313yba.19.2023.03.24.14.45.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Mar 2023 14:45:56 -0700 (PDT) From: William Breathitt Gray To: Linus Walleij , Bartosz Golaszewski Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Andy Shevchenko , William Breathitt Gray Subject: [PATCH v3 2/4] gpio: 104-idio-16: Migrate to the regmap API Date: Fri, 24 Mar 2023 17:45:42 -0400 Message-Id: <62a596b6e881497e15f7f38e18b6e970ccdc998e.1679693714.git.william.gray@linaro.org> X-Mailer: git-send-email 2.39.2 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. Migrate the 104-idio-16 module to the new idio-16 library interface leveraging the gpio-regmap API. Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Signed-off-by: William Breathitt Gray --- Changes in v3: - Remove volatile regmap configuration structures; the existing read regmap table can be used to configure the volatile regmap table - Line wrapping to 100 characters rather than 80 drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-104-idio-16.c | 286 +++++++------------------------- 2 files changed, 64 insertions(+), 224 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 415b86cfd1a9..9f7ec4f3fdbf 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -860,7 +860,7 @@ config GPIO_104_IDIO_16 tristate "ACCES 104-IDIO-16 GPIO support" depends on PC104 select ISA_BUS_API - select GPIOLIB_IRQCHIP + select REGMAP_MMIO select GPIO_IDIO_16 help Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16, diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-1= 6.c index 098fbefdbe22..21035dadee46 100644 --- a/drivers/gpio/gpio-104-idio-16.c +++ b/drivers/gpio/gpio-104-idio-16.c @@ -6,19 +6,16 @@ * This driver supports the following ACCES devices: 104-IDIO-16, * 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, and 104-IDO-8. */ -#include +#include #include -#include -#include -#include +#include #include -#include -#include +#include #include #include #include #include -#include +#include #include =20 #include "gpio-idio-16.h" @@ -36,187 +33,62 @@ static unsigned int num_irq; module_param_hw_array(irq, uint, irq, &num_irq, 0); MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers"); =20 -/** - * struct idio_16_gpio - GPIO device private data structure - * @chip: instance of the gpio_chip - * @lock: synchronization lock to prevent I/O race conditions - * @irq_mask: I/O bits affected by interrupts - * @reg: I/O address offset for the device registers - * @state: ACCES IDIO-16 device state - */ -struct idio_16_gpio { - struct gpio_chip chip; - raw_spinlock_t lock; - unsigned long irq_mask; - struct idio_16 __iomem *reg; - struct idio_16_state state; +static const struct regmap_range idio_16_wr_ranges[] =3D { + regmap_reg_range(0x0, 0x2), regmap_reg_range(0x4, 0x4), }; - -static int idio_16_gpio_get_direction(struct gpio_chip *chip, - unsigned int offset) -{ - if (idio_16_get_direction(offset)) - return GPIO_LINE_DIRECTION_IN; - - return GPIO_LINE_DIRECTION_OUT; -} - -static int idio_16_gpio_direction_input(struct gpio_chip *chip, - unsigned int offset) -{ - return 0; -} - -static int idio_16_gpio_direction_output(struct gpio_chip *chip, - unsigned int offset, int value) -{ - chip->set(chip, offset, value); - return 0; -} - -static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset) -{ - struct idio_16_gpio *const idio16gpio =3D gpiochip_get_data(chip); - - return idio_16_get(idio16gpio->reg, &idio16gpio->state, offset); -} - -static int idio_16_gpio_get_multiple(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) -{ - struct idio_16_gpio *const idio16gpio =3D gpiochip_get_data(chip); - - idio_16_get_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits); - - return 0; -} - -static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset, - int value) -{ - struct idio_16_gpio *const idio16gpio =3D gpiochip_get_data(chip); - - idio_16_set(idio16gpio->reg, &idio16gpio->state, offset, value); -} - -static void idio_16_gpio_set_multiple(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) -{ - struct idio_16_gpio *const idio16gpio =3D gpiochip_get_data(chip); - - idio_16_set_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits); -} - -static void idio_16_irq_ack(struct irq_data *data) -{ -} - -static void idio_16_irq_mask(struct irq_data *data) -{ - struct gpio_chip *chip =3D irq_data_get_irq_chip_data(data); - struct idio_16_gpio *const idio16gpio =3D gpiochip_get_data(chip); - const unsigned long offset =3D irqd_to_hwirq(data); - unsigned long flags; - - idio16gpio->irq_mask &=3D ~BIT(offset); - gpiochip_disable_irq(chip, offset); - - if (!idio16gpio->irq_mask) { - raw_spin_lock_irqsave(&idio16gpio->lock, flags); - - iowrite8(0, &idio16gpio->reg->irq_ctl); - - raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); - } -} - -static void idio_16_irq_unmask(struct irq_data *data) -{ - struct gpio_chip *chip =3D irq_data_get_irq_chip_data(data); - struct idio_16_gpio *const idio16gpio =3D gpiochip_get_data(chip); - const unsigned long offset =3D irqd_to_hwirq(data); - const unsigned long prev_irq_mask =3D idio16gpio->irq_mask; - unsigned long flags; - - gpiochip_enable_irq(chip, offset); - idio16gpio->irq_mask |=3D BIT(offset); - - if (!prev_irq_mask) { - raw_spin_lock_irqsave(&idio16gpio->lock, flags); - - ioread8(&idio16gpio->reg->irq_ctl); - - raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); - } -} - -static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_t= ype) -{ - /* 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 idio_16_irqchip =3D { - .name =3D "104-idio-16", - .irq_ack =3D idio_16_irq_ack, - .irq_mask =3D idio_16_irq_mask, - .irq_unmask =3D idio_16_irq_unmask, - .irq_set_type =3D idio_16_irq_set_type, - .flags =3D IRQCHIP_IMMUTABLE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, +static const struct regmap_range idio_16_rd_ranges[] =3D { + regmap_reg_range(0x1, 0x2), regmap_reg_range(0x5, 0x5), }; - -static irqreturn_t idio_16_irq_handler(int irq, void *dev_id) -{ - struct idio_16_gpio *const idio16gpio =3D dev_id; - struct gpio_chip *const chip =3D &idio16gpio->chip; - int gpio; - - for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio) - generic_handle_domain_irq(chip->irq.domain, gpio); - - raw_spin_lock(&idio16gpio->lock); - - iowrite8(0, &idio16gpio->reg->in0_7); - - raw_spin_unlock(&idio16gpio->lock); - - return IRQ_HANDLED; -} - -#define IDIO_16_NGPIO 32 -static const char *idio_16_names[IDIO_16_NGPIO] =3D { - "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7", - "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15", - "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7", - "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15" +static const struct regmap_range idio_16_precious_ranges[] =3D { + regmap_reg_range(0x2, 0x2), +}; +static const struct regmap_access_table idio_16_wr_table =3D { + .yes_ranges =3D idio_16_wr_ranges, + .n_yes_ranges =3D ARRAY_SIZE(idio_16_wr_ranges), +}; +static const struct regmap_access_table idio_16_rd_table =3D { + .yes_ranges =3D idio_16_rd_ranges, + .n_yes_ranges =3D ARRAY_SIZE(idio_16_rd_ranges), +}; +static const struct regmap_access_table idio_16_precious_table =3D { + .yes_ranges =3D idio_16_precious_ranges, + .n_yes_ranges =3D ARRAY_SIZE(idio_16_precious_ranges), +}; +static const struct regmap_config idio_16_regmap_config =3D { + .reg_bits =3D 8, + .reg_stride =3D 1, + .val_bits =3D 8, + .io_port =3D true, + .max_register =3D 0x5, + .wr_table =3D &idio_16_wr_table, + .rd_table =3D &idio_16_rd_table, + .volatile_table =3D &idio_16_rd_table, + .precious_table =3D &idio_16_precious_table, + .cache_type =3D REGCACHE_FLAT, }; =20 -static int idio_16_irq_init_hw(struct gpio_chip *gc) -{ - struct idio_16_gpio *const idio16gpio =3D gpiochip_get_data(gc); - - /* Disable IRQ by default */ - iowrite8(0, &idio16gpio->reg->irq_ctl); - iowrite8(0, &idio16gpio->reg->in0_7); +/* Only input lines (GPIO 16-31) support interrupts */ +#define IDIO_16_REGMAP_IRQ(_id) \ + [16 + _id] =3D { \ + .mask =3D BIT(_id), \ + .type =3D { .types_supported =3D IRQ_TYPE_EDGE_BOTH }, \ + } =20 - return 0; -} +static const struct regmap_irq idio_16_regmap_irqs[] =3D { + IDIO_16_REGMAP_IRQ(0), IDIO_16_REGMAP_IRQ(1), IDIO_16_REGMAP_IRQ(2), /* 0= -2 */ + IDIO_16_REGMAP_IRQ(3), IDIO_16_REGMAP_IRQ(4), IDIO_16_REGMAP_IRQ(5), /* 3= -5 */ + IDIO_16_REGMAP_IRQ(6), IDIO_16_REGMAP_IRQ(7), IDIO_16_REGMAP_IRQ(8), /* 6= -8 */ + IDIO_16_REGMAP_IRQ(9), IDIO_16_REGMAP_IRQ(10), IDIO_16_REGMAP_IRQ(11), /*= 9-11 */ + IDIO_16_REGMAP_IRQ(12), IDIO_16_REGMAP_IRQ(13), IDIO_16_REGMAP_IRQ(14), /= * 12-14 */ + IDIO_16_REGMAP_IRQ(15), /* 15 */ +}; =20 static int idio_16_probe(struct device *dev, unsigned int id) { - struct idio_16_gpio *idio16gpio; const char *const name =3D dev_name(dev); - struct gpio_irq_chip *girq; - int err; - - idio16gpio =3D devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL); - if (!idio16gpio) - return -ENOMEM; + struct idio_16_regmap_config config =3D {}; + void __iomem *regs; + struct regmap *map; =20 if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) { dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", @@ -224,54 +96,22 @@ static int idio_16_probe(struct device *dev, unsigned = int id) return -EBUSY; } =20 - idio16gpio->reg =3D devm_ioport_map(dev, base[id], IDIO_16_EXTENT); - if (!idio16gpio->reg) + regs =3D devm_ioport_map(dev, base[id], IDIO_16_EXTENT); + if (!regs) return -ENOMEM; =20 - idio16gpio->chip.label =3D name; - idio16gpio->chip.parent =3D dev; - idio16gpio->chip.owner =3D THIS_MODULE; - idio16gpio->chip.base =3D -1; - idio16gpio->chip.ngpio =3D IDIO_16_NGPIO; - idio16gpio->chip.names =3D idio_16_names; - idio16gpio->chip.get_direction =3D idio_16_gpio_get_direction; - idio16gpio->chip.direction_input =3D idio_16_gpio_direction_input; - idio16gpio->chip.direction_output =3D idio_16_gpio_direction_output; - idio16gpio->chip.get =3D idio_16_gpio_get; - idio16gpio->chip.get_multiple =3D idio_16_gpio_get_multiple; - idio16gpio->chip.set =3D idio_16_gpio_set; - idio16gpio->chip.set_multiple =3D idio_16_gpio_set_multiple; - - idio_16_state_init(&idio16gpio->state); - /* FET off states are represented by bit values of "1" */ - bitmap_fill(idio16gpio->state.out_state, IDIO_16_NOUT); - - girq =3D &idio16gpio->chip.irq; - gpio_irq_chip_set_chip(girq, &idio_16_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 idio_16_irq_init_hw; + map =3D devm_regmap_init_mmio(dev, regs, &idio_16_regmap_config); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), "Unable to initialize register m= ap\n"); =20 - raw_spin_lock_init(&idio16gpio->lock); - - err =3D devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio); - if (err) { - dev_err(dev, "GPIO registering failed (%d)\n", err); - return err; - } - - err =3D devm_request_irq(dev, irq[id], idio_16_irq_handler, 0, name, - idio16gpio); - if (err) { - dev_err(dev, "IRQ handler registering failed (%d)\n", err); - return err; - } + config.parent =3D dev; + config.map =3D map; + config.regmap_irqs =3D idio_16_regmap_irqs; + config.num_regmap_irqs =3D ARRAY_SIZE(idio_16_regmap_irqs); + config.irq =3D irq[id]; + config.no_status =3D true; =20 - return 0; + return devm_idio_16_regmap_register(dev, &config); } =20 static struct isa_driver idio_16_driver =3D { --=20 2.39.2 From nobody Sun May 5 08:49:09 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 43272C6FD1C for ; Fri, 24 Mar 2023 21:46:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232102AbjCXVqH (ORCPT ); Fri, 24 Mar 2023 17:46:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51404 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232011AbjCXVqB (ORCPT ); Fri, 24 Mar 2023 17:46:01 -0400 Received: from mail-yb1-xb33.google.com (mail-yb1-xb33.google.com [IPv6:2607:f8b0:4864:20::b33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C69361C5A9 for ; Fri, 24 Mar 2023 14:45:58 -0700 (PDT) Received: by mail-yb1-xb33.google.com with SMTP id j7so3958816ybg.4 for ; Fri, 24 Mar 2023 14:45:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1679694358; 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=sV0cpQvWQs1LXsDHQnT7/6ykDqLWUrb+f1a7KWv7G+8=; b=Ehkeedo91GjUQ9BG7y4IFpVvbBOTQ0V6Tk2bPGsZD/8WBtx9nkpVH7xF2e7I1fHdrt k+m+Puo3lsLOG160fBpr2/exKHBphonX3jWFEJ460N8BixH44sreiu1f/S5T8NFqVvoQ d2RGGGIVI7hMAr1DpzUtoZjc0xcQtukIRCXMgJd038KNj9fKcZSId0BdlGtDSQgSD8yI Ew9usMWNr5tzW+DmEz/coUkrZoOigEctBBut+b0AXF12tbGpVo+DJbiRWhdr0SvZK89E TIujdMGBkxR0+oO1kkvLJ1goGelUd++ar3bV2DsasNZU0J3GXEF5QBxyfmazbZpm4U4g RX3g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679694358; 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=sV0cpQvWQs1LXsDHQnT7/6ykDqLWUrb+f1a7KWv7G+8=; b=IlFCPQnyhoe0uDUsFTEdthTI9StcLGEnsYIjekDYfkFBKgK8uPjuUOcqU32IKcOmPD F/dz1/6tXeS/skQUkbvdx7BB3SOo+A+m96HHwQQymkan5+TCC2iFnDgs8kSDS7KwRlIw +8uBMRckyO512jL86KNNFZTl2z+ckV/h2LgT66NXKkPqMwmrzFJ9FARpCHus82noiU65 pK673YW89h2gjczw/YIalGtUPzCzpD7iQVlsu+495I1vmBR79qKK4foaC+x45UfkySWD JATcWkmWXmqOui34iGTFR2igwoGPDb9EK4ceVxTw56LZteDXdEy+PGeBZXu/fv9vpdkw HmTQ== X-Gm-Message-State: AAQBX9frek/VoiRE+dBNnYGBJ3VN/aq1vXV1T68/wJ73yS27uXN8gnQ8 caydv/0MOIFflwrOsSJXBn2oPg== X-Google-Smtp-Source: AKy350bxNkdm9rihoQUUW4hAHa21o1/fPTDOV968Yo/sbQ0KllYFDMbx73OaFYrGwulxQ6T2M2KfuA== X-Received: by 2002:a25:420c:0:b0:a8d:ab20:c456 with SMTP id p12-20020a25420c000000b00a8dab20c456mr3943865yba.4.1679694357945; Fri, 24 Mar 2023 14:45:57 -0700 (PDT) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id p8-20020a254208000000b00b7767ca7476sm705313yba.19.2023.03.24.14.45.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Mar 2023 14:45:57 -0700 (PDT) From: William Breathitt Gray To: Linus Walleij , Bartosz Golaszewski Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Andy Shevchenko , William Breathitt Gray Subject: [PATCH v3 3/4] gpio: pci-idio-16: Migrate to the regmap API Date: Fri, 24 Mar 2023 17:45:43 -0400 Message-Id: X-Mailer: git-send-email 2.39.2 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. Migrate the pci-idio-16 module to the new idio-16 library interface leveraging the gpio-regmap API. Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Signed-off-by: William Breathitt Gray --- Changes in v3: - Remove volatile regmap configuration structures; the existing read regmap table can be used to configure the volatile regmap table - Line wrapping to 100 characters rather than 80 drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-pci-idio-16.c | 294 +++++++------------------------- 2 files changed, 62 insertions(+), 234 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 9f7ec4f3fdbf..e19b2612e67c 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1580,7 +1580,7 @@ config GPIO_PCH =20 config GPIO_PCI_IDIO_16 tristate "ACCES PCI-IDIO-16 GPIO support" - select GPIOLIB_IRQCHIP + select REGMAP_MMIO select GPIO_IDIO_16 help Enables GPIO support for the ACCES PCI-IDIO-16. An interrupt is diff --git a/drivers/gpio/gpio-pci-idio-16.c b/drivers/gpio/gpio-pci-idio-1= 6.c index 6726c32e31e6..5da67e0c83ff 100644 --- a/drivers/gpio/gpio-pci-idio-16.c +++ b/drivers/gpio/gpio-pci-idio-16.c @@ -5,214 +5,75 @@ */ #include #include -#include -#include -#include -#include +#include +#include #include #include #include -#include +#include #include =20 #include "gpio-idio-16.h" =20 -/** - * struct idio_16_gpio - GPIO device private data structure - * @chip: instance of the gpio_chip - * @lock: synchronization lock to prevent I/O race conditions - * @reg: I/O address offset for the GPIO device registers - * @state: ACCES IDIO-16 device state - * @irq_mask: I/O bits affected by interrupts - */ -struct idio_16_gpio { - struct gpio_chip chip; - raw_spinlock_t lock; - struct idio_16 __iomem *reg; - struct idio_16_state state; - unsigned long irq_mask; +static const struct regmap_range idio_16_wr_ranges[] =3D { + regmap_reg_range(0x0, 0x2), regmap_reg_range(0x3, 0x4), }; - -static int idio_16_gpio_get_direction(struct gpio_chip *chip, - unsigned int offset) -{ - if (idio_16_get_direction(offset)) - return GPIO_LINE_DIRECTION_IN; - - return GPIO_LINE_DIRECTION_OUT; -} - -static int idio_16_gpio_direction_input(struct gpio_chip *chip, - unsigned int offset) -{ - return 0; -} - -static int idio_16_gpio_direction_output(struct gpio_chip *chip, - unsigned int offset, int value) -{ - chip->set(chip, offset, value); - return 0; -} - -static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset) -{ - struct idio_16_gpio *const idio16gpio =3D gpiochip_get_data(chip); - - return idio_16_get(idio16gpio->reg, &idio16gpio->state, offset); -} - -static int idio_16_gpio_get_multiple(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) -{ - struct idio_16_gpio *const idio16gpio =3D gpiochip_get_data(chip); - - idio_16_get_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits); - return 0; -} - -static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset, - int value) -{ - struct idio_16_gpio *const idio16gpio =3D gpiochip_get_data(chip); - - idio_16_set(idio16gpio->reg, &idio16gpio->state, offset, value); -} - -static void idio_16_gpio_set_multiple(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) -{ - struct idio_16_gpio *const idio16gpio =3D gpiochip_get_data(chip); - - idio_16_set_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits); -} - -static void idio_16_irq_ack(struct irq_data *data) -{ -} - -static void idio_16_irq_mask(struct irq_data *data) -{ - struct gpio_chip *chip =3D irq_data_get_irq_chip_data(data); - struct idio_16_gpio *const idio16gpio =3D gpiochip_get_data(chip); - const unsigned long mask =3D BIT(irqd_to_hwirq(data)); - unsigned long flags; - - idio16gpio->irq_mask &=3D ~mask; - - if (!idio16gpio->irq_mask) { - raw_spin_lock_irqsave(&idio16gpio->lock, flags); - - iowrite8(0, &idio16gpio->reg->irq_ctl); - - raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); - } - - gpiochip_disable_irq(chip, irqd_to_hwirq(data)); -} - -static void idio_16_irq_unmask(struct irq_data *data) -{ - struct gpio_chip *chip =3D irq_data_get_irq_chip_data(data); - struct idio_16_gpio *const idio16gpio =3D gpiochip_get_data(chip); - const unsigned long mask =3D BIT(irqd_to_hwirq(data)); - const unsigned long prev_irq_mask =3D idio16gpio->irq_mask; - unsigned long flags; - - gpiochip_enable_irq(chip, irqd_to_hwirq(data)); - - idio16gpio->irq_mask |=3D mask; - - if (!prev_irq_mask) { - raw_spin_lock_irqsave(&idio16gpio->lock, flags); - - ioread8(&idio16gpio->reg->irq_ctl); - - raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); - } -} - -static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_t= ype) -{ - /* 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 idio_16_irqchip =3D { - .name =3D "pci-idio-16", - .irq_ack =3D idio_16_irq_ack, - .irq_mask =3D idio_16_irq_mask, - .irq_unmask =3D idio_16_irq_unmask, - .irq_set_type =3D idio_16_irq_set_type, - .flags =3D IRQCHIP_IMMUTABLE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, +static const struct regmap_range idio_16_rd_ranges[] =3D { + regmap_reg_range(0x1, 0x2), regmap_reg_range(0x5, 0x6), }; - -static irqreturn_t idio_16_irq_handler(int irq, void *dev_id) -{ - struct idio_16_gpio *const idio16gpio =3D dev_id; - unsigned int irq_status; - struct gpio_chip *const chip =3D &idio16gpio->chip; - int gpio; - - raw_spin_lock(&idio16gpio->lock); - - irq_status =3D ioread8(&idio16gpio->reg->irq_status); - - raw_spin_unlock(&idio16gpio->lock); - - /* Make sure our device generated IRQ */ - if (!(irq_status & 0x3) || !(irq_status & 0x4)) - return IRQ_NONE; - - for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio) - generic_handle_domain_irq(chip->irq.domain, gpio); - - raw_spin_lock(&idio16gpio->lock); - - /* Clear interrupt */ - iowrite8(0, &idio16gpio->reg->in0_7); - - raw_spin_unlock(&idio16gpio->lock); - - return IRQ_HANDLED; -} - -#define IDIO_16_NGPIO 32 -static const char *idio_16_names[IDIO_16_NGPIO] =3D { - "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7", - "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15", - "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7", - "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15" +static const struct regmap_range idio_16_precious_ranges[] =3D { + regmap_reg_range(0x2, 0x2), +}; +static const struct regmap_access_table idio_16_wr_table =3D { + .yes_ranges =3D idio_16_wr_ranges, + .n_yes_ranges =3D ARRAY_SIZE(idio_16_wr_ranges), +}; +static const struct regmap_access_table idio_16_rd_table =3D { + .yes_ranges =3D idio_16_rd_ranges, + .n_yes_ranges =3D ARRAY_SIZE(idio_16_rd_ranges), +}; +static const struct regmap_access_table idio_16_precious_table =3D { + .yes_ranges =3D idio_16_precious_ranges, + .n_yes_ranges =3D ARRAY_SIZE(idio_16_precious_ranges), +}; +static const struct regmap_config idio_16_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 &idio_16_wr_table, + .rd_table =3D &idio_16_rd_table, + .volatile_table =3D &idio_16_rd_table, + .precious_table =3D &idio_16_precious_table, + .cache_type =3D REGCACHE_FLAT, }; =20 -static int idio_16_irq_init_hw(struct gpio_chip *gc) -{ - struct idio_16_gpio *const idio16gpio =3D gpiochip_get_data(gc); - - /* Disable IRQ by default and clear any pending interrupt */ - iowrite8(0, &idio16gpio->reg->irq_ctl); - iowrite8(0, &idio16gpio->reg->in0_7); +/* Only input lines (GPIO 16-31) support interrupts */ +#define IDIO_16_REGMAP_IRQ(_id) \ + [16 + _id] =3D { \ + .mask =3D BIT(2), \ + .type =3D { .types_supported =3D IRQ_TYPE_EDGE_BOTH }, \ + } =20 - return 0; -} +static const struct regmap_irq idio_16_regmap_irqs[] =3D { + IDIO_16_REGMAP_IRQ(0), IDIO_16_REGMAP_IRQ(1), IDIO_16_REGMAP_IRQ(2), /* 0= -2 */ + IDIO_16_REGMAP_IRQ(3), IDIO_16_REGMAP_IRQ(4), IDIO_16_REGMAP_IRQ(5), /* 3= -5 */ + IDIO_16_REGMAP_IRQ(6), IDIO_16_REGMAP_IRQ(7), IDIO_16_REGMAP_IRQ(8), /* 6= -8 */ + IDIO_16_REGMAP_IRQ(9), IDIO_16_REGMAP_IRQ(10), IDIO_16_REGMAP_IRQ(11), /*= 9-11 */ + IDIO_16_REGMAP_IRQ(12), IDIO_16_REGMAP_IRQ(13), IDIO_16_REGMAP_IRQ(14), /= * 12-14 */ + IDIO_16_REGMAP_IRQ(15), /* 15 */ +}; =20 static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id = *id) { struct device *const dev =3D &pdev->dev; - struct idio_16_gpio *idio16gpio; int err; const size_t pci_bar_index =3D 2; const char *const name =3D pci_name(pdev); - struct gpio_irq_chip *girq; - - idio16gpio =3D devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL); - if (!idio16gpio) - return -ENOMEM; + struct idio_16_regmap_config config =3D {}; + void __iomem *regs; + struct regmap *map; =20 err =3D pcim_enable_device(pdev); if (err) { @@ -226,53 +87,20 @@ static int idio_16_probe(struct pci_dev *pdev, const s= truct pci_device_id *id) return err; } =20 - idio16gpio->reg =3D pcim_iomap_table(pdev)[pci_bar_index]; + regs =3D pcim_iomap_table(pdev)[pci_bar_index]; =20 - /* Deactivate input filters */ - iowrite8(0, &idio16gpio->reg->filter_ctl); + map =3D devm_regmap_init_mmio(dev, regs, &idio_16_regmap_config); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), "Unable to initialize register m= ap\n"); =20 - idio16gpio->chip.label =3D name; - idio16gpio->chip.parent =3D dev; - idio16gpio->chip.owner =3D THIS_MODULE; - idio16gpio->chip.base =3D -1; - idio16gpio->chip.ngpio =3D IDIO_16_NGPIO; - idio16gpio->chip.names =3D idio_16_names; - idio16gpio->chip.get_direction =3D idio_16_gpio_get_direction; - idio16gpio->chip.direction_input =3D idio_16_gpio_direction_input; - idio16gpio->chip.direction_output =3D idio_16_gpio_direction_output; - idio16gpio->chip.get =3D idio_16_gpio_get; - idio16gpio->chip.get_multiple =3D idio_16_gpio_get_multiple; - idio16gpio->chip.set =3D idio_16_gpio_set; - idio16gpio->chip.set_multiple =3D idio_16_gpio_set_multiple; - - idio_16_state_init(&idio16gpio->state); - - girq =3D &idio16gpio->chip.irq; - gpio_irq_chip_set_chip(girq, &idio_16_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 idio_16_irq_init_hw; - - raw_spin_lock_init(&idio16gpio->lock); - - err =3D devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio); - if (err) { - dev_err(dev, "GPIO registering failed (%d)\n", err); - return err; - } - - err =3D devm_request_irq(dev, pdev->irq, idio_16_irq_handler, IRQF_SHARED, - name, idio16gpio); - if (err) { - dev_err(dev, "IRQ handler registering failed (%d)\n", err); - return err; - } + config.parent =3D dev; + config.map =3D map; + config.regmap_irqs =3D idio_16_regmap_irqs; + config.num_regmap_irqs =3D ARRAY_SIZE(idio_16_regmap_irqs); + config.irq =3D pdev->irq; + config.filters =3D true; =20 - return 0; + return devm_idio_16_regmap_register(dev, &config); } =20 static const struct pci_device_id idio_16_pci_dev_id[] =3D { --=20 2.39.2 From nobody Sun May 5 08:49:09 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 1A71AC6FD20 for ; Fri, 24 Mar 2023 21:46:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232127AbjCXVqK (ORCPT ); Fri, 24 Mar 2023 17:46:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51488 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232021AbjCXVqB (ORCPT ); Fri, 24 Mar 2023 17:46:01 -0400 Received: from mail-yb1-xb29.google.com (mail-yb1-xb29.google.com [IPv6:2607:f8b0:4864:20::b29]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 974771CACA for ; Fri, 24 Mar 2023 14:45:59 -0700 (PDT) Received: by mail-yb1-xb29.google.com with SMTP id i6so3946479ybu.8 for ; Fri, 24 Mar 2023 14:45:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1679694359; 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=L1JSEFgA+jCl54x/kaa281Ch3B6k7vOXPPiIYy1PFjs=; b=C3ELzIpXTfrvxbNed7YSYswVDlbVVk1nQEBJQTPMYNiOb/8KvOE8HPkUIdyBvRoqHC r8uM49o7rlyaWKCWfAGCEJ6nNBSNlT6uZnqddMAhvfTOIeccty2WTp42dsbO3TZ7E7xZ gBMEJQ3zgOvpbxuiVcwYDey9fVkXOq+g7WPX4yxcQ0mJRcmTN0cMLJiUQRIT79e6+zov 38p+4NWBxX/DzxTHS26jRzRdDiggQdCyMTi9kuOLTsJ524DwO1oo6+ZhfAGK2xPB1HDn ZO81inwBiN/wpqHjf2yIHBrwo+pAFP7EqhYwvryix9mSbX61XqYKMwdd6wgWGHjw+dBx dCMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679694359; 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=L1JSEFgA+jCl54x/kaa281Ch3B6k7vOXPPiIYy1PFjs=; b=CQYsHLGSA5deB3DGhiV49ON88hvLCmWlaP9ca5XDfuyBuycWOpk23mqc54OvTsqXel M4oy2I5NoLefvD+md/aWJhOCxGkTwQDMHWUUgeNMJPYTzhJ8AF/2Gh7rCeTTikmg8eIL 3wDVOvMkBPn3+SWlRx11Ajww49BlWVOH/sWv2HxCDVhouXNZ9gwzCPhEahr7SSE7WoHw K74ywWTxDbGq2YWT/LC4s2FWrNRTGStviirxZmPedKTX9PYtcc8vm8F14gAGP+2iwNcn L014HO7Bl5DLXL10ykbKsAVrWUBtQN3gTAhdrS7DEpHm0h32pCruqYeDlGD/3elW+er7 W+Kg== X-Gm-Message-State: AAQBX9e09yhZWhHfZjEblfJjyYPdCWY64OcY1lzb+D4z4pI7OsRpip/J j8xIOSNYjiiMQxJHUSoCQ/ykrQ== X-Google-Smtp-Source: AKy350Y4jIptvjBHioNjRvLktl7NOYtMyyYpFdkjOTL6GeS2g43tzS18F0Cu2acx4E65qy5BldnxDQ== X-Received: by 2002:a25:ac8e:0:b0:b25:594d:eaff with SMTP id x14-20020a25ac8e000000b00b25594deaffmr3966241ybi.57.1679694358765; Fri, 24 Mar 2023 14:45:58 -0700 (PDT) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id p8-20020a254208000000b00b7767ca7476sm705313yba.19.2023.03.24.14.45.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Mar 2023 14:45:58 -0700 (PDT) From: William Breathitt Gray To: Linus Walleij , Bartosz Golaszewski Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Andy Shevchenko , William Breathitt Gray Subject: [PATCH v3 4/4] gpio: idio-16: Remove unused legacy interface Date: Fri, 24 Mar 2023 17:45:44 -0400 Message-Id: <016729e69fcfe6c12fbb645aaa12ec1900f7810a.1679693714.git.william.gray@linaro.org> X-Mailer: git-send-email 2.39.2 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 idio-16 library consumers have migrated to the new interface leveraging the gpio-regmap API. Legacy interface functions and code are removed as no longer needed. Reviewed-by: Andy Shevchenko Signed-off-by: William Breathitt Gray --- Changes in v3: none drivers/gpio/gpio-idio-16.c | 131 +----------------------------------- drivers/gpio/gpio-idio-16.h | 65 ------------------ 2 files changed, 1 insertion(+), 195 deletions(-) diff --git a/drivers/gpio/gpio-idio-16.c b/drivers/gpio/gpio-idio-16.c index e8507f16b1c2..f9a8bdf5b2d4 100644 --- a/drivers/gpio/gpio-idio-16.c +++ b/drivers/gpio/gpio-idio-16.c @@ -3,15 +3,13 @@ * GPIO library for the ACCES IDIO-16 family * Copyright (C) 2022 William Breathitt Gray */ -#include +#include #include #include #include #include -#include #include #include -#include #include =20 #include "gpio-idio-16.h" @@ -174,133 +172,6 @@ int devm_idio_16_regmap_register(struct device *const= dev, } EXPORT_SYMBOL_GPL(devm_idio_16_regmap_register); =20 -/** - * idio_16_get - get signal value at signal offset - * @reg: ACCES IDIO-16 device registers - * @state: ACCES IDIO-16 device state - * @offset: offset of signal to get - * - * Returns the signal value (0=3Dlow, 1=3Dhigh) for the signal at @offset. - */ -int idio_16_get(struct idio_16 __iomem *const reg, - struct idio_16_state *const state, const unsigned long offset) -{ - const unsigned long mask =3D BIT(offset); - - if (offset < IDIO_16_NOUT) - return test_bit(offset, state->out_state); - - if (offset < 24) - return !!(ioread8(®->in0_7) & (mask >> IDIO_16_NOUT)); - - if (offset < 32) - return !!(ioread8(®->in8_15) & (mask >> 24)); - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(idio_16_get); - -/** - * idio_16_get_multiple - get multiple signal values at multiple signal of= fsets - * @reg: ACCES IDIO-16 device registers - * @state: ACCES IDIO-16 device state - * @mask: mask of signals to get - * @bits: bitmap to store signal values - * - * Stores in @bits the values (0=3Dlow, 1=3Dhigh) for the signals defined = by @mask. - */ -void idio_16_get_multiple(struct idio_16 __iomem *const reg, - struct idio_16_state *const state, - const unsigned long *const mask, - unsigned long *const bits) -{ - unsigned long flags; - const unsigned long out_mask =3D GENMASK(IDIO_16_NOUT - 1, 0); - - spin_lock_irqsave(&state->lock, flags); - - bitmap_replace(bits, bits, state->out_state, &out_mask, IDIO_16_NOUT); - if (*mask & GENMASK(23, 16)) - bitmap_set_value8(bits, ioread8(®->in0_7), 16); - if (*mask & GENMASK(31, 24)) - bitmap_set_value8(bits, ioread8(®->in8_15), 24); - - spin_unlock_irqrestore(&state->lock, flags); -} -EXPORT_SYMBOL_GPL(idio_16_get_multiple); - -/** - * idio_16_set - set signal value at signal offset - * @reg: ACCES IDIO-16 device registers - * @state: ACCES IDIO-16 device state - * @offset: offset of signal to set - * @value: value of signal to set - * - * Assigns output @value for the signal at @offset. - */ -void idio_16_set(struct idio_16 __iomem *const reg, - struct idio_16_state *const state, const unsigned long offset, - const unsigned long value) -{ - unsigned long flags; - - if (offset >=3D IDIO_16_NOUT) - return; - - spin_lock_irqsave(&state->lock, flags); - - __assign_bit(offset, state->out_state, value); - if (offset < 8) - iowrite8(bitmap_get_value8(state->out_state, 0), ®->out0_7); - else - iowrite8(bitmap_get_value8(state->out_state, 8), ®->out8_15); - - spin_unlock_irqrestore(&state->lock, flags); -} -EXPORT_SYMBOL_GPL(idio_16_set); - -/** - * idio_16_set_multiple - set signal values at multiple signal offsets - * @reg: ACCES IDIO-16 device registers - * @state: ACCES IDIO-16 device state - * @mask: mask of signals to set - * @bits: bitmap of signal output values - * - * Assigns output values defined by @bits for the signals defined by @mask. - */ -void idio_16_set_multiple(struct idio_16 __iomem *const reg, - struct idio_16_state *const state, - const unsigned long *const mask, - const unsigned long *const bits) -{ - unsigned long flags; - - spin_lock_irqsave(&state->lock, flags); - - bitmap_replace(state->out_state, state->out_state, bits, mask, - IDIO_16_NOUT); - if (*mask & GENMASK(7, 0)) - iowrite8(bitmap_get_value8(state->out_state, 0), ®->out0_7); - if (*mask & GENMASK(15, 8)) - iowrite8(bitmap_get_value8(state->out_state, 8), ®->out8_15); - - spin_unlock_irqrestore(&state->lock, flags); -} -EXPORT_SYMBOL_GPL(idio_16_set_multiple); - -/** - * idio_16_state_init - initialize idio_16_state structure - * @state: ACCES IDIO-16 device state - * - * Initializes the ACCES IDIO-16 device @state for use in idio-16 library - * functions. - */ -void idio_16_state_init(struct idio_16_state *const state) -{ - spin_lock_init(&state->lock); -} -EXPORT_SYMBOL_GPL(idio_16_state_init); - MODULE_AUTHOR("William Breathitt Gray"); MODULE_DESCRIPTION("ACCES IDIO-16 GPIO Library"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-idio-16.h b/drivers/gpio/gpio-idio-16.h index 255bd8504ed7..93b08ad73065 100644 --- a/drivers/gpio/gpio-idio-16.h +++ b/drivers/gpio/gpio-idio-16.h @@ -3,9 +3,6 @@ #ifndef _IDIO_16_H_ #define _IDIO_16_H_ =20 -#include -#include - struct device; struct regmap; struct regmap_irq; @@ -30,68 +27,6 @@ struct idio_16_regmap_config { bool filters; }; =20 -/** - * struct idio_16 - IDIO-16 registers structure - * @out0_7: Read: FET Drive Outputs 0-7 - * Write: FET Drive Outputs 0-7 - * @in0_7: Read: Isolated Inputs 0-7 - * Write: Clear Interrupt - * @irq_ctl: Read: Enable IRQ - * Write: Disable IRQ - * @filter_ctl: Read: Activate Input Filters 0-15 - * Write: Deactivate Input Filters 0-15 - * @out8_15: Read: FET Drive Outputs 8-15 - * Write: FET Drive Outputs 8-15 - * @in8_15: Read: Isolated Inputs 8-15 - * Write: Unused - * @irq_status: Read: Interrupt status - * Write: Unused - */ -struct idio_16 { - u8 out0_7; - u8 in0_7; - u8 irq_ctl; - u8 filter_ctl; - u8 out8_15; - u8 in8_15; - u8 irq_status; -}; - -#define IDIO_16_NOUT 16 - -/** - * struct idio_16_state - IDIO-16 state structure - * @lock: synchronization lock for accessing device state - * @out_state: output signals state - */ -struct idio_16_state { - spinlock_t lock; - DECLARE_BITMAP(out_state, IDIO_16_NOUT); -}; - -/** - * idio_16_get_direction - get the I/O direction for a signal offset - * @offset: offset of signal to get direction - * - * Returns the signal direction (0=3Doutput, 1=3Dinput) for the signal at = @offset. - */ -static inline int idio_16_get_direction(const unsigned long offset) -{ - return (offset >=3D IDIO_16_NOUT) ? 1 : 0; -} - -int idio_16_get(struct idio_16 __iomem *reg, struct idio_16_state *state, - unsigned long offset); -void idio_16_get_multiple(struct idio_16 __iomem *reg, - struct idio_16_state *state, - const unsigned long *mask, unsigned long *bits); -void idio_16_set(struct idio_16 __iomem *reg, struct idio_16_state *state, - unsigned long offset, unsigned long value); -void idio_16_set_multiple(struct idio_16 __iomem *reg, - struct idio_16_state *state, - const unsigned long *mask, const unsigned long *bits); -void idio_16_state_init(struct idio_16_state *state); - int devm_idio_16_regmap_register(struct device *dev, const struct idio_16_= regmap_config *config); =20 #endif /* _IDIO_16_H_ */ --=20 2.39.2