1 /* 2 * OMAP16xx specific gpio init 3 * 4 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ 5 * 6 * Author: 7 * Charulatha V <charu@ti.com> 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation version 2. 12 * 13 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 14 * kind, whether express or implied; without even the implied warranty 15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 */ 18 19 #include <linux/gpio.h> 20 21 #define OMAP1610_GPIO1_BASE 0xfffbe400 22 #define OMAP1610_GPIO2_BASE 0xfffbec00 23 #define OMAP1610_GPIO3_BASE 0xfffbb400 24 #define OMAP1610_GPIO4_BASE 0xfffbbc00 25 #define OMAP1_MPUIO_VBASE OMAP1_MPUIO_BASE 26 27 /* smart idle, enable wakeup */ 28 #define SYSCONFIG_WORD 0x14 29 30 /* mpu gpio */ 31 static struct __initdata resource omap16xx_mpu_gpio_resources[] = { 32 { 33 .start = OMAP1_MPUIO_VBASE, 34 .end = OMAP1_MPUIO_VBASE + SZ_2K - 1, 35 .flags = IORESOURCE_MEM, 36 }, 37 { 38 .start = INT_MPUIO, 39 .flags = IORESOURCE_IRQ, 40 }, 41 }; 42 43 static struct omap_gpio_reg_offs omap16xx_mpuio_regs = { 44 .revision = USHRT_MAX, 45 .direction = OMAP_MPUIO_IO_CNTL, 46 .datain = OMAP_MPUIO_INPUT_LATCH, 47 .dataout = OMAP_MPUIO_OUTPUT, 48 .irqstatus = OMAP_MPUIO_GPIO_INT, 49 .irqenable = OMAP_MPUIO_GPIO_MASKIT, 50 .irqenable_inv = true, 51 .irqctrl = OMAP_MPUIO_GPIO_INT_EDGE, 52 }; 53 54 static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = { 55 .is_mpuio = true, 56 .bank_width = 16, 57 .bank_stride = 1, 58 .regs = &omap16xx_mpuio_regs, 59 }; 60 61 static struct platform_device omap16xx_mpu_gpio = { 62 .name = "omap_gpio", 63 .id = 0, 64 .dev = { 65 .platform_data = &omap16xx_mpu_gpio_config, 66 }, 67 .num_resources = ARRAY_SIZE(omap16xx_mpu_gpio_resources), 68 .resource = omap16xx_mpu_gpio_resources, 69 }; 70 71 /* gpio1 */ 72 static struct __initdata resource omap16xx_gpio1_resources[] = { 73 { 74 .start = OMAP1610_GPIO1_BASE, 75 .end = OMAP1610_GPIO1_BASE + SZ_2K - 1, 76 .flags = IORESOURCE_MEM, 77 }, 78 { 79 .start = INT_GPIO_BANK1, 80 .flags = IORESOURCE_IRQ, 81 }, 82 }; 83 84 static struct omap_gpio_reg_offs omap16xx_gpio_regs = { 85 .revision = OMAP1610_GPIO_REVISION, 86 .direction = OMAP1610_GPIO_DIRECTION, 87 .set_dataout = OMAP1610_GPIO_SET_DATAOUT, 88 .clr_dataout = OMAP1610_GPIO_CLEAR_DATAOUT, 89 .datain = OMAP1610_GPIO_DATAIN, 90 .dataout = OMAP1610_GPIO_DATAOUT, 91 .irqstatus = OMAP1610_GPIO_IRQSTATUS1, 92 .irqenable = OMAP1610_GPIO_IRQENABLE1, 93 .set_irqenable = OMAP1610_GPIO_SET_IRQENABLE1, 94 .clr_irqenable = OMAP1610_GPIO_CLEAR_IRQENABLE1, 95 .wkup_en = OMAP1610_GPIO_WAKEUPENABLE, 96 .edgectrl1 = OMAP1610_GPIO_EDGE_CTRL1, 97 .edgectrl2 = OMAP1610_GPIO_EDGE_CTRL2, 98 }; 99 100 static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = { 101 .bank_width = 16, 102 .regs = &omap16xx_gpio_regs, 103 }; 104 105 static struct platform_device omap16xx_gpio1 = { 106 .name = "omap_gpio", 107 .id = 1, 108 .dev = { 109 .platform_data = &omap16xx_gpio1_config, 110 }, 111 .num_resources = ARRAY_SIZE(omap16xx_gpio1_resources), 112 .resource = omap16xx_gpio1_resources, 113 }; 114 115 /* gpio2 */ 116 static struct __initdata resource omap16xx_gpio2_resources[] = { 117 { 118 .start = OMAP1610_GPIO2_BASE, 119 .end = OMAP1610_GPIO2_BASE + SZ_2K - 1, 120 .flags = IORESOURCE_MEM, 121 }, 122 { 123 .start = INT_1610_GPIO_BANK2, 124 .flags = IORESOURCE_IRQ, 125 }, 126 }; 127 128 static struct __initdata omap_gpio_platform_data omap16xx_gpio2_config = { 129 .bank_width = 16, 130 .regs = &omap16xx_gpio_regs, 131 }; 132 133 static struct platform_device omap16xx_gpio2 = { 134 .name = "omap_gpio", 135 .id = 2, 136 .dev = { 137 .platform_data = &omap16xx_gpio2_config, 138 }, 139 .num_resources = ARRAY_SIZE(omap16xx_gpio2_resources), 140 .resource = omap16xx_gpio2_resources, 141 }; 142 143 /* gpio3 */ 144 static struct __initdata resource omap16xx_gpio3_resources[] = { 145 { 146 .start = OMAP1610_GPIO3_BASE, 147 .end = OMAP1610_GPIO3_BASE + SZ_2K - 1, 148 .flags = IORESOURCE_MEM, 149 }, 150 { 151 .start = INT_1610_GPIO_BANK3, 152 .flags = IORESOURCE_IRQ, 153 }, 154 }; 155 156 static struct __initdata omap_gpio_platform_data omap16xx_gpio3_config = { 157 .bank_width = 16, 158 .regs = &omap16xx_gpio_regs, 159 }; 160 161 static struct platform_device omap16xx_gpio3 = { 162 .name = "omap_gpio", 163 .id = 3, 164 .dev = { 165 .platform_data = &omap16xx_gpio3_config, 166 }, 167 .num_resources = ARRAY_SIZE(omap16xx_gpio3_resources), 168 .resource = omap16xx_gpio3_resources, 169 }; 170 171 /* gpio4 */ 172 static struct __initdata resource omap16xx_gpio4_resources[] = { 173 { 174 .start = OMAP1610_GPIO4_BASE, 175 .end = OMAP1610_GPIO4_BASE + SZ_2K - 1, 176 .flags = IORESOURCE_MEM, 177 }, 178 { 179 .start = INT_1610_GPIO_BANK4, 180 .flags = IORESOURCE_IRQ, 181 }, 182 }; 183 184 static struct __initdata omap_gpio_platform_data omap16xx_gpio4_config = { 185 .bank_width = 16, 186 .regs = &omap16xx_gpio_regs, 187 }; 188 189 static struct platform_device omap16xx_gpio4 = { 190 .name = "omap_gpio", 191 .id = 4, 192 .dev = { 193 .platform_data = &omap16xx_gpio4_config, 194 }, 195 .num_resources = ARRAY_SIZE(omap16xx_gpio4_resources), 196 .resource = omap16xx_gpio4_resources, 197 }; 198 199 static struct __initdata platform_device * omap16xx_gpio_dev[] = { 200 &omap16xx_mpu_gpio, 201 &omap16xx_gpio1, 202 &omap16xx_gpio2, 203 &omap16xx_gpio3, 204 &omap16xx_gpio4, 205 }; 206 207 /* 208 * omap16xx_gpio_init needs to be done before 209 * machine_init functions access gpio APIs. 210 * Hence omap16xx_gpio_init is a postcore_initcall. 211 */ 212 static int __init omap16xx_gpio_init(void) 213 { 214 int i; 215 void __iomem *base; 216 struct resource *res; 217 struct platform_device *pdev; 218 struct omap_gpio_platform_data *pdata; 219 220 if (!cpu_is_omap16xx()) 221 return -EINVAL; 222 223 /* 224 * Enable system clock for GPIO module. 225 * The CAM_CLK_CTRL *is* really the right place. 226 */ 227 omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, 228 ULPD_CAM_CLK_CTRL); 229 230 for (i = 0; i < ARRAY_SIZE(omap16xx_gpio_dev); i++) { 231 pdev = omap16xx_gpio_dev[i]; 232 pdata = pdev->dev.platform_data; 233 234 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 235 if (unlikely(!res)) { 236 dev_err(&pdev->dev, "Invalid mem resource.\n"); 237 return -ENODEV; 238 } 239 240 base = ioremap(res->start, resource_size(res)); 241 if (unlikely(!base)) { 242 dev_err(&pdev->dev, "ioremap failed.\n"); 243 return -ENOMEM; 244 } 245 246 __raw_writel(SYSCONFIG_WORD, base + OMAP1610_GPIO_SYSCONFIG); 247 iounmap(base); 248 249 platform_device_register(omap16xx_gpio_dev[i]); 250 } 251 252 return 0; 253 } 254 postcore_initcall(omap16xx_gpio_init); 255