提交 52e31344 编写于 作者: D David Brownell 提交者: Tony Lindgren

ARM: OMAP: Use gpiolib

Update OMAP to use the new GPIO implementation framework.  This is just a
quick'n'dirty update ... more code could now be removed, ideally as part
of cleaning up the entire OMAP GPIO infrastructure ...
Signed-off-by: NDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: NTony Lindgren <tony@atomide.com>

上级 120dd64c
...@@ -468,6 +468,7 @@ config ARCH_DAVINCI ...@@ -468,6 +468,7 @@ config ARCH_DAVINCI
config ARCH_OMAP config ARCH_OMAP
bool "TI OMAP" bool "TI OMAP"
select GENERIC_GPIO select GENERIC_GPIO
select HAVE_GPIO_LIB
select GENERIC_TIME select GENERIC_TIME
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
help help
......
...@@ -136,7 +136,6 @@ struct gpio_bank { ...@@ -136,7 +136,6 @@ struct gpio_bank {
u16 irq; u16 irq;
u16 virtual_irq_start; u16 virtual_irq_start;
int method; int method;
u32 reserved_map;
#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
u32 suspend_wakeup; u32 suspend_wakeup;
u32 saved_wakeup; u32 saved_wakeup;
...@@ -150,6 +149,7 @@ struct gpio_bank { ...@@ -150,6 +149,7 @@ struct gpio_bank {
u32 saved_risingdetect; u32 saved_risingdetect;
#endif #endif
spinlock_t lock; spinlock_t lock;
struct gpio_chip chip;
}; };
#define METHOD_MPUIO 0 #define METHOD_MPUIO 0
...@@ -903,19 +903,17 @@ int omap_request_gpio(int gpio) ...@@ -903,19 +903,17 @@ int omap_request_gpio(int gpio)
{ {
struct gpio_bank *bank; struct gpio_bank *bank;
unsigned long flags; unsigned long flags;
int status;
if (check_gpio(gpio) < 0) if (check_gpio(gpio) < 0)
return -EINVAL; return -EINVAL;
status = gpio_request(gpio, NULL);
if (status < 0)
return status;
bank = get_gpio_bank(gpio); bank = get_gpio_bank(gpio);
spin_lock_irqsave(&bank->lock, flags); spin_lock_irqsave(&bank->lock, flags);
if (unlikely(bank->reserved_map & (1 << get_gpio_index(gpio)))) {
printk(KERN_ERR "omap-gpio: GPIO %d is already reserved!\n", gpio);
dump_stack();
spin_unlock_irqrestore(&bank->lock, flags);
return -1;
}
bank->reserved_map |= (1 << get_gpio_index(gpio));
/* Set trigger to none. You need to enable the desired trigger with /* Set trigger to none. You need to enable the desired trigger with
* request_irq() or set_irq_type(). * request_irq() or set_irq_type().
...@@ -945,10 +943,11 @@ void omap_free_gpio(int gpio) ...@@ -945,10 +943,11 @@ void omap_free_gpio(int gpio)
return; return;
bank = get_gpio_bank(gpio); bank = get_gpio_bank(gpio);
spin_lock_irqsave(&bank->lock, flags); spin_lock_irqsave(&bank->lock, flags);
if (unlikely(!(bank->reserved_map & (1 << get_gpio_index(gpio))))) { if (unlikely(!gpiochip_is_requested(&bank->chip,
get_gpio_index(gpio)))) {
spin_unlock_irqrestore(&bank->lock, flags);
printk(KERN_ERR "omap-gpio: GPIO %d wasn't reserved!\n", gpio); printk(KERN_ERR "omap-gpio: GPIO %d wasn't reserved!\n", gpio);
dump_stack(); dump_stack();
spin_unlock_irqrestore(&bank->lock, flags);
return; return;
} }
#ifdef CONFIG_ARCH_OMAP16XX #ifdef CONFIG_ARCH_OMAP16XX
...@@ -965,9 +964,9 @@ void omap_free_gpio(int gpio) ...@@ -965,9 +964,9 @@ void omap_free_gpio(int gpio)
__raw_writel(1 << get_gpio_index(gpio), reg); __raw_writel(1 << get_gpio_index(gpio), reg);
} }
#endif #endif
bank->reserved_map &= ~(1 << get_gpio_index(gpio));
_reset_gpio(bank, gpio); _reset_gpio(bank, gpio);
spin_unlock_irqrestore(&bank->lock, flags); spin_unlock_irqrestore(&bank->lock, flags);
gpio_free(gpio);
} }
/* /*
...@@ -1266,6 +1265,53 @@ static inline void mpuio_init(void) {} ...@@ -1266,6 +1265,53 @@ static inline void mpuio_init(void) {}
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
/* REVISIT these are stupid implementations! replace by ones that
* don't switch on METHOD_* and which mostly avoid spinlocks
*/
static int gpio_input(struct gpio_chip *chip, unsigned offset)
{
struct gpio_bank *bank;
unsigned long flags;
bank = container_of(chip, struct gpio_bank, chip);
spin_lock_irqsave(&bank->lock, flags);
_set_gpio_direction(bank, offset, 1);
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
}
static int gpio_get(struct gpio_chip *chip, unsigned offset)
{
return omap_get_gpio_datain(chip->base + offset);
}
static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
{
struct gpio_bank *bank;
unsigned long flags;
bank = container_of(chip, struct gpio_bank, chip);
spin_lock_irqsave(&bank->lock, flags);
_set_gpio_dataout(bank, offset, value);
_set_gpio_direction(bank, offset, 0);
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
}
static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct gpio_bank *bank;
unsigned long flags;
bank = container_of(chip, struct gpio_bank, chip);
spin_lock_irqsave(&bank->lock, flags);
_set_gpio_dataout(bank, offset, value);
spin_unlock_irqrestore(&bank->lock, flags);
}
/*---------------------------------------------------------------------*/
static int initialized; static int initialized;
#if !defined(CONFIG_ARCH_OMAP3) #if !defined(CONFIG_ARCH_OMAP3)
static struct clk * gpio_ick; static struct clk * gpio_ick;
...@@ -1293,6 +1339,7 @@ static struct lock_class_key gpio_lock_class; ...@@ -1293,6 +1339,7 @@ static struct lock_class_key gpio_lock_class;
static int __init _omap_gpio_init(void) static int __init _omap_gpio_init(void)
{ {
int i; int i;
int gpio = 0;
struct gpio_bank *bank; struct gpio_bank *bank;
#if defined(CONFIG_ARCH_OMAP3) #if defined(CONFIG_ARCH_OMAP3)
char clk_name[11]; char clk_name[11];
...@@ -1423,7 +1470,6 @@ static int __init _omap_gpio_init(void) ...@@ -1423,7 +1470,6 @@ static int __init _omap_gpio_init(void)
int j, gpio_count = 16; int j, gpio_count = 16;
bank = &gpio_bank[i]; bank = &gpio_bank[i];
bank->reserved_map = 0;
bank->base = IO_ADDRESS(bank->base); bank->base = IO_ADDRESS(bank->base);
spin_lock_init(&bank->lock); spin_lock_init(&bank->lock);
if (bank_is_mpuio(bank)) if (bank_is_mpuio(bank))
...@@ -1461,6 +1507,26 @@ static int __init _omap_gpio_init(void) ...@@ -1461,6 +1507,26 @@ static int __init _omap_gpio_init(void)
gpio_count = 32; gpio_count = 32;
} }
#endif #endif
/* REVISIT eventually switch from OMAP-specific gpio structs
* over to the generic ones
*/
bank->chip.direction_input = gpio_input;
bank->chip.get = gpio_get;
bank->chip.direction_output = gpio_output;
bank->chip.set = gpio_set;
if (bank_is_mpuio(bank)) {
bank->chip.label = "mpuio";
bank->chip.base = OMAP_MPUIO(0);
} else {
bank->chip.label = "gpio";
bank->chip.base = gpio;
gpio += gpio_count;
}
bank->chip.ngpio = gpio_count;
gpiochip_add(&bank->chip);
for (j = bank->virtual_irq_start; for (j = bank->virtual_irq_start;
j < bank->virtual_irq_start + gpio_count; j++) { j < bank->virtual_irq_start + gpio_count; j++) {
lockdep_set_class(&irq_desc[j].lock, &gpio_lock_class); lockdep_set_class(&irq_desc[j].lock, &gpio_lock_class);
...@@ -1757,8 +1823,10 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) ...@@ -1757,8 +1823,10 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) { for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) {
unsigned irq, value, is_in, irqstat; unsigned irq, value, is_in, irqstat;
const char *label;
if (!(bank->reserved_map & mask)) label = gpiochip_is_requested(&bank->chip, j);
if (!label)
continue; continue;
irq = bank->virtual_irq_start + j; irq = bank->virtual_irq_start + j;
...@@ -1766,13 +1834,16 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) ...@@ -1766,13 +1834,16 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
is_in = gpio_is_input(bank, mask); is_in = gpio_is_input(bank, mask);
if (bank_is_mpuio(bank)) if (bank_is_mpuio(bank))
seq_printf(s, "MPUIO %2d: ", j); seq_printf(s, "MPUIO %2d ", j);
else else
seq_printf(s, "GPIO %3d: ", gpio); seq_printf(s, "GPIO %3d ", gpio);
seq_printf(s, "%s %s", seq_printf(s, "(%10s): %s %s",
label,
is_in ? "in " : "out", is_in ? "in " : "out",
value ? "hi" : "lo"); value ? "hi" : "lo");
/* FIXME for at least omap2, show pullup/pulldown state */
irqstat = irq_desc[irq].status; irqstat = irq_desc[irq].status;
if (is_in && ((bank->suspend_wakeup & mask) if (is_in && ((bank->suspend_wakeup & mask)
|| irqstat & IRQ_TYPE_SENSE_MASK)) { || irqstat & IRQ_TYPE_SENSE_MASK)) {
...@@ -1795,10 +1866,10 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) ...@@ -1795,10 +1866,10 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
trigger = "high"; trigger = "high";
break; break;
case IRQ_TYPE_NONE: case IRQ_TYPE_NONE:
trigger = "(unspecified)"; trigger = "(?)";
break; break;
} }
seq_printf(s, ", irq-%d %s%s", seq_printf(s, ", irq-%d %-8s%s",
irq, trigger, irq, trigger,
(bank->suspend_wakeup & mask) (bank->suspend_wakeup & mask)
? " wakeup" : ""); ? " wakeup" : "");
......
...@@ -82,62 +82,35 @@ extern void omap_set_gpio_debounce_time(int gpio, int enable); ...@@ -82,62 +82,35 @@ extern void omap_set_gpio_debounce_time(int gpio, int enable);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* wrappers for "new style" GPIO calls. the old OMAP-specfic ones should /* Wrappers for "new style" GPIO calls, using the new infrastructure
* eventually be removed (along with this errno.h inclusion), and maybe * which lets us plug in FPGA, I2C, and other implementations.
* gpios should put MPUIOs last too. * *
* The original OMAP-specfic calls should eventually be removed.
*/ */
#include <asm/errno.h> #include <linux/errno.h>
#include <asm-generic/gpio.h>
static inline int gpio_request(unsigned gpio, const char *label)
{
return omap_request_gpio(gpio);
}
static inline void gpio_free(unsigned gpio)
{
omap_free_gpio(gpio);
}
static inline int __gpio_set_direction(unsigned gpio, int is_input)
{
if (cpu_class_is_omap2()) {
if (gpio > OMAP_MAX_GPIO_LINES)
return -EINVAL;
} else {
if (gpio > (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */))
return -EINVAL;
}
omap_set_gpio_direction(gpio, is_input);
return 0;
}
static inline int gpio_direction_input(unsigned gpio)
{
return __gpio_set_direction(gpio, 1);
}
static inline int gpio_direction_output(unsigned gpio, int value)
{
omap_set_gpio_dataout(gpio, value);
return __gpio_set_direction(gpio, 0);
}
static inline int gpio_get_value(unsigned gpio) static inline int gpio_get_value(unsigned gpio)
{ {
return omap_get_gpio_datain(gpio); return __gpio_get_value(gpio);
} }
static inline void gpio_set_value(unsigned gpio, int value) static inline void gpio_set_value(unsigned gpio, int value)
{ {
omap_set_gpio_dataout(gpio, value); __gpio_set_value(gpio, value);
} }
#include <asm-generic/gpio.h> /* cansleep wrappers */ static inline int gpio_cansleep(unsigned gpio)
{
return __gpio_cansleep(gpio);
}
static inline int gpio_to_irq(unsigned gpio) static inline int gpio_to_irq(unsigned gpio)
{ {
if (gpio < (OMAP_MAX_GPIO_LINES + 16))
return OMAP_GPIO_IRQ(gpio); return OMAP_GPIO_IRQ(gpio);
return -EINVAL;
} }
static inline int irq_to_gpio(unsigned irq) static inline int irq_to_gpio(unsigned irq)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册