-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
gpiolib support for the PXA architecture
This adds gpiolib support for the PXA architecture: - move all GPIO API functions from generic.c into gpio.c - convert the gpio_get/set_value macros into inline functions This makes it easier to hook up GPIOs provided by external chips like ASICs and CPLDs. Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Acked-by: Russell King <rmk+kernel@arm.linux.org.uk> Cc: Jean Delvare <khali@linux-fr.org> Cc: Eric Miao <eric.miao@marvell.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Haavard Skinnemoen <hskinnemoen@atmel.com> Cc: Ben Gardner <bgardner@wabtec.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> [ Minor ARM fixup from David Brownell folded into this ] Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
- Loading branch information
Philipp Zabel
authored and
Linus Torvalds
committed
Feb 5, 2008
1 parent
7c2db75
commit 1c44f5f
Showing
8 changed files
with
236 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
/* | ||
* linux/arch/arm/mach-pxa/gpio.c | ||
* | ||
* Generic PXA GPIO handling | ||
* | ||
* Author: Nicolas Pitre | ||
* Created: Jun 15, 2001 | ||
* Copyright: MontaVista Software Inc. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
*/ | ||
|
||
#include <linux/init.h> | ||
#include <linux/module.h> | ||
|
||
#include <asm/gpio.h> | ||
#include <asm/hardware.h> | ||
#include <asm/io.h> | ||
#include <asm/arch/pxa-regs.h> | ||
|
||
#include "generic.h" | ||
|
||
|
||
struct pxa_gpio_chip { | ||
struct gpio_chip chip; | ||
void __iomem *regbase; | ||
}; | ||
|
||
int pxa_last_gpio; | ||
|
||
/* | ||
* Configure pins for GPIO or other functions | ||
*/ | ||
int pxa_gpio_mode(int gpio_mode) | ||
{ | ||
unsigned long flags; | ||
int gpio = gpio_mode & GPIO_MD_MASK_NR; | ||
int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8; | ||
int gafr; | ||
|
||
if (gpio > pxa_last_gpio) | ||
return -EINVAL; | ||
|
||
local_irq_save(flags); | ||
if (gpio_mode & GPIO_DFLT_LOW) | ||
GPCR(gpio) = GPIO_bit(gpio); | ||
else if (gpio_mode & GPIO_DFLT_HIGH) | ||
GPSR(gpio) = GPIO_bit(gpio); | ||
if (gpio_mode & GPIO_MD_MASK_DIR) | ||
GPDR(gpio) |= GPIO_bit(gpio); | ||
else | ||
GPDR(gpio) &= ~GPIO_bit(gpio); | ||
gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2)); | ||
GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2)); | ||
local_irq_restore(flags); | ||
|
||
return 0; | ||
} | ||
EXPORT_SYMBOL(pxa_gpio_mode); | ||
|
||
static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
{ | ||
unsigned long flags; | ||
u32 mask = 1 << offset; | ||
u32 value; | ||
struct pxa_gpio_chip *pxa; | ||
void __iomem *gpdr; | ||
|
||
pxa = container_of(chip, struct pxa_gpio_chip, chip); | ||
gpdr = pxa->regbase + GPDR_OFFSET; | ||
local_irq_save(flags); | ||
value = __raw_readl(gpdr); | ||
value &= ~mask; | ||
__raw_writel(value, gpdr); | ||
local_irq_restore(flags); | ||
|
||
return 0; | ||
} | ||
|
||
static int pxa_gpio_direction_output(struct gpio_chip *chip, | ||
unsigned offset, int value) | ||
{ | ||
unsigned long flags; | ||
u32 mask = 1 << offset; | ||
u32 tmp; | ||
struct pxa_gpio_chip *pxa; | ||
void __iomem *gpdr; | ||
|
||
pxa = container_of(chip, struct pxa_gpio_chip, chip); | ||
__raw_writel(mask, | ||
pxa->regbase + (value ? GPSR_OFFSET : GPCR_OFFSET)); | ||
gpdr = pxa->regbase + GPDR_OFFSET; | ||
local_irq_save(flags); | ||
tmp = __raw_readl(gpdr); | ||
tmp |= mask; | ||
__raw_writel(tmp, gpdr); | ||
local_irq_restore(flags); | ||
|
||
return 0; | ||
} | ||
|
||
/* | ||
* Return GPIO level | ||
*/ | ||
static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
{ | ||
u32 mask = 1 << offset; | ||
struct pxa_gpio_chip *pxa; | ||
|
||
pxa = container_of(chip, struct pxa_gpio_chip, chip); | ||
return __raw_readl(pxa->regbase + GPLR_OFFSET) & mask; | ||
} | ||
|
||
/* | ||
* Set output GPIO level | ||
*/ | ||
static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
{ | ||
u32 mask = 1 << offset; | ||
struct pxa_gpio_chip *pxa; | ||
|
||
pxa = container_of(chip, struct pxa_gpio_chip, chip); | ||
|
||
if (value) | ||
__raw_writel(mask, pxa->regbase + GPSR_OFFSET); | ||
else | ||
__raw_writel(mask, pxa->regbase + GPCR_OFFSET); | ||
} | ||
|
||
static struct pxa_gpio_chip pxa_gpio_chip[] = { | ||
[0] = { | ||
.regbase = GPIO0_BASE, | ||
.chip = { | ||
.label = "gpio-0", | ||
.direction_input = pxa_gpio_direction_input, | ||
.direction_output = pxa_gpio_direction_output, | ||
.get = pxa_gpio_get, | ||
.set = pxa_gpio_set, | ||
.base = 0, | ||
.ngpio = 32, | ||
}, | ||
}, | ||
[1] = { | ||
.regbase = GPIO1_BASE, | ||
.chip = { | ||
.label = "gpio-1", | ||
.direction_input = pxa_gpio_direction_input, | ||
.direction_output = pxa_gpio_direction_output, | ||
.get = pxa_gpio_get, | ||
.set = pxa_gpio_set, | ||
.base = 32, | ||
.ngpio = 32, | ||
}, | ||
}, | ||
[2] = { | ||
.regbase = GPIO2_BASE, | ||
.chip = { | ||
.label = "gpio-2", | ||
.direction_input = pxa_gpio_direction_input, | ||
.direction_output = pxa_gpio_direction_output, | ||
.get = pxa_gpio_get, | ||
.set = pxa_gpio_set, | ||
.base = 64, | ||
.ngpio = 32, /* 21 for PXA25x */ | ||
}, | ||
}, | ||
#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) | ||
[3] = { | ||
.regbase = GPIO3_BASE, | ||
.chip = { | ||
.label = "gpio-3", | ||
.direction_input = pxa_gpio_direction_input, | ||
.direction_output = pxa_gpio_direction_output, | ||
.get = pxa_gpio_get, | ||
.set = pxa_gpio_set, | ||
.base = 96, | ||
.ngpio = 32, | ||
}, | ||
}, | ||
#endif | ||
}; | ||
|
||
void __init pxa_init_gpio(int gpio_nr) | ||
{ | ||
int i; | ||
|
||
/* add a GPIO chip for each register bank. | ||
* the last PXA25x register only contains 21 GPIOs | ||
*/ | ||
for (i = 0; i < gpio_nr; i += 32) { | ||
if (i+32 > gpio_nr) | ||
pxa_gpio_chip[i/32].chip.ngpio = gpio_nr - i; | ||
gpiochip_add(&pxa_gpio_chip[i/32].chip); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.