File Index
Files and directories
Sign in
FILE

gpio-samsung.c

File preview with syntax highlighting.

linux-6.19.14/arch/arm/mach-s3c/gpio-samsung.c C
  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/gpio/driver.h>
 15#include <linux/irq.h>
 16#include <linux/io.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 "pm.h"
 39
 40static int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
 41				unsigned int off, samsung_gpio_pull_t pull)
 42{
 43	void __iomem *reg = chip->base + 0x08;
 44	int shift = off * 2;
 45	u32 pup;
 46
 47	pup = __raw_readl(reg);
 48	pup &= ~(3 << shift);
 49	pup |= pull << shift;
 50	__raw_writel(pup, reg);
 51
 52	return 0;
 53}
 54
 55static samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
 56						unsigned int off)
 57{
 58	void __iomem *reg = chip->base + 0x08;
 59	int shift = off * 2;
 60	u32 pup = __raw_readl(reg);
 61
 62	pup >>= shift;
 63	pup &= 0x3;
 64
 65	return (__force samsung_gpio_pull_t)pup;
 66}
 67
 68static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
 69				    unsigned int off, unsigned int cfg)
 70{
 71	void __iomem *reg = chip->base;
 72	unsigned int shift = off * 2;
 73	u32 con;
 74
 75	if (samsung_gpio_is_cfg_special(cfg)) {
 76		cfg &= 0xf;
 77		if (cfg > 3)
 78			return -EINVAL;
 79
 80		cfg <<= shift;
 81	}
 82
 83	con = __raw_readl(reg);
 84	con &= ~(0x3 << shift);
 85	con |= cfg;
 86	__raw_writel(con, reg);
 87
 88	return 0;
 89}
 90
 91/*
 92 * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
 93 * @chip: The gpio chip that is being configured.
 94 * @off: The offset for the GPIO being configured.
 95 *
 96 * The reverse of samsung_gpio_setcfg_2bit(). Will return a value which
 97 * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
 98 * S3C_GPIO_SPECIAL() macro.
 99 */
100
101static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
102					     unsigned int off)
103{
104	u32 con;
105
106	con = __raw_readl(chip->base);
107	con >>= off * 2;
108	con &= 3;
109
110	/* this conversion works for IN and OUT as well as special mode */
111	return S3C_GPIO_SPECIAL(con);
112}
113
114/*
115 * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
116 * @chip: The gpio chip that is being configured.
117 * @off: The offset for the GPIO being configured.
118 * @cfg: The configuration value to set.
119 *
120 * This helper deal with the GPIO cases where the control register has 4 bits
121 * of control per GPIO, generally in the form of:
122 *	0000 = Input
123 *	0001 = Output
124 *	others = Special functions (dependent on bank)
125 *
126 * Note, since the code to deal with the case where there are two control
127 * registers instead of one, we do not have a separate set of functions for
128 * each case.
129 */
130
131static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
132				    unsigned int off, unsigned int cfg)
133{
134	void __iomem *reg = chip->base;
135	unsigned int shift = (off & 7) * 4;
136	u32 con;
137
138	if (off < 8 && chip->chip.ngpio > 8)
139		reg -= 4;
140
141	if (samsung_gpio_is_cfg_special(cfg)) {
142		cfg &= 0xf;
143		cfg <<= shift;
144	}
145
146	con = __raw_readl(reg);
147	con &= ~(0xf << shift);
148	con |= cfg;
149	__raw_writel(con, reg);
150
151	return 0;
152}
153
154/*
155 * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
156 * @chip: The gpio chip that is being configured.
157 * @off: The offset for the GPIO being configured.
158 *
159 * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
160 * register setting into a value the software can use, such as could be passed
161 * to samsung_gpio_setcfg_4bit().
162 *
163 * @sa samsung_gpio_getcfg_2bit
164 */
165
166static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
167					 unsigned int off)
168{
169	void __iomem *reg = chip->base;
170	unsigned int shift = (off & 7) * 4;
171	u32 con;
172
173	if (off < 8 && chip->chip.ngpio > 8)
174		reg -= 4;
175
176	con = __raw_readl(reg);
177	con >>= shift;
178	con &= 0xf;
179
180	/* this conversion works for IN and OUT as well as special mode */
181	return S3C_GPIO_SPECIAL(con);
182}
183
184static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
185					   int nr_chips)
186{
187	for (; nr_chips > 0; nr_chips--, chipcfg++) {
188		if (!chipcfg->set_config)
189			chipcfg->set_config = samsung_gpio_setcfg_4bit;
190		if (!chipcfg->get_config)
191			chipcfg->get_config = samsung_gpio_getcfg_4bit;
192		if (!chipcfg->set_pull)
193			chipcfg->set_pull = samsung_gpio_setpull_updown;
194		if (!chipcfg->get_pull)
195			chipcfg->get_pull = samsung_gpio_getpull_updown;
196	}
197}
198
199static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
200	[0] = {
201		.cfg_eint	= 0x0,
202	},
203	[1] = {
204		.cfg_eint	= 0x3,
205	},
206	[2] = {
207		.cfg_eint	= 0x7,
208	},
209	[3] = {
210		.cfg_eint	= 0xF,
211	},
212	[4] = {
213		.cfg_eint	= 0x0,
214		.set_config	= samsung_gpio_setcfg_2bit,
215		.get_config	= samsung_gpio_getcfg_2bit,
216	},
217	[5] = {
218		.cfg_eint	= 0x2,
219		.set_config	= samsung_gpio_setcfg_2bit,
220		.get_config	= samsung_gpio_getcfg_2bit,
221	},
222	[6] = {
223		.cfg_eint	= 0x3,
224		.set_config	= samsung_gpio_setcfg_2bit,
225		.get_config	= samsung_gpio_getcfg_2bit,
226	},
227	[7] = {
228		.set_config	= samsung_gpio_setcfg_2bit,
229		.get_config	= samsung_gpio_getcfg_2bit,
230	},
231};
232
233/*
234 * Default routines for controlling GPIO, based on the original S3C24XX
235 * GPIO functions which deal with the case where each gpio bank of the
236 * chip is as following:
237 *
238 * base + 0x00: Control register, 2 bits per gpio
239 *	        gpio n: 2 bits starting at (2*n)
240 *		00 = input, 01 = output, others mean special-function
241 * base + 0x04: Data register, 1 bit per gpio
242 *		bit n: data bit n
243*/
244
245static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
246{
247	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
248	void __iomem *base = ourchip->base;
249	unsigned long flags;
250	unsigned long con;
251
252	samsung_gpio_lock(ourchip, flags);
253
254	con = __raw_readl(base + 0x00);
255	con &= ~(3 << (offset * 2));
256
257	__raw_writel(con, base + 0x00);
258
259	samsung_gpio_unlock(ourchip, flags);
260	return 0;
261}
262
263static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
264				       unsigned offset, int value)
265{
266	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
267	void __iomem *base = ourchip->base;
268	unsigned long flags;
269	unsigned long dat;
270	unsigned long con;
271
272	samsung_gpio_lock(ourchip, flags);
273
274	dat = __raw_readl(base + 0x04);
275	dat &= ~(1 << offset);
276	if (value)
277		dat |= 1 << offset;
278	__raw_writel(dat, base + 0x04);
279
280	con = __raw_readl(base + 0x00);
281	con &= ~(3 << (offset * 2));
282	con |= 1 << (offset * 2);
283
284	__raw_writel(con, base + 0x00);
285	__raw_writel(dat, base + 0x04);
286
287	samsung_gpio_unlock(ourchip, flags);
288	return 0;
289}
290
291/*
292 * The samsung_gpiolib_4bit routines are to control the gpio banks where
293 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
294 * following example:
295 *
296 * base + 0x00: Control register, 4 bits per gpio
297 *		gpio n: 4 bits starting at (4*n)
298 *		0000 = input, 0001 = output, others mean special-function
299 * base + 0x04: Data register, 1 bit per gpio
300 *		bit n: data bit n
301 *
302 * Note, since the data register is one bit per gpio and is at base + 0x4
303 * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
304 * state of the output.
305 */
306
307static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
308				      unsigned int offset)
309{
310	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
311	void __iomem *base = ourchip->base;
312	unsigned long con;
313
314	con = __raw_readl(base + GPIOCON_OFF);
315	if (ourchip->bitmap_gpio_int & BIT(offset))
316		con |= 0xf << con_4bit_shift(offset);
317	else
318		con &= ~(0xf << con_4bit_shift(offset));
319	__raw_writel(con, base + GPIOCON_OFF);
320
321	pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
322
323	return 0;
324}
325
326static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
327				       unsigned int offset, int value)
328{
329	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
330	void __iomem *base = ourchip->base;
331	unsigned long con;
332	unsigned long dat;
333
334	con = __raw_readl(base + GPIOCON_OFF);
335	con &= ~(0xf << con_4bit_shift(offset));
336	con |= 0x1 << con_4bit_shift(offset);
337
338	dat = __raw_readl(base + GPIODAT_OFF);
339
340	if (value)
341		dat |= 1 << offset;
342	else
343		dat &= ~(1 << offset);
344
345	__raw_writel(dat, base + GPIODAT_OFF);
346	__raw_writel(con, base + GPIOCON_OFF);
347	__raw_writel(dat, base + GPIODAT_OFF);
348
349	pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
350
351	return 0;
352}
353
354/*
355 * The next set of routines are for the case where the GPIO configuration
356 * registers are 4 bits per GPIO but there is more than one register (the
357 * bank has more than 8 GPIOs.
358 *
359 * This case is the similar to the 4 bit case, but the registers are as
360 * follows:
361 *
362 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
363 *		gpio n: 4 bits starting at (4*n)
364 *		0000 = input, 0001 = output, others mean special-function
365 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
366 *		gpio n: 4 bits starting at (4*n)
367 *		0000 = input, 0001 = output, others mean special-function
368 * base + 0x08: Data register, 1 bit per gpio
369 *		bit n: data bit n
370 *
371 * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
372 * routines we store the 'base + 0x4' address so that these routines see
373 * the data register at ourchip->base + 0x04.
374 */
375
376static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
377				       unsigned int offset)
378{
379	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
380	void __iomem *base = ourchip->base;
381	void __iomem *regcon = base;
382	unsigned long con;
383
384	if (offset > 7)
385		offset -= 8;
386	else
387		regcon -= 4;
388
389	con = __raw_readl(regcon);
390	con &= ~(0xf << con_4bit_shift(offset));
391	__raw_writel(con, regcon);
392
393	pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
394
395	return 0;
396}
397
398static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
399					unsigned int offset, int value)
400{
401	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
402	void __iomem *base = ourchip->base;
403	void __iomem *regcon = base;
404	unsigned long con;
405	unsigned long dat;
406	unsigned con_offset = offset;
407
408	if (con_offset > 7)
409		con_offset -= 8;
410	else
411		regcon -= 4;
412
413	con = __raw_readl(regcon);
414	con &= ~(0xf << con_4bit_shift(con_offset));
415	con |= 0x1 << con_4bit_shift(con_offset);
416
417	dat = __raw_readl(base + GPIODAT_OFF);
418
419	if (value)
420		dat |= 1 << offset;
421	else
422		dat &= ~(1 << offset);
423
424	__raw_writel(dat, base + GPIODAT_OFF);
425	__raw_writel(con, regcon);
426	__raw_writel(dat, base + GPIODAT_OFF);
427
428	pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
429
430	return 0;
431}
432
433static int samsung_gpiolib_set(struct gpio_chip *chip, unsigned int offset,
434			       int value)
435{
436	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
437	void __iomem *base = ourchip->base;
438	unsigned long flags;
439	unsigned long dat;
440
441	samsung_gpio_lock(ourchip, flags);
442
443	dat = __raw_readl(base + 0x04);
444	dat &= ~(1 << offset);
445	if (value)
446		dat |= 1 << offset;
447	__raw_writel(dat, base + 0x04);
448
449	samsung_gpio_unlock(ourchip, flags);
450
451	return 0;
452}
453
454static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
455{
456	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
457	unsigned long val;
458
459	val = __raw_readl(ourchip->base + 0x04);
460	val >>= offset;
461	val &= 1;
462
463	return val;
464}
465
466/*
467 * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
468 * for use with the configuration calls, and other parts of the s3c gpiolib
469 * support code.
470 *
471 * Not all s3c support code will need this, as some configurations of cpu
472 * may only support one or two different configuration options and have an
473 * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
474 * the machine support file should provide its own samsung_gpiolib_getchip()
475 * and any other necessary functions.
476 */
477
478#ifdef CONFIG_S3C_GPIO_TRACK
479struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
480
481static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
482{
483	unsigned int gpn;
484	int i;
485
486	gpn = chip->chip.base;
487	for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
488		BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
489		s3c_gpios[gpn] = chip;
490	}
491}
492#endif /* CONFIG_S3C_GPIO_TRACK */
493
494/*
495 * samsung_gpiolib_add() - add the Samsung gpio_chip.
496 * @chip: The chip to register
497 *
498 * This is a wrapper to gpiochip_add() that takes our specific gpio chip
499 * information and makes the necessary alterations for the platform and
500 * notes the information for use with the configuration systems and any
501 * other parts of the system.
502 */
503
504static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
505{
506	struct gpio_chip *gc = &chip->chip;
507	int ret;
508
509	BUG_ON(!chip->base);
510	BUG_ON(!gc->label);
511	BUG_ON(!gc->ngpio);
512
513	spin_lock_init(&chip->lock);
514
515	if (!gc->direction_input)
516		gc->direction_input = samsung_gpiolib_2bit_input;
517	if (!gc->direction_output)
518		gc->direction_output = samsung_gpiolib_2bit_output;
519	if (!gc->set)
520		gc->set = samsung_gpiolib_set;
521	if (!gc->get)
522		gc->get = samsung_gpiolib_get;
523
524#ifdef CONFIG_PM
525	if (chip->pm != NULL) {
526		if (!chip->pm->save || !chip->pm->resume)
527			pr_err("gpio: %s has missing PM functions\n",
528			       gc->label);
529	} else
530		pr_err("gpio: %s has no PM function\n", gc->label);
531#endif
532
533	/* gpiochip_add() prints own failure message on error. */
534	ret = gpiochip_add_data(gc, chip);
535	if (ret >= 0)
536		s3c_gpiolib_track(chip);
537}
538
539static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
540						  int nr_chips, void __iomem *base,
541						  unsigned int offset)
542{
543	int i;
544
545	for (i = 0 ; i < nr_chips; i++, chip++) {
546		chip->chip.direction_input = samsung_gpiolib_2bit_input;
547		chip->chip.direction_output = samsung_gpiolib_2bit_output;
548
549		if (!chip->config)
550			chip->config = &samsung_gpio_cfgs[7];
551		if (!chip->pm)
552			chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
553		if ((base != NULL) && (chip->base == NULL))
554			chip->base = base + ((i) * offset);
555
556		samsung_gpiolib_add(chip);
557	}
558}
559
560/*
561 * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
562 * @chip: The gpio chip that is being configured.
563 * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
564 *
565 * This helper deal with the GPIO cases where the control register has 4 bits
566 * of control per GPIO, generally in the form of:
567 * 0000 = Input
568 * 0001 = Output
569 * others = Special functions (dependent on bank)
570 *
571 * Note, since the code to deal with the case where there are two control
572 * registers instead of one, we do not have a separate set of function
573 * (samsung_gpiolib_add_4bit2_chips)for each case.
574 */
575
576static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
577						  int nr_chips, void __iomem *base)
578{
579	int i;
580
581	for (i = 0 ; i < nr_chips; i++, chip++) {
582		chip->chip.direction_input = samsung_gpiolib_4bit_input;
583		chip->chip.direction_output = samsung_gpiolib_4bit_output;
584
585		if (!chip->config)
586			chip->config = &samsung_gpio_cfgs[2];
587		if (!chip->pm)
588			chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
589		if ((base != NULL) && (chip->base == NULL))
590			chip->base = base + ((i) * 0x20);
591
592		chip->bitmap_gpio_int = 0;
593
594		samsung_gpiolib_add(chip);
595	}
596}
597
598static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
599						   int nr_chips)
600{
601	for (; nr_chips > 0; nr_chips--, chip++) {
602		chip->chip.direction_input = samsung_gpiolib_4bit2_input;
603		chip->chip.direction_output = samsung_gpiolib_4bit2_output;
604
605		if (!chip->config)
606			chip->config = &samsung_gpio_cfgs[2];
607		if (!chip->pm)
608			chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
609
610		samsung_gpiolib_add(chip);
611	}
612}
613
614int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
615{
616	struct samsung_gpio_chip *samsung_chip = gpiochip_get_data(chip);
617
618	return samsung_chip->irq_base + offset;
619}
620
621static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
622{
623	return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
624}
625
626static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
627{
628	return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
629}
630
631/*
632 * GPIO bank summary:
633 *
634 * Bank	GPIOs	Style	SlpCon	ExtInt Group
635 * A	8	4Bit	Yes	1
636 * B	7	4Bit	Yes	1
637 * C	8	4Bit	Yes	2
638 * D	5	4Bit	Yes	3
639 * E	5	4Bit	Yes	None
640 * F	16	2Bit	Yes	4 [1]
641 * G	7	4Bit	Yes	5
642 * H	10	4Bit[2]	Yes	6
643 * I	16	2Bit	Yes	None
644 * J	12	2Bit	Yes	None
645 * K	16	4Bit[2]	No	None
646 * L	15	4Bit[2] No	None
647 * M	6	4Bit	No	IRQ_EINT
648 * N	16	2Bit	No	IRQ_EINT
649 * O	16	2Bit	Yes	7
650 * P	15	2Bit	Yes	8
651 * Q	9	2Bit	Yes	9
652 *
653 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
654 * [2] BANK has two control registers, GPxCON0 and GPxCON1
655 */
656
657static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
658	{
659		.chip	= {
660			.base	= S3C64XX_GPA(0),
661			.ngpio	= S3C64XX_GPIO_A_NR,
662			.label	= "GPA",
663		},
664	}, {
665		.chip	= {
666			.base	= S3C64XX_GPB(0),
667			.ngpio	= S3C64XX_GPIO_B_NR,
668			.label	= "GPB",
669		},
670	}, {
671		.chip	= {
672			.base	= S3C64XX_GPC(0),
673			.ngpio	= S3C64XX_GPIO_C_NR,
674			.label	= "GPC",
675		},
676	}, {
677		.chip	= {
678			.base	= S3C64XX_GPD(0),
679			.ngpio	= S3C64XX_GPIO_D_NR,
680			.label	= "GPD",
681		},
682	}, {
683		.config	= &samsung_gpio_cfgs[0],
684		.chip	= {
685			.base	= S3C64XX_GPE(0),
686			.ngpio	= S3C64XX_GPIO_E_NR,
687			.label	= "GPE",
688		},
689	}, {
690		.base	= S3C64XX_GPG_BASE,
691		.chip	= {
692			.base	= S3C64XX_GPG(0),
693			.ngpio	= S3C64XX_GPIO_G_NR,
694			.label	= "GPG",
695		},
696	}, {
697		.base	= S3C64XX_GPM_BASE,
698		.config	= &samsung_gpio_cfgs[1],
699		.chip	= {
700			.base	= S3C64XX_GPM(0),
701			.ngpio	= S3C64XX_GPIO_M_NR,
702			.label	= "GPM",
703			.to_irq = s3c64xx_gpiolib_mbank_to_irq,
704		},
705	},
706};
707
708static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
709	{
710		.base	= S3C64XX_GPH_BASE + 0x4,
711		.chip	= {
712			.base	= S3C64XX_GPH(0),
713			.ngpio	= S3C64XX_GPIO_H_NR,
714			.label	= "GPH",
715		},
716	}, {
717		.base	= S3C64XX_GPK_BASE + 0x4,
718		.config	= &samsung_gpio_cfgs[0],
719		.chip	= {
720			.base	= S3C64XX_GPK(0),
721			.ngpio	= S3C64XX_GPIO_K_NR,
722			.label	= "GPK",
723		},
724	}, {
725		.base	= S3C64XX_GPL_BASE + 0x4,
726		.config	= &samsung_gpio_cfgs[1],
727		.chip	= {
728			.base	= S3C64XX_GPL(0),
729			.ngpio	= S3C64XX_GPIO_L_NR,
730			.label	= "GPL",
731			.to_irq = s3c64xx_gpiolib_lbank_to_irq,
732		},
733	},
734};
735
736static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
737	{
738		.base	= S3C64XX_GPF_BASE,
739		.config	= &samsung_gpio_cfgs[6],
740		.chip	= {
741			.base	= S3C64XX_GPF(0),
742			.ngpio	= S3C64XX_GPIO_F_NR,
743			.label	= "GPF",
744		},
745	}, {
746		.config	= &samsung_gpio_cfgs[7],
747		.chip	= {
748			.base	= S3C64XX_GPI(0),
749			.ngpio	= S3C64XX_GPIO_I_NR,
750			.label	= "GPI",
751		},
752	}, {
753		.config	= &samsung_gpio_cfgs[7],
754		.chip	= {
755			.base	= S3C64XX_GPJ(0),
756			.ngpio	= S3C64XX_GPIO_J_NR,
757			.label	= "GPJ",
758		},
759	}, {
760		.config	= &samsung_gpio_cfgs[6],
761		.chip	= {
762			.base	= S3C64XX_GPO(0),
763			.ngpio	= S3C64XX_GPIO_O_NR,
764			.label	= "GPO",
765		},
766	}, {
767		.config	= &samsung_gpio_cfgs[6],
768		.chip	= {
769			.base	= S3C64XX_GPP(0),
770			.ngpio	= S3C64XX_GPIO_P_NR,
771			.label	= "GPP",
772		},
773	}, {
774		.config	= &samsung_gpio_cfgs[6],
775		.chip	= {
776			.base	= S3C64XX_GPQ(0),
777			.ngpio	= S3C64XX_GPIO_Q_NR,
778			.label	= "GPQ",
779		},
780	}, {
781		.base	= S3C64XX_GPN_BASE,
782		.irq_base = IRQ_EINT(0),
783		.config	= &samsung_gpio_cfgs[5],
784		.chip	= {
785			.base	= S3C64XX_GPN(0),
786			.ngpio	= S3C64XX_GPIO_N_NR,
787			.label	= "GPN",
788			.to_irq = samsung_gpiolib_to_irq,
789		},
790	},
791};
792
793/* TODO: cleanup soc_is_* */
794static __init int samsung_gpiolib_init(void)
795{
796	/*
797	 * Currently there are two drivers that can provide GPIO support for
798	 * Samsung SoCs. For device tree enabled platforms, the new
799	 * pinctrl-samsung driver is used, providing both GPIO and pin control
800	 * interfaces. For legacy (non-DT) platforms this driver is used.
801	 */
802	if (of_have_populated_dt())
803		return 0;
804
805	if (soc_is_s3c64xx()) {
806		samsung_gpiolib_set_cfg(samsung_gpio_cfgs,
807				ARRAY_SIZE(samsung_gpio_cfgs));
808		samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
809				ARRAY_SIZE(s3c64xx_gpios_2bit),
810				S3C64XX_VA_GPIO + 0xE0, 0x20);
811		samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
812				ARRAY_SIZE(s3c64xx_gpios_4bit),
813				S3C64XX_VA_GPIO);
814		samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
815				ARRAY_SIZE(s3c64xx_gpios_4bit2));
816	}
817
818	return 0;
819}
820core_initcall(samsung_gpiolib_init);
821
822int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
823{
824	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
825	unsigned long flags;
826	int offset;
827	int ret;
828
829	if (!chip)
830		return -EINVAL;
831
832	offset = pin - chip->chip.base;
833
834	samsung_gpio_lock(chip, flags);
835	ret = samsung_gpio_do_setcfg(chip, offset, config);
836	samsung_gpio_unlock(chip, flags);
837
838	return ret;
839}
840EXPORT_SYMBOL(s3c_gpio_cfgpin);
841
842int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
843			  unsigned int cfg)
844{
845	int ret;
846
847	for (; nr > 0; nr--, start++) {
848		ret = s3c_gpio_cfgpin(start, cfg);
849		if (ret != 0)
850			return ret;
851	}
852
853	return 0;
854}
855EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
856
857int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
858			  unsigned int cfg, samsung_gpio_pull_t pull)
859{
860	int ret;
861
862	for (; nr > 0; nr--, start++) {
863		s3c_gpio_setpull(start, pull);
864		ret = s3c_gpio_cfgpin(start, cfg);
865		if (ret != 0)
866			return ret;
867	}
868
869	return 0;
870}
871EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
872
873int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
874{
875	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
876	unsigned long flags;
877	int offset, ret;
878
879	if (!chip)
880		return -EINVAL;
881
882	offset = pin - chip->chip.base;
883
884	samsung_gpio_lock(chip, flags);
885	ret = samsung_gpio_do_setpull(chip, offset, pull);
886	samsung_gpio_unlock(chip, flags);
887
888	return ret;
889}
890EXPORT_SYMBOL(s3c_gpio_setpull);
~/ Read-only file preview.