2007-02-11 18:31:01 +01:00
/* linux/arch/arm/plat-s3c24xx/gpio.c
*
* Copyright ( c ) 2004 - 2005 Simtec Electronics
* Ben Dooks < ben @ simtec . co . uk >
*
* S3C24XX GPIO 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 , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/module.h>
# include <linux/interrupt.h>
# include <linux/ioport.h>
2008-09-06 12:10:45 +01:00
# include <linux/io.h>
2007-02-11 18:31:01 +01:00
2008-08-05 16:14:15 +01:00
# include <mach/hardware.h>
2009-10-26 21:17:15 +00:00
# include <mach/gpio-fns.h>
2007-02-11 18:31:01 +01:00
# include <asm/irq.h>
2008-08-05 16:14:15 +01:00
# include <mach/regs-gpio.h>
2007-02-11 18:31:01 +01:00
void s3c2410_gpio_cfgpin ( unsigned int pin , unsigned int function )
{
void __iomem * base = S3C24XX_GPIO_BASE ( pin ) ;
unsigned long mask ;
unsigned long con ;
unsigned long flags ;
if ( pin < S3C2410_GPIO_BANKB ) {
mask = 1 < < S3C2410_GPIO_OFFSET ( pin ) ;
} else {
mask = 3 < < S3C2410_GPIO_OFFSET ( pin ) * 2 ;
}
switch ( function ) {
case S3C2410_GPIO_LEAVE :
mask = 0 ;
function = 0 ;
break ;
case S3C2410_GPIO_INPUT :
case S3C2410_GPIO_OUTPUT :
case S3C2410_GPIO_SFN2 :
case S3C2410_GPIO_SFN3 :
if ( pin < S3C2410_GPIO_BANKB ) {
function - = 1 ;
function & = 1 ;
function < < = S3C2410_GPIO_OFFSET ( pin ) ;
} else {
function & = 3 ;
function < < = S3C2410_GPIO_OFFSET ( pin ) * 2 ;
}
}
/* modify the specified register wwith IRQs off */
local_irq_save ( flags ) ;
con = __raw_readl ( base + 0x00 ) ;
con & = ~ mask ;
con | = function ;
__raw_writel ( con , base + 0x00 ) ;
local_irq_restore ( flags ) ;
}
EXPORT_SYMBOL ( s3c2410_gpio_cfgpin ) ;
unsigned int s3c2410_gpio_getcfg ( unsigned int pin )
{
void __iomem * base = S3C24XX_GPIO_BASE ( pin ) ;
unsigned long val = __raw_readl ( base ) ;
if ( pin < S3C2410_GPIO_BANKB ) {
val > > = S3C2410_GPIO_OFFSET ( pin ) ;
val & = 1 ;
val + = 1 ;
} else {
val > > = S3C2410_GPIO_OFFSET ( pin ) * 2 ;
val & = 3 ;
}
return val | S3C2410_GPIO_INPUT ;
}
EXPORT_SYMBOL ( s3c2410_gpio_getcfg ) ;
void s3c2410_gpio_pullup ( unsigned int pin , unsigned int to )
{
void __iomem * base = S3C24XX_GPIO_BASE ( pin ) ;
unsigned long offs = S3C2410_GPIO_OFFSET ( pin ) ;
unsigned long flags ;
unsigned long up ;
if ( pin < S3C2410_GPIO_BANKB )
return ;
local_irq_save ( flags ) ;
up = __raw_readl ( base + 0x08 ) ;
up & = ~ ( 1L < < offs ) ;
up | = to < < offs ;
__raw_writel ( up , base + 0x08 ) ;
local_irq_restore ( flags ) ;
}
EXPORT_SYMBOL ( s3c2410_gpio_pullup ) ;
2008-01-28 13:01:23 +01:00
int s3c2410_gpio_getpull ( unsigned int pin )
{
void __iomem * base = S3C24XX_GPIO_BASE ( pin ) ;
unsigned long offs = S3C2410_GPIO_OFFSET ( pin ) ;
if ( pin < S3C2410_GPIO_BANKB )
return - EINVAL ;
return ( __raw_readl ( base + 0x08 ) & ( 1L < < offs ) ) ? 1 : 0 ;
}
EXPORT_SYMBOL ( s3c2410_gpio_getpull ) ;
2007-02-11 18:31:01 +01:00
void s3c2410_gpio_setpin ( unsigned int pin , unsigned int to )
{
void __iomem * base = S3C24XX_GPIO_BASE ( pin ) ;
unsigned long offs = S3C2410_GPIO_OFFSET ( pin ) ;
unsigned long flags ;
unsigned long dat ;
local_irq_save ( flags ) ;
dat = __raw_readl ( base + 0x04 ) ;
dat & = ~ ( 1 < < offs ) ;
dat | = to < < offs ;
__raw_writel ( dat , base + 0x04 ) ;
local_irq_restore ( flags ) ;
}
EXPORT_SYMBOL ( s3c2410_gpio_setpin ) ;
unsigned int s3c2410_gpio_getpin ( unsigned int pin )
{
void __iomem * base = S3C24XX_GPIO_BASE ( pin ) ;
unsigned long offs = S3C2410_GPIO_OFFSET ( pin ) ;
return __raw_readl ( base + 0x04 ) & ( 1 < < offs ) ;
}
EXPORT_SYMBOL ( s3c2410_gpio_getpin ) ;
unsigned int s3c2410_modify_misccr ( unsigned int clear , unsigned int change )
{
unsigned long flags ;
unsigned long misccr ;
local_irq_save ( flags ) ;
misccr = __raw_readl ( S3C24XX_MISCCR ) ;
misccr & = ~ clear ;
misccr ^ = change ;
__raw_writel ( misccr , S3C24XX_MISCCR ) ;
local_irq_restore ( flags ) ;
return misccr ;
}
EXPORT_SYMBOL ( s3c2410_modify_misccr ) ;
int s3c2410_gpio_getirq ( unsigned int pin )
{
2009-05-17 22:32:23 +01:00
if ( pin < S3C2410_GPF ( 0 ) | | pin > S3C2410_GPG ( 15 ) )
2009-05-18 19:40:18 +01:00
return - EINVAL ; /* not valid interrupts */
2007-02-11 18:31:01 +01:00
2009-05-17 22:32:23 +01:00
if ( pin < S3C2410_GPG ( 0 ) & & pin > S3C2410_GPF ( 7 ) )
2009-05-18 19:40:18 +01:00
return - EINVAL ; /* not valid pin */
2007-02-11 18:31:01 +01:00
2009-05-17 22:32:23 +01:00
if ( pin < S3C2410_GPF ( 4 ) )
return ( pin - S3C2410_GPF ( 0 ) ) + IRQ_EINT0 ;
2007-02-11 18:31:01 +01:00
2009-05-17 22:32:23 +01:00
if ( pin < S3C2410_GPG ( 0 ) )
return ( pin - S3C2410_GPF ( 4 ) ) + IRQ_EINT4 ;
2007-02-11 18:31:01 +01:00
2009-05-17 22:32:23 +01:00
return ( pin - S3C2410_GPG ( 0 ) ) + IRQ_EINT8 ;
2007-02-11 18:31:01 +01:00
}
EXPORT_SYMBOL ( s3c2410_gpio_getirq ) ;