From nobody Tue Apr 28 05:05:47 2026 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 ABFEDC433EF for ; Mon, 6 Jun 2022 14:37:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239837AbiFFOhG (ORCPT ); Mon, 6 Jun 2022 10:37:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38334 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239841AbiFFOgR (ORCPT ); Mon, 6 Jun 2022 10:36:17 -0400 Received: from mail-oa1-x2f.google.com (mail-oa1-x2f.google.com [IPv6:2001:4860:4864:20::2f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A297612B01B for ; Mon, 6 Jun 2022 07:36:10 -0700 (PDT) Received: by mail-oa1-x2f.google.com with SMTP id 586e51a60fabf-f2e0a41009so19361467fac.6 for ; Mon, 06 Jun 2022 07:36:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=VfTrAEC+8RIPbSv52tbPZfU+fEKDARXIrRMp1LlzURg=; b=PdVn8UAKMCpAesFj5BGFLpNp+aIwTXO4mG6N2TEYZLF5GNt3e2WbJFsJXOJhSpcnuG IZtlFZzIB8VZAICoqaLu59LLLQVlugx3X+ljocTiKocjhKWTzy47LVeM4N4wm4h2jO7T HV9RojTqb2zTHhmEtCv2z9QBcWd175TvygQmWF+hm15mPyDyqXjh6icIvnzK0tHMTajA SI7Rn+L6WSMUgZ5JgPu0wu3wMsZ3x/If1D19+1KuzDbelxufvoPa7t+dU+sXY1/2qSLi f8V+jGUS6rmxLks9JQQpJw7iMLSWjkZ2HdoeronDKf6egUAziKmcA/ARoozmDu1PpHxz XsBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=VfTrAEC+8RIPbSv52tbPZfU+fEKDARXIrRMp1LlzURg=; b=Vkxdd8HaDopPrO9RzI2SoU45hLMcSgEQuMHLNenolSXQ55qrOQGvpb5tN8aGbnaGri /s/Cbr2xI1+tehkQP98h6s5NV28apKD4dIO6fZXWj6OhNFgIWLKbAgh4mlHFbbERwjBj ZV07AkSa777HcBcj6JVw5rp0dNL2dUyju1uNHK1u852oTDrmDGfrb0RNHrSrD9zv7F3+ L7BGNBz2O9bUyjWpElYVvVTjuEDKXwRCP7oazuAxEA/gi3zDSGYa2aKUGDdfdTRW637h stcDi4gY3urawZqf3BFaniBiNSpNE7YcHO9C1EQirNA/N7f2O8UBRaug3qjlxdGxgC/o 5SwA== X-Gm-Message-State: AOAM53099Nj3fDqGw7kSJ1/lN+d6St7c0PImkDe9WeQL8v0vstWEAPXb W3oppn/HPtomi3jYd/OpPRGMlorSPRygTQ== X-Google-Smtp-Source: ABdhPJxH6gbXCunuQbHxi/D/1wcisDJtuO5XeNd2Om3ppELl/Dy+KlzcX7HmvliSW/sqzxFIBpFZZA== X-Received: by 2002:a05:6870:c690:b0:f2:99d5:343e with SMTP id cv16-20020a056870c69000b000f299d5343emr31198250oab.136.1654526169955; Mon, 06 Jun 2022 07:36:09 -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 u13-20020a056871008d00b000f5d4e5b9a0sm6942791oaa.2.2022.06.06.07.36.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Jun 2022 07:36:09 -0700 (PDT) From: William Breathitt Gray To: linus.walleij@linaro.org, brgl@bgdev.pl Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, William Breathitt Gray Subject: [PATCH 1/5] gpio: 104-dio-48e: Implement and utilize register structures Date: Mon, 6 Jun 2022 10:33:16 -0400 Message-Id: <7d28ff3373d49d29b01765958ec322ce5ed0d4ff.1654525394.git.william.gray@linaro.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Reduce magic numbers and improve code readability by implementing and utilizing named register data structures. Signed-off-by: William Breathitt Gray --- drivers/gpio/gpio-104-dio-48e.c | 157 +++++++++++++++++++++----------- 1 file changed, 106 insertions(+), 51 deletions(-) diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48= e.c index f118ad9bcd33..e1c5759e0902 100644 --- a/drivers/gpio/gpio-104-dio-48e.c +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -20,6 +20,7 @@ #include #include #include +#include =20 #define DIO48E_EXTENT 16 #define MAX_NUM_DIO48E max_num_isa_dev(DIO48E_EXTENT) @@ -33,6 +34,40 @@ static unsigned int irq[MAX_NUM_DIO48E]; module_param_hw_array(irq, uint, irq, NULL, 0); MODULE_PARM_DESC(irq, "ACCES 104-DIO-48E interrupt line numbers"); =20 +/** + * struct i8255_reg - Intel 8255 register structure + * @port: Port A, B, and C + * @control: Control register + */ +struct i8255_reg { + u8 port[3]; + u8 control; +}; + +/** + * struct dio48e_reg - device register structure + * @ppi: Programmable Peripheral Interface groups + * @enable_buffer: Enable/Disable Buffer groups + * @unused1: Unused + * @enable_interrupt: Write: Enable Interrupt + * Read: Disable Interrupt + * @unused2: Unused + * @enable_counter: Write: Enable Counter/Timer Addressing + * Read: Disable Counter/Timer Addressing + * @unused3: Unused + * @clear_interrupt: Clear Interrupt + */ +struct dio48e_reg { + struct i8255_reg ppi[2]; + u8 enable_buffer[2]; + u8 unused1; + u8 enable_interrupt; + u8 unused2; + u8 enable_counter; + u8 unused3; + u8 clear_interrupt; +}; + /** * struct dio48e_gpio - GPIO device private data structure * @chip: instance of the gpio_chip @@ -40,7 +75,7 @@ MODULE_PARM_DESC(irq, "ACCES 104-DIO-48E interrupt line n= umbers"); * @out_state: output bits state * @control: Control registers state * @lock: synchronization lock to prevent I/O race conditions - * @base: base port address of the GPIO device + * @reg: I/O address offset for the device registers * @irq_mask: I/O bits affected by interrupts */ struct dio48e_gpio { @@ -49,7 +84,7 @@ struct dio48e_gpio { unsigned char out_state[6]; unsigned char control[2]; raw_spinlock_t lock; - void __iomem *base; + struct dio48e_reg __iomem *reg; unsigned char irq_mask; }; =20 @@ -69,32 +104,33 @@ static int dio48e_gpio_direction_input(struct gpio_chi= p *chip, unsigned int offs { struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(chip); const unsigned int io_port =3D offset / 8; - const unsigned int control_port =3D io_port / 3; - void __iomem *const control_addr =3D dio48egpio->base + 3 + control_port = * 4; + const unsigned long group =3D io_port / 3; + const unsigned long port =3D io_port - (group * 3); + u8 __iomem *const control_addr =3D &dio48egpio->reg->ppi[group].control; unsigned long flags; unsigned int control; =20 raw_spin_lock_irqsave(&dio48egpio->lock, flags); =20 /* Check if configuring Port C */ - if (io_port =3D=3D 2 || io_port =3D=3D 5) { + if (port =3D=3D 2) { /* Port C can be configured by nibble */ if (offset % 8 > 3) { dio48egpio->io_state[io_port] |=3D 0xF0; - dio48egpio->control[control_port] |=3D BIT(3); + dio48egpio->control[group] |=3D BIT(3); } else { dio48egpio->io_state[io_port] |=3D 0x0F; - dio48egpio->control[control_port] |=3D BIT(0); + dio48egpio->control[group] |=3D BIT(0); } } else { dio48egpio->io_state[io_port] |=3D 0xFF; - if (io_port =3D=3D 0 || io_port =3D=3D 3) - dio48egpio->control[control_port] |=3D BIT(4); + if (port =3D=3D 0) + dio48egpio->control[group] |=3D BIT(4); else - dio48egpio->control[control_port] |=3D BIT(1); + dio48egpio->control[group] |=3D BIT(1); } =20 - control =3D BIT(7) | dio48egpio->control[control_port]; + control =3D BIT(7) | dio48egpio->control[group]; iowrite8(control, control_addr); control &=3D ~BIT(7); iowrite8(control, control_addr); @@ -109,31 +145,33 @@ static int dio48e_gpio_direction_output(struct gpio_c= hip *chip, unsigned int off { struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(chip); const unsigned int io_port =3D offset / 8; - const unsigned int control_port =3D io_port / 3; + const unsigned long group =3D io_port / 3; + const unsigned long port =3D io_port - (group * 3); const unsigned int mask =3D BIT(offset % 8); - void __iomem *const control_addr =3D dio48egpio->base + 3 + control_port = * 4; - const unsigned int out_port =3D (io_port > 2) ? io_port + 1 : io_port; + struct i8255_reg __iomem *const ppi =3D dio48egpio->reg->ppi + group; + u8 __iomem *const control_addr =3D &ppi->control; + u8 __iomem *const port_addr =3D ppi->port + port; unsigned long flags; unsigned int control; =20 raw_spin_lock_irqsave(&dio48egpio->lock, flags); =20 /* Check if configuring Port C */ - if (io_port =3D=3D 2 || io_port =3D=3D 5) { + if (port =3D=3D 2) { /* Port C can be configured by nibble */ if (offset % 8 > 3) { dio48egpio->io_state[io_port] &=3D 0x0F; - dio48egpio->control[control_port] &=3D ~BIT(3); + dio48egpio->control[group] &=3D ~BIT(3); } else { dio48egpio->io_state[io_port] &=3D 0xF0; - dio48egpio->control[control_port] &=3D ~BIT(0); + dio48egpio->control[group] &=3D ~BIT(0); } } else { dio48egpio->io_state[io_port] &=3D 0x00; - if (io_port =3D=3D 0 || io_port =3D=3D 3) - dio48egpio->control[control_port] &=3D ~BIT(4); + if (port =3D=3D 0) + dio48egpio->control[group] &=3D ~BIT(4); else - dio48egpio->control[control_port] &=3D ~BIT(1); + dio48egpio->control[group] &=3D ~BIT(1); } =20 if (value) @@ -141,10 +179,10 @@ static int dio48e_gpio_direction_output(struct gpio_c= hip *chip, unsigned int off else dio48egpio->out_state[io_port] &=3D ~mask; =20 - control =3D BIT(7) | dio48egpio->control[control_port]; + control =3D BIT(7) | dio48egpio->control[group]; iowrite8(control, control_addr); =20 - iowrite8(dio48egpio->out_state[io_port], dio48egpio->base + out_port); + iowrite8(dio48egpio->out_state[io_port], port_addr); =20 control &=3D ~BIT(7); iowrite8(control, control_addr); @@ -159,7 +197,8 @@ static int dio48e_gpio_get(struct gpio_chip *chip, unsi= gned int offset) struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(chip); const unsigned int port =3D offset / 8; const unsigned int mask =3D BIT(offset % 8); - const unsigned int in_port =3D (port > 2) ? port + 1 : port; + const unsigned long group =3D port / 3; + const unsigned long in_port =3D port - (group * 3); unsigned long flags; unsigned int port_state; =20 @@ -171,29 +210,33 @@ static int dio48e_gpio_get(struct gpio_chip *chip, un= signed int offset) return -EINVAL; } =20 - port_state =3D ioread8(dio48egpio->base + in_port); + port_state =3D ioread8(dio48egpio->reg->ppi[group].port + in_port); =20 raw_spin_unlock_irqrestore(&dio48egpio->lock, flags); =20 return !!(port_state & mask); } =20 -static const size_t ports[] =3D { 0, 1, 2, 4, 5, 6 }; - static int dio48e_gpio_get_multiple(struct gpio_chip *chip, unsigned long = *mask, unsigned long *bits) { struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(chip); unsigned long offset; unsigned long gpio_mask; - void __iomem *port_addr; + unsigned long port; + unsigned long group; + unsigned long in_port; + u8 __iomem *port_addr; unsigned long port_state; =20 /* clear bits array to a clean slate */ bitmap_zero(bits, chip->ngpio); =20 - for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { - port_addr =3D dio48egpio->base + ports[offset / 8]; + for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) { + port =3D offset / 8; + group =3D port / 3; + in_port =3D port - (group * 3); + port_addr =3D dio48egpio->reg->ppi[group].port + in_port; port_state =3D ioread8(port_addr) & gpio_mask; =20 bitmap_set_value8(bits, port_state, offset); @@ -207,7 +250,8 @@ static void dio48e_gpio_set(struct gpio_chip *chip, uns= igned int offset, int val struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(chip); const unsigned int port =3D offset / 8; const unsigned int mask =3D BIT(offset % 8); - const unsigned int out_port =3D (port > 2) ? port + 1 : port; + const unsigned long group =3D port / 3; + const unsigned long out_port =3D port - (group * 3); unsigned long flags; =20 raw_spin_lock_irqsave(&dio48egpio->lock, flags); @@ -217,7 +261,8 @@ static void dio48e_gpio_set(struct gpio_chip *chip, uns= igned int offset, int val else dio48egpio->out_state[port] &=3D ~mask; =20 - iowrite8(dio48egpio->out_state[port], dio48egpio->base + out_port); + iowrite8(dio48egpio->out_state[port], + dio48egpio->reg->ppi[group].port + out_port); =20 raw_spin_unlock_irqrestore(&dio48egpio->lock, flags); } @@ -229,13 +274,17 @@ static void dio48e_gpio_set_multiple(struct gpio_chip= *chip, unsigned long offset; unsigned long gpio_mask; size_t index; - void __iomem *port_addr; + size_t group; + size_t out_port; + u8 __iomem *port_addr; unsigned long bitmask; unsigned long flags; =20 - for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { + for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) { index =3D offset / 8; - port_addr =3D dio48egpio->base + ports[index]; + group =3D index / 3; + out_port =3D index - (group * 3); + port_addr =3D dio48egpio->reg->ppi[group].port + out_port; =20 bitmask =3D bitmap_get_value8(bits, offset) & gpio_mask; =20 @@ -274,7 +323,7 @@ static void dio48e_irq_mask(struct irq_data *data) =20 if (!dio48egpio->irq_mask) /* disable interrupts */ - ioread8(dio48egpio->base + 0xB); + ioread8(&dio48egpio->reg->enable_interrupt); =20 raw_spin_unlock_irqrestore(&dio48egpio->lock, flags); } @@ -294,8 +343,8 @@ static void dio48e_irq_unmask(struct irq_data *data) =20 if (!dio48egpio->irq_mask) { /* enable interrupts */ - iowrite8(0x00, dio48egpio->base + 0xF); - iowrite8(0x00, dio48egpio->base + 0xB); + iowrite8(0x00, &dio48egpio->reg->clear_interrupt); + iowrite8(0x00, &dio48egpio->reg->enable_interrupt); } =20 if (offset =3D=3D 19) @@ -341,7 +390,7 @@ static irqreturn_t dio48e_irq_handler(int irq, void *de= v_id) =20 raw_spin_lock(&dio48egpio->lock); =20 - iowrite8(0x00, dio48egpio->base + 0xF); + iowrite8(0x00, &dio48egpio->reg->clear_interrupt); =20 raw_spin_unlock(&dio48egpio->lock); =20 @@ -373,11 +422,25 @@ static int dio48e_irq_init_hw(struct gpio_chip *gc) struct dio48e_gpio *const dio48egpio =3D gpiochip_get_data(gc); =20 /* Disable IRQ by default */ - ioread8(dio48egpio->base + 0xB); + ioread8(&dio48egpio->reg->enable_interrupt); =20 return 0; } =20 +static void dio48e_init_ppi(struct i8255_reg __iomem *const ppi) +{ + /* Activate Mode Set; set Mode 0 output mode for Port A, B, and C */ + iowrite8(0x80, &ppi->control); + + /* Initialize all GPIO to 0 */ + iowrite8(0x00, &ppi->port[0]); + iowrite8(0x00, &ppi->port[1]); + iowrite8(0x00, &ppi->port[2]); + + /* Deactivate Mode Set */ + iowrite8(0x00, &ppi->control); +} + static int dio48e_probe(struct device *dev, unsigned int id) { struct dio48e_gpio *dio48egpio; @@ -395,8 +458,8 @@ static int dio48e_probe(struct device *dev, unsigned in= t id) return -EBUSY; } =20 - dio48egpio->base =3D devm_ioport_map(dev, base[id], DIO48E_EXTENT); - if (!dio48egpio->base) + dio48egpio->reg =3D devm_ioport_map(dev, base[id], DIO48E_EXTENT); + if (!dio48egpio->reg) return -ENOMEM; =20 dio48egpio->chip.label =3D name; @@ -426,16 +489,8 @@ static int dio48e_probe(struct device *dev, unsigned i= nt id) raw_spin_lock_init(&dio48egpio->lock); =20 /* initialize all GPIO as output */ - iowrite8(0x80, dio48egpio->base + 3); - iowrite8(0x00, dio48egpio->base); - iowrite8(0x00, dio48egpio->base + 1); - iowrite8(0x00, dio48egpio->base + 2); - iowrite8(0x00, dio48egpio->base + 3); - iowrite8(0x80, dio48egpio->base + 7); - iowrite8(0x00, dio48egpio->base + 4); - iowrite8(0x00, dio48egpio->base + 5); - iowrite8(0x00, dio48egpio->base + 6); - iowrite8(0x00, dio48egpio->base + 7); + dio48e_init_ppi(&dio48egpio->reg->ppi[0]); + dio48e_init_ppi(&dio48egpio->reg->ppi[1]); =20 err =3D devm_gpiochip_add_data(dev, &dio48egpio->chip, dio48egpio); if (err) { --=20 2.36.1 From nobody Tue Apr 28 05:05:47 2026 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 710E1C43334 for ; Mon, 6 Jun 2022 14:36:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239931AbiFFOgz (ORCPT ); Mon, 6 Jun 2022 10:36:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38392 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239850AbiFFOgS (ORCPT ); Mon, 6 Jun 2022 10:36:18 -0400 Received: from mail-ot1-x32b.google.com (mail-ot1-x32b.google.com [IPv6:2607:f8b0:4864:20::32b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A9E9112E32A for ; Mon, 6 Jun 2022 07:36:11 -0700 (PDT) Received: by mail-ot1-x32b.google.com with SMTP id g13-20020a9d6b0d000000b0060b13026e0dso10886467otp.8 for ; Mon, 06 Jun 2022 07:36:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=D9soskDv6KXVPHCaTa4CNNvs92+O4+arQnAcZVRZbT0=; b=qBquZDqP7VN6yh7Mp0E/g0yyjt5kNSP8AK3EnE54P/q3yE3LlMoH2/TEmIg2UJQnWU /Fqmnmsrc3D+Ljh2XgbU8/RjSZg+lG58HAstpsi6q6hW4k8kqkq4Bc4LetEO5flXiTZ1 bV8to5CFT3LbggX0tH+FgaWAzs+KPxVsO29F7lwhHtUKEtmkJkcVtINQyAp67s9UuN2n 45cS26ygVyD9OZGNrb65rdSchWZxmSvBZEdHQ3uphO3uoYuq2sRzVJ9sINYPnT5KGvtr T0uYdpVF+UUK9X069Wmm2ynwH7Vmtx0vExFcopTEg9+8Pz8y5YkV2ihO32DMv9KJKoqb xPJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=D9soskDv6KXVPHCaTa4CNNvs92+O4+arQnAcZVRZbT0=; b=lGLXr+stBnuKyrKZILvMUjgbm5tj/2fafmhL1GptuuPuoX1AvJHbQ4TvTLbTBVTESO IJ0hGx7KZQo+wkb3vhPoiA5dRLIqYKp+ExxnXv9lIX01oUj4sg9lgBMCuZxgHLJ08XG2 S9NaHZtxHcC4eGotj4FRN9pSk2sC771i825/wim8d7K9sNHiT+xDEEH9bcI/mE0pY0po pj586fbve6KbvdqVq2qlh6XD+R8kxBhytGvd7AnFHhEqBMvkiFY3/NrBMLUXbw7UpM5u lZX6f7g8dIqADavRfqqzqDdqgaqAQhcQtSZeCxP9+wJ9SChH1/8CQGwGKRmRLK9lrjYs MU1Q== X-Gm-Message-State: AOAM530nAQcCTWJSBO/JABYxVJ4gFRY97o+Gy5Cz9ET4WrF2g5gPOX/T FCXYCSi+ZoFNEO52rtjOAPpxow== X-Google-Smtp-Source: ABdhPJz6P2zs40Kr7rXerX3QlSpEo4I+NPEWZJBS7kHMKTpI2K63060Uy3lUZZaayRlZWc6OnQM0og== X-Received: by 2002:a9d:129:0:b0:60b:23b5:1659 with SMTP id 38-20020a9d0129000000b0060b23b51659mr9942070otu.26.1654526170952; Mon, 06 Jun 2022 07:36:10 -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 u13-20020a056871008d00b000f5d4e5b9a0sm6942791oaa.2.2022.06.06.07.36.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Jun 2022 07:36:10 -0700 (PDT) From: William Breathitt Gray To: linus.walleij@linaro.org, brgl@bgdev.pl Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, William Breathitt Gray Subject: [PATCH 2/5] gpio: 104-idi-48: Implement and utilize register structures Date: Mon, 6 Jun 2022 10:33:17 -0400 Message-Id: <0a893282333f195a208aa8c9fa3f38e447452abd.1654525394.git.william.gray@linaro.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Reduce magic numbers and improve code readability by implementing and utilizing named register data structures. Signed-off-by: William Breathitt Gray --- drivers/gpio/gpio-104-idi-48.c | 128 ++++++++++++++++----------------- 1 file changed, 63 insertions(+), 65 deletions(-) diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c index 9521ece3ebef..1f8c556d9013 100644 --- a/drivers/gpio/gpio-104-idi-48.c +++ b/drivers/gpio/gpio-104-idi-48.c @@ -20,6 +20,7 @@ #include #include #include +#include =20 #define IDI_48_EXTENT 8 #define MAX_NUM_IDI_48 max_num_isa_dev(IDI_48_EXTENT) @@ -33,13 +34,28 @@ static unsigned int irq[MAX_NUM_IDI_48]; module_param_hw_array(irq, uint, irq, NULL, 0); MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers"); =20 +/** + * struct idi_48_reg - device register structure + * @port0: Port 0 Inputs + * @unused: Unused + * @port1: Port 1 Inputs + * @irq: Read: IRQ Status Register/IRQ Clear + * Write: IRQ Enable/Disable + */ +struct idi_48_reg { + u8 port0[3]; + u8 unused; + u8 port1[3]; + u8 irq; +}; + /** * struct idi_48_gpio - GPIO device private data structure * @chip: instance of the gpio_chip * @lock: synchronization lock to prevent I/O race conditions * @ack_lock: synchronization lock to prevent IRQ handler race conditions * @irq_mask: input bits affected by interrupts - * @base: base port address of the GPIO device + * @reg: I/O address offset for the device registers * @cos_enb: Change-Of-State IRQ enable boundaries mask */ struct idi_48_gpio { @@ -47,7 +63,7 @@ struct idi_48_gpio { raw_spinlock_t lock; spinlock_t ack_lock; unsigned char irq_mask[6]; - void __iomem *base; + struct idi_48_reg __iomem *reg; unsigned char cos_enb; }; =20 @@ -64,39 +80,38 @@ static int idi_48_gpio_direction_input(struct gpio_chip= *chip, unsigned offset) static int idi_48_gpio_get(struct gpio_chip *chip, unsigned offset) { struct idi_48_gpio *const idi48gpio =3D gpiochip_get_data(chip); - unsigned i; - static const unsigned int register_offset[6] =3D { 0, 1, 2, 4, 5, 6 }; - void __iomem *port_addr; - unsigned mask; - - for (i =3D 0; i < 48; i +=3D 8) - if (offset < i + 8) { - port_addr =3D idi48gpio->base + register_offset[i / 8]; - mask =3D BIT(offset - i); - - return !!(ioread8(port_addr) & mask); - } - - /* The following line should never execute since offset < 48 */ - return 0; + struct idi_48_reg __iomem *const reg =3D idi48gpio->reg; + const unsigned long boundary =3D offset / 8; + const unsigned long group =3D boundary / 3; + u8 __iomem *const port_addr =3D group ? reg->port1 : reg->port0; + const unsigned long in_port =3D boundary - (group * 3); + const unsigned long mask =3D BIT(offset % 8); + + return !!(ioread8(port_addr + in_port) & mask); } =20 static int idi_48_gpio_get_multiple(struct gpio_chip *chip, unsigned long = *mask, unsigned long *bits) { struct idi_48_gpio *const idi48gpio =3D gpiochip_get_data(chip); + struct idi_48_reg __iomem *const reg =3D idi48gpio->reg; unsigned long offset; unsigned long gpio_mask; - static const size_t ports[] =3D { 0, 1, 2, 4, 5, 6 }; - void __iomem *port_addr; + unsigned long boundary; + unsigned long group; + unsigned long in_port; + u8 __iomem *port_addr; unsigned long port_state; =20 /* clear bits array to a clean slate */ bitmap_zero(bits, chip->ngpio); =20 - for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { - port_addr =3D idi48gpio->base + ports[offset / 8]; - port_state =3D ioread8(port_addr) & gpio_mask; + for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) { + boundary =3D offset / 8; + group =3D boundary / 3; + port_addr =3D group ? reg->port1 : reg->port0; + in_port =3D boundary - (group * 3); + port_state =3D ioread8(port_addr + in_port) & gpio_mask; =20 bitmap_set_value8(bits, port_state, offset); } @@ -113,30 +128,21 @@ static void idi_48_irq_mask(struct irq_data *data) struct gpio_chip *chip =3D irq_data_get_irq_chip_data(data); struct idi_48_gpio *const idi48gpio =3D gpiochip_get_data(chip); const unsigned offset =3D irqd_to_hwirq(data); - unsigned i; - unsigned mask; - unsigned boundary; + const unsigned long boundary =3D offset / 8; + const unsigned long mask =3D BIT(offset % 8); unsigned long flags; =20 - for (i =3D 0; i < 48; i +=3D 8) - if (offset < i + 8) { - mask =3D BIT(offset - i); - boundary =3D i / 8; - - idi48gpio->irq_mask[boundary] &=3D ~mask; - - if (!idi48gpio->irq_mask[boundary]) { - idi48gpio->cos_enb &=3D ~BIT(boundary); - - raw_spin_lock_irqsave(&idi48gpio->lock, flags); + idi48gpio->irq_mask[boundary] &=3D ~mask; =20 - iowrite8(idi48gpio->cos_enb, idi48gpio->base + 7); + /* Exit early if there are still input lines with IRQ unmasked */ + if (idi48gpio->irq_mask[boundary]) + return; =20 - raw_spin_unlock_irqrestore(&idi48gpio->lock, flags); - } + idi48gpio->cos_enb &=3D ~BIT(boundary); =20 - return; - } + raw_spin_lock_irqsave(&idi48gpio->lock, flags); + iowrite8(idi48gpio->cos_enb, &idi48gpio->reg->irq); + raw_spin_unlock_irqrestore(&idi48gpio->lock, flags); } =20 static void idi_48_irq_unmask(struct irq_data *data) @@ -144,32 +150,24 @@ static void idi_48_irq_unmask(struct irq_data *data) struct gpio_chip *chip =3D irq_data_get_irq_chip_data(data); struct idi_48_gpio *const idi48gpio =3D gpiochip_get_data(chip); const unsigned offset =3D irqd_to_hwirq(data); - unsigned i; - unsigned mask; - unsigned boundary; + const unsigned long boundary =3D offset / 8; + const unsigned long mask =3D BIT(offset % 8); unsigned prev_irq_mask; unsigned long flags; =20 - for (i =3D 0; i < 48; i +=3D 8) - if (offset < i + 8) { - mask =3D BIT(offset - i); - boundary =3D i / 8; - prev_irq_mask =3D idi48gpio->irq_mask[boundary]; - - idi48gpio->irq_mask[boundary] |=3D mask; + prev_irq_mask =3D idi48gpio->irq_mask[boundary]; =20 - if (!prev_irq_mask) { - idi48gpio->cos_enb |=3D BIT(boundary); + idi48gpio->irq_mask[boundary] |=3D mask; =20 - raw_spin_lock_irqsave(&idi48gpio->lock, flags); + /* Exit early if IRQ was already unmasked for this boundary */ + if (prev_irq_mask) + return; =20 - iowrite8(idi48gpio->cos_enb, idi48gpio->base + 7); + idi48gpio->cos_enb |=3D BIT(boundary); =20 - raw_spin_unlock_irqrestore(&idi48gpio->lock, flags); - } - - return; - } + raw_spin_lock_irqsave(&idi48gpio->lock, flags); + iowrite8(idi48gpio->cos_enb, &idi48gpio->reg->irq); + raw_spin_unlock_irqrestore(&idi48gpio->lock, flags); } =20 static int idi_48_irq_set_type(struct irq_data *data, unsigned flow_type) @@ -204,7 +202,7 @@ static irqreturn_t idi_48_irq_handler(int irq, void *de= v_id) =20 raw_spin_lock(&idi48gpio->lock); =20 - cos_status =3D ioread8(idi48gpio->base + 7); + cos_status =3D ioread8(&idi48gpio->reg->irq); =20 raw_spin_unlock(&idi48gpio->lock); =20 @@ -250,8 +248,8 @@ static int idi_48_irq_init_hw(struct gpio_chip *gc) struct idi_48_gpio *const idi48gpio =3D gpiochip_get_data(gc); =20 /* Disable IRQ by default */ - iowrite8(0, idi48gpio->base + 7); - ioread8(idi48gpio->base + 7); + iowrite8(0, &idi48gpio->reg->irq); + ioread8(&idi48gpio->reg->irq); =20 return 0; } @@ -273,8 +271,8 @@ static int idi_48_probe(struct device *dev, unsigned in= t id) return -EBUSY; } =20 - idi48gpio->base =3D devm_ioport_map(dev, base[id], IDI_48_EXTENT); - if (!idi48gpio->base) + idi48gpio->reg =3D devm_ioport_map(dev, base[id], IDI_48_EXTENT); + if (!idi48gpio->reg) return -ENOMEM; =20 idi48gpio->chip.label =3D name; --=20 2.36.1 From nobody Tue Apr 28 05:05:47 2026 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 71D85C43334 for ; Mon, 6 Jun 2022 14:36:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239955AbiFFOgp (ORCPT ); Mon, 6 Jun 2022 10:36:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38466 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239912AbiFFOgT (ORCPT ); Mon, 6 Jun 2022 10:36:19 -0400 Received: from mail-ot1-x32f.google.com (mail-ot1-x32f.google.com [IPv6:2607:f8b0:4864:20::32f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C6FE5131F04 for ; Mon, 6 Jun 2022 07:36:12 -0700 (PDT) Received: by mail-ot1-x32f.google.com with SMTP id r14-20020a056830418e00b0060b8da9ff75so10861913otu.11 for ; Mon, 06 Jun 2022 07:36:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Q2777MlCrWf6jryTiFZsDg5chGgCdhRgryHt5py+rzE=; b=diH8ZiHRZY9FdSSg+r7mCyQm4v39feHVxKCXY+sivbww1p9dhsxV3I0Baqr7+TeVyB irIbsOItz9rYAOnVKfXbV9utUyGnuxnVizZR8EYJYJKpaYfFug+W9+jXT6n1MjZPuWhh Q25u1XZj1vz6lp9Lc/N4vtrlskijlOh0rfAFtBrZrZpadx9i+3/L+TWzz418/sDJ4b1z knOFBRlOXeeavEYZY5KnvUIot+IuZOcyoNOzuahk8qVoca5uUPQrATdA0ha/2S/V5I0M QDov0776gS41vaqKgHOdkMP0q0S1cLW6nQXIBfshsiZcu67HACYKn+oJpywAxFg/TCGC F0bQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Q2777MlCrWf6jryTiFZsDg5chGgCdhRgryHt5py+rzE=; b=ouuzJgVrUvVWJPem7k5ms6TTxE/LXTOW6XM1+tYOYHbjzJtV15lS80kpfY04noGXFC II4Ip8WBgxFaGgxiXg4F0XiXTWIIgB1yJxRVxUdsWi+/XK8IQutP5vOiYtmnc3f9ffyo pq036CgQx/pO/mOI7xFHOO3uGWFD2BdLG1sDO2e4CC0G1H5aIkbSIQ48aJbI41ocF2ee MgorpWUYNzb58emNNj33PSpokPuCwT72R/hapDmEu8ip5G6HgpFGCoWBjkHSCXsz7mgl /29VPgS4/x7ndkd7Uec7MPqYgSFAGo0p+bcrzQx4T0Extc/Uy3wC04+gx3lG8Em7Hn2O AVyA== X-Gm-Message-State: AOAM533/2fuhC1VxoHiAjwdBAoaLEY097lJsTNPaP8hnjGA107/OLdSK xh3NXDD9/yeVHBODz/9PqvsHSw== X-Google-Smtp-Source: ABdhPJwK6LANYJEn1qcfJ4u+9iQE0OOYcHswotmAQeDnQnoBMVzE/2VQEMs7e4dwb0BqvjEG9Ip3VA== X-Received: by 2002:a9d:6250:0:b0:60b:e6cf:4942 with SMTP id i16-20020a9d6250000000b0060be6cf4942mr5669186otk.278.1654526171894; Mon, 06 Jun 2022 07:36:11 -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 u13-20020a056871008d00b000f5d4e5b9a0sm6942791oaa.2.2022.06.06.07.36.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Jun 2022 07:36:11 -0700 (PDT) From: William Breathitt Gray To: linus.walleij@linaro.org, brgl@bgdev.pl Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, William Breathitt Gray Subject: [PATCH 3/5] gpio: 104-idio-16: Implement and utilize register structures Date: Mon, 6 Jun 2022 10:33:18 -0400 Message-Id: X-Mailer: git-send-email 2.36.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Reduce magic numbers and improve code readability by implementing and utilizing named register data structures. Signed-off-by: William Breathitt Gray --- drivers/gpio/gpio-104-idio-16.c | 58 +++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-1= 6.c index 45f7ad8573e1..2f8e295f5541 100644 --- a/drivers/gpio/gpio-104-idio-16.c +++ b/drivers/gpio/gpio-104-idio-16.c @@ -19,6 +19,7 @@ #include #include #include +#include =20 #define IDIO_16_EXTENT 8 #define MAX_NUM_IDIO_16 max_num_isa_dev(IDIO_16_EXTENT) @@ -32,19 +33,42 @@ static unsigned int irq[MAX_NUM_IDIO_16]; module_param_hw_array(irq, uint, irq, NULL, 0); MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers"); =20 +/** + * struct idio_16_reg - device registers structure + * @out0_7: Read: N/A + * Write: FET Drive Outputs 0-7 + * @in0_7: Read: Isolated Inputs 0-7 + * Write: Clear Interrupt + * @irq_ctl: Read: Enable IRQ + * Write: Disable IRQ + * @unused: N/A + * @out8_15: Read: N/A + * Write: FET Drive Outputs 8-15 + * @in8_15: Read: Isolated Inputs 8-15 + * Write: N/A + */ +struct idio_16_reg { + u8 out0_7; + u8 in0_7; + u8 irq_ctl; + u8 unused; + u8 out8_15; + u8 in8_15; +}; + /** * 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 - * @base: base port address of the GPIO device + * @reg: I/O address offset for the device registers * @out_state: output bits state */ struct idio_16_gpio { struct gpio_chip chip; raw_spinlock_t lock; unsigned long irq_mask; - void __iomem *base; + struct idio_16_reg __iomem *reg; unsigned int out_state; }; =20 @@ -79,9 +103,9 @@ static int idio_16_gpio_get(struct gpio_chip *chip, unsi= gned int offset) return -EINVAL; =20 if (offset < 24) - return !!(ioread8(idio16gpio->base + 1) & mask); + return !!(ioread8(&idio16gpio->reg->in0_7) & mask); =20 - return !!(ioread8(idio16gpio->base + 5) & (mask>>8)); + return !!(ioread8(&idio16gpio->reg->in8_15) & (mask>>8)); } =20 static int idio_16_gpio_get_multiple(struct gpio_chip *chip, @@ -91,9 +115,9 @@ static int idio_16_gpio_get_multiple(struct gpio_chip *c= hip, =20 *bits =3D 0; if (*mask & GENMASK(23, 16)) - *bits |=3D (unsigned long)ioread8(idio16gpio->base + 1) << 16; + *bits |=3D (unsigned long)ioread8(&idio16gpio->reg->in0_7) << 16; if (*mask & GENMASK(31, 24)) - *bits |=3D (unsigned long)ioread8(idio16gpio->base + 5) << 24; + *bits |=3D (unsigned long)ioread8(&idio16gpio->reg->in8_15) << 24; =20 return 0; } @@ -116,9 +140,9 @@ static void idio_16_gpio_set(struct gpio_chip *chip, un= signed int offset, idio16gpio->out_state &=3D ~mask; =20 if (offset > 7) - iowrite8(idio16gpio->out_state >> 8, idio16gpio->base + 4); + iowrite8(idio16gpio->out_state >> 8, &idio16gpio->reg->out8_15); else - iowrite8(idio16gpio->out_state, idio16gpio->base); + iowrite8(idio16gpio->out_state, &idio16gpio->reg->out0_7); =20 raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); } @@ -135,9 +159,9 @@ static void idio_16_gpio_set_multiple(struct gpio_chip = *chip, idio16gpio->out_state |=3D *mask & *bits; =20 if (*mask & 0xFF) - iowrite8(idio16gpio->out_state, idio16gpio->base); + iowrite8(idio16gpio->out_state, &idio16gpio->reg->out0_7); if ((*mask >> 8) & 0xFF) - iowrite8(idio16gpio->out_state >> 8, idio16gpio->base + 4); + iowrite8(idio16gpio->out_state >> 8, &idio16gpio->reg->out8_15); =20 raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); } @@ -158,7 +182,7 @@ static void idio_16_irq_mask(struct irq_data *data) if (!idio16gpio->irq_mask) { raw_spin_lock_irqsave(&idio16gpio->lock, flags); =20 - iowrite8(0, idio16gpio->base + 2); + iowrite8(0, &idio16gpio->reg->irq_ctl); =20 raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); } @@ -177,7 +201,7 @@ static void idio_16_irq_unmask(struct irq_data *data) if (!prev_irq_mask) { raw_spin_lock_irqsave(&idio16gpio->lock, flags); =20 - ioread8(idio16gpio->base + 2); + ioread8(&idio16gpio->reg->irq_ctl); =20 raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); } @@ -212,7 +236,7 @@ static irqreturn_t idio_16_irq_handler(int irq, void *d= ev_id) =20 raw_spin_lock(&idio16gpio->lock); =20 - iowrite8(0, idio16gpio->base + 1); + iowrite8(0, &idio16gpio->reg->in0_7); =20 raw_spin_unlock(&idio16gpio->lock); =20 @@ -232,8 +256,8 @@ static int idio_16_irq_init_hw(struct gpio_chip *gc) struct idio_16_gpio *const idio16gpio =3D gpiochip_get_data(gc); =20 /* Disable IRQ by default */ - iowrite8(0, idio16gpio->base + 2); - iowrite8(0, idio16gpio->base + 1); + iowrite8(0, &idio16gpio->reg->irq_ctl); + iowrite8(0, &idio16gpio->reg->in0_7); =20 return 0; } @@ -255,8 +279,8 @@ static int idio_16_probe(struct device *dev, unsigned i= nt id) return -EBUSY; } =20 - idio16gpio->base =3D devm_ioport_map(dev, base[id], IDIO_16_EXTENT); - if (!idio16gpio->base) + idio16gpio->reg =3D devm_ioport_map(dev, base[id], IDIO_16_EXTENT); + if (!idio16gpio->reg) return -ENOMEM; =20 idio16gpio->chip.label =3D name; --=20 2.36.1 From nobody Tue Apr 28 05:05:47 2026 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 B1711CCA481 for ; Mon, 6 Jun 2022 14:36:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239932AbiFFOgZ (ORCPT ); Mon, 6 Jun 2022 10:36:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38390 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239829AbiFFOgV (ORCPT ); Mon, 6 Jun 2022 10:36:21 -0400 Received: from mail-ot1-x330.google.com (mail-ot1-x330.google.com [IPv6:2607:f8b0:4864:20::330]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9E7E31339D1 for ; Mon, 6 Jun 2022 07:36:13 -0700 (PDT) Received: by mail-ot1-x330.google.com with SMTP id r3-20020a9d5cc3000000b0060ae1789875so10856542oti.13 for ; Mon, 06 Jun 2022 07:36:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=7G/D0jrlvNgMc+Tde0XVhDy5Wvyd9twlgo7j0TICrRc=; b=niXsWsKtWaVclpeC3TuRqVL1gv/xiSdzbpfZBGPvo0JeRr1OVIO82F5WbhdFjcB//4 8By7sa2TDe1Bo0i1L7FUiFEurXjSReM/UKd30yUHG0AQNZd4wI8t/A9W78T04H4R1gbi VTgAvArN4LOqQO2k87PUZAiIyo9w98XM7MWQlvWNVno9wmPq6VaBtcMpBq7AOIuiw9nh Oyzh35dF666yIYgUnbeovalOS396uhlPO05sF+HMm55Zd+g+tMiungG0sGyVo5Itd/gL nidcFegF3kbBDl106IchsNJuUp+rfBXcHRQNxNn4KPGkO4yLipEd6Ottt09Jy2WclR4H o/KA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=7G/D0jrlvNgMc+Tde0XVhDy5Wvyd9twlgo7j0TICrRc=; b=3lzLFHBUbKwun8DkOPqbas9HKZ/Se8YIgVgKQn6vkFOJnN0bgXTo87drKUfcakUB17 E9gkSVz0JpskXX5JeHPuGr25tInFs5siK2fXwf17/UDzv6vNN8q/UdmEZ+xMndn0JZ/M HftOqkelB+acm6woxxRSQPesaTJBDhCd6uNlStTLGsoiTS+u+YqEgpyRJqyTEMqzvX22 /g3R4i4DSOet/GRW/Wzv/wMK2mK5MSwUmi6aFST3S3pCLLH/C3I7M3EalcuNKpAN3pxl kofpdzyPJRGzcMH2D8co8yGg4PgkON0g0Yedg69kn3BJ9gIHNOxH13TBgGKJjP3sWo82 DBJw== X-Gm-Message-State: AOAM533H7O2PP7OCkPBwupVe9M6g/I2/i7+OAj5pia5YOmA/j5LvG/Vf gSod4SFqeCgHZZ3MvdTRb7v0+A== X-Google-Smtp-Source: ABdhPJzkR5XFlreMYTBXKawn5WYoiJ7aAGM+h9awXDBuTc024Dti6K+voL1nOEzn8EhccycZHf8H6Q== X-Received: by 2002:a9d:4c6:0:b0:60b:537c:f4c1 with SMTP id 64-20020a9d04c6000000b0060b537cf4c1mr10492707otm.16.1654526172844; Mon, 06 Jun 2022 07:36:12 -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 u13-20020a056871008d00b000f5d4e5b9a0sm6942791oaa.2.2022.06.06.07.36.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Jun 2022 07:36:12 -0700 (PDT) From: William Breathitt Gray To: linus.walleij@linaro.org, brgl@bgdev.pl Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, William Breathitt Gray Subject: [PATCH 4/5] gpio: gpio-mm: Implement and utilize register structures Date: Mon, 6 Jun 2022 10:33:19 -0400 Message-Id: X-Mailer: git-send-email 2.36.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Reduce magic numbers and improve code readability by implementing and utilizing named register data structures. Signed-off-by: William Breathitt Gray --- drivers/gpio/gpio-gpio-mm.c | 116 ++++++++++++++++++++++-------------- 1 file changed, 72 insertions(+), 44 deletions(-) diff --git a/drivers/gpio/gpio-gpio-mm.c b/drivers/gpio/gpio-gpio-mm.c index 097a06463d01..8f67442b8715 100644 --- a/drivers/gpio/gpio-gpio-mm.c +++ b/drivers/gpio/gpio-gpio-mm.c @@ -27,6 +27,16 @@ static unsigned int num_gpiomm; module_param_hw_array(base, uint, ioport, &num_gpiomm, 0); MODULE_PARM_DESC(base, "Diamond Systems GPIO-MM base addresses"); =20 +/** + * struct i8255_reg - Intel 8255 register structure + * @port: Port A, B, and C + * @control: Control register + */ +struct i8255_reg { + u8 port[3]; + u8 control; +}; + /** * struct gpiomm_gpio - GPIO device private data structure * @chip: instance of the gpio_chip @@ -34,7 +44,7 @@ MODULE_PARM_DESC(base, "Diamond Systems GPIO-MM base addr= esses"); * @out_state: output bits state * @control: Control registers state * @lock: synchronization lock to prevent I/O race conditions - * @base: base port address of the GPIO device + * @dio: Digital I/O register groups */ struct gpiomm_gpio { struct gpio_chip chip; @@ -42,7 +52,7 @@ struct gpiomm_gpio { unsigned char out_state[6]; unsigned char control[2]; spinlock_t lock; - void __iomem *base; + struct i8255_reg __iomem *dio; }; =20 static int gpiomm_gpio_get_direction(struct gpio_chip *chip, @@ -63,32 +73,33 @@ static int gpiomm_gpio_direction_input(struct gpio_chip= *chip, { struct gpiomm_gpio *const gpiommgpio =3D gpiochip_get_data(chip); const unsigned int io_port =3D offset / 8; - const unsigned int control_port =3D io_port / 3; + const unsigned long group =3D io_port / 3; + const unsigned long port =3D io_port - (group * 3); unsigned long flags; unsigned int control; =20 spin_lock_irqsave(&gpiommgpio->lock, flags); =20 /* Check if configuring Port C */ - if (io_port =3D=3D 2 || io_port =3D=3D 5) { + if (port =3D=3D 2) { /* Port C can be configured by nibble */ if (offset % 8 > 3) { gpiommgpio->io_state[io_port] |=3D 0xF0; - gpiommgpio->control[control_port] |=3D BIT(3); + gpiommgpio->control[group] |=3D BIT(3); } else { gpiommgpio->io_state[io_port] |=3D 0x0F; - gpiommgpio->control[control_port] |=3D BIT(0); + gpiommgpio->control[group] |=3D BIT(0); } } else { gpiommgpio->io_state[io_port] |=3D 0xFF; - if (io_port =3D=3D 0 || io_port =3D=3D 3) - gpiommgpio->control[control_port] |=3D BIT(4); + if (port =3D=3D 0) + gpiommgpio->control[group] |=3D BIT(4); else - gpiommgpio->control[control_port] |=3D BIT(1); + gpiommgpio->control[group] |=3D BIT(1); } =20 - control =3D BIT(7) | gpiommgpio->control[control_port]; - iowrite8(control, gpiommgpio->base + 3 + control_port*4); + control =3D BIT(7) | gpiommgpio->control[group]; + iowrite8(control, &gpiommgpio->dio[group].control); =20 spin_unlock_irqrestore(&gpiommgpio->lock, flags); =20 @@ -100,30 +111,31 @@ static int gpiomm_gpio_direction_output(struct gpio_c= hip *chip, { struct gpiomm_gpio *const gpiommgpio =3D gpiochip_get_data(chip); const unsigned int io_port =3D offset / 8; - const unsigned int control_port =3D io_port / 3; + const unsigned long group =3D io_port / 3; + const unsigned long port =3D io_port - (group * 3); const unsigned int mask =3D BIT(offset % 8); - const unsigned int out_port =3D (io_port > 2) ? io_port + 1 : io_port; + struct i8255_reg __iomem *const dio =3D gpiommgpio->dio + group; unsigned long flags; unsigned int control; =20 spin_lock_irqsave(&gpiommgpio->lock, flags); =20 /* Check if configuring Port C */ - if (io_port =3D=3D 2 || io_port =3D=3D 5) { + if (port =3D=3D 2) { /* Port C can be configured by nibble */ if (offset % 8 > 3) { gpiommgpio->io_state[io_port] &=3D 0x0F; - gpiommgpio->control[control_port] &=3D ~BIT(3); + gpiommgpio->control[group] &=3D ~BIT(3); } else { gpiommgpio->io_state[io_port] &=3D 0xF0; - gpiommgpio->control[control_port] &=3D ~BIT(0); + gpiommgpio->control[group] &=3D ~BIT(0); } } else { gpiommgpio->io_state[io_port] &=3D 0x00; - if (io_port =3D=3D 0 || io_port =3D=3D 3) - gpiommgpio->control[control_port] &=3D ~BIT(4); + if (port =3D=3D 0) + gpiommgpio->control[group] &=3D ~BIT(4); else - gpiommgpio->control[control_port] &=3D ~BIT(1); + gpiommgpio->control[group] &=3D ~BIT(1); } =20 if (value) @@ -131,10 +143,10 @@ static int gpiomm_gpio_direction_output(struct gpio_c= hip *chip, else gpiommgpio->out_state[io_port] &=3D ~mask; =20 - control =3D BIT(7) | gpiommgpio->control[control_port]; - iowrite8(control, gpiommgpio->base + 3 + control_port*4); + control =3D BIT(7) | gpiommgpio->control[group]; + iowrite8(control, &dio->control); =20 - iowrite8(gpiommgpio->out_state[io_port], gpiommgpio->base + out_port); + iowrite8(gpiommgpio->out_state[io_port], dio->port + port); =20 spin_unlock_irqrestore(&gpiommgpio->lock, flags); =20 @@ -146,7 +158,8 @@ static int gpiomm_gpio_get(struct gpio_chip *chip, unsi= gned int offset) struct gpiomm_gpio *const gpiommgpio =3D gpiochip_get_data(chip); const unsigned int port =3D offset / 8; const unsigned int mask =3D BIT(offset % 8); - const unsigned int in_port =3D (port > 2) ? port + 1 : port; + const unsigned long group =3D port / 3; + const unsigned long in_port =3D port - (group * 3); unsigned long flags; unsigned int port_state; =20 @@ -158,29 +171,33 @@ static int gpiomm_gpio_get(struct gpio_chip *chip, un= signed int offset) return -EINVAL; } =20 - port_state =3D ioread8(gpiommgpio->base + in_port); + port_state =3D ioread8(gpiommgpio->dio[group].port + in_port); =20 spin_unlock_irqrestore(&gpiommgpio->lock, flags); =20 return !!(port_state & mask); } =20 -static const size_t ports[] =3D { 0, 1, 2, 4, 5, 6 }; - static int gpiomm_gpio_get_multiple(struct gpio_chip *chip, unsigned long = *mask, unsigned long *bits) { struct gpiomm_gpio *const gpiommgpio =3D gpiochip_get_data(chip); unsigned long offset; unsigned long gpio_mask; - void __iomem *port_addr; + unsigned long port; + unsigned long group; + unsigned long in_port; + u8 __iomem *port_addr; unsigned long port_state; =20 /* clear bits array to a clean slate */ bitmap_zero(bits, chip->ngpio); =20 - for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { - port_addr =3D gpiommgpio->base + ports[offset / 8]; + for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) { + port =3D offset / 8; + group =3D port / 3; + in_port =3D port - (group * 3); + port_addr =3D gpiommgpio->dio[group].port + in_port; port_state =3D ioread8(port_addr) & gpio_mask; =20 bitmap_set_value8(bits, port_state, offset); @@ -195,7 +212,8 @@ static void gpiomm_gpio_set(struct gpio_chip *chip, uns= igned int offset, struct gpiomm_gpio *const gpiommgpio =3D gpiochip_get_data(chip); const unsigned int port =3D offset / 8; const unsigned int mask =3D BIT(offset % 8); - const unsigned int out_port =3D (port > 2) ? port + 1 : port; + const unsigned long group =3D port / 3; + const unsigned long out_port =3D port - (group * 3); unsigned long flags; =20 spin_lock_irqsave(&gpiommgpio->lock, flags); @@ -205,7 +223,8 @@ static void gpiomm_gpio_set(struct gpio_chip *chip, uns= igned int offset, else gpiommgpio->out_state[port] &=3D ~mask; =20 - iowrite8(gpiommgpio->out_state[port], gpiommgpio->base + out_port); + iowrite8(gpiommgpio->out_state[port], + gpiommgpio->dio[group].port + out_port); =20 spin_unlock_irqrestore(&gpiommgpio->lock, flags); } @@ -217,13 +236,17 @@ static void gpiomm_gpio_set_multiple(struct gpio_chip= *chip, unsigned long offset; unsigned long gpio_mask; size_t index; - void __iomem *port_addr; + size_t group; + size_t out_port; + u8 __iomem *port_addr; unsigned long bitmask; unsigned long flags; =20 - for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { + for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) { index =3D offset / 8; - port_addr =3D gpiommgpio->base + ports[index]; + group =3D index / 3; + out_port =3D index - (group * 3); + port_addr =3D gpiommgpio->dio[group].port + out_port; =20 bitmask =3D bitmap_get_value8(bits, offset) & gpio_mask; =20 @@ -250,6 +273,17 @@ static const char *gpiomm_names[GPIOMM_NGPIO] =3D { "Port 2C2", "Port 2C3", "Port 2C4", "Port 2C5", "Port 2C6", "Port 2C7", }; =20 +static void gpiomm_init_dio(struct i8255_reg __iomem *const dio) +{ + /* Activate Mode Set; set Mode 0 output mode for Port A, B, and C */ + iowrite8(0x80, &dio->control); + + /* Initialize all GPIO to 0 */ + iowrite8(0x00, &dio->port[0]); + iowrite8(0x00, &dio->port[1]); + iowrite8(0x00, &dio->port[2]); +} + static int gpiomm_probe(struct device *dev, unsigned int id) { struct gpiomm_gpio *gpiommgpio; @@ -266,8 +300,8 @@ static int gpiomm_probe(struct device *dev, unsigned in= t id) return -EBUSY; } =20 - gpiommgpio->base =3D devm_ioport_map(dev, base[id], GPIOMM_EXTENT); - if (!gpiommgpio->base) + gpiommgpio->dio =3D devm_ioport_map(dev, base[id], GPIOMM_EXTENT); + if (!gpiommgpio->dio) return -ENOMEM; =20 gpiommgpio->chip.label =3D name; @@ -293,14 +327,8 @@ static int gpiomm_probe(struct device *dev, unsigned i= nt id) } =20 /* initialize all GPIO as output */ - iowrite8(0x80, gpiommgpio->base + 3); - iowrite8(0x00, gpiommgpio->base); - iowrite8(0x00, gpiommgpio->base + 1); - iowrite8(0x00, gpiommgpio->base + 2); - iowrite8(0x80, gpiommgpio->base + 7); - iowrite8(0x00, gpiommgpio->base + 4); - iowrite8(0x00, gpiommgpio->base + 5); - iowrite8(0x00, gpiommgpio->base + 6); + gpiomm_init_dio(&gpiommgpio->dio[0]); + gpiomm_init_dio(&gpiommgpio->dio[1]); =20 return 0; } --=20 2.36.1 From nobody Tue Apr 28 05:05:47 2026 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 A8F55C433EF for ; Mon, 6 Jun 2022 14:36:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239814AbiFFOg3 (ORCPT ); Mon, 6 Jun 2022 10:36:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38458 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239922AbiFFOgV (ORCPT ); Mon, 6 Jun 2022 10:36:21 -0400 Received: from mail-ot1-x32e.google.com (mail-ot1-x32e.google.com [IPv6:2607:f8b0:4864:20::32e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F31FF12C971 for ; Mon, 6 Jun 2022 07:36:14 -0700 (PDT) Received: by mail-ot1-x32e.google.com with SMTP id t22-20020a0568301e3600b0060b333f7a1eso10913074otr.0 for ; Mon, 06 Jun 2022 07:36:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=/Y0M6xu1GLZK7ZGrwULwxb7+/2I3xvkk3luUj/TCV1w=; b=vKVh+3cn1sqO6NjItSr8bIrjy5N6mODxNhLm7BkT42S6ggxLyfV4rUVJbuCJKgG6ux 10LO6VLEaEyKtgxi4xtzXcYwK/TtyzOYjPna7rCVZwSHpnRmIJXAenU0NYYGXMMENo5s Dy7oZb/r04kcnJuX9AlHFIeIMnuRi91XjS0uKmGSVrjsMo0HlwDJ37i5QoeowbHiSlT+ i+Z3uHg4F/HnPfW8SaxX8Hrwy+yc3GQ4oZxHIni8HcDOfj+0FFzUJC0RabmTs/c8o47j ztZ/6l/4cpQILHRsNnMhtPtz36xuCuODcZKwaVhohY0c88cfj9/yuGhtxcDNtqo89k1n TzQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/Y0M6xu1GLZK7ZGrwULwxb7+/2I3xvkk3luUj/TCV1w=; b=MTkUiA1eTo5dqOi9NszQ0/IrHQIGvJsxqmGq6RrmDMh9COD6MP+jxAJUaJxA74TIPQ xakToiAgvOpp1gh5mziYAKIPSosYn3nCu0Khwiq7D/a7oEkcP2luCLxqmlDNkSmcrGsi 0UZA7g//3l1dAj1LM7tmXQM/z4W4+tyD6GX25D3Q2AwjEg3cOCzmzQEtd2yj6ArAKHCr lIcbn/nxDa5+tt3PsZvcKZpeaufmZ69jLeKmxJ6TqhfjbfyEJZKJ+T+MrebPK+CiH6en ewk6MbQFruLUCqws7q8M63HhyZUJml7GS81w+BRpKqeUtkHnw/OimoxLXtwQdDIG8L5y LFyA== X-Gm-Message-State: AOAM5315ECK3T7IZrdB5ptp79XwA1+BrdFMYYtbU/frgQw9pIsJSV+lA vkwBQhb45SUbbFkKJbVw02iu8Kfz8LahPA== X-Google-Smtp-Source: ABdhPJw0Bv8CWzQuDCGPXI/7xIJd7fqqhe0U+v5fXafIjzmN+St0QQYWG4P8olpSVj+0p6AtjoHxKw== X-Received: by 2002:a05:6830:54d:b0:606:a7d6:f809 with SMTP id l13-20020a056830054d00b00606a7d6f809mr10494401otb.139.1654526174292; Mon, 06 Jun 2022 07:36:14 -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 u13-20020a056871008d00b000f5d4e5b9a0sm6942791oaa.2.2022.06.06.07.36.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Jun 2022 07:36:13 -0700 (PDT) From: William Breathitt Gray To: linus.walleij@linaro.org, brgl@bgdev.pl Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, William Breathitt Gray Subject: [PATCH 5/5] gpio: ws16c48: Implement and utilize register structures Date: Mon, 6 Jun 2022 10:33:20 -0400 Message-Id: <2991a4f1db1f12be499124e0059be23535894dad.1654525394.git.william.gray@linaro.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Reduce magic numbers and improve code readability by implementing and utilizing named register data structures. Signed-off-by: William Breathitt Gray --- drivers/gpio/gpio-ws16c48.c | 119 +++++++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 35 deletions(-) diff --git a/drivers/gpio/gpio-ws16c48.c b/drivers/gpio/gpio-ws16c48.c index 5078631d8014..663d4491b90f 100644 --- a/drivers/gpio/gpio-ws16c48.c +++ b/drivers/gpio/gpio-ws16c48.c @@ -17,8 +17,9 @@ #include #include #include +#include =20 -#define WS16C48_EXTENT 16 +#define WS16C48_EXTENT 10 #define MAX_NUM_WS16C48 max_num_isa_dev(WS16C48_EXTENT) =20 static unsigned int base[MAX_NUM_WS16C48]; @@ -30,6 +31,20 @@ static unsigned int irq[MAX_NUM_WS16C48]; module_param_hw_array(irq, uint, irq, NULL, 0); MODULE_PARM_DESC(irq, "WinSystems WS16C48 interrupt line numbers"); =20 +/** + * struct ws16c48_reg - device register structure + * @port: Port 0 through 5 I/O + * @int_pending: Interrupt Pending + * @page_lock: Register page (Bits 7-6) and I/O port lock (Bits 5-0) + * @pol_enab_int_id: Interrupt polarity, enable, and ID + */ +struct ws16c48_reg { + u8 port[6]; + u8 int_pending; + u8 page_lock; + u8 pol_enab_int_id[3]; +}; + /** * struct ws16c48_gpio - GPIO device private data structure * @chip: instance of the gpio_chip @@ -38,7 +53,7 @@ MODULE_PARM_DESC(irq, "WinSystems WS16C48 interrupt line = numbers"); * @lock: synchronization lock to prevent I/O race conditions * @irq_mask: I/O bits affected by interrupts * @flow_mask: IRQ flow type mask for the respective I/O bits - * @base: base port address of the GPIO device + * @reg: I/O address offset for the device registers */ struct ws16c48_gpio { struct gpio_chip chip; @@ -47,7 +62,7 @@ struct ws16c48_gpio { raw_spinlock_t lock; unsigned long irq_mask; unsigned long flow_mask; - void __iomem *base; + struct ws16c48_reg __iomem *reg; }; =20 static int ws16c48_gpio_get_direction(struct gpio_chip *chip, unsigned off= set) @@ -73,7 +88,7 @@ static int ws16c48_gpio_direction_input(struct gpio_chip = *chip, unsigned offset) =20 ws16c48gpio->io_state[port] |=3D mask; ws16c48gpio->out_state[port] &=3D ~mask; - iowrite8(ws16c48gpio->out_state[port], ws16c48gpio->base + port); + iowrite8(ws16c48gpio->out_state[port], ws16c48gpio->reg->port + port); =20 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); =20 @@ -95,7 +110,7 @@ static int ws16c48_gpio_direction_output(struct gpio_chi= p *chip, ws16c48gpio->out_state[port] |=3D mask; else ws16c48gpio->out_state[port] &=3D ~mask; - iowrite8(ws16c48gpio->out_state[port], ws16c48gpio->base + port); + iowrite8(ws16c48gpio->out_state[port], ws16c48gpio->reg->port + port); =20 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); =20 @@ -118,7 +133,7 @@ static int ws16c48_gpio_get(struct gpio_chip *chip, uns= igned offset) return -EINVAL; } =20 - port_state =3D ioread8(ws16c48gpio->base + port); + port_state =3D ioread8(ws16c48gpio->reg->port + port); =20 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); =20 @@ -131,14 +146,16 @@ static int ws16c48_gpio_get_multiple(struct gpio_chip= *chip, struct ws16c48_gpio *const ws16c48gpio =3D gpiochip_get_data(chip); unsigned long offset; unsigned long gpio_mask; - void __iomem *port_addr; + size_t index; + u8 __iomem *port_addr; unsigned long port_state; =20 /* clear bits array to a clean slate */ bitmap_zero(bits, chip->ngpio); =20 for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) { - port_addr =3D ws16c48gpio->base + offset / 8; + index =3D offset / 8; + port_addr =3D ws16c48gpio->reg->port + index; port_state =3D ioread8(port_addr) & gpio_mask; =20 bitmap_set_value8(bits, port_state, offset); @@ -166,7 +183,7 @@ static void ws16c48_gpio_set(struct gpio_chip *chip, un= signed offset, int value) ws16c48gpio->out_state[port] |=3D mask; else ws16c48gpio->out_state[port] &=3D ~mask; - iowrite8(ws16c48gpio->out_state[port], ws16c48gpio->base + port); + iowrite8(ws16c48gpio->out_state[port], ws16c48gpio->reg->port + port); =20 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); } @@ -178,13 +195,13 @@ static void ws16c48_gpio_set_multiple(struct gpio_chi= p *chip, unsigned long offset; unsigned long gpio_mask; size_t index; - void __iomem *port_addr; + u8 __iomem *port_addr; unsigned long bitmask; unsigned long flags; =20 for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) { index =3D offset / 8; - port_addr =3D ws16c48gpio->base + index; + port_addr =3D ws16c48gpio->reg->port + index; =20 /* mask out GPIO configured for input */ gpio_mask &=3D ~ws16c48gpio->io_state[index]; @@ -219,10 +236,15 @@ static void ws16c48_irq_ack(struct irq_data *data) =20 port_state =3D ws16c48gpio->irq_mask >> (8*port); =20 - iowrite8(0x80, ws16c48gpio->base + 7); - iowrite8(port_state & ~mask, ws16c48gpio->base + 8 + port); - iowrite8(port_state | mask, ws16c48gpio->base + 8 + port); - iowrite8(0xC0, ws16c48gpio->base + 7); + /* Select Register Page 2; Unlock all I/O ports */ + iowrite8(0x80, &ws16c48gpio->reg->page_lock); + + /* Clear pending interrupt */ + iowrite8(port_state & ~mask, ws16c48gpio->reg->pol_enab_int_id + port); + iowrite8(port_state | mask, ws16c48gpio->reg->pol_enab_int_id + port); + + /* Select Register Page 3; Unlock all I/O ports */ + iowrite8(0xC0, &ws16c48gpio->reg->page_lock); =20 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); } @@ -235,6 +257,7 @@ static void ws16c48_irq_mask(struct irq_data *data) const unsigned long mask =3D BIT(offset); const unsigned port =3D offset / 8; unsigned long flags; + unsigned long port_state; =20 /* only the first 3 ports support interrupts */ if (port > 2) @@ -243,10 +266,16 @@ static void ws16c48_irq_mask(struct irq_data *data) raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); =20 ws16c48gpio->irq_mask &=3D ~mask; + port_state =3D ws16c48gpio->irq_mask >> (8 * port); + + /* Select Register Page 2; Unlock all I/O ports */ + iowrite8(0x80, &ws16c48gpio->reg->page_lock); =20 - iowrite8(0x80, ws16c48gpio->base + 7); - iowrite8(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port); - iowrite8(0xC0, ws16c48gpio->base + 7); + /* Disable interrupt */ + iowrite8(port_state, ws16c48gpio->reg->pol_enab_int_id + port); + + /* Select Register Page 3; Unlock all I/O ports */ + iowrite8(0xC0, &ws16c48gpio->reg->page_lock); =20 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); } @@ -259,6 +288,7 @@ static void ws16c48_irq_unmask(struct irq_data *data) const unsigned long mask =3D BIT(offset); const unsigned port =3D offset / 8; unsigned long flags; + unsigned long port_state; =20 /* only the first 3 ports support interrupts */ if (port > 2) @@ -267,10 +297,16 @@ static void ws16c48_irq_unmask(struct irq_data *data) raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); =20 ws16c48gpio->irq_mask |=3D mask; + port_state =3D ws16c48gpio->irq_mask >> (8 * port); + + /* Select Register Page 2; Unlock all I/O ports */ + iowrite8(0x80, &ws16c48gpio->reg->page_lock); =20 - iowrite8(0x80, ws16c48gpio->base + 7); - iowrite8(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port); - iowrite8(0xC0, ws16c48gpio->base + 7); + /* Enable interrupt */ + iowrite8(port_state, ws16c48gpio->reg->pol_enab_int_id + port); + + /* Select Register Page 3; Unlock all I/O ports */ + iowrite8(0xC0, &ws16c48gpio->reg->page_lock); =20 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); } @@ -283,6 +319,7 @@ static int ws16c48_irq_set_type(struct irq_data *data, = unsigned flow_type) const unsigned long mask =3D BIT(offset); const unsigned port =3D offset / 8; unsigned long flags; + unsigned long port_state; =20 /* only the first 3 ports support interrupts */ if (port > 2) @@ -304,9 +341,16 @@ static int ws16c48_irq_set_type(struct irq_data *data,= unsigned flow_type) return -EINVAL; } =20 - iowrite8(0x40, ws16c48gpio->base + 7); - iowrite8(ws16c48gpio->flow_mask >> (8*port), ws16c48gpio->base + 8 + port= ); - iowrite8(0xC0, ws16c48gpio->base + 7); + port_state =3D ws16c48gpio->flow_mask >> (8 * port); + + /* Select Register Page 1; Unlock all I/O ports */ + iowrite8(0x40, &ws16c48gpio->reg->page_lock); + + /* Set interrupt polarity */ + iowrite8(port_state, ws16c48gpio->reg->pol_enab_int_id + port); + + /* Select Register Page 3; Unlock all I/O ports */ + iowrite8(0xC0, &ws16c48gpio->reg->page_lock); =20 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); =20 @@ -325,25 +369,26 @@ static irqreturn_t ws16c48_irq_handler(int irq, void = *dev_id) { struct ws16c48_gpio *const ws16c48gpio =3D dev_id; struct gpio_chip *const chip =3D &ws16c48gpio->chip; + struct ws16c48_reg __iomem *const reg =3D ws16c48gpio->reg; unsigned long int_pending; unsigned long port; unsigned long int_id; unsigned long gpio; =20 - int_pending =3D ioread8(ws16c48gpio->base + 6) & 0x7; + int_pending =3D ioread8(®->int_pending) & 0x7; if (!int_pending) return IRQ_NONE; =20 /* loop until all pending interrupts are handled */ do { for_each_set_bit(port, &int_pending, 3) { - int_id =3D ioread8(ws16c48gpio->base + 8 + port); + int_id =3D ioread8(reg->pol_enab_int_id + port); for_each_set_bit(gpio, &int_id, 8) generic_handle_domain_irq(chip->irq.domain, gpio + 8*port); } =20 - int_pending =3D ioread8(ws16c48gpio->base + 6) & 0x7; + int_pending =3D ioread8(®->int_pending) & 0x7; } while (int_pending); =20 return IRQ_HANDLED; @@ -369,12 +414,16 @@ static int ws16c48_irq_init_hw(struct gpio_chip *gc) { struct ws16c48_gpio *const ws16c48gpio =3D gpiochip_get_data(gc); =20 - /* Disable IRQ by default */ - iowrite8(0x80, ws16c48gpio->base + 7); - iowrite8(0, ws16c48gpio->base + 8); - iowrite8(0, ws16c48gpio->base + 9); - iowrite8(0, ws16c48gpio->base + 10); - iowrite8(0xC0, ws16c48gpio->base + 7); + /* Select Register Page 2; Unlock all I/O ports */ + iowrite8(0x80, &ws16c48gpio->reg->page_lock); + + /* Disable interrupts for all lines */ + iowrite8(0, &ws16c48gpio->reg->pol_enab_int_id[0]); + iowrite8(0, &ws16c48gpio->reg->pol_enab_int_id[1]); + iowrite8(0, &ws16c48gpio->reg->pol_enab_int_id[2]); + + /* Select Register Page 3; Unlock all I/O ports */ + iowrite8(0xC0, &ws16c48gpio->reg->page_lock); =20 return 0; } @@ -396,8 +445,8 @@ static int ws16c48_probe(struct device *dev, unsigned i= nt id) return -EBUSY; } =20 - ws16c48gpio->base =3D devm_ioport_map(dev, base[id], WS16C48_EXTENT); - if (!ws16c48gpio->base) + ws16c48gpio->reg =3D devm_ioport_map(dev, base[id], WS16C48_EXTENT); + if (!ws16c48gpio->reg) return -ENOMEM; =20 ws16c48gpio->chip.label =3D name; --=20 2.36.1