From patchwork Mon Jul 29 13:06:01 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonas Jensen X-Patchwork-Id: 2834942 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 54EC49F9D9 for ; Mon, 29 Jul 2013 13:07:03 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7370220166 for ; Mon, 29 Jul 2013 13:06:58 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E941620113 for ; Mon, 29 Jul 2013 13:06:56 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1V3nA6-0006cf-TD; Mon, 29 Jul 2013 13:06:55 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1V3nA4-0000Yn-KM; Mon, 29 Jul 2013 13:06:52 +0000 Received: from mail-la0-x230.google.com ([2a00:1450:4010:c03::230]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1V3nA2-0000XH-8y for linux-arm-kernel@lists.infradead.org; Mon, 29 Jul 2013 13:06:51 +0000 Received: by mail-la0-f48.google.com with SMTP id hi8so3943523lab.7 for ; Mon, 29 Jul 2013 06:06:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=UxZAH4ighY1aXNF6cH4viaLBv5BPgbd9ss8GXVjBSb4=; b=VwbIU21Hmko7R3dKJGFagjPUizdc8u/msRO4aGFdSiwulcAu/NIEsvpf+DrUcgtQRO Fm2FH4lRN/AHcOAE0Ht+UIMhBES87t9kzO+eN9OobmJjwU3Vtp8GJlDrddSezUJBS7RL YwolJahPnm1znVbcotqJr84M/gXM+rRBP/a976yGYYb7DwMvAhDVvJYB2QDGyc4WsRLO CLtmbZ7/IstJ91H9zotoV1LjuAt1ogXsm/dCmU9a2Nhu6jD88PXYLAAUfJRHZ8jDJ700 Nu1Cc0RxBY4Kpxek+0uU/JpmhN78P7VhRCNbBvG7L9SHq9avx8Odnu9BbRu6CpZNtUcs +saA== X-Received: by 10.112.50.41 with SMTP id z9mr3783619lbn.83.1375103188298; Mon, 29 Jul 2013 06:06:28 -0700 (PDT) Received: from Ildjarn.ath.cx (static-213-115-41-10.sme.bredbandsbolaget.se. [213.115.41.10]) by mx.google.com with ESMTPSA id y5sm24190171lae.2.2013.07.29.06.06.26 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Mon, 29 Jul 2013 06:06:27 -0700 (PDT) From: Jonas Jensen To: linux-gpio@vger.kernel.org Subject: [PATCH v4] gpio: Add MOXA ART GPIO driver Date: Mon, 29 Jul 2013 15:06:01 +0200 Message-Id: <1375103161-12460-1-git-send-email-jonas.jensen@gmail.com> X-Mailer: git-send-email 1.8.2.1 In-Reply-To: <1374053693-6166-1-git-send-email-jonas.jensen@gmail.com> References: <1374053693-6166-1-git-send-email-jonas.jensen@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130729_090650_626050_6AE0F9F5 X-CRM114-Status: GOOD ( 17.77 ) X-Spam-Score: -2.0 (--) Cc: arnd@arndb.de, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, Jonas Jensen , arm@kernel.org, grant.likely@linaro.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-5.6 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add GPIO driver for MOXA ART SoCs. Signed-off-by: Jonas Jensen --- Notes: Changes since v3: 1. use local struct device *dev pointer, replace "&pdev->dev" with "dev" device tree bindings document: 2. describe compatible variable "Must be" instead of "Should be". Applies to next-20130729 .../devicetree/bindings/gpio/moxa,moxart-gpio.txt | 23 +++ drivers/gpio/Kconfig | 7 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-moxart.c | 189 +++++++++++++++++++++ 4 files changed, 220 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt create mode 100644 drivers/gpio/gpio-moxart.c diff --git a/Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt b/Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt new file mode 100644 index 0000000..795afab --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt @@ -0,0 +1,23 @@ +MOXA ART GPIO Controller + +Required properties: + +- #gpio-cells : Should be 2 +- compatible : Must be "moxa,moxart-gpio" +- reg : Should contain registers location and length + index 0 : input, output, and direction control + index 1 : enable/disable individual pins, pin 0-31 +- gpio-ready-led : ready LED gpio, with zero flags +- gpio-reset-switch : reset switch gpio, with zero flags + +Example: + + gpio: gpio@98700000 { + gpio-controller; + #gpio-cells = <2>; + compatible = "moxa,moxart-gpio"; + reg = <0x98700000 0xC>, + <0x98100100 0x4>; + gpio-ready-led = <&gpio 27 0>; + gpio-reset-switch = <&gpio 25 0>; + }; diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 4b7ba53..5419413 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -741,6 +741,13 @@ config GPIO_MSIC Enable support for GPIO on intel MSIC controllers found in intel MID devices +config GPIO_MOXART + bool "MOXART GPIO support" + depends on ARCH_MOXART + help + Select this option to enable GPIO driver for + MOXA ART SoC devices. + comment "USB GPIO expanders:" config GPIO_VIPERBOARD diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 156fd28..c7a7a2b 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o +obj-$(CONFIG_GPIO_MOXART) += gpio-moxart.o obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c new file mode 100644 index 0000000..a5bdbca --- /dev/null +++ b/drivers/gpio/gpio-moxart.c @@ -0,0 +1,189 @@ +/* + * MOXA ART SoCs GPIO driver. + * + * Copyright (C) 2013 Jonas Jensen + * + * Jonas Jensen + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GPIO_DATA_OUT 0x00 +#define GPIO_DATA_IN 0x04 +#define GPIO_PIN_DIRECTION 0x08 + +static void __iomem *moxart_pincontrol_base; +static void __iomem *moxart_gpio_base; + +void moxart_gpio_enable(u32 gpio) +{ + writel(readl(moxart_pincontrol_base) | gpio, moxart_pincontrol_base); +} + +void moxart_gpio_disable(u32 gpio) +{ + writel(readl(moxart_pincontrol_base) & ~gpio, moxart_pincontrol_base); +} + +static int moxart_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + moxart_gpio_enable(1 << offset); + return pinctrl_request_gpio(offset); +} + +static void moxart_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + pinctrl_free_gpio(offset); + moxart_gpio_disable(1 << offset); +} + +static int moxart_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + void __iomem *ioaddr = moxart_gpio_base + GPIO_PIN_DIRECTION; + + writel(readl(ioaddr) & ~(1 << offset), ioaddr); + return 0; +} + +static int moxart_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + void __iomem *ioaddr = moxart_gpio_base + GPIO_PIN_DIRECTION; + + writel(readl(ioaddr) | (1 << offset), ioaddr); + return 0; +} + +static void moxart_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + void __iomem *ioaddr = moxart_gpio_base + GPIO_DATA_OUT; + u32 reg = readl(ioaddr); + + (value) ? writel(reg | (1 << offset), ioaddr) : + writel(reg & ~(1 << offset), ioaddr); +} + +static int moxart_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + u32 ret = readl(moxart_gpio_base + GPIO_PIN_DIRECTION); + + if (ret & (1 << offset)) + ret = readl(moxart_gpio_base + GPIO_DATA_OUT) & (1 << offset); + else + ret = readl(moxart_gpio_base + GPIO_DATA_IN) & (1 << offset); + + return ret; +} + +static struct gpio_chip moxart_gpio_chip = { + .label = "moxart-gpio", + .request = moxart_gpio_request, + .free = moxart_gpio_free, + .direction_input = moxart_gpio_direction_input, + .direction_output = moxart_gpio_direction_output, + .set = moxart_gpio_set, + .get = moxart_gpio_get, + .base = 0, + .ngpio = 32, + .can_sleep = 0, +}; + +static int moxart_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + int ret, gpio_ready_led, gpio_reset_switch; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + moxart_gpio_base = devm_ioremap_resource(dev, res); + if (IS_ERR(moxart_gpio_base)) { + dev_err(dev, "%s: devm_ioremap_resource res_gpio failed\n", + dev->of_node->full_name); + return PTR_ERR(moxart_gpio_base); + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + moxart_pincontrol_base = devm_ioremap_resource(dev, res); + if (IS_ERR(moxart_pincontrol_base)) { + dev_err(dev, "%s: devm_ioremap_resource res_pmu failed\n", + dev->of_node->full_name); + return PTR_ERR(moxart_pincontrol_base); + } + + moxart_gpio_chip.dev = dev; + + ret = gpiochip_add(&moxart_gpio_chip); + if (ret) + dev_err(dev, "%s: gpiochip_add failed\n", + dev->of_node->full_name); + + + gpio_ready_led = of_get_named_gpio(dev->of_node, + "gpio-ready-led", 0); + if (!gpio_is_valid(gpio_ready_led)) { + dev_err(dev, "invalid gpio (gpio-ready-led): %d\n", + gpio_ready_led); + return gpio_ready_led; + } + + gpio_reset_switch = of_get_named_gpio(dev->of_node, + "gpio-reset-switch", 0); + if (!gpio_is_valid(gpio_reset_switch)) { + dev_err(dev, "invalid gpio (gpio-reset-switch): %d\n", + gpio_reset_switch); + return gpio_reset_switch; + } + + moxart_gpio_enable(gpio_ready_led | gpio_reset_switch); + + moxart_gpio_direction_input(&moxart_gpio_chip, gpio_reset_switch); + + /* + * gpio_ready_led=0 ready LED on + * gpio_ready_led=1 ready LED off + */ + moxart_gpio_direction_output(&moxart_gpio_chip, gpio_ready_led, 0); + moxart_gpio_set(&moxart_gpio_chip, gpio_ready_led, 0); + + return 0; +} + +static const struct of_device_id moxart_gpio_match[] = { + { .compatible = "moxa,moxart-gpio" }, + { } +}; + +static struct platform_driver moxart_gpio_driver = { + .driver = { + .name = "moxart-gpio", + .owner = THIS_MODULE, + .of_match_table = moxart_gpio_match, + }, + .probe = moxart_gpio_probe, +}; + +static int __init moxart_gpio_init(void) +{ + return platform_driver_register(&moxart_gpio_driver); +} + +postcore_initcall(moxart_gpio_init); + +MODULE_DESCRIPTION("MOXART GPIO chip driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jonas Jensen ");