1/* linux/arch/arm/plat-s3c24xx/gpio.c 2 * 3 * Copyright (c) 2004-2005 Simtec Electronics 4 * Ben Dooks <ben@simtec.co.uk> 5 * 6 * S3C24XX GPIO support 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21*/ 22 23 24#include <linux/kernel.h> 25#include <linux/init.h> 26#include <linux/module.h> 27#include <linux/interrupt.h> 28#include <linux/ioport.h> 29#include <linux/io.h> 30 31#include <mach/hardware.h> 32#include <mach/gpio-fns.h> 33#include <asm/irq.h> 34 35#include <mach/regs-gpio.h> 36 37void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function) 38{ 39 void __iomem *base = S3C24XX_GPIO_BASE(pin); 40 unsigned long mask; 41 unsigned long con; 42 unsigned long flags; 43 44 if (pin < S3C2410_GPIO_BANKB) { 45 mask = 1 << S3C2410_GPIO_OFFSET(pin); 46 } else { 47 mask = 3 << S3C2410_GPIO_OFFSET(pin)*2; 48 } 49 50 switch (function) { 51 case S3C2410_GPIO_LEAVE: 52 mask = 0; 53 function = 0; 54 break; 55 56 case S3C2410_GPIO_INPUT: 57 case S3C2410_GPIO_OUTPUT: 58 case S3C2410_GPIO_SFN2: 59 case S3C2410_GPIO_SFN3: 60 if (pin < S3C2410_GPIO_BANKB) { 61 function -= 1; 62 function &= 1; 63 function <<= S3C2410_GPIO_OFFSET(pin); 64 } else { 65 function &= 3; 66 function <<= S3C2410_GPIO_OFFSET(pin)*2; 67 } 68 } 69 70 /* modify the specified register wwith IRQs off */ 71 72 local_irq_save(flags); 73 74 con = __raw_readl(base + 0x00); 75 con &= ~mask; 76 con |= function; 77 78 __raw_writel(con, base + 0x00); 79 80 local_irq_restore(flags); 81} 82 83EXPORT_SYMBOL(s3c2410_gpio_cfgpin); 84 85unsigned int s3c2410_gpio_getcfg(unsigned int pin) 86{ 87 void __iomem *base = S3C24XX_GPIO_BASE(pin); 88 unsigned long val = __raw_readl(base); 89 90 if (pin < S3C2410_GPIO_BANKB) { 91 val >>= S3C2410_GPIO_OFFSET(pin); 92 val &= 1; 93 val += 1; 94 } else { 95 val >>= S3C2410_GPIO_OFFSET(pin)*2; 96 val &= 3; 97 } 98 99 return val | S3C2410_GPIO_INPUT; 100} 101 102EXPORT_SYMBOL(s3c2410_gpio_getcfg); 103 104void s3c2410_gpio_pullup(unsigned int pin, unsigned int to) 105{ 106 void __iomem *base = S3C24XX_GPIO_BASE(pin); 107 unsigned long offs = S3C2410_GPIO_OFFSET(pin); 108 unsigned long flags; 109 unsigned long up; 110 111 if (pin < S3C2410_GPIO_BANKB) 112 return; 113 114 local_irq_save(flags); 115 116 up = __raw_readl(base + 0x08); 117 up &= ~(1L << offs); 118 up |= to << offs; 119 __raw_writel(up, base + 0x08); 120 121 local_irq_restore(flags); 122} 123 124EXPORT_SYMBOL(s3c2410_gpio_pullup); 125 126int s3c2410_gpio_getpull(unsigned int pin) 127{ 128 void __iomem *base = S3C24XX_GPIO_BASE(pin); 129 unsigned long offs = S3C2410_GPIO_OFFSET(pin); 130 131 if (pin < S3C2410_GPIO_BANKB) 132 return -EINVAL; 133 134 return (__raw_readl(base + 0x08) & (1L << offs)) ? 1 : 0; 135} 136 137EXPORT_SYMBOL(s3c2410_gpio_getpull); 138 139void s3c2410_gpio_setpin(unsigned int pin, unsigned int to) 140{ 141 void __iomem *base = S3C24XX_GPIO_BASE(pin); 142 unsigned long offs = S3C2410_GPIO_OFFSET(pin); 143 unsigned long flags; 144 unsigned long dat; 145 146 local_irq_save(flags); 147 148 dat = __raw_readl(base + 0x04); 149 dat &= ~(1 << offs); 150 dat |= to << offs; 151 __raw_writel(dat, base + 0x04); 152 153 local_irq_restore(flags); 154} 155 156EXPORT_SYMBOL(s3c2410_gpio_setpin); 157 158unsigned int s3c2410_gpio_getpin(unsigned int pin) 159{ 160 void __iomem *base = S3C24XX_GPIO_BASE(pin); 161 unsigned long offs = S3C2410_GPIO_OFFSET(pin); 162 163 return __raw_readl(base + 0x04) & (1<< offs); 164} 165 166EXPORT_SYMBOL(s3c2410_gpio_getpin); 167 168unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change) 169{ 170 unsigned long flags; 171 unsigned long misccr; 172 173 local_irq_save(flags); 174 misccr = __raw_readl(S3C24XX_MISCCR); 175 misccr &= ~clear; 176 misccr ^= change; 177 __raw_writel(misccr, S3C24XX_MISCCR); 178 local_irq_restore(flags); 179 180 return misccr; 181} 182 183EXPORT_SYMBOL(s3c2410_modify_misccr); 184 185int s3c2410_gpio_getirq(unsigned int pin) 186{ 187 if (pin < S3C2410_GPF(0) || pin > S3C2410_GPG(15)) 188 return -EINVAL; /* not valid interrupts */ 189 190 if (pin < S3C2410_GPG(0) && pin > S3C2410_GPF(7)) 191 return -EINVAL; /* not valid pin */ 192 193 if (pin < S3C2410_GPF(4)) 194 return (pin - S3C2410_GPF(0)) + IRQ_EINT0; 195 196 if (pin < S3C2410_GPG(0)) 197 return (pin - S3C2410_GPF(4)) + IRQ_EINT4; 198 199 return (pin - S3C2410_GPG(0)) + IRQ_EINT8; 200} 201 202EXPORT_SYMBOL(s3c2410_gpio_getirq); 203