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