xref: /OK3568_Linux_fs/u-boot/drivers/gpio/s5p_gpio.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2009 Samsung Electronics
3*4882a593Smuzhiyun  * Minkyu Kang <mk7.kang@samsung.com>
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <dm.h>
10*4882a593Smuzhiyun #include <errno.h>
11*4882a593Smuzhiyun #include <fdtdec.h>
12*4882a593Smuzhiyun #include <malloc.h>
13*4882a593Smuzhiyun #include <asm/io.h>
14*4882a593Smuzhiyun #include <asm/gpio.h>
15*4882a593Smuzhiyun #include <dm/device-internal.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #define S5P_GPIO_GET_PIN(x)	(x % GPIO_PER_BANK)
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define CON_MASK(val)			(0xf << ((val) << 2))
22*4882a593Smuzhiyun #define CON_SFR(gpio, cfg)		((cfg) << ((gpio) << 2))
23*4882a593Smuzhiyun #define CON_SFR_UNSHIFT(val, gpio)	((val) >> ((gpio) << 2))
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define DAT_MASK(gpio)			(0x1 << (gpio))
26*4882a593Smuzhiyun #define DAT_SET(gpio)			(0x1 << (gpio))
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #define PULL_MASK(gpio)		(0x3 << ((gpio) << 1))
29*4882a593Smuzhiyun #define PULL_MODE(gpio, pull)		((pull) << ((gpio) << 1))
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #define DRV_MASK(gpio)			(0x3 << ((gpio) << 1))
32*4882a593Smuzhiyun #define DRV_SET(gpio, mode)		((mode) << ((gpio) << 1))
33*4882a593Smuzhiyun #define RATE_MASK(gpio)		(0x1 << (gpio + 16))
34*4882a593Smuzhiyun #define RATE_SET(gpio)			(0x1 << (gpio + 16))
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun /* Platform data for each bank */
37*4882a593Smuzhiyun struct exynos_gpio_platdata {
38*4882a593Smuzhiyun 	struct s5p_gpio_bank *bank;
39*4882a593Smuzhiyun 	const char *bank_name;	/* Name of port, e.g. 'gpa0" */
40*4882a593Smuzhiyun };
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun /* Information about each bank at run-time */
43*4882a593Smuzhiyun struct exynos_bank_info {
44*4882a593Smuzhiyun 	struct s5p_gpio_bank *bank;
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun 
s5p_gpio_get_bank(unsigned int gpio)47*4882a593Smuzhiyun static struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned int gpio)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun 	const struct gpio_info *data;
50*4882a593Smuzhiyun 	unsigned int upto;
51*4882a593Smuzhiyun 	int i, count;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	data = get_gpio_data();
54*4882a593Smuzhiyun 	count = get_bank_num();
55*4882a593Smuzhiyun 	upto = 0;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	for (i = 0; i < count; i++) {
58*4882a593Smuzhiyun 		debug("i=%d, upto=%d\n", i, upto);
59*4882a593Smuzhiyun 		if (gpio < data->max_gpio) {
60*4882a593Smuzhiyun 			struct s5p_gpio_bank *bank;
61*4882a593Smuzhiyun 			bank = (struct s5p_gpio_bank *)data->reg_addr;
62*4882a593Smuzhiyun 			bank += (gpio - upto) / GPIO_PER_BANK;
63*4882a593Smuzhiyun 			debug("gpio=%d, bank=%p\n", gpio, bank);
64*4882a593Smuzhiyun 			return bank;
65*4882a593Smuzhiyun 		}
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 		upto = data->max_gpio;
68*4882a593Smuzhiyun 		data++;
69*4882a593Smuzhiyun 	}
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	return NULL;
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun 
s5p_gpio_cfg_pin(struct s5p_gpio_bank * bank,int gpio,int cfg)74*4882a593Smuzhiyun static void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun 	unsigned int value;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	value = readl(&bank->con);
79*4882a593Smuzhiyun 	value &= ~CON_MASK(gpio);
80*4882a593Smuzhiyun 	value |= CON_SFR(gpio, cfg);
81*4882a593Smuzhiyun 	writel(value, &bank->con);
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun 
s5p_gpio_set_value(struct s5p_gpio_bank * bank,int gpio,int en)84*4882a593Smuzhiyun static void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	unsigned int value;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	value = readl(&bank->dat);
89*4882a593Smuzhiyun 	value &= ~DAT_MASK(gpio);
90*4882a593Smuzhiyun 	if (en)
91*4882a593Smuzhiyun 		value |= DAT_SET(gpio);
92*4882a593Smuzhiyun 	writel(value, &bank->dat);
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun #ifdef CONFIG_SPL_BUILD
96*4882a593Smuzhiyun /* Common GPIO API - SPL does not support driver model yet */
gpio_set_value(unsigned gpio,int value)97*4882a593Smuzhiyun int gpio_set_value(unsigned gpio, int value)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	s5p_gpio_set_value(s5p_gpio_get_bank(gpio),
100*4882a593Smuzhiyun 			   s5p_gpio_get_pin(gpio), value);
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	return 0;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun #else
s5p_gpio_get_cfg_pin(struct s5p_gpio_bank * bank,int gpio)105*4882a593Smuzhiyun static int s5p_gpio_get_cfg_pin(struct s5p_gpio_bank *bank, int gpio)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun 	unsigned int value;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	value = readl(&bank->con);
110*4882a593Smuzhiyun 	value &= CON_MASK(gpio);
111*4882a593Smuzhiyun 	return CON_SFR_UNSHIFT(value, gpio);
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun 
s5p_gpio_get_value(struct s5p_gpio_bank * bank,int gpio)114*4882a593Smuzhiyun static unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun 	unsigned int value;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	value = readl(&bank->dat);
119*4882a593Smuzhiyun 	return !!(value & DAT_MASK(gpio));
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun #endif /* CONFIG_SPL_BUILD */
122*4882a593Smuzhiyun 
s5p_gpio_set_pull(struct s5p_gpio_bank * bank,int gpio,int mode)123*4882a593Smuzhiyun static void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun 	unsigned int value;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	value = readl(&bank->pull);
128*4882a593Smuzhiyun 	value &= ~PULL_MASK(gpio);
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	switch (mode) {
131*4882a593Smuzhiyun 	case S5P_GPIO_PULL_DOWN:
132*4882a593Smuzhiyun 	case S5P_GPIO_PULL_UP:
133*4882a593Smuzhiyun 		value |= PULL_MODE(gpio, mode);
134*4882a593Smuzhiyun 		break;
135*4882a593Smuzhiyun 	default:
136*4882a593Smuzhiyun 		break;
137*4882a593Smuzhiyun 	}
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	writel(value, &bank->pull);
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun 
s5p_gpio_set_drv(struct s5p_gpio_bank * bank,int gpio,int mode)142*4882a593Smuzhiyun static void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun 	unsigned int value;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	value = readl(&bank->drv);
147*4882a593Smuzhiyun 	value &= ~DRV_MASK(gpio);
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	switch (mode) {
150*4882a593Smuzhiyun 	case S5P_GPIO_DRV_1X:
151*4882a593Smuzhiyun 	case S5P_GPIO_DRV_2X:
152*4882a593Smuzhiyun 	case S5P_GPIO_DRV_3X:
153*4882a593Smuzhiyun 	case S5P_GPIO_DRV_4X:
154*4882a593Smuzhiyun 		value |= DRV_SET(gpio, mode);
155*4882a593Smuzhiyun 		break;
156*4882a593Smuzhiyun 	default:
157*4882a593Smuzhiyun 		return;
158*4882a593Smuzhiyun 	}
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	writel(value, &bank->drv);
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun 
s5p_gpio_set_rate(struct s5p_gpio_bank * bank,int gpio,int mode)163*4882a593Smuzhiyun static void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun 	unsigned int value;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	value = readl(&bank->drv);
168*4882a593Smuzhiyun 	value &= ~RATE_MASK(gpio);
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	switch (mode) {
171*4882a593Smuzhiyun 	case S5P_GPIO_DRV_FAST:
172*4882a593Smuzhiyun 	case S5P_GPIO_DRV_SLOW:
173*4882a593Smuzhiyun 		value |= RATE_SET(gpio);
174*4882a593Smuzhiyun 		break;
175*4882a593Smuzhiyun 	default:
176*4882a593Smuzhiyun 		return;
177*4882a593Smuzhiyun 	}
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	writel(value, &bank->drv);
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun 
s5p_gpio_get_pin(unsigned gpio)182*4882a593Smuzhiyun int s5p_gpio_get_pin(unsigned gpio)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun 	return S5P_GPIO_GET_PIN(gpio);
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun /* Driver model interface */
188*4882a593Smuzhiyun #ifndef CONFIG_SPL_BUILD
189*4882a593Smuzhiyun /* set GPIO pin 'gpio' as an input */
exynos_gpio_direction_input(struct udevice * dev,unsigned offset)190*4882a593Smuzhiyun static int exynos_gpio_direction_input(struct udevice *dev, unsigned offset)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun 	struct exynos_bank_info *state = dev_get_priv(dev);
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	/* Configure GPIO direction as input. */
195*4882a593Smuzhiyun 	s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_INPUT);
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	return 0;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun /* set GPIO pin 'gpio' as an output, with polarity 'value' */
exynos_gpio_direction_output(struct udevice * dev,unsigned offset,int value)201*4882a593Smuzhiyun static int exynos_gpio_direction_output(struct udevice *dev, unsigned offset,
202*4882a593Smuzhiyun 				       int value)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun 	struct exynos_bank_info *state = dev_get_priv(dev);
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	/* Configure GPIO output value. */
207*4882a593Smuzhiyun 	s5p_gpio_set_value(state->bank, offset, value);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	/* Configure GPIO direction as output. */
210*4882a593Smuzhiyun 	s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_OUTPUT);
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	return 0;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun /* read GPIO IN value of pin 'gpio' */
exynos_gpio_get_value(struct udevice * dev,unsigned offset)216*4882a593Smuzhiyun static int exynos_gpio_get_value(struct udevice *dev, unsigned offset)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	struct exynos_bank_info *state = dev_get_priv(dev);
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	return s5p_gpio_get_value(state->bank, offset);
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun /* write GPIO OUT value to pin 'gpio' */
exynos_gpio_set_value(struct udevice * dev,unsigned offset,int value)224*4882a593Smuzhiyun static int exynos_gpio_set_value(struct udevice *dev, unsigned offset,
225*4882a593Smuzhiyun 				 int value)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun 	struct exynos_bank_info *state = dev_get_priv(dev);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	s5p_gpio_set_value(state->bank, offset, value);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	return 0;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun #endif /* nCONFIG_SPL_BUILD */
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun /*
236*4882a593Smuzhiyun  * There is no common GPIO API for pull, drv, pin, rate (yet). These
237*4882a593Smuzhiyun  * functions are kept here to preserve function ordering for review.
238*4882a593Smuzhiyun  */
gpio_set_pull(int gpio,int mode)239*4882a593Smuzhiyun void gpio_set_pull(int gpio, int mode)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun 	s5p_gpio_set_pull(s5p_gpio_get_bank(gpio),
242*4882a593Smuzhiyun 			  s5p_gpio_get_pin(gpio), mode);
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun 
gpio_set_drv(int gpio,int mode)245*4882a593Smuzhiyun void gpio_set_drv(int gpio, int mode)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun 	s5p_gpio_set_drv(s5p_gpio_get_bank(gpio),
248*4882a593Smuzhiyun 			 s5p_gpio_get_pin(gpio), mode);
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun 
gpio_cfg_pin(int gpio,int cfg)251*4882a593Smuzhiyun void gpio_cfg_pin(int gpio, int cfg)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	s5p_gpio_cfg_pin(s5p_gpio_get_bank(gpio),
254*4882a593Smuzhiyun 			 s5p_gpio_get_pin(gpio), cfg);
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun 
gpio_set_rate(int gpio,int mode)257*4882a593Smuzhiyun void gpio_set_rate(int gpio, int mode)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun 	s5p_gpio_set_rate(s5p_gpio_get_bank(gpio),
260*4882a593Smuzhiyun 			  s5p_gpio_get_pin(gpio), mode);
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun #ifndef CONFIG_SPL_BUILD
exynos_gpio_get_function(struct udevice * dev,unsigned offset)264*4882a593Smuzhiyun static int exynos_gpio_get_function(struct udevice *dev, unsigned offset)
265*4882a593Smuzhiyun {
266*4882a593Smuzhiyun 	struct exynos_bank_info *state = dev_get_priv(dev);
267*4882a593Smuzhiyun 	int cfg;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	cfg = s5p_gpio_get_cfg_pin(state->bank, offset);
270*4882a593Smuzhiyun 	if (cfg == S5P_GPIO_OUTPUT)
271*4882a593Smuzhiyun 		return GPIOF_OUTPUT;
272*4882a593Smuzhiyun 	else if (cfg == S5P_GPIO_INPUT)
273*4882a593Smuzhiyun 		return GPIOF_INPUT;
274*4882a593Smuzhiyun 	else
275*4882a593Smuzhiyun 		return GPIOF_FUNC;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun static const struct dm_gpio_ops gpio_exynos_ops = {
279*4882a593Smuzhiyun 	.direction_input	= exynos_gpio_direction_input,
280*4882a593Smuzhiyun 	.direction_output	= exynos_gpio_direction_output,
281*4882a593Smuzhiyun 	.get_value		= exynos_gpio_get_value,
282*4882a593Smuzhiyun 	.set_value		= exynos_gpio_set_value,
283*4882a593Smuzhiyun 	.get_function		= exynos_gpio_get_function,
284*4882a593Smuzhiyun };
285*4882a593Smuzhiyun 
gpio_exynos_probe(struct udevice * dev)286*4882a593Smuzhiyun static int gpio_exynos_probe(struct udevice *dev)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
289*4882a593Smuzhiyun 	struct exynos_bank_info *priv = dev->priv;
290*4882a593Smuzhiyun 	struct exynos_gpio_platdata *plat = dev->platdata;
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	/* Only child devices have ports */
293*4882a593Smuzhiyun 	if (!plat)
294*4882a593Smuzhiyun 		return 0;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	priv->bank = plat->bank;
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	uc_priv->gpio_count = GPIO_PER_BANK;
299*4882a593Smuzhiyun 	uc_priv->bank_name = plat->bank_name;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	return 0;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun /**
305*4882a593Smuzhiyun  * We have a top-level GPIO device with no actual GPIOs. It has a child
306*4882a593Smuzhiyun  * device for each Exynos GPIO bank.
307*4882a593Smuzhiyun  */
gpio_exynos_bind(struct udevice * parent)308*4882a593Smuzhiyun static int gpio_exynos_bind(struct udevice *parent)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun 	struct exynos_gpio_platdata *plat = parent->platdata;
311*4882a593Smuzhiyun 	struct s5p_gpio_bank *bank, *base;
312*4882a593Smuzhiyun 	const void *blob = gd->fdt_blob;
313*4882a593Smuzhiyun 	int node;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	/* If this is a child device, there is nothing to do here */
316*4882a593Smuzhiyun 	if (plat)
317*4882a593Smuzhiyun 		return 0;
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	base = (struct s5p_gpio_bank *)devfdt_get_addr(parent);
320*4882a593Smuzhiyun 	for (node = fdt_first_subnode(blob, dev_of_offset(parent)), bank = base;
321*4882a593Smuzhiyun 	     node > 0;
322*4882a593Smuzhiyun 	     node = fdt_next_subnode(blob, node), bank++) {
323*4882a593Smuzhiyun 		struct exynos_gpio_platdata *plat;
324*4882a593Smuzhiyun 		struct udevice *dev;
325*4882a593Smuzhiyun 		fdt_addr_t reg;
326*4882a593Smuzhiyun 		int ret;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 		if (!fdtdec_get_bool(blob, node, "gpio-controller"))
329*4882a593Smuzhiyun 			continue;
330*4882a593Smuzhiyun 		plat = calloc(1, sizeof(*plat));
331*4882a593Smuzhiyun 		if (!plat)
332*4882a593Smuzhiyun 			return -ENOMEM;
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 		plat->bank_name = fdt_get_name(blob, node, NULL);
335*4882a593Smuzhiyun 		ret = device_bind(parent, parent->driver,
336*4882a593Smuzhiyun 				  plat->bank_name, plat, -1, &dev);
337*4882a593Smuzhiyun 		if (ret)
338*4882a593Smuzhiyun 			return ret;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 		dev_set_of_offset(dev, node);
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 		reg = devfdt_get_addr(dev);
343*4882a593Smuzhiyun 		if (reg != FDT_ADDR_T_NONE)
344*4882a593Smuzhiyun 			bank = (struct s5p_gpio_bank *)((ulong)base + reg);
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 		plat->bank = bank;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 		debug("dev at %p: %s\n", bank, plat->bank_name);
349*4882a593Smuzhiyun 	}
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	return 0;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun static const struct udevice_id exynos_gpio_ids[] = {
355*4882a593Smuzhiyun 	{ .compatible = "samsung,s5pc100-pinctrl" },
356*4882a593Smuzhiyun 	{ .compatible = "samsung,s5pc110-pinctrl" },
357*4882a593Smuzhiyun 	{ .compatible = "samsung,exynos4210-pinctrl" },
358*4882a593Smuzhiyun 	{ .compatible = "samsung,exynos4x12-pinctrl" },
359*4882a593Smuzhiyun 	{ .compatible = "samsung,exynos5250-pinctrl" },
360*4882a593Smuzhiyun 	{ .compatible = "samsung,exynos5420-pinctrl" },
361*4882a593Smuzhiyun 	{ }
362*4882a593Smuzhiyun };
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun U_BOOT_DRIVER(gpio_exynos) = {
365*4882a593Smuzhiyun 	.name	= "gpio_exynos",
366*4882a593Smuzhiyun 	.id	= UCLASS_GPIO,
367*4882a593Smuzhiyun 	.of_match = exynos_gpio_ids,
368*4882a593Smuzhiyun 	.bind	= gpio_exynos_bind,
369*4882a593Smuzhiyun 	.probe = gpio_exynos_probe,
370*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct exynos_bank_info),
371*4882a593Smuzhiyun 	.ops	= &gpio_exynos_ops,
372*4882a593Smuzhiyun };
373*4882a593Smuzhiyun #endif
374