1/* arch/arm/plat-s3c64xx/gpiolib.c 2 * 3 * Copyright 2008 Openmoko, Inc. 4 * Copyright 2008 Simtec Electronics 5 * Ben Dooks <ben@simtec.co.uk> 6 * http://armlinux.simtec.co.uk/ 7 * 8 * S3C64XX - GPIOlib support 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 15#include <linux/kernel.h> 16#include <linux/irq.h> 17#include <linux/io.h> 18#include <linux/gpio.h> 19 20#include <mach/map.h> 21 22#include <plat/gpio-core.h> 23#include <plat/gpio-cfg.h> 24#include <plat/gpio-cfg-helpers.h> 25#include <mach/regs-gpio.h> 26 27/* GPIO bank summary: 28 * 29 * Bank GPIOs Style SlpCon ExtInt Group 30 * A 8 4Bit Yes 1 31 * B 7 4Bit Yes 1 32 * C 8 4Bit Yes 2 33 * D 5 4Bit Yes 3 34 * E 5 4Bit Yes None 35 * F 16 2Bit Yes 4 [1] 36 * G 7 4Bit Yes 5 37 * H 10 4Bit[2] Yes 6 38 * I 16 2Bit Yes None 39 * J 12 2Bit Yes None 40 * K 16 4Bit[2] No None 41 * L 15 4Bit[2] No None 42 * M 6 4Bit No IRQ_EINT 43 * N 16 2Bit No IRQ_EINT 44 * O 16 2Bit Yes 7 45 * P 15 2Bit Yes 8 46 * Q 9 2Bit Yes 9 47 * 48 * [1] BANKF pins 14,15 do not form part of the external interrupt sources 49 * [2] BANK has two control registers, GPxCON0 and GPxCON1 50 */ 51 52static struct s3c_gpio_cfg gpio_4bit_cfg_noint = { 53 .set_config = s3c_gpio_setcfg_s3c64xx_4bit, 54 .get_config = s3c_gpio_getcfg_s3c64xx_4bit, 55 .set_pull = s3c_gpio_setpull_updown, 56 .get_pull = s3c_gpio_getpull_updown, 57}; 58 59static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = { 60 .cfg_eint = 7, 61 .set_config = s3c_gpio_setcfg_s3c64xx_4bit, 62 .get_config = s3c_gpio_getcfg_s3c64xx_4bit, 63 .set_pull = s3c_gpio_setpull_updown, 64 .get_pull = s3c_gpio_getpull_updown, 65}; 66 67static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = { 68 .cfg_eint = 3, 69 .get_config = s3c_gpio_getcfg_s3c64xx_4bit, 70 .set_config = s3c_gpio_setcfg_s3c64xx_4bit, 71 .set_pull = s3c_gpio_setpull_updown, 72 .get_pull = s3c_gpio_getpull_updown, 73}; 74 75int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin) 76{ 77 return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO; 78} 79 80static struct s3c_gpio_chip gpio_4bit[] = { 81 { 82 .base = S3C64XX_GPA_BASE, 83 .config = &gpio_4bit_cfg_eint0111, 84 .chip = { 85 .base = S3C64XX_GPA(0), 86 .ngpio = S3C64XX_GPIO_A_NR, 87 .label = "GPA", 88 }, 89 }, { 90 .base = S3C64XX_GPB_BASE, 91 .config = &gpio_4bit_cfg_eint0111, 92 .chip = { 93 .base = S3C64XX_GPB(0), 94 .ngpio = S3C64XX_GPIO_B_NR, 95 .label = "GPB", 96 }, 97 }, { 98 .base = S3C64XX_GPC_BASE, 99 .config = &gpio_4bit_cfg_eint0111, 100 .chip = { 101 .base = S3C64XX_GPC(0), 102 .ngpio = S3C64XX_GPIO_C_NR, 103 .label = "GPC", 104 }, 105 }, { 106 .base = S3C64XX_GPD_BASE, 107 .config = &gpio_4bit_cfg_eint0111, 108 .chip = { 109 .base = S3C64XX_GPD(0), 110 .ngpio = S3C64XX_GPIO_D_NR, 111 .label = "GPD", 112 }, 113 }, { 114 .base = S3C64XX_GPE_BASE, 115 .config = &gpio_4bit_cfg_noint, 116 .chip = { 117 .base = S3C64XX_GPE(0), 118 .ngpio = S3C64XX_GPIO_E_NR, 119 .label = "GPE", 120 }, 121 }, { 122 .base = S3C64XX_GPG_BASE, 123 .config = &gpio_4bit_cfg_eint0111, 124 .chip = { 125 .base = S3C64XX_GPG(0), 126 .ngpio = S3C64XX_GPIO_G_NR, 127 .label = "GPG", 128 }, 129 }, { 130 .base = S3C64XX_GPM_BASE, 131 .config = &gpio_4bit_cfg_eint0011, 132 .chip = { 133 .base = S3C64XX_GPM(0), 134 .ngpio = S3C64XX_GPIO_M_NR, 135 .label = "GPM", 136 .to_irq = s3c64xx_gpio2int_gpm, 137 }, 138 }, 139}; 140 141int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin) 142{ 143 return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO; 144} 145 146static struct s3c_gpio_chip gpio_4bit2[] = { 147 { 148 .base = S3C64XX_GPH_BASE + 0x4, 149 .config = &gpio_4bit_cfg_eint0111, 150 .chip = { 151 .base = S3C64XX_GPH(0), 152 .ngpio = S3C64XX_GPIO_H_NR, 153 .label = "GPH", 154 }, 155 }, { 156 .base = S3C64XX_GPK_BASE + 0x4, 157 .config = &gpio_4bit_cfg_noint, 158 .chip = { 159 .base = S3C64XX_GPK(0), 160 .ngpio = S3C64XX_GPIO_K_NR, 161 .label = "GPK", 162 }, 163 }, { 164 .base = S3C64XX_GPL_BASE + 0x4, 165 .config = &gpio_4bit_cfg_eint0011, 166 .chip = { 167 .base = S3C64XX_GPL(0), 168 .ngpio = S3C64XX_GPIO_L_NR, 169 .label = "GPL", 170 .to_irq = s3c64xx_gpio2int_gpl, 171 }, 172 }, 173}; 174 175static struct s3c_gpio_cfg gpio_2bit_cfg_noint = { 176 .set_config = s3c_gpio_setcfg_s3c24xx, 177 .get_config = s3c_gpio_getcfg_s3c24xx, 178 .set_pull = s3c_gpio_setpull_updown, 179 .get_pull = s3c_gpio_getpull_updown, 180}; 181 182static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = { 183 .cfg_eint = 2, 184 .set_config = s3c_gpio_setcfg_s3c24xx, 185 .get_config = s3c_gpio_getcfg_s3c24xx, 186 .set_pull = s3c_gpio_setpull_updown, 187 .get_pull = s3c_gpio_getpull_updown, 188}; 189 190static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = { 191 .cfg_eint = 3, 192 .set_config = s3c_gpio_setcfg_s3c24xx, 193 .get_config = s3c_gpio_getcfg_s3c24xx, 194 .set_pull = s3c_gpio_setpull_updown, 195 .get_pull = s3c_gpio_getpull_updown, 196}; 197 198int s3c64xx_gpio2int_gpn(struct gpio_chip *chip, unsigned pin) 199{ 200 return IRQ_EINT(0) + pin; 201} 202 203static struct s3c_gpio_chip gpio_2bit[] = { 204 { 205 .base = S3C64XX_GPF_BASE, 206 .config = &gpio_2bit_cfg_eint11, 207 .chip = { 208 .base = S3C64XX_GPF(0), 209 .ngpio = S3C64XX_GPIO_F_NR, 210 .label = "GPF", 211 }, 212 }, { 213 .base = S3C64XX_GPI_BASE, 214 .config = &gpio_2bit_cfg_noint, 215 .chip = { 216 .base = S3C64XX_GPI(0), 217 .ngpio = S3C64XX_GPIO_I_NR, 218 .label = "GPI", 219 }, 220 }, { 221 .base = S3C64XX_GPJ_BASE, 222 .config = &gpio_2bit_cfg_noint, 223 .chip = { 224 .base = S3C64XX_GPJ(0), 225 .ngpio = S3C64XX_GPIO_J_NR, 226 .label = "GPJ", 227 }, 228 }, { 229 .base = S3C64XX_GPN_BASE, 230 .config = &gpio_2bit_cfg_eint10, 231 .chip = { 232 .base = S3C64XX_GPN(0), 233 .ngpio = S3C64XX_GPIO_N_NR, 234 .label = "GPN", 235 .to_irq = s3c64xx_gpio2int_gpn, 236 }, 237 }, { 238 .base = S3C64XX_GPO_BASE, 239 .config = &gpio_2bit_cfg_eint11, 240 .chip = { 241 .base = S3C64XX_GPO(0), 242 .ngpio = S3C64XX_GPIO_O_NR, 243 .label = "GPO", 244 }, 245 }, { 246 .base = S3C64XX_GPP_BASE, 247 .config = &gpio_2bit_cfg_eint11, 248 .chip = { 249 .base = S3C64XX_GPP(0), 250 .ngpio = S3C64XX_GPIO_P_NR, 251 .label = "GPP", 252 }, 253 }, { 254 .base = S3C64XX_GPQ_BASE, 255 .config = &gpio_2bit_cfg_eint11, 256 .chip = { 257 .base = S3C64XX_GPQ(0), 258 .ngpio = S3C64XX_GPIO_Q_NR, 259 .label = "GPQ", 260 }, 261 }, 262}; 263 264static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip) 265{ 266 chip->pm = __gpio_pm(&s3c_gpio_pm_2bit); 267} 268 269static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips, 270 int nr_chips, 271 void (*fn)(struct s3c_gpio_chip *)) 272{ 273 for (; nr_chips > 0; nr_chips--, chips++) { 274 if (fn) 275 (fn)(chips); 276 s3c_gpiolib_add(chips); 277 } 278} 279 280static __init int s3c64xx_gpiolib_init(void) 281{ 282 s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit), 283 samsung_gpiolib_add_4bit); 284 285 s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2), 286 samsung_gpiolib_add_4bit2); 287 288 s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit), 289 s3c64xx_gpiolib_add_2bit); 290 291 return 0; 292} 293 294core_initcall(s3c64xx_gpiolib_init); 295