From patchwork Wed Feb 14 16:24:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Th=C3=A9o_Lebrun?= X-Patchwork-Id: 13556853 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BBD51C48BEC for ; Wed, 14 Feb 2024 17:31:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References:Message-Id :MIME-Version:Subject:Date:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=VltWjvdwNQHxQ6syNIennmMrgMcRhRVN6BKXb8ZRTiA=; b=pS3niATXHCKQVh LoyVogEp4fN1/kogYV8HKzE+EbZdMlxt2/7asRxKOrbL77qgCDeHk5Os9KBO2+puW1Vrz/JYpraVY B8uTnmpMIACHZ6hlseYRRfX4Jl1Nu6u5ni/knj427Jyun1dAL1pXy4tEgQxDQaFp1uT2zXqre7qrH EyGb9aLyXq50anPf9c1Mz0iB5dOG/ZvxCusFA8Ku0PErvSzffX+AcmORqxL6GvHIQqjz/IMS/vL6i 0uHHGk+NEbkTetxfUe66RubXUMIqjjj/nJ8lY+BfQYxYUUV6k0WT/h+17xz6G+YP7i251UqwPpk6f rzEFUqTy8sV1GQF2jmcg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1raJ5r-0000000Djw3-3kSR; Wed, 14 Feb 2024 17:30:47 +0000 Received: from relay3-d.mail.gandi.net ([2001:4b98:dc4:8::223]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1raI47-0000000DTxP-0D5h for linux-arm-kernel@lists.infradead.org; Wed, 14 Feb 2024 16:24:57 +0000 Received: by mail.gandi.net (Postfix) with ESMTPSA id D2B3860007; Wed, 14 Feb 2024 16:24:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1707927893; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=oJ14tHqSqLHFtg6avp0X1Ritv/bgPHCct9WWR86lzjo=; b=j9wNif49vyuB2N1ghzZdkYvXJqOuDxV5K/Bldfi6wun0Dm4St/QW8qVvmsniMdQNAVjdux fdjzOJeQ8JFIcPHNUnSazEhL49lZEUk3oQLWhS2JDjbItD/P5snFOqYU4/0lkF7dC+l1V+ sTaPtDu38kiFYbHT/4QoqFLwDIw0fN5kbgUms2Sfv89z5dSfYEyMqvsaJrN4KTpWhufaD2 UGHCNDOPeAw1R0Q039aeKRlxcjaAZcWwsAneDh46npdB3nUHBguxcwYkzrDQIhMKThYDVU OPTfx7eZilXMG6v7fqVRljHF77nY1TZFxer30Y4qof4lz5kG/tizbRvwBCKpOg== From: =?utf-8?q?Th=C3=A9o_Lebrun?= Date: Wed, 14 Feb 2024 17:24:05 +0100 Subject: [PATCH 12/23] gpio: nomadik: request dynamic ID allocation MIME-Version: 1.0 Message-Id: <20240214-mbly-gpio-v1-12-f88c0ccf372b@bootlin.com> References: <20240214-mbly-gpio-v1-0-f88c0ccf372b@bootlin.com> In-Reply-To: <20240214-mbly-gpio-v1-0-f88c0ccf372b@bootlin.com> To: Linus Walleij , Bartosz Golaszewski , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Philipp Zabel , Thomas Bogendoerfer Cc: linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mips@vger.kernel.org, Gregory CLEMENT , Vladimir Kondratiev , Thomas Petazzoni , Tawfik Bayouk , =?utf-8?q?Th=C3=A9o_Lebrun?= X-Mailer: b4 0.12.4 X-GND-Sasl: theo.lebrun@bootlin.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240214_082455_488833_A0734E6F X-CRM114-Status: GOOD ( 22.57 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Move away from statically allocated GPIO IDs. Switch to dynamic ID allocation. Static IDs are deprecated because they cause issues when multiple GPIO controllers are to be found on the same platform. Add a bit of complexity to do pin number -> GPIO chip + offset. Previously, bank number and offsets were retrieved using division and remainder (bank size being constant 32). Now, to get the pin number matching a bank base, we must know the sum of ngpios of previous banks. This is done in find_nmk_gpio_from_pin() which also exposes the offset inside the bank. Also remove the assumption that bank sizes are constant. Instead of using NMK_GPIO_PER_CHIP as bank size, use nmk_gpio_chips[i]->ngpio. Signed-off-by: Théo Lebrun --- drivers/gpio/gpio-nomadik.c | 2 +- drivers/pinctrl/nomadik/pinctrl-nomadik.c | 55 +++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/gpio/gpio-nomadik.c index e39477e1a58f..8d47aef8d2c4 100644 --- a/drivers/gpio/gpio-nomadik.c +++ b/drivers/gpio/gpio-nomadik.c @@ -516,7 +516,7 @@ struct nmk_gpio_chip *nmk_gpio_populate_chip(struct device_node *np, nmk_chip->bank = id; chip = &nmk_chip->chip; - chip->base = id * NMK_GPIO_PER_CHIP; + chip->base = -1; chip->ngpio = NMK_GPIO_PER_CHIP; chip->label = dev_name(&gpio_pdev->dev); chip->parent = &gpio_pdev->dev; diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c index 8099dd947701..c7693fbc0484 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c @@ -530,25 +530,33 @@ static int nmk_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector return 0; } -static struct nmk_gpio_chip *find_nmk_gpio_from_pin(unsigned int pin) +/* This makes the mapping from pin number to a GPIO chip. We also return the pin + * offset in the GPIO chip for convenience (and to avoid a second loop). + */ +static struct nmk_gpio_chip *find_nmk_gpio_from_pin(unsigned int pin, + unsigned int *offset) { - int i; + int i, j = 0; struct nmk_gpio_chip *nmk_gpio; + /* We assume that pins are allocated in bank order. */ for (i = 0; i < NMK_MAX_BANKS; i++) { nmk_gpio = nmk_gpio_chips[i]; if (!nmk_gpio) continue; - if (pin >= nmk_gpio->chip.base && - pin < nmk_gpio->chip.base + nmk_gpio->chip.ngpio) + if (pin >= j && pin < j + nmk_gpio->chip.ngpio) { + if (offset) + *offset = pin - j; return nmk_gpio; + } + j += nmk_gpio->chip.ngpio; } return NULL; } static struct gpio_chip *find_gc_from_pin(unsigned int pin) { - struct nmk_gpio_chip *nmk_gpio = find_nmk_gpio_from_pin(pin); + struct nmk_gpio_chip *nmk_gpio = find_nmk_gpio_from_pin(pin, NULL); if (nmk_gpio) return &nmk_gpio->chip; @@ -903,8 +911,19 @@ static int nmk_pmx_set(struct pinctrl_dev *pctldev, unsigned int function, * Then mask the pins that need to be sleeping now when we're * switching to the ALT C function. */ - for (i = 0; i < g->grp.npins; i++) - slpm[g->grp.pins[i] / NMK_GPIO_PER_CHIP] &= ~BIT(g->grp.pins[i]); + for (i = 0; i < g->grp.npins; i++) { + struct nmk_gpio_chip *nmk_chip; + + nmk_chip = find_nmk_gpio_from_pin(g->grp.pins[i], NULL); + if (!nmk_chip) { + dev_err(npct->dev, + "invalid pin offset %d in group %s at index %d\n", + g->grp.pins[i], g->grp.name, i); + goto out_pre_slpm_init; + } + + slpm[nmk_chip->bank] &= ~BIT(g->grp.pins[i]); + } nmk_gpio_glitch_slpm_init(slpm); } @@ -912,7 +931,7 @@ static int nmk_pmx_set(struct pinctrl_dev *pctldev, unsigned int function, struct nmk_gpio_chip *nmk_chip; unsigned int bit; - nmk_chip = find_nmk_gpio_from_pin(g->grp.pins[i]); + nmk_chip = find_nmk_gpio_from_pin(g->grp.pins[i], &bit); if (!nmk_chip) { dev_err(npct->dev, "invalid pin offset %d in group %s at index %d\n", @@ -923,7 +942,6 @@ static int nmk_pmx_set(struct pinctrl_dev *pctldev, unsigned int function, g->grp.pins[i], g->altsetting); clk_enable(nmk_chip->clk); - bit = g->grp.pins[i] % NMK_GPIO_PER_CHIP; /* * If the pin is switching to altfunc, and there was an * interrupt installed on it which has been lazy disabled, @@ -954,17 +972,18 @@ static int nmk_pmx_set(struct pinctrl_dev *pctldev, unsigned int function, ret = 0; out_glitch: - if (glitch) { + if (glitch) nmk_gpio_glitch_slpm_restore(slpm); +out_pre_slpm_init: + if (glitch) spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); - } return ret; } static int nmk_gpio_request_enable(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, - unsigned int offset) + unsigned int pin) { struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); struct nmk_gpio_chip *nmk_chip; @@ -982,10 +1001,11 @@ static int nmk_gpio_request_enable(struct pinctrl_dev *pctldev, chip = range->gc; nmk_chip = gpiochip_get_data(chip); - dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset); + dev_dbg(npct->dev, "enable pin %u as GPIO\n", pin); + + find_nmk_gpio_from_pin(pin, &bit); clk_enable(nmk_chip->clk); - bit = offset % NMK_GPIO_PER_CHIP; /* There is no glitch when converting any pin to GPIO */ __nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO); clk_disable(nmk_chip->clk); @@ -995,11 +1015,11 @@ static int nmk_gpio_request_enable(struct pinctrl_dev *pctldev, static void nmk_gpio_disable_free(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, - unsigned int offset) + unsigned int pin) { struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); - dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset); + dev_dbg(npct->dev, "disable pin %u as GPIO\n", pin); /* Set the pin to some default state, GPIO is usually default */ } @@ -1040,7 +1060,7 @@ static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin, int pull, slpm, output, val, i; bool lowemi, gpiomode, sleep; - nmk_chip = find_nmk_gpio_from_pin(pin); + nmk_chip = find_nmk_gpio_from_pin(pin, &bit); if (!nmk_chip) { dev_err(npct->dev, "invalid pin offset %d\n", pin); @@ -1098,7 +1118,6 @@ static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin, lowemi ? "on" : "off"); clk_enable(nmk_chip->clk); - bit = pin % NMK_GPIO_PER_CHIP; if (gpiomode) /* No glitch when going to GPIO mode */ __nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO);