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