diff options
Diffstat (limited to 'arch/blackfin/kernel/bfin_gpio.c')
-rw-r--r-- | arch/blackfin/kernel/bfin_gpio.c | 549 |
1 files changed, 430 insertions, 119 deletions
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 5d488ef965ce..3fe0cd49e8db 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Description: GPIO Abstraction Layer | 7 | * Description: GPIO Abstraction Layer |
8 | * | 8 | * |
9 | * Modified: | 9 | * Modified: |
10 | * Copyright 2006 Analog Devices Inc. | 10 | * Copyright 2007 Analog Devices Inc. |
11 | * | 11 | * |
12 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 12 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ |
13 | * | 13 | * |
@@ -28,9 +28,9 @@ | |||
28 | */ | 28 | */ |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * Number BF537/6/4 BF561 BF533/2/1 | 31 | * Number BF537/6/4 BF561 BF533/2/1 BF549/8/4/2 |
32 | * | 32 | * |
33 | * GPIO_0 PF0 PF0 PF0 | 33 | * GPIO_0 PF0 PF0 PF0 PA0...PJ13 |
34 | * GPIO_1 PF1 PF1 PF1 | 34 | * GPIO_1 PF1 PF1 PF1 |
35 | * GPIO_2 PF2 PF2 PF2 | 35 | * GPIO_2 PF2 PF2 PF2 |
36 | * GPIO_3 PF3 PF3 PF3 | 36 | * GPIO_3 PF3 PF3 PF3 |
@@ -80,6 +80,7 @@ | |||
80 | * GPIO_47 PH15 PF47 | 80 | * GPIO_47 PH15 PF47 |
81 | */ | 81 | */ |
82 | 82 | ||
83 | #include <linux/delay.h> | ||
83 | #include <linux/module.h> | 84 | #include <linux/module.h> |
84 | #include <linux/err.h> | 85 | #include <linux/err.h> |
85 | #include <asm/blackfin.h> | 86 | #include <asm/blackfin.h> |
@@ -87,6 +88,36 @@ | |||
87 | #include <asm/portmux.h> | 88 | #include <asm/portmux.h> |
88 | #include <linux/irq.h> | 89 | #include <linux/irq.h> |
89 | 90 | ||
91 | #if ANOMALY_05000311 || ANOMALY_05000323 | ||
92 | enum { | ||
93 | AWA_data = SYSCR, | ||
94 | AWA_data_clear = SYSCR, | ||
95 | AWA_data_set = SYSCR, | ||
96 | AWA_toggle = SYSCR, | ||
97 | AWA_maska = UART_SCR, | ||
98 | AWA_maska_clear = UART_SCR, | ||
99 | AWA_maska_set = UART_SCR, | ||
100 | AWA_maska_toggle = UART_SCR, | ||
101 | AWA_maskb = UART_GCTL, | ||
102 | AWA_maskb_clear = UART_GCTL, | ||
103 | AWA_maskb_set = UART_GCTL, | ||
104 | AWA_maskb_toggle = UART_GCTL, | ||
105 | AWA_dir = SPORT1_STAT, | ||
106 | AWA_polar = SPORT1_STAT, | ||
107 | AWA_edge = SPORT1_STAT, | ||
108 | AWA_both = SPORT1_STAT, | ||
109 | #if ANOMALY_05000311 | ||
110 | AWA_inen = TIMER_ENABLE, | ||
111 | #elif ANOMALY_05000323 | ||
112 | AWA_inen = DMA1_1_CONFIG, | ||
113 | #endif | ||
114 | }; | ||
115 | /* Anomaly Workaround */ | ||
116 | #define AWA_DUMMY_READ(name) bfin_read16(AWA_ ## name) | ||
117 | #else | ||
118 | #define AWA_DUMMY_READ(...) do { } while (0) | ||
119 | #endif | ||
120 | |||
90 | #ifdef BF533_FAMILY | 121 | #ifdef BF533_FAMILY |
91 | static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = { | 122 | static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = { |
92 | (struct gpio_port_t *) FIO_FLAG_D, | 123 | (struct gpio_port_t *) FIO_FLAG_D, |
@@ -116,11 +147,31 @@ static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = { | |||
116 | }; | 147 | }; |
117 | #endif | 148 | #endif |
118 | 149 | ||
150 | #ifdef BF548_FAMILY | ||
151 | static struct gpio_port_t *gpio_array[gpio_bank(MAX_BLACKFIN_GPIOS)] = { | ||
152 | (struct gpio_port_t *)PORTA_FER, | ||
153 | (struct gpio_port_t *)PORTB_FER, | ||
154 | (struct gpio_port_t *)PORTC_FER, | ||
155 | (struct gpio_port_t *)PORTD_FER, | ||
156 | (struct gpio_port_t *)PORTE_FER, | ||
157 | (struct gpio_port_t *)PORTF_FER, | ||
158 | (struct gpio_port_t *)PORTG_FER, | ||
159 | (struct gpio_port_t *)PORTH_FER, | ||
160 | (struct gpio_port_t *)PORTI_FER, | ||
161 | (struct gpio_port_t *)PORTJ_FER, | ||
162 | }; | ||
163 | #endif | ||
164 | |||
119 | static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; | 165 | static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; |
120 | static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS + 16)]; | 166 | static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS + 16)]; |
121 | char *str_ident = NULL; | ||
122 | 167 | ||
123 | #define RESOURCE_LABEL_SIZE 16 | 168 | #define MAX_RESOURCES 256 |
169 | #define RESOURCE_LABEL_SIZE 16 | ||
170 | |||
171 | struct str_ident { | ||
172 | char name[RESOURCE_LABEL_SIZE]; | ||
173 | } *str_ident; | ||
174 | |||
124 | 175 | ||
125 | #ifdef CONFIG_PM | 176 | #ifdef CONFIG_PM |
126 | static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; | 177 | static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; |
@@ -141,21 +192,32 @@ static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INT | |||
141 | 192 | ||
142 | #endif /* CONFIG_PM */ | 193 | #endif /* CONFIG_PM */ |
143 | 194 | ||
195 | #if defined(BF548_FAMILY) | ||
196 | inline int check_gpio(unsigned short gpio) | ||
197 | { | ||
198 | if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 | ||
199 | || gpio == GPIO_PH14 || gpio == GPIO_PH15 | ||
200 | || gpio == GPIO_PJ14 || gpio == GPIO_PJ15 | ||
201 | || gpio > MAX_BLACKFIN_GPIOS) | ||
202 | return -EINVAL; | ||
203 | return 0; | ||
204 | } | ||
205 | #else | ||
144 | inline int check_gpio(unsigned short gpio) | 206 | inline int check_gpio(unsigned short gpio) |
145 | { | 207 | { |
146 | if (gpio >= MAX_BLACKFIN_GPIOS) | 208 | if (gpio >= MAX_BLACKFIN_GPIOS) |
147 | return -EINVAL; | 209 | return -EINVAL; |
148 | return 0; | 210 | return 0; |
149 | } | 211 | } |
212 | #endif | ||
150 | 213 | ||
151 | static void set_label(unsigned short ident, const char *label) | 214 | static void set_label(unsigned short ident, const char *label) |
152 | { | 215 | { |
153 | 216 | ||
154 | if (label && str_ident) { | 217 | if (label && str_ident) { |
155 | strncpy(str_ident + ident * RESOURCE_LABEL_SIZE, label, | 218 | strncpy(str_ident[ident].name, label, |
156 | RESOURCE_LABEL_SIZE); | 219 | RESOURCE_LABEL_SIZE); |
157 | str_ident[ident * RESOURCE_LABEL_SIZE + | 220 | str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0; |
158 | RESOURCE_LABEL_SIZE - 1] = 0; | ||
159 | } | 221 | } |
160 | } | 222 | } |
161 | 223 | ||
@@ -164,14 +226,13 @@ static char *get_label(unsigned short ident) | |||
164 | if (!str_ident) | 226 | if (!str_ident) |
165 | return "UNKNOWN"; | 227 | return "UNKNOWN"; |
166 | 228 | ||
167 | return (str_ident[ident * RESOURCE_LABEL_SIZE] ? | 229 | return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN"); |
168 | (str_ident + ident * RESOURCE_LABEL_SIZE) : "UNKNOWN"); | ||
169 | } | 230 | } |
170 | 231 | ||
171 | static int cmp_label(unsigned short ident, const char *label) | 232 | static int cmp_label(unsigned short ident, const char *label) |
172 | { | 233 | { |
173 | if (label && str_ident) | 234 | if (label && str_ident) |
174 | return strncmp(str_ident + ident * RESOURCE_LABEL_SIZE, | 235 | return strncmp(str_ident[ident].name, |
175 | label, strlen(label)); | 236 | label, strlen(label)); |
176 | else | 237 | else |
177 | return -EINVAL; | 238 | return -EINVAL; |
@@ -181,50 +242,84 @@ static int cmp_label(unsigned short ident, const char *label) | |||
181 | static void port_setup(unsigned short gpio, unsigned short usage) | 242 | static void port_setup(unsigned short gpio, unsigned short usage) |
182 | { | 243 | { |
183 | if (!check_gpio(gpio)) { | 244 | if (!check_gpio(gpio)) { |
184 | if (usage == GPIO_USAGE) { | 245 | if (usage == GPIO_USAGE) |
185 | *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); | 246 | *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); |
186 | } else | 247 | else |
187 | *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); | 248 | *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); |
188 | SSYNC(); | 249 | SSYNC(); |
189 | } | 250 | } |
190 | } | 251 | } |
252 | #elif defined(BF548_FAMILY) | ||
253 | static void port_setup(unsigned short gpio, unsigned short usage) | ||
254 | { | ||
255 | if (usage == GPIO_USAGE) | ||
256 | gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio); | ||
257 | else | ||
258 | gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio); | ||
259 | SSYNC(); | ||
260 | } | ||
191 | #else | 261 | #else |
192 | # define port_setup(...) do { } while (0) | 262 | # define port_setup(...) do { } while (0) |
193 | #endif | 263 | #endif |
194 | 264 | ||
195 | #ifdef BF537_FAMILY | 265 | #ifdef BF537_FAMILY |
196 | 266 | static struct { | |
197 | #define PMUX_LUT_RES 0 | 267 | unsigned short res; |
198 | #define PMUX_LUT_OFFSET 1 | 268 | unsigned short offset; |
199 | #define PMUX_LUT_ENTRIES 41 | 269 | } port_mux_lut[] = { |
200 | #define PMUX_LUT_SIZE 2 | 270 | {.res = P_PPI0_D13, .offset = 11}, |
201 | 271 | {.res = P_PPI0_D14, .offset = 11}, | |
202 | static unsigned short port_mux_lut[PMUX_LUT_ENTRIES][PMUX_LUT_SIZE] = { | 272 | {.res = P_PPI0_D15, .offset = 11}, |
203 | {P_PPI0_D13, 11}, {P_PPI0_D14, 11}, {P_PPI0_D15, 11}, | 273 | {.res = P_SPORT1_TFS, .offset = 11}, |
204 | {P_SPORT1_TFS, 11}, {P_SPORT1_TSCLK, 11}, {P_SPORT1_DTPRI, 11}, | 274 | {.res = P_SPORT1_TSCLK, .offset = 11}, |
205 | {P_PPI0_D10, 10}, {P_PPI0_D11, 10}, {P_PPI0_D12, 10}, | 275 | {.res = P_SPORT1_DTPRI, .offset = 11}, |
206 | {P_SPORT1_RSCLK, 10}, {P_SPORT1_RFS, 10}, {P_SPORT1_DRPRI, 10}, | 276 | {.res = P_PPI0_D10, .offset = 10}, |
207 | {P_PPI0_D8, 9}, {P_PPI0_D9, 9}, {P_SPORT1_DRSEC, 9}, | 277 | {.res = P_PPI0_D11, .offset = 10}, |
208 | {P_SPORT1_DTSEC, 9}, {P_TMR2, 8}, {P_PPI0_FS3, 8}, {P_TMR3, 7}, | 278 | {.res = P_PPI0_D12, .offset = 10}, |
209 | {P_SPI0_SSEL4, 7}, {P_TMR4, 6}, {P_SPI0_SSEL5, 6}, {P_TMR5, 5}, | 279 | {.res = P_SPORT1_RSCLK, .offset = 10}, |
210 | {P_SPI0_SSEL6, 5}, {P_UART1_RX, 4}, {P_UART1_TX, 4}, {P_TMR6, 4}, | 280 | {.res = P_SPORT1_RFS, .offset = 10}, |
211 | {P_TMR7, 4}, {P_UART0_RX, 3}, {P_UART0_TX, 3}, {P_DMAR0, 3}, | 281 | {.res = P_SPORT1_DRPRI, .offset = 10}, |
212 | {P_DMAR1, 3}, {P_SPORT0_DTSEC, 1}, {P_SPORT0_DRSEC, 1}, | 282 | {.res = P_PPI0_D8, .offset = 9}, |
213 | {P_CAN0_RX, 1}, {P_CAN0_TX, 1}, {P_SPI0_SSEL7, 1}, | 283 | {.res = P_PPI0_D9, .offset = 9}, |
214 | {P_SPORT0_TFS, 0}, {P_SPORT0_DTPRI, 0}, {P_SPI0_SSEL2, 0}, | 284 | {.res = P_SPORT1_DRSEC, .offset = 9}, |
215 | {P_SPI0_SSEL3, 0} | 285 | {.res = P_SPORT1_DTSEC, .offset = 9}, |
286 | {.res = P_TMR2, .offset = 8}, | ||
287 | {.res = P_PPI0_FS3, .offset = 8}, | ||
288 | {.res = P_TMR3, .offset = 7}, | ||
289 | {.res = P_SPI0_SSEL4, .offset = 7}, | ||
290 | {.res = P_TMR4, .offset = 6}, | ||
291 | {.res = P_SPI0_SSEL5, .offset = 6}, | ||
292 | {.res = P_TMR5, .offset = 5}, | ||
293 | {.res = P_SPI0_SSEL6, .offset = 5}, | ||
294 | {.res = P_UART1_RX, .offset = 4}, | ||
295 | {.res = P_UART1_TX, .offset = 4}, | ||
296 | {.res = P_TMR6, .offset = 4}, | ||
297 | {.res = P_TMR7, .offset = 4}, | ||
298 | {.res = P_UART0_RX, .offset = 3}, | ||
299 | {.res = P_UART0_TX, .offset = 3}, | ||
300 | {.res = P_DMAR0, .offset = 3}, | ||
301 | {.res = P_DMAR1, .offset = 3}, | ||
302 | {.res = P_SPORT0_DTSEC, .offset = 1}, | ||
303 | {.res = P_SPORT0_DRSEC, .offset = 1}, | ||
304 | {.res = P_CAN0_RX, .offset = 1}, | ||
305 | {.res = P_CAN0_TX, .offset = 1}, | ||
306 | {.res = P_SPI0_SSEL7, .offset = 1}, | ||
307 | {.res = P_SPORT0_TFS, .offset = 0}, | ||
308 | {.res = P_SPORT0_DTPRI, .offset = 0}, | ||
309 | {.res = P_SPI0_SSEL2, .offset = 0}, | ||
310 | {.res = P_SPI0_SSEL3, .offset = 0}, | ||
216 | }; | 311 | }; |
217 | 312 | ||
218 | static void portmux_setup(unsigned short per, unsigned short function) | 313 | static void portmux_setup(unsigned short per, unsigned short function) |
219 | { | 314 | { |
220 | u16 y, muxreg, offset; | 315 | u16 y, offset, muxreg; |
221 | 316 | ||
222 | for (y = 0; y < PMUX_LUT_ENTRIES; y++) { | 317 | for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) { |
223 | if (port_mux_lut[y][PMUX_LUT_RES] == per) { | 318 | if (port_mux_lut[y].res == per) { |
224 | 319 | ||
225 | /* SET PORTMUX REG */ | 320 | /* SET PORTMUX REG */ |
226 | 321 | ||
227 | offset = port_mux_lut[y][PMUX_LUT_OFFSET]; | 322 | offset = port_mux_lut[y].offset; |
228 | muxreg = bfin_read_PORT_MUX(); | 323 | muxreg = bfin_read_PORT_MUX(); |
229 | 324 | ||
230 | if (offset != 1) { | 325 | if (offset != 1) { |
@@ -238,18 +333,42 @@ static void portmux_setup(unsigned short per, unsigned short function) | |||
238 | } | 333 | } |
239 | } | 334 | } |
240 | } | 335 | } |
336 | #elif defined(BF548_FAMILY) | ||
337 | inline void portmux_setup(unsigned short portno, unsigned short function) | ||
338 | { | ||
339 | u32 pmux; | ||
340 | |||
341 | pmux = gpio_array[gpio_bank(portno)]->port_mux; | ||
342 | |||
343 | pmux &= ~(0x3 << (2 * gpio_sub_n(portno))); | ||
344 | pmux |= (function & 0x3) << (2 * gpio_sub_n(portno)); | ||
241 | 345 | ||
346 | gpio_array[gpio_bank(portno)]->port_mux = pmux; | ||
347 | } | ||
348 | |||
349 | inline u16 get_portmux(unsigned short portno) | ||
350 | { | ||
351 | u32 pmux; | ||
352 | |||
353 | pmux = gpio_array[gpio_bank(portno)]->port_mux; | ||
354 | |||
355 | return (pmux >> (2 * gpio_sub_n(portno)) & 0x3); | ||
356 | } | ||
242 | #else | 357 | #else |
243 | # define portmux_setup(...) do { } while (0) | 358 | # define portmux_setup(...) do { } while (0) |
244 | #endif | 359 | #endif |
245 | 360 | ||
361 | #ifndef BF548_FAMILY | ||
246 | static void default_gpio(unsigned short gpio) | 362 | static void default_gpio(unsigned short gpio) |
247 | { | 363 | { |
248 | unsigned short bank, bitmask; | 364 | unsigned short bank, bitmask; |
365 | unsigned long flags; | ||
249 | 366 | ||
250 | bank = gpio_bank(gpio); | 367 | bank = gpio_bank(gpio); |
251 | bitmask = gpio_bit(gpio); | 368 | bitmask = gpio_bit(gpio); |
252 | 369 | ||
370 | local_irq_save(flags); | ||
371 | |||
253 | gpio_bankb[bank]->maska_clear = bitmask; | 372 | gpio_bankb[bank]->maska_clear = bitmask; |
254 | gpio_bankb[bank]->maskb_clear = bitmask; | 373 | gpio_bankb[bank]->maskb_clear = bitmask; |
255 | SSYNC(); | 374 | SSYNC(); |
@@ -258,24 +377,32 @@ static void default_gpio(unsigned short gpio) | |||
258 | gpio_bankb[bank]->polar &= ~bitmask; | 377 | gpio_bankb[bank]->polar &= ~bitmask; |
259 | gpio_bankb[bank]->both &= ~bitmask; | 378 | gpio_bankb[bank]->both &= ~bitmask; |
260 | gpio_bankb[bank]->edge &= ~bitmask; | 379 | gpio_bankb[bank]->edge &= ~bitmask; |
380 | AWA_DUMMY_READ(edge); | ||
381 | local_irq_restore(flags); | ||
382 | |||
261 | } | 383 | } |
384 | #else | ||
385 | # define default_gpio(...) do { } while (0) | ||
386 | #endif | ||
262 | 387 | ||
263 | static int __init bfin_gpio_init(void) | 388 | static int __init bfin_gpio_init(void) |
264 | { | 389 | { |
265 | 390 | str_ident = kcalloc(MAX_RESOURCES, | |
266 | str_ident = kzalloc(RESOURCE_LABEL_SIZE * 256, GFP_KERNEL); | 391 | sizeof(struct str_ident), GFP_KERNEL); |
267 | if (!str_ident) | 392 | if (str_ident == NULL) |
268 | return -ENOMEM; | 393 | return -ENOMEM; |
269 | 394 | ||
395 | memset(str_ident, 0, MAX_RESOURCES * sizeof(struct str_ident)); | ||
396 | |||
270 | printk(KERN_INFO "Blackfin GPIO Controller\n"); | 397 | printk(KERN_INFO "Blackfin GPIO Controller\n"); |
271 | 398 | ||
272 | return 0; | 399 | return 0; |
273 | 400 | ||
274 | } | 401 | } |
275 | |||
276 | arch_initcall(bfin_gpio_init); | 402 | arch_initcall(bfin_gpio_init); |
277 | 403 | ||
278 | 404 | ||
405 | #ifndef BF548_FAMILY | ||
279 | /*********************************************************** | 406 | /*********************************************************** |
280 | * | 407 | * |
281 | * FUNCTIONS: Blackfin General Purpose Ports Access Functions | 408 | * FUNCTIONS: Blackfin General Purpose Ports Access Functions |
@@ -305,6 +432,7 @@ void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ | |||
305 | gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ | 432 | gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ |
306 | else \ | 433 | else \ |
307 | gpio_bankb[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \ | 434 | gpio_bankb[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \ |
435 | AWA_DUMMY_READ(name); \ | ||
308 | local_irq_restore(flags); \ | 436 | local_irq_restore(flags); \ |
309 | } \ | 437 | } \ |
310 | EXPORT_SYMBOL(set_gpio_ ## name); | 438 | EXPORT_SYMBOL(set_gpio_ ## name); |
@@ -316,6 +444,22 @@ SET_GPIO(edge) | |||
316 | SET_GPIO(both) | 444 | SET_GPIO(both) |
317 | 445 | ||
318 | 446 | ||
447 | #if ANOMALY_05000311 || ANOMALY_05000323 | ||
448 | #define SET_GPIO_SC(name) \ | ||
449 | void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ | ||
450 | { \ | ||
451 | unsigned long flags; \ | ||
452 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); \ | ||
453 | local_irq_save(flags); \ | ||
454 | if (arg) \ | ||
455 | gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ | ||
456 | else \ | ||
457 | gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ | ||
458 | AWA_DUMMY_READ(name); \ | ||
459 | local_irq_restore(flags); \ | ||
460 | } \ | ||
461 | EXPORT_SYMBOL(set_gpio_ ## name); | ||
462 | #else | ||
319 | #define SET_GPIO_SC(name) \ | 463 | #define SET_GPIO_SC(name) \ |
320 | void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ | 464 | void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ |
321 | { \ | 465 | { \ |
@@ -326,37 +470,20 @@ void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ | |||
326 | gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ | 470 | gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ |
327 | } \ | 471 | } \ |
328 | EXPORT_SYMBOL(set_gpio_ ## name); | 472 | EXPORT_SYMBOL(set_gpio_ ## name); |
473 | #endif | ||
329 | 474 | ||
330 | SET_GPIO_SC(maska) | 475 | SET_GPIO_SC(maska) |
331 | SET_GPIO_SC(maskb) | 476 | SET_GPIO_SC(maskb) |
332 | |||
333 | #if defined(ANOMALY_05000311) | ||
334 | void set_gpio_data(unsigned short gpio, unsigned short arg) | ||
335 | { | ||
336 | unsigned long flags; | ||
337 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); | ||
338 | local_irq_save(flags); | ||
339 | if (arg) | ||
340 | gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); | ||
341 | else | ||
342 | gpio_bankb[gpio_bank(gpio)]->data_clear = gpio_bit(gpio); | ||
343 | bfin_read_CHIPID(); | ||
344 | local_irq_restore(flags); | ||
345 | } | ||
346 | EXPORT_SYMBOL(set_gpio_data); | ||
347 | #else | ||
348 | SET_GPIO_SC(data) | 477 | SET_GPIO_SC(data) |
349 | #endif | ||
350 | |||
351 | 478 | ||
352 | #if defined(ANOMALY_05000311) | 479 | #if ANOMALY_05000311 || ANOMALY_05000323 |
353 | void set_gpio_toggle(unsigned short gpio) | 480 | void set_gpio_toggle(unsigned short gpio) |
354 | { | 481 | { |
355 | unsigned long flags; | 482 | unsigned long flags; |
356 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); | 483 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); |
357 | local_irq_save(flags); | 484 | local_irq_save(flags); |
358 | gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); | 485 | gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); |
359 | bfin_read_CHIPID(); | 486 | AWA_DUMMY_READ(toggle); |
360 | local_irq_restore(flags); | 487 | local_irq_restore(flags); |
361 | } | 488 | } |
362 | #else | 489 | #else |
@@ -371,13 +498,27 @@ EXPORT_SYMBOL(set_gpio_toggle); | |||
371 | 498 | ||
372 | /*Set current PORT date (16-bit word)*/ | 499 | /*Set current PORT date (16-bit word)*/ |
373 | 500 | ||
501 | #if ANOMALY_05000311 || ANOMALY_05000323 | ||
374 | #define SET_GPIO_P(name) \ | 502 | #define SET_GPIO_P(name) \ |
375 | void set_gpiop_ ## name(unsigned short gpio, unsigned short arg) \ | 503 | void set_gpiop_ ## name(unsigned short gpio, unsigned short arg) \ |
376 | { \ | 504 | { \ |
505 | unsigned long flags; \ | ||
506 | local_irq_save(flags); \ | ||
377 | gpio_bankb[gpio_bank(gpio)]->name = arg; \ | 507 | gpio_bankb[gpio_bank(gpio)]->name = arg; \ |
508 | AWA_DUMMY_READ(name); \ | ||
509 | local_irq_restore(flags); \ | ||
378 | } \ | 510 | } \ |
379 | EXPORT_SYMBOL(set_gpiop_ ## name); | 511 | EXPORT_SYMBOL(set_gpiop_ ## name); |
512 | #else | ||
513 | #define SET_GPIO_P(name) \ | ||
514 | void set_gpiop_ ## name(unsigned short gpio, unsigned short arg) \ | ||
515 | { \ | ||
516 | gpio_bankb[gpio_bank(gpio)]->name = arg; \ | ||
517 | } \ | ||
518 | EXPORT_SYMBOL(set_gpiop_ ## name); | ||
519 | #endif | ||
380 | 520 | ||
521 | SET_GPIO_P(data) | ||
381 | SET_GPIO_P(dir) | 522 | SET_GPIO_P(dir) |
382 | SET_GPIO_P(inen) | 523 | SET_GPIO_P(inen) |
383 | SET_GPIO_P(polar) | 524 | SET_GPIO_P(polar) |
@@ -387,31 +528,30 @@ SET_GPIO_P(maska) | |||
387 | SET_GPIO_P(maskb) | 528 | SET_GPIO_P(maskb) |
388 | 529 | ||
389 | 530 | ||
390 | #if defined(ANOMALY_05000311) | ||
391 | void set_gpiop_data(unsigned short gpio, unsigned short arg) | ||
392 | { | ||
393 | unsigned long flags; | ||
394 | local_irq_save(flags); | ||
395 | gpio_bankb[gpio_bank(gpio)]->data = arg; | ||
396 | bfin_read_CHIPID(); | ||
397 | local_irq_restore(flags); | ||
398 | } | ||
399 | EXPORT_SYMBOL(set_gpiop_data); | ||
400 | #else | ||
401 | SET_GPIO_P(data) | ||
402 | #endif | ||
403 | |||
404 | |||
405 | |||
406 | /* Get a specific bit */ | 531 | /* Get a specific bit */ |
407 | 532 | #if ANOMALY_05000311 || ANOMALY_05000323 | |
533 | #define GET_GPIO(name) \ | ||
534 | unsigned short get_gpio_ ## name(unsigned short gpio) \ | ||
535 | { \ | ||
536 | unsigned long flags; \ | ||
537 | unsigned short ret; \ | ||
538 | local_irq_save(flags); \ | ||
539 | ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \ | ||
540 | AWA_DUMMY_READ(name); \ | ||
541 | local_irq_restore(flags); \ | ||
542 | return ret; \ | ||
543 | } \ | ||
544 | EXPORT_SYMBOL(get_gpio_ ## name); | ||
545 | #else | ||
408 | #define GET_GPIO(name) \ | 546 | #define GET_GPIO(name) \ |
409 | unsigned short get_gpio_ ## name(unsigned short gpio) \ | 547 | unsigned short get_gpio_ ## name(unsigned short gpio) \ |
410 | { \ | 548 | { \ |
411 | return (0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio))); \ | 549 | return (0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio))); \ |
412 | } \ | 550 | } \ |
413 | EXPORT_SYMBOL(get_gpio_ ## name); | 551 | EXPORT_SYMBOL(get_gpio_ ## name); |
552 | #endif | ||
414 | 553 | ||
554 | GET_GPIO(data) | ||
415 | GET_GPIO(dir) | 555 | GET_GPIO(dir) |
416 | GET_GPIO(inen) | 556 | GET_GPIO(inen) |
417 | GET_GPIO(polar) | 557 | GET_GPIO(polar) |
@@ -420,33 +560,31 @@ GET_GPIO(both) | |||
420 | GET_GPIO(maska) | 560 | GET_GPIO(maska) |
421 | GET_GPIO(maskb) | 561 | GET_GPIO(maskb) |
422 | 562 | ||
423 | |||
424 | #if defined(ANOMALY_05000311) | ||
425 | unsigned short get_gpio_data(unsigned short gpio) | ||
426 | { | ||
427 | unsigned long flags; | ||
428 | unsigned short ret; | ||
429 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); | ||
430 | local_irq_save(flags); | ||
431 | ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)); | ||
432 | bfin_read_CHIPID(); | ||
433 | local_irq_restore(flags); | ||
434 | return ret; | ||
435 | } | ||
436 | EXPORT_SYMBOL(get_gpio_data); | ||
437 | #else | ||
438 | GET_GPIO(data) | ||
439 | #endif | ||
440 | |||
441 | /*Get current PORT date (16-bit word)*/ | 563 | /*Get current PORT date (16-bit word)*/ |
442 | 564 | ||
565 | #if ANOMALY_05000311 || ANOMALY_05000323 | ||
566 | #define GET_GPIO_P(name) \ | ||
567 | unsigned short get_gpiop_ ## name(unsigned short gpio) \ | ||
568 | { \ | ||
569 | unsigned long flags; \ | ||
570 | unsigned short ret; \ | ||
571 | local_irq_save(flags); \ | ||
572 | ret = (gpio_bankb[gpio_bank(gpio)]->name); \ | ||
573 | AWA_DUMMY_READ(name); \ | ||
574 | local_irq_restore(flags); \ | ||
575 | return ret; \ | ||
576 | } \ | ||
577 | EXPORT_SYMBOL(get_gpiop_ ## name); | ||
578 | #else | ||
443 | #define GET_GPIO_P(name) \ | 579 | #define GET_GPIO_P(name) \ |
444 | unsigned short get_gpiop_ ## name(unsigned short gpio) \ | 580 | unsigned short get_gpiop_ ## name(unsigned short gpio) \ |
445 | { \ | 581 | { \ |
446 | return (gpio_bankb[gpio_bank(gpio)]->name);\ | 582 | return (gpio_bankb[gpio_bank(gpio)]->name);\ |
447 | } \ | 583 | } \ |
448 | EXPORT_SYMBOL(get_gpiop_ ## name); | 584 | EXPORT_SYMBOL(get_gpiop_ ## name); |
585 | #endif | ||
449 | 586 | ||
587 | GET_GPIO_P(data) | ||
450 | GET_GPIO_P(dir) | 588 | GET_GPIO_P(dir) |
451 | GET_GPIO_P(inen) | 589 | GET_GPIO_P(inen) |
452 | GET_GPIO_P(polar) | 590 | GET_GPIO_P(polar) |
@@ -455,21 +593,6 @@ GET_GPIO_P(both) | |||
455 | GET_GPIO_P(maska) | 593 | GET_GPIO_P(maska) |
456 | GET_GPIO_P(maskb) | 594 | GET_GPIO_P(maskb) |
457 | 595 | ||
458 | #if defined(ANOMALY_05000311) | ||
459 | unsigned short get_gpiop_data(unsigned short gpio) | ||
460 | { | ||
461 | unsigned long flags; | ||
462 | unsigned short ret; | ||
463 | local_irq_save(flags); | ||
464 | ret = gpio_bankb[gpio_bank(gpio)]->data; | ||
465 | bfin_read_CHIPID(); | ||
466 | local_irq_restore(flags); | ||
467 | return ret; | ||
468 | } | ||
469 | EXPORT_SYMBOL(get_gpiop_data); | ||
470 | #else | ||
471 | GET_GPIO_P(data) | ||
472 | #endif | ||
473 | 596 | ||
474 | #ifdef CONFIG_PM | 597 | #ifdef CONFIG_PM |
475 | /*********************************************************** | 598 | /*********************************************************** |
@@ -593,6 +716,8 @@ u32 gpio_pm_setup(void) | |||
593 | } | 716 | } |
594 | } | 717 | } |
595 | 718 | ||
719 | AWA_DUMMY_READ(maskb_set); | ||
720 | |||
596 | if (sic_iwr) | 721 | if (sic_iwr) |
597 | return sic_iwr; | 722 | return sic_iwr; |
598 | else | 723 | else |
@@ -624,12 +749,99 @@ void gpio_pm_restore(void) | |||
624 | 749 | ||
625 | gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb; | 750 | gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb; |
626 | } | 751 | } |
752 | AWA_DUMMY_READ(maskb); | ||
627 | } | 753 | } |
628 | 754 | ||
629 | #endif | 755 | #endif |
756 | #endif /* BF548_FAMILY */ | ||
630 | 757 | ||
758 | /*********************************************************** | ||
759 | * | ||
760 | * FUNCTIONS: Blackfin Peripheral Resource Allocation | ||
761 | * and PortMux Setup | ||
762 | * | ||
763 | * INPUTS/OUTPUTS: | ||
764 | * per Peripheral Identifier | ||
765 | * label String | ||
766 | * | ||
767 | * DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API | ||
768 | * | ||
769 | * CAUTION: | ||
770 | ************************************************************* | ||
771 | * MODIFICATION HISTORY : | ||
772 | **************************************************************/ | ||
773 | |||
774 | #ifdef BF548_FAMILY | ||
775 | int peripheral_request(unsigned short per, const char *label) | ||
776 | { | ||
777 | unsigned long flags; | ||
778 | unsigned short ident = P_IDENT(per); | ||
779 | |||
780 | /* | ||
781 | * Don't cares are pins with only one dedicated function | ||
782 | */ | ||
783 | |||
784 | if (per & P_DONTCARE) | ||
785 | return 0; | ||
786 | |||
787 | if (!(per & P_DEFINED)) | ||
788 | return -ENODEV; | ||
789 | |||
790 | if (check_gpio(ident) < 0) | ||
791 | return -EINVAL; | ||
792 | |||
793 | local_irq_save(flags); | ||
794 | |||
795 | if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) { | ||
796 | printk(KERN_ERR | ||
797 | "%s: Peripheral %d is already reserved as GPIO by %s !\n", | ||
798 | __FUNCTION__, ident, get_label(ident)); | ||
799 | dump_stack(); | ||
800 | local_irq_restore(flags); | ||
801 | return -EBUSY; | ||
802 | } | ||
803 | |||
804 | if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) { | ||
805 | |||
806 | u16 funct = get_portmux(ident); | ||
807 | |||
808 | /* | ||
809 | * Pin functions like AMC address strobes my | ||
810 | * be requested and used by several drivers | ||
811 | */ | ||
812 | |||
813 | if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) { | ||
814 | |||
815 | /* | ||
816 | * Allow that the identical pin function can | ||
817 | * be requested from the same driver twice | ||
818 | */ | ||
819 | |||
820 | if (cmp_label(ident, label) == 0) | ||
821 | goto anyway; | ||
631 | 822 | ||
823 | printk(KERN_ERR | ||
824 | "%s: Peripheral %d function %d is already reserved by %s !\n", | ||
825 | __FUNCTION__, ident, P_FUNCT2MUX(per), get_label(ident)); | ||
826 | dump_stack(); | ||
827 | local_irq_restore(flags); | ||
828 | return -EBUSY; | ||
829 | } | ||
830 | } | ||
632 | 831 | ||
832 | anyway: | ||
833 | reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident); | ||
834 | |||
835 | portmux_setup(ident, P_FUNCT2MUX(per)); | ||
836 | port_setup(ident, PERIPHERAL_USAGE); | ||
837 | |||
838 | local_irq_restore(flags); | ||
839 | set_label(ident, label); | ||
840 | |||
841 | return 0; | ||
842 | } | ||
843 | EXPORT_SYMBOL(peripheral_request); | ||
844 | #else | ||
633 | 845 | ||
634 | int peripheral_request(unsigned short per, const char *label) | 846 | int peripheral_request(unsigned short per, const char *label) |
635 | { | 847 | { |
@@ -680,7 +892,7 @@ int peripheral_request(unsigned short per, const char *label) | |||
680 | 892 | ||
681 | printk(KERN_ERR | 893 | printk(KERN_ERR |
682 | "%s: Peripheral %d function %d is already" | 894 | "%s: Peripheral %d function %d is already" |
683 | "reserved by %s !\n", | 895 | " reserved by %s !\n", |
684 | __FUNCTION__, ident, P_FUNCT2MUX(per), | 896 | __FUNCTION__, ident, P_FUNCT2MUX(per), |
685 | get_label(ident)); | 897 | get_label(ident)); |
686 | dump_stack(); | 898 | dump_stack(); |
@@ -691,8 +903,6 @@ int peripheral_request(unsigned short per, const char *label) | |||
691 | } | 903 | } |
692 | 904 | ||
693 | anyway: | 905 | anyway: |
694 | |||
695 | |||
696 | portmux_setup(per, P_FUNCT2MUX(per)); | 906 | portmux_setup(per, P_FUNCT2MUX(per)); |
697 | 907 | ||
698 | port_setup(ident, PERIPHERAL_USAGE); | 908 | port_setup(ident, PERIPHERAL_USAGE); |
@@ -704,6 +914,7 @@ anyway: | |||
704 | return 0; | 914 | return 0; |
705 | } | 915 | } |
706 | EXPORT_SYMBOL(peripheral_request); | 916 | EXPORT_SYMBOL(peripheral_request); |
917 | #endif | ||
707 | 918 | ||
708 | int peripheral_request_list(unsigned short per[], const char *label) | 919 | int peripheral_request_list(unsigned short per[], const char *label) |
709 | { | 920 | { |
@@ -711,9 +922,15 @@ int peripheral_request_list(unsigned short per[], const char *label) | |||
711 | int ret; | 922 | int ret; |
712 | 923 | ||
713 | for (cnt = 0; per[cnt] != 0; cnt++) { | 924 | for (cnt = 0; per[cnt] != 0; cnt++) { |
925 | |||
714 | ret = peripheral_request(per[cnt], label); | 926 | ret = peripheral_request(per[cnt], label); |
715 | if (ret < 0) | 927 | |
716 | return ret; | 928 | if (ret < 0) { |
929 | for ( ; cnt > 0; cnt--) { | ||
930 | peripheral_free(per[cnt - 1]); | ||
931 | } | ||
932 | return ret; | ||
933 | } | ||
717 | } | 934 | } |
718 | 935 | ||
719 | return 0; | 936 | return 0; |
@@ -748,6 +965,8 @@ void peripheral_free(unsigned short per) | |||
748 | 965 | ||
749 | reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident); | 966 | reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident); |
750 | 967 | ||
968 | set_label(ident, "free"); | ||
969 | |||
751 | local_irq_restore(flags); | 970 | local_irq_restore(flags); |
752 | } | 971 | } |
753 | EXPORT_SYMBOL(peripheral_free); | 972 | EXPORT_SYMBOL(peripheral_free); |
@@ -768,8 +987,8 @@ EXPORT_SYMBOL(peripheral_free_list); | |||
768 | * FUNCTIONS: Blackfin GPIO Driver | 987 | * FUNCTIONS: Blackfin GPIO Driver |
769 | * | 988 | * |
770 | * INPUTS/OUTPUTS: | 989 | * INPUTS/OUTPUTS: |
771 | * gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS | 990 | * gpio PIO Number between 0 and MAX_BLACKFIN_GPIOS |
772 | * | 991 | * label String |
773 | * | 992 | * |
774 | * DESCRIPTION: Blackfin GPIO Driver API | 993 | * DESCRIPTION: Blackfin GPIO Driver API |
775 | * | 994 | * |
@@ -787,17 +1006,39 @@ int gpio_request(unsigned short gpio, const char *label) | |||
787 | 1006 | ||
788 | local_irq_save(flags); | 1007 | local_irq_save(flags); |
789 | 1008 | ||
1009 | /* | ||
1010 | * Allow that the identical GPIO can | ||
1011 | * be requested from the same driver twice | ||
1012 | * Do nothing and return - | ||
1013 | */ | ||
1014 | |||
1015 | if (cmp_label(gpio, label) == 0) { | ||
1016 | local_irq_restore(flags); | ||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
790 | if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { | 1020 | if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { |
791 | printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio); | 1021 | printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n", |
1022 | gpio, get_label(gpio)); | ||
792 | dump_stack(); | 1023 | dump_stack(); |
793 | local_irq_restore(flags); | 1024 | local_irq_restore(flags); |
794 | return -EBUSY; | 1025 | return -EBUSY; |
795 | } | 1026 | } |
1027 | if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) { | ||
1028 | printk(KERN_ERR | ||
1029 | "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", | ||
1030 | gpio, get_label(gpio)); | ||
1031 | dump_stack(); | ||
1032 | local_irq_restore(flags); | ||
1033 | return -EBUSY; | ||
1034 | } | ||
1035 | |||
796 | reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); | 1036 | reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); |
797 | 1037 | ||
798 | local_irq_restore(flags); | 1038 | local_irq_restore(flags); |
799 | 1039 | ||
800 | port_setup(gpio, GPIO_USAGE); | 1040 | port_setup(gpio, GPIO_USAGE); |
1041 | set_label(gpio, label); | ||
801 | 1042 | ||
802 | return 0; | 1043 | return 0; |
803 | } | 1044 | } |
@@ -823,10 +1064,57 @@ void gpio_free(unsigned short gpio) | |||
823 | 1064 | ||
824 | reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); | 1065 | reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); |
825 | 1066 | ||
1067 | set_label(gpio, "free"); | ||
1068 | |||
826 | local_irq_restore(flags); | 1069 | local_irq_restore(flags); |
827 | } | 1070 | } |
828 | EXPORT_SYMBOL(gpio_free); | 1071 | EXPORT_SYMBOL(gpio_free); |
829 | 1072 | ||
1073 | #ifdef BF548_FAMILY | ||
1074 | void gpio_direction_input(unsigned short gpio) | ||
1075 | { | ||
1076 | unsigned long flags; | ||
1077 | |||
1078 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); | ||
1079 | |||
1080 | local_irq_save(flags); | ||
1081 | gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio); | ||
1082 | gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio); | ||
1083 | local_irq_restore(flags); | ||
1084 | } | ||
1085 | EXPORT_SYMBOL(gpio_direction_input); | ||
1086 | |||
1087 | void gpio_direction_output(unsigned short gpio) | ||
1088 | { | ||
1089 | unsigned long flags; | ||
1090 | |||
1091 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); | ||
1092 | |||
1093 | local_irq_save(flags); | ||
1094 | gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio); | ||
1095 | gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio); | ||
1096 | local_irq_restore(flags); | ||
1097 | } | ||
1098 | EXPORT_SYMBOL(gpio_direction_output); | ||
1099 | |||
1100 | void gpio_set_value(unsigned short gpio, unsigned short arg) | ||
1101 | { | ||
1102 | if (arg) | ||
1103 | gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio); | ||
1104 | else | ||
1105 | gpio_array[gpio_bank(gpio)]->port_clear = gpio_bit(gpio); | ||
1106 | |||
1107 | } | ||
1108 | EXPORT_SYMBOL(gpio_set_value); | ||
1109 | |||
1110 | unsigned short gpio_get_value(unsigned short gpio) | ||
1111 | { | ||
1112 | return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio))); | ||
1113 | } | ||
1114 | EXPORT_SYMBOL(gpio_get_value); | ||
1115 | |||
1116 | #else | ||
1117 | |||
830 | void gpio_direction_input(unsigned short gpio) | 1118 | void gpio_direction_input(unsigned short gpio) |
831 | { | 1119 | { |
832 | unsigned long flags; | 1120 | unsigned long flags; |
@@ -836,6 +1124,7 @@ void gpio_direction_input(unsigned short gpio) | |||
836 | local_irq_save(flags); | 1124 | local_irq_save(flags); |
837 | gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); | 1125 | gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); |
838 | gpio_bankb[gpio_bank(gpio)]->inen |= gpio_bit(gpio); | 1126 | gpio_bankb[gpio_bank(gpio)]->inen |= gpio_bit(gpio); |
1127 | AWA_DUMMY_READ(inen); | ||
839 | local_irq_restore(flags); | 1128 | local_irq_restore(flags); |
840 | } | 1129 | } |
841 | EXPORT_SYMBOL(gpio_direction_input); | 1130 | EXPORT_SYMBOL(gpio_direction_input); |
@@ -849,6 +1138,28 @@ void gpio_direction_output(unsigned short gpio) | |||
849 | local_irq_save(flags); | 1138 | local_irq_save(flags); |
850 | gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); | 1139 | gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); |
851 | gpio_bankb[gpio_bank(gpio)]->dir |= gpio_bit(gpio); | 1140 | gpio_bankb[gpio_bank(gpio)]->dir |= gpio_bit(gpio); |
1141 | AWA_DUMMY_READ(dir); | ||
852 | local_irq_restore(flags); | 1142 | local_irq_restore(flags); |
853 | } | 1143 | } |
854 | EXPORT_SYMBOL(gpio_direction_output); | 1144 | EXPORT_SYMBOL(gpio_direction_output); |
1145 | |||
1146 | /* If we are booting from SPI and our board lacks a strong enough pull up, | ||
1147 | * the core can reset and execute the bootrom faster than the resistor can | ||
1148 | * pull the signal logically high. To work around this (common) error in | ||
1149 | * board design, we explicitly set the pin back to GPIO mode, force /CS | ||
1150 | * high, and wait for the electrons to do their thing. | ||
1151 | * | ||
1152 | * This function only makes sense to be called from reset code, but it | ||
1153 | * lives here as we need to force all the GPIO states w/out going through | ||
1154 | * BUG() checks and such. | ||
1155 | */ | ||
1156 | void bfin_gpio_reset_spi0_ssel1(void) | ||
1157 | { | ||
1158 | u16 gpio = P_IDENT(P_SPI0_SSEL1); | ||
1159 | |||
1160 | port_setup(gpio, GPIO_USAGE); | ||
1161 | gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); | ||
1162 | udelay(1); | ||
1163 | } | ||
1164 | |||
1165 | #endif /*BF548_FAMILY */ | ||