xref: /rk3399_rockchip-uboot/drivers/gpio/s5p_gpio.c (revision a821c4af79e4f5ce9b629b20473863397bbe9b10)
13bb6b037SMinkyu Kang /*
23bb6b037SMinkyu Kang  * (C) Copyright 2009 Samsung Electronics
33bb6b037SMinkyu Kang  * Minkyu Kang <mk7.kang@samsung.com>
43bb6b037SMinkyu Kang  *
51a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
63bb6b037SMinkyu Kang  */
73bb6b037SMinkyu Kang 
83bb6b037SMinkyu Kang #include <common.h>
9b8809e60SSimon Glass #include <dm.h>
10b8809e60SSimon Glass #include <errno.h>
11b8809e60SSimon Glass #include <fdtdec.h>
12b8809e60SSimon Glass #include <malloc.h>
133bb6b037SMinkyu Kang #include <asm/io.h>
14365d6070SJoe Hershberger #include <asm/gpio.h>
15b8809e60SSimon Glass #include <dm/device-internal.h>
16b8809e60SSimon Glass 
17b8809e60SSimon Glass DECLARE_GLOBAL_DATA_PTR;
183bb6b037SMinkyu Kang 
19f6ae1ca0SAkshay Saraswat #define S5P_GPIO_GET_PIN(x)	(x % GPIO_PER_BANK)
208475c869SPrzemyslaw Marczak 
213a233dbfSSimon Glass #define CON_MASK(val)			(0xf << ((val) << 2))
223a233dbfSSimon Glass #define CON_SFR(gpio, cfg)		((cfg) << ((gpio) << 2))
233a233dbfSSimon Glass #define CON_SFR_UNSHIFT(val, gpio)	((val) >> ((gpio) << 2))
243bb6b037SMinkyu Kang 
253a233dbfSSimon Glass #define DAT_MASK(gpio)			(0x1 << (gpio))
263a233dbfSSimon Glass #define DAT_SET(gpio)			(0x1 << (gpio))
273bb6b037SMinkyu Kang 
283a233dbfSSimon Glass #define PULL_MASK(gpio)		(0x3 << ((gpio) << 1))
293a233dbfSSimon Glass #define PULL_MODE(gpio, pull)		((pull) << ((gpio) << 1))
303bb6b037SMinkyu Kang 
313a233dbfSSimon Glass #define DRV_MASK(gpio)			(0x3 << ((gpio) << 1))
323a233dbfSSimon Glass #define DRV_SET(gpio, mode)		((mode) << ((gpio) << 1))
333a233dbfSSimon Glass #define RATE_MASK(gpio)		(0x1 << (gpio + 16))
343a233dbfSSimon Glass #define RATE_SET(gpio)			(0x1 << (gpio + 16))
353bb6b037SMinkyu Kang 
36b8809e60SSimon Glass /* Platform data for each bank */
37b8809e60SSimon Glass struct exynos_gpio_platdata {
38b8809e60SSimon Glass 	struct s5p_gpio_bank *bank;
39b8809e60SSimon Glass 	const char *bank_name;	/* Name of port, e.g. 'gpa0" */
40b8809e60SSimon Glass };
41b8809e60SSimon Glass 
42b8809e60SSimon Glass /* Information about each bank at run-time */
43b8809e60SSimon Glass struct exynos_bank_info {
44b8809e60SSimon Glass 	struct s5p_gpio_bank *bank;
45b8809e60SSimon Glass };
46b8809e60SSimon Glass 
s5p_gpio_get_bank(unsigned int gpio)47b8809e60SSimon Glass static struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned int gpio)
48f6ae1ca0SAkshay Saraswat {
49b8809e60SSimon Glass 	const struct gpio_info *data;
50b8809e60SSimon Glass 	unsigned int upto;
51b8809e60SSimon Glass 	int i, count;
52f6ae1ca0SAkshay Saraswat 
53b8809e60SSimon Glass 	data = get_gpio_data();
54b8809e60SSimon Glass 	count = get_bank_num();
55b8809e60SSimon Glass 	upto = 0;
56f6ae1ca0SAkshay Saraswat 
57b8809e60SSimon Glass 	for (i = 0; i < count; i++) {
58b8809e60SSimon Glass 		debug("i=%d, upto=%d\n", i, upto);
59b8809e60SSimon Glass 		if (gpio < data->max_gpio) {
60b8809e60SSimon Glass 			struct s5p_gpio_bank *bank;
61b8809e60SSimon Glass 			bank = (struct s5p_gpio_bank *)data->reg_addr;
62b8809e60SSimon Glass 			bank += (gpio - upto) / GPIO_PER_BANK;
63b8809e60SSimon Glass 			debug("gpio=%d, bank=%p\n", gpio, bank);
64b8809e60SSimon Glass 			return bank;
65f6ae1ca0SAkshay Saraswat 		}
66f6ae1ca0SAkshay Saraswat 
67b8809e60SSimon Glass 		upto = data->max_gpio;
68b8809e60SSimon Glass 		data++;
69f6ae1ca0SAkshay Saraswat 	}
70f6ae1ca0SAkshay Saraswat 
71b8809e60SSimon Glass 	return NULL;
72f6ae1ca0SAkshay Saraswat }
73f6ae1ca0SAkshay Saraswat 
s5p_gpio_cfg_pin(struct s5p_gpio_bank * bank,int gpio,int cfg)74f6ae1ca0SAkshay Saraswat static void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg)
753bb6b037SMinkyu Kang {
763bb6b037SMinkyu Kang 	unsigned int value;
773bb6b037SMinkyu Kang 
783bb6b037SMinkyu Kang 	value = readl(&bank->con);
793bb6b037SMinkyu Kang 	value &= ~CON_MASK(gpio);
803bb6b037SMinkyu Kang 	value |= CON_SFR(gpio, cfg);
813bb6b037SMinkyu Kang 	writel(value, &bank->con);
823bb6b037SMinkyu Kang }
833bb6b037SMinkyu Kang 
s5p_gpio_set_value(struct s5p_gpio_bank * bank,int gpio,int en)84f6ae1ca0SAkshay Saraswat static void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en)
853bb6b037SMinkyu Kang {
863bb6b037SMinkyu Kang 	unsigned int value;
873bb6b037SMinkyu Kang 
883bb6b037SMinkyu Kang 	value = readl(&bank->dat);
893bb6b037SMinkyu Kang 	value &= ~DAT_MASK(gpio);
903bb6b037SMinkyu Kang 	if (en)
913bb6b037SMinkyu Kang 		value |= DAT_SET(gpio);
923bb6b037SMinkyu Kang 	writel(value, &bank->dat);
933bb6b037SMinkyu Kang }
943bb6b037SMinkyu Kang 
95b8809e60SSimon Glass #ifdef CONFIG_SPL_BUILD
96b8809e60SSimon Glass /* Common GPIO API - SPL does not support driver model yet */
gpio_set_value(unsigned gpio,int value)97b8809e60SSimon Glass int gpio_set_value(unsigned gpio, int value)
98f6ae1ca0SAkshay Saraswat {
99b8809e60SSimon Glass 	s5p_gpio_set_value(s5p_gpio_get_bank(gpio),
100b8809e60SSimon Glass 			   s5p_gpio_get_pin(gpio), value);
101f6ae1ca0SAkshay Saraswat 
102b8809e60SSimon Glass 	return 0;
103b8809e60SSimon Glass }
104b8809e60SSimon Glass #else
s5p_gpio_get_cfg_pin(struct s5p_gpio_bank * bank,int gpio)105b8809e60SSimon Glass static int s5p_gpio_get_cfg_pin(struct s5p_gpio_bank *bank, int gpio)
106f6ae1ca0SAkshay Saraswat {
107b8809e60SSimon Glass 	unsigned int value;
108b8809e60SSimon Glass 
109b8809e60SSimon Glass 	value = readl(&bank->con);
110b8809e60SSimon Glass 	value &= CON_MASK(gpio);
111b8809e60SSimon Glass 	return CON_SFR_UNSHIFT(value, gpio);
112f6ae1ca0SAkshay Saraswat }
113f6ae1ca0SAkshay Saraswat 
s5p_gpio_get_value(struct s5p_gpio_bank * bank,int gpio)114f6ae1ca0SAkshay Saraswat static unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio)
1153bb6b037SMinkyu Kang {
1163bb6b037SMinkyu Kang 	unsigned int value;
1173bb6b037SMinkyu Kang 
1183bb6b037SMinkyu Kang 	value = readl(&bank->dat);
1193bb6b037SMinkyu Kang 	return !!(value & DAT_MASK(gpio));
1203bb6b037SMinkyu Kang }
121b8809e60SSimon Glass #endif /* CONFIG_SPL_BUILD */
1223bb6b037SMinkyu Kang 
s5p_gpio_set_pull(struct s5p_gpio_bank * bank,int gpio,int mode)123f6ae1ca0SAkshay Saraswat static void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode)
1243bb6b037SMinkyu Kang {
1253bb6b037SMinkyu Kang 	unsigned int value;
1263bb6b037SMinkyu Kang 
1273bb6b037SMinkyu Kang 	value = readl(&bank->pull);
1283bb6b037SMinkyu Kang 	value &= ~PULL_MASK(gpio);
1293bb6b037SMinkyu Kang 
1303bb6b037SMinkyu Kang 	switch (mode) {
131f6ae1ca0SAkshay Saraswat 	case S5P_GPIO_PULL_DOWN:
132f6ae1ca0SAkshay Saraswat 	case S5P_GPIO_PULL_UP:
1333bb6b037SMinkyu Kang 		value |= PULL_MODE(gpio, mode);
1343bb6b037SMinkyu Kang 		break;
1353bb6b037SMinkyu Kang 	default:
136ffb4b025SMinkyu Kang 		break;
1373bb6b037SMinkyu Kang 	}
1383bb6b037SMinkyu Kang 
1393bb6b037SMinkyu Kang 	writel(value, &bank->pull);
1403bb6b037SMinkyu Kang }
1413bb6b037SMinkyu Kang 
s5p_gpio_set_drv(struct s5p_gpio_bank * bank,int gpio,int mode)142f6ae1ca0SAkshay Saraswat static void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode)
1433bb6b037SMinkyu Kang {
1443bb6b037SMinkyu Kang 	unsigned int value;
1453bb6b037SMinkyu Kang 
1463bb6b037SMinkyu Kang 	value = readl(&bank->drv);
1473bb6b037SMinkyu Kang 	value &= ~DRV_MASK(gpio);
1483bb6b037SMinkyu Kang 
1493bb6b037SMinkyu Kang 	switch (mode) {
150f6ae1ca0SAkshay Saraswat 	case S5P_GPIO_DRV_1X:
151f6ae1ca0SAkshay Saraswat 	case S5P_GPIO_DRV_2X:
152f6ae1ca0SAkshay Saraswat 	case S5P_GPIO_DRV_3X:
153f6ae1ca0SAkshay Saraswat 	case S5P_GPIO_DRV_4X:
1543bb6b037SMinkyu Kang 		value |= DRV_SET(gpio, mode);
1553bb6b037SMinkyu Kang 		break;
1563bb6b037SMinkyu Kang 	default:
1573bb6b037SMinkyu Kang 		return;
1583bb6b037SMinkyu Kang 	}
1593bb6b037SMinkyu Kang 
1603bb6b037SMinkyu Kang 	writel(value, &bank->drv);
1613bb6b037SMinkyu Kang }
1623bb6b037SMinkyu Kang 
s5p_gpio_set_rate(struct s5p_gpio_bank * bank,int gpio,int mode)163f6ae1ca0SAkshay Saraswat static void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode)
1643bb6b037SMinkyu Kang {
1653bb6b037SMinkyu Kang 	unsigned int value;
1663bb6b037SMinkyu Kang 
1673bb6b037SMinkyu Kang 	value = readl(&bank->drv);
1683bb6b037SMinkyu Kang 	value &= ~RATE_MASK(gpio);
1693bb6b037SMinkyu Kang 
1703bb6b037SMinkyu Kang 	switch (mode) {
171f6ae1ca0SAkshay Saraswat 	case S5P_GPIO_DRV_FAST:
172f6ae1ca0SAkshay Saraswat 	case S5P_GPIO_DRV_SLOW:
1733bb6b037SMinkyu Kang 		value |= RATE_SET(gpio);
1743bb6b037SMinkyu Kang 		break;
1753bb6b037SMinkyu Kang 	default:
1763bb6b037SMinkyu Kang 		return;
1773bb6b037SMinkyu Kang 	}
1783bb6b037SMinkyu Kang 
1793bb6b037SMinkyu Kang 	writel(value, &bank->drv);
1803bb6b037SMinkyu Kang }
1819f15bc0cSŁukasz Majewski 
s5p_gpio_get_pin(unsigned gpio)182365d6070SJoe Hershberger int s5p_gpio_get_pin(unsigned gpio)
1839f15bc0cSŁukasz Majewski {
1848475c869SPrzemyslaw Marczak 	return S5P_GPIO_GET_PIN(gpio);
1859f15bc0cSŁukasz Majewski }
1869f15bc0cSŁukasz Majewski 
187b8809e60SSimon Glass /* Driver model interface */
188b8809e60SSimon Glass #ifndef CONFIG_SPL_BUILD
189b8809e60SSimon Glass /* set GPIO pin 'gpio' as an input */
exynos_gpio_direction_input(struct udevice * dev,unsigned offset)190b8809e60SSimon Glass static int exynos_gpio_direction_input(struct udevice *dev, unsigned offset)
191b8809e60SSimon Glass {
192b8809e60SSimon Glass 	struct exynos_bank_info *state = dev_get_priv(dev);
193b8809e60SSimon Glass 
194b8809e60SSimon Glass 	/* Configure GPIO direction as input. */
195b8809e60SSimon Glass 	s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_INPUT);
196b8809e60SSimon Glass 
197b8809e60SSimon Glass 	return 0;
198b8809e60SSimon Glass }
199b8809e60SSimon Glass 
200b8809e60SSimon Glass /* set GPIO pin 'gpio' as an output, with polarity 'value' */
exynos_gpio_direction_output(struct udevice * dev,unsigned offset,int value)201b8809e60SSimon Glass static int exynos_gpio_direction_output(struct udevice *dev, unsigned offset,
202b8809e60SSimon Glass 				       int value)
203b8809e60SSimon Glass {
204b8809e60SSimon Glass 	struct exynos_bank_info *state = dev_get_priv(dev);
205b8809e60SSimon Glass 
206b8809e60SSimon Glass 	/* Configure GPIO output value. */
207b8809e60SSimon Glass 	s5p_gpio_set_value(state->bank, offset, value);
208b8809e60SSimon Glass 
209b8809e60SSimon Glass 	/* Configure GPIO direction as output. */
210b8809e60SSimon Glass 	s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_OUTPUT);
211b8809e60SSimon Glass 
212b8809e60SSimon Glass 	return 0;
213b8809e60SSimon Glass }
214b8809e60SSimon Glass 
215b8809e60SSimon Glass /* read GPIO IN value of pin 'gpio' */
exynos_gpio_get_value(struct udevice * dev,unsigned offset)216b8809e60SSimon Glass static int exynos_gpio_get_value(struct udevice *dev, unsigned offset)
217b8809e60SSimon Glass {
218b8809e60SSimon Glass 	struct exynos_bank_info *state = dev_get_priv(dev);
219b8809e60SSimon Glass 
220b8809e60SSimon Glass 	return s5p_gpio_get_value(state->bank, offset);
221b8809e60SSimon Glass }
222b8809e60SSimon Glass 
223b8809e60SSimon Glass /* write GPIO OUT value to pin 'gpio' */
exynos_gpio_set_value(struct udevice * dev,unsigned offset,int value)224b8809e60SSimon Glass static int exynos_gpio_set_value(struct udevice *dev, unsigned offset,
225b8809e60SSimon Glass 				 int value)
226b8809e60SSimon Glass {
227b8809e60SSimon Glass 	struct exynos_bank_info *state = dev_get_priv(dev);
228b8809e60SSimon Glass 
229b8809e60SSimon Glass 	s5p_gpio_set_value(state->bank, offset, value);
230b8809e60SSimon Glass 
231b8809e60SSimon Glass 	return 0;
232b8809e60SSimon Glass }
233b8809e60SSimon Glass #endif /* nCONFIG_SPL_BUILD */
234b8809e60SSimon Glass 
235b8809e60SSimon Glass /*
236b8809e60SSimon Glass  * There is no common GPIO API for pull, drv, pin, rate (yet). These
237b8809e60SSimon Glass  * functions are kept here to preserve function ordering for review.
238b8809e60SSimon Glass  */
gpio_set_pull(int gpio,int mode)239f6ae1ca0SAkshay Saraswat void gpio_set_pull(int gpio, int mode)
240f6ae1ca0SAkshay Saraswat {
241f6ae1ca0SAkshay Saraswat 	s5p_gpio_set_pull(s5p_gpio_get_bank(gpio),
242f6ae1ca0SAkshay Saraswat 			  s5p_gpio_get_pin(gpio), mode);
243f6ae1ca0SAkshay Saraswat }
244f6ae1ca0SAkshay Saraswat 
gpio_set_drv(int gpio,int mode)245f6ae1ca0SAkshay Saraswat void gpio_set_drv(int gpio, int mode)
246f6ae1ca0SAkshay Saraswat {
247f6ae1ca0SAkshay Saraswat 	s5p_gpio_set_drv(s5p_gpio_get_bank(gpio),
248f6ae1ca0SAkshay Saraswat 			 s5p_gpio_get_pin(gpio), mode);
249f6ae1ca0SAkshay Saraswat }
250f6ae1ca0SAkshay Saraswat 
gpio_cfg_pin(int gpio,int cfg)251f6ae1ca0SAkshay Saraswat void gpio_cfg_pin(int gpio, int cfg)
252f6ae1ca0SAkshay Saraswat {
253f6ae1ca0SAkshay Saraswat 	s5p_gpio_cfg_pin(s5p_gpio_get_bank(gpio),
254f6ae1ca0SAkshay Saraswat 			 s5p_gpio_get_pin(gpio), cfg);
255f6ae1ca0SAkshay Saraswat }
256f6ae1ca0SAkshay Saraswat 
gpio_set_rate(int gpio,int mode)257f6ae1ca0SAkshay Saraswat void gpio_set_rate(int gpio, int mode)
258f6ae1ca0SAkshay Saraswat {
259f6ae1ca0SAkshay Saraswat 	s5p_gpio_set_rate(s5p_gpio_get_bank(gpio),
260f6ae1ca0SAkshay Saraswat 			  s5p_gpio_get_pin(gpio), mode);
261f6ae1ca0SAkshay Saraswat }
262b8809e60SSimon Glass 
263b8809e60SSimon Glass #ifndef CONFIG_SPL_BUILD
exynos_gpio_get_function(struct udevice * dev,unsigned offset)264b8809e60SSimon Glass static int exynos_gpio_get_function(struct udevice *dev, unsigned offset)
265b8809e60SSimon Glass {
266b8809e60SSimon Glass 	struct exynos_bank_info *state = dev_get_priv(dev);
267b8809e60SSimon Glass 	int cfg;
268b8809e60SSimon Glass 
269b8809e60SSimon Glass 	cfg = s5p_gpio_get_cfg_pin(state->bank, offset);
270b8809e60SSimon Glass 	if (cfg == S5P_GPIO_OUTPUT)
271b8809e60SSimon Glass 		return GPIOF_OUTPUT;
272b8809e60SSimon Glass 	else if (cfg == S5P_GPIO_INPUT)
273b8809e60SSimon Glass 		return GPIOF_INPUT;
274b8809e60SSimon Glass 	else
275b8809e60SSimon Glass 		return GPIOF_FUNC;
276b8809e60SSimon Glass }
277b8809e60SSimon Glass 
278b8809e60SSimon Glass static const struct dm_gpio_ops gpio_exynos_ops = {
279b8809e60SSimon Glass 	.direction_input	= exynos_gpio_direction_input,
280b8809e60SSimon Glass 	.direction_output	= exynos_gpio_direction_output,
281b8809e60SSimon Glass 	.get_value		= exynos_gpio_get_value,
282b8809e60SSimon Glass 	.set_value		= exynos_gpio_set_value,
283b8809e60SSimon Glass 	.get_function		= exynos_gpio_get_function,
284b8809e60SSimon Glass };
285b8809e60SSimon Glass 
gpio_exynos_probe(struct udevice * dev)286b8809e60SSimon Glass static int gpio_exynos_probe(struct udevice *dev)
287b8809e60SSimon Glass {
288e564f054SSimon Glass 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
289b8809e60SSimon Glass 	struct exynos_bank_info *priv = dev->priv;
290b8809e60SSimon Glass 	struct exynos_gpio_platdata *plat = dev->platdata;
291b8809e60SSimon Glass 
292b8809e60SSimon Glass 	/* Only child devices have ports */
293b8809e60SSimon Glass 	if (!plat)
294b8809e60SSimon Glass 		return 0;
295b8809e60SSimon Glass 
296b8809e60SSimon Glass 	priv->bank = plat->bank;
297b8809e60SSimon Glass 
298b8809e60SSimon Glass 	uc_priv->gpio_count = GPIO_PER_BANK;
299b8809e60SSimon Glass 	uc_priv->bank_name = plat->bank_name;
300b8809e60SSimon Glass 
301b8809e60SSimon Glass 	return 0;
302b8809e60SSimon Glass }
303b8809e60SSimon Glass 
304b8809e60SSimon Glass /**
305b8809e60SSimon Glass  * We have a top-level GPIO device with no actual GPIOs. It has a child
306b8809e60SSimon Glass  * device for each Exynos GPIO bank.
307b8809e60SSimon Glass  */
gpio_exynos_bind(struct udevice * parent)308b8809e60SSimon Glass static int gpio_exynos_bind(struct udevice *parent)
309b8809e60SSimon Glass {
310b8809e60SSimon Glass 	struct exynos_gpio_platdata *plat = parent->platdata;
311b8809e60SSimon Glass 	struct s5p_gpio_bank *bank, *base;
312b8809e60SSimon Glass 	const void *blob = gd->fdt_blob;
313b8809e60SSimon Glass 	int node;
314b8809e60SSimon Glass 
315b8809e60SSimon Glass 	/* If this is a child device, there is nothing to do here */
316b8809e60SSimon Glass 	if (plat)
317b8809e60SSimon Glass 		return 0;
318b8809e60SSimon Glass 
319*a821c4afSSimon Glass 	base = (struct s5p_gpio_bank *)devfdt_get_addr(parent);
320e160f7d4SSimon Glass 	for (node = fdt_first_subnode(blob, dev_of_offset(parent)), bank = base;
321b8809e60SSimon Glass 	     node > 0;
322b8809e60SSimon Glass 	     node = fdt_next_subnode(blob, node), bank++) {
323b8809e60SSimon Glass 		struct exynos_gpio_platdata *plat;
324b8809e60SSimon Glass 		struct udevice *dev;
325b8809e60SSimon Glass 		fdt_addr_t reg;
326b8809e60SSimon Glass 		int ret;
327b8809e60SSimon Glass 
328b8809e60SSimon Glass 		if (!fdtdec_get_bool(blob, node, "gpio-controller"))
329b8809e60SSimon Glass 			continue;
330b8809e60SSimon Glass 		plat = calloc(1, sizeof(*plat));
331b8809e60SSimon Glass 		if (!plat)
332b8809e60SSimon Glass 			return -ENOMEM;
333b8809e60SSimon Glass 
3346f183e86SPrzemyslaw Marczak 		plat->bank_name = fdt_get_name(blob, node, NULL);
335b8809e60SSimon Glass 		ret = device_bind(parent, parent->driver,
336b8809e60SSimon Glass 				  plat->bank_name, plat, -1, &dev);
337b8809e60SSimon Glass 		if (ret)
338b8809e60SSimon Glass 			return ret;
3396f183e86SPrzemyslaw Marczak 
340e160f7d4SSimon Glass 		dev_set_of_offset(dev, node);
3416f183e86SPrzemyslaw Marczak 
342*a821c4afSSimon Glass 		reg = devfdt_get_addr(dev);
3436f183e86SPrzemyslaw Marczak 		if (reg != FDT_ADDR_T_NONE)
3446f183e86SPrzemyslaw Marczak 			bank = (struct s5p_gpio_bank *)((ulong)base + reg);
3456f183e86SPrzemyslaw Marczak 
3466f183e86SPrzemyslaw Marczak 		plat->bank = bank;
3476f183e86SPrzemyslaw Marczak 
3486f183e86SPrzemyslaw Marczak 		debug("dev at %p: %s\n", bank, plat->bank_name);
349b8809e60SSimon Glass 	}
350b8809e60SSimon Glass 
351b8809e60SSimon Glass 	return 0;
352b8809e60SSimon Glass }
353b8809e60SSimon Glass 
354b8809e60SSimon Glass static const struct udevice_id exynos_gpio_ids[] = {
355b8809e60SSimon Glass 	{ .compatible = "samsung,s5pc100-pinctrl" },
356b8809e60SSimon Glass 	{ .compatible = "samsung,s5pc110-pinctrl" },
357b8809e60SSimon Glass 	{ .compatible = "samsung,exynos4210-pinctrl" },
358b8809e60SSimon Glass 	{ .compatible = "samsung,exynos4x12-pinctrl" },
359b8809e60SSimon Glass 	{ .compatible = "samsung,exynos5250-pinctrl" },
360b8809e60SSimon Glass 	{ .compatible = "samsung,exynos5420-pinctrl" },
361b8809e60SSimon Glass 	{ }
362b8809e60SSimon Glass };
363b8809e60SSimon Glass 
364b8809e60SSimon Glass U_BOOT_DRIVER(gpio_exynos) = {
365b8809e60SSimon Glass 	.name	= "gpio_exynos",
366b8809e60SSimon Glass 	.id	= UCLASS_GPIO,
367b8809e60SSimon Glass 	.of_match = exynos_gpio_ids,
368b8809e60SSimon Glass 	.bind	= gpio_exynos_bind,
369b8809e60SSimon Glass 	.probe = gpio_exynos_probe,
370b8809e60SSimon Glass 	.priv_auto_alloc_size = sizeof(struct exynos_bank_info),
371b8809e60SSimon Glass 	.ops	= &gpio_exynos_ops,
372b8809e60SSimon Glass };
373b8809e60SSimon Glass #endif
374