From patchwork Fri Oct 13 10:21:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 115742 Delivered-To: patch@linaro.org Received: by 10.140.22.163 with SMTP id 32csp566871qgn; Fri, 13 Oct 2017 03:35:12 -0700 (PDT) X-Google-Smtp-Source: AOwi7QCQHVG4WKBblU+NgKKeUJl4O8BgFlcju9FwdfgKKyoDAaDj7kArVRg7j9jbwWiVYP541ML7 X-Received: by 10.80.149.169 with SMTP id w38mr1518538eda.191.1507890912117; Fri, 13 Oct 2017 03:35:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1507890912; cv=none; d=google.com; s=arc-20160816; b=uYtRzCckYdS0SWgzeYfxWvI+brMVdWVfyIUD+xFjpTvi7b+IDw8nteiFqNJpq4PiSc FPtQapv2aTzfBS/oKn6dk07Yo2HyeoZewavAIdec1HutAltnLdSVr+ndQnBSAgZm+pBI Dvjq5aX+VXNtqwOCbgCo/81rOhxCIRUr+/MxI1+LWUgTMDxITy+Mijoi90pDMh+mXOqB zycA30wnGRHezUUZxJDp52qmpFWObztKTsIc1U91sx6qsF6EIbA3uS41GiNIB7BhS00+ QoQ818fFkH58ZTl2Wxaew5xEpeXqQrCB5oSE3pmbHHpxrtv9BDpNkjejrHEWgrSEVFfR nCxw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:dkim-signature:dkim-filter:arc-authentication-results; bh=LRvaZBVCuSy9DH0eTTW2AP0i5HIQ/kbA8hottzHUl9k=; b=EPOROu+NEJU29M7qhaaqMOWbzjUx/QvnxG5PnbJSd1Woq2HaP+ZvlCzkzuG9ssWcK3 PYLbC5nYRUpL6OctBfOQhsRx4VEEb9Bb3vsjA3Pox2rDaReSKIoR6qs3eAeVo+ovv0jU oQgNfhKUM9tYilbgqLmJC97dCvMqYOLKKdGv/RVdSYv53uzhBM/TQVsDjE0/goBm6pLW v7KqUN7dbz5BBv1AJrJHXIgPP4NLGJv+mwbty/YP3E5inRPcexe54lvv/rJWKhOFCfe5 QuoebEwSiGSD7WeHzL/BYQTuBIAU4qcrXXMClXdqMB3dgTmz3fN0fd0dzmH+nitq/c4m Xw0g== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@nifty.com header.s=dec2015msa header.b=ZduvnNvl; spf=pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de Return-Path: Received: from lists.denx.de (dione.denx.de. [81.169.180.215]) by mx.google.com with ESMTP id f9si743975edf.121.2017.10.13.03.35.11; Fri, 13 Oct 2017 03:35:12 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) client-ip=81.169.180.215; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@nifty.com header.s=dec2015msa header.b=ZduvnNvl; spf=pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by lists.denx.de (Postfix, from userid 105) id 99796C21D99; Fri, 13 Oct 2017 10:28:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 070D6C2202C; Fri, 13 Oct 2017 10:22:54 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 8545CC21F06; Fri, 13 Oct 2017 10:22:41 +0000 (UTC) Received: from conuserg-12.nifty.com (conuserg-12.nifty.com [210.131.2.79]) by lists.denx.de (Postfix) with ESMTPS id BF807C21F33 for ; Fri, 13 Oct 2017 10:22:39 +0000 (UTC) Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-12.nifty.com with ESMTP id v9DAMGx5009903; Fri, 13 Oct 2017 19:22:18 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-12.nifty.com v9DAMGx5009903 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1507890138; bh=S2xBLijxD/rWWknh3FN+PQfjznB9hMJ3GEOi/ueGRmg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZduvnNvlbAWDnAYSiFxbWGIgixF2MCVV1/h+HIBEgdnGLbmcA2DvwObQYJwL+GkZn qthPLYkUomrcbzbX8qJbI1Bre0peoqNA8tIfis7wobr14PikyP404gKTtmsvSBnAt5 pfIqY+XXZCj/i3/WTrQZr1pr24MGbtL+e1bWL1UeydNre7R7oke0poPcJcrJTRlnmS lyVci5yEbFPvvmsgRspWhy0JxS1cLKjVD1qNBs+gWXr+4JvA4HkJxYlnWu7Zv/GmQW 4KEIE1P+fNhBkFxLDnW/ybWbZpIDNl3chvnaP1TXz7tw9v3H0j6LALwZpbdnbPBxNo D0/QExJtCUFgw== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: u-boot@lists.denx.de Date: Fri, 13 Oct 2017 19:21:51 +0900 Message-Id: <1507890129-1543-3-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1507890129-1543-1-git-send-email-yamada.masahiro@socionext.com> References: <1507890129-1543-1-git-send-email-yamada.masahiro@socionext.com> Subject: [U-Boot] [PATCH 02/20] gpio: uniphier: rework single device node model X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" First, I implemented this driver as per-bank model, but it was a design mistake. - There are 31 banks in the maximum case. It is painful to add so many nodes to DT. - The IRQ control registers are shared between banks. Per-bank design is a problem for Linux. The counterpart for Linux turned around to the single node model. Rework based on the driver for Linux. Signed-off-by: Masahiro Yamada --- drivers/gpio/gpio-uniphier.c | 140 +++++++++++++++++++++++++++---------------- 1 file changed, 89 insertions(+), 51 deletions(-) diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c index c11e953..107c3fc 100644 --- a/drivers/gpio/gpio-uniphier.c +++ b/drivers/gpio/gpio-uniphier.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Socionext Inc. + * Copyright (C) 2016-2017 Socionext Inc. * Author: Masahiro Yamada * * SPDX-License-Identifier: GPL-2.0+ @@ -11,73 +11,123 @@ #include #include #include +#include #include -#define UNIPHIER_GPIO_PORTS_PER_BANK 8 +#define UNIPHIER_GPIO_LINES_PER_BANK 8 -#define UNIPHIER_GPIO_REG_DATA 0 /* data */ -#define UNIPHIER_GPIO_REG_DIR 4 /* direction (1:in, 0:out) */ +#define UNIPHIER_GPIO_PORT_DATA 0x0 /* data */ +#define UNIPHIER_GPIO_PORT_DIR 0x4 /* direction (1:in, 0:out) */ +#define UNIPHIER_GPIO_IRQ_EN 0x90 /* irq enable */ struct uniphier_gpio_priv { - void __iomem *base; - char bank_name[16]; + void __iomem *regs; }; -static void uniphier_gpio_offset_write(struct udevice *dev, unsigned offset, - unsigned reg, int value) +static unsigned int uniphier_gpio_bank_to_reg(unsigned int bank) +{ + unsigned int reg; + + reg = (bank + 1) * 8; + + /* + * Unfortunately, the GPIO port registers are not contiguous because + * offset 0x90-0x9f is used for IRQ. Add 0x10 when crossing the region. + */ + if (reg >= UNIPHIER_GPIO_IRQ_EN) + reg += 0x10; + + return reg; +} + +static void uniphier_gpio_get_bank_and_mask(unsigned int offset, + unsigned int *bank, u32 *mask) +{ + *bank = offset / UNIPHIER_GPIO_LINES_PER_BANK; + *mask = BIT(offset % UNIPHIER_GPIO_LINES_PER_BANK); +} + +static void uniphier_gpio_reg_update(struct uniphier_gpio_priv *priv, + unsigned int reg, u32 mask, u32 val) { - struct uniphier_gpio_priv *priv = dev_get_priv(dev); u32 tmp; - tmp = readl(priv->base + reg); - if (value) - tmp |= BIT(offset); - else - tmp &= ~BIT(offset); - writel(tmp, priv->base + reg); + tmp = readl(priv->regs + reg); + tmp &= ~mask; + tmp |= mask & val; + writel(tmp, priv->regs + reg); } -static int uniphier_gpio_offset_read(struct udevice *dev, unsigned offset, - unsigned reg) +static void uniphier_gpio_bank_write(struct udevice *dev, unsigned int bank, + unsigned int reg, u32 mask, u32 val) { struct uniphier_gpio_priv *priv = dev_get_priv(dev); - return !!(readl(priv->base + reg) & BIT(offset)); + if (!mask) + return; + + uniphier_gpio_reg_update(priv, uniphier_gpio_bank_to_reg(bank) + reg, + mask, val); } -static int uniphier_gpio_direction_input(struct udevice *dev, unsigned offset) +static void uniphier_gpio_offset_write(struct udevice *dev, unsigned int offset, + unsigned int reg, int val) { - uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DIR, 1); + unsigned int bank; + u32 mask; - return 0; + uniphier_gpio_get_bank_and_mask(offset, &bank, &mask); + + uniphier_gpio_bank_write(dev, bank, reg, mask, val ? mask : 0); } -static int uniphier_gpio_direction_output(struct udevice *dev, unsigned offset, - int value) +static int uniphier_gpio_offset_read(struct udevice *dev, + unsigned int offset, unsigned int reg) { - uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DATA, value); - uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DIR, 0); + struct uniphier_gpio_priv *priv = dev_get_priv(dev); + unsigned int bank, reg_offset; + u32 mask; - return 0; + uniphier_gpio_get_bank_and_mask(offset, &bank, &mask); + reg_offset = uniphier_gpio_bank_to_reg(bank) + reg; + + return !!(readl(priv->regs + reg_offset) & mask); } -static int uniphier_gpio_get_value(struct udevice *dev, unsigned offset) +static int uniphier_gpio_get_function(struct udevice *dev, unsigned int offset) { - return uniphier_gpio_offset_read(dev, offset, UNIPHIER_GPIO_REG_DATA); + return uniphier_gpio_offset_read(dev, offset, UNIPHIER_GPIO_PORT_DIR) ? + GPIOF_INPUT : GPIOF_OUTPUT; } -static int uniphier_gpio_set_value(struct udevice *dev, unsigned offset, - int value) +static int uniphier_gpio_direction_input(struct udevice *dev, + unsigned int offset) { - uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DATA, value); + uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_PORT_DIR, 1); return 0; } -static int uniphier_gpio_get_function(struct udevice *dev, unsigned offset) +static int uniphier_gpio_direction_output(struct udevice *dev, + unsigned int offset, int value) { - return uniphier_gpio_offset_read(dev, offset, UNIPHIER_GPIO_REG_DIR) ? - GPIOF_INPUT : GPIOF_OUTPUT; + uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_PORT_DATA, value); + uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_PORT_DIR, 0); + + return 0; +} + +static int uniphier_gpio_get_value(struct udevice *dev, unsigned int offset) +{ + return uniphier_gpio_offset_read(dev, offset, UNIPHIER_GPIO_PORT_DATA); +} + +static int uniphier_gpio_set_value(struct udevice *dev, + unsigned int offset, int value) +{ + uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_PORT_DATA, value); + + return 0; } static const struct dm_gpio_ops uniphier_gpio_ops = { @@ -93,40 +143,28 @@ static int uniphier_gpio_probe(struct udevice *dev) struct uniphier_gpio_priv *priv = dev_get_priv(dev); struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); fdt_addr_t addr; - unsigned int tmp; addr = devfdt_get_addr(dev); if (addr == FDT_ADDR_T_NONE) return -EINVAL; - priv->base = devm_ioremap(dev, addr, SZ_8); - if (!priv->base) + priv->regs = devm_ioremap(dev, addr, SZ_512); + if (!priv->regs) return -ENOMEM; - uc_priv->gpio_count = UNIPHIER_GPIO_PORTS_PER_BANK; - - tmp = (addr & 0xfff); - - /* Unfortunately, there is a register hole at offset 0x90-0x9f. */ - if (tmp > 0x90) - tmp -= 0x10; - - snprintf(priv->bank_name, sizeof(priv->bank_name) - 1, - "port%d-", (tmp - 8) / 8); - - uc_priv->bank_name = priv->bank_name; + uc_priv->gpio_count = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), + "ngpios", 0); return 0; } -/* .data = the number of GPIO banks */ static const struct udevice_id uniphier_gpio_match[] = { { .compatible = "socionext,uniphier-gpio" }, { /* sentinel */ } }; U_BOOT_DRIVER(uniphier_gpio) = { - .name = "uniphier_gpio", + .name = "uniphier-gpio", .id = UCLASS_GPIO, .of_match = uniphier_gpio_match, .probe = uniphier_gpio_probe,