alistair23-linux/arch/arm/mach-w90x900/gpio.c
wanzongshun 35c9221acb ARM: 5682/1: Add cpu.c and dev.c and modify some files of w90p910 platform
Add the cpu.c and dev.c and modify w90p910 platform
to apply to use the common API(provided by cpu.c and dev.c)
at the same time, I renamed all w90x900 to nuc900 in every
c file of w90x900 platform and touchscreen's driver name.

Signed-off-by: Wan ZongShun <mcuos.com@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2009-09-02 11:22:23 +01:00

155 lines
3.8 KiB
C

/*
* linux/arch/arm/mach-w90x900/gpio.c
*
* Generic nuc900 GPIO handling
*
* Wan ZongShun <mcuos.com@gmail.com>
*
* 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/clk.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
#define GPIO_BASE (W90X900_VA_GPIO)
#define GPIO_DIR (0x04)
#define GPIO_OUT (0x08)
#define GPIO_IN (0x0C)
#define GROUPINERV (0x10)
#define GPIO_GPIO(Nb) (0x00000001 << (Nb))
#define to_nuc900_gpio_chip(c) container_of(c, struct nuc900_gpio_chip, chip)
#define NUC900_GPIO_CHIP(name, base_gpio, nr_gpio) \
{ \
.chip = { \
.label = name, \
.direction_input = nuc900_dir_input, \
.direction_output = nuc900_dir_output, \
.get = nuc900_gpio_get, \
.set = nuc900_gpio_set, \
.base = base_gpio, \
.ngpio = nr_gpio, \
} \
}
struct nuc900_gpio_chip {
struct gpio_chip chip;
void __iomem *regbase; /* Base of group register*/
spinlock_t gpio_lock;
};
static int nuc900_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct nuc900_gpio_chip *nuc900_gpio = to_nuc900_gpio_chip(chip);
void __iomem *pio = nuc900_gpio->regbase + GPIO_IN;
unsigned int regval;
regval = __raw_readl(pio);
regval &= GPIO_GPIO(offset);
return (regval != 0);
}
static void nuc900_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
{
struct nuc900_gpio_chip *nuc900_gpio = to_nuc900_gpio_chip(chip);
void __iomem *pio = nuc900_gpio->regbase + GPIO_OUT;
unsigned int regval;
unsigned long flags;
spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags);
regval = __raw_readl(pio);
if (val)
regval |= GPIO_GPIO(offset);
else
regval &= ~GPIO_GPIO(offset);
__raw_writel(regval, pio);
spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags);
}
static int nuc900_dir_input(struct gpio_chip *chip, unsigned offset)
{
struct nuc900_gpio_chip *nuc900_gpio = to_nuc900_gpio_chip(chip);
void __iomem *pio = nuc900_gpio->regbase + GPIO_DIR;
unsigned int regval;
unsigned long flags;
spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags);
regval = __raw_readl(pio);
regval &= ~GPIO_GPIO(offset);
__raw_writel(regval, pio);
spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags);
return 0;
}
static int nuc900_dir_output(struct gpio_chip *chip, unsigned offset, int val)
{
struct nuc900_gpio_chip *nuc900_gpio = to_nuc900_gpio_chip(chip);
void __iomem *outreg = nuc900_gpio->regbase + GPIO_OUT;
void __iomem *pio = nuc900_gpio->regbase + GPIO_DIR;
unsigned int regval;
unsigned long flags;
spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags);
regval = __raw_readl(pio);
regval |= GPIO_GPIO(offset);
__raw_writel(regval, pio);
regval = __raw_readl(outreg);
if (val)
regval |= GPIO_GPIO(offset);
else
regval &= ~GPIO_GPIO(offset);
__raw_writel(regval, outreg);
spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags);
return 0;
}
static struct nuc900_gpio_chip nuc900_gpio[] = {
NUC900_GPIO_CHIP("GROUPC", 0, 16),
NUC900_GPIO_CHIP("GROUPD", 16, 10),
NUC900_GPIO_CHIP("GROUPE", 26, 14),
NUC900_GPIO_CHIP("GROUPF", 40, 10),
NUC900_GPIO_CHIP("GROUPG", 50, 17),
NUC900_GPIO_CHIP("GROUPH", 67, 8),
NUC900_GPIO_CHIP("GROUPI", 75, 17),
};
void __init nuc900_init_gpio(int nr_group)
{
unsigned i;
struct nuc900_gpio_chip *gpio_chip;
for (i = 0; i < nr_group; i++) {
gpio_chip = &nuc900_gpio[i];
spin_lock_init(&gpio_chip->gpio_lock);
gpio_chip->regbase = GPIO_BASE + i * GROUPINERV;
gpiochip_add(&gpio_chip->chip);
}
}