blob: f9306bb5aedeb5c1ead3335ad08edfb129abd03c [file] [log] [blame]
Bryan Wu1394f032007-05-06 14:50:22 -07001/*
Robin Getz96f10502009-09-24 14:11:24 +00002 * GPIO Abstraction Layer
Bryan Wu1394f032007-05-06 14:50:22 -07003 *
steven miao05bbec32010-09-17 03:03:17 +00004 * Copyright 2006-2010 Analog Devices Inc.
Bryan Wu1394f032007-05-06 14:50:22 -07005 *
Robin Getz96f10502009-09-24 14:11:24 +00006 * Licensed under the GPL-2 or later
Bryan Wu1394f032007-05-06 14:50:22 -07007 */
8
Mike Frysinger168f1212007-10-11 00:22:35 +08009#include <linux/delay.h>
Bryan Wu1394f032007-05-06 14:50:22 -070010#include <linux/module.h>
11#include <linux/err.h>
Mike Frysinger1545a112007-12-24 16:54:48 +080012#include <linux/proc_fs.h>
Bryan Wu1394f032007-05-06 14:50:22 -070013#include <asm/blackfin.h>
14#include <asm/gpio.h>
Michael Hennerichc58c2142007-10-04 00:35:05 +080015#include <asm/portmux.h>
Bryan Wu1394f032007-05-06 14:50:22 -070016#include <linux/irq.h>
Mike Frysinger6327a572011-04-15 03:06:59 -040017#include <asm/irq_handler.h>
Bryan Wu1394f032007-05-06 14:50:22 -070018
Michael Hennerich2b393312007-10-10 16:58:49 +080019#if ANOMALY_05000311 || ANOMALY_05000323
20enum {
21 AWA_data = SYSCR,
22 AWA_data_clear = SYSCR,
23 AWA_data_set = SYSCR,
24 AWA_toggle = SYSCR,
Graf Yang6ed83942008-04-24 04:43:14 +080025 AWA_maska = BFIN_UART_SCR,
26 AWA_maska_clear = BFIN_UART_SCR,
27 AWA_maska_set = BFIN_UART_SCR,
28 AWA_maska_toggle = BFIN_UART_SCR,
29 AWA_maskb = BFIN_UART_GCTL,
30 AWA_maskb_clear = BFIN_UART_GCTL,
31 AWA_maskb_set = BFIN_UART_GCTL,
32 AWA_maskb_toggle = BFIN_UART_GCTL,
Michael Hennerich2b393312007-10-10 16:58:49 +080033 AWA_dir = SPORT1_STAT,
34 AWA_polar = SPORT1_STAT,
35 AWA_edge = SPORT1_STAT,
36 AWA_both = SPORT1_STAT,
37#if ANOMALY_05000311
38 AWA_inen = TIMER_ENABLE,
39#elif ANOMALY_05000323
40 AWA_inen = DMA1_1_CONFIG,
41#endif
42};
43 /* Anomaly Workaround */
44#define AWA_DUMMY_READ(name) bfin_read16(AWA_ ## name)
45#else
46#define AWA_DUMMY_READ(...) do { } while (0)
47#endif
48
Mike Frysingerf5563092009-02-04 16:49:45 +080049static struct gpio_port_t * const gpio_array[] = {
Michael Hennerichdc26aec2008-11-18 17:48:22 +080050#if defined(BF533_FAMILY) || defined(BF538_FAMILY)
Bryan Wu1394f032007-05-06 14:50:22 -070051 (struct gpio_port_t *) FIO_FLAG_D,
Mike Frysinger269647d2009-03-28 20:32:57 +080052#elif defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Bryan Wu1394f032007-05-06 14:50:22 -070053 (struct gpio_port_t *) PORTFIO,
54 (struct gpio_port_t *) PORTGIO,
55 (struct gpio_port_t *) PORTHIO,
Mike Frysingerf5563092009-02-04 16:49:45 +080056#elif defined(BF561_FAMILY)
57 (struct gpio_port_t *) FIO0_FLAG_D,
58 (struct gpio_port_t *) FIO1_FLAG_D,
59 (struct gpio_port_t *) FIO2_FLAG_D,
Mike Frysinger269647d2009-03-28 20:32:57 +080060#elif defined(CONFIG_BF54x)
Mike Frysingerf5563092009-02-04 16:49:45 +080061 (struct gpio_port_t *)PORTA_FER,
62 (struct gpio_port_t *)PORTB_FER,
63 (struct gpio_port_t *)PORTC_FER,
64 (struct gpio_port_t *)PORTD_FER,
65 (struct gpio_port_t *)PORTE_FER,
66 (struct gpio_port_t *)PORTF_FER,
67 (struct gpio_port_t *)PORTG_FER,
68 (struct gpio_port_t *)PORTH_FER,
69 (struct gpio_port_t *)PORTI_FER,
70 (struct gpio_port_t *)PORTJ_FER,
71#else
72# error no gpio arrays defined
73#endif
Bryan Wu1394f032007-05-06 14:50:22 -070074};
75
Mike Frysinger269647d2009-03-28 20:32:57 +080076#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +080077static unsigned short * const port_fer[] = {
Bryan Wu1394f032007-05-06 14:50:22 -070078 (unsigned short *) PORTF_FER,
79 (unsigned short *) PORTG_FER,
80 (unsigned short *) PORTH_FER,
81};
Bryan Wu1394f032007-05-06 14:50:22 -070082
Mike Frysingerf5563092009-02-04 16:49:45 +080083# if !defined(BF537_FAMILY)
84static unsigned short * const port_mux[] = {
Michael Hennerich59003142007-10-21 16:54:27 +080085 (unsigned short *) PORTF_MUX,
86 (unsigned short *) PORTG_MUX,
87 (unsigned short *) PORTH_MUX,
88};
89
90static const
Graf Yang0ce5eaf2009-02-04 16:49:45 +080091u8 pmux_offset[][16] = {
Mike Frysinger269647d2009-03-28 20:32:57 +080092# if defined(CONFIG_BF52x)
Graf Yang0ce5eaf2009-02-04 16:49:45 +080093 { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */
94 { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */
95 { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */
Mike Frysinger269647d2009-03-28 20:32:57 +080096# elif defined(CONFIG_BF51x)
Graf Yang0ce5eaf2009-02-04 16:49:45 +080097 { 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */
98 { 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */
99 { 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */
100# endif
101};
Mike Frysingerf5563092009-02-04 16:49:45 +0800102# endif
Graf Yang0ce5eaf2009-02-04 16:49:45 +0800103
Michael Hennerich621dd242009-09-28 12:23:41 +0000104#elif defined(BF538_FAMILY)
105static unsigned short * const port_fer[] = {
106 (unsigned short *) PORTCIO_FER,
107 (unsigned short *) PORTDIO_FER,
108 (unsigned short *) PORTEIO_FER,
109};
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800110#endif
111
Mike Frysinger812ae982010-07-05 08:40:41 +0000112#define RESOURCE_LABEL_SIZE 16
Michael Hennerich8c613622007-08-03 17:48:09 +0800113
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800114static struct str_ident {
Michael Hennerich8c613622007-08-03 17:48:09 +0800115 char name[RESOURCE_LABEL_SIZE];
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800116} str_ident[MAX_RESOURCES];
Bryan Wu1394f032007-05-06 14:50:22 -0700117
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800118#if defined(CONFIG_PM)
Bryan Wu397861c2008-11-18 17:48:22 +0800119static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM];
Bryan Wu1394f032007-05-06 14:50:22 -0700120#endif
121
Mike Frysinger74c04502008-10-08 16:13:17 +0800122static void gpio_error(unsigned gpio)
Michael Hennerichacbcd262008-01-22 18:36:20 +0800123{
124 printk(KERN_ERR "bfin-gpio: GPIO %d wasn't requested!\n", gpio);
125}
126
Michael Hennerichc58c2142007-10-04 00:35:05 +0800127static void set_label(unsigned short ident, const char *label)
128{
Michael Henneriche9fae182008-10-13 11:35:22 +0800129 if (label) {
Michael Hennerich8c613622007-08-03 17:48:09 +0800130 strncpy(str_ident[ident].name, label,
Michael Hennerichc58c2142007-10-04 00:35:05 +0800131 RESOURCE_LABEL_SIZE);
Michael Hennerich8c613622007-08-03 17:48:09 +0800132 str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800133 }
134}
135
136static char *get_label(unsigned short ident)
137{
Michael Hennerich8c613622007-08-03 17:48:09 +0800138 return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN");
Michael Hennerichc58c2142007-10-04 00:35:05 +0800139}
140
141static int cmp_label(unsigned short ident, const char *label)
142{
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800143 if (label == NULL) {
144 dump_stack();
145 printk(KERN_ERR "Please provide none-null label\n");
146 }
147
Michael Henneriche9fae182008-10-13 11:35:22 +0800148 if (label)
Mike Frysinger1f7d3732008-10-28 15:47:11 +0800149 return strcmp(str_ident[ident].name, label);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800150 else
151 return -EINVAL;
152}
153
Mike Frysinger332824b2010-06-02 04:22:01 +0000154#define map_entry(m, i) reserved_##m##_map[gpio_bank(i)]
155#define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i))
156#define reserve(m, i) (map_entry(m, i) |= gpio_bit(i))
157#define unreserve(m, i) (map_entry(m, i) &= ~gpio_bit(i))
158#define DECLARE_RESERVED_MAP(m, c) static unsigned short reserved_##m##_map[c]
159
160DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM);
Michael Hennerich382dbe52010-07-13 08:26:10 +0000161DECLARE_RESERVED_MAP(peri, DIV_ROUND_UP(MAX_RESOURCES, GPIO_BANKSIZE));
Mike Frysinger332824b2010-06-02 04:22:01 +0000162DECLARE_RESERVED_MAP(gpio_irq, GPIO_BANK_NUM);
163
164inline int check_gpio(unsigned gpio)
165{
166#if defined(CONFIG_BF54x)
167 if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
168 || gpio == GPIO_PH14 || gpio == GPIO_PH15
169 || gpio == GPIO_PJ14 || gpio == GPIO_PJ15)
170 return -EINVAL;
171#endif
172 if (gpio >= MAX_BLACKFIN_GPIOS)
173 return -EINVAL;
174 return 0;
175}
176
Mike Frysingera2d03a12008-10-28 15:53:37 +0800177static void port_setup(unsigned gpio, unsigned short usage)
178{
Michael Hennerich621dd242009-09-28 12:23:41 +0000179#if defined(BF538_FAMILY)
180 /*
181 * BF538/9 Port C,D and E are special.
182 * Inverted PORT_FER polarity on CDE and no PORF_FER on F
183 * Regular PORT F GPIOs are handled here, CDE are exclusively
184 * managed by GPIOLIB
185 */
186
187 if (gpio < MAX_BLACKFIN_GPIOS || gpio >= MAX_RESOURCES)
188 return;
189
190 gpio -= MAX_BLACKFIN_GPIOS;
191
192 if (usage == GPIO_USAGE)
193 *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
194 else
195 *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
196 SSYNC();
197 return;
198#endif
199
Mike Frysingera2d03a12008-10-28 15:53:37 +0800200 if (check_gpio(gpio))
201 return;
202
Mike Frysinger269647d2009-03-28 20:32:57 +0800203#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Mike Frysingera2d03a12008-10-28 15:53:37 +0800204 if (usage == GPIO_USAGE)
205 *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
206 else
207 *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
208 SSYNC();
Mike Frysinger269647d2009-03-28 20:32:57 +0800209#elif defined(CONFIG_BF54x)
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800210 if (usage == GPIO_USAGE)
211 gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
212 else
213 gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
214 SSYNC();
Bryan Wu1394f032007-05-06 14:50:22 -0700215#endif
Mike Frysingera2d03a12008-10-28 15:53:37 +0800216}
Bryan Wu1394f032007-05-06 14:50:22 -0700217
Michael Hennerichc58c2142007-10-04 00:35:05 +0800218#ifdef BF537_FAMILY
steven miao05bbec32010-09-17 03:03:17 +0000219static const s8 port_mux[] = {
220 [GPIO_PF0] = 3,
221 [GPIO_PF1] = 3,
222 [GPIO_PF2] = 4,
223 [GPIO_PF3] = 4,
224 [GPIO_PF4] = 5,
225 [GPIO_PF5] = 6,
226 [GPIO_PF6] = 7,
227 [GPIO_PF7] = 8,
228 [GPIO_PF8 ... GPIO_PF15] = -1,
229 [GPIO_PG0 ... GPIO_PG7] = -1,
230 [GPIO_PG8] = 9,
231 [GPIO_PG9] = 9,
232 [GPIO_PG10] = 10,
233 [GPIO_PG11] = 10,
234 [GPIO_PG12] = 10,
235 [GPIO_PG13] = 11,
236 [GPIO_PG14] = 11,
237 [GPIO_PG15] = 11,
238 [GPIO_PH0 ... GPIO_PH15] = -1,
239 [PORT_PJ0 ... PORT_PJ3] = -1,
240 [PORT_PJ4] = 1,
241 [PORT_PJ5] = 1,
242 [PORT_PJ6 ... PORT_PJ9] = -1,
243 [PORT_PJ10] = 0,
244 [PORT_PJ11] = 0,
Michael Hennerichc58c2142007-10-04 00:35:05 +0800245};
246
steven miao05bbec32010-09-17 03:03:17 +0000247static int portmux_group_check(unsigned short per)
248{
249 u16 ident = P_IDENT(per);
250 u16 function = P_FUNCT2MUX(per);
251 s8 offset = port_mux[ident];
252 u16 m, pmux, pfunc;
253
254 if (offset < 0)
255 return 0;
256
257 pmux = bfin_read_PORT_MUX();
258 for (m = 0; m < ARRAY_SIZE(port_mux); ++m) {
259 if (m == ident)
260 continue;
261 if (port_mux[m] != offset)
262 continue;
263 if (!is_reserved(peri, m, 1))
264 continue;
265
266 if (offset == 1)
267 pfunc = (pmux >> offset) & 3;
268 else
269 pfunc = (pmux >> offset) & 1;
270 if (pfunc != function) {
271 pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",
272 ident, function, m, pfunc);
273 return -EINVAL;
274 }
275 }
276
277 return 0;
278}
279
Mike Frysingerf5563092009-02-04 16:49:45 +0800280static void portmux_setup(unsigned short per)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800281{
steven miao05bbec32010-09-17 03:03:17 +0000282 u16 ident = P_IDENT(per);
Mike Frysingerf5563092009-02-04 16:49:45 +0800283 u16 function = P_FUNCT2MUX(per);
steven miao05bbec32010-09-17 03:03:17 +0000284 s8 offset = port_mux[ident];
285 u16 pmux;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800286
steven miao05bbec32010-09-17 03:03:17 +0000287 if (offset == -1)
288 return;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800289
steven miao05bbec32010-09-17 03:03:17 +0000290 pmux = bfin_read_PORT_MUX();
291 if (offset != 1)
292 pmux &= ~(1 << offset);
293 else
294 pmux &= ~(3 << 1);
295 pmux |= (function << offset);
296 bfin_write_PORT_MUX(pmux);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800297}
Mike Frysinger269647d2009-03-28 20:32:57 +0800298#elif defined(CONFIG_BF54x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800299inline void portmux_setup(unsigned short per)
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800300{
Mike Frysingerf5563092009-02-04 16:49:45 +0800301 u16 ident = P_IDENT(per);
302 u16 function = P_FUNCT2MUX(per);
steven miao05bbec32010-09-17 03:03:17 +0000303 u32 pmux;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800304
Mike Frysingerf5563092009-02-04 16:49:45 +0800305 pmux = gpio_array[gpio_bank(ident)]->port_mux;
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800306
Mike Frysingerf5563092009-02-04 16:49:45 +0800307 pmux &= ~(0x3 << (2 * gpio_sub_n(ident)));
308 pmux |= (function & 0x3) << (2 * gpio_sub_n(ident));
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800309
Mike Frysingerf5563092009-02-04 16:49:45 +0800310 gpio_array[gpio_bank(ident)]->port_mux = pmux;
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800311}
312
Mike Frysingerf5563092009-02-04 16:49:45 +0800313inline u16 get_portmux(unsigned short per)
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800314{
Mike Frysingerf5563092009-02-04 16:49:45 +0800315 u16 ident = P_IDENT(per);
steven miao05bbec32010-09-17 03:03:17 +0000316 u32 pmux = gpio_array[gpio_bank(ident)]->port_mux;
Mike Frysingerf5563092009-02-04 16:49:45 +0800317 return (pmux >> (2 * gpio_sub_n(ident)) & 0x3);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800318}
steven miao05bbec32010-09-17 03:03:17 +0000319static int portmux_group_check(unsigned short per)
320{
321 return 0;
322}
Mike Frysinger269647d2009-03-28 20:32:57 +0800323#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
steven miao05bbec32010-09-17 03:03:17 +0000324static int portmux_group_check(unsigned short per)
325{
326 u16 ident = P_IDENT(per);
327 u16 function = P_FUNCT2MUX(per);
328 u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
329 u16 pin, gpiopin, pfunc;
330
331 for (pin = 0; pin < GPIO_BANKSIZE; ++pin) {
332 if (offset != pmux_offset[gpio_bank(ident)][pin])
333 continue;
334
335 gpiopin = gpio_bank(ident) * GPIO_BANKSIZE + pin;
336 if (gpiopin == ident)
337 continue;
338 if (!is_reserved(peri, gpiopin, 1))
339 continue;
340
341 pfunc = *port_mux[gpio_bank(ident)];
342 pfunc = (pfunc >> offset) & 3;
343 if (pfunc != function) {
344 pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",
345 ident, function, gpiopin, pfunc);
346 return -EINVAL;
347 }
348 }
349
350 return 0;
351}
352
Mike Frysingerf5563092009-02-04 16:49:45 +0800353inline void portmux_setup(unsigned short per)
Michael Hennerich59003142007-10-21 16:54:27 +0800354{
steven miao05bbec32010-09-17 03:03:17 +0000355 u16 ident = P_IDENT(per);
356 u16 function = P_FUNCT2MUX(per);
Michael Hennerich59003142007-10-21 16:54:27 +0800357 u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
steven miao05bbec32010-09-17 03:03:17 +0000358 u16 pmux;
Michael Hennerich59003142007-10-21 16:54:27 +0800359
360 pmux = *port_mux[gpio_bank(ident)];
steven miao05bbec32010-09-17 03:03:17 +0000361 if (((pmux >> offset) & 3) == function)
362 return;
Michael Hennerich59003142007-10-21 16:54:27 +0800363 pmux &= ~(3 << offset);
364 pmux |= (function & 3) << offset;
365 *port_mux[gpio_bank(ident)] = pmux;
366 SSYNC();
367}
Michael Hennerichc58c2142007-10-04 00:35:05 +0800368#else
369# define portmux_setup(...) do { } while (0)
steven miao05bbec32010-09-17 03:03:17 +0000370static int portmux_group_check(unsigned short per)
371{
372 return 0;
373}
Michael Hennerichc58c2142007-10-04 00:35:05 +0800374#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700375
Mike Frysinger269647d2009-03-28 20:32:57 +0800376#ifndef CONFIG_BF54x
Bryan Wu1394f032007-05-06 14:50:22 -0700377/***********************************************************
378*
379* FUNCTIONS: Blackfin General Purpose Ports Access Functions
380*
381* INPUTS/OUTPUTS:
382* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
383*
384*
385* DESCRIPTION: These functions abstract direct register access
386* to Blackfin processor General Purpose
387* Ports Regsiters
388*
389* CAUTION: These functions do not belong to the GPIO Driver API
390*************************************************************
391* MODIFICATION HISTORY :
392**************************************************************/
393
394/* Set a specific bit */
395
396#define SET_GPIO(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800397void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
Bryan Wu1394f032007-05-06 14:50:22 -0700398{ \
399 unsigned long flags; \
David Howells3b139cd2010-10-07 14:08:52 +0100400 flags = hard_local_irq_save(); \
Bryan Wu1394f032007-05-06 14:50:22 -0700401 if (arg) \
Mike Frysingerf5563092009-02-04 16:49:45 +0800402 gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
Bryan Wu1394f032007-05-06 14:50:22 -0700403 else \
Mike Frysingerf5563092009-02-04 16:49:45 +0800404 gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
Michael Hennerich2b393312007-10-10 16:58:49 +0800405 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100406 hard_local_irq_restore(flags); \
Bryan Wu1394f032007-05-06 14:50:22 -0700407} \
408EXPORT_SYMBOL(set_gpio_ ## name);
409
Mike Frysingerf5563092009-02-04 16:49:45 +0800410SET_GPIO(dir) /* set_gpio_dir() */
411SET_GPIO(inen) /* set_gpio_inen() */
412SET_GPIO(polar) /* set_gpio_polar() */
413SET_GPIO(edge) /* set_gpio_edge() */
414SET_GPIO(both) /* set_gpio_both() */
Bryan Wu1394f032007-05-06 14:50:22 -0700415
416
Michael Hennerich2b393312007-10-10 16:58:49 +0800417#define SET_GPIO_SC(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800418void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800419{ \
420 unsigned long flags; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800421 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100422 flags = hard_local_irq_save(); \
Michael Hennerich2b393312007-10-10 16:58:49 +0800423 if (arg) \
Mike Frysingerf5563092009-02-04 16:49:45 +0800424 gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
Michael Hennerich2b393312007-10-10 16:58:49 +0800425 else \
Mike Frysingerf5563092009-02-04 16:49:45 +0800426 gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
427 if (ANOMALY_05000311 || ANOMALY_05000323) { \
428 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100429 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800430 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800431} \
432EXPORT_SYMBOL(set_gpio_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700433
434SET_GPIO_SC(maska)
435SET_GPIO_SC(maskb)
Bryan Wu1394f032007-05-06 14:50:22 -0700436SET_GPIO_SC(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700437
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800438void set_gpio_toggle(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -0700439{
440 unsigned long flags;
Mike Frysingerf5563092009-02-04 16:49:45 +0800441 if (ANOMALY_05000311 || ANOMALY_05000323)
David Howells3b139cd2010-10-07 14:08:52 +0100442 flags = hard_local_irq_save();
Mike Frysingerf5563092009-02-04 16:49:45 +0800443 gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
444 if (ANOMALY_05000311 || ANOMALY_05000323) {
445 AWA_DUMMY_READ(toggle);
David Howells3b139cd2010-10-07 14:08:52 +0100446 hard_local_irq_restore(flags);
Mike Frysingerf5563092009-02-04 16:49:45 +0800447 }
Bryan Wu1394f032007-05-06 14:50:22 -0700448}
Bryan Wu1394f032007-05-06 14:50:22 -0700449EXPORT_SYMBOL(set_gpio_toggle);
450
451
452/*Set current PORT date (16-bit word)*/
453
Michael Hennerich2b393312007-10-10 16:58:49 +0800454#define SET_GPIO_P(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800455void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800456{ \
457 unsigned long flags; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800458 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100459 flags = hard_local_irq_save(); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800460 gpio_array[gpio_bank(gpio)]->name = arg; \
461 if (ANOMALY_05000311 || ANOMALY_05000323) { \
462 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100463 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800464 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800465} \
466EXPORT_SYMBOL(set_gpiop_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700467
Michael Hennerich2b393312007-10-10 16:58:49 +0800468SET_GPIO_P(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700469SET_GPIO_P(dir)
470SET_GPIO_P(inen)
471SET_GPIO_P(polar)
472SET_GPIO_P(edge)
473SET_GPIO_P(both)
474SET_GPIO_P(maska)
475SET_GPIO_P(maskb)
476
Bryan Wu1394f032007-05-06 14:50:22 -0700477/* Get a specific bit */
Michael Hennerich2b393312007-10-10 16:58:49 +0800478#define GET_GPIO(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800479unsigned short get_gpio_ ## name(unsigned gpio) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800480{ \
481 unsigned long flags; \
482 unsigned short ret; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800483 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100484 flags = hard_local_irq_save(); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800485 ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \
486 if (ANOMALY_05000311 || ANOMALY_05000323) { \
487 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100488 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800489 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800490 return ret; \
491} \
492EXPORT_SYMBOL(get_gpio_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700493
Michael Hennerich2b393312007-10-10 16:58:49 +0800494GET_GPIO(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700495GET_GPIO(dir)
496GET_GPIO(inen)
497GET_GPIO(polar)
498GET_GPIO(edge)
499GET_GPIO(both)
500GET_GPIO(maska)
501GET_GPIO(maskb)
502
Bryan Wu1394f032007-05-06 14:50:22 -0700503/*Get current PORT date (16-bit word)*/
504
Michael Hennerich2b393312007-10-10 16:58:49 +0800505#define GET_GPIO_P(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800506unsigned short get_gpiop_ ## name(unsigned gpio) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800507{ \
508 unsigned long flags; \
509 unsigned short ret; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800510 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100511 flags = hard_local_irq_save(); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800512 ret = (gpio_array[gpio_bank(gpio)]->name); \
513 if (ANOMALY_05000311 || ANOMALY_05000323) { \
514 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100515 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800516 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800517 return ret; \
518} \
519EXPORT_SYMBOL(get_gpiop_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700520
Michael Hennerich2b393312007-10-10 16:58:49 +0800521GET_GPIO_P(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700522GET_GPIO_P(dir)
523GET_GPIO_P(inen)
524GET_GPIO_P(polar)
525GET_GPIO_P(edge)
526GET_GPIO_P(both)
527GET_GPIO_P(maska)
528GET_GPIO_P(maskb)
529
Bryan Wu1394f032007-05-06 14:50:22 -0700530
531#ifdef CONFIG_PM
Mike Frysinger332824b2010-06-02 04:22:01 +0000532DECLARE_RESERVED_MAP(wakeup, GPIO_BANK_NUM);
Mike Frysingerf5563092009-02-04 16:49:45 +0800533
534static const unsigned int sic_iwr_irqs[] = {
535#if defined(BF533_FAMILY)
536 IRQ_PROG_INTB
537#elif defined(BF537_FAMILY)
Mike Frysinger8c054102011-04-15 13:04:59 -0400538 IRQ_PF_INTB_WATCH, IRQ_PORTG_INTB, IRQ_PH_INTB_MAC_TX
Mike Frysingerf5563092009-02-04 16:49:45 +0800539#elif defined(BF538_FAMILY)
540 IRQ_PORTF_INTB
Mike Frysinger269647d2009-03-28 20:32:57 +0800541#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800542 IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB
543#elif defined(BF561_FAMILY)
544 IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB
545#else
546# error no SIC_IWR defined
547#endif
548};
549
Bryan Wu1394f032007-05-06 14:50:22 -0700550/***********************************************************
551*
552* FUNCTIONS: Blackfin PM Setup API
553*
554* INPUTS/OUTPUTS:
555* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
556* type -
557* PM_WAKE_RISING
558* PM_WAKE_FALLING
559* PM_WAKE_HIGH
560* PM_WAKE_LOW
561* PM_WAKE_BOTH_EDGES
562*
563* DESCRIPTION: Blackfin PM Driver API
564*
565* CAUTION:
566*************************************************************
567* MODIFICATION HISTORY :
568**************************************************************/
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000569int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)
Bryan Wu1394f032007-05-06 14:50:22 -0700570{
571 unsigned long flags;
572
573 if (check_gpio(gpio) < 0)
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000574 return -EINVAL;
Bryan Wu1394f032007-05-06 14:50:22 -0700575
David Howells3b139cd2010-10-07 14:08:52 +0100576 flags = hard_local_irq_save();
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000577 if (ctrl)
Mike Frysinger332824b2010-06-02 04:22:01 +0000578 reserve(wakeup, gpio);
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000579 else
Mike Frysinger332824b2010-06-02 04:22:01 +0000580 unreserve(wakeup, gpio);
Bryan Wu1394f032007-05-06 14:50:22 -0700581
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000582 set_gpio_maskb(gpio, ctrl);
David Howells3b139cd2010-10-07 14:08:52 +0100583 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700584
585 return 0;
586}
587
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000588int bfin_pm_standby_ctrl(unsigned ctrl)
Bryan Wu1394f032007-05-06 14:50:22 -0700589{
590 u16 bank, mask, i;
591
Mike Frysinger1f83b8f2007-07-12 22:58:21 +0800592 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Mike Frysinger332824b2010-06-02 04:22:01 +0000593 mask = map_entry(wakeup, i);
Bryan Wu1394f032007-05-06 14:50:22 -0700594 bank = gpio_bank(i);
595
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000596 if (mask)
597 bfin_internal_set_wake(sic_iwr_irqs[bank], ctrl);
Bryan Wu1394f032007-05-06 14:50:22 -0700598 }
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000599 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -0700600}
601
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800602void bfin_gpio_pm_hibernate_suspend(void)
603{
604 int i, bank;
605
606 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
607 bank = gpio_bank(i);
608
Mike Frysinger269647d2009-03-28 20:32:57 +0800609#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800610 gpio_bank_saved[bank].fer = *port_fer[bank];
Mike Frysinger269647d2009-03-28 20:32:57 +0800611#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800612 gpio_bank_saved[bank].mux = *port_mux[bank];
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800613#else
Mike Frysingerf5563092009-02-04 16:49:45 +0800614 if (bank == 0)
615 gpio_bank_saved[bank].mux = bfin_read_PORT_MUX();
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800616#endif
617#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800618 gpio_bank_saved[bank].data = gpio_array[bank]->data;
619 gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
620 gpio_bank_saved[bank].polar = gpio_array[bank]->polar;
621 gpio_bank_saved[bank].dir = gpio_array[bank]->dir;
622 gpio_bank_saved[bank].edge = gpio_array[bank]->edge;
623 gpio_bank_saved[bank].both = gpio_array[bank]->both;
624 gpio_bank_saved[bank].maska = gpio_array[bank]->maska;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800625 }
626
627 AWA_DUMMY_READ(maska);
628}
629
630void bfin_gpio_pm_hibernate_restore(void)
631{
632 int i, bank;
633
634 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Mike Frysingerf5563092009-02-04 16:49:45 +0800635 bank = gpio_bank(i);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800636
Mike Frysinger269647d2009-03-28 20:32:57 +0800637#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
638#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800639 *port_mux[bank] = gpio_bank_saved[bank].mux;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800640#else
Mike Frysingerf5563092009-02-04 16:49:45 +0800641 if (bank == 0)
642 bfin_write_PORT_MUX(gpio_bank_saved[bank].mux);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800643#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800644 *port_fer[bank] = gpio_bank_saved[bank].fer;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800645#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800646 gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
Michael Hennerichc03c2a82009-07-08 12:04:43 +0000647 gpio_array[bank]->data_set = gpio_bank_saved[bank].data
648 & gpio_bank_saved[bank].dir;
Mike Frysingerf5563092009-02-04 16:49:45 +0800649 gpio_array[bank]->dir = gpio_bank_saved[bank].dir;
650 gpio_array[bank]->polar = gpio_bank_saved[bank].polar;
651 gpio_array[bank]->edge = gpio_bank_saved[bank].edge;
652 gpio_array[bank]->both = gpio_bank_saved[bank].both;
Mike Frysingerf5563092009-02-04 16:49:45 +0800653 gpio_array[bank]->maska = gpio_bank_saved[bank].maska;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800654 }
655 AWA_DUMMY_READ(maska);
656}
657
658
Bryan Wu1394f032007-05-06 14:50:22 -0700659#endif
Mike Frysinger269647d2009-03-28 20:32:57 +0800660#else /* CONFIG_BF54x */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800661#ifdef CONFIG_PM
662
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000663int bfin_pm_standby_ctrl(unsigned ctrl)
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800664{
665 return 0;
666}
667
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800668void bfin_gpio_pm_hibernate_suspend(void)
669{
670 int i, bank;
671
672 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
673 bank = gpio_bank(i);
674
Mike Frysingerf5563092009-02-04 16:49:45 +0800675 gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer;
676 gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux;
677 gpio_bank_saved[bank].data = gpio_array[bank]->data;
Mike Frysingerf5563092009-02-04 16:49:45 +0800678 gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
679 gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800680 }
681}
682
683void bfin_gpio_pm_hibernate_restore(void)
684{
685 int i, bank;
686
687 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Mike Frysingerf5563092009-02-04 16:49:45 +0800688 bank = gpio_bank(i);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800689
Mike Frysingerf5563092009-02-04 16:49:45 +0800690 gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux;
691 gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer;
692 gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
693 gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir;
694 gpio_array[bank]->data_set = gpio_bank_saved[bank].data
695 | gpio_bank_saved[bank].dir;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800696 }
697}
698#endif
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800699
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800700unsigned short get_gpio_dir(unsigned gpio)
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800701{
Mike Frysingerf5563092009-02-04 16:49:45 +0800702 return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio)));
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800703}
704EXPORT_SYMBOL(get_gpio_dir);
705
Mike Frysinger269647d2009-03-28 20:32:57 +0800706#endif /* CONFIG_BF54x */
Bryan Wu1394f032007-05-06 14:50:22 -0700707
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800708/***********************************************************
709*
Mike Frysinger812ae982010-07-05 08:40:41 +0000710* FUNCTIONS: Blackfin Peripheral Resource Allocation
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800711* and PortMux Setup
712*
713* INPUTS/OUTPUTS:
714* per Peripheral Identifier
715* label String
716*
717* DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API
718*
719* CAUTION:
720*************************************************************
721* MODIFICATION HISTORY :
722**************************************************************/
Michael Hennerichc58c2142007-10-04 00:35:05 +0800723
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800724int peripheral_request(unsigned short per, const char *label)
725{
726 unsigned long flags;
727 unsigned short ident = P_IDENT(per);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800728
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800729 /*
730 * Don't cares are pins with only one dedicated function
731 */
732
733 if (per & P_DONTCARE)
734 return 0;
735
736 if (!(per & P_DEFINED))
737 return -ENODEV;
738
Barry Song89e84ee2009-09-16 04:36:29 +0000739 BUG_ON(ident >= MAX_RESOURCES);
740
David Howells3b139cd2010-10-07 14:08:52 +0100741 flags = hard_local_irq_save();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800742
Mike Frysinger6a87d292008-10-28 16:16:29 +0800743 /* If a pin can be muxed as either GPIO or peripheral, make
744 * sure it is not already a GPIO pin when we request it.
745 */
Mike Frysinger332824b2010-06-02 04:22:01 +0000746 if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800747 if (system_state == SYSTEM_BOOTING)
748 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800749 printk(KERN_ERR
Mike Frysinger6c7ec0e2008-10-28 15:49:59 +0800750 "%s: Peripheral %d is already reserved as GPIO by %s !\n",
Harvey Harrisonb85d8582008-04-23 09:39:01 +0800751 __func__, ident, get_label(ident));
David Howells3b139cd2010-10-07 14:08:52 +0100752 hard_local_irq_restore(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800753 return -EBUSY;
754 }
755
Mike Frysinger332824b2010-06-02 04:22:01 +0000756 if (unlikely(is_reserved(peri, ident, 1))) {
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800757
Mike Frysingerd171c232008-03-26 08:35:46 +0800758 /*
759 * Pin functions like AMC address strobes my
760 * be requested and used by several drivers
761 */
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800762
Mike Frysinger269647d2009-03-28 20:32:57 +0800763#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +0800764 if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) {
Mike Frysinger6c7ec0e2008-10-28 15:49:59 +0800765#else
766 if (!(per & P_MAYSHARE)) {
767#endif
Mike Frysingerd171c232008-03-26 08:35:46 +0800768 /*
769 * Allow that the identical pin function can
770 * be requested from the same driver twice
771 */
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800772
Mike Frysingerd171c232008-03-26 08:35:46 +0800773 if (cmp_label(ident, label) == 0)
774 goto anyway;
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800775
Robin Getzd6879c52009-03-29 01:10:30 +0800776 if (system_state == SYSTEM_BOOTING)
777 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800778 printk(KERN_ERR
779 "%s: Peripheral %d function %d is already reserved by %s !\n",
Harvey Harrisonb85d8582008-04-23 09:39:01 +0800780 __func__, ident, P_FUNCT2MUX(per), get_label(ident));
David Howells3b139cd2010-10-07 14:08:52 +0100781 hard_local_irq_restore(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800782 return -EBUSY;
783 }
784 }
785
steven miao05bbec32010-09-17 03:03:17 +0000786 if (unlikely(portmux_group_check(per))) {
787 hard_local_irq_restore(flags);
788 return -EBUSY;
789 }
Mike Frysingerd171c232008-03-26 08:35:46 +0800790 anyway:
Mike Frysinger332824b2010-06-02 04:22:01 +0000791 reserve(peri, ident);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800792
Mike Frysingerf5563092009-02-04 16:49:45 +0800793 portmux_setup(per);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800794 port_setup(ident, PERIPHERAL_USAGE);
795
David Howells3b139cd2010-10-07 14:08:52 +0100796 hard_local_irq_restore(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800797 set_label(ident, label);
798
799 return 0;
800}
801EXPORT_SYMBOL(peripheral_request);
802
Mike Frysinger68179372008-04-24 05:04:24 +0800803int peripheral_request_list(const unsigned short per[], const char *label)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800804{
805 u16 cnt;
806 int ret;
807
808 for (cnt = 0; per[cnt] != 0; cnt++) {
Michael Hennerich314c98d2007-07-24 18:03:45 +0800809
Michael Hennerichc58c2142007-10-04 00:35:05 +0800810 ret = peripheral_request(per[cnt], label);
Michael Hennerich314c98d2007-07-24 18:03:45 +0800811
812 if (ret < 0) {
Mike Frysingerd171c232008-03-26 08:35:46 +0800813 for ( ; cnt > 0; cnt--)
Michael Hennerich314c98d2007-07-24 18:03:45 +0800814 peripheral_free(per[cnt - 1]);
Mike Frysingerd171c232008-03-26 08:35:46 +0800815
816 return ret;
Michael Hennerich314c98d2007-07-24 18:03:45 +0800817 }
Michael Hennerichc58c2142007-10-04 00:35:05 +0800818 }
819
820 return 0;
821}
822EXPORT_SYMBOL(peripheral_request_list);
823
824void peripheral_free(unsigned short per)
825{
826 unsigned long flags;
827 unsigned short ident = P_IDENT(per);
828
829 if (per & P_DONTCARE)
830 return;
831
832 if (!(per & P_DEFINED))
833 return;
834
David Howells3b139cd2010-10-07 14:08:52 +0100835 flags = hard_local_irq_save();
Michael Hennerichc58c2142007-10-04 00:35:05 +0800836
Mike Frysinger332824b2010-06-02 04:22:01 +0000837 if (unlikely(!is_reserved(peri, ident, 0))) {
David Howells3b139cd2010-10-07 14:08:52 +0100838 hard_local_irq_restore(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800839 return;
840 }
841
Mike Frysingerd171c232008-03-26 08:35:46 +0800842 if (!(per & P_MAYSHARE))
Michael Hennerichc58c2142007-10-04 00:35:05 +0800843 port_setup(ident, GPIO_USAGE);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800844
Mike Frysinger332824b2010-06-02 04:22:01 +0000845 unreserve(peri, ident);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800846
Michael Hennerich2acde902007-10-11 00:24:40 +0800847 set_label(ident, "free");
848
David Howells3b139cd2010-10-07 14:08:52 +0100849 hard_local_irq_restore(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800850}
851EXPORT_SYMBOL(peripheral_free);
852
Mike Frysinger68179372008-04-24 05:04:24 +0800853void peripheral_free_list(const unsigned short per[])
Michael Hennerichc58c2142007-10-04 00:35:05 +0800854{
855 u16 cnt;
Mike Frysingerd171c232008-03-26 08:35:46 +0800856 for (cnt = 0; per[cnt] != 0; cnt++)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800857 peripheral_free(per[cnt]);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800858}
859EXPORT_SYMBOL(peripheral_free_list);
860
Bryan Wu1394f032007-05-06 14:50:22 -0700861/***********************************************************
862*
863* FUNCTIONS: Blackfin GPIO Driver
864*
865* INPUTS/OUTPUTS:
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800866* gpio PIO Number between 0 and MAX_BLACKFIN_GPIOS
867* label String
Bryan Wu1394f032007-05-06 14:50:22 -0700868*
869* DESCRIPTION: Blackfin GPIO Driver API
870*
871* CAUTION:
872*************************************************************
873* MODIFICATION HISTORY :
874**************************************************************/
875
Michael Hennericha4f0b322008-11-18 17:48:22 +0800876int bfin_gpio_request(unsigned gpio, const char *label)
Bryan Wu1394f032007-05-06 14:50:22 -0700877{
878 unsigned long flags;
879
880 if (check_gpio(gpio) < 0)
881 return -EINVAL;
882
David Howells3b139cd2010-10-07 14:08:52 +0100883 flags = hard_local_irq_save();
Bryan Wu1394f032007-05-06 14:50:22 -0700884
Michael Hennerich2acde902007-10-11 00:24:40 +0800885 /*
886 * Allow that the identical GPIO can
887 * be requested from the same driver twice
888 * Do nothing and return -
889 */
890
891 if (cmp_label(gpio, label) == 0) {
David Howells3b139cd2010-10-07 14:08:52 +0100892 hard_local_irq_restore(flags);
Michael Hennerich2acde902007-10-11 00:24:40 +0800893 return 0;
894 }
895
Mike Frysinger332824b2010-06-02 04:22:01 +0000896 if (unlikely(is_reserved(gpio, gpio, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800897 if (system_state == SYSTEM_BOOTING)
898 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800899 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
Graf Yang9570ff42009-01-07 23:14:38 +0800900 gpio, get_label(gpio));
David Howells3b139cd2010-10-07 14:08:52 +0100901 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700902 return -EBUSY;
903 }
Mike Frysinger332824b2010-06-02 04:22:01 +0000904 if (unlikely(is_reserved(peri, gpio, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800905 if (system_state == SYSTEM_BOOTING)
906 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800907 printk(KERN_ERR
908 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
909 gpio, get_label(gpio));
David Howells3b139cd2010-10-07 14:08:52 +0100910 hard_local_irq_restore(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800911 return -EBUSY;
912 }
Mike Frysinger332824b2010-06-02 04:22:01 +0000913 if (unlikely(is_reserved(gpio_irq, gpio, 1))) {
Graf Yang9570ff42009-01-07 23:14:38 +0800914 printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!"
915 " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio);
Michael Hennericha2be3932009-02-04 16:49:45 +0800916 }
Mike Frysinger269647d2009-03-28 20:32:57 +0800917#ifndef CONFIG_BF54x
Michael Hennericha2be3932009-02-04 16:49:45 +0800918 else { /* Reset POLAR setting when acquiring a gpio for the first time */
919 set_gpio_polar(gpio, 0);
920 }
921#endif
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800922
Mike Frysinger332824b2010-06-02 04:22:01 +0000923 reserve(gpio, gpio);
Graf Yang9570ff42009-01-07 23:14:38 +0800924 set_label(gpio, label);
Bryan Wu1394f032007-05-06 14:50:22 -0700925
David Howells3b139cd2010-10-07 14:08:52 +0100926 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700927
928 port_setup(gpio, GPIO_USAGE);
929
930 return 0;
931}
Michael Hennericha4f0b322008-11-18 17:48:22 +0800932EXPORT_SYMBOL(bfin_gpio_request);
Bryan Wu1394f032007-05-06 14:50:22 -0700933
Michael Hennericha4f0b322008-11-18 17:48:22 +0800934void bfin_gpio_free(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -0700935{
936 unsigned long flags;
937
938 if (check_gpio(gpio) < 0)
939 return;
940
Uwe Kleine-Koenig45c4f2a2009-02-04 17:02:30 +0800941 might_sleep();
942
David Howells3b139cd2010-10-07 14:08:52 +0100943 flags = hard_local_irq_save();
Bryan Wu1394f032007-05-06 14:50:22 -0700944
Mike Frysinger332824b2010-06-02 04:22:01 +0000945 if (unlikely(!is_reserved(gpio, gpio, 0))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800946 if (system_state == SYSTEM_BOOTING)
947 dump_stack();
Mike Frysingerf85c4ab2008-03-26 08:34:23 +0800948 gpio_error(gpio);
David Howells3b139cd2010-10-07 14:08:52 +0100949 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700950 return;
951 }
952
Mike Frysinger332824b2010-06-02 04:22:01 +0000953 unreserve(gpio, gpio);
Bryan Wu1394f032007-05-06 14:50:22 -0700954
Michael Hennerich2acde902007-10-11 00:24:40 +0800955 set_label(gpio, "free");
956
David Howells3b139cd2010-10-07 14:08:52 +0100957 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700958}
Michael Hennericha4f0b322008-11-18 17:48:22 +0800959EXPORT_SYMBOL(bfin_gpio_free);
Bryan Wu1394f032007-05-06 14:50:22 -0700960
Michael Hennerich621dd242009-09-28 12:23:41 +0000961#ifdef BFIN_SPECIAL_GPIO_BANKS
Mike Frysinger332824b2010-06-02 04:22:01 +0000962DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES));
Michael Hennerich621dd242009-09-28 12:23:41 +0000963
964int bfin_special_gpio_request(unsigned gpio, const char *label)
965{
966 unsigned long flags;
967
David Howells3b139cd2010-10-07 14:08:52 +0100968 flags = hard_local_irq_save();
Michael Hennerich621dd242009-09-28 12:23:41 +0000969
970 /*
971 * Allow that the identical GPIO can
972 * be requested from the same driver twice
973 * Do nothing and return -
974 */
975
976 if (cmp_label(gpio, label) == 0) {
David Howells3b139cd2010-10-07 14:08:52 +0100977 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +0000978 return 0;
979 }
980
Mike Frysinger332824b2010-06-02 04:22:01 +0000981 if (unlikely(is_reserved(special_gpio, gpio, 1))) {
David Howells3b139cd2010-10-07 14:08:52 +0100982 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +0000983 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
984 gpio, get_label(gpio));
985
986 return -EBUSY;
987 }
Mike Frysinger332824b2010-06-02 04:22:01 +0000988 if (unlikely(is_reserved(peri, gpio, 1))) {
David Howells3b139cd2010-10-07 14:08:52 +0100989 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +0000990 printk(KERN_ERR
991 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
992 gpio, get_label(gpio));
993
994 return -EBUSY;
995 }
996
Mike Frysinger332824b2010-06-02 04:22:01 +0000997 reserve(special_gpio, gpio);
998 reserve(peri, gpio);
Michael Hennerich621dd242009-09-28 12:23:41 +0000999
1000 set_label(gpio, label);
David Howells3b139cd2010-10-07 14:08:52 +01001001 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +00001002 port_setup(gpio, GPIO_USAGE);
1003
1004 return 0;
1005}
1006EXPORT_SYMBOL(bfin_special_gpio_request);
1007
1008void bfin_special_gpio_free(unsigned gpio)
1009{
1010 unsigned long flags;
1011
1012 might_sleep();
1013
David Howells3b139cd2010-10-07 14:08:52 +01001014 flags = hard_local_irq_save();
Michael Hennerich621dd242009-09-28 12:23:41 +00001015
Mike Frysinger332824b2010-06-02 04:22:01 +00001016 if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
Michael Hennerich621dd242009-09-28 12:23:41 +00001017 gpio_error(gpio);
David Howells3b139cd2010-10-07 14:08:52 +01001018 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +00001019 return;
1020 }
1021
Mike Frysinger332824b2010-06-02 04:22:01 +00001022 unreserve(special_gpio, gpio);
1023 unreserve(peri, gpio);
Michael Hennerich621dd242009-09-28 12:23:41 +00001024 set_label(gpio, "free");
David Howells3b139cd2010-10-07 14:08:52 +01001025 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +00001026}
1027EXPORT_SYMBOL(bfin_special_gpio_free);
1028#endif
1029
1030
Graf Yang9570ff42009-01-07 23:14:38 +08001031int bfin_gpio_irq_request(unsigned gpio, const char *label)
1032{
1033 unsigned long flags;
1034
1035 if (check_gpio(gpio) < 0)
1036 return -EINVAL;
1037
David Howells3b139cd2010-10-07 14:08:52 +01001038 flags = hard_local_irq_save();
Graf Yang9570ff42009-01-07 23:14:38 +08001039
Mike Frysinger332824b2010-06-02 04:22:01 +00001040 if (unlikely(is_reserved(peri, gpio, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +08001041 if (system_state == SYSTEM_BOOTING)
1042 dump_stack();
Graf Yang9570ff42009-01-07 23:14:38 +08001043 printk(KERN_ERR
1044 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
1045 gpio, get_label(gpio));
David Howells3b139cd2010-10-07 14:08:52 +01001046 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001047 return -EBUSY;
1048 }
Mike Frysinger332824b2010-06-02 04:22:01 +00001049 if (unlikely(is_reserved(gpio, gpio, 1)))
Graf Yang9570ff42009-01-07 23:14:38 +08001050 printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved by %s! "
1051 "(Documentation/blackfin/bfin-gpio-notes.txt)\n",
1052 gpio, get_label(gpio));
1053
Mike Frysinger332824b2010-06-02 04:22:01 +00001054 reserve(gpio_irq, gpio);
Graf Yang9570ff42009-01-07 23:14:38 +08001055 set_label(gpio, label);
1056
David Howells3b139cd2010-10-07 14:08:52 +01001057 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001058
1059 port_setup(gpio, GPIO_USAGE);
1060
1061 return 0;
1062}
1063
1064void bfin_gpio_irq_free(unsigned gpio)
1065{
1066 unsigned long flags;
1067
1068 if (check_gpio(gpio) < 0)
1069 return;
1070
David Howells3b139cd2010-10-07 14:08:52 +01001071 flags = hard_local_irq_save();
Graf Yang9570ff42009-01-07 23:14:38 +08001072
Mike Frysinger332824b2010-06-02 04:22:01 +00001073 if (unlikely(!is_reserved(gpio_irq, gpio, 0))) {
Robin Getzd6879c52009-03-29 01:10:30 +08001074 if (system_state == SYSTEM_BOOTING)
1075 dump_stack();
Graf Yang9570ff42009-01-07 23:14:38 +08001076 gpio_error(gpio);
David Howells3b139cd2010-10-07 14:08:52 +01001077 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001078 return;
1079 }
1080
Mike Frysinger332824b2010-06-02 04:22:01 +00001081 unreserve(gpio_irq, gpio);
Graf Yang9570ff42009-01-07 23:14:38 +08001082
1083 set_label(gpio, "free");
1084
David Howells3b139cd2010-10-07 14:08:52 +01001085 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001086}
1087
Mike Frysingerf5563092009-02-04 16:49:45 +08001088static inline void __bfin_gpio_direction_input(unsigned gpio)
1089{
Mike Frysinger269647d2009-03-28 20:32:57 +08001090#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001091 gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
Michael Hennerichd2b11a42007-08-28 16:47:46 +08001092#else
Mike Frysingerf5563092009-02-04 16:49:45 +08001093 gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
1094#endif
1095 gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
Michael Hennerich803a8d22008-05-17 16:01:51 +08001096}
Michael Hennerich803a8d22008-05-17 16:01:51 +08001097
Michael Hennericha4f0b322008-11-18 17:48:22 +08001098int bfin_gpio_direction_input(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -07001099{
1100 unsigned long flags;
1101
Mike Frysinger332824b2010-06-02 04:22:01 +00001102 if (unlikely(!is_reserved(gpio, gpio, 0))) {
Michael Hennerichacbcd262008-01-22 18:36:20 +08001103 gpio_error(gpio);
1104 return -EINVAL;
1105 }
Bryan Wu1394f032007-05-06 14:50:22 -07001106
David Howells3b139cd2010-10-07 14:08:52 +01001107 flags = hard_local_irq_save();
Mike Frysingerf5563092009-02-04 16:49:45 +08001108 __bfin_gpio_direction_input(gpio);
Michael Hennerich2b393312007-10-10 16:58:49 +08001109 AWA_DUMMY_READ(inen);
David Howells3b139cd2010-10-07 14:08:52 +01001110 hard_local_irq_restore(flags);
Michael Hennerichacbcd262008-01-22 18:36:20 +08001111
1112 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -07001113}
Michael Hennericha4f0b322008-11-18 17:48:22 +08001114EXPORT_SYMBOL(bfin_gpio_direction_input);
Bryan Wu1394f032007-05-06 14:50:22 -07001115
Mike Frysingerf5563092009-02-04 16:49:45 +08001116void bfin_gpio_irq_prepare(unsigned gpio)
1117{
Mike Frysinger269647d2009-03-28 20:32:57 +08001118#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001119 unsigned long flags;
1120#endif
1121
1122 port_setup(gpio, GPIO_USAGE);
1123
Mike Frysinger269647d2009-03-28 20:32:57 +08001124#ifdef CONFIG_BF54x
David Howells3b139cd2010-10-07 14:08:52 +01001125 flags = hard_local_irq_save();
Mike Frysingerf5563092009-02-04 16:49:45 +08001126 __bfin_gpio_direction_input(gpio);
David Howells3b139cd2010-10-07 14:08:52 +01001127 hard_local_irq_restore(flags);
Mike Frysingerf5563092009-02-04 16:49:45 +08001128#endif
1129}
1130
1131void bfin_gpio_set_value(unsigned gpio, int arg)
1132{
1133 if (arg)
1134 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
1135 else
1136 gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
1137}
1138EXPORT_SYMBOL(bfin_gpio_set_value);
1139
Michael Hennericha4f0b322008-11-18 17:48:22 +08001140int bfin_gpio_direction_output(unsigned gpio, int value)
Bryan Wu1394f032007-05-06 14:50:22 -07001141{
1142 unsigned long flags;
1143
Mike Frysinger332824b2010-06-02 04:22:01 +00001144 if (unlikely(!is_reserved(gpio, gpio, 0))) {
Michael Hennerichacbcd262008-01-22 18:36:20 +08001145 gpio_error(gpio);
1146 return -EINVAL;
1147 }
Bryan Wu1394f032007-05-06 14:50:22 -07001148
David Howells3b139cd2010-10-07 14:08:52 +01001149 flags = hard_local_irq_save();
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001150
Mike Frysingerf5563092009-02-04 16:49:45 +08001151 gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
1152 gpio_set_value(gpio, value);
Mike Frysinger269647d2009-03-28 20:32:57 +08001153#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001154 gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
1155#else
1156 gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
1157#endif
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001158
Michael Hennerich2b393312007-10-10 16:58:49 +08001159 AWA_DUMMY_READ(dir);
David Howells3b139cd2010-10-07 14:08:52 +01001160 hard_local_irq_restore(flags);
Michael Hennerichacbcd262008-01-22 18:36:20 +08001161
1162 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -07001163}
Michael Hennericha4f0b322008-11-18 17:48:22 +08001164EXPORT_SYMBOL(bfin_gpio_direction_output);
Mike Frysinger168f1212007-10-11 00:22:35 +08001165
Mike Frysingerf5563092009-02-04 16:49:45 +08001166int bfin_gpio_get_value(unsigned gpio)
1167{
Mike Frysinger269647d2009-03-28 20:32:57 +08001168#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001169 return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)));
1170#else
1171 unsigned long flags;
1172
1173 if (unlikely(get_gpio_edge(gpio))) {
1174 int ret;
David Howells3b139cd2010-10-07 14:08:52 +01001175 flags = hard_local_irq_save();
Mike Frysingerf5563092009-02-04 16:49:45 +08001176 set_gpio_edge(gpio, 0);
1177 ret = get_gpio_data(gpio);
1178 set_gpio_edge(gpio, 1);
David Howells3b139cd2010-10-07 14:08:52 +01001179 hard_local_irq_restore(flags);
Mike Frysingerf5563092009-02-04 16:49:45 +08001180 return ret;
1181 } else
1182 return get_gpio_data(gpio);
1183#endif
1184}
1185EXPORT_SYMBOL(bfin_gpio_get_value);
1186
Mike Frysinger168f1212007-10-11 00:22:35 +08001187/* If we are booting from SPI and our board lacks a strong enough pull up,
1188 * the core can reset and execute the bootrom faster than the resistor can
1189 * pull the signal logically high. To work around this (common) error in
1190 * board design, we explicitly set the pin back to GPIO mode, force /CS
1191 * high, and wait for the electrons to do their thing.
1192 *
1193 * This function only makes sense to be called from reset code, but it
1194 * lives here as we need to force all the GPIO states w/out going through
1195 * BUG() checks and such.
1196 */
Sonic Zhangb52dae32009-02-04 16:49:45 +08001197void bfin_reset_boot_spi_cs(unsigned short pin)
Mike Frysinger168f1212007-10-11 00:22:35 +08001198{
Sonic Zhangb52dae32009-02-04 16:49:45 +08001199 unsigned short gpio = P_IDENT(pin);
Michael Hennerich4d5f4ed2007-08-27 16:46:17 +08001200 port_setup(gpio, GPIO_USAGE);
Mike Frysingerf5563092009-02-04 16:49:45 +08001201 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001202 AWA_DUMMY_READ(data_set);
Mike Frysinger168f1212007-10-11 00:22:35 +08001203 udelay(1);
1204}
Michael Hennerichd2b11a42007-08-28 16:47:46 +08001205
Mike Frysinger1545a112007-12-24 16:54:48 +08001206#if defined(CONFIG_PROC_FS)
1207static int gpio_proc_read(char *buf, char **start, off_t offset,
1208 int len, int *unused_i, void *unused_v)
1209{
Graf Yang9570ff42009-01-07 23:14:38 +08001210 int c, irq, gpio, outlen = 0;
Mike Frysinger1545a112007-12-24 16:54:48 +08001211
1212 for (c = 0; c < MAX_RESOURCES; c++) {
Mike Frysinger332824b2010-06-02 04:22:01 +00001213 irq = is_reserved(gpio_irq, c, 1);
1214 gpio = is_reserved(gpio, c, 1);
Graf Yang9570ff42009-01-07 23:14:38 +08001215 if (!check_gpio(c) && (gpio || irq))
1216 len = sprintf(buf, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c,
1217 get_label(c), (gpio && irq) ? " *" : "",
1218 get_gpio_dir(c) ? "OUTPUT" : "INPUT");
Mike Frysinger332824b2010-06-02 04:22:01 +00001219 else if (is_reserved(peri, c, 1))
Graf Yang8eb3e3b2008-11-18 17:48:22 +08001220 len = sprintf(buf, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c));
Mike Frysinger1545a112007-12-24 16:54:48 +08001221 else
1222 continue;
1223 buf += len;
1224 outlen += len;
1225 }
1226 return outlen;
1227}
1228
1229static __init int gpio_register_proc(void)
1230{
1231 struct proc_dir_entry *proc_gpio;
1232
1233 proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL);
1234 if (proc_gpio)
1235 proc_gpio->read_proc = gpio_proc_read;
1236 return proc_gpio != NULL;
1237}
Mike Frysinger1545a112007-12-24 16:54:48 +08001238__initcall(gpio_register_proc);
1239#endif
Michael Hennericha4f0b322008-11-18 17:48:22 +08001240
1241#ifdef CONFIG_GPIOLIB
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001242static int bfin_gpiolib_direction_input(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b322008-11-18 17:48:22 +08001243{
1244 return bfin_gpio_direction_input(gpio);
1245}
1246
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001247static int bfin_gpiolib_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
Michael Hennericha4f0b322008-11-18 17:48:22 +08001248{
1249 return bfin_gpio_direction_output(gpio, level);
1250}
1251
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001252static int bfin_gpiolib_get_value(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b322008-11-18 17:48:22 +08001253{
1254 return bfin_gpio_get_value(gpio);
1255}
1256
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001257static void bfin_gpiolib_set_value(struct gpio_chip *chip, unsigned gpio, int value)
Michael Hennericha4f0b322008-11-18 17:48:22 +08001258{
Michael Hennericha4f0b322008-11-18 17:48:22 +08001259 return bfin_gpio_set_value(gpio, value);
Michael Hennericha4f0b322008-11-18 17:48:22 +08001260}
1261
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001262static int bfin_gpiolib_gpio_request(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b322008-11-18 17:48:22 +08001263{
1264 return bfin_gpio_request(gpio, chip->label);
1265}
1266
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001267static void bfin_gpiolib_gpio_free(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b322008-11-18 17:48:22 +08001268{
1269 return bfin_gpio_free(gpio);
1270}
1271
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001272static int bfin_gpiolib_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
Joachim Eastwood7f4f69f2010-02-10 12:31:41 +01001273{
1274 return gpio + GPIO_IRQ_BASE;
1275}
1276
Michael Hennericha4f0b322008-11-18 17:48:22 +08001277static struct gpio_chip bfin_chip = {
Michael Hennerichedd07992009-12-16 08:45:17 +00001278 .label = "BFIN-GPIO",
Michael Hennericha4f0b322008-11-18 17:48:22 +08001279 .direction_input = bfin_gpiolib_direction_input,
1280 .get = bfin_gpiolib_get_value,
1281 .direction_output = bfin_gpiolib_direction_output,
1282 .set = bfin_gpiolib_set_value,
1283 .request = bfin_gpiolib_gpio_request,
1284 .free = bfin_gpiolib_gpio_free,
Joachim Eastwood7f4f69f2010-02-10 12:31:41 +01001285 .to_irq = bfin_gpiolib_gpio_to_irq,
Michael Hennericha4f0b322008-11-18 17:48:22 +08001286 .base = 0,
1287 .ngpio = MAX_BLACKFIN_GPIOS,
1288};
1289
1290static int __init bfin_gpiolib_setup(void)
1291{
1292 return gpiochip_add(&bfin_chip);
1293}
1294arch_initcall(bfin_gpiolib_setup);
1295#endif