android_kernel_xiaomi_sdm845/arch/arm/plat-s3c24xx/gpiolib.c
Ben Dooks f2edc7565a [ARM] S3C24XX: Reduce code lineage of gpiolib.c
All the s3c24xx gpiolib chips share the same get/set
calls and all but one bank shares the same calls for
.direction_input and .direction_output methods.

Change the initialisation process to use an new call
to register the chips that fills in any blank calls
with the default values to avoid having to fill them
in the structure initialisers.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
2008-12-15 21:46:24 +00:00

255 lines
5.3 KiB
C

/* linux/arch/arm/plat-s3c24xx/gpiolib.c
*
* Copyright (c) 2008 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
* S3C24XX GPIOlib support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
struct s3c24xx_gpio_chip {
struct gpio_chip chip;
void __iomem *base;
};
static inline struct s3c24xx_gpio_chip *to_s3c_chip(struct gpio_chip *gpc)
{
return container_of(gpc, struct s3c24xx_gpio_chip, chip);
}
/* these routines are exported for use by other parts of the platform
* and system support, but are not intended to be used directly by the
* drivers themsevles.
*/
static int s3c24xx_gpiolib_input(struct gpio_chip *chip, unsigned offset)
{
struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip);
void __iomem *base = ourchip->base;
unsigned long flags;
unsigned long con;
local_irq_save(flags);
con = __raw_readl(base + 0x00);
con &= ~(3 << (offset * 2));
con |= (S3C2410_GPIO_OUTPUT & 0xf) << (offset * 2);
__raw_writel(con, base + 0x00);
local_irq_restore(flags);
return 0;
}
static int s3c24xx_gpiolib_output(struct gpio_chip *chip,
unsigned offset, int value)
{
struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip);
void __iomem *base = ourchip->base;
unsigned long flags;
unsigned long dat;
unsigned long con;
local_irq_save(flags);
dat = __raw_readl(base + 0x04);
dat &= ~(1 << offset);
if (value)
dat |= 1 << offset;
__raw_writel(dat, base + 0x04);
con = __raw_readl(base + 0x00);
con &= ~(3 << (offset * 2));
con |= (S3C2410_GPIO_OUTPUT & 0xf) << (offset * 2);
__raw_writel(con, base + 0x00);
__raw_writel(dat, base + 0x04);
local_irq_restore(flags);
return 0;
}
static void s3c24xx_gpiolib_set(struct gpio_chip *chip,
unsigned offset, int value)
{
struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip);
void __iomem *base = ourchip->base;
unsigned long flags;
unsigned long dat;
local_irq_save(flags);
dat = __raw_readl(base + 0x04);
dat &= ~(1 << offset);
if (value)
dat |= 1 << offset;
__raw_writel(dat, base + 0x04);
local_irq_restore(flags);
}
static int s3c24xx_gpiolib_get(struct gpio_chip *chip, unsigned offset)
{
struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip);
unsigned long val;
val = __raw_readl(ourchip->base + 0x04);
val >>= offset;
val &= 1;
return val;
}
static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
{
return -EINVAL;
}
static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
unsigned offset, int value)
{
struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip);
void __iomem *base = ourchip->base;
unsigned long flags;
unsigned long dat;
unsigned long con;
local_irq_save(flags);
con = __raw_readl(base + 0x00);
dat = __raw_readl(base + 0x04);
dat &= ~(1 << offset);
if (value)
dat |= 1 << offset;
__raw_writel(dat, base + 0x04);
con &= ~(1 << offset);
__raw_writel(con, base + 0x00);
__raw_writel(dat, base + 0x04);
local_irq_restore(flags);
return 0;
}
static struct s3c24xx_gpio_chip gpios[] = {
[0] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPA0),
.chip = {
.base = S3C2410_GPA0,
.owner = THIS_MODULE,
.label = "GPIOA",
.ngpio = 24,
.direction_input = s3c24xx_gpiolib_banka_input,
.direction_output = s3c24xx_gpiolib_banka_output,
},
},
[1] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPB0),
.chip = {
.base = S3C2410_GPB0,
.owner = THIS_MODULE,
.label = "GPIOB",
.ngpio = 16,
},
},
[2] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPC0),
.chip = {
.base = S3C2410_GPC0,
.owner = THIS_MODULE,
.label = "GPIOC",
.ngpio = 16,
},
},
[3] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPD0),
.chip = {
.base = S3C2410_GPD0,
.owner = THIS_MODULE,
.label = "GPIOD",
.ngpio = 16,
},
},
[4] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPE0),
.chip = {
.base = S3C2410_GPE0,
.label = "GPIOE",
.owner = THIS_MODULE,
.ngpio = 16,
},
},
[5] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPF0),
.chip = {
.base = S3C2410_GPF0,
.owner = THIS_MODULE,
.label = "GPIOF",
.ngpio = 8,
},
},
[6] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPG0),
.chip = {
.base = S3C2410_GPG0,
.owner = THIS_MODULE,
.label = "GPIOG",
.ngpio = 10,
},
},
};
static __init void s3c24xx_gpiolib_add(struct s3c24xx_gpio_chip *chip)
{
struct gpio_chip *gc = &chip->chip;
BUG_ON(!chip->base);
BUG_ON(!gc->label);
BUG_ON(!gc->ngpio);
if (!gc->direction_input)
gc->direction_input = s3c24xx_gpiolib_input;
if (!gc->direction_output)
gc->direction_output = s3c24xx_gpiolib_output;
if (!gc->set)
gc->set = s3c24xx_gpiolib_set;
if (!gc->get)
gc->get = s3c24xx_gpiolib_get;
/* gpiochip_add() prints own failure message on error. */
gpiochip_add(gc);
}
static __init int s3c24xx_gpiolib_init(void)
{
struct s3c24xx_gpio_chip *chip = gpios;
int gpn;
for (gpn = 0; gpn < ARRAY_SIZE(gpios); gpn++, chip++)
s3c24xx_gpiolib_add(chip);
return 0;
}
arch_initcall(s3c24xx_gpiolib_init);