From patchwork Wed Jul 7 11:32:38 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roman Fietze X-Patchwork-Id: 58103 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from bilbo.ozlabs.org (localhost [127.0.0.1]) by ozlabs.org (Postfix) with ESMTP id 306A41008D2 for ; Wed, 7 Jul 2010 21:32:54 +1000 (EST) Received: from coyote.quickmin.net (coyote.quickmin.net [217.14.112.24]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "smtp.quickmin.de", Issuer "smtp.quickmin.de" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 654DBB6EEE for ; Wed, 7 Jul 2010 21:32:46 +1000 (EST) Received: (qmail 74596 invoked from network); 7 Jul 2010 13:32:39 +0200 Received: by simscan 1.4.0 ppid: 74593, pid: 74594, t: 0.0169s scanners: clamav: 0.95.2/m:49/d:8609 Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=telemotive.de; b=o1XkFD3q23wWqIuH8Q0GySDNFIT/HRiRcxSIGlASWCGeceemm+WCK4YNJu3O+k3mkNO6WGIHbf4LgLhMrL6KCKuBnMj8XiPIjQa4Y7eRCRkXdpkLTiA49EgDgJSqBFhUXaU6X/SeMCkPeWvST++k0dEYyYDg15KfANgywjH4Hwg= ; Received: from mail.telemotive.de (62.206.149.210) by coyote.quickmin.net with SMTP; 7 Jul 2010 13:32:39 +0200 Received: from alderan.mit.telemotive.de ([192.168.5.15]) by mail.telemotive.de (Lotus Domino Release 8.0.2FP1) with ESMTP id 2010070713323834-18262 ; Wed, 7 Jul 2010 13:32:38 +0200 Received: from rfietze.mit.telemotive.de (rfietze.mit.telemotive.de [192.168.5.33]) by alderan.mit.telemotive.de (Postfix) with ESMTP id 25F2DCC7AE; Wed, 7 Jul 2010 13:32:39 +0200 (CEST) Received: by rfietze.mit.telemotive.de (Postfix, from userid 10062) id E27DB205FA; Wed, 7 Jul 2010 13:32:38 +0200 (CEST) From: Roman Fietze Organization: Telemotive AG To: Sascha Hauer Subject: [PATCH] mpc52xx_gpio: support MPC52xx simple interrupt GPIO User-Agent: KMail/1.13.5 (Linux/2.6.31.12-0.2-default; KDE/4.4.4; x86_64; ; ) MIME-Version: 1.0 Message-ID: <201007071332.38754.roman.fietze@telemotive.de> Date: Wed, 7 Jul 2010 13:32:38 +0200 X-MIMETrack: Itemize by SMTP Server on muc/Telemotive(Release 8.0.2FP1|January 12, 2009) at 07.07.2010 13:32:38, Serialize by Router on muc/Telemotive(Release 8.0.2FP1|January 12, 2009) at 07.07.2010 13:32:39, Serialize complete at 07.07.2010 13:32:39 Cc: linuxppc-dev@lists.ozlabs.org X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Hello Sascha, hello List Members, I could not find a way to access the MPC5200(B) simple interrupt pins using the 52xx platform GPIO driver. So I added the simple interrupt pins when the mpc5200-gpio is probed. Is there something I overlooked? If not, here's the patch. From 749b58686384275d253eeca8f3f0bd7a12daebe2 Mon Sep 17 00:00:00 2001 From: Roman Fietze Date: Wed, 7 Jul 2010 13:21:12 +0200 Subject: [PATCH] mpc52xx_gpio: support MPC52xx simple interrupt GPIO Add two OF GPIO chips when probing fsl,mpc5200-gpio, one for the 32 simple GPIO pins and one for the 8 simple interrupt GPIO pins. The current order of driver registrations will cause the simple interrupt GPIO pin numbers be below the ones of the simple GPIO pins, so current code will not have to be changed, except if there are more GPIO pins with dynamic pin numbers registered after the platform driver. Signed-off-by: Roman Fietze --- arch/powerpc/platforms/52xx/mpc52xx_gpio.c | 128 +++++++++++++++++++++++++++- 1 files changed, 126 insertions(+), 2 deletions(-) +static int __devinit mpc52xx_simple_sint_gpiochip_probe(struct of_device *ofdev, const struct of_device_id *match) { struct mpc52xx_gpiochip *chip; @@ -316,6 +416,7 @@ static int __devinit mpc52xx_simple_gpiochip_probe(struct of_device *ofdev, struct mpc52xx_gpio __iomem *regs; int ret; + /* simple GPIO */ chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (!chip) return -ENOMEM; @@ -338,6 +439,29 @@ static int __devinit mpc52xx_simple_gpiochip_probe(struct of_device *ofdev, chip->shadow_ddr = in_be32(®s->simple_ddr); chip->shadow_dvo = in_be32(®s->simple_dvo); + /* simple interrupt GPIO */ + chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + ofchip = &chip->mmchip.of_gc; + + ofchip->gpio_cells = 2; + ofchip->gc.ngpio = 8; + ofchip->gc.direction_input = mpc52xx_sint_gpio_dir_in; + ofchip->gc.direction_output = mpc52xx_sint_gpio_dir_out; + ofchip->gc.get = mpc52xx_sint_gpio_get; + ofchip->gc.set = mpc52xx_sint_gpio_set; + + ret = of_mm_gpiochip_add(ofdev->node, &chip->mmchip); + if (ret) + return ret; + + regs = chip->mmchip.regs; + chip->shadow_gpioe = in_8(®s->sint_gpioe); + chip->shadow_ddr = in_8(®s->sint_ddr); + chip->shadow_dvo = in_8(®s->sint_dvo); + return 0; } @@ -351,7 +475,7 @@ static const struct of_device_id mpc52xx_simple_gpiochip_match[] = { static struct of_platform_driver mpc52xx_simple_gpiochip_driver = { .name = "gpio", .match_table = mpc52xx_simple_gpiochip_match, - .probe = mpc52xx_simple_gpiochip_probe, + .probe = mpc52xx_simple_sint_gpiochip_probe, .remove = mpc52xx_gpiochip_remove, }; diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c index fda7c2a..d0a9fce 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c @@ -308,7 +308,107 @@ mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) return 0; } -static int __devinit mpc52xx_simple_gpiochip_probe(struct of_device *ofdev, +/* + * GPIO LIB API implementation for simple interrupt GPIOs + * + * There's a maximum of 8 simple interrupt GPIOs. Which of these are + * available for use depends on your board setup. The numbering + * reflects the bit numbering in the port registers: + * + * 0.. 3 > ETH_16..ETH_13 + * 4 > USB1_9 + * 5 > PSC3_8 + * 6.. 7 > PSC3_5..PSC3_4 + */ +static int mpc52xx_sint_gpio_get(struct gpio_chip *gc, unsigned int gpio) +{ + struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + struct mpc52xx_gpio __iomem *regs = mm_gc->regs; + unsigned int ret; + + ret = (in_8(®s->sint_ival) >> (7 - gpio)) & 1; + + return ret; +} + +static inline void +__mpc52xx_sint_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +{ + struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + struct mpc52xx_gpiochip *chip = container_of(mm_gc, + struct mpc52xx_gpiochip, mmchip); + struct mpc52xx_gpio __iomem *regs = mm_gc->regs; + + if (val) + chip->shadow_dvo |= 1 << (7 - gpio); + else + chip->shadow_dvo &= ~(1 << (7 - gpio)); + out_8(®s->sint_dvo, chip->shadow_dvo); +} + +static void +mpc52xx_sint_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +{ + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + + __mpc52xx_sint_gpio_set(gc, gpio, val); + + spin_unlock_irqrestore(&gpio_lock, flags); +} + +static int mpc52xx_sint_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) +{ + struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + struct mpc52xx_gpiochip *chip = container_of(mm_gc, + struct mpc52xx_gpiochip, mmchip); + struct mpc52xx_gpio __iomem *regs = mm_gc->regs; + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + + /* set the direction */ + chip->shadow_ddr &= ~(1 << (7 - gpio)); + out_8(®s->sint_ddr, chip->shadow_ddr); + + /* and enable the pin */ + chip->shadow_gpioe |= 1 << (7 - gpio); + out_8(®s->sint_gpioe, chip->shadow_gpioe); + + spin_unlock_irqrestore(&gpio_lock, flags); + + return 0; +} + +static int +mpc52xx_sint_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) +{ + struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + struct mpc52xx_gpiochip *chip = container_of(mm_gc, + struct mpc52xx_gpiochip, mmchip); + struct mpc52xx_gpio __iomem *regs = mm_gc->regs; + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + + /* First set initial value */ + __mpc52xx_sint_gpio_set(gc, gpio, val); + + /* Then set direction */ + chip->shadow_ddr |= 1 << (7 - gpio); + out_8(®s->sint_ddr, chip->shadow_ddr); + + /* Finally enable the pin */ + chip->shadow_gpioe |= 1 << (7 - gpio); + out_8(®s->sint_gpioe, chip->shadow_gpioe); + + spin_unlock_irqrestore(&gpio_lock, flags); + + return 0; +} +