-
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.
ARM: S5P6440: Add S5P6440 GPIO support
This patch adds Samsung's S5P6440 GPIO support. Signed-off-by: Adityapratap Sharma <aditya.ps@samsung.com> Signed-off-by: Atul Dahiya <atul.dahiya@samsung.com> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
- Loading branch information
Kukjin Kim
authored and
Ben Dooks
committed
Jan 19, 2010
1 parent
1f323cf
commit 42d828d
Showing
4 changed files
with
381 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* linux/arch/arm/mach-s5p6440/include/mach/regs-gpio.h | ||
* | ||
* Copyright (c) 2009 Samsung Electronics Co., Ltd. | ||
* http://www.samsung.com/ | ||
* | ||
* S5P6440 - GPIO register definitions | ||
* | ||
* 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. | ||
*/ | ||
|
||
#ifndef __ASM_ARCH_REGS_GPIO_H | ||
#define __ASM_ARCH_REGS_GPIO_H __FILE__ | ||
|
||
#include <mach/map.h> | ||
|
||
/* Base addresses for each of the banks */ | ||
#define S5P6440_GPA_BASE (S5P_VA_GPIO + 0x0000) | ||
#define S5P6440_GPB_BASE (S5P_VA_GPIO + 0x0020) | ||
#define S5P6440_GPC_BASE (S5P_VA_GPIO + 0x0040) | ||
#define S5P6440_GPF_BASE (S5P_VA_GPIO + 0x00A0) | ||
#define S5P6440_GPG_BASE (S5P_VA_GPIO + 0x00C0) | ||
#define S5P6440_GPH_BASE (S5P_VA_GPIO + 0x00E0) | ||
#define S5P6440_GPI_BASE (S5P_VA_GPIO + 0x0100) | ||
#define S5P6440_GPJ_BASE (S5P_VA_GPIO + 0x0120) | ||
#define S5P6440_GPN_BASE (S5P_VA_GPIO + 0x0830) | ||
#define S5P6440_GPP_BASE (S5P_VA_GPIO + 0x0160) | ||
#define S5P6440_GPR_BASE (S5P_VA_GPIO + 0x0290) | ||
#define S5P6440_EINT0CON0 (S5P_VA_GPIO + 0x900) | ||
#define S5P6440_EINT0FLTCON0 (S5P_VA_GPIO + 0x910) | ||
#define S5P6440_EINT0FLTCON1 (S5P_VA_GPIO + 0x914) | ||
#define S5P6440_EINT0MASK (S5P_VA_GPIO + 0x920) | ||
#define S5P6440_EINT0PEND (S5P_VA_GPIO + 0x924) | ||
|
||
/* for LCD */ | ||
#define S5P6440_SPCON_LCD_SEL_RGB (1 << 0) | ||
#define S5P6440_SPCON_LCD_SEL_MASK (3 << 0) | ||
|
||
/* These set of macros are not really useful for the | ||
* GPF/GPI/GPJ/GPN/GPP, | ||
* useful for others set of GPIO's (4 bit) | ||
*/ | ||
#define S5P6440_GPIO_CONMASK(__gpio) (0xf << ((__gpio) * 4)) | ||
#define S5P6440_GPIO_INPUT(__gpio) (0x0 << ((__gpio) * 4)) | ||
#define S5P6440_GPIO_OUTPUT(__gpio) (0x1 << ((__gpio) * 4)) | ||
|
||
/* Use these macros for GPF/GPI/GPJ/GPN/GPP set of GPIO (2 bit) | ||
* */ | ||
#define S5P6440_GPIO2_CONMASK(__gpio) (0x3 << ((__gpio) * 2)) | ||
#define S5P6440_GPIO2_INPUT(__gpio) (0x0 << ((__gpio) * 2)) | ||
#define S5P6440_GPIO2_OUTPUT(__gpio) (0x1 << ((__gpio) * 2)) | ||
|
||
#endif /* __ASM_ARCH_REGS_GPIO_H */ |
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,322 @@ | ||
/* arch/arm/mach-s5p6440/s5p6440-gpio.c | ||
* | ||
* Copyright (c) 2009 Samsung Electronics Co., Ltd. | ||
* http://www.samsung.com/ | ||
* | ||
* S5P6440 - GPIOlib support | ||
* | ||
* 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/kernel.h> | ||
#include <linux/irq.h> | ||
#include <linux/io.h> | ||
#include <mach/map.h> | ||
#include <mach/gpio.h> | ||
#include <mach/regs-gpio.h> | ||
#include <plat/gpio-core.h> | ||
#include <plat/gpio-cfg.h> | ||
#include <plat/gpio-cfg-helpers.h> | ||
|
||
/* GPIO bank summary: | ||
* | ||
* Bank GPIOs Style SlpCon ExtInt Group | ||
* A 6 4Bit Yes 1 | ||
* B 7 4Bit Yes 1 | ||
* C 8 4Bit Yes 2 | ||
* F 2 2Bit Yes 4 [1] | ||
* G 7 4Bit Yes 5 | ||
* H 10 4Bit[2] Yes 6 | ||
* I 16 2Bit Yes None | ||
* J 12 2Bit Yes None | ||
* N 16 2Bit No IRQ_EINT | ||
* P 8 2Bit Yes 8 | ||
* R 15 4Bit[2] Yes 8 | ||
* | ||
* [1] BANKF pins 14,15 do not form part of the external interrupt sources | ||
* [2] BANK has two control registers, GPxCON0 and GPxCON1 | ||
*/ | ||
|
||
static int s5p6440_gpiolib_rbank_4bit2_input(struct gpio_chip *chip, | ||
unsigned int offset) | ||
{ | ||
struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
void __iomem *base = ourchip->base; | ||
void __iomem *regcon = base; | ||
unsigned long con; | ||
|
||
switch (offset) { | ||
case 6: | ||
offset += 1; | ||
case 0: | ||
case 1: | ||
case 2: | ||
case 3: | ||
case 4: | ||
case 5: | ||
regcon -= 4; | ||
break; | ||
default: | ||
offset -= 7; | ||
break; | ||
} | ||
|
||
con = __raw_readl(regcon); | ||
con &= ~(0xf << con_4bit_shift(offset)); | ||
__raw_writel(con, regcon); | ||
|
||
return 0; | ||
} | ||
|
||
static int s5p6440_gpiolib_rbank_4bit2_output(struct gpio_chip *chip, | ||
unsigned int offset, int value) | ||
{ | ||
struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
void __iomem *base = ourchip->base; | ||
void __iomem *regcon = base; | ||
unsigned long con; | ||
unsigned long dat; | ||
unsigned con_offset = offset; | ||
|
||
switch (con_offset) { | ||
case 6: | ||
con_offset += 1; | ||
case 0: | ||
case 1: | ||
case 2: | ||
case 3: | ||
case 4: | ||
case 5: | ||
regcon -= 4; | ||
break; | ||
default: | ||
con_offset -= 7; | ||
break; | ||
} | ||
|
||
con = __raw_readl(regcon); | ||
con &= ~(0xf << con_4bit_shift(con_offset)); | ||
con |= 0x1 << con_4bit_shift(con_offset); | ||
|
||
dat = __raw_readl(base + GPIODAT_OFF); | ||
if (value) | ||
dat |= 1 << offset; | ||
else | ||
dat &= ~(1 << offset); | ||
|
||
__raw_writel(con, regcon); | ||
__raw_writel(dat, base + GPIODAT_OFF); | ||
|
||
return 0; | ||
} | ||
|
||
int s5p6440_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip, | ||
unsigned int off, unsigned int cfg) | ||
{ | ||
void __iomem *reg = chip->base; | ||
unsigned int shift; | ||
u32 con; | ||
|
||
switch (off) { | ||
case 0: | ||
case 1: | ||
case 2: | ||
case 3: | ||
case 4: | ||
case 5: | ||
shift = (off & 7) * 4; | ||
reg -= 4; | ||
break; | ||
case 6: | ||
shift = ((off + 1) & 7) * 4; | ||
reg -= 4; | ||
default: | ||
shift = ((off + 1) & 7) * 4; | ||
break; | ||
} | ||
|
||
if (s3c_gpio_is_cfg_special(cfg)) { | ||
cfg &= 0xf; | ||
cfg <<= shift; | ||
} | ||
|
||
con = __raw_readl(reg); | ||
con &= ~(0xf << shift); | ||
con |= cfg; | ||
__raw_writel(con, reg); | ||
|
||
return 0; | ||
} | ||
|
||
static struct s3c_gpio_cfg s5p6440_gpio_cfgs[] = { | ||
{ | ||
.cfg_eint = 0, | ||
}, { | ||
.cfg_eint = 7, | ||
}, { | ||
.cfg_eint = 3, | ||
.set_config = s5p6440_gpio_setcfg_4bit_rbank, | ||
}, { | ||
.cfg_eint = 0, | ||
.set_config = s3c_gpio_setcfg_s3c24xx, | ||
}, { | ||
.cfg_eint = 2, | ||
.set_config = s3c_gpio_setcfg_s3c24xx, | ||
}, { | ||
.cfg_eint = 3, | ||
.set_config = s3c_gpio_setcfg_s3c24xx, | ||
}, | ||
}; | ||
|
||
static struct s3c_gpio_chip s5p6440_gpio_4bit[] = { | ||
{ | ||
.base = S5P6440_GPA_BASE, | ||
.config = &s5p6440_gpio_cfgs[1], | ||
.chip = { | ||
.base = S5P6440_GPA(0), | ||
.ngpio = S5P6440_GPIO_A_NR, | ||
.label = "GPA", | ||
}, | ||
}, { | ||
.base = S5P6440_GPB_BASE, | ||
.config = &s5p6440_gpio_cfgs[1], | ||
.chip = { | ||
.base = S5P6440_GPB(0), | ||
.ngpio = S5P6440_GPIO_B_NR, | ||
.label = "GPB", | ||
}, | ||
}, { | ||
.base = S5P6440_GPC_BASE, | ||
.config = &s5p6440_gpio_cfgs[1], | ||
.chip = { | ||
.base = S5P6440_GPC(0), | ||
.ngpio = S5P6440_GPIO_C_NR, | ||
.label = "GPC", | ||
}, | ||
}, { | ||
.base = S5P6440_GPG_BASE, | ||
.config = &s5p6440_gpio_cfgs[1], | ||
.chip = { | ||
.base = S5P6440_GPG(0), | ||
.ngpio = S5P6440_GPIO_G_NR, | ||
.label = "GPG", | ||
}, | ||
}, | ||
}; | ||
|
||
static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = { | ||
{ | ||
.base = S5P6440_GPH_BASE + 0x4, | ||
.config = &s5p6440_gpio_cfgs[1], | ||
.chip = { | ||
.base = S5P6440_GPH(0), | ||
.ngpio = S5P6440_GPIO_H_NR, | ||
.label = "GPH", | ||
}, | ||
}, | ||
}; | ||
|
||
static struct s3c_gpio_chip gpio_rbank_4bit2[] = { | ||
{ | ||
.base = S5P6440_GPR_BASE + 0x4, | ||
.config = &s5p6440_gpio_cfgs[2], | ||
.chip = { | ||
.base = S5P6440_GPR(0), | ||
.ngpio = S5P6440_GPIO_R_NR, | ||
.label = "GPR", | ||
}, | ||
}, | ||
}; | ||
|
||
static struct s3c_gpio_chip s5p6440_gpio_2bit[] = { | ||
{ | ||
.base = S5P6440_GPF_BASE, | ||
.config = &s5p6440_gpio_cfgs[5], | ||
.chip = { | ||
.base = S5P6440_GPF(0), | ||
.ngpio = S5P6440_GPIO_F_NR, | ||
.label = "GPF", | ||
}, | ||
}, { | ||
.base = S5P6440_GPI_BASE, | ||
.config = &s5p6440_gpio_cfgs[3], | ||
.chip = { | ||
.base = S5P6440_GPI(0), | ||
.ngpio = S5P6440_GPIO_I_NR, | ||
.label = "GPI", | ||
}, | ||
}, { | ||
.base = S5P6440_GPJ_BASE, | ||
.config = &s5p6440_gpio_cfgs[3], | ||
.chip = { | ||
.base = S5P6440_GPJ(0), | ||
.ngpio = S5P6440_GPIO_J_NR, | ||
.label = "GPJ", | ||
}, | ||
}, { | ||
.base = S5P6440_GPN_BASE, | ||
.config = &s5p6440_gpio_cfgs[4], | ||
.chip = { | ||
.base = S5P6440_GPN(0), | ||
.ngpio = S5P6440_GPIO_N_NR, | ||
.label = "GPN", | ||
}, | ||
}, { | ||
.base = S5P6440_GPP_BASE, | ||
.config = &s5p6440_gpio_cfgs[5], | ||
.chip = { | ||
.base = S5P6440_GPP(0), | ||
.ngpio = S5P6440_GPIO_P_NR, | ||
.label = "GPP", | ||
}, | ||
}, | ||
}; | ||
|
||
void __init s5p6440_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips) | ||
{ | ||
for (; nr_chips > 0; nr_chips--, chipcfg++) { | ||
if (!chipcfg->set_config) | ||
chipcfg->set_config = s3c_gpio_setcfg_s3c64xx_4bit; | ||
if (!chipcfg->set_pull) | ||
chipcfg->set_pull = s3c_gpio_setpull_updown; | ||
if (!chipcfg->get_pull) | ||
chipcfg->get_pull = s3c_gpio_getpull_updown; | ||
} | ||
} | ||
|
||
static void __init s5p6440_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip, | ||
int nr_chips) | ||
{ | ||
for (; nr_chips > 0; nr_chips--, chip++) { | ||
chip->chip.direction_input = s5p6440_gpiolib_rbank_4bit2_input; | ||
chip->chip.direction_output = | ||
s5p6440_gpiolib_rbank_4bit2_output; | ||
s3c_gpiolib_add(chip); | ||
} | ||
} | ||
|
||
static int __init s5p6440_gpiolib_init(void) | ||
{ | ||
struct s3c_gpio_chip *chips = s5p6440_gpio_2bit; | ||
int nr_chips = ARRAY_SIZE(s5p6440_gpio_2bit); | ||
|
||
s5p6440_gpiolib_set_cfg(s5p6440_gpio_cfgs, | ||
ARRAY_SIZE(s5p6440_gpio_cfgs)); | ||
|
||
for (; nr_chips > 0; nr_chips--, chips++) | ||
s3c_gpiolib_add(chips); | ||
|
||
samsung_gpiolib_add_4bit_chips(s5p6440_gpio_4bit, | ||
ARRAY_SIZE(s5p6440_gpio_4bit)); | ||
|
||
samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2, | ||
ARRAY_SIZE(s5p6440_gpio_4bit2)); | ||
|
||
s5p6440_gpio_add_rbank_4bit2(gpio_rbank_4bit2, | ||
ARRAY_SIZE(gpio_rbank_4bit2)); | ||
|
||
return 0; | ||
} | ||
arch_initcall(s5p6440_gpiolib_init); |
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