xref: /rk3399_rockchip-uboot/drivers/gpio/omap_gpio.c (revision bcd4d4eb2b37bfeccccd284b885edaaa18c9b823)
1308252adSMarek Vasut /*
2308252adSMarek Vasut  * Copyright (c) 2009 Wind River Systems, Inc.
3308252adSMarek Vasut  * Tom Rix <Tom.Rix@windriver.com>
4308252adSMarek Vasut  *
5*bcd4d4ebSWolfgang 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>
22308252adSMarek Vasut #include <asm/gpio.h>
23308252adSMarek Vasut #include <asm/io.h>
24308252adSMarek Vasut #include <asm/errno.h>
25308252adSMarek Vasut 
26308252adSMarek Vasut #define OMAP_GPIO_DIR_OUT	0
27308252adSMarek Vasut #define OMAP_GPIO_DIR_IN	1
28308252adSMarek Vasut 
29308252adSMarek Vasut static inline const struct gpio_bank *get_gpio_bank(int gpio)
30308252adSMarek Vasut {
31308252adSMarek Vasut 	return &omap_gpio_bank[gpio >> 5];
32308252adSMarek Vasut }
33308252adSMarek Vasut 
34308252adSMarek Vasut static inline int get_gpio_index(int gpio)
35308252adSMarek Vasut {
36308252adSMarek Vasut 	return gpio & 0x1f;
37308252adSMarek Vasut }
38308252adSMarek Vasut 
39dcee1ab3SNikita Kiryanov int gpio_is_valid(int gpio)
40308252adSMarek Vasut {
4187bd05d7SAxel Lin 	return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);
42308252adSMarek Vasut }
43308252adSMarek Vasut 
44308252adSMarek Vasut static int check_gpio(int gpio)
45308252adSMarek Vasut {
46dcee1ab3SNikita Kiryanov 	if (!gpio_is_valid(gpio)) {
47308252adSMarek Vasut 		printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
48308252adSMarek Vasut 		return -1;
49308252adSMarek Vasut 	}
50308252adSMarek Vasut 	return 0;
51308252adSMarek Vasut }
52308252adSMarek Vasut 
53308252adSMarek Vasut static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
54308252adSMarek Vasut 				int is_input)
55308252adSMarek Vasut {
56308252adSMarek Vasut 	void *reg = bank->base;
57308252adSMarek Vasut 	u32 l;
58308252adSMarek Vasut 
59308252adSMarek Vasut 	switch (bank->method) {
60308252adSMarek Vasut 	case METHOD_GPIO_24XX:
61308252adSMarek Vasut 		reg += OMAP_GPIO_OE;
62308252adSMarek Vasut 		break;
63308252adSMarek Vasut 	default:
64308252adSMarek Vasut 		return;
65308252adSMarek Vasut 	}
66308252adSMarek Vasut 	l = __raw_readl(reg);
67308252adSMarek Vasut 	if (is_input)
68308252adSMarek Vasut 		l |= 1 << gpio;
69308252adSMarek Vasut 	else
70308252adSMarek Vasut 		l &= ~(1 << gpio);
71308252adSMarek Vasut 	__raw_writel(l, reg);
72308252adSMarek Vasut }
73308252adSMarek Vasut 
74308252adSMarek Vasut /**
75308252adSMarek Vasut  * Get the direction of the GPIO by reading the GPIO_OE register
76308252adSMarek Vasut  * corresponding to the specified bank.
77308252adSMarek Vasut  */
78308252adSMarek Vasut static int _get_gpio_direction(const struct gpio_bank *bank, int gpio)
79308252adSMarek Vasut {
80308252adSMarek Vasut 	void *reg = bank->base;
81308252adSMarek Vasut 	u32 v;
82308252adSMarek Vasut 
83308252adSMarek Vasut 	switch (bank->method) {
84308252adSMarek Vasut 	case METHOD_GPIO_24XX:
85308252adSMarek Vasut 		reg += OMAP_GPIO_OE;
86308252adSMarek Vasut 		break;
87308252adSMarek Vasut 	default:
88308252adSMarek Vasut 		return -1;
89308252adSMarek Vasut 	}
90308252adSMarek Vasut 
91308252adSMarek Vasut 	v = __raw_readl(reg);
92308252adSMarek Vasut 
93308252adSMarek Vasut 	if (v & (1 << gpio))
94308252adSMarek Vasut 		return OMAP_GPIO_DIR_IN;
95308252adSMarek Vasut 	else
96308252adSMarek Vasut 		return OMAP_GPIO_DIR_OUT;
97308252adSMarek Vasut }
98308252adSMarek Vasut 
99308252adSMarek Vasut static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
100308252adSMarek Vasut 				int enable)
101308252adSMarek Vasut {
102308252adSMarek Vasut 	void *reg = bank->base;
103308252adSMarek Vasut 	u32 l = 0;
104308252adSMarek Vasut 
105308252adSMarek Vasut 	switch (bank->method) {
106308252adSMarek Vasut 	case METHOD_GPIO_24XX:
107308252adSMarek Vasut 		if (enable)
108308252adSMarek Vasut 			reg += OMAP_GPIO_SETDATAOUT;
109308252adSMarek Vasut 		else
110308252adSMarek Vasut 			reg += OMAP_GPIO_CLEARDATAOUT;
111308252adSMarek Vasut 		l = 1 << gpio;
112308252adSMarek Vasut 		break;
113308252adSMarek Vasut 	default:
114308252adSMarek Vasut 		printf("omap3-gpio unknown bank method %s %d\n",
115308252adSMarek Vasut 		       __FILE__, __LINE__);
116308252adSMarek Vasut 		return;
117308252adSMarek Vasut 	}
118308252adSMarek Vasut 	__raw_writel(l, reg);
119308252adSMarek Vasut }
120308252adSMarek Vasut 
121308252adSMarek Vasut /**
122308252adSMarek Vasut  * Set value of the specified gpio
123308252adSMarek Vasut  */
124308252adSMarek Vasut int gpio_set_value(unsigned gpio, int value)
125308252adSMarek Vasut {
126308252adSMarek Vasut 	const struct gpio_bank *bank;
127308252adSMarek Vasut 
128308252adSMarek Vasut 	if (check_gpio(gpio) < 0)
129308252adSMarek Vasut 		return -1;
130308252adSMarek Vasut 	bank = get_gpio_bank(gpio);
131308252adSMarek Vasut 	_set_gpio_dataout(bank, get_gpio_index(gpio), value);
132308252adSMarek Vasut 
133308252adSMarek Vasut 	return 0;
134308252adSMarek Vasut }
135308252adSMarek Vasut 
136308252adSMarek Vasut /**
137308252adSMarek Vasut  * Get value of the specified gpio
138308252adSMarek Vasut  */
139308252adSMarek Vasut int gpio_get_value(unsigned gpio)
140308252adSMarek Vasut {
141308252adSMarek Vasut 	const struct gpio_bank *bank;
142308252adSMarek Vasut 	void *reg;
143308252adSMarek Vasut 	int input;
144308252adSMarek Vasut 
145308252adSMarek Vasut 	if (check_gpio(gpio) < 0)
146308252adSMarek Vasut 		return -1;
147308252adSMarek Vasut 	bank = get_gpio_bank(gpio);
148308252adSMarek Vasut 	reg = bank->base;
149308252adSMarek Vasut 	switch (bank->method) {
150308252adSMarek Vasut 	case METHOD_GPIO_24XX:
151308252adSMarek Vasut 		input = _get_gpio_direction(bank, get_gpio_index(gpio));
152308252adSMarek Vasut 		switch (input) {
153308252adSMarek Vasut 		case OMAP_GPIO_DIR_IN:
154308252adSMarek Vasut 			reg += OMAP_GPIO_DATAIN;
155308252adSMarek Vasut 			break;
156308252adSMarek Vasut 		case OMAP_GPIO_DIR_OUT:
157308252adSMarek Vasut 			reg += OMAP_GPIO_DATAOUT;
158308252adSMarek Vasut 			break;
159308252adSMarek Vasut 		default:
160308252adSMarek Vasut 			return -1;
161308252adSMarek Vasut 		}
162308252adSMarek Vasut 		break;
163308252adSMarek Vasut 	default:
164308252adSMarek Vasut 		return -1;
165308252adSMarek Vasut 	}
166308252adSMarek Vasut 	return (__raw_readl(reg)
167308252adSMarek Vasut 			& (1 << get_gpio_index(gpio))) != 0;
168308252adSMarek Vasut }
169308252adSMarek Vasut 
170308252adSMarek Vasut /**
171308252adSMarek Vasut  * Set gpio direction as input
172308252adSMarek Vasut  */
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  */
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  */
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  */
219308252adSMarek Vasut int gpio_free(unsigned gpio)
220308252adSMarek Vasut {
221308252adSMarek Vasut 	return 0;
222308252adSMarek Vasut }
223