]>
Commit | Line | Data |
---|---|---|
0c872ecd TR |
1 | /* |
2 | * Copyright (c) 2009 Wind River Systems, Inc. | |
3 | * Tom Rix <Tom.Rix@windriver.com> | |
4 | * | |
bcd4d4eb | 5 | * SPDX-License-Identifier: GPL-2.0 |
0c872ecd TR |
6 | * |
7 | * This work is derived from the linux 2.6.27 kernel source | |
8 | * To fetch, use the kernel repository | |
9 | * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git | |
10 | * Use the v2.6.27 tag. | |
11 | * | |
12 | * Below is the original's header including its copyright | |
13 | * | |
14 | * linux/arch/arm/plat-omap/gpio.c | |
15 | * | |
16 | * Support functions for OMAP GPIO | |
17 | * | |
18 | * Copyright (C) 2003-2005 Nokia Corporation | |
19 | * Written by Juha Yrjölä <juha.yrjola@nokia.com> | |
0c872ecd TR |
20 | */ |
21 | #include <common.h> | |
365d6070 | 22 | #include <asm/gpio.h> |
0c872ecd TR |
23 | #include <asm/io.h> |
24 | #include <asm/errno.h> | |
25 | ||
81bdc155 SP |
26 | #define OMAP_GPIO_DIR_OUT 0 |
27 | #define OMAP_GPIO_DIR_IN 1 | |
28 | ||
25223a68 | 29 | static inline const struct gpio_bank *get_gpio_bank(int gpio) |
0c872ecd | 30 | { |
25223a68 | 31 | return &omap_gpio_bank[gpio >> 5]; |
0c872ecd TR |
32 | } |
33 | ||
34 | static inline int get_gpio_index(int gpio) | |
35 | { | |
36 | return gpio & 0x1f; | |
37 | } | |
38 | ||
dcee1ab3 | 39 | int gpio_is_valid(int gpio) |
0c872ecd | 40 | { |
87bd05d7 | 41 | return (gpio >= 0) && (gpio < OMAP_MAX_GPIO); |
0c872ecd TR |
42 | } |
43 | ||
44 | static int check_gpio(int gpio) | |
45 | { | |
dcee1ab3 | 46 | if (!gpio_is_valid(gpio)) { |
0c872ecd | 47 | printf("ERROR : check_gpio: invalid GPIO %d\n", gpio); |
365d6070 | 48 | return -1; |
0c872ecd TR |
49 | } |
50 | return 0; | |
51 | } | |
52 | ||
25223a68 A |
53 | static void _set_gpio_direction(const struct gpio_bank *bank, int gpio, |
54 | int is_input) | |
0c872ecd TR |
55 | { |
56 | void *reg = bank->base; | |
57 | u32 l; | |
58 | ||
59 | switch (bank->method) { | |
60 | case METHOD_GPIO_24XX: | |
25223a68 | 61 | reg += OMAP_GPIO_OE; |
0c872ecd TR |
62 | break; |
63 | default: | |
64 | return; | |
65 | } | |
66 | l = __raw_readl(reg); | |
67 | if (is_input) | |
68 | l |= 1 << gpio; | |
69 | else | |
70 | l &= ~(1 << gpio); | |
71 | __raw_writel(l, reg); | |
72 | } | |
73 | ||
81bdc155 SP |
74 | /** |
75 | * Get the direction of the GPIO by reading the GPIO_OE register | |
76 | * corresponding to the specified bank. | |
77 | */ | |
78 | static int _get_gpio_direction(const struct gpio_bank *bank, int gpio) | |
0c872ecd | 79 | { |
81bdc155 SP |
80 | void *reg = bank->base; |
81 | u32 v; | |
0c872ecd | 82 | |
81bdc155 SP |
83 | switch (bank->method) { |
84 | case METHOD_GPIO_24XX: | |
85 | reg += OMAP_GPIO_OE; | |
86 | break; | |
87 | default: | |
365d6070 | 88 | return -1; |
81bdc155 SP |
89 | } |
90 | ||
91 | v = __raw_readl(reg); | |
92 | ||
93 | if (v & (1 << gpio)) | |
94 | return OMAP_GPIO_DIR_IN; | |
95 | else | |
96 | return OMAP_GPIO_DIR_OUT; | |
0c872ecd TR |
97 | } |
98 | ||
25223a68 A |
99 | static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio, |
100 | int enable) | |
0c872ecd TR |
101 | { |
102 | void *reg = bank->base; | |
103 | u32 l = 0; | |
104 | ||
105 | switch (bank->method) { | |
106 | case METHOD_GPIO_24XX: | |
107 | if (enable) | |
25223a68 | 108 | reg += OMAP_GPIO_SETDATAOUT; |
0c872ecd | 109 | else |
25223a68 | 110 | reg += OMAP_GPIO_CLEARDATAOUT; |
0c872ecd TR |
111 | l = 1 << gpio; |
112 | break; | |
113 | default: | |
114 | printf("omap3-gpio unknown bank method %s %d\n", | |
115 | __FILE__, __LINE__); | |
116 | return; | |
117 | } | |
118 | __raw_writel(l, reg); | |
119 | } | |
120 | ||
81bdc155 SP |
121 | /** |
122 | * Set value of the specified gpio | |
123 | */ | |
365d6070 | 124 | int gpio_set_value(unsigned gpio, int value) |
0c872ecd | 125 | { |
25223a68 | 126 | const struct gpio_bank *bank; |
0c872ecd TR |
127 | |
128 | if (check_gpio(gpio) < 0) | |
365d6070 | 129 | return -1; |
0c872ecd | 130 | bank = get_gpio_bank(gpio); |
81bdc155 | 131 | _set_gpio_dataout(bank, get_gpio_index(gpio), value); |
365d6070 JH |
132 | |
133 | return 0; | |
0c872ecd TR |
134 | } |
135 | ||
81bdc155 SP |
136 | /** |
137 | * Get value of the specified gpio | |
138 | */ | |
365d6070 | 139 | int gpio_get_value(unsigned gpio) |
0c872ecd | 140 | { |
25223a68 | 141 | const struct gpio_bank *bank; |
0c872ecd | 142 | void *reg; |
81bdc155 | 143 | int input; |
0c872ecd TR |
144 | |
145 | if (check_gpio(gpio) < 0) | |
365d6070 | 146 | return -1; |
0c872ecd TR |
147 | bank = get_gpio_bank(gpio); |
148 | reg = bank->base; | |
149 | switch (bank->method) { | |
150 | case METHOD_GPIO_24XX: | |
81bdc155 SP |
151 | input = _get_gpio_direction(bank, get_gpio_index(gpio)); |
152 | switch (input) { | |
153 | case OMAP_GPIO_DIR_IN: | |
154 | reg += OMAP_GPIO_DATAIN; | |
155 | break; | |
156 | case OMAP_GPIO_DIR_OUT: | |
157 | reg += OMAP_GPIO_DATAOUT; | |
158 | break; | |
159 | default: | |
365d6070 | 160 | return -1; |
81bdc155 | 161 | } |
0c872ecd TR |
162 | break; |
163 | default: | |
365d6070 | 164 | return -1; |
0c872ecd TR |
165 | } |
166 | return (__raw_readl(reg) | |
167 | & (1 << get_gpio_index(gpio))) != 0; | |
168 | } | |
169 | ||
81bdc155 SP |
170 | /** |
171 | * Set gpio direction as input | |
172 | */ | |
173 | int gpio_direction_input(unsigned gpio) | |
569919d8 | 174 | { |
81bdc155 | 175 | const struct gpio_bank *bank; |
569919d8 JF |
176 | |
177 | if (check_gpio(gpio) < 0) | |
365d6070 | 178 | return -1; |
81bdc155 | 179 | |
569919d8 | 180 | bank = get_gpio_bank(gpio); |
81bdc155 SP |
181 | _set_gpio_direction(bank, get_gpio_index(gpio), 1); |
182 | ||
183 | return 0; | |
569919d8 JF |
184 | } |
185 | ||
81bdc155 SP |
186 | /** |
187 | * Set gpio direction as output | |
188 | */ | |
189 | int gpio_direction_output(unsigned gpio, int value) | |
0c872ecd | 190 | { |
81bdc155 SP |
191 | const struct gpio_bank *bank; |
192 | ||
193 | if (check_gpio(gpio) < 0) | |
365d6070 | 194 | return -1; |
81bdc155 SP |
195 | |
196 | bank = get_gpio_bank(gpio); | |
197 | _set_gpio_dataout(bank, get_gpio_index(gpio), value); | |
198 | _set_gpio_direction(bank, get_gpio_index(gpio), 0); | |
199 | ||
200 | return 0; | |
0c872ecd TR |
201 | } |
202 | ||
81bdc155 SP |
203 | /** |
204 | * Request a gpio before using it. | |
205 | * | |
206 | * NOTE: Argument 'label' is unused. | |
207 | */ | |
365d6070 | 208 | int gpio_request(unsigned gpio, const char *label) |
0c872ecd TR |
209 | { |
210 | if (check_gpio(gpio) < 0) | |
365d6070 | 211 | return -1; |
0c872ecd TR |
212 | |
213 | return 0; | |
214 | } | |
215 | ||
81bdc155 SP |
216 | /** |
217 | * Reset and free the gpio after using it. | |
218 | */ | |
365d6070 | 219 | int gpio_free(unsigned gpio) |
0c872ecd | 220 | { |
365d6070 | 221 | return 0; |
0c872ecd | 222 | } |