From patchwork Fri Mar 31 21:05:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Breathitt Gray X-Patchwork-Id: 669895 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 6A4DDC77B60 for ; Fri, 31 Mar 2023 21:05:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231770AbjCaVFu (ORCPT ); Fri, 31 Mar 2023 17:05:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37732 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232508AbjCaVFt (ORCPT ); Fri, 31 Mar 2023 17:05:49 -0400 Received: from mail-yw1-x1135.google.com (mail-yw1-x1135.google.com [IPv6:2607:f8b0:4864:20::1135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3452E1D847 for ; Fri, 31 Mar 2023 14:05:48 -0700 (PDT) Received: by mail-yw1-x1135.google.com with SMTP id 00721157ae682-54606036bb3so272818737b3.6 for ; Fri, 31 Mar 2023 14:05:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1680296747; 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=iW1s1+Gu9N67RQRLodX4e69YS2yEkIKFeu2veFvolAY=; b=FqHGbsSKX5sGUwzQY5HxvkUfXAxXuLY/nefqRa+MPxMyped11D/dbhy6BE3o9YupAn PIdJpCwzPkBSmyWzAy4fI0yhS394sJyI1IbDae+ypddTCiOsseW/ZrZiuOznBN5UgK7n 726GqSSii9pMkRs8HbA64baQbpiwfMbRjlwCVW9rW+B4iVYyjFiQy4v5KAjDpTN+Vhwc IfgSD4rBJTikwwiEa0eXEeGosWI2j5XTgefnSGJO5FRKwFHauOp3n/OD4h3ntclFfv0e S+FJbASPjnAMmJakwld5Pl1NfI8DREnLs8QdFbdXMCxuOup35POefXvRCeLln/ITVkJQ 0mbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680296747; 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=iW1s1+Gu9N67RQRLodX4e69YS2yEkIKFeu2veFvolAY=; b=qTNTOl53vnLHJgsxe9rcFzWvzubjQdhNAaOxoJegEHPKjYUmuNCRbLGW62ZqnezN7q WD3lDNZK0iIoxxk2zKYilHkAnHDDAcFv6e7TSx/fFJpNAB57Ss5ir7uuwVGb2wrRQ8ml uXoFYiqjUxQynDLk1KbPo6kp65seyrIJgNq5d2HD4GUemaWsd3hPEr0oRRarl2SSLVWu QDPuAk05+F8pdBfXzPq2NV/ZVPJMnb2BgslmpXqr3arXxqc85aKMblazPJJqbO/9OHrH Fp1/6cnOEItCXJ3g6Z21QpHMxT3Byrd1hnR0itDnvXJ+gEU1yphNJJWo4p67RxfyDrbX AhKg== X-Gm-Message-State: AAQBX9dNrdlSu0nQFEih+c0BvVvekfEolcOpezRAW2egd1ZzAV2jlH7M A2s7mcsC80Um7Lf7bpjQWJQoNw== X-Google-Smtp-Source: AKy350YSx8syFV4NQsQQ+Zjw0jVUbNDc+6UCbJp4LSfepx5rYJHMOPcuxW7mHe6J7yeu2IcyfytauA== X-Received: by 2002:a81:a505:0:b0:541:4561:544d with SMTP id u5-20020a81a505000000b005414561544dmr24906326ywg.43.1680296747311; Fri, 31 Mar 2023 14:05:47 -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 q70-20020a81b249000000b0054601ee157fsm751990ywh.114.2023.03.31.14.05.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 31 Mar 2023 14:05:46 -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 v4 1/4] gpio: idio-16: Migrate to the regmap API Date: Fri, 31 Mar 2023 17:05:23 -0400 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org 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 v4: - Remove superfluous base check in idio_16_reg_mask_xlate() - Format idio_16_names[] to 8 GPIO per line - Utilize dev_err_probe() in idio_16_regmap_register() drivers/gpio/Kconfig | 3 + drivers/gpio/gpio-idio-16.c | 155 ++++++++++++++++++++++++++++++++++++ drivers/gpio/gpio-idio-16.h | 26 ++++++ 3 files changed, 184 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 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..f9349e8d7fdc 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 @@ -14,6 +18,157 @@ #define DEFAULT_SYMBOL_NAMESPACE GPIO_IDIO_16 +#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 mask_buf_def, + const unsigned int mask_buf, void *const irq_drv_data) +{ + struct idio_16_data *const data = irq_drv_data; + const unsigned int prev_mask = data->irq_mask; + int err; + unsigned int val; + + /* exit early if no change since the previous mask */ + if (mask_buf == prev_mask) + return 0; + + /* remember the current mask for the next mask sync */ + data->irq_mask = mask_buf; + + /* if all previously masked, enable interrupts when unmasking */ + if (prev_mask == mask_buf_def) { + err = 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 == 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 unsigned int base, + const unsigned int offset, unsigned int *const reg, + unsigned int *const mask) +{ + unsigned int stride; + + /* Input lines start at GPIO 16 */ + if (offset < 16) { + stride = offset / IDIO_16_NGPIO_PER_REG; + *reg = IDIO_16_OUT_BASE + stride * IDIO_16_REG_STRIDE; + } else { + stride = (offset - 16) / IDIO_16_NGPIO_PER_REG; + *reg = IDIO_16_IN_BASE + stride * IDIO_16_REG_STRIDE; + } + + *mask = BIT(offset % IDIO_16_NGPIO_PER_REG); + + return 0; +} + +static const char *idio_16_names[IDIO_16_NGPIO] = { + "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", +}; + +/** + * 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 error 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 = {}; + 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 = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + data->map = config->map; + + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->name = dev_name(dev); + chip->status_base = IDIO_16_INTERRUPT_STATUS; + chip->mask_base = IDIO_16_ENABLE_IRQ; + chip->ack_base = IDIO_16_CLEAR_INTERRUPT; + chip->no_status = config->no_status; + chip->num_regs = 1; + chip->irqs = config->regmap_irqs; + chip->num_irqs = config->num_regmap_irqs; + chip->handle_mask_sync = idio_16_handle_mask_sync; + chip->irq_drv_data = data; + + /* Disable IRQ to prevent spurious interrupts before we're ready */ + err = regmap_write(data->map, IDIO_16_DISABLE_IRQ, 0x00); + if (err) + return err; + + err = devm_regmap_add_irq_chip(dev, data->map, config->irq, 0, 0, chip, &chip_data); + if (err) + return dev_err_probe(dev, err, "IRQ registration failed\n"); + + if (config->filters) { + /* Deactivate input filters */ + err = regmap_write(data->map, IDIO_16_DEACTIVATE_INPUT_FILTERS, 0x00); + if (err) + return err; + } + + gpio_config.parent = config->parent; + gpio_config.regmap = data->map; + gpio_config.ngpio = IDIO_16_NGPIO; + gpio_config.names = idio_16_names; + gpio_config.reg_dat_base = GPIO_REGMAP_ADDR(IDIO_16_DAT_BASE); + gpio_config.reg_set_base = GPIO_REGMAP_ADDR(IDIO_16_DAT_BASE); + gpio_config.ngpio_per_reg = IDIO_16_NGPIO_PER_REG; + gpio_config.reg_stride = IDIO_16_REG_STRIDE; + gpio_config.irq_domain = regmap_irq_get_domain(chip_data); + gpio_config.reg_mask_xlate = 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 +struct device; +struct regmap; +struct regmap_irq; + +/** + * struct idio_16_regmap_config - Configuration for the IDIO-16 register map + * @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); +int devm_idio_16_regmap_register(struct device *dev, const struct idio_16_regmap_config *config); + #endif /* _IDIO_16_H_ */ From patchwork Fri Mar 31 21:05:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Breathitt Gray X-Patchwork-Id: 669894 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 5C6FBC761A6 for ; Fri, 31 Mar 2023 21:05:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233042AbjCaVFy (ORCPT ); Fri, 31 Mar 2023 17:05:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37804 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232788AbjCaVFv (ORCPT ); Fri, 31 Mar 2023 17:05:51 -0400 Received: from mail-yw1-x1129.google.com (mail-yw1-x1129.google.com [IPv6:2607:f8b0:4864:20::1129]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4895A1D2DD for ; Fri, 31 Mar 2023 14:05:49 -0700 (PDT) Received: by mail-yw1-x1129.google.com with SMTP id 00721157ae682-545e907790fso322470637b3.3 for ; Fri, 31 Mar 2023 14:05:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1680296748; 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=SP9X9kxgiV5uszeLSB2zIqb4Yvuepj1dFk5ABV7jKn8=; b=hsc2oCIPHD0udLznPtJSzeCHBKgaXfX3+c3B2Fo683tXHlO5JzMk0/WkfQoTSz4vGX lRXI/HXUCK+tA9wCgyzCJ0Df0R3YQXKFTXn3bbG7c8kMoVjutG3y3vYlLO44GAyuAl+o HDO0Qtv4/bZyBUG2PZgRZfGZU1ct3SNvhXT6eyDtK4BpY3ZyeGsdIynL2uW6GE26E/2m JaZXxbTz/eTh3XH630D1jJEcITbWo74xNP1ac2hSQzXzhWIyKkajuZGNi5M/cyqP92HO SnSFS9iOar0odyr1e34jx0U+mth9csqFWxiN4z8Exk6gJg2a6g0AtzUZ3Wbfzko44vfW Nxhw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680296748; 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=SP9X9kxgiV5uszeLSB2zIqb4Yvuepj1dFk5ABV7jKn8=; b=KExJnNVaLh+p0x8Qmahn+CdMOLuNtBYbFT5hBMxm1J/jaZFArICLMHsSbJPnnbRzmd ebIUxO9AmIThT5f0ezVeS4tDcA+9Mh+wOJgkUBWQJR32+gKYTD481TTpEIdn1/YI9aEX 7HQJTrisNs//SplnPDedDo3OC86nvV6dOMdp7sx6jbNPxunbs4cNdvDzOJK+h2cnvx2R xHRbm/6F5rSoJwGq7JXJJx3WGvehqGxkHzkjE7OiGoftZEDDiBVWN5wBk2KfFnX4EIFB hZLEHXA3o5nN7Gap/+6U6lkfi2cME26JTiFhWj4Tujub+YjHWmCyfJ+vzVgFpCwymS54 9lDA== X-Gm-Message-State: AAQBX9c7neraO2wAzYSMBHIfECJB5ZfLyaerI+049EcKPe9SaewfiVrW 1CZuQdoLhwFt6y7+Pyfh1sX45Q== X-Google-Smtp-Source: AKy350Yd4Z8uxoJe6Eh3HpwXnkojNCwW+6IkzFAWCyyUXfQY5GJtDeaQYDQlonhMJ7+H0Q4+Kipjeg== X-Received: by 2002:a0d:ddd1:0:b0:544:f952:2184 with SMTP id g200-20020a0dddd1000000b00544f9522184mr30737729ywe.44.1680296748330; Fri, 31 Mar 2023 14:05:48 -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 q70-20020a81b249000000b0054601ee157fsm751990ywh.114.2023.03.31.14.05.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 31 Mar 2023 14:05:47 -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 v4 2/4] gpio: 104-idio-16: Migrate to the regmap API Date: Fri, 31 Mar 2023 17:05:24 -0400 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org 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 v4: none 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-16.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 #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"); -/** - * 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[] = { + 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 = 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 = 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 = 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 = 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 = irq_data_get_irq_chip_data(data); - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned long offset = irqd_to_hwirq(data); - unsigned long flags; - - idio16gpio->irq_mask &= ~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 = irq_data_get_irq_chip_data(data); - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned long offset = irqd_to_hwirq(data); - const unsigned long prev_irq_mask = idio16gpio->irq_mask; - unsigned long flags; - - gpiochip_enable_irq(chip, offset); - idio16gpio->irq_mask |= 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_type) -{ - /* The only valid irq types are none and both-edges */ - if (flow_type != IRQ_TYPE_NONE && - (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH) - return -EINVAL; - - return 0; -} - -static const struct irq_chip idio_16_irqchip = { - .name = "104-idio-16", - .irq_ack = idio_16_irq_ack, - .irq_mask = idio_16_irq_mask, - .irq_unmask = idio_16_irq_unmask, - .irq_set_type = idio_16_irq_set_type, - .flags = IRQCHIP_IMMUTABLE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, +static const struct regmap_range idio_16_rd_ranges[] = { + 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 = dev_id; - struct gpio_chip *const chip = &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] = { - "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[] = { + regmap_reg_range(0x2, 0x2), +}; +static const struct regmap_access_table idio_16_wr_table = { + .yes_ranges = idio_16_wr_ranges, + .n_yes_ranges = ARRAY_SIZE(idio_16_wr_ranges), +}; +static const struct regmap_access_table idio_16_rd_table = { + .yes_ranges = idio_16_rd_ranges, + .n_yes_ranges = ARRAY_SIZE(idio_16_rd_ranges), +}; +static const struct regmap_access_table idio_16_precious_table = { + .yes_ranges = idio_16_precious_ranges, + .n_yes_ranges = ARRAY_SIZE(idio_16_precious_ranges), +}; +static const struct regmap_config idio_16_regmap_config = { + .reg_bits = 8, + .reg_stride = 1, + .val_bits = 8, + .io_port = true, + .max_register = 0x5, + .wr_table = &idio_16_wr_table, + .rd_table = &idio_16_rd_table, + .volatile_table = &idio_16_rd_table, + .precious_table = &idio_16_precious_table, + .cache_type = REGCACHE_FLAT, }; -static int idio_16_irq_init_hw(struct gpio_chip *gc) -{ - struct idio_16_gpio *const idio16gpio = 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] = { \ + .mask = BIT(_id), \ + .type = { .types_supported = IRQ_TYPE_EDGE_BOTH }, \ + } - return 0; -} +static const struct regmap_irq idio_16_regmap_irqs[] = { + 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 */ +}; static int idio_16_probe(struct device *dev, unsigned int id) { - struct idio_16_gpio *idio16gpio; const char *const name = dev_name(dev); - struct gpio_irq_chip *girq; - int err; - - idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL); - if (!idio16gpio) - return -ENOMEM; + struct idio_16_regmap_config config = {}; + void __iomem *regs; + struct regmap *map; 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; } - idio16gpio->reg = devm_ioport_map(dev, base[id], IDIO_16_EXTENT); - if (!idio16gpio->reg) + regs = devm_ioport_map(dev, base[id], IDIO_16_EXTENT); + if (!regs) return -ENOMEM; - idio16gpio->chip.label = name; - idio16gpio->chip.parent = dev; - idio16gpio->chip.owner = THIS_MODULE; - idio16gpio->chip.base = -1; - idio16gpio->chip.ngpio = IDIO_16_NGPIO; - idio16gpio->chip.names = idio_16_names; - idio16gpio->chip.get_direction = idio_16_gpio_get_direction; - idio16gpio->chip.direction_input = idio_16_gpio_direction_input; - idio16gpio->chip.direction_output = idio_16_gpio_direction_output; - idio16gpio->chip.get = idio_16_gpio_get; - idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple; - idio16gpio->chip.set = idio_16_gpio_set; - idio16gpio->chip.set_multiple = 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 = &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 = NULL; - girq->num_parents = 0; - girq->parents = NULL; - girq->default_type = IRQ_TYPE_NONE; - girq->handler = handle_edge_irq; - girq->init_hw = idio_16_irq_init_hw; + map = 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 map\n"); - raw_spin_lock_init(&idio16gpio->lock); - - err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio); - if (err) { - dev_err(dev, "GPIO registering failed (%d)\n", err); - return err; - } - - err = 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 = dev; + config.map = map; + config.regmap_irqs = idio_16_regmap_irqs; + config.num_regmap_irqs = ARRAY_SIZE(idio_16_regmap_irqs); + config.irq = irq[id]; + config.no_status = true; - return 0; + return devm_idio_16_regmap_register(dev, &config); } static struct isa_driver idio_16_driver = { From patchwork Fri Mar 31 21:05:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Breathitt Gray X-Patchwork-Id: 669288 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 40E34C77B60 for ; Fri, 31 Mar 2023 21:05:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232048AbjCaVF5 (ORCPT ); Fri, 31 Mar 2023 17:05:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37852 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232929AbjCaVFw (ORCPT ); Fri, 31 Mar 2023 17:05:52 -0400 Received: from mail-yw1-x1135.google.com (mail-yw1-x1135.google.com [IPv6:2607:f8b0:4864:20::1135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 276F91D843 for ; Fri, 31 Mar 2023 14:05:50 -0700 (PDT) Received: by mail-yw1-x1135.google.com with SMTP id 00721157ae682-5445009c26bso438275287b3.8 for ; Fri, 31 Mar 2023 14:05:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1680296749; 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=aHDpWJ8LmFXnhqNV9hvIQWX65CwoKi+B8qVcqGGaFg0=; b=G0+PT7ejGRpajE70IDG+VljDx3e7hktCXEbeutu4Z4pJBD548bMqOWlCZrG8xnwd4r TFXNwlB2wI9Vc/2N9+eev2ReA5CZUsm2K2SXUwJROOy0Jgh/dLIm+srdAbJo8dq4c7Qn lgwojuCpF6qB4raUbuePretyHJAxgHhonIohQ8BaIMVXqWVhniJLQYqLNfO51jgtiPsd rox5wnzCuO5O7JL8TgiyTljQ10t52M1/6YaAPhGOR/rWF/e9oUFu+tPkX3nkk2Da+KEY 737F06pFt10ESPCILHraylzZeVDpNDlfL8PR7GTioMzDUfzqcDD497oX4nDrTxtc0rlk X/Jw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680296749; 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=aHDpWJ8LmFXnhqNV9hvIQWX65CwoKi+B8qVcqGGaFg0=; b=1saCsaeMYP1wd0LnMtfLopX+1TGKeIqEixtmYoZLayyzimDKsCFiI+TvbrbD4qsmWO EHJqjE+bL/w2eA8vD3b8AGEvBfT0lzlFeu/DYVaU2XuodGazExfgCDt3Ha8q3xeHemQC rcOkIhnw88qUPOku5n2tvbhtSYdFhClIO/xPfFtLyvxYtldZouLOGy1f6YyM/GLPZX8k VbKo4cX6gwCZAaBE7lOcwQsl0y7LMswXJz5BE+nZswEod1V0mm1IovDwLbxVGOw03bpk ZtNB7zSz1aP/XFFv5tIPi2K2tLALSSU2lvWSf3vfpiyn//9U4j1BypfCKGoS5Ad4rmVK Irqw== X-Gm-Message-State: AAQBX9f5Xx6BcxmrFd08Dh+U9lE3vx/dXdTxuEjlDYE4Eskg29sSalc1 B2oxG8P5l4Cq4c4QMrUoTfXzfg== X-Google-Smtp-Source: AKy350ZMxzGAxGBBzwyegUQTjZuCNCvSqOdvEKiR8RakGgyyjTeJgysvwuTu8De3A5lkz/9wj4s9CA== X-Received: by 2002:a0d:e28c:0:b0:544:7994:34dc with SMTP id l134-20020a0de28c000000b00544799434dcmr22865405ywe.43.1680296749222; Fri, 31 Mar 2023 14:05:49 -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 q70-20020a81b249000000b0054601ee157fsm751990ywh.114.2023.03.31.14.05.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 31 Mar 2023 14:05:48 -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 v4 3/4] gpio: pci-idio-16: Migrate to the regmap API Date: Fri, 31 Mar 2023 17:05:25 -0400 Message-Id: <672f7f4ad6afb0d6bf5745118334b27c36594f77.1680296343.git.william.gray@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org 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 v4: none 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 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-16.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 #include "gpio-idio-16.h" -/** - * 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[] = { + 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 = 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 = 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 = 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 = 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 = irq_data_get_irq_chip_data(data); - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned long mask = BIT(irqd_to_hwirq(data)); - unsigned long flags; - - idio16gpio->irq_mask &= ~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 = irq_data_get_irq_chip_data(data); - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned long mask = BIT(irqd_to_hwirq(data)); - const unsigned long prev_irq_mask = idio16gpio->irq_mask; - unsigned long flags; - - gpiochip_enable_irq(chip, irqd_to_hwirq(data)); - - idio16gpio->irq_mask |= 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_type) -{ - /* The only valid irq types are none and both-edges */ - if (flow_type != IRQ_TYPE_NONE && - (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH) - return -EINVAL; - - return 0; -} - -static const struct irq_chip idio_16_irqchip = { - .name = "pci-idio-16", - .irq_ack = idio_16_irq_ack, - .irq_mask = idio_16_irq_mask, - .irq_unmask = idio_16_irq_unmask, - .irq_set_type = idio_16_irq_set_type, - .flags = IRQCHIP_IMMUTABLE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, +static const struct regmap_range idio_16_rd_ranges[] = { + 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 = dev_id; - unsigned int irq_status; - struct gpio_chip *const chip = &idio16gpio->chip; - int gpio; - - raw_spin_lock(&idio16gpio->lock); - - irq_status = 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] = { - "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[] = { + regmap_reg_range(0x2, 0x2), +}; +static const struct regmap_access_table idio_16_wr_table = { + .yes_ranges = idio_16_wr_ranges, + .n_yes_ranges = ARRAY_SIZE(idio_16_wr_ranges), +}; +static const struct regmap_access_table idio_16_rd_table = { + .yes_ranges = idio_16_rd_ranges, + .n_yes_ranges = ARRAY_SIZE(idio_16_rd_ranges), +}; +static const struct regmap_access_table idio_16_precious_table = { + .yes_ranges = idio_16_precious_ranges, + .n_yes_ranges = ARRAY_SIZE(idio_16_precious_ranges), +}; +static const struct regmap_config idio_16_regmap_config = { + .reg_bits = 8, + .reg_stride = 1, + .val_bits = 8, + .io_port = true, + .max_register = 0x6, + .wr_table = &idio_16_wr_table, + .rd_table = &idio_16_rd_table, + .volatile_table = &idio_16_rd_table, + .precious_table = &idio_16_precious_table, + .cache_type = REGCACHE_FLAT, }; -static int idio_16_irq_init_hw(struct gpio_chip *gc) -{ - struct idio_16_gpio *const idio16gpio = 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] = { \ + .mask = BIT(2), \ + .type = { .types_supported = IRQ_TYPE_EDGE_BOTH }, \ + } - return 0; -} +static const struct regmap_irq idio_16_regmap_irqs[] = { + 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 */ +}; static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct device *const dev = &pdev->dev; - struct idio_16_gpio *idio16gpio; int err; const size_t pci_bar_index = 2; const char *const name = pci_name(pdev); - struct gpio_irq_chip *girq; - - idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL); - if (!idio16gpio) - return -ENOMEM; + struct idio_16_regmap_config config = {}; + void __iomem *regs; + struct regmap *map; err = pcim_enable_device(pdev); if (err) { @@ -226,53 +87,20 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id) return err; } - idio16gpio->reg = pcim_iomap_table(pdev)[pci_bar_index]; + regs = pcim_iomap_table(pdev)[pci_bar_index]; - /* Deactivate input filters */ - iowrite8(0, &idio16gpio->reg->filter_ctl); + map = 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 map\n"); - idio16gpio->chip.label = name; - idio16gpio->chip.parent = dev; - idio16gpio->chip.owner = THIS_MODULE; - idio16gpio->chip.base = -1; - idio16gpio->chip.ngpio = IDIO_16_NGPIO; - idio16gpio->chip.names = idio_16_names; - idio16gpio->chip.get_direction = idio_16_gpio_get_direction; - idio16gpio->chip.direction_input = idio_16_gpio_direction_input; - idio16gpio->chip.direction_output = idio_16_gpio_direction_output; - idio16gpio->chip.get = idio_16_gpio_get; - idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple; - idio16gpio->chip.set = idio_16_gpio_set; - idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple; - - idio_16_state_init(&idio16gpio->state); - - girq = &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 = NULL; - girq->num_parents = 0; - girq->parents = NULL; - girq->default_type = IRQ_TYPE_NONE; - girq->handler = handle_edge_irq; - girq->init_hw = idio_16_irq_init_hw; - - raw_spin_lock_init(&idio16gpio->lock); - - err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio); - if (err) { - dev_err(dev, "GPIO registering failed (%d)\n", err); - return err; - } - - err = 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 = dev; + config.map = map; + config.regmap_irqs = idio_16_regmap_irqs; + config.num_regmap_irqs = ARRAY_SIZE(idio_16_regmap_irqs); + config.irq = pdev->irq; + config.filters = true; - return 0; + return devm_idio_16_regmap_register(dev, &config); } static const struct pci_device_id idio_16_pci_dev_id[] = { From patchwork Fri Mar 31 21:05:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Breathitt Gray X-Patchwork-Id: 669289 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 61491C77B6C for ; Fri, 31 Mar 2023 21:05:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233050AbjCaVFy (ORCPT ); Fri, 31 Mar 2023 17:05:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37854 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232974AbjCaVFw (ORCPT ); Fri, 31 Mar 2023 17:05:52 -0400 Received: from mail-yw1-x112d.google.com (mail-yw1-x112d.google.com [IPv6:2607:f8b0:4864:20::112d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2EB3B1D84A for ; Fri, 31 Mar 2023 14:05:51 -0700 (PDT) Received: by mail-yw1-x112d.google.com with SMTP id 00721157ae682-544787916d9so437797507b3.13 for ; Fri, 31 Mar 2023 14:05:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1680296750; 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=KlccS8PuhgiaZf91f27SabAjxszuRJsMXVMDszCbILs=; b=hJtRlMwEdV+FXGwi9QXe+mRxKskphkSscXmkBxcqM+bWcwHHBS1W35qX1vFNWcIewr n+qT5fFFCIxE9ghL4tTc+OsPY+ksiDDolMVsTIwafsGYFC/npAgeJrMcHNChfCqBG1CG iKbmuLKKi4B4keXb1IYOJKdMYznFljMIZMFQVvhBerpFivChNNdFhG6cQv4cln4iWpnZ UymjGn8P137BiEoL1ZIIJ9ENpRq165as3/hQIXLh3bUXoewMZZyuxlbcNjMT7XY9ZBCz XotLRkFb9pA+6hNMeAVzCKvuDBBek808UPv8ncntcU2NFbOnTMcrt0SYMKKQ0jmf6yYH WTIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680296750; 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=KlccS8PuhgiaZf91f27SabAjxszuRJsMXVMDszCbILs=; b=ocp0m61mHraNULbau1n4OCmewjhGeGyuKxMePk96ep2UYaIxSauovCdHHJmR4mnGpa RugWwKW/u//eZ4N/WNnk5VsuKc95TBEe+UI5wlCxR0cji0xpd9d5zl8M3d9bMdwFGfO0 f3gaxhYfksNutJO+6kNuAKuIxjmsMZYFEaIafVvvXlGtdj3dBvgYXGtxFY/PZIUvIk0z sTWlSYUJR9I8JCvz/UiivdU/j9sOdgC2Un/16KQ7Aew6400qCXcifXLVds1uFL92KlGp VEpTR6sZMgPT1mp1sFkChofrZIcXGkObzR2Y0Ncck2mZVMmTB874qEj0itJGgrFNawYT BZmg== X-Gm-Message-State: AAQBX9c4CFwm/IvKxk+mf/k3rQXeXuZnAP7p2XeaJBasDuA0j2IC5yaK NUlURIk+3r21pDhQOm/9JBG2wA== X-Google-Smtp-Source: AKy350Zig3kb0gtLjKETx+QjCVgAdPmHmQbyKdRvbaYXvJyjnDq6VBi6iB4CLefDsdjnmkN2VXSxgg== X-Received: by 2002:a81:a209:0:b0:545:91c2:d5eb with SMTP id w9-20020a81a209000000b0054591c2d5ebmr25732254ywg.28.1680296750352; Fri, 31 Mar 2023 14:05:50 -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 q70-20020a81b249000000b0054601ee157fsm751990ywh.114.2023.03.31.14.05.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 31 Mar 2023 14:05:50 -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 v4 4/4] gpio: idio-16: Remove unused legacy interface Date: Fri, 31 Mar 2023 17:05:26 -0400 Message-Id: <3d77e0b3dd3b3d3f7dad53222a755459b5e2aa57.1680296343.git.william.gray@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org 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 v4: 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 f9349e8d7fdc..53b1eb876a12 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 #include "gpio-idio-16.h" @@ -169,133 +167,6 @@ int devm_idio_16_regmap_register(struct device *const dev, } EXPORT_SYMBOL_GPL(devm_idio_16_regmap_register); -/** - * 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=low, 1=high) 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 = 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 offsets - * @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=low, 1=high) 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 = 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 >= 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_ -#include -#include - struct device; struct regmap; struct regmap_irq; @@ -30,68 +27,6 @@ struct idio_16_regmap_config { bool filters; }; -/** - * 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=output, 1=input) for the signal at @offset. - */ -static inline int idio_16_get_direction(const unsigned long offset) -{ - return (offset >= 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); #endif /* _IDIO_16_H_ */