xref: /OK3568_Linux_fs/kernel/arch/arm/mach-s3c/gpio-samsung.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
4*4882a593Smuzhiyun //		http://www.samsung.com/
5*4882a593Smuzhiyun //
6*4882a593Smuzhiyun // Copyright 2008 Openmoko, Inc.
7*4882a593Smuzhiyun // Copyright 2008 Simtec Electronics
8*4882a593Smuzhiyun //      Ben Dooks <ben@simtec.co.uk>
9*4882a593Smuzhiyun //      http://armlinux.simtec.co.uk/
10*4882a593Smuzhiyun //
11*4882a593Smuzhiyun // Samsung - GPIOlib support
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <linux/irq.h>
15*4882a593Smuzhiyun #include <linux/io.h>
16*4882a593Smuzhiyun #include <linux/gpio.h>
17*4882a593Smuzhiyun #include <linux/init.h>
18*4882a593Smuzhiyun #include <linux/spinlock.h>
19*4882a593Smuzhiyun #include <linux/module.h>
20*4882a593Smuzhiyun #include <linux/interrupt.h>
21*4882a593Smuzhiyun #include <linux/device.h>
22*4882a593Smuzhiyun #include <linux/ioport.h>
23*4882a593Smuzhiyun #include <linux/of.h>
24*4882a593Smuzhiyun #include <linux/slab.h>
25*4882a593Smuzhiyun #include <linux/of_address.h>
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #include <asm/irq.h>
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #include <mach/irqs.h>
30*4882a593Smuzhiyun #include "map.h"
31*4882a593Smuzhiyun #include "regs-gpio.h"
32*4882a593Smuzhiyun #include "gpio-samsung.h"
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #include "cpu.h"
35*4882a593Smuzhiyun #include "gpio-core.h"
36*4882a593Smuzhiyun #include "gpio-cfg.h"
37*4882a593Smuzhiyun #include "gpio-cfg-helpers.h"
38*4882a593Smuzhiyun #include "pm.h"
39*4882a593Smuzhiyun 
samsung_gpio_setpull_updown(struct samsung_gpio_chip * chip,unsigned int off,samsung_gpio_pull_t pull)40*4882a593Smuzhiyun int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
41*4882a593Smuzhiyun 				unsigned int off, samsung_gpio_pull_t pull)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	void __iomem *reg = chip->base + 0x08;
44*4882a593Smuzhiyun 	int shift = off * 2;
45*4882a593Smuzhiyun 	u32 pup;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	pup = __raw_readl(reg);
48*4882a593Smuzhiyun 	pup &= ~(3 << shift);
49*4882a593Smuzhiyun 	pup |= pull << shift;
50*4882a593Smuzhiyun 	__raw_writel(pup, reg);
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	return 0;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun 
samsung_gpio_getpull_updown(struct samsung_gpio_chip * chip,unsigned int off)55*4882a593Smuzhiyun samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
56*4882a593Smuzhiyun 						unsigned int off)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun 	void __iomem *reg = chip->base + 0x08;
59*4882a593Smuzhiyun 	int shift = off * 2;
60*4882a593Smuzhiyun 	u32 pup = __raw_readl(reg);
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	pup >>= shift;
63*4882a593Smuzhiyun 	pup &= 0x3;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	return (__force samsung_gpio_pull_t)pup;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun 
s3c2443_gpio_setpull(struct samsung_gpio_chip * chip,unsigned int off,samsung_gpio_pull_t pull)68*4882a593Smuzhiyun int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
69*4882a593Smuzhiyun 			 unsigned int off, samsung_gpio_pull_t pull)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun 	switch (pull) {
72*4882a593Smuzhiyun 	case S3C_GPIO_PULL_NONE:
73*4882a593Smuzhiyun 		pull = 0x01;
74*4882a593Smuzhiyun 		break;
75*4882a593Smuzhiyun 	case S3C_GPIO_PULL_UP:
76*4882a593Smuzhiyun 		pull = 0x00;
77*4882a593Smuzhiyun 		break;
78*4882a593Smuzhiyun 	case S3C_GPIO_PULL_DOWN:
79*4882a593Smuzhiyun 		pull = 0x02;
80*4882a593Smuzhiyun 		break;
81*4882a593Smuzhiyun 	}
82*4882a593Smuzhiyun 	return samsung_gpio_setpull_updown(chip, off, pull);
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun 
s3c2443_gpio_getpull(struct samsung_gpio_chip * chip,unsigned int off)85*4882a593Smuzhiyun samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
86*4882a593Smuzhiyun 					 unsigned int off)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun 	samsung_gpio_pull_t pull;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	pull = samsung_gpio_getpull_updown(chip, off);
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	switch (pull) {
93*4882a593Smuzhiyun 	case 0x00:
94*4882a593Smuzhiyun 		pull = S3C_GPIO_PULL_UP;
95*4882a593Smuzhiyun 		break;
96*4882a593Smuzhiyun 	case 0x01:
97*4882a593Smuzhiyun 	case 0x03:
98*4882a593Smuzhiyun 		pull = S3C_GPIO_PULL_NONE;
99*4882a593Smuzhiyun 		break;
100*4882a593Smuzhiyun 	case 0x02:
101*4882a593Smuzhiyun 		pull = S3C_GPIO_PULL_DOWN;
102*4882a593Smuzhiyun 		break;
103*4882a593Smuzhiyun 	}
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	return pull;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
s3c24xx_gpio_setpull_1(struct samsung_gpio_chip * chip,unsigned int off,samsung_gpio_pull_t pull,samsung_gpio_pull_t updown)108*4882a593Smuzhiyun static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
109*4882a593Smuzhiyun 				  unsigned int off, samsung_gpio_pull_t pull,
110*4882a593Smuzhiyun 				  samsung_gpio_pull_t updown)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun 	void __iomem *reg = chip->base + 0x08;
113*4882a593Smuzhiyun 	u32 pup = __raw_readl(reg);
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	if (pull == updown)
116*4882a593Smuzhiyun 		pup &= ~(1 << off);
117*4882a593Smuzhiyun 	else if (pull == S3C_GPIO_PULL_NONE)
118*4882a593Smuzhiyun 		pup |= (1 << off);
119*4882a593Smuzhiyun 	else
120*4882a593Smuzhiyun 		return -EINVAL;
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	__raw_writel(pup, reg);
123*4882a593Smuzhiyun 	return 0;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun 
s3c24xx_gpio_getpull_1(struct samsung_gpio_chip * chip,unsigned int off,samsung_gpio_pull_t updown)126*4882a593Smuzhiyun static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
127*4882a593Smuzhiyun 						  unsigned int off,
128*4882a593Smuzhiyun 						  samsung_gpio_pull_t updown)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	void __iomem *reg = chip->base + 0x08;
131*4882a593Smuzhiyun 	u32 pup = __raw_readl(reg);
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	pup &= (1 << off);
134*4882a593Smuzhiyun 	return pup ? S3C_GPIO_PULL_NONE : updown;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun 
s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip * chip,unsigned int off)137*4882a593Smuzhiyun samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
138*4882a593Smuzhiyun 					     unsigned int off)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun 	return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip * chip,unsigned int off,samsung_gpio_pull_t pull)143*4882a593Smuzhiyun int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
144*4882a593Smuzhiyun 			     unsigned int off, samsung_gpio_pull_t pull)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun 	return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun 
s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip * chip,unsigned int off)149*4882a593Smuzhiyun samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
150*4882a593Smuzhiyun 					       unsigned int off)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun 	return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun 
s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip * chip,unsigned int off,samsung_gpio_pull_t pull)155*4882a593Smuzhiyun int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
156*4882a593Smuzhiyun 			       unsigned int off, samsung_gpio_pull_t pull)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun /*
162*4882a593Smuzhiyun  * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
163*4882a593Smuzhiyun  * @chip: The gpio chip that is being configured.
164*4882a593Smuzhiyun  * @off: The offset for the GPIO being configured.
165*4882a593Smuzhiyun  * @cfg: The configuration value to set.
166*4882a593Smuzhiyun  *
167*4882a593Smuzhiyun  * This helper deal with the GPIO cases where the control register
168*4882a593Smuzhiyun  * has two bits of configuration per gpio, which have the following
169*4882a593Smuzhiyun  * functions:
170*4882a593Smuzhiyun  *	00 = input
171*4882a593Smuzhiyun  *	01 = output
172*4882a593Smuzhiyun  *	1x = special function
173*4882a593Smuzhiyun  */
174*4882a593Smuzhiyun 
samsung_gpio_setcfg_2bit(struct samsung_gpio_chip * chip,unsigned int off,unsigned int cfg)175*4882a593Smuzhiyun static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
176*4882a593Smuzhiyun 				    unsigned int off, unsigned int cfg)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun 	void __iomem *reg = chip->base;
179*4882a593Smuzhiyun 	unsigned int shift = off * 2;
180*4882a593Smuzhiyun 	u32 con;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	if (samsung_gpio_is_cfg_special(cfg)) {
183*4882a593Smuzhiyun 		cfg &= 0xf;
184*4882a593Smuzhiyun 		if (cfg > 3)
185*4882a593Smuzhiyun 			return -EINVAL;
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 		cfg <<= shift;
188*4882a593Smuzhiyun 	}
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	con = __raw_readl(reg);
191*4882a593Smuzhiyun 	con &= ~(0x3 << shift);
192*4882a593Smuzhiyun 	con |= cfg;
193*4882a593Smuzhiyun 	__raw_writel(con, reg);
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	return 0;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun /*
199*4882a593Smuzhiyun  * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
200*4882a593Smuzhiyun  * @chip: The gpio chip that is being configured.
201*4882a593Smuzhiyun  * @off: The offset for the GPIO being configured.
202*4882a593Smuzhiyun  *
203*4882a593Smuzhiyun  * The reverse of samsung_gpio_setcfg_2bit(). Will return a value which
204*4882a593Smuzhiyun  * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
205*4882a593Smuzhiyun  * S3C_GPIO_SPECIAL() macro.
206*4882a593Smuzhiyun  */
207*4882a593Smuzhiyun 
samsung_gpio_getcfg_2bit(struct samsung_gpio_chip * chip,unsigned int off)208*4882a593Smuzhiyun static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
209*4882a593Smuzhiyun 					     unsigned int off)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun 	u32 con;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	con = __raw_readl(chip->base);
214*4882a593Smuzhiyun 	con >>= off * 2;
215*4882a593Smuzhiyun 	con &= 3;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	/* this conversion works for IN and OUT as well as special mode */
218*4882a593Smuzhiyun 	return S3C_GPIO_SPECIAL(con);
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun /*
222*4882a593Smuzhiyun  * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
223*4882a593Smuzhiyun  * @chip: The gpio chip that is being configured.
224*4882a593Smuzhiyun  * @off: The offset for the GPIO being configured.
225*4882a593Smuzhiyun  * @cfg: The configuration value to set.
226*4882a593Smuzhiyun  *
227*4882a593Smuzhiyun  * This helper deal with the GPIO cases where the control register has 4 bits
228*4882a593Smuzhiyun  * of control per GPIO, generally in the form of:
229*4882a593Smuzhiyun  *	0000 = Input
230*4882a593Smuzhiyun  *	0001 = Output
231*4882a593Smuzhiyun  *	others = Special functions (dependent on bank)
232*4882a593Smuzhiyun  *
233*4882a593Smuzhiyun  * Note, since the code to deal with the case where there are two control
234*4882a593Smuzhiyun  * registers instead of one, we do not have a separate set of functions for
235*4882a593Smuzhiyun  * each case.
236*4882a593Smuzhiyun  */
237*4882a593Smuzhiyun 
samsung_gpio_setcfg_4bit(struct samsung_gpio_chip * chip,unsigned int off,unsigned int cfg)238*4882a593Smuzhiyun static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
239*4882a593Smuzhiyun 				    unsigned int off, unsigned int cfg)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun 	void __iomem *reg = chip->base;
242*4882a593Smuzhiyun 	unsigned int shift = (off & 7) * 4;
243*4882a593Smuzhiyun 	u32 con;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	if (off < 8 && chip->chip.ngpio > 8)
246*4882a593Smuzhiyun 		reg -= 4;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	if (samsung_gpio_is_cfg_special(cfg)) {
249*4882a593Smuzhiyun 		cfg &= 0xf;
250*4882a593Smuzhiyun 		cfg <<= shift;
251*4882a593Smuzhiyun 	}
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	con = __raw_readl(reg);
254*4882a593Smuzhiyun 	con &= ~(0xf << shift);
255*4882a593Smuzhiyun 	con |= cfg;
256*4882a593Smuzhiyun 	__raw_writel(con, reg);
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	return 0;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun /*
262*4882a593Smuzhiyun  * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
263*4882a593Smuzhiyun  * @chip: The gpio chip that is being configured.
264*4882a593Smuzhiyun  * @off: The offset for the GPIO being configured.
265*4882a593Smuzhiyun  *
266*4882a593Smuzhiyun  * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
267*4882a593Smuzhiyun  * register setting into a value the software can use, such as could be passed
268*4882a593Smuzhiyun  * to samsung_gpio_setcfg_4bit().
269*4882a593Smuzhiyun  *
270*4882a593Smuzhiyun  * @sa samsung_gpio_getcfg_2bit
271*4882a593Smuzhiyun  */
272*4882a593Smuzhiyun 
samsung_gpio_getcfg_4bit(struct samsung_gpio_chip * chip,unsigned int off)273*4882a593Smuzhiyun static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
274*4882a593Smuzhiyun 					 unsigned int off)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun 	void __iomem *reg = chip->base;
277*4882a593Smuzhiyun 	unsigned int shift = (off & 7) * 4;
278*4882a593Smuzhiyun 	u32 con;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	if (off < 8 && chip->chip.ngpio > 8)
281*4882a593Smuzhiyun 		reg -= 4;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	con = __raw_readl(reg);
284*4882a593Smuzhiyun 	con >>= shift;
285*4882a593Smuzhiyun 	con &= 0xf;
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	/* this conversion works for IN and OUT as well as special mode */
288*4882a593Smuzhiyun 	return S3C_GPIO_SPECIAL(con);
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun #ifdef CONFIG_PLAT_S3C24XX
292*4882a593Smuzhiyun /*
293*4882a593Smuzhiyun  * s3c24xx_gpio_setcfg_abank - S3C24XX style GPIO configuration (Bank A)
294*4882a593Smuzhiyun  * @chip: The gpio chip that is being configured.
295*4882a593Smuzhiyun  * @off: The offset for the GPIO being configured.
296*4882a593Smuzhiyun  * @cfg: The configuration value to set.
297*4882a593Smuzhiyun  *
298*4882a593Smuzhiyun  * This helper deal with the GPIO cases where the control register
299*4882a593Smuzhiyun  * has one bit of configuration for the gpio, where setting the bit
300*4882a593Smuzhiyun  * means the pin is in special function mode and unset means output.
301*4882a593Smuzhiyun  */
302*4882a593Smuzhiyun 
s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip * chip,unsigned int off,unsigned int cfg)303*4882a593Smuzhiyun static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
304*4882a593Smuzhiyun 				     unsigned int off, unsigned int cfg)
305*4882a593Smuzhiyun {
306*4882a593Smuzhiyun 	void __iomem *reg = chip->base;
307*4882a593Smuzhiyun 	unsigned int shift = off;
308*4882a593Smuzhiyun 	u32 con;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	if (samsung_gpio_is_cfg_special(cfg)) {
311*4882a593Smuzhiyun 		cfg &= 0xf;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 		/* Map output to 0, and SFN2 to 1 */
314*4882a593Smuzhiyun 		cfg -= 1;
315*4882a593Smuzhiyun 		if (cfg > 1)
316*4882a593Smuzhiyun 			return -EINVAL;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 		cfg <<= shift;
319*4882a593Smuzhiyun 	}
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	con = __raw_readl(reg);
322*4882a593Smuzhiyun 	con &= ~(0x1 << shift);
323*4882a593Smuzhiyun 	con |= cfg;
324*4882a593Smuzhiyun 	__raw_writel(con, reg);
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	return 0;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun /*
330*4882a593Smuzhiyun  * s3c24xx_gpio_getcfg_abank - S3C24XX style GPIO configuration read (Bank A)
331*4882a593Smuzhiyun  * @chip: The gpio chip that is being configured.
332*4882a593Smuzhiyun  * @off: The offset for the GPIO being configured.
333*4882a593Smuzhiyun  *
334*4882a593Smuzhiyun  * The reverse of s3c24xx_gpio_setcfg_abank() turning an GPIO into a usable
335*4882a593Smuzhiyun  * GPIO configuration value.
336*4882a593Smuzhiyun  *
337*4882a593Smuzhiyun  * @sa samsung_gpio_getcfg_2bit
338*4882a593Smuzhiyun  * @sa samsung_gpio_getcfg_4bit
339*4882a593Smuzhiyun  */
340*4882a593Smuzhiyun 
s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip * chip,unsigned int off)341*4882a593Smuzhiyun static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
342*4882a593Smuzhiyun 					  unsigned int off)
343*4882a593Smuzhiyun {
344*4882a593Smuzhiyun 	u32 con;
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	con = __raw_readl(chip->base);
347*4882a593Smuzhiyun 	con >>= off;
348*4882a593Smuzhiyun 	con &= 1;
349*4882a593Smuzhiyun 	con++;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	return S3C_GPIO_SFN(con);
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun #endif
354*4882a593Smuzhiyun 
samsung_gpiolib_set_cfg(struct samsung_gpio_cfg * chipcfg,int nr_chips)355*4882a593Smuzhiyun static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
356*4882a593Smuzhiyun 					   int nr_chips)
357*4882a593Smuzhiyun {
358*4882a593Smuzhiyun 	for (; nr_chips > 0; nr_chips--, chipcfg++) {
359*4882a593Smuzhiyun 		if (!chipcfg->set_config)
360*4882a593Smuzhiyun 			chipcfg->set_config = samsung_gpio_setcfg_4bit;
361*4882a593Smuzhiyun 		if (!chipcfg->get_config)
362*4882a593Smuzhiyun 			chipcfg->get_config = samsung_gpio_getcfg_4bit;
363*4882a593Smuzhiyun 		if (!chipcfg->set_pull)
364*4882a593Smuzhiyun 			chipcfg->set_pull = samsung_gpio_setpull_updown;
365*4882a593Smuzhiyun 		if (!chipcfg->get_pull)
366*4882a593Smuzhiyun 			chipcfg->get_pull = samsung_gpio_getpull_updown;
367*4882a593Smuzhiyun 	}
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
371*4882a593Smuzhiyun 	.set_config	= samsung_gpio_setcfg_2bit,
372*4882a593Smuzhiyun 	.get_config	= samsung_gpio_getcfg_2bit,
373*4882a593Smuzhiyun };
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun #ifdef CONFIG_PLAT_S3C24XX
376*4882a593Smuzhiyun static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
377*4882a593Smuzhiyun 	.set_config	= s3c24xx_gpio_setcfg_abank,
378*4882a593Smuzhiyun 	.get_config	= s3c24xx_gpio_getcfg_abank,
379*4882a593Smuzhiyun };
380*4882a593Smuzhiyun #endif
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
383*4882a593Smuzhiyun 	[0] = {
384*4882a593Smuzhiyun 		.cfg_eint	= 0x0,
385*4882a593Smuzhiyun 	},
386*4882a593Smuzhiyun 	[1] = {
387*4882a593Smuzhiyun 		.cfg_eint	= 0x3,
388*4882a593Smuzhiyun 	},
389*4882a593Smuzhiyun 	[2] = {
390*4882a593Smuzhiyun 		.cfg_eint	= 0x7,
391*4882a593Smuzhiyun 	},
392*4882a593Smuzhiyun 	[3] = {
393*4882a593Smuzhiyun 		.cfg_eint	= 0xF,
394*4882a593Smuzhiyun 	},
395*4882a593Smuzhiyun 	[4] = {
396*4882a593Smuzhiyun 		.cfg_eint	= 0x0,
397*4882a593Smuzhiyun 		.set_config	= samsung_gpio_setcfg_2bit,
398*4882a593Smuzhiyun 		.get_config	= samsung_gpio_getcfg_2bit,
399*4882a593Smuzhiyun 	},
400*4882a593Smuzhiyun 	[5] = {
401*4882a593Smuzhiyun 		.cfg_eint	= 0x2,
402*4882a593Smuzhiyun 		.set_config	= samsung_gpio_setcfg_2bit,
403*4882a593Smuzhiyun 		.get_config	= samsung_gpio_getcfg_2bit,
404*4882a593Smuzhiyun 	},
405*4882a593Smuzhiyun 	[6] = {
406*4882a593Smuzhiyun 		.cfg_eint	= 0x3,
407*4882a593Smuzhiyun 		.set_config	= samsung_gpio_setcfg_2bit,
408*4882a593Smuzhiyun 		.get_config	= samsung_gpio_getcfg_2bit,
409*4882a593Smuzhiyun 	},
410*4882a593Smuzhiyun 	[7] = {
411*4882a593Smuzhiyun 		.set_config	= samsung_gpio_setcfg_2bit,
412*4882a593Smuzhiyun 		.get_config	= samsung_gpio_getcfg_2bit,
413*4882a593Smuzhiyun 	},
414*4882a593Smuzhiyun };
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun /*
417*4882a593Smuzhiyun  * Default routines for controlling GPIO, based on the original S3C24XX
418*4882a593Smuzhiyun  * GPIO functions which deal with the case where each gpio bank of the
419*4882a593Smuzhiyun  * chip is as following:
420*4882a593Smuzhiyun  *
421*4882a593Smuzhiyun  * base + 0x00: Control register, 2 bits per gpio
422*4882a593Smuzhiyun  *	        gpio n: 2 bits starting at (2*n)
423*4882a593Smuzhiyun  *		00 = input, 01 = output, others mean special-function
424*4882a593Smuzhiyun  * base + 0x04: Data register, 1 bit per gpio
425*4882a593Smuzhiyun  *		bit n: data bit n
426*4882a593Smuzhiyun */
427*4882a593Smuzhiyun 
samsung_gpiolib_2bit_input(struct gpio_chip * chip,unsigned offset)428*4882a593Smuzhiyun static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
429*4882a593Smuzhiyun {
430*4882a593Smuzhiyun 	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
431*4882a593Smuzhiyun 	void __iomem *base = ourchip->base;
432*4882a593Smuzhiyun 	unsigned long flags;
433*4882a593Smuzhiyun 	unsigned long con;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	samsung_gpio_lock(ourchip, flags);
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	con = __raw_readl(base + 0x00);
438*4882a593Smuzhiyun 	con &= ~(3 << (offset * 2));
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 	__raw_writel(con, base + 0x00);
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	samsung_gpio_unlock(ourchip, flags);
443*4882a593Smuzhiyun 	return 0;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun 
samsung_gpiolib_2bit_output(struct gpio_chip * chip,unsigned offset,int value)446*4882a593Smuzhiyun static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
447*4882a593Smuzhiyun 				       unsigned offset, int value)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun 	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
450*4882a593Smuzhiyun 	void __iomem *base = ourchip->base;
451*4882a593Smuzhiyun 	unsigned long flags;
452*4882a593Smuzhiyun 	unsigned long dat;
453*4882a593Smuzhiyun 	unsigned long con;
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	samsung_gpio_lock(ourchip, flags);
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	dat = __raw_readl(base + 0x04);
458*4882a593Smuzhiyun 	dat &= ~(1 << offset);
459*4882a593Smuzhiyun 	if (value)
460*4882a593Smuzhiyun 		dat |= 1 << offset;
461*4882a593Smuzhiyun 	__raw_writel(dat, base + 0x04);
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	con = __raw_readl(base + 0x00);
464*4882a593Smuzhiyun 	con &= ~(3 << (offset * 2));
465*4882a593Smuzhiyun 	con |= 1 << (offset * 2);
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	__raw_writel(con, base + 0x00);
468*4882a593Smuzhiyun 	__raw_writel(dat, base + 0x04);
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	samsung_gpio_unlock(ourchip, flags);
471*4882a593Smuzhiyun 	return 0;
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun /*
475*4882a593Smuzhiyun  * The samsung_gpiolib_4bit routines are to control the gpio banks where
476*4882a593Smuzhiyun  * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
477*4882a593Smuzhiyun  * following example:
478*4882a593Smuzhiyun  *
479*4882a593Smuzhiyun  * base + 0x00: Control register, 4 bits per gpio
480*4882a593Smuzhiyun  *		gpio n: 4 bits starting at (4*n)
481*4882a593Smuzhiyun  *		0000 = input, 0001 = output, others mean special-function
482*4882a593Smuzhiyun  * base + 0x04: Data register, 1 bit per gpio
483*4882a593Smuzhiyun  *		bit n: data bit n
484*4882a593Smuzhiyun  *
485*4882a593Smuzhiyun  * Note, since the data register is one bit per gpio and is at base + 0x4
486*4882a593Smuzhiyun  * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
487*4882a593Smuzhiyun  * state of the output.
488*4882a593Smuzhiyun  */
489*4882a593Smuzhiyun 
samsung_gpiolib_4bit_input(struct gpio_chip * chip,unsigned int offset)490*4882a593Smuzhiyun static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
491*4882a593Smuzhiyun 				      unsigned int offset)
492*4882a593Smuzhiyun {
493*4882a593Smuzhiyun 	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
494*4882a593Smuzhiyun 	void __iomem *base = ourchip->base;
495*4882a593Smuzhiyun 	unsigned long con;
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	con = __raw_readl(base + GPIOCON_OFF);
498*4882a593Smuzhiyun 	if (ourchip->bitmap_gpio_int & BIT(offset))
499*4882a593Smuzhiyun 		con |= 0xf << con_4bit_shift(offset);
500*4882a593Smuzhiyun 	else
501*4882a593Smuzhiyun 		con &= ~(0xf << con_4bit_shift(offset));
502*4882a593Smuzhiyun 	__raw_writel(con, base + GPIOCON_OFF);
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	return 0;
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun 
samsung_gpiolib_4bit_output(struct gpio_chip * chip,unsigned int offset,int value)509*4882a593Smuzhiyun static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
510*4882a593Smuzhiyun 				       unsigned int offset, int value)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun 	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
513*4882a593Smuzhiyun 	void __iomem *base = ourchip->base;
514*4882a593Smuzhiyun 	unsigned long con;
515*4882a593Smuzhiyun 	unsigned long dat;
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	con = __raw_readl(base + GPIOCON_OFF);
518*4882a593Smuzhiyun 	con &= ~(0xf << con_4bit_shift(offset));
519*4882a593Smuzhiyun 	con |= 0x1 << con_4bit_shift(offset);
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	dat = __raw_readl(base + GPIODAT_OFF);
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	if (value)
524*4882a593Smuzhiyun 		dat |= 1 << offset;
525*4882a593Smuzhiyun 	else
526*4882a593Smuzhiyun 		dat &= ~(1 << offset);
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	__raw_writel(dat, base + GPIODAT_OFF);
529*4882a593Smuzhiyun 	__raw_writel(con, base + GPIOCON_OFF);
530*4882a593Smuzhiyun 	__raw_writel(dat, base + GPIODAT_OFF);
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 	return 0;
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun /*
538*4882a593Smuzhiyun  * The next set of routines are for the case where the GPIO configuration
539*4882a593Smuzhiyun  * registers are 4 bits per GPIO but there is more than one register (the
540*4882a593Smuzhiyun  * bank has more than 8 GPIOs.
541*4882a593Smuzhiyun  *
542*4882a593Smuzhiyun  * This case is the similar to the 4 bit case, but the registers are as
543*4882a593Smuzhiyun  * follows:
544*4882a593Smuzhiyun  *
545*4882a593Smuzhiyun  * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
546*4882a593Smuzhiyun  *		gpio n: 4 bits starting at (4*n)
547*4882a593Smuzhiyun  *		0000 = input, 0001 = output, others mean special-function
548*4882a593Smuzhiyun  * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
549*4882a593Smuzhiyun  *		gpio n: 4 bits starting at (4*n)
550*4882a593Smuzhiyun  *		0000 = input, 0001 = output, others mean special-function
551*4882a593Smuzhiyun  * base + 0x08: Data register, 1 bit per gpio
552*4882a593Smuzhiyun  *		bit n: data bit n
553*4882a593Smuzhiyun  *
554*4882a593Smuzhiyun  * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
555*4882a593Smuzhiyun  * routines we store the 'base + 0x4' address so that these routines see
556*4882a593Smuzhiyun  * the data register at ourchip->base + 0x04.
557*4882a593Smuzhiyun  */
558*4882a593Smuzhiyun 
samsung_gpiolib_4bit2_input(struct gpio_chip * chip,unsigned int offset)559*4882a593Smuzhiyun static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
560*4882a593Smuzhiyun 				       unsigned int offset)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun 	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
563*4882a593Smuzhiyun 	void __iomem *base = ourchip->base;
564*4882a593Smuzhiyun 	void __iomem *regcon = base;
565*4882a593Smuzhiyun 	unsigned long con;
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	if (offset > 7)
568*4882a593Smuzhiyun 		offset -= 8;
569*4882a593Smuzhiyun 	else
570*4882a593Smuzhiyun 		regcon -= 4;
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun 	con = __raw_readl(regcon);
573*4882a593Smuzhiyun 	con &= ~(0xf << con_4bit_shift(offset));
574*4882a593Smuzhiyun 	__raw_writel(con, regcon);
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun 	pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun 	return 0;
579*4882a593Smuzhiyun }
580*4882a593Smuzhiyun 
samsung_gpiolib_4bit2_output(struct gpio_chip * chip,unsigned int offset,int value)581*4882a593Smuzhiyun static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
582*4882a593Smuzhiyun 					unsigned int offset, int value)
583*4882a593Smuzhiyun {
584*4882a593Smuzhiyun 	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
585*4882a593Smuzhiyun 	void __iomem *base = ourchip->base;
586*4882a593Smuzhiyun 	void __iomem *regcon = base;
587*4882a593Smuzhiyun 	unsigned long con;
588*4882a593Smuzhiyun 	unsigned long dat;
589*4882a593Smuzhiyun 	unsigned con_offset = offset;
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun 	if (con_offset > 7)
592*4882a593Smuzhiyun 		con_offset -= 8;
593*4882a593Smuzhiyun 	else
594*4882a593Smuzhiyun 		regcon -= 4;
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun 	con = __raw_readl(regcon);
597*4882a593Smuzhiyun 	con &= ~(0xf << con_4bit_shift(con_offset));
598*4882a593Smuzhiyun 	con |= 0x1 << con_4bit_shift(con_offset);
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun 	dat = __raw_readl(base + GPIODAT_OFF);
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	if (value)
603*4882a593Smuzhiyun 		dat |= 1 << offset;
604*4882a593Smuzhiyun 	else
605*4882a593Smuzhiyun 		dat &= ~(1 << offset);
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun 	__raw_writel(dat, base + GPIODAT_OFF);
608*4882a593Smuzhiyun 	__raw_writel(con, regcon);
609*4882a593Smuzhiyun 	__raw_writel(dat, base + GPIODAT_OFF);
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 	pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	return 0;
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun #ifdef CONFIG_PLAT_S3C24XX
617*4882a593Smuzhiyun /* The next set of routines are for the case of s3c24xx bank a */
618*4882a593Smuzhiyun 
s3c24xx_gpiolib_banka_input(struct gpio_chip * chip,unsigned offset)619*4882a593Smuzhiyun static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
620*4882a593Smuzhiyun {
621*4882a593Smuzhiyun 	return -EINVAL;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun 
s3c24xx_gpiolib_banka_output(struct gpio_chip * chip,unsigned offset,int value)624*4882a593Smuzhiyun static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
625*4882a593Smuzhiyun 					unsigned offset, int value)
626*4882a593Smuzhiyun {
627*4882a593Smuzhiyun 	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
628*4882a593Smuzhiyun 	void __iomem *base = ourchip->base;
629*4882a593Smuzhiyun 	unsigned long flags;
630*4882a593Smuzhiyun 	unsigned long dat;
631*4882a593Smuzhiyun 	unsigned long con;
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 	local_irq_save(flags);
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 	con = __raw_readl(base + 0x00);
636*4882a593Smuzhiyun 	dat = __raw_readl(base + 0x04);
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	dat &= ~(1 << offset);
639*4882a593Smuzhiyun 	if (value)
640*4882a593Smuzhiyun 		dat |= 1 << offset;
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 	__raw_writel(dat, base + 0x04);
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun 	con &= ~(1 << offset);
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	__raw_writel(con, base + 0x00);
647*4882a593Smuzhiyun 	__raw_writel(dat, base + 0x04);
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	local_irq_restore(flags);
650*4882a593Smuzhiyun 	return 0;
651*4882a593Smuzhiyun }
652*4882a593Smuzhiyun #endif
653*4882a593Smuzhiyun 
samsung_gpiolib_set(struct gpio_chip * chip,unsigned offset,int value)654*4882a593Smuzhiyun static void samsung_gpiolib_set(struct gpio_chip *chip,
655*4882a593Smuzhiyun 				unsigned offset, int value)
656*4882a593Smuzhiyun {
657*4882a593Smuzhiyun 	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
658*4882a593Smuzhiyun 	void __iomem *base = ourchip->base;
659*4882a593Smuzhiyun 	unsigned long flags;
660*4882a593Smuzhiyun 	unsigned long dat;
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 	samsung_gpio_lock(ourchip, flags);
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	dat = __raw_readl(base + 0x04);
665*4882a593Smuzhiyun 	dat &= ~(1 << offset);
666*4882a593Smuzhiyun 	if (value)
667*4882a593Smuzhiyun 		dat |= 1 << offset;
668*4882a593Smuzhiyun 	__raw_writel(dat, base + 0x04);
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	samsung_gpio_unlock(ourchip, flags);
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun 
samsung_gpiolib_get(struct gpio_chip * chip,unsigned offset)673*4882a593Smuzhiyun static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
674*4882a593Smuzhiyun {
675*4882a593Smuzhiyun 	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
676*4882a593Smuzhiyun 	unsigned long val;
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun 	val = __raw_readl(ourchip->base + 0x04);
679*4882a593Smuzhiyun 	val >>= offset;
680*4882a593Smuzhiyun 	val &= 1;
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	return val;
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun /*
686*4882a593Smuzhiyun  * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
687*4882a593Smuzhiyun  * for use with the configuration calls, and other parts of the s3c gpiolib
688*4882a593Smuzhiyun  * support code.
689*4882a593Smuzhiyun  *
690*4882a593Smuzhiyun  * Not all s3c support code will need this, as some configurations of cpu
691*4882a593Smuzhiyun  * may only support one or two different configuration options and have an
692*4882a593Smuzhiyun  * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
693*4882a593Smuzhiyun  * the machine support file should provide its own samsung_gpiolib_getchip()
694*4882a593Smuzhiyun  * and any other necessary functions.
695*4882a593Smuzhiyun  */
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun #ifdef CONFIG_S3C_GPIO_TRACK
698*4882a593Smuzhiyun struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
699*4882a593Smuzhiyun 
s3c_gpiolib_track(struct samsung_gpio_chip * chip)700*4882a593Smuzhiyun static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
701*4882a593Smuzhiyun {
702*4882a593Smuzhiyun 	unsigned int gpn;
703*4882a593Smuzhiyun 	int i;
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun 	gpn = chip->chip.base;
706*4882a593Smuzhiyun 	for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
707*4882a593Smuzhiyun 		BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
708*4882a593Smuzhiyun 		s3c_gpios[gpn] = chip;
709*4882a593Smuzhiyun 	}
710*4882a593Smuzhiyun }
711*4882a593Smuzhiyun #endif /* CONFIG_S3C_GPIO_TRACK */
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun /*
714*4882a593Smuzhiyun  * samsung_gpiolib_add() - add the Samsung gpio_chip.
715*4882a593Smuzhiyun  * @chip: The chip to register
716*4882a593Smuzhiyun  *
717*4882a593Smuzhiyun  * This is a wrapper to gpiochip_add() that takes our specific gpio chip
718*4882a593Smuzhiyun  * information and makes the necessary alterations for the platform and
719*4882a593Smuzhiyun  * notes the information for use with the configuration systems and any
720*4882a593Smuzhiyun  * other parts of the system.
721*4882a593Smuzhiyun  */
722*4882a593Smuzhiyun 
samsung_gpiolib_add(struct samsung_gpio_chip * chip)723*4882a593Smuzhiyun static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
724*4882a593Smuzhiyun {
725*4882a593Smuzhiyun 	struct gpio_chip *gc = &chip->chip;
726*4882a593Smuzhiyun 	int ret;
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun 	BUG_ON(!chip->base);
729*4882a593Smuzhiyun 	BUG_ON(!gc->label);
730*4882a593Smuzhiyun 	BUG_ON(!gc->ngpio);
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun 	spin_lock_init(&chip->lock);
733*4882a593Smuzhiyun 
734*4882a593Smuzhiyun 	if (!gc->direction_input)
735*4882a593Smuzhiyun 		gc->direction_input = samsung_gpiolib_2bit_input;
736*4882a593Smuzhiyun 	if (!gc->direction_output)
737*4882a593Smuzhiyun 		gc->direction_output = samsung_gpiolib_2bit_output;
738*4882a593Smuzhiyun 	if (!gc->set)
739*4882a593Smuzhiyun 		gc->set = samsung_gpiolib_set;
740*4882a593Smuzhiyun 	if (!gc->get)
741*4882a593Smuzhiyun 		gc->get = samsung_gpiolib_get;
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun #ifdef CONFIG_PM
744*4882a593Smuzhiyun 	if (chip->pm != NULL) {
745*4882a593Smuzhiyun 		if (!chip->pm->save || !chip->pm->resume)
746*4882a593Smuzhiyun 			pr_err("gpio: %s has missing PM functions\n",
747*4882a593Smuzhiyun 			       gc->label);
748*4882a593Smuzhiyun 	} else
749*4882a593Smuzhiyun 		pr_err("gpio: %s has no PM function\n", gc->label);
750*4882a593Smuzhiyun #endif
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun 	/* gpiochip_add() prints own failure message on error. */
753*4882a593Smuzhiyun 	ret = gpiochip_add_data(gc, chip);
754*4882a593Smuzhiyun 	if (ret >= 0)
755*4882a593Smuzhiyun 		s3c_gpiolib_track(chip);
756*4882a593Smuzhiyun }
757*4882a593Smuzhiyun 
s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip * chip,int nr_chips,void __iomem * base)758*4882a593Smuzhiyun static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
759*4882a593Smuzhiyun 					     int nr_chips, void __iomem *base)
760*4882a593Smuzhiyun {
761*4882a593Smuzhiyun 	int i;
762*4882a593Smuzhiyun 	struct gpio_chip *gc = &chip->chip;
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun 	for (i = 0 ; i < nr_chips; i++, chip++) {
765*4882a593Smuzhiyun 		/* skip banks not present on SoC */
766*4882a593Smuzhiyun 		if (chip->chip.base >= S3C_GPIO_END)
767*4882a593Smuzhiyun 			continue;
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun 		if (!chip->config)
770*4882a593Smuzhiyun 			chip->config = &s3c24xx_gpiocfg_default;
771*4882a593Smuzhiyun 		if (!chip->pm)
772*4882a593Smuzhiyun 			chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
773*4882a593Smuzhiyun 		if ((base != NULL) && (chip->base == NULL))
774*4882a593Smuzhiyun 			chip->base = base + ((i) * 0x10);
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun 		if (!gc->direction_input)
777*4882a593Smuzhiyun 			gc->direction_input = samsung_gpiolib_2bit_input;
778*4882a593Smuzhiyun 		if (!gc->direction_output)
779*4882a593Smuzhiyun 			gc->direction_output = samsung_gpiolib_2bit_output;
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun 		samsung_gpiolib_add(chip);
782*4882a593Smuzhiyun 	}
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun 
samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip * chip,int nr_chips,void __iomem * base,unsigned int offset)785*4882a593Smuzhiyun static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
786*4882a593Smuzhiyun 						  int nr_chips, void __iomem *base,
787*4882a593Smuzhiyun 						  unsigned int offset)
788*4882a593Smuzhiyun {
789*4882a593Smuzhiyun 	int i;
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun 	for (i = 0 ; i < nr_chips; i++, chip++) {
792*4882a593Smuzhiyun 		chip->chip.direction_input = samsung_gpiolib_2bit_input;
793*4882a593Smuzhiyun 		chip->chip.direction_output = samsung_gpiolib_2bit_output;
794*4882a593Smuzhiyun 
795*4882a593Smuzhiyun 		if (!chip->config)
796*4882a593Smuzhiyun 			chip->config = &samsung_gpio_cfgs[7];
797*4882a593Smuzhiyun 		if (!chip->pm)
798*4882a593Smuzhiyun 			chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
799*4882a593Smuzhiyun 		if ((base != NULL) && (chip->base == NULL))
800*4882a593Smuzhiyun 			chip->base = base + ((i) * offset);
801*4882a593Smuzhiyun 
802*4882a593Smuzhiyun 		samsung_gpiolib_add(chip);
803*4882a593Smuzhiyun 	}
804*4882a593Smuzhiyun }
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun /*
807*4882a593Smuzhiyun  * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
808*4882a593Smuzhiyun  * @chip: The gpio chip that is being configured.
809*4882a593Smuzhiyun  * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
810*4882a593Smuzhiyun  *
811*4882a593Smuzhiyun  * This helper deal with the GPIO cases where the control register has 4 bits
812*4882a593Smuzhiyun  * of control per GPIO, generally in the form of:
813*4882a593Smuzhiyun  * 0000 = Input
814*4882a593Smuzhiyun  * 0001 = Output
815*4882a593Smuzhiyun  * others = Special functions (dependent on bank)
816*4882a593Smuzhiyun  *
817*4882a593Smuzhiyun  * Note, since the code to deal with the case where there are two control
818*4882a593Smuzhiyun  * registers instead of one, we do not have a separate set of function
819*4882a593Smuzhiyun  * (samsung_gpiolib_add_4bit2_chips)for each case.
820*4882a593Smuzhiyun  */
821*4882a593Smuzhiyun 
samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip * chip,int nr_chips,void __iomem * base)822*4882a593Smuzhiyun static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
823*4882a593Smuzhiyun 						  int nr_chips, void __iomem *base)
824*4882a593Smuzhiyun {
825*4882a593Smuzhiyun 	int i;
826*4882a593Smuzhiyun 
827*4882a593Smuzhiyun 	for (i = 0 ; i < nr_chips; i++, chip++) {
828*4882a593Smuzhiyun 		chip->chip.direction_input = samsung_gpiolib_4bit_input;
829*4882a593Smuzhiyun 		chip->chip.direction_output = samsung_gpiolib_4bit_output;
830*4882a593Smuzhiyun 
831*4882a593Smuzhiyun 		if (!chip->config)
832*4882a593Smuzhiyun 			chip->config = &samsung_gpio_cfgs[2];
833*4882a593Smuzhiyun 		if (!chip->pm)
834*4882a593Smuzhiyun 			chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
835*4882a593Smuzhiyun 		if ((base != NULL) && (chip->base == NULL))
836*4882a593Smuzhiyun 			chip->base = base + ((i) * 0x20);
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 		chip->bitmap_gpio_int = 0;
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun 		samsung_gpiolib_add(chip);
841*4882a593Smuzhiyun 	}
842*4882a593Smuzhiyun }
843*4882a593Smuzhiyun 
samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip * chip,int nr_chips)844*4882a593Smuzhiyun static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
845*4882a593Smuzhiyun 						   int nr_chips)
846*4882a593Smuzhiyun {
847*4882a593Smuzhiyun 	for (; nr_chips > 0; nr_chips--, chip++) {
848*4882a593Smuzhiyun 		chip->chip.direction_input = samsung_gpiolib_4bit2_input;
849*4882a593Smuzhiyun 		chip->chip.direction_output = samsung_gpiolib_4bit2_output;
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun 		if (!chip->config)
852*4882a593Smuzhiyun 			chip->config = &samsung_gpio_cfgs[2];
853*4882a593Smuzhiyun 		if (!chip->pm)
854*4882a593Smuzhiyun 			chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
855*4882a593Smuzhiyun 
856*4882a593Smuzhiyun 		samsung_gpiolib_add(chip);
857*4882a593Smuzhiyun 	}
858*4882a593Smuzhiyun }
859*4882a593Smuzhiyun 
samsung_gpiolib_to_irq(struct gpio_chip * chip,unsigned int offset)860*4882a593Smuzhiyun int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
861*4882a593Smuzhiyun {
862*4882a593Smuzhiyun 	struct samsung_gpio_chip *samsung_chip = gpiochip_get_data(chip);
863*4882a593Smuzhiyun 
864*4882a593Smuzhiyun 	return samsung_chip->irq_base + offset;
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun 
867*4882a593Smuzhiyun #ifdef CONFIG_PLAT_S3C24XX
s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip * chip,unsigned offset)868*4882a593Smuzhiyun static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
869*4882a593Smuzhiyun {
870*4882a593Smuzhiyun 	if (offset < 4) {
871*4882a593Smuzhiyun 		if (soc_is_s3c2412())
872*4882a593Smuzhiyun 			return IRQ_EINT0_2412 + offset;
873*4882a593Smuzhiyun 		else
874*4882a593Smuzhiyun 			return IRQ_EINT0 + offset;
875*4882a593Smuzhiyun 	}
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun 	if (offset < 8)
878*4882a593Smuzhiyun 		return IRQ_EINT4 + offset - 4;
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun 	return -EINVAL;
881*4882a593Smuzhiyun }
882*4882a593Smuzhiyun #endif
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun #ifdef CONFIG_ARCH_S3C64XX
s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip * chip,unsigned pin)885*4882a593Smuzhiyun static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
886*4882a593Smuzhiyun {
887*4882a593Smuzhiyun 	return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
888*4882a593Smuzhiyun }
889*4882a593Smuzhiyun 
s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip * chip,unsigned pin)890*4882a593Smuzhiyun static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
891*4882a593Smuzhiyun {
892*4882a593Smuzhiyun 	return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
893*4882a593Smuzhiyun }
894*4882a593Smuzhiyun #endif
895*4882a593Smuzhiyun 
896*4882a593Smuzhiyun struct samsung_gpio_chip s3c24xx_gpios[] = {
897*4882a593Smuzhiyun #ifdef CONFIG_PLAT_S3C24XX
898*4882a593Smuzhiyun 	{
899*4882a593Smuzhiyun 		.config	= &s3c24xx_gpiocfg_banka,
900*4882a593Smuzhiyun 		.chip	= {
901*4882a593Smuzhiyun 			.base			= S3C2410_GPA(0),
902*4882a593Smuzhiyun 			.owner			= THIS_MODULE,
903*4882a593Smuzhiyun 			.label			= "GPIOA",
904*4882a593Smuzhiyun 			.ngpio			= 27,
905*4882a593Smuzhiyun 			.direction_input	= s3c24xx_gpiolib_banka_input,
906*4882a593Smuzhiyun 			.direction_output	= s3c24xx_gpiolib_banka_output,
907*4882a593Smuzhiyun 		},
908*4882a593Smuzhiyun 	}, {
909*4882a593Smuzhiyun 		.chip	= {
910*4882a593Smuzhiyun 			.base	= S3C2410_GPB(0),
911*4882a593Smuzhiyun 			.owner	= THIS_MODULE,
912*4882a593Smuzhiyun 			.label	= "GPIOB",
913*4882a593Smuzhiyun 			.ngpio	= 11,
914*4882a593Smuzhiyun 		},
915*4882a593Smuzhiyun 	}, {
916*4882a593Smuzhiyun 		.chip	= {
917*4882a593Smuzhiyun 			.base	= S3C2410_GPC(0),
918*4882a593Smuzhiyun 			.owner	= THIS_MODULE,
919*4882a593Smuzhiyun 			.label	= "GPIOC",
920*4882a593Smuzhiyun 			.ngpio	= 16,
921*4882a593Smuzhiyun 		},
922*4882a593Smuzhiyun 	}, {
923*4882a593Smuzhiyun 		.chip	= {
924*4882a593Smuzhiyun 			.base	= S3C2410_GPD(0),
925*4882a593Smuzhiyun 			.owner	= THIS_MODULE,
926*4882a593Smuzhiyun 			.label	= "GPIOD",
927*4882a593Smuzhiyun 			.ngpio	= 16,
928*4882a593Smuzhiyun 		},
929*4882a593Smuzhiyun 	}, {
930*4882a593Smuzhiyun 		.chip	= {
931*4882a593Smuzhiyun 			.base	= S3C2410_GPE(0),
932*4882a593Smuzhiyun 			.label	= "GPIOE",
933*4882a593Smuzhiyun 			.owner	= THIS_MODULE,
934*4882a593Smuzhiyun 			.ngpio	= 16,
935*4882a593Smuzhiyun 		},
936*4882a593Smuzhiyun 	}, {
937*4882a593Smuzhiyun 		.chip	= {
938*4882a593Smuzhiyun 			.base	= S3C2410_GPF(0),
939*4882a593Smuzhiyun 			.owner	= THIS_MODULE,
940*4882a593Smuzhiyun 			.label	= "GPIOF",
941*4882a593Smuzhiyun 			.ngpio	= 8,
942*4882a593Smuzhiyun 			.to_irq	= s3c24xx_gpiolib_fbank_to_irq,
943*4882a593Smuzhiyun 		},
944*4882a593Smuzhiyun 	}, {
945*4882a593Smuzhiyun 		.irq_base = IRQ_EINT8,
946*4882a593Smuzhiyun 		.chip	= {
947*4882a593Smuzhiyun 			.base	= S3C2410_GPG(0),
948*4882a593Smuzhiyun 			.owner	= THIS_MODULE,
949*4882a593Smuzhiyun 			.label	= "GPIOG",
950*4882a593Smuzhiyun 			.ngpio	= 16,
951*4882a593Smuzhiyun 			.to_irq	= samsung_gpiolib_to_irq,
952*4882a593Smuzhiyun 		},
953*4882a593Smuzhiyun 	}, {
954*4882a593Smuzhiyun 		.chip	= {
955*4882a593Smuzhiyun 			.base	= S3C2410_GPH(0),
956*4882a593Smuzhiyun 			.owner	= THIS_MODULE,
957*4882a593Smuzhiyun 			.label	= "GPIOH",
958*4882a593Smuzhiyun 			.ngpio	= 15,
959*4882a593Smuzhiyun 		},
960*4882a593Smuzhiyun 	},
961*4882a593Smuzhiyun 		/* GPIOS for the S3C2443 and later devices. */
962*4882a593Smuzhiyun 	{
963*4882a593Smuzhiyun 		.base	= S3C2440_GPJCON,
964*4882a593Smuzhiyun 		.chip	= {
965*4882a593Smuzhiyun 			.base	= S3C2410_GPJ(0),
966*4882a593Smuzhiyun 			.owner	= THIS_MODULE,
967*4882a593Smuzhiyun 			.label	= "GPIOJ",
968*4882a593Smuzhiyun 			.ngpio	= 16,
969*4882a593Smuzhiyun 		},
970*4882a593Smuzhiyun 	}, {
971*4882a593Smuzhiyun 		.base	= S3C2443_GPKCON,
972*4882a593Smuzhiyun 		.chip	= {
973*4882a593Smuzhiyun 			.base	= S3C2410_GPK(0),
974*4882a593Smuzhiyun 			.owner	= THIS_MODULE,
975*4882a593Smuzhiyun 			.label	= "GPIOK",
976*4882a593Smuzhiyun 			.ngpio	= 16,
977*4882a593Smuzhiyun 		},
978*4882a593Smuzhiyun 	}, {
979*4882a593Smuzhiyun 		.base	= S3C2443_GPLCON,
980*4882a593Smuzhiyun 		.chip	= {
981*4882a593Smuzhiyun 			.base	= S3C2410_GPL(0),
982*4882a593Smuzhiyun 			.owner	= THIS_MODULE,
983*4882a593Smuzhiyun 			.label	= "GPIOL",
984*4882a593Smuzhiyun 			.ngpio	= 15,
985*4882a593Smuzhiyun 		},
986*4882a593Smuzhiyun 	}, {
987*4882a593Smuzhiyun 		.base	= S3C2443_GPMCON,
988*4882a593Smuzhiyun 		.chip	= {
989*4882a593Smuzhiyun 			.base	= S3C2410_GPM(0),
990*4882a593Smuzhiyun 			.owner	= THIS_MODULE,
991*4882a593Smuzhiyun 			.label	= "GPIOM",
992*4882a593Smuzhiyun 			.ngpio	= 2,
993*4882a593Smuzhiyun 		},
994*4882a593Smuzhiyun 	},
995*4882a593Smuzhiyun #endif
996*4882a593Smuzhiyun };
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun /*
999*4882a593Smuzhiyun  * GPIO bank summary:
1000*4882a593Smuzhiyun  *
1001*4882a593Smuzhiyun  * Bank	GPIOs	Style	SlpCon	ExtInt Group
1002*4882a593Smuzhiyun  * A	8	4Bit	Yes	1
1003*4882a593Smuzhiyun  * B	7	4Bit	Yes	1
1004*4882a593Smuzhiyun  * C	8	4Bit	Yes	2
1005*4882a593Smuzhiyun  * D	5	4Bit	Yes	3
1006*4882a593Smuzhiyun  * E	5	4Bit	Yes	None
1007*4882a593Smuzhiyun  * F	16	2Bit	Yes	4 [1]
1008*4882a593Smuzhiyun  * G	7	4Bit	Yes	5
1009*4882a593Smuzhiyun  * H	10	4Bit[2]	Yes	6
1010*4882a593Smuzhiyun  * I	16	2Bit	Yes	None
1011*4882a593Smuzhiyun  * J	12	2Bit	Yes	None
1012*4882a593Smuzhiyun  * K	16	4Bit[2]	No	None
1013*4882a593Smuzhiyun  * L	15	4Bit[2] No	None
1014*4882a593Smuzhiyun  * M	6	4Bit	No	IRQ_EINT
1015*4882a593Smuzhiyun  * N	16	2Bit	No	IRQ_EINT
1016*4882a593Smuzhiyun  * O	16	2Bit	Yes	7
1017*4882a593Smuzhiyun  * P	15	2Bit	Yes	8
1018*4882a593Smuzhiyun  * Q	9	2Bit	Yes	9
1019*4882a593Smuzhiyun  *
1020*4882a593Smuzhiyun  * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1021*4882a593Smuzhiyun  * [2] BANK has two control registers, GPxCON0 and GPxCON1
1022*4882a593Smuzhiyun  */
1023*4882a593Smuzhiyun 
1024*4882a593Smuzhiyun static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
1025*4882a593Smuzhiyun #ifdef CONFIG_ARCH_S3C64XX
1026*4882a593Smuzhiyun 	{
1027*4882a593Smuzhiyun 		.chip	= {
1028*4882a593Smuzhiyun 			.base	= S3C64XX_GPA(0),
1029*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_A_NR,
1030*4882a593Smuzhiyun 			.label	= "GPA",
1031*4882a593Smuzhiyun 		},
1032*4882a593Smuzhiyun 	}, {
1033*4882a593Smuzhiyun 		.chip	= {
1034*4882a593Smuzhiyun 			.base	= S3C64XX_GPB(0),
1035*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_B_NR,
1036*4882a593Smuzhiyun 			.label	= "GPB",
1037*4882a593Smuzhiyun 		},
1038*4882a593Smuzhiyun 	}, {
1039*4882a593Smuzhiyun 		.chip	= {
1040*4882a593Smuzhiyun 			.base	= S3C64XX_GPC(0),
1041*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_C_NR,
1042*4882a593Smuzhiyun 			.label	= "GPC",
1043*4882a593Smuzhiyun 		},
1044*4882a593Smuzhiyun 	}, {
1045*4882a593Smuzhiyun 		.chip	= {
1046*4882a593Smuzhiyun 			.base	= S3C64XX_GPD(0),
1047*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_D_NR,
1048*4882a593Smuzhiyun 			.label	= "GPD",
1049*4882a593Smuzhiyun 		},
1050*4882a593Smuzhiyun 	}, {
1051*4882a593Smuzhiyun 		.config	= &samsung_gpio_cfgs[0],
1052*4882a593Smuzhiyun 		.chip	= {
1053*4882a593Smuzhiyun 			.base	= S3C64XX_GPE(0),
1054*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_E_NR,
1055*4882a593Smuzhiyun 			.label	= "GPE",
1056*4882a593Smuzhiyun 		},
1057*4882a593Smuzhiyun 	}, {
1058*4882a593Smuzhiyun 		.base	= S3C64XX_GPG_BASE,
1059*4882a593Smuzhiyun 		.chip	= {
1060*4882a593Smuzhiyun 			.base	= S3C64XX_GPG(0),
1061*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_G_NR,
1062*4882a593Smuzhiyun 			.label	= "GPG",
1063*4882a593Smuzhiyun 		},
1064*4882a593Smuzhiyun 	}, {
1065*4882a593Smuzhiyun 		.base	= S3C64XX_GPM_BASE,
1066*4882a593Smuzhiyun 		.config	= &samsung_gpio_cfgs[1],
1067*4882a593Smuzhiyun 		.chip	= {
1068*4882a593Smuzhiyun 			.base	= S3C64XX_GPM(0),
1069*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_M_NR,
1070*4882a593Smuzhiyun 			.label	= "GPM",
1071*4882a593Smuzhiyun 			.to_irq = s3c64xx_gpiolib_mbank_to_irq,
1072*4882a593Smuzhiyun 		},
1073*4882a593Smuzhiyun 	},
1074*4882a593Smuzhiyun #endif
1075*4882a593Smuzhiyun };
1076*4882a593Smuzhiyun 
1077*4882a593Smuzhiyun static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
1078*4882a593Smuzhiyun #ifdef CONFIG_ARCH_S3C64XX
1079*4882a593Smuzhiyun 	{
1080*4882a593Smuzhiyun 		.base	= S3C64XX_GPH_BASE + 0x4,
1081*4882a593Smuzhiyun 		.chip	= {
1082*4882a593Smuzhiyun 			.base	= S3C64XX_GPH(0),
1083*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_H_NR,
1084*4882a593Smuzhiyun 			.label	= "GPH",
1085*4882a593Smuzhiyun 		},
1086*4882a593Smuzhiyun 	}, {
1087*4882a593Smuzhiyun 		.base	= S3C64XX_GPK_BASE + 0x4,
1088*4882a593Smuzhiyun 		.config	= &samsung_gpio_cfgs[0],
1089*4882a593Smuzhiyun 		.chip	= {
1090*4882a593Smuzhiyun 			.base	= S3C64XX_GPK(0),
1091*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_K_NR,
1092*4882a593Smuzhiyun 			.label	= "GPK",
1093*4882a593Smuzhiyun 		},
1094*4882a593Smuzhiyun 	}, {
1095*4882a593Smuzhiyun 		.base	= S3C64XX_GPL_BASE + 0x4,
1096*4882a593Smuzhiyun 		.config	= &samsung_gpio_cfgs[1],
1097*4882a593Smuzhiyun 		.chip	= {
1098*4882a593Smuzhiyun 			.base	= S3C64XX_GPL(0),
1099*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_L_NR,
1100*4882a593Smuzhiyun 			.label	= "GPL",
1101*4882a593Smuzhiyun 			.to_irq = s3c64xx_gpiolib_lbank_to_irq,
1102*4882a593Smuzhiyun 		},
1103*4882a593Smuzhiyun 	},
1104*4882a593Smuzhiyun #endif
1105*4882a593Smuzhiyun };
1106*4882a593Smuzhiyun 
1107*4882a593Smuzhiyun static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
1108*4882a593Smuzhiyun #ifdef CONFIG_ARCH_S3C64XX
1109*4882a593Smuzhiyun 	{
1110*4882a593Smuzhiyun 		.base	= S3C64XX_GPF_BASE,
1111*4882a593Smuzhiyun 		.config	= &samsung_gpio_cfgs[6],
1112*4882a593Smuzhiyun 		.chip	= {
1113*4882a593Smuzhiyun 			.base	= S3C64XX_GPF(0),
1114*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_F_NR,
1115*4882a593Smuzhiyun 			.label	= "GPF",
1116*4882a593Smuzhiyun 		},
1117*4882a593Smuzhiyun 	}, {
1118*4882a593Smuzhiyun 		.config	= &samsung_gpio_cfgs[7],
1119*4882a593Smuzhiyun 		.chip	= {
1120*4882a593Smuzhiyun 			.base	= S3C64XX_GPI(0),
1121*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_I_NR,
1122*4882a593Smuzhiyun 			.label	= "GPI",
1123*4882a593Smuzhiyun 		},
1124*4882a593Smuzhiyun 	}, {
1125*4882a593Smuzhiyun 		.config	= &samsung_gpio_cfgs[7],
1126*4882a593Smuzhiyun 		.chip	= {
1127*4882a593Smuzhiyun 			.base	= S3C64XX_GPJ(0),
1128*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_J_NR,
1129*4882a593Smuzhiyun 			.label	= "GPJ",
1130*4882a593Smuzhiyun 		},
1131*4882a593Smuzhiyun 	}, {
1132*4882a593Smuzhiyun 		.config	= &samsung_gpio_cfgs[6],
1133*4882a593Smuzhiyun 		.chip	= {
1134*4882a593Smuzhiyun 			.base	= S3C64XX_GPO(0),
1135*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_O_NR,
1136*4882a593Smuzhiyun 			.label	= "GPO",
1137*4882a593Smuzhiyun 		},
1138*4882a593Smuzhiyun 	}, {
1139*4882a593Smuzhiyun 		.config	= &samsung_gpio_cfgs[6],
1140*4882a593Smuzhiyun 		.chip	= {
1141*4882a593Smuzhiyun 			.base	= S3C64XX_GPP(0),
1142*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_P_NR,
1143*4882a593Smuzhiyun 			.label	= "GPP",
1144*4882a593Smuzhiyun 		},
1145*4882a593Smuzhiyun 	}, {
1146*4882a593Smuzhiyun 		.config	= &samsung_gpio_cfgs[6],
1147*4882a593Smuzhiyun 		.chip	= {
1148*4882a593Smuzhiyun 			.base	= S3C64XX_GPQ(0),
1149*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_Q_NR,
1150*4882a593Smuzhiyun 			.label	= "GPQ",
1151*4882a593Smuzhiyun 		},
1152*4882a593Smuzhiyun 	}, {
1153*4882a593Smuzhiyun 		.base	= S3C64XX_GPN_BASE,
1154*4882a593Smuzhiyun 		.irq_base = IRQ_EINT(0),
1155*4882a593Smuzhiyun 		.config	= &samsung_gpio_cfgs[5],
1156*4882a593Smuzhiyun 		.chip	= {
1157*4882a593Smuzhiyun 			.base	= S3C64XX_GPN(0),
1158*4882a593Smuzhiyun 			.ngpio	= S3C64XX_GPIO_N_NR,
1159*4882a593Smuzhiyun 			.label	= "GPN",
1160*4882a593Smuzhiyun 			.to_irq = samsung_gpiolib_to_irq,
1161*4882a593Smuzhiyun 		},
1162*4882a593Smuzhiyun 	},
1163*4882a593Smuzhiyun #endif
1164*4882a593Smuzhiyun };
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun /* TODO: cleanup soc_is_* */
samsung_gpiolib_init(void)1167*4882a593Smuzhiyun static __init int samsung_gpiolib_init(void)
1168*4882a593Smuzhiyun {
1169*4882a593Smuzhiyun 	/*
1170*4882a593Smuzhiyun 	 * Currently there are two drivers that can provide GPIO support for
1171*4882a593Smuzhiyun 	 * Samsung SoCs. For device tree enabled platforms, the new
1172*4882a593Smuzhiyun 	 * pinctrl-samsung driver is used, providing both GPIO and pin control
1173*4882a593Smuzhiyun 	 * interfaces. For legacy (non-DT) platforms this driver is used.
1174*4882a593Smuzhiyun 	 */
1175*4882a593Smuzhiyun 	if (of_have_populated_dt())
1176*4882a593Smuzhiyun 		return 0;
1177*4882a593Smuzhiyun 
1178*4882a593Smuzhiyun 	if (soc_is_s3c24xx()) {
1179*4882a593Smuzhiyun 		samsung_gpiolib_set_cfg(samsung_gpio_cfgs,
1180*4882a593Smuzhiyun 				ARRAY_SIZE(samsung_gpio_cfgs));
1181*4882a593Smuzhiyun 		s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
1182*4882a593Smuzhiyun 				ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
1183*4882a593Smuzhiyun 	} else if (soc_is_s3c64xx()) {
1184*4882a593Smuzhiyun 		samsung_gpiolib_set_cfg(samsung_gpio_cfgs,
1185*4882a593Smuzhiyun 				ARRAY_SIZE(samsung_gpio_cfgs));
1186*4882a593Smuzhiyun 		samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
1187*4882a593Smuzhiyun 				ARRAY_SIZE(s3c64xx_gpios_2bit),
1188*4882a593Smuzhiyun 				S3C64XX_VA_GPIO + 0xE0, 0x20);
1189*4882a593Smuzhiyun 		samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
1190*4882a593Smuzhiyun 				ARRAY_SIZE(s3c64xx_gpios_4bit),
1191*4882a593Smuzhiyun 				S3C64XX_VA_GPIO);
1192*4882a593Smuzhiyun 		samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
1193*4882a593Smuzhiyun 				ARRAY_SIZE(s3c64xx_gpios_4bit2));
1194*4882a593Smuzhiyun 	}
1195*4882a593Smuzhiyun 
1196*4882a593Smuzhiyun 	return 0;
1197*4882a593Smuzhiyun }
1198*4882a593Smuzhiyun core_initcall(samsung_gpiolib_init);
1199*4882a593Smuzhiyun 
s3c_gpio_cfgpin(unsigned int pin,unsigned int config)1200*4882a593Smuzhiyun int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
1201*4882a593Smuzhiyun {
1202*4882a593Smuzhiyun 	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1203*4882a593Smuzhiyun 	unsigned long flags;
1204*4882a593Smuzhiyun 	int offset;
1205*4882a593Smuzhiyun 	int ret;
1206*4882a593Smuzhiyun 
1207*4882a593Smuzhiyun 	if (!chip)
1208*4882a593Smuzhiyun 		return -EINVAL;
1209*4882a593Smuzhiyun 
1210*4882a593Smuzhiyun 	offset = pin - chip->chip.base;
1211*4882a593Smuzhiyun 
1212*4882a593Smuzhiyun 	samsung_gpio_lock(chip, flags);
1213*4882a593Smuzhiyun 	ret = samsung_gpio_do_setcfg(chip, offset, config);
1214*4882a593Smuzhiyun 	samsung_gpio_unlock(chip, flags);
1215*4882a593Smuzhiyun 
1216*4882a593Smuzhiyun 	return ret;
1217*4882a593Smuzhiyun }
1218*4882a593Smuzhiyun EXPORT_SYMBOL(s3c_gpio_cfgpin);
1219*4882a593Smuzhiyun 
s3c_gpio_cfgpin_range(unsigned int start,unsigned int nr,unsigned int cfg)1220*4882a593Smuzhiyun int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
1221*4882a593Smuzhiyun 			  unsigned int cfg)
1222*4882a593Smuzhiyun {
1223*4882a593Smuzhiyun 	int ret;
1224*4882a593Smuzhiyun 
1225*4882a593Smuzhiyun 	for (; nr > 0; nr--, start++) {
1226*4882a593Smuzhiyun 		ret = s3c_gpio_cfgpin(start, cfg);
1227*4882a593Smuzhiyun 		if (ret != 0)
1228*4882a593Smuzhiyun 			return ret;
1229*4882a593Smuzhiyun 	}
1230*4882a593Smuzhiyun 
1231*4882a593Smuzhiyun 	return 0;
1232*4882a593Smuzhiyun }
1233*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
1234*4882a593Smuzhiyun 
s3c_gpio_cfgall_range(unsigned int start,unsigned int nr,unsigned int cfg,samsung_gpio_pull_t pull)1235*4882a593Smuzhiyun int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
1236*4882a593Smuzhiyun 			  unsigned int cfg, samsung_gpio_pull_t pull)
1237*4882a593Smuzhiyun {
1238*4882a593Smuzhiyun 	int ret;
1239*4882a593Smuzhiyun 
1240*4882a593Smuzhiyun 	for (; nr > 0; nr--, start++) {
1241*4882a593Smuzhiyun 		s3c_gpio_setpull(start, pull);
1242*4882a593Smuzhiyun 		ret = s3c_gpio_cfgpin(start, cfg);
1243*4882a593Smuzhiyun 		if (ret != 0)
1244*4882a593Smuzhiyun 			return ret;
1245*4882a593Smuzhiyun 	}
1246*4882a593Smuzhiyun 
1247*4882a593Smuzhiyun 	return 0;
1248*4882a593Smuzhiyun }
1249*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
1250*4882a593Smuzhiyun 
s3c_gpio_getcfg(unsigned int pin)1251*4882a593Smuzhiyun unsigned s3c_gpio_getcfg(unsigned int pin)
1252*4882a593Smuzhiyun {
1253*4882a593Smuzhiyun 	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1254*4882a593Smuzhiyun 	unsigned long flags;
1255*4882a593Smuzhiyun 	unsigned ret = 0;
1256*4882a593Smuzhiyun 	int offset;
1257*4882a593Smuzhiyun 
1258*4882a593Smuzhiyun 	if (chip) {
1259*4882a593Smuzhiyun 		offset = pin - chip->chip.base;
1260*4882a593Smuzhiyun 
1261*4882a593Smuzhiyun 		samsung_gpio_lock(chip, flags);
1262*4882a593Smuzhiyun 		ret = samsung_gpio_do_getcfg(chip, offset);
1263*4882a593Smuzhiyun 		samsung_gpio_unlock(chip, flags);
1264*4882a593Smuzhiyun 	}
1265*4882a593Smuzhiyun 
1266*4882a593Smuzhiyun 	return ret;
1267*4882a593Smuzhiyun }
1268*4882a593Smuzhiyun EXPORT_SYMBOL(s3c_gpio_getcfg);
1269*4882a593Smuzhiyun 
s3c_gpio_setpull(unsigned int pin,samsung_gpio_pull_t pull)1270*4882a593Smuzhiyun int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
1271*4882a593Smuzhiyun {
1272*4882a593Smuzhiyun 	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1273*4882a593Smuzhiyun 	unsigned long flags;
1274*4882a593Smuzhiyun 	int offset, ret;
1275*4882a593Smuzhiyun 
1276*4882a593Smuzhiyun 	if (!chip)
1277*4882a593Smuzhiyun 		return -EINVAL;
1278*4882a593Smuzhiyun 
1279*4882a593Smuzhiyun 	offset = pin - chip->chip.base;
1280*4882a593Smuzhiyun 
1281*4882a593Smuzhiyun 	samsung_gpio_lock(chip, flags);
1282*4882a593Smuzhiyun 	ret = samsung_gpio_do_setpull(chip, offset, pull);
1283*4882a593Smuzhiyun 	samsung_gpio_unlock(chip, flags);
1284*4882a593Smuzhiyun 
1285*4882a593Smuzhiyun 	return ret;
1286*4882a593Smuzhiyun }
1287*4882a593Smuzhiyun EXPORT_SYMBOL(s3c_gpio_setpull);
1288*4882a593Smuzhiyun 
s3c_gpio_getpull(unsigned int pin)1289*4882a593Smuzhiyun samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
1290*4882a593Smuzhiyun {
1291*4882a593Smuzhiyun 	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1292*4882a593Smuzhiyun 	unsigned long flags;
1293*4882a593Smuzhiyun 	int offset;
1294*4882a593Smuzhiyun 	u32 pup = 0;
1295*4882a593Smuzhiyun 
1296*4882a593Smuzhiyun 	if (chip) {
1297*4882a593Smuzhiyun 		offset = pin - chip->chip.base;
1298*4882a593Smuzhiyun 
1299*4882a593Smuzhiyun 		samsung_gpio_lock(chip, flags);
1300*4882a593Smuzhiyun 		pup = samsung_gpio_do_getpull(chip, offset);
1301*4882a593Smuzhiyun 		samsung_gpio_unlock(chip, flags);
1302*4882a593Smuzhiyun 	}
1303*4882a593Smuzhiyun 
1304*4882a593Smuzhiyun 	return (__force samsung_gpio_pull_t)pup;
1305*4882a593Smuzhiyun }
1306*4882a593Smuzhiyun EXPORT_SYMBOL(s3c_gpio_getpull);
1307*4882a593Smuzhiyun 
1308*4882a593Smuzhiyun #ifdef CONFIG_PLAT_S3C24XX
s3c2410_modify_misccr(unsigned int clear,unsigned int change)1309*4882a593Smuzhiyun unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
1310*4882a593Smuzhiyun {
1311*4882a593Smuzhiyun 	unsigned long flags;
1312*4882a593Smuzhiyun 	unsigned long misccr;
1313*4882a593Smuzhiyun 
1314*4882a593Smuzhiyun 	local_irq_save(flags);
1315*4882a593Smuzhiyun 	misccr = __raw_readl(S3C24XX_MISCCR);
1316*4882a593Smuzhiyun 	misccr &= ~clear;
1317*4882a593Smuzhiyun 	misccr ^= change;
1318*4882a593Smuzhiyun 	__raw_writel(misccr, S3C24XX_MISCCR);
1319*4882a593Smuzhiyun 	local_irq_restore(flags);
1320*4882a593Smuzhiyun 
1321*4882a593Smuzhiyun 	return misccr;
1322*4882a593Smuzhiyun }
1323*4882a593Smuzhiyun EXPORT_SYMBOL(s3c2410_modify_misccr);
1324*4882a593Smuzhiyun #endif
1325