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