From patchwork Fri Sep 5 15:08:47 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Korsgaard X-Patchwork-Id: 188 X-Patchwork-Delegate: galak@kernel.crashing.org Return-Path: X-Original-To: patchwork@ozlabs.org Delivered-To: patchwork@ozlabs.org Received: from ozlabs.org (localhost [127.0.0.1]) by ozlabs.org (Postfix) with ESMTP id CF520DE1CF for ; Sat, 6 Sep 2008 01:09:11 +1000 (EST) X-Original-To: linuxppc-dev@ozlabs.org Delivered-To: linuxppc-dev@ozlabs.org Received: from fg-out-1718.google.com (fg-out-1718.google.com [72.14.220.156]) by ozlabs.org (Postfix) with ESMTP id 99326DDF6F for ; Sat, 6 Sep 2008 01:08:53 +1000 (EST) Received: by fg-out-1718.google.com with SMTP id d23so788383fga.39 for ; Fri, 05 Sep 2008 08:08:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:received:from:to:cc:subject :date:message-id:x-mailer:sender; bh=wNBpvDoLEkPV2iCPSWSE0tgb4hCAeYe2q7cO20Wf4tA=; b=PP91iaBZSRD9zSRxvctjznzUaaKc+XvgLuJPgrKiqND29DJ6vX62Hj5FN99f2xMKlH C7L6MTmzBDvyckyF3A5PE4oWWmUde+CP/FFhEIB8nmzjsVvx9w856zxtcApSEBZkpycy Kt1YnW20zdeK+RxpFhvD6R3ZQMLpySXpjtWM0= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:sender; b=WrPtmfswa1BvcvWdEqCCUsBfihtbr5I4P3DUT0vHBtO5qqk9oPDV2/T9MzgDD8FlPV ye8kjAAdmHUynr1Nmk0k6Ow6LdiZmIsBi+v9kuhWxr3z9UKOv+t8tDAK64JxMIKABp0N SVqjOOZbmdCQany/WfrS7mvssJ5+N6SBARmBs= Received: by 10.86.94.11 with SMTP id r11mr8879564fgb.0.1220627329315; Fri, 05 Sep 2008 08:08:49 -0700 (PDT) Received: from macbook.be.48ers.dk ( [194.78.207.191]) by mx.google.com with ESMTPS id l12sm1234617fgb.6.2008.09.05.08.08.47 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 05 Sep 2008 08:08:48 -0700 (PDT) Received: by macbook.be.48ers.dk (Postfix, from userid 1000) id CB2FC98C5B3; Fri, 5 Sep 2008 17:08:47 +0200 (CEST) From: Peter Korsgaard To: linuxppc-dev@ozlabs.org, galak@kernel.crashing.org, avorontsov@ru.mvista.com Subject: [PATCH] powerpc: gpio driver for mpc831x/834x/837x with OF bindings Date: Fri, 5 Sep 2008 17:08:47 +0200 Message-Id: <1220627327-28852-1-git-send-email-jacmet@sunsite.dk> X-Mailer: git-send-email 1.5.6.3 X-BeenThere: linuxppc-dev@ozlabs.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linuxppc-dev-bounces+patchwork=ozlabs.org@ozlabs.org Errors-To: linuxppc-dev-bounces+patchwork=ozlabs.org@ozlabs.org Structured similar to the existing QE GPIO support. Signed-off-by: Peter Korsgaard diff --git a/Documentation/powerpc/dts-bindings/fsl/83xx_gpio.txt b/Documentation/powerpc/dts-bindings/fsl/83xx_gpio.txt new file mode 100644 index 0000000..f43f048 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/fsl/83xx_gpio.txt @@ -0,0 +1,33 @@ +GPIO controllers on MPC831x/834x/837x SoCs + +Every GPIO controller node must have #gpio-cells property defined, +this information will be used to translate gpio-specifiers. + +Required properties: +- compatible : "fsl,mpc8349-gpio" +- #gpio-cells : Should be two. The first cell is the pin number and the + second cell is used to specify optional parameters (currently unused). + - interrupts : Interrupt mapping for GPIO IRQ (currently unused). + - interrupt-parent : Phandle for the interrupt controller that + services interrupts for this device. +- gpio-controller : Marks the port as GPIO controller. + +Example of gpio-controller nodes for a MPC8349 SoC: + + gpio1: gpio-controller@c00 { + #gpio-cells = <2>; + compatible = "fsl,mpc8349-gpio"; + reg = <0xc00 0x100>; + interrupts = <74 0x8>; + interrupt-parent = <&ipic>; + gpio-controller; + }; + + gpio2: gpio-controller@d00 { + #gpio-cells = <2>; + compatible = "fsl,mpc8349-gpio"; + reg = <0xd00 0x100>; + interrupts = <75 0x8>; + interrupt-parent = <&ipic>; + gpio-controller; + }; diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig index 72fb35b..d28c3c5 100644 --- a/arch/powerpc/sysdev/Kconfig +++ b/arch/powerpc/sysdev/Kconfig @@ -6,3 +6,12 @@ config PPC4xx_PCI_EXPRESS bool depends on PCI && 4xx default n + +config MPC83xx_GPIO + bool "MPC83xx GPIO support" + depends on PPC_MPC831x || PPC_MPC834x || PPC_MPC837x + select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB + help + Say Y here if you're going to use hardware that connects to the + MPC831x/834x/837x GPIOs. diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index a90054b..ced5793 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_FSL_SOC) += fsl_soc.o obj-$(CONFIG_FSL_PCI) += fsl_pci.o $(fsl-msi-obj-y) obj-$(CONFIG_FSL_LBC) += fsl_lbc.o obj-$(CONFIG_FSL_GTM) += fsl_gtm.o +obj-$(CONFIG_MPC83xx_GPIO) += mpc83xx_gpio.o obj-$(CONFIG_RAPIDIO) += fsl_rio.o obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ diff --git a/arch/powerpc/sysdev/mpc83xx_gpio.c b/arch/powerpc/sysdev/mpc83xx_gpio.c new file mode 100644 index 0000000..a8a132d --- /dev/null +++ b/arch/powerpc/sysdev/mpc83xx_gpio.c @@ -0,0 +1,141 @@ +/* + * GPIOs on MPC831x/834x/837x + * + * Copyright (C) 2008 Peter Korsgaard + * + * 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 + +#define GPIO_DIR 0x00 +#define GPIO_ODR 0x04 +#define GPIO_DAT 0x08 +#define GPIO_IER 0x0c +#define GPIO_IMR 0x10 +#define GPIO_ICR 0x14 + +struct mpc83xx_gpio_chip { + struct of_mm_gpio_chip mm_gc; + spinlock_t lock; +}; + +static inline struct mpc83xx_gpio_chip * +to_mpc83xx_gpio_chip(struct of_mm_gpio_chip *mm) +{ + return container_of(mm, struct mpc83xx_gpio_chip, mm_gc); +} + +static int mpc83xx_gpio_get(struct gpio_chip *gc, unsigned int gpio) +{ + struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); + u32 bit = 1u << (31-gpio); + + return !!(in_be32(mm->regs + GPIO_DAT) & bit); +} + +static void mpc83xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +{ + struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); + struct mpc83xx_gpio_chip *mpc83xx_gc = to_mpc83xx_gpio_chip(mm); + unsigned long flags; + u32 data, bit = 1u << (31-gpio); + + spin_lock_irqsave(&mpc83xx_gc->lock, flags); + + data = in_be32(mm->regs + GPIO_DAT); + if (val) + data |= bit; + else + data &= ~bit; + out_be32(mm->regs + GPIO_DAT, data); + + spin_unlock_irqrestore(&mpc83xx_gc->lock, flags); +} + +static int mpc83xx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) +{ + struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); + struct mpc83xx_gpio_chip *mpc83xx_gc = to_mpc83xx_gpio_chip(mm); + unsigned long flags; + u32 bit = 1u << (31-gpio); + + spin_lock_irqsave(&mpc83xx_gc->lock, flags); + + out_be32(mm->regs + GPIO_DIR, + in_be32(mm->regs + GPIO_DIR) & ~bit); + + spin_unlock_irqrestore(&mpc83xx_gc->lock, flags); + + return 0; +} + +static int mpc83xx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) +{ + struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); + struct mpc83xx_gpio_chip *mpc83xx_gc = to_mpc83xx_gpio_chip(mm); + unsigned long flags; + u32 bit = 1u << (31-gpio); + + mpc83xx_gpio_set(gc, gpio, val); + + spin_lock_irqsave(&mpc83xx_gc->lock, flags); + out_be32(mm->regs + GPIO_DIR, + in_be32(mm->regs + GPIO_DIR) | bit); + + spin_unlock_irqrestore(&mpc83xx_gc->lock, flags); + + return 0; +} + +static int __init mpc83xx_add_gpiochips(void) +{ + struct device_node *np; + + for_each_compatible_node(np, NULL, "fsl,mpc8349-gpio") { + int ret; + struct mpc83xx_gpio_chip *mpc83xx_gc; + struct of_mm_gpio_chip *mm_gc; + struct of_gpio_chip *of_gc; + struct gpio_chip *gc; + + mpc83xx_gc = kzalloc(sizeof(*mpc83xx_gc), GFP_KERNEL); + if (!mpc83xx_gc) { + ret = -ENOMEM; + goto err; + } + + spin_lock_init(&mpc83xx_gc->lock); + + mm_gc = &mpc83xx_gc->mm_gc; + of_gc = &mm_gc->of_gc; + gc = &of_gc->gc; + + of_gc->gpio_cells = 2; + gc->ngpio = 32; + gc->direction_input = mpc83xx_gpio_dir_in; + gc->direction_output = mpc83xx_gpio_dir_out; + gc->get = mpc83xx_gpio_get; + gc->set = mpc83xx_gpio_set; + + ret = of_mm_gpiochip_add(np, mm_gc); + if (ret) + goto err; + continue; +err: + pr_err("%s: registration failed with status %d\n", + np->full_name, ret); + kfree(mpc83xx_gc); + /* try others anyway */ + } + return 0; +} +arch_initcall(mpc83xx_add_gpiochips);