xref: /OK3568_Linux_fs/kernel/arch/arm/mach-omap1/gpio16xx.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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