1308252adSMarek Vasut /*
2308252adSMarek Vasut * Copyright (c) 2009 Wind River Systems, Inc.
3308252adSMarek Vasut * Tom Rix <Tom.Rix@windriver.com>
4308252adSMarek Vasut *
5bcd4d4ebSWolfgang Denk * SPDX-License-Identifier: GPL-2.0
6308252adSMarek Vasut *
7308252adSMarek Vasut * This work is derived from the linux 2.6.27 kernel source
8308252adSMarek Vasut * To fetch, use the kernel repository
9308252adSMarek Vasut * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
10308252adSMarek Vasut * Use the v2.6.27 tag.
11308252adSMarek Vasut *
12308252adSMarek Vasut * Below is the original's header including its copyright
13308252adSMarek Vasut *
14308252adSMarek Vasut * linux/arch/arm/plat-omap/gpio.c
15308252adSMarek Vasut *
16308252adSMarek Vasut * Support functions for OMAP GPIO
17308252adSMarek Vasut *
18308252adSMarek Vasut * Copyright (C) 2003-2005 Nokia Corporation
19308252adSMarek Vasut * Written by Juha Yrjölä <juha.yrjola@nokia.com>
20308252adSMarek Vasut */
21308252adSMarek Vasut #include <common.h>
225915a2adSSimon Glass #include <dm.h>
230a9e3405STom Rini #include <fdtdec.h>
24308252adSMarek Vasut #include <asm/gpio.h>
25308252adSMarek Vasut #include <asm/io.h>
261221ce45SMasahiro Yamada #include <linux/errno.h>
270a9e3405STom Rini #include <malloc.h>
280a9e3405STom Rini
290a9e3405STom Rini DECLARE_GLOBAL_DATA_PTR;
30308252adSMarek Vasut
31308252adSMarek Vasut #define OMAP_GPIO_DIR_OUT 0
32308252adSMarek Vasut #define OMAP_GPIO_DIR_IN 1
33308252adSMarek Vasut
345915a2adSSimon Glass #ifdef CONFIG_DM_GPIO
355915a2adSSimon Glass
365915a2adSSimon Glass #define GPIO_PER_BANK 32
375915a2adSSimon Glass
385915a2adSSimon Glass struct gpio_bank {
395915a2adSSimon Glass /* TODO(sjg@chromium.org): Can we use a struct here? */
405915a2adSSimon Glass void *base; /* address of registers in physical memory */
415915a2adSSimon Glass };
425915a2adSSimon Glass
435915a2adSSimon Glass #endif
445915a2adSSimon Glass
get_gpio_index(int gpio)45308252adSMarek Vasut static inline int get_gpio_index(int gpio)
46308252adSMarek Vasut {
47308252adSMarek Vasut return gpio & 0x1f;
48308252adSMarek Vasut }
49308252adSMarek Vasut
gpio_is_valid(int gpio)50dcee1ab3SNikita Kiryanov int gpio_is_valid(int gpio)
51308252adSMarek Vasut {
5287bd05d7SAxel Lin return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);
53308252adSMarek Vasut }
54308252adSMarek Vasut
_set_gpio_direction(const struct gpio_bank * bank,int gpio,int is_input)55308252adSMarek Vasut static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
56308252adSMarek Vasut int is_input)
57308252adSMarek Vasut {
58308252adSMarek Vasut void *reg = bank->base;
59308252adSMarek Vasut u32 l;
60308252adSMarek Vasut
61308252adSMarek Vasut reg += OMAP_GPIO_OE;
620a9e3405STom Rini
63308252adSMarek Vasut l = __raw_readl(reg);
64308252adSMarek Vasut if (is_input)
65308252adSMarek Vasut l |= 1 << gpio;
66308252adSMarek Vasut else
67308252adSMarek Vasut l &= ~(1 << gpio);
68308252adSMarek Vasut __raw_writel(l, reg);
69308252adSMarek Vasut }
70308252adSMarek Vasut
71308252adSMarek Vasut /**
72308252adSMarek Vasut * Get the direction of the GPIO by reading the GPIO_OE register
73308252adSMarek Vasut * corresponding to the specified bank.
74308252adSMarek Vasut */
_get_gpio_direction(const struct gpio_bank * bank,int gpio)75308252adSMarek Vasut static int _get_gpio_direction(const struct gpio_bank *bank, int gpio)
76308252adSMarek Vasut {
77308252adSMarek Vasut void *reg = bank->base;
78308252adSMarek Vasut u32 v;
79308252adSMarek Vasut
80308252adSMarek Vasut reg += OMAP_GPIO_OE;
81308252adSMarek Vasut
82308252adSMarek Vasut v = __raw_readl(reg);
83308252adSMarek Vasut
84308252adSMarek Vasut if (v & (1 << gpio))
85308252adSMarek Vasut return OMAP_GPIO_DIR_IN;
86308252adSMarek Vasut else
87308252adSMarek Vasut return OMAP_GPIO_DIR_OUT;
88308252adSMarek Vasut }
89308252adSMarek Vasut
_set_gpio_dataout(const struct gpio_bank * bank,int gpio,int enable)90308252adSMarek Vasut static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
91308252adSMarek Vasut int enable)
92308252adSMarek Vasut {
93308252adSMarek Vasut void *reg = bank->base;
94308252adSMarek Vasut u32 l = 0;
95308252adSMarek Vasut
96308252adSMarek Vasut if (enable)
97308252adSMarek Vasut reg += OMAP_GPIO_SETDATAOUT;
98308252adSMarek Vasut else
99308252adSMarek Vasut reg += OMAP_GPIO_CLEARDATAOUT;
1000a9e3405STom Rini
101308252adSMarek Vasut l = 1 << gpio;
102308252adSMarek Vasut __raw_writel(l, reg);
103308252adSMarek Vasut }
104308252adSMarek Vasut
_get_gpio_value(const struct gpio_bank * bank,int gpio)105d57b6114SSimon Glass static int _get_gpio_value(const struct gpio_bank *bank, int gpio)
106d57b6114SSimon Glass {
107d57b6114SSimon Glass void *reg = bank->base;
108d57b6114SSimon Glass int input;
109d57b6114SSimon Glass
110d57b6114SSimon Glass input = _get_gpio_direction(bank, gpio);
111d57b6114SSimon Glass switch (input) {
112d57b6114SSimon Glass case OMAP_GPIO_DIR_IN:
113d57b6114SSimon Glass reg += OMAP_GPIO_DATAIN;
114d57b6114SSimon Glass break;
115d57b6114SSimon Glass case OMAP_GPIO_DIR_OUT:
116d57b6114SSimon Glass reg += OMAP_GPIO_DATAOUT;
117d57b6114SSimon Glass break;
118d57b6114SSimon Glass default:
119d57b6114SSimon Glass return -1;
120d57b6114SSimon Glass }
121d57b6114SSimon Glass
122d57b6114SSimon Glass return (__raw_readl(reg) & (1 << gpio)) != 0;
123d57b6114SSimon Glass }
124d57b6114SSimon Glass
1255915a2adSSimon Glass #ifndef CONFIG_DM_GPIO
1265915a2adSSimon Glass
get_gpio_bank(int gpio)127d57b6114SSimon Glass static inline const struct gpio_bank *get_gpio_bank(int gpio)
128d57b6114SSimon Glass {
129d57b6114SSimon Glass return &omap_gpio_bank[gpio >> 5];
130d57b6114SSimon Glass }
131d57b6114SSimon Glass
check_gpio(int gpio)132d57b6114SSimon Glass static int check_gpio(int gpio)
133d57b6114SSimon Glass {
134d57b6114SSimon Glass if (!gpio_is_valid(gpio)) {
135d57b6114SSimon Glass printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
136d57b6114SSimon Glass return -1;
137d57b6114SSimon Glass }
138d57b6114SSimon Glass return 0;
139d57b6114SSimon Glass }
140d57b6114SSimon Glass
141308252adSMarek Vasut /**
142308252adSMarek Vasut * Set value of the specified gpio
143308252adSMarek Vasut */
gpio_set_value(unsigned gpio,int value)144308252adSMarek Vasut int gpio_set_value(unsigned gpio, int value)
145308252adSMarek Vasut {
146308252adSMarek Vasut const struct gpio_bank *bank;
147308252adSMarek Vasut
148308252adSMarek Vasut if (check_gpio(gpio) < 0)
149308252adSMarek Vasut return -1;
150308252adSMarek Vasut bank = get_gpio_bank(gpio);
151308252adSMarek Vasut _set_gpio_dataout(bank, get_gpio_index(gpio), value);
152308252adSMarek Vasut
153308252adSMarek Vasut return 0;
154308252adSMarek Vasut }
155308252adSMarek Vasut
156308252adSMarek Vasut /**
157308252adSMarek Vasut * Get value of the specified gpio
158308252adSMarek Vasut */
gpio_get_value(unsigned gpio)159308252adSMarek Vasut int gpio_get_value(unsigned gpio)
160308252adSMarek Vasut {
161308252adSMarek Vasut const struct gpio_bank *bank;
162308252adSMarek Vasut
163308252adSMarek Vasut if (check_gpio(gpio) < 0)
164308252adSMarek Vasut return -1;
165308252adSMarek Vasut bank = get_gpio_bank(gpio);
166d57b6114SSimon Glass
167d57b6114SSimon Glass return _get_gpio_value(bank, get_gpio_index(gpio));
168308252adSMarek Vasut }
169308252adSMarek Vasut
170308252adSMarek Vasut /**
171308252adSMarek Vasut * Set gpio direction as input
172308252adSMarek Vasut */
gpio_direction_input(unsigned gpio)173308252adSMarek Vasut int gpio_direction_input(unsigned gpio)
174308252adSMarek Vasut {
175308252adSMarek Vasut const struct gpio_bank *bank;
176308252adSMarek Vasut
177308252adSMarek Vasut if (check_gpio(gpio) < 0)
178308252adSMarek Vasut return -1;
179308252adSMarek Vasut
180308252adSMarek Vasut bank = get_gpio_bank(gpio);
181308252adSMarek Vasut _set_gpio_direction(bank, get_gpio_index(gpio), 1);
182308252adSMarek Vasut
183308252adSMarek Vasut return 0;
184308252adSMarek Vasut }
185308252adSMarek Vasut
186308252adSMarek Vasut /**
187308252adSMarek Vasut * Set gpio direction as output
188308252adSMarek Vasut */
gpio_direction_output(unsigned gpio,int value)189308252adSMarek Vasut int gpio_direction_output(unsigned gpio, int value)
190308252adSMarek Vasut {
191308252adSMarek Vasut const struct gpio_bank *bank;
192308252adSMarek Vasut
193308252adSMarek Vasut if (check_gpio(gpio) < 0)
194308252adSMarek Vasut return -1;
195308252adSMarek Vasut
196308252adSMarek Vasut bank = get_gpio_bank(gpio);
197308252adSMarek Vasut _set_gpio_dataout(bank, get_gpio_index(gpio), value);
198308252adSMarek Vasut _set_gpio_direction(bank, get_gpio_index(gpio), 0);
199308252adSMarek Vasut
200308252adSMarek Vasut return 0;
201308252adSMarek Vasut }
202308252adSMarek Vasut
203308252adSMarek Vasut /**
204308252adSMarek Vasut * Request a gpio before using it.
205308252adSMarek Vasut *
206308252adSMarek Vasut * NOTE: Argument 'label' is unused.
207308252adSMarek Vasut */
gpio_request(unsigned gpio,const char * label)208308252adSMarek Vasut int gpio_request(unsigned gpio, const char *label)
209308252adSMarek Vasut {
210308252adSMarek Vasut if (check_gpio(gpio) < 0)
211308252adSMarek Vasut return -1;
212308252adSMarek Vasut
213308252adSMarek Vasut return 0;
214308252adSMarek Vasut }
215308252adSMarek Vasut
216308252adSMarek Vasut /**
217308252adSMarek Vasut * Reset and free the gpio after using it.
218308252adSMarek Vasut */
gpio_free(unsigned gpio)219308252adSMarek Vasut int gpio_free(unsigned gpio)
220308252adSMarek Vasut {
221308252adSMarek Vasut return 0;
222308252adSMarek Vasut }
2235915a2adSSimon Glass
2245915a2adSSimon Glass #else /* new driver model interface CONFIG_DM_GPIO */
2255915a2adSSimon Glass
2265915a2adSSimon Glass /* set GPIO pin 'gpio' as an input */
omap_gpio_direction_input(struct udevice * dev,unsigned offset)2275915a2adSSimon Glass static int omap_gpio_direction_input(struct udevice *dev, unsigned offset)
2285915a2adSSimon Glass {
2295915a2adSSimon Glass struct gpio_bank *bank = dev_get_priv(dev);
2305915a2adSSimon Glass
2315915a2adSSimon Glass /* Configure GPIO direction as input. */
2325915a2adSSimon Glass _set_gpio_direction(bank, offset, 1);
2335915a2adSSimon Glass
2345915a2adSSimon Glass return 0;
2355915a2adSSimon Glass }
2365915a2adSSimon Glass
2375915a2adSSimon Glass /* set GPIO pin 'gpio' as an output, with polarity 'value' */
omap_gpio_direction_output(struct udevice * dev,unsigned offset,int value)2385915a2adSSimon Glass static int omap_gpio_direction_output(struct udevice *dev, unsigned offset,
2395915a2adSSimon Glass int value)
2405915a2adSSimon Glass {
2415915a2adSSimon Glass struct gpio_bank *bank = dev_get_priv(dev);
2425915a2adSSimon Glass
2435915a2adSSimon Glass _set_gpio_dataout(bank, offset, value);
2445915a2adSSimon Glass _set_gpio_direction(bank, offset, 0);
2455915a2adSSimon Glass
2465915a2adSSimon Glass return 0;
2475915a2adSSimon Glass }
2485915a2adSSimon Glass
2495915a2adSSimon Glass /* read GPIO IN value of pin 'gpio' */
omap_gpio_get_value(struct udevice * dev,unsigned offset)2505915a2adSSimon Glass static int omap_gpio_get_value(struct udevice *dev, unsigned offset)
2515915a2adSSimon Glass {
2525915a2adSSimon Glass struct gpio_bank *bank = dev_get_priv(dev);
2535915a2adSSimon Glass
2545915a2adSSimon Glass return _get_gpio_value(bank, offset);
2555915a2adSSimon Glass }
2565915a2adSSimon Glass
2575915a2adSSimon Glass /* write GPIO OUT value to pin 'gpio' */
omap_gpio_set_value(struct udevice * dev,unsigned offset,int value)2585915a2adSSimon Glass static int omap_gpio_set_value(struct udevice *dev, unsigned offset,
2595915a2adSSimon Glass int value)
2605915a2adSSimon Glass {
2615915a2adSSimon Glass struct gpio_bank *bank = dev_get_priv(dev);
2625915a2adSSimon Glass
2635915a2adSSimon Glass _set_gpio_dataout(bank, offset, value);
2645915a2adSSimon Glass
2655915a2adSSimon Glass return 0;
2665915a2adSSimon Glass }
2675915a2adSSimon Glass
omap_gpio_get_function(struct udevice * dev,unsigned offset)2685915a2adSSimon Glass static int omap_gpio_get_function(struct udevice *dev, unsigned offset)
2695915a2adSSimon Glass {
2705915a2adSSimon Glass struct gpio_bank *bank = dev_get_priv(dev);
2715915a2adSSimon Glass
2725915a2adSSimon Glass /* GPIOF_FUNC is not implemented yet */
27326c0472cSAxel Lin if (_get_gpio_direction(bank, offset) == OMAP_GPIO_DIR_OUT)
2745915a2adSSimon Glass return GPIOF_OUTPUT;
2755915a2adSSimon Glass else
2765915a2adSSimon Glass return GPIOF_INPUT;
2775915a2adSSimon Glass }
2785915a2adSSimon Glass
2795915a2adSSimon Glass static const struct dm_gpio_ops gpio_omap_ops = {
2805915a2adSSimon Glass .direction_input = omap_gpio_direction_input,
2815915a2adSSimon Glass .direction_output = omap_gpio_direction_output,
2825915a2adSSimon Glass .get_value = omap_gpio_get_value,
2835915a2adSSimon Glass .set_value = omap_gpio_set_value,
2845915a2adSSimon Glass .get_function = omap_gpio_get_function,
2855915a2adSSimon Glass };
2865915a2adSSimon Glass
omap_gpio_probe(struct udevice * dev)2875915a2adSSimon Glass static int omap_gpio_probe(struct udevice *dev)
2885915a2adSSimon Glass {
2895915a2adSSimon Glass struct gpio_bank *bank = dev_get_priv(dev);
2905915a2adSSimon Glass struct omap_gpio_platdata *plat = dev_get_platdata(dev);
291e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
2925915a2adSSimon Glass
2930a9e3405STom Rini uc_priv->bank_name = plat->port_name;
2945915a2adSSimon Glass uc_priv->gpio_count = GPIO_PER_BANK;
2955915a2adSSimon Glass bank->base = (void *)plat->base;
2965915a2adSSimon Glass
2975915a2adSSimon Glass return 0;
2985915a2adSSimon Glass }
2995915a2adSSimon Glass
omap_gpio_bind(struct udevice * dev)3000a9e3405STom Rini static int omap_gpio_bind(struct udevice *dev)
3010a9e3405STom Rini {
3020a9e3405STom Rini struct omap_gpio_platdata *plat = dev->platdata;
3030a9e3405STom Rini fdt_addr_t base_addr;
3040a9e3405STom Rini
3050a9e3405STom Rini if (plat)
3060a9e3405STom Rini return 0;
3070a9e3405STom Rini
308a821c4afSSimon Glass base_addr = devfdt_get_addr(dev);
3090a9e3405STom Rini if (base_addr == FDT_ADDR_T_NONE)
310*90d0ce44SSimon Glass return -EINVAL;
3110a9e3405STom Rini
3120a9e3405STom Rini /*
3130a9e3405STom Rini * TODO:
3140a9e3405STom Rini * When every board is converted to driver model and DT is
3150a9e3405STom Rini * supported, this can be done by auto-alloc feature, but
3160a9e3405STom Rini * not using calloc to alloc memory for platdata.
3170a9e3405STom Rini */
3180a9e3405STom Rini plat = calloc(1, sizeof(*plat));
3190a9e3405STom Rini if (!plat)
3200a9e3405STom Rini return -ENOMEM;
3210a9e3405STom Rini
3220a9e3405STom Rini plat->base = base_addr;
323e160f7d4SSimon Glass plat->port_name = fdt_get_name(gd->fdt_blob, dev_of_offset(dev), NULL);
3240a9e3405STom Rini dev->platdata = plat;
3250a9e3405STom Rini
3260a9e3405STom Rini return 0;
3270a9e3405STom Rini }
3280a9e3405STom Rini
3290a9e3405STom Rini static const struct udevice_id omap_gpio_ids[] = {
3300a9e3405STom Rini { .compatible = "ti,omap3-gpio" },
3310a9e3405STom Rini { .compatible = "ti,omap4-gpio" },
3320a9e3405STom Rini { .compatible = "ti,am4372-gpio" },
3330a9e3405STom Rini { }
3340a9e3405STom Rini };
3350a9e3405STom Rini
3365915a2adSSimon Glass U_BOOT_DRIVER(gpio_omap) = {
3375915a2adSSimon Glass .name = "gpio_omap",
3385915a2adSSimon Glass .id = UCLASS_GPIO,
3395915a2adSSimon Glass .ops = &gpio_omap_ops,
3400a9e3405STom Rini .of_match = omap_gpio_ids,
3410a9e3405STom Rini .bind = omap_gpio_bind,
3425915a2adSSimon Glass .probe = omap_gpio_probe,
3435915a2adSSimon Glass .priv_auto_alloc_size = sizeof(struct gpio_bank),
3445915a2adSSimon Glass };
3455915a2adSSimon Glass
3465915a2adSSimon Glass #endif /* CONFIG_DM_GPIO */
347