Commit 5460b8d469ca9510cfc45463eaf7eecfca68b8a5
Committed by
Sonic Zhang
1 parent
6a19cc9df0
Exists in
master
and in
53 other branches
blackfin: gpio: Unreserve gpio in special_gpio_free()
In special_gpio_free(), call unreserve() rather than reserve() to release gpio. Signed-off-by: Axel Lin <axel.lin@ingics.com> Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Showing 1 changed file with 2 additions and 2 deletions Inline Diff
arch/blackfin/cpu/gpio.c
1 | /* | 1 | /* |
2 | * ADI GPIO1 Abstraction Layer | 2 | * ADI GPIO1 Abstraction Layer |
3 | * Support BF50x, BF51x, BF52x, BF53x and BF561 only. | 3 | * Support BF50x, BF51x, BF52x, BF53x and BF561 only. |
4 | * | 4 | * |
5 | * Copyright 2006-2010 Analog Devices Inc. | 5 | * Copyright 2006-2010 Analog Devices Inc. |
6 | * | 6 | * |
7 | * Licensed under the GPL-2 or later | 7 | * Licensed under the GPL-2 or later |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <common.h> | 10 | #include <common.h> |
11 | #include <asm/errno.h> | 11 | #include <asm/errno.h> |
12 | #include <asm/gpio.h> | 12 | #include <asm/gpio.h> |
13 | #include <asm/portmux.h> | 13 | #include <asm/portmux.h> |
14 | 14 | ||
15 | #if ANOMALY_05000311 || ANOMALY_05000323 | 15 | #if ANOMALY_05000311 || ANOMALY_05000323 |
16 | enum { | 16 | enum { |
17 | AWA_data = SYSCR, | 17 | AWA_data = SYSCR, |
18 | AWA_data_clear = SYSCR, | 18 | AWA_data_clear = SYSCR, |
19 | AWA_data_set = SYSCR, | 19 | AWA_data_set = SYSCR, |
20 | AWA_toggle = SYSCR, | 20 | AWA_toggle = SYSCR, |
21 | AWA_maska = UART_SCR, | 21 | AWA_maska = UART_SCR, |
22 | AWA_maska_clear = UART_SCR, | 22 | AWA_maska_clear = UART_SCR, |
23 | AWA_maska_set = UART_SCR, | 23 | AWA_maska_set = UART_SCR, |
24 | AWA_maska_toggle = UART_SCR, | 24 | AWA_maska_toggle = UART_SCR, |
25 | AWA_maskb = UART_GCTL, | 25 | AWA_maskb = UART_GCTL, |
26 | AWA_maskb_clear = UART_GCTL, | 26 | AWA_maskb_clear = UART_GCTL, |
27 | AWA_maskb_set = UART_GCTL, | 27 | AWA_maskb_set = UART_GCTL, |
28 | AWA_maskb_toggle = UART_GCTL, | 28 | AWA_maskb_toggle = UART_GCTL, |
29 | AWA_dir = SPORT1_STAT, | 29 | AWA_dir = SPORT1_STAT, |
30 | AWA_polar = SPORT1_STAT, | 30 | AWA_polar = SPORT1_STAT, |
31 | AWA_edge = SPORT1_STAT, | 31 | AWA_edge = SPORT1_STAT, |
32 | AWA_both = SPORT1_STAT, | 32 | AWA_both = SPORT1_STAT, |
33 | #if ANOMALY_05000311 | 33 | #if ANOMALY_05000311 |
34 | AWA_inen = TIMER_ENABLE, | 34 | AWA_inen = TIMER_ENABLE, |
35 | #elif ANOMALY_05000323 | 35 | #elif ANOMALY_05000323 |
36 | AWA_inen = DMA1_1_CONFIG, | 36 | AWA_inen = DMA1_1_CONFIG, |
37 | #endif | 37 | #endif |
38 | }; | 38 | }; |
39 | /* Anomaly Workaround */ | 39 | /* Anomaly Workaround */ |
40 | #define AWA_DUMMY_READ(name) bfin_read16(AWA_ ## name) | 40 | #define AWA_DUMMY_READ(name) bfin_read16(AWA_ ## name) |
41 | #else | 41 | #else |
42 | #define AWA_DUMMY_READ(...) do { } while (0) | 42 | #define AWA_DUMMY_READ(...) do { } while (0) |
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | static struct gpio_port_t * const gpio_array[] = { | 45 | static struct gpio_port_t * const gpio_array[] = { |
46 | #if defined(BF533_FAMILY) | 46 | #if defined(BF533_FAMILY) |
47 | (struct gpio_port_t *) FIO_FLAG_D, | 47 | (struct gpio_port_t *) FIO_FLAG_D, |
48 | #elif defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) \ | 48 | #elif defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) \ |
49 | || defined(BF538_FAMILY) || defined(CONFIG_BF50x) | 49 | || defined(BF538_FAMILY) || defined(CONFIG_BF50x) |
50 | (struct gpio_port_t *) PORTFIO, | 50 | (struct gpio_port_t *) PORTFIO, |
51 | # if !defined(BF538_FAMILY) | 51 | # if !defined(BF538_FAMILY) |
52 | (struct gpio_port_t *) PORTGIO, | 52 | (struct gpio_port_t *) PORTGIO, |
53 | (struct gpio_port_t *) PORTHIO, | 53 | (struct gpio_port_t *) PORTHIO, |
54 | # endif | 54 | # endif |
55 | #elif defined(BF561_FAMILY) | 55 | #elif defined(BF561_FAMILY) |
56 | (struct gpio_port_t *) FIO0_FLAG_D, | 56 | (struct gpio_port_t *) FIO0_FLAG_D, |
57 | (struct gpio_port_t *) FIO1_FLAG_D, | 57 | (struct gpio_port_t *) FIO1_FLAG_D, |
58 | (struct gpio_port_t *) FIO2_FLAG_D, | 58 | (struct gpio_port_t *) FIO2_FLAG_D, |
59 | #else | 59 | #else |
60 | # error no gpio arrays defined | 60 | # error no gpio arrays defined |
61 | #endif | 61 | #endif |
62 | }; | 62 | }; |
63 | 63 | ||
64 | #if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) || \ | 64 | #if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) || \ |
65 | defined(CONFIG_BF50x) | 65 | defined(CONFIG_BF50x) |
66 | static unsigned short * const port_fer[] = { | 66 | static unsigned short * const port_fer[] = { |
67 | (unsigned short *) PORTF_FER, | 67 | (unsigned short *) PORTF_FER, |
68 | (unsigned short *) PORTG_FER, | 68 | (unsigned short *) PORTG_FER, |
69 | (unsigned short *) PORTH_FER, | 69 | (unsigned short *) PORTH_FER, |
70 | }; | 70 | }; |
71 | 71 | ||
72 | # if !defined(BF537_FAMILY) | 72 | # if !defined(BF537_FAMILY) |
73 | static unsigned short * const port_mux[] = { | 73 | static unsigned short * const port_mux[] = { |
74 | (unsigned short *) PORTF_MUX, | 74 | (unsigned short *) PORTF_MUX, |
75 | (unsigned short *) PORTG_MUX, | 75 | (unsigned short *) PORTG_MUX, |
76 | (unsigned short *) PORTH_MUX, | 76 | (unsigned short *) PORTH_MUX, |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static const | 79 | static const |
80 | u8 pmux_offset[][16] = { | 80 | u8 pmux_offset[][16] = { |
81 | # if defined(CONFIG_BF52x) | 81 | # if defined(CONFIG_BF52x) |
82 | { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */ | 82 | { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */ |
83 | { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */ | 83 | { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */ |
84 | { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */ | 84 | { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */ |
85 | # elif defined(CONFIG_BF51x) | 85 | # elif defined(CONFIG_BF51x) |
86 | { 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */ | 86 | { 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */ |
87 | { 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */ | 87 | { 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */ |
88 | { 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */ | 88 | { 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */ |
89 | # endif | 89 | # endif |
90 | }; | 90 | }; |
91 | # endif | 91 | # endif |
92 | 92 | ||
93 | #elif defined(BF538_FAMILY) | 93 | #elif defined(BF538_FAMILY) |
94 | static unsigned short * const port_fer[] = { | 94 | static unsigned short * const port_fer[] = { |
95 | (unsigned short *) PORTCIO_FER, | 95 | (unsigned short *) PORTCIO_FER, |
96 | (unsigned short *) PORTDIO_FER, | 96 | (unsigned short *) PORTDIO_FER, |
97 | (unsigned short *) PORTEIO_FER, | 97 | (unsigned short *) PORTEIO_FER, |
98 | }; | 98 | }; |
99 | #endif | 99 | #endif |
100 | 100 | ||
101 | #ifdef CONFIG_BFIN_GPIO_TRACK | 101 | #ifdef CONFIG_BFIN_GPIO_TRACK |
102 | #define RESOURCE_LABEL_SIZE 16 | 102 | #define RESOURCE_LABEL_SIZE 16 |
103 | 103 | ||
104 | static struct str_ident { | 104 | static struct str_ident { |
105 | char name[RESOURCE_LABEL_SIZE]; | 105 | char name[RESOURCE_LABEL_SIZE]; |
106 | } str_ident[MAX_RESOURCES]; | 106 | } str_ident[MAX_RESOURCES]; |
107 | 107 | ||
108 | static void gpio_error(unsigned gpio) | 108 | static void gpio_error(unsigned gpio) |
109 | { | 109 | { |
110 | printf("bfin-gpio: GPIO %d wasn't requested!\n", gpio); | 110 | printf("bfin-gpio: GPIO %d wasn't requested!\n", gpio); |
111 | } | 111 | } |
112 | 112 | ||
113 | static void set_label(unsigned short ident, const char *label) | 113 | static void set_label(unsigned short ident, const char *label) |
114 | { | 114 | { |
115 | if (label) { | 115 | if (label) { |
116 | strncpy(str_ident[ident].name, label, | 116 | strncpy(str_ident[ident].name, label, |
117 | RESOURCE_LABEL_SIZE); | 117 | RESOURCE_LABEL_SIZE); |
118 | str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0; | 118 | str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0; |
119 | } | 119 | } |
120 | } | 120 | } |
121 | 121 | ||
122 | static char *get_label(unsigned short ident) | 122 | static char *get_label(unsigned short ident) |
123 | { | 123 | { |
124 | return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN"); | 124 | return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN"); |
125 | } | 125 | } |
126 | 126 | ||
127 | static int cmp_label(unsigned short ident, const char *label) | 127 | static int cmp_label(unsigned short ident, const char *label) |
128 | { | 128 | { |
129 | if (label == NULL) | 129 | if (label == NULL) |
130 | printf("bfin-gpio: please provide none-null label\n"); | 130 | printf("bfin-gpio: please provide none-null label\n"); |
131 | 131 | ||
132 | if (label) | 132 | if (label) |
133 | return strcmp(str_ident[ident].name, label); | 133 | return strcmp(str_ident[ident].name, label); |
134 | else | 134 | else |
135 | return -EINVAL; | 135 | return -EINVAL; |
136 | } | 136 | } |
137 | 137 | ||
138 | #define map_entry(m, i) reserved_##m##_map[gpio_bank(i)] | 138 | #define map_entry(m, i) reserved_##m##_map[gpio_bank(i)] |
139 | #define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i)) | 139 | #define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i)) |
140 | #define reserve(m, i) (map_entry(m, i) |= gpio_bit(i)) | 140 | #define reserve(m, i) (map_entry(m, i) |= gpio_bit(i)) |
141 | #define unreserve(m, i) (map_entry(m, i) &= ~gpio_bit(i)) | 141 | #define unreserve(m, i) (map_entry(m, i) &= ~gpio_bit(i)) |
142 | #define DECLARE_RESERVED_MAP(m, c) static unsigned short reserved_##m##_map[c] | 142 | #define DECLARE_RESERVED_MAP(m, c) static unsigned short reserved_##m##_map[c] |
143 | #else | 143 | #else |
144 | #define is_reserved(m, i, e) (!(e)) | 144 | #define is_reserved(m, i, e) (!(e)) |
145 | #define reserve(m, i) | 145 | #define reserve(m, i) |
146 | #define unreserve(m, i) | 146 | #define unreserve(m, i) |
147 | #define DECLARE_RESERVED_MAP(m, c) | 147 | #define DECLARE_RESERVED_MAP(m, c) |
148 | #define gpio_error(gpio) | 148 | #define gpio_error(gpio) |
149 | #define set_label(...) | 149 | #define set_label(...) |
150 | #define get_label(...) "" | 150 | #define get_label(...) "" |
151 | #define cmp_label(...) 1 | 151 | #define cmp_label(...) 1 |
152 | #endif | 152 | #endif |
153 | 153 | ||
154 | DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM); | 154 | DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM); |
155 | DECLARE_RESERVED_MAP(peri, gpio_bank(MAX_RESOURCES)); | 155 | DECLARE_RESERVED_MAP(peri, gpio_bank(MAX_RESOURCES)); |
156 | 156 | ||
157 | inline int check_gpio(unsigned gpio) | 157 | inline int check_gpio(unsigned gpio) |
158 | { | 158 | { |
159 | if (gpio >= MAX_BLACKFIN_GPIOS) | 159 | if (gpio >= MAX_BLACKFIN_GPIOS) |
160 | return -EINVAL; | 160 | return -EINVAL; |
161 | return 0; | 161 | return 0; |
162 | } | 162 | } |
163 | 163 | ||
164 | static void port_setup(unsigned gpio, unsigned short usage) | 164 | static void port_setup(unsigned gpio, unsigned short usage) |
165 | { | 165 | { |
166 | #if defined(BF538_FAMILY) | 166 | #if defined(BF538_FAMILY) |
167 | /* | 167 | /* |
168 | * BF538/9 Port C,D and E are special. | 168 | * BF538/9 Port C,D and E are special. |
169 | * Inverted PORT_FER polarity on CDE and no PORF_FER on F | 169 | * Inverted PORT_FER polarity on CDE and no PORF_FER on F |
170 | * Regular PORT F GPIOs are handled here, CDE are exclusively | 170 | * Regular PORT F GPIOs are handled here, CDE are exclusively |
171 | * managed by GPIOLIB | 171 | * managed by GPIOLIB |
172 | */ | 172 | */ |
173 | 173 | ||
174 | if (gpio < MAX_BLACKFIN_GPIOS || gpio >= MAX_RESOURCES) | 174 | if (gpio < MAX_BLACKFIN_GPIOS || gpio >= MAX_RESOURCES) |
175 | return; | 175 | return; |
176 | 176 | ||
177 | gpio -= MAX_BLACKFIN_GPIOS; | 177 | gpio -= MAX_BLACKFIN_GPIOS; |
178 | 178 | ||
179 | if (usage == GPIO_USAGE) | 179 | if (usage == GPIO_USAGE) |
180 | *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); | 180 | *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); |
181 | else | 181 | else |
182 | *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); | 182 | *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); |
183 | SSYNC(); | 183 | SSYNC(); |
184 | return; | 184 | return; |
185 | #endif | 185 | #endif |
186 | 186 | ||
187 | if (check_gpio(gpio)) | 187 | if (check_gpio(gpio)) |
188 | return; | 188 | return; |
189 | 189 | ||
190 | #if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) || \ | 190 | #if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) || \ |
191 | defined(CONFIG_BF50x) | 191 | defined(CONFIG_BF50x) |
192 | if (usage == GPIO_USAGE) | 192 | if (usage == GPIO_USAGE) |
193 | *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); | 193 | *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); |
194 | else | 194 | else |
195 | *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); | 195 | *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); |
196 | SSYNC(); | 196 | SSYNC(); |
197 | #endif | 197 | #endif |
198 | } | 198 | } |
199 | 199 | ||
200 | #ifdef BF537_FAMILY | 200 | #ifdef BF537_FAMILY |
201 | static struct { | 201 | static struct { |
202 | unsigned short res; | 202 | unsigned short res; |
203 | unsigned short offset; | 203 | unsigned short offset; |
204 | } port_mux_lut[] = { | 204 | } port_mux_lut[] = { |
205 | {.res = P_PPI0_D13, .offset = 11}, | 205 | {.res = P_PPI0_D13, .offset = 11}, |
206 | {.res = P_PPI0_D14, .offset = 11}, | 206 | {.res = P_PPI0_D14, .offset = 11}, |
207 | {.res = P_PPI0_D15, .offset = 11}, | 207 | {.res = P_PPI0_D15, .offset = 11}, |
208 | {.res = P_SPORT1_TFS, .offset = 11}, | 208 | {.res = P_SPORT1_TFS, .offset = 11}, |
209 | {.res = P_SPORT1_TSCLK, .offset = 11}, | 209 | {.res = P_SPORT1_TSCLK, .offset = 11}, |
210 | {.res = P_SPORT1_DTPRI, .offset = 11}, | 210 | {.res = P_SPORT1_DTPRI, .offset = 11}, |
211 | {.res = P_PPI0_D10, .offset = 10}, | 211 | {.res = P_PPI0_D10, .offset = 10}, |
212 | {.res = P_PPI0_D11, .offset = 10}, | 212 | {.res = P_PPI0_D11, .offset = 10}, |
213 | {.res = P_PPI0_D12, .offset = 10}, | 213 | {.res = P_PPI0_D12, .offset = 10}, |
214 | {.res = P_SPORT1_RSCLK, .offset = 10}, | 214 | {.res = P_SPORT1_RSCLK, .offset = 10}, |
215 | {.res = P_SPORT1_RFS, .offset = 10}, | 215 | {.res = P_SPORT1_RFS, .offset = 10}, |
216 | {.res = P_SPORT1_DRPRI, .offset = 10}, | 216 | {.res = P_SPORT1_DRPRI, .offset = 10}, |
217 | {.res = P_PPI0_D8, .offset = 9}, | 217 | {.res = P_PPI0_D8, .offset = 9}, |
218 | {.res = P_PPI0_D9, .offset = 9}, | 218 | {.res = P_PPI0_D9, .offset = 9}, |
219 | {.res = P_SPORT1_DRSEC, .offset = 9}, | 219 | {.res = P_SPORT1_DRSEC, .offset = 9}, |
220 | {.res = P_SPORT1_DTSEC, .offset = 9}, | 220 | {.res = P_SPORT1_DTSEC, .offset = 9}, |
221 | {.res = P_TMR2, .offset = 8}, | 221 | {.res = P_TMR2, .offset = 8}, |
222 | {.res = P_PPI0_FS3, .offset = 8}, | 222 | {.res = P_PPI0_FS3, .offset = 8}, |
223 | {.res = P_TMR3, .offset = 7}, | 223 | {.res = P_TMR3, .offset = 7}, |
224 | {.res = P_SPI0_SSEL4, .offset = 7}, | 224 | {.res = P_SPI0_SSEL4, .offset = 7}, |
225 | {.res = P_TMR4, .offset = 6}, | 225 | {.res = P_TMR4, .offset = 6}, |
226 | {.res = P_SPI0_SSEL5, .offset = 6}, | 226 | {.res = P_SPI0_SSEL5, .offset = 6}, |
227 | {.res = P_TMR5, .offset = 5}, | 227 | {.res = P_TMR5, .offset = 5}, |
228 | {.res = P_SPI0_SSEL6, .offset = 5}, | 228 | {.res = P_SPI0_SSEL6, .offset = 5}, |
229 | {.res = P_UART1_RX, .offset = 4}, | 229 | {.res = P_UART1_RX, .offset = 4}, |
230 | {.res = P_UART1_TX, .offset = 4}, | 230 | {.res = P_UART1_TX, .offset = 4}, |
231 | {.res = P_TMR6, .offset = 4}, | 231 | {.res = P_TMR6, .offset = 4}, |
232 | {.res = P_TMR7, .offset = 4}, | 232 | {.res = P_TMR7, .offset = 4}, |
233 | {.res = P_UART0_RX, .offset = 3}, | 233 | {.res = P_UART0_RX, .offset = 3}, |
234 | {.res = P_UART0_TX, .offset = 3}, | 234 | {.res = P_UART0_TX, .offset = 3}, |
235 | {.res = P_DMAR0, .offset = 3}, | 235 | {.res = P_DMAR0, .offset = 3}, |
236 | {.res = P_DMAR1, .offset = 3}, | 236 | {.res = P_DMAR1, .offset = 3}, |
237 | {.res = P_SPORT0_DTSEC, .offset = 1}, | 237 | {.res = P_SPORT0_DTSEC, .offset = 1}, |
238 | {.res = P_SPORT0_DRSEC, .offset = 1}, | 238 | {.res = P_SPORT0_DRSEC, .offset = 1}, |
239 | {.res = P_CAN0_RX, .offset = 1}, | 239 | {.res = P_CAN0_RX, .offset = 1}, |
240 | {.res = P_CAN0_TX, .offset = 1}, | 240 | {.res = P_CAN0_TX, .offset = 1}, |
241 | {.res = P_SPI0_SSEL7, .offset = 1}, | 241 | {.res = P_SPI0_SSEL7, .offset = 1}, |
242 | {.res = P_SPORT0_TFS, .offset = 0}, | 242 | {.res = P_SPORT0_TFS, .offset = 0}, |
243 | {.res = P_SPORT0_DTPRI, .offset = 0}, | 243 | {.res = P_SPORT0_DTPRI, .offset = 0}, |
244 | {.res = P_SPI0_SSEL2, .offset = 0}, | 244 | {.res = P_SPI0_SSEL2, .offset = 0}, |
245 | {.res = P_SPI0_SSEL3, .offset = 0}, | 245 | {.res = P_SPI0_SSEL3, .offset = 0}, |
246 | }; | 246 | }; |
247 | 247 | ||
248 | static void portmux_setup(unsigned short per) | 248 | static void portmux_setup(unsigned short per) |
249 | { | 249 | { |
250 | u16 y, offset, muxreg; | 250 | u16 y, offset, muxreg; |
251 | u16 function = P_FUNCT2MUX(per); | 251 | u16 function = P_FUNCT2MUX(per); |
252 | 252 | ||
253 | for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) { | 253 | for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) { |
254 | if (port_mux_lut[y].res == per) { | 254 | if (port_mux_lut[y].res == per) { |
255 | 255 | ||
256 | /* SET PORTMUX REG */ | 256 | /* SET PORTMUX REG */ |
257 | 257 | ||
258 | offset = port_mux_lut[y].offset; | 258 | offset = port_mux_lut[y].offset; |
259 | muxreg = bfin_read_PORT_MUX(); | 259 | muxreg = bfin_read_PORT_MUX(); |
260 | 260 | ||
261 | if (offset != 1) | 261 | if (offset != 1) |
262 | muxreg &= ~(1 << offset); | 262 | muxreg &= ~(1 << offset); |
263 | else | 263 | else |
264 | muxreg &= ~(3 << 1); | 264 | muxreg &= ~(3 << 1); |
265 | 265 | ||
266 | muxreg |= (function << offset); | 266 | muxreg |= (function << offset); |
267 | bfin_write_PORT_MUX(muxreg); | 267 | bfin_write_PORT_MUX(muxreg); |
268 | } | 268 | } |
269 | } | 269 | } |
270 | } | 270 | } |
271 | #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) | 271 | #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) |
272 | inline void portmux_setup(unsigned short per) | 272 | inline void portmux_setup(unsigned short per) |
273 | { | 273 | { |
274 | u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per); | 274 | u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per); |
275 | u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; | 275 | u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; |
276 | 276 | ||
277 | pmux = *port_mux[gpio_bank(ident)]; | 277 | pmux = *port_mux[gpio_bank(ident)]; |
278 | pmux &= ~(3 << offset); | 278 | pmux &= ~(3 << offset); |
279 | pmux |= (function & 3) << offset; | 279 | pmux |= (function & 3) << offset; |
280 | *port_mux[gpio_bank(ident)] = pmux; | 280 | *port_mux[gpio_bank(ident)] = pmux; |
281 | SSYNC(); | 281 | SSYNC(); |
282 | } | 282 | } |
283 | #else | 283 | #else |
284 | # define portmux_setup(...) do { } while (0) | 284 | # define portmux_setup(...) do { } while (0) |
285 | #endif | 285 | #endif |
286 | 286 | ||
287 | /*********************************************************** | 287 | /*********************************************************** |
288 | * | 288 | * |
289 | * FUNCTIONS: Blackfin General Purpose Ports Access Functions | 289 | * FUNCTIONS: Blackfin General Purpose Ports Access Functions |
290 | * | 290 | * |
291 | * INPUTS/OUTPUTS: | 291 | * INPUTS/OUTPUTS: |
292 | * gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS | 292 | * gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS |
293 | * | 293 | * |
294 | * | 294 | * |
295 | * DESCRIPTION: These functions abstract direct register access | 295 | * DESCRIPTION: These functions abstract direct register access |
296 | * to Blackfin processor General Purpose | 296 | * to Blackfin processor General Purpose |
297 | * Ports Regsiters | 297 | * Ports Regsiters |
298 | * | 298 | * |
299 | * CAUTION: These functions do not belong to the GPIO Driver API | 299 | * CAUTION: These functions do not belong to the GPIO Driver API |
300 | ************************************************************* | 300 | ************************************************************* |
301 | * MODIFICATION HISTORY : | 301 | * MODIFICATION HISTORY : |
302 | **************************************************************/ | 302 | **************************************************************/ |
303 | 303 | ||
304 | /* Set a specific bit */ | 304 | /* Set a specific bit */ |
305 | 305 | ||
306 | #define SET_GPIO(name) \ | 306 | #define SET_GPIO(name) \ |
307 | void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ | 307 | void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ |
308 | { \ | 308 | { \ |
309 | unsigned long flags; \ | 309 | unsigned long flags; \ |
310 | local_irq_save(flags); \ | 310 | local_irq_save(flags); \ |
311 | if (arg) \ | 311 | if (arg) \ |
312 | gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ | 312 | gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ |
313 | else \ | 313 | else \ |
314 | gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \ | 314 | gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \ |
315 | AWA_DUMMY_READ(name); \ | 315 | AWA_DUMMY_READ(name); \ |
316 | local_irq_restore(flags); \ | 316 | local_irq_restore(flags); \ |
317 | } | 317 | } |
318 | 318 | ||
319 | SET_GPIO(dir) /* set_gpio_dir() */ | 319 | SET_GPIO(dir) /* set_gpio_dir() */ |
320 | SET_GPIO(inen) /* set_gpio_inen() */ | 320 | SET_GPIO(inen) /* set_gpio_inen() */ |
321 | SET_GPIO(polar) /* set_gpio_polar() */ | 321 | SET_GPIO(polar) /* set_gpio_polar() */ |
322 | SET_GPIO(edge) /* set_gpio_edge() */ | 322 | SET_GPIO(edge) /* set_gpio_edge() */ |
323 | SET_GPIO(both) /* set_gpio_both() */ | 323 | SET_GPIO(both) /* set_gpio_both() */ |
324 | 324 | ||
325 | 325 | ||
326 | #define SET_GPIO_SC(name) \ | 326 | #define SET_GPIO_SC(name) \ |
327 | void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ | 327 | void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ |
328 | { \ | 328 | { \ |
329 | unsigned long flags; \ | 329 | unsigned long flags; \ |
330 | if (ANOMALY_05000311 || ANOMALY_05000323) \ | 330 | if (ANOMALY_05000311 || ANOMALY_05000323) \ |
331 | local_irq_save(flags); \ | 331 | local_irq_save(flags); \ |
332 | if (arg) \ | 332 | if (arg) \ |
333 | gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ | 333 | gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ |
334 | else \ | 334 | else \ |
335 | gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ | 335 | gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ |
336 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ | 336 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ |
337 | AWA_DUMMY_READ(name); \ | 337 | AWA_DUMMY_READ(name); \ |
338 | local_irq_restore(flags); \ | 338 | local_irq_restore(flags); \ |
339 | } \ | 339 | } \ |
340 | } | 340 | } |
341 | 341 | ||
342 | SET_GPIO_SC(maska) | 342 | SET_GPIO_SC(maska) |
343 | SET_GPIO_SC(maskb) | 343 | SET_GPIO_SC(maskb) |
344 | SET_GPIO_SC(data) | 344 | SET_GPIO_SC(data) |
345 | 345 | ||
346 | void set_gpio_toggle(unsigned gpio) | 346 | void set_gpio_toggle(unsigned gpio) |
347 | { | 347 | { |
348 | unsigned long flags; | 348 | unsigned long flags; |
349 | if (ANOMALY_05000311 || ANOMALY_05000323) | 349 | if (ANOMALY_05000311 || ANOMALY_05000323) |
350 | local_irq_save(flags); | 350 | local_irq_save(flags); |
351 | gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio); | 351 | gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio); |
352 | if (ANOMALY_05000311 || ANOMALY_05000323) { | 352 | if (ANOMALY_05000311 || ANOMALY_05000323) { |
353 | AWA_DUMMY_READ(toggle); | 353 | AWA_DUMMY_READ(toggle); |
354 | local_irq_restore(flags); | 354 | local_irq_restore(flags); |
355 | } | 355 | } |
356 | } | 356 | } |
357 | 357 | ||
358 | /* Set current PORT date (16-bit word) */ | 358 | /* Set current PORT date (16-bit word) */ |
359 | 359 | ||
360 | #define SET_GPIO_P(name) \ | 360 | #define SET_GPIO_P(name) \ |
361 | void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \ | 361 | void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \ |
362 | { \ | 362 | { \ |
363 | unsigned long flags; \ | 363 | unsigned long flags; \ |
364 | if (ANOMALY_05000311 || ANOMALY_05000323) \ | 364 | if (ANOMALY_05000311 || ANOMALY_05000323) \ |
365 | local_irq_save(flags); \ | 365 | local_irq_save(flags); \ |
366 | gpio_array[gpio_bank(gpio)]->name = arg; \ | 366 | gpio_array[gpio_bank(gpio)]->name = arg; \ |
367 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ | 367 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ |
368 | AWA_DUMMY_READ(name); \ | 368 | AWA_DUMMY_READ(name); \ |
369 | local_irq_restore(flags); \ | 369 | local_irq_restore(flags); \ |
370 | } \ | 370 | } \ |
371 | } | 371 | } |
372 | 372 | ||
373 | SET_GPIO_P(data) | 373 | SET_GPIO_P(data) |
374 | SET_GPIO_P(dir) | 374 | SET_GPIO_P(dir) |
375 | SET_GPIO_P(inen) | 375 | SET_GPIO_P(inen) |
376 | SET_GPIO_P(polar) | 376 | SET_GPIO_P(polar) |
377 | SET_GPIO_P(edge) | 377 | SET_GPIO_P(edge) |
378 | SET_GPIO_P(both) | 378 | SET_GPIO_P(both) |
379 | SET_GPIO_P(maska) | 379 | SET_GPIO_P(maska) |
380 | SET_GPIO_P(maskb) | 380 | SET_GPIO_P(maskb) |
381 | 381 | ||
382 | /* Get a specific bit */ | 382 | /* Get a specific bit */ |
383 | #define GET_GPIO(name) \ | 383 | #define GET_GPIO(name) \ |
384 | unsigned short get_gpio_ ## name(unsigned gpio) \ | 384 | unsigned short get_gpio_ ## name(unsigned gpio) \ |
385 | { \ | 385 | { \ |
386 | unsigned long flags; \ | 386 | unsigned long flags; \ |
387 | unsigned short ret; \ | 387 | unsigned short ret; \ |
388 | if (ANOMALY_05000311 || ANOMALY_05000323) \ | 388 | if (ANOMALY_05000311 || ANOMALY_05000323) \ |
389 | local_irq_save(flags); \ | 389 | local_irq_save(flags); \ |
390 | ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \ | 390 | ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \ |
391 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ | 391 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ |
392 | AWA_DUMMY_READ(name); \ | 392 | AWA_DUMMY_READ(name); \ |
393 | local_irq_restore(flags); \ | 393 | local_irq_restore(flags); \ |
394 | } \ | 394 | } \ |
395 | return ret; \ | 395 | return ret; \ |
396 | } | 396 | } |
397 | 397 | ||
398 | GET_GPIO(data) | 398 | GET_GPIO(data) |
399 | GET_GPIO(dir) | 399 | GET_GPIO(dir) |
400 | GET_GPIO(inen) | 400 | GET_GPIO(inen) |
401 | GET_GPIO(polar) | 401 | GET_GPIO(polar) |
402 | GET_GPIO(edge) | 402 | GET_GPIO(edge) |
403 | GET_GPIO(both) | 403 | GET_GPIO(both) |
404 | GET_GPIO(maska) | 404 | GET_GPIO(maska) |
405 | GET_GPIO(maskb) | 405 | GET_GPIO(maskb) |
406 | 406 | ||
407 | /* Get current PORT date (16-bit word) */ | 407 | /* Get current PORT date (16-bit word) */ |
408 | 408 | ||
409 | #define GET_GPIO_P(name) \ | 409 | #define GET_GPIO_P(name) \ |
410 | unsigned short get_gpiop_ ## name(unsigned gpio) \ | 410 | unsigned short get_gpiop_ ## name(unsigned gpio) \ |
411 | { \ | 411 | { \ |
412 | unsigned long flags; \ | 412 | unsigned long flags; \ |
413 | unsigned short ret; \ | 413 | unsigned short ret; \ |
414 | if (ANOMALY_05000311 || ANOMALY_05000323) \ | 414 | if (ANOMALY_05000311 || ANOMALY_05000323) \ |
415 | local_irq_save(flags); \ | 415 | local_irq_save(flags); \ |
416 | ret = (gpio_array[gpio_bank(gpio)]->name); \ | 416 | ret = (gpio_array[gpio_bank(gpio)]->name); \ |
417 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ | 417 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ |
418 | AWA_DUMMY_READ(name); \ | 418 | AWA_DUMMY_READ(name); \ |
419 | local_irq_restore(flags); \ | 419 | local_irq_restore(flags); \ |
420 | } \ | 420 | } \ |
421 | return ret; \ | 421 | return ret; \ |
422 | } | 422 | } |
423 | 423 | ||
424 | GET_GPIO_P(data) | 424 | GET_GPIO_P(data) |
425 | GET_GPIO_P(dir) | 425 | GET_GPIO_P(dir) |
426 | GET_GPIO_P(inen) | 426 | GET_GPIO_P(inen) |
427 | GET_GPIO_P(polar) | 427 | GET_GPIO_P(polar) |
428 | GET_GPIO_P(edge) | 428 | GET_GPIO_P(edge) |
429 | GET_GPIO_P(both) | 429 | GET_GPIO_P(both) |
430 | GET_GPIO_P(maska) | 430 | GET_GPIO_P(maska) |
431 | GET_GPIO_P(maskb) | 431 | GET_GPIO_P(maskb) |
432 | 432 | ||
433 | /*********************************************************** | 433 | /*********************************************************** |
434 | * | 434 | * |
435 | * FUNCTIONS: Blackfin Peripheral Resource Allocation | 435 | * FUNCTIONS: Blackfin Peripheral Resource Allocation |
436 | * and PortMux Setup | 436 | * and PortMux Setup |
437 | * | 437 | * |
438 | * INPUTS/OUTPUTS: | 438 | * INPUTS/OUTPUTS: |
439 | * per Peripheral Identifier | 439 | * per Peripheral Identifier |
440 | * label String | 440 | * label String |
441 | * | 441 | * |
442 | * DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API | 442 | * DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API |
443 | * | 443 | * |
444 | * CAUTION: | 444 | * CAUTION: |
445 | ************************************************************* | 445 | ************************************************************* |
446 | * MODIFICATION HISTORY : | 446 | * MODIFICATION HISTORY : |
447 | **************************************************************/ | 447 | **************************************************************/ |
448 | 448 | ||
449 | int peripheral_request(unsigned short per, const char *label) | 449 | int peripheral_request(unsigned short per, const char *label) |
450 | { | 450 | { |
451 | unsigned short ident = P_IDENT(per); | 451 | unsigned short ident = P_IDENT(per); |
452 | 452 | ||
453 | /* | 453 | /* |
454 | * Don't cares are pins with only one dedicated function | 454 | * Don't cares are pins with only one dedicated function |
455 | */ | 455 | */ |
456 | 456 | ||
457 | if (per & P_DONTCARE) | 457 | if (per & P_DONTCARE) |
458 | return 0; | 458 | return 0; |
459 | 459 | ||
460 | if (!(per & P_DEFINED)) | 460 | if (!(per & P_DEFINED)) |
461 | return -ENODEV; | 461 | return -ENODEV; |
462 | 462 | ||
463 | BUG_ON(ident >= MAX_RESOURCES); | 463 | BUG_ON(ident >= MAX_RESOURCES); |
464 | 464 | ||
465 | /* If a pin can be muxed as either GPIO or peripheral, make | 465 | /* If a pin can be muxed as either GPIO or peripheral, make |
466 | * sure it is not already a GPIO pin when we request it. | 466 | * sure it is not already a GPIO pin when we request it. |
467 | */ | 467 | */ |
468 | if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) { | 468 | if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) { |
469 | printf("%s: Peripheral %d is already reserved as GPIO by %s !\n", | 469 | printf("%s: Peripheral %d is already reserved as GPIO by %s !\n", |
470 | __func__, ident, get_label(ident)); | 470 | __func__, ident, get_label(ident)); |
471 | return -EBUSY; | 471 | return -EBUSY; |
472 | } | 472 | } |
473 | 473 | ||
474 | if (unlikely(is_reserved(peri, ident, 1))) { | 474 | if (unlikely(is_reserved(peri, ident, 1))) { |
475 | 475 | ||
476 | /* | 476 | /* |
477 | * Pin functions like AMC address strobes my | 477 | * Pin functions like AMC address strobes my |
478 | * be requested and used by several drivers | 478 | * be requested and used by several drivers |
479 | */ | 479 | */ |
480 | 480 | ||
481 | if (!(per & P_MAYSHARE)) { | 481 | if (!(per & P_MAYSHARE)) { |
482 | /* | 482 | /* |
483 | * Allow that the identical pin function can | 483 | * Allow that the identical pin function can |
484 | * be requested from the same driver twice | 484 | * be requested from the same driver twice |
485 | */ | 485 | */ |
486 | 486 | ||
487 | if (cmp_label(ident, label) == 0) | 487 | if (cmp_label(ident, label) == 0) |
488 | goto anyway; | 488 | goto anyway; |
489 | 489 | ||
490 | printf("%s: Peripheral %d function %d is already reserved by %s !\n", | 490 | printf("%s: Peripheral %d function %d is already reserved by %s !\n", |
491 | __func__, ident, P_FUNCT2MUX(per), get_label(ident)); | 491 | __func__, ident, P_FUNCT2MUX(per), get_label(ident)); |
492 | return -EBUSY; | 492 | return -EBUSY; |
493 | } | 493 | } |
494 | } | 494 | } |
495 | 495 | ||
496 | anyway: | 496 | anyway: |
497 | reserve(peri, ident); | 497 | reserve(peri, ident); |
498 | 498 | ||
499 | portmux_setup(per); | 499 | portmux_setup(per); |
500 | port_setup(ident, PERIPHERAL_USAGE); | 500 | port_setup(ident, PERIPHERAL_USAGE); |
501 | 501 | ||
502 | set_label(ident, label); | 502 | set_label(ident, label); |
503 | 503 | ||
504 | return 0; | 504 | return 0; |
505 | } | 505 | } |
506 | 506 | ||
507 | int peripheral_request_list(const unsigned short per[], const char *label) | 507 | int peripheral_request_list(const unsigned short per[], const char *label) |
508 | { | 508 | { |
509 | u16 cnt; | 509 | u16 cnt; |
510 | int ret; | 510 | int ret; |
511 | 511 | ||
512 | for (cnt = 0; per[cnt] != 0; cnt++) { | 512 | for (cnt = 0; per[cnt] != 0; cnt++) { |
513 | 513 | ||
514 | ret = peripheral_request(per[cnt], label); | 514 | ret = peripheral_request(per[cnt], label); |
515 | 515 | ||
516 | if (ret < 0) { | 516 | if (ret < 0) { |
517 | for ( ; cnt > 0; cnt--) | 517 | for ( ; cnt > 0; cnt--) |
518 | peripheral_free(per[cnt - 1]); | 518 | peripheral_free(per[cnt - 1]); |
519 | 519 | ||
520 | return ret; | 520 | return ret; |
521 | } | 521 | } |
522 | } | 522 | } |
523 | 523 | ||
524 | return 0; | 524 | return 0; |
525 | } | 525 | } |
526 | 526 | ||
527 | void peripheral_free(unsigned short per) | 527 | void peripheral_free(unsigned short per) |
528 | { | 528 | { |
529 | unsigned short ident = P_IDENT(per); | 529 | unsigned short ident = P_IDENT(per); |
530 | 530 | ||
531 | if (per & P_DONTCARE) | 531 | if (per & P_DONTCARE) |
532 | return; | 532 | return; |
533 | 533 | ||
534 | if (!(per & P_DEFINED)) | 534 | if (!(per & P_DEFINED)) |
535 | return; | 535 | return; |
536 | 536 | ||
537 | if (unlikely(!is_reserved(peri, ident, 0))) | 537 | if (unlikely(!is_reserved(peri, ident, 0))) |
538 | return; | 538 | return; |
539 | 539 | ||
540 | if (!(per & P_MAYSHARE)) | 540 | if (!(per & P_MAYSHARE)) |
541 | port_setup(ident, GPIO_USAGE); | 541 | port_setup(ident, GPIO_USAGE); |
542 | 542 | ||
543 | unreserve(peri, ident); | 543 | unreserve(peri, ident); |
544 | 544 | ||
545 | set_label(ident, "free"); | 545 | set_label(ident, "free"); |
546 | } | 546 | } |
547 | 547 | ||
548 | void peripheral_free_list(const unsigned short per[]) | 548 | void peripheral_free_list(const unsigned short per[]) |
549 | { | 549 | { |
550 | u16 cnt; | 550 | u16 cnt; |
551 | for (cnt = 0; per[cnt] != 0; cnt++) | 551 | for (cnt = 0; per[cnt] != 0; cnt++) |
552 | peripheral_free(per[cnt]); | 552 | peripheral_free(per[cnt]); |
553 | } | 553 | } |
554 | 554 | ||
555 | /*********************************************************** | 555 | /*********************************************************** |
556 | * | 556 | * |
557 | * FUNCTIONS: Blackfin GPIO Driver | 557 | * FUNCTIONS: Blackfin GPIO Driver |
558 | * | 558 | * |
559 | * INPUTS/OUTPUTS: | 559 | * INPUTS/OUTPUTS: |
560 | * gpio PIO Number between 0 and MAX_BLACKFIN_GPIOS | 560 | * gpio PIO Number between 0 and MAX_BLACKFIN_GPIOS |
561 | * label String | 561 | * label String |
562 | * | 562 | * |
563 | * DESCRIPTION: Blackfin GPIO Driver API | 563 | * DESCRIPTION: Blackfin GPIO Driver API |
564 | * | 564 | * |
565 | * CAUTION: | 565 | * CAUTION: |
566 | ************************************************************* | 566 | ************************************************************* |
567 | * MODIFICATION HISTORY : | 567 | * MODIFICATION HISTORY : |
568 | **************************************************************/ | 568 | **************************************************************/ |
569 | 569 | ||
570 | int gpio_request(unsigned gpio, const char *label) | 570 | int gpio_request(unsigned gpio, const char *label) |
571 | { | 571 | { |
572 | if (check_gpio(gpio) < 0) | 572 | if (check_gpio(gpio) < 0) |
573 | return -EINVAL; | 573 | return -EINVAL; |
574 | 574 | ||
575 | /* | 575 | /* |
576 | * Allow that the identical GPIO can | 576 | * Allow that the identical GPIO can |
577 | * be requested from the same driver twice | 577 | * be requested from the same driver twice |
578 | * Do nothing and return - | 578 | * Do nothing and return - |
579 | */ | 579 | */ |
580 | 580 | ||
581 | if (cmp_label(gpio, label) == 0) | 581 | if (cmp_label(gpio, label) == 0) |
582 | return 0; | 582 | return 0; |
583 | 583 | ||
584 | if (unlikely(is_reserved(gpio, gpio, 1))) { | 584 | if (unlikely(is_reserved(gpio, gpio, 1))) { |
585 | printf("bfin-gpio: GPIO %d is already reserved by %s !\n", | 585 | printf("bfin-gpio: GPIO %d is already reserved by %s !\n", |
586 | gpio, get_label(gpio)); | 586 | gpio, get_label(gpio)); |
587 | return -EBUSY; | 587 | return -EBUSY; |
588 | } | 588 | } |
589 | if (unlikely(is_reserved(peri, gpio, 1))) { | 589 | if (unlikely(is_reserved(peri, gpio, 1))) { |
590 | printf("bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", | 590 | printf("bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", |
591 | gpio, get_label(gpio)); | 591 | gpio, get_label(gpio)); |
592 | return -EBUSY; | 592 | return -EBUSY; |
593 | } | 593 | } |
594 | else { /* Reset POLAR setting when acquiring a gpio for the first time */ | 594 | else { /* Reset POLAR setting when acquiring a gpio for the first time */ |
595 | set_gpio_polar(gpio, 0); | 595 | set_gpio_polar(gpio, 0); |
596 | } | 596 | } |
597 | 597 | ||
598 | reserve(gpio, gpio); | 598 | reserve(gpio, gpio); |
599 | set_label(gpio, label); | 599 | set_label(gpio, label); |
600 | 600 | ||
601 | port_setup(gpio, GPIO_USAGE); | 601 | port_setup(gpio, GPIO_USAGE); |
602 | 602 | ||
603 | return 0; | 603 | return 0; |
604 | } | 604 | } |
605 | 605 | ||
606 | int gpio_free(unsigned gpio) | 606 | int gpio_free(unsigned gpio) |
607 | { | 607 | { |
608 | if (check_gpio(gpio) < 0) | 608 | if (check_gpio(gpio) < 0) |
609 | return -1; | 609 | return -1; |
610 | 610 | ||
611 | if (unlikely(!is_reserved(gpio, gpio, 0))) { | 611 | if (unlikely(!is_reserved(gpio, gpio, 0))) { |
612 | gpio_error(gpio); | 612 | gpio_error(gpio); |
613 | return -1; | 613 | return -1; |
614 | } | 614 | } |
615 | 615 | ||
616 | unreserve(gpio, gpio); | 616 | unreserve(gpio, gpio); |
617 | 617 | ||
618 | set_label(gpio, "free"); | 618 | set_label(gpio, "free"); |
619 | 619 | ||
620 | return 0; | 620 | return 0; |
621 | } | 621 | } |
622 | 622 | ||
623 | #ifdef ADI_SPECIAL_GPIO_BANKS | 623 | #ifdef ADI_SPECIAL_GPIO_BANKS |
624 | DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES)); | 624 | DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES)); |
625 | 625 | ||
626 | int special_gpio_request(unsigned gpio, const char *label) | 626 | int special_gpio_request(unsigned gpio, const char *label) |
627 | { | 627 | { |
628 | /* | 628 | /* |
629 | * Allow that the identical GPIO can | 629 | * Allow that the identical GPIO can |
630 | * be requested from the same driver twice | 630 | * be requested from the same driver twice |
631 | * Do nothing and return - | 631 | * Do nothing and return - |
632 | */ | 632 | */ |
633 | 633 | ||
634 | if (cmp_label(gpio, label) == 0) | 634 | if (cmp_label(gpio, label) == 0) |
635 | return 0; | 635 | return 0; |
636 | 636 | ||
637 | if (unlikely(is_reserved(special_gpio, gpio, 1))) { | 637 | if (unlikely(is_reserved(special_gpio, gpio, 1))) { |
638 | printf("bfin-gpio: GPIO %d is already reserved by %s !\n", | 638 | printf("bfin-gpio: GPIO %d is already reserved by %s !\n", |
639 | gpio, get_label(gpio)); | 639 | gpio, get_label(gpio)); |
640 | return -EBUSY; | 640 | return -EBUSY; |
641 | } | 641 | } |
642 | if (unlikely(is_reserved(peri, gpio, 1))) { | 642 | if (unlikely(is_reserved(peri, gpio, 1))) { |
643 | printf("bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", | 643 | printf("bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", |
644 | gpio, get_label(gpio)); | 644 | gpio, get_label(gpio)); |
645 | 645 | ||
646 | return -EBUSY; | 646 | return -EBUSY; |
647 | } | 647 | } |
648 | 648 | ||
649 | reserve(special_gpio, gpio); | 649 | reserve(special_gpio, gpio); |
650 | reserve(peri, gpio); | 650 | reserve(peri, gpio); |
651 | 651 | ||
652 | set_label(gpio, label); | 652 | set_label(gpio, label); |
653 | port_setup(gpio, GPIO_USAGE); | 653 | port_setup(gpio, GPIO_USAGE); |
654 | 654 | ||
655 | return 0; | 655 | return 0; |
656 | } | 656 | } |
657 | 657 | ||
658 | void special_gpio_free(unsigned gpio) | 658 | void special_gpio_free(unsigned gpio) |
659 | { | 659 | { |
660 | if (unlikely(!is_reserved(special_gpio, gpio, 0))) { | 660 | if (unlikely(!is_reserved(special_gpio, gpio, 0))) { |
661 | gpio_error(gpio); | 661 | gpio_error(gpio); |
662 | return; | 662 | return; |
663 | } | 663 | } |
664 | 664 | ||
665 | reserve(special_gpio, gpio); | 665 | unreserve(special_gpio, gpio); |
666 | reserve(peri, gpio); | 666 | unreserve(peri, gpio); |
667 | set_label(gpio, "free"); | 667 | set_label(gpio, "free"); |
668 | } | 668 | } |
669 | #endif | 669 | #endif |
670 | 670 | ||
671 | static inline void __gpio_direction_input(unsigned gpio) | 671 | static inline void __gpio_direction_input(unsigned gpio) |
672 | { | 672 | { |
673 | gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); | 673 | gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); |
674 | gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio); | 674 | gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio); |
675 | } | 675 | } |
676 | 676 | ||
677 | int gpio_direction_input(unsigned gpio) | 677 | int gpio_direction_input(unsigned gpio) |
678 | { | 678 | { |
679 | unsigned long flags; | 679 | unsigned long flags; |
680 | 680 | ||
681 | if (!is_reserved(gpio, gpio, 0)) { | 681 | if (!is_reserved(gpio, gpio, 0)) { |
682 | gpio_error(gpio); | 682 | gpio_error(gpio); |
683 | return -EINVAL; | 683 | return -EINVAL; |
684 | } | 684 | } |
685 | 685 | ||
686 | local_irq_save(flags); | 686 | local_irq_save(flags); |
687 | __gpio_direction_input(gpio); | 687 | __gpio_direction_input(gpio); |
688 | AWA_DUMMY_READ(inen); | 688 | AWA_DUMMY_READ(inen); |
689 | local_irq_restore(flags); | 689 | local_irq_restore(flags); |
690 | 690 | ||
691 | return 0; | 691 | return 0; |
692 | } | 692 | } |
693 | 693 | ||
694 | int gpio_set_value(unsigned gpio, int arg) | 694 | int gpio_set_value(unsigned gpio, int arg) |
695 | { | 695 | { |
696 | if (arg) | 696 | if (arg) |
697 | gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); | 697 | gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); |
698 | else | 698 | else |
699 | gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio); | 699 | gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio); |
700 | 700 | ||
701 | return 0; | 701 | return 0; |
702 | } | 702 | } |
703 | 703 | ||
704 | int gpio_direction_output(unsigned gpio, int value) | 704 | int gpio_direction_output(unsigned gpio, int value) |
705 | { | 705 | { |
706 | unsigned long flags; | 706 | unsigned long flags; |
707 | 707 | ||
708 | if (!is_reserved(gpio, gpio, 0)) { | 708 | if (!is_reserved(gpio, gpio, 0)) { |
709 | gpio_error(gpio); | 709 | gpio_error(gpio); |
710 | return -EINVAL; | 710 | return -EINVAL; |
711 | } | 711 | } |
712 | 712 | ||
713 | local_irq_save(flags); | 713 | local_irq_save(flags); |
714 | 714 | ||
715 | gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); | 715 | gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); |
716 | gpio_set_value(gpio, value); | 716 | gpio_set_value(gpio, value); |
717 | gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio); | 717 | gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio); |
718 | 718 | ||
719 | AWA_DUMMY_READ(dir); | 719 | AWA_DUMMY_READ(dir); |
720 | local_irq_restore(flags); | 720 | local_irq_restore(flags); |
721 | 721 | ||
722 | return 0; | 722 | return 0; |
723 | } | 723 | } |
724 | 724 | ||
725 | int gpio_get_value(unsigned gpio) | 725 | int gpio_get_value(unsigned gpio) |
726 | { | 726 | { |
727 | unsigned long flags; | 727 | unsigned long flags; |
728 | 728 | ||
729 | if (unlikely(get_gpio_edge(gpio))) { | 729 | if (unlikely(get_gpio_edge(gpio))) { |
730 | int ret; | 730 | int ret; |
731 | local_irq_save(flags); | 731 | local_irq_save(flags); |
732 | set_gpio_edge(gpio, 0); | 732 | set_gpio_edge(gpio, 0); |
733 | ret = get_gpio_data(gpio); | 733 | ret = get_gpio_data(gpio); |
734 | set_gpio_edge(gpio, 1); | 734 | set_gpio_edge(gpio, 1); |
735 | local_irq_restore(flags); | 735 | local_irq_restore(flags); |
736 | return ret; | 736 | return ret; |
737 | } else | 737 | } else |
738 | return get_gpio_data(gpio); | 738 | return get_gpio_data(gpio); |
739 | } | 739 | } |
740 | 740 | ||
741 | /* If we are booting from SPI and our board lacks a strong enough pull up, | 741 | /* If we are booting from SPI and our board lacks a strong enough pull up, |
742 | * the core can reset and execute the bootrom faster than the resistor can | 742 | * the core can reset and execute the bootrom faster than the resistor can |
743 | * pull the signal logically high. To work around this (common) error in | 743 | * pull the signal logically high. To work around this (common) error in |
744 | * board design, we explicitly set the pin back to GPIO mode, force /CS | 744 | * board design, we explicitly set the pin back to GPIO mode, force /CS |
745 | * high, and wait for the electrons to do their thing. | 745 | * high, and wait for the electrons to do their thing. |
746 | * | 746 | * |
747 | * This function only makes sense to be called from reset code, but it | 747 | * This function only makes sense to be called from reset code, but it |
748 | * lives here as we need to force all the GPIO states w/out going through | 748 | * lives here as we need to force all the GPIO states w/out going through |
749 | * BUG() checks and such. | 749 | * BUG() checks and such. |
750 | */ | 750 | */ |
751 | void bfin_reset_boot_spi_cs(unsigned short pin) | 751 | void bfin_reset_boot_spi_cs(unsigned short pin) |
752 | { | 752 | { |
753 | unsigned short gpio = P_IDENT(pin); | 753 | unsigned short gpio = P_IDENT(pin); |
754 | port_setup(gpio, GPIO_USAGE); | 754 | port_setup(gpio, GPIO_USAGE); |
755 | gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); | 755 | gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); |
756 | AWA_DUMMY_READ(data_set); | 756 | AWA_DUMMY_READ(data_set); |
757 | udelay(1); | 757 | udelay(1); |
758 | } | 758 | } |
759 | 759 | ||
760 | void gpio_labels(void) | 760 | void gpio_labels(void) |
761 | { | 761 | { |
762 | int c, gpio; | 762 | int c, gpio; |
763 | 763 | ||
764 | for (c = 0; c < MAX_RESOURCES; c++) { | 764 | for (c = 0; c < MAX_RESOURCES; c++) { |
765 | gpio = is_reserved(gpio, c, 1); | 765 | gpio = is_reserved(gpio, c, 1); |
766 | if (!check_gpio(c) && gpio) | 766 | if (!check_gpio(c) && gpio) |
767 | printf("GPIO_%d:\t%s\tGPIO %s\n", c, | 767 | printf("GPIO_%d:\t%s\tGPIO %s\n", c, |
768 | get_label(c), | 768 | get_label(c), |
769 | get_gpio_dir(c) ? "OUTPUT" : "INPUT"); | 769 | get_gpio_dir(c) ? "OUTPUT" : "INPUT"); |
770 | else if (is_reserved(peri, c, 1)) | 770 | else if (is_reserved(peri, c, 1)) |
771 | printf("GPIO_%d:\t%s\tPeripheral\n", c, get_label(c)); | 771 | printf("GPIO_%d:\t%s\tPeripheral\n", c, get_label(c)); |
772 | else | 772 | else |
773 | continue; | 773 | continue; |
774 | } | 774 | } |
775 | } | 775 | } |
776 | 776 |