From patchwork Tue Oct 29 21:08:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suneel Garapati X-Patchwork-Id: 1186316 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="f9R7iR7s"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 472ky24ycZz9s7T for ; Wed, 30 Oct 2019 08:20:10 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 2DDD1C21DD4; Tue, 29 Oct 2019 21:13: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=FREEMAIL_FROM, RCVD_IN_MSPIKE_H2, 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 58295C21DFB; Tue, 29 Oct 2019 21:09:37 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 9D9E5C21E0F; Tue, 29 Oct 2019 21:08:56 +0000 (UTC) Received: from mail-pf1-f171.google.com (mail-pf1-f171.google.com [209.85.210.171]) by lists.denx.de (Postfix) with ESMTPS id A78CDC21E30 for ; Tue, 29 Oct 2019 21:08:51 +0000 (UTC) Received: by mail-pf1-f171.google.com with SMTP id q26so6886875pfn.11 for ; Tue, 29 Oct 2019 14:08:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=nBUFiDW35JU5sE/h1J4Cx4L+FEkCm+hqwpEnkYeXhKk=; b=f9R7iR7sUocVjm+QJDlFeZHsk5iRBb4AvH5uDWRU2eKdb4QhrekMfzDGUrpeI6HaRG IppUfX7WXfVLCUwL6QsmZok1Zux5ZbXPzRBQ40q7zmBc55fmlxFYMKPaPoK+W2ceEKW7 mYfg3PZj330YHywOnzsLvf+nZZYolFm++CsL7tZQAYFpHLzHsIlxe1Dcs7X1hjf0qjFX Q5PuMzfodAXFuG55ENN12M22ZeRUmb4bGA8DoU+AosJt8lQaHy7kxm6c/ApgWb00x1Th z68eakMZrsBfreIsv/Zq42jVPwy2/aTnoh7unD2s7530aoA7MHwrU1qT8YDd8xXKlgO5 zxXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=nBUFiDW35JU5sE/h1J4Cx4L+FEkCm+hqwpEnkYeXhKk=; b=AWPB7pISK9055rJG+wU90TZryjHAQWbdV2yJBrO7m2pmzkdLtLXbc5tuIIX+quKo9/ G7K7zqH91xJz+HgguNnGqahNphI3kerU6HCJ5cSM2W8bBpjfOsloOKFlSQISGSiz9DJM Ps323ztSi6Gspxx3ryvV6Eyw8/lhnlz4w9G6adbZqLaHVyS/fQ9pDb1gQOUGlEJ6CnsM TQX0WkO00FHt9GbLnRzB/gaO77htMmgZSBJJ4usRUNfCmYo2GJDlG0atgVC7JTQDzf5V TDB/sIA2+/a5HKqRVjgnv3wSwghV1GnkDU9Xo9mf6eWtJkv0GTig9T72zdbsXbY2Fr/l K+HQ== X-Gm-Message-State: APjAAAWKUhUhNqvbus4+a4mrtPHBQX3jAoxXb6kKcr7hCXkhvh/kSK/H GZb7kIpz2+5MR5NFxwiakrt39lp1 X-Google-Smtp-Source: APXvYqzdIDrrFRWUOsCSJghD3POVEJsdtVK1ajXgJn7yO1sRXfp0Z6gL38v/ooTAnZtx2DKca/l6Rw== X-Received: by 2002:a63:fe16:: with SMTP id p22mr988322pgh.318.1572383330027; Tue, 29 Oct 2019 14:08:50 -0700 (PDT) Received: from suneel.hsd1.ca.comcast.net ([2601:641:4000:c9c0:7044:5eef:7096:2413]) by smtp.gmail.com with ESMTPSA id q3sm131160pgj.54.2019.10.29.14.08.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Oct 2019 14:08:49 -0700 (PDT) From: Suneel Garapati To: u-boot Date: Tue, 29 Oct 2019 14:08:11 -0700 Message-Id: <20191029210821.1954-20-suneelglinux@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191029210821.1954-1-suneelglinux@gmail.com> References: <20191029210821.1954-1-suneelglinux@gmail.com> MIME-Version: 1.0 Cc: Tom Rini , Matthias Brugger , Joe Hershberger , Prasun Kapoor , Maen Suleiman , Chandrakala Chavva , Zi Shen Lim , Stefan Roese , Chris Packham Subject: [U-Boot] [RFC PATCH 19/29] drivers: gpio: add GPIO controller driver for OcteonTX 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: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: Suneel Garapati Adds support for GPIO controllers found on OcteonTX or OcteonTX2 SoC platforms. Signed-off-by: Aaron Williams Signed-off-by: Suneel Garapati --- drivers/gpio/Kconfig | 7 ++ drivers/gpio/Makefile | 1 + drivers/gpio/octeontx_gpio.c | 218 +++++++++++++++++++++++++++++++++++ 3 files changed, 226 insertions(+) create mode 100644 drivers/gpio/octeontx_gpio.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index c1ad5d64a3..91265180d3 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -276,6 +276,13 @@ config PIC32_GPIO help Say yes here to support Microchip PIC32 GPIOs. +config OCTEONTX_GPIO + bool "OcteonTX GPIO driver" + depends on DM_GPIO && (ARCH_OCTEONTX || ARCH_OCTEONTX2) + default y + help + Say yes here to support OcteonTX GPIOs. + config STM32_GPIO bool "ST STM32 GPIO driver" depends on DM_GPIO && (STM32 || ARCH_STM32MP) diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ccc49e2eb0..d7651bff4b 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_HIKEY_GPIO) += hi6220_gpio.o obj-$(CONFIG_HSDK_CREG_GPIO) += hsdk-creg-gpio.o obj-$(CONFIG_IMX_RGPIO2P) += imx_rgpio2p.o obj-$(CONFIG_PIC32_GPIO) += pic32_gpio.o +obj-$(CONFIG_OCTEONTX_GPIO) += octeontx_gpio.o obj-$(CONFIG_MVEBU_GPIO) += mvebu_gpio.o obj-$(CONFIG_MSM_GPIO) += msm_gpio.o obj-$(CONFIG_$(SPL_)PCF8575_GPIO) += pcf8575_gpio.o diff --git a/drivers/gpio/octeontx_gpio.c b/drivers/gpio/octeontx_gpio.c new file mode 100644 index 0000000000..d012044c47 --- /dev/null +++ b/drivers/gpio/octeontx_gpio.c @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * https://spdx.org/licenses + * + * (C) Copyright 2011 + * eInfochips Ltd. + * Written-by: Ajay Bhargav + * + * (C) Copyright 2010 + * Marvell Semiconductor + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/** Returns the bit value to write or read based on the offset */ +#define GPIO_BIT(x) (1ULL << ((x) & 0x3f)) + +#define GPIO_RX_DAT (0x0) +#define GPIO_TX_SET (0x8) +#define GPIO_TX_CLR (0x10) +#define GPIO_CONST (0x90) +#define GPIO_RX1_DAT (0x1400) +#define GPIO_TX1_SET (0x1408) +#define GPIO_TX1_CLR (0x1410) + +/** Returns the offset to the output register based on the offset and value */ +#define GPIO_TX_REG(offset, value) \ + ((offset) >= 64 ? ((value) ? GPIO_TX1_SET : GPIO_TX1_CLR) : \ + ((value) ? GPIO_TX_SET : GPIO_TX_CLR)) + +/** Returns the offset to the input data register based on the offset */ +#define GPIO_RX_DAT_REG(offset) (((offset) >= 64) ? GPIO_RX1_DAT : GPIO_RX_DAT) + +/** Returns the bit configuration register based on the offset */ +#define GPIO_BIT_CFG(x) (0x400 + 8 * (x)) +#define GPIO_BIT_CFG_FN(x) (((x) >> 16) & 0x3ff) +#define GPIO_BIT_CFG_TX_OE(x) ((x) & 0x1) +#define GPIO_BIT_CFG_RX_DAT(x) ((x) & 0x1) + +/** PCI ID on NCB bus */ +#define PCI_DEVICE_ID_OCTEONTX_GPIO 0xa00a + +union gpio_const { + u64 u; + struct { + u64 gpios:8; /** Number of GPIOs implemented */ + u64 pp:8; /** Number of PP vectors */ + u64:48; /* Reserved */ + } s; +}; + +struct octeontx_gpio { + void __iomem *baseaddr; +}; + +static int octeontx_gpio_dir_input(struct udevice *dev, unsigned int offset) +{ + struct octeontx_gpio *gpio = dev_get_priv(dev); + + debug("%s(%s, %u)\n", __func__, dev->name, offset); + clrbits_le64(gpio->baseaddr + GPIO_BIT_CFG(offset), + (0x3ffUL << 16) | 4UL | 2UL | 1UL); + return 0; +} + +static int octeontx_gpio_dir_output(struct udevice *dev, unsigned int offset, + int value) +{ + struct octeontx_gpio *gpio = dev_get_priv(dev); + + debug("%s(%s, %u, %d)\n", __func__, dev->name, offset, value); + writeq(GPIO_BIT(offset), gpio->baseaddr + GPIO_TX_REG(offset, value)); + + clrsetbits_le64(gpio->baseaddr + GPIO_BIT_CFG(offset), + ((0x3ffUL << 16) | 4UL), 1UL); + return 0; +} + +static int octeontx_gpio_get_value(struct udevice *dev, + unsigned int offset) +{ + struct octeontx_gpio *gpio = dev_get_priv(dev); + u64 reg = readq(gpio->baseaddr + GPIO_RX_DAT_REG(offset)); + + debug("%s(%s, %u): value: %d\n", __func__, dev->name, offset, + !!(reg & GPIO_BIT(offset))); + + return !!(reg & GPIO_BIT(offset)); +} + +static int octeontx_gpio_set_value(struct udevice *dev, + unsigned int offset, int value) +{ + struct octeontx_gpio *gpio = dev_get_priv(dev); + + debug("%s(%s, %u, %d)\n", __func__, dev->name, offset, value); + writeq(GPIO_BIT(offset), gpio->baseaddr + GPIO_TX_REG(offset, value)); + + return 0; +} + +static int octeontx_gpio_get_function(struct udevice *dev, + unsigned int offset) +{ + struct octeontx_gpio *gpio = dev_get_priv(dev); + u64 pinsel = readl(gpio->baseaddr + GPIO_BIT_CFG(offset)); + + debug("%s(%s, %u): pinsel: 0x%llx\n", __func__, dev->name, offset, + pinsel); + if (GPIO_BIT_CFG_FN(pinsel)) + return GPIOF_FUNC; + else if (GPIO_BIT_CFG_TX_OE(pinsel)) + return GPIOF_OUTPUT; + else + return GPIOF_INPUT; +} + +static int octeontx_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, + struct ofnode_phandle_args *args) +{ + if (args->args_count < 1) + return -EINVAL; + + desc->offset = args->args[0]; + desc->flags = 0; + if (args->args_count > 1) { + if (args->args[1] & GPIO_ACTIVE_LOW) + desc->flags |= GPIOD_ACTIVE_LOW; + /* In the future add tri-state flag support */ + } + return 0; +} + +static const struct dm_gpio_ops octeontx_gpio_ops = { + .direction_input = octeontx_gpio_dir_input, + .direction_output = octeontx_gpio_dir_output, + .get_value = octeontx_gpio_get_value, + .set_value = octeontx_gpio_set_value, + .get_function = octeontx_gpio_get_function, + .xlate = octeontx_gpio_xlate, +}; + +static int octeontx_gpio_probe(struct udevice *dev) +{ + pci_dev_t bdf = dm_pci_get_bdf(dev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct octeontx_gpio *priv = dev_get_priv(dev); + union gpio_const gpio_const; + char *end; + const char *status; + + status = ofnode_read_string(dev->node, "status"); + + if (status && !strncmp(status, "ok", 2)) { + debug("%s(%s): GPIO device disabled in device tree\n", + __func__, dev->name); + return -1; + } + + dev->req_seq = PCI_FUNC(bdf); + priv->baseaddr = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + PCI_REGION_MEM); + + if (!priv->baseaddr) { + debug("%s(%s): Could not get base address\n", + __func__, dev->name); + return -1; + } + + gpio_const.u = readq(priv->baseaddr + GPIO_CONST); + + debug("%s(%s): base address: %p, of_offset: %ld, pin count: %d\n", + __func__, dev->name, priv->baseaddr, dev->node.of_offset, + gpio_const.s.gpios); + + uc_priv->gpio_count = gpio_const.s.gpios; + uc_priv->bank_name = strdup(dev->name); + end = strchr(uc_priv->bank_name, '@'); + end[0] = 'A' + dev->seq; + end[1] = '\0'; + + return 0; +} + +static const struct udevice_id octeontx_gpio_ids[] = { + { .compatible = "cavium,thunder-8890-gpio" }, + { } +}; + +U_BOOT_DRIVER(octeontx_gpio) = { + .name = "octeontx_gpio", + .id = UCLASS_GPIO, + .of_match = of_match_ptr(octeontx_gpio_ids), + .probe = octeontx_gpio_probe, + .priv_auto_alloc_size = sizeof(struct octeontx_gpio), + .ops = &octeontx_gpio_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +static struct pci_device_id octeontx_gpio_supported[] = { + { PCI_VDEVICE(CAVIUM, PCI_DEVICE_ID_OCTEONTX_GPIO) }, + { }, +}; + +U_BOOT_PCI_DEVICE(octeontx_gpio, octeontx_gpio_supported);