blob: a017359c182668f71583ce013ae92263b95c69e6 [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>
Alexey Dobriyan6362ec22011-05-14 19:48:46 +030013#include <linux/seq_file.h>
Sonic Zhang54e4ff42013-05-30 18:37:28 +080014#include <linux/gpio.h>
Bryan Wu1394f032007-05-06 14:50:22 -070015#include <linux/irq.h>
16
Michael Hennerich2b393312007-10-10 16:58:49 +080017#if ANOMALY_05000311 || ANOMALY_05000323
18enum {
19 AWA_data = SYSCR,
20 AWA_data_clear = SYSCR,
21 AWA_data_set = SYSCR,
22 AWA_toggle = SYSCR,
Graf Yang6ed83942008-04-24 04:43:14 +080023 AWA_maska = BFIN_UART_SCR,
24 AWA_maska_clear = BFIN_UART_SCR,
25 AWA_maska_set = BFIN_UART_SCR,
26 AWA_maska_toggle = BFIN_UART_SCR,
27 AWA_maskb = BFIN_UART_GCTL,
28 AWA_maskb_clear = BFIN_UART_GCTL,
29 AWA_maskb_set = BFIN_UART_GCTL,
30 AWA_maskb_toggle = BFIN_UART_GCTL,
Michael Hennerich2b393312007-10-10 16:58:49 +080031 AWA_dir = SPORT1_STAT,
32 AWA_polar = SPORT1_STAT,
33 AWA_edge = SPORT1_STAT,
34 AWA_both = SPORT1_STAT,
35#if ANOMALY_05000311
36 AWA_inen = TIMER_ENABLE,
37#elif ANOMALY_05000323
38 AWA_inen = DMA1_1_CONFIG,
39#endif
40};
41 /* Anomaly Workaround */
42#define AWA_DUMMY_READ(name) bfin_read16(AWA_ ## name)
43#else
44#define AWA_DUMMY_READ(...) do { } while (0)
45#endif
46
Mike Frysingerf5563092009-02-04 16:49:45 +080047static struct gpio_port_t * const gpio_array[] = {
Michael Hennerichdc26aec2008-11-18 17:48:22 +080048#if defined(BF533_FAMILY) || defined(BF538_FAMILY)
Bryan Wu1394f032007-05-06 14:50:22 -070049 (struct gpio_port_t *) FIO_FLAG_D,
Mike Frysinger269647d2009-03-28 20:32:57 +080050#elif defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Bryan Wu1394f032007-05-06 14:50:22 -070051 (struct gpio_port_t *) PORTFIO,
52 (struct gpio_port_t *) PORTGIO,
53 (struct gpio_port_t *) PORTHIO,
Mike Frysingerf5563092009-02-04 16:49:45 +080054#elif defined(BF561_FAMILY)
55 (struct gpio_port_t *) FIO0_FLAG_D,
56 (struct gpio_port_t *) FIO1_FLAG_D,
57 (struct gpio_port_t *) FIO2_FLAG_D,
Mike Frysingerf5563092009-02-04 16:49:45 +080058#else
59# error no gpio arrays defined
60#endif
Bryan Wu1394f032007-05-06 14:50:22 -070061};
62
Mike Frysinger269647d2009-03-28 20:32:57 +080063#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +080064static unsigned short * const port_fer[] = {
Bryan Wu1394f032007-05-06 14:50:22 -070065 (unsigned short *) PORTF_FER,
66 (unsigned short *) PORTG_FER,
67 (unsigned short *) PORTH_FER,
68};
Bryan Wu1394f032007-05-06 14:50:22 -070069
Mike Frysingerf5563092009-02-04 16:49:45 +080070# if !defined(BF537_FAMILY)
71static unsigned short * const port_mux[] = {
Michael Hennerich59003142007-10-21 16:54:27 +080072 (unsigned short *) PORTF_MUX,
73 (unsigned short *) PORTG_MUX,
74 (unsigned short *) PORTH_MUX,
75};
76
77static const
Graf Yang0ce5eaf2009-02-04 16:49:45 +080078u8 pmux_offset[][16] = {
Mike Frysinger269647d2009-03-28 20:32:57 +080079# if defined(CONFIG_BF52x)
Graf Yang0ce5eaf2009-02-04 16:49:45 +080080 { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */
81 { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */
82 { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */
Mike Frysinger269647d2009-03-28 20:32:57 +080083# elif defined(CONFIG_BF51x)
Graf Yang0ce5eaf2009-02-04 16:49:45 +080084 { 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */
85 { 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */
86 { 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */
87# endif
88};
Mike Frysingerf5563092009-02-04 16:49:45 +080089# endif
Graf Yang0ce5eaf2009-02-04 16:49:45 +080090
Michael Hennerich621dd242009-09-28 12:23:41 +000091#elif defined(BF538_FAMILY)
92static unsigned short * const port_fer[] = {
93 (unsigned short *) PORTCIO_FER,
94 (unsigned short *) PORTDIO_FER,
95 (unsigned short *) PORTEIO_FER,
96};
Michael Hennerichd2b11a42007-08-28 16:47:46 +080097#endif
98
Mike Frysinger812ae982010-07-05 08:40:41 +000099#define RESOURCE_LABEL_SIZE 16
Michael Hennerich8c613622007-08-03 17:48:09 +0800100
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800101static struct str_ident {
Michael Hennerich8c613622007-08-03 17:48:09 +0800102 char name[RESOURCE_LABEL_SIZE];
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800103} str_ident[MAX_RESOURCES];
Bryan Wu1394f032007-05-06 14:50:22 -0700104
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800105#if defined(CONFIG_PM)
Bryan Wu397861c2008-11-18 17:48:22 +0800106static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM];
Mike Frysinger9466a052011-06-27 14:46:14 -0400107# ifdef BF538_FAMILY
108static unsigned short port_fer_saved[3];
109# endif
Bryan Wu1394f032007-05-06 14:50:22 -0700110#endif
111
Mike Frysinger74c04502008-10-08 16:13:17 +0800112static void gpio_error(unsigned gpio)
Michael Hennerichacbcd262008-01-22 18:36:20 +0800113{
114 printk(KERN_ERR "bfin-gpio: GPIO %d wasn't requested!\n", gpio);
115}
116
Michael Hennerichc58c2142007-10-04 00:35:05 +0800117static void set_label(unsigned short ident, const char *label)
118{
Michael Henneriche9fae182008-10-13 11:35:22 +0800119 if (label) {
Michael Hennerich8c613622007-08-03 17:48:09 +0800120 strncpy(str_ident[ident].name, label,
Michael Hennerichc58c2142007-10-04 00:35:05 +0800121 RESOURCE_LABEL_SIZE);
Michael Hennerich8c613622007-08-03 17:48:09 +0800122 str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800123 }
124}
125
126static char *get_label(unsigned short ident)
127{
Michael Hennerich8c613622007-08-03 17:48:09 +0800128 return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN");
Michael Hennerichc58c2142007-10-04 00:35:05 +0800129}
130
131static int cmp_label(unsigned short ident, const char *label)
132{
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800133 if (label == NULL) {
134 dump_stack();
135 printk(KERN_ERR "Please provide none-null label\n");
136 }
137
Michael Henneriche9fae182008-10-13 11:35:22 +0800138 if (label)
Mike Frysinger1f7d3732008-10-28 15:47:11 +0800139 return strcmp(str_ident[ident].name, label);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800140 else
141 return -EINVAL;
142}
143
Mike Frysinger332824b2010-06-02 04:22:01 +0000144#define map_entry(m, i) reserved_##m##_map[gpio_bank(i)]
145#define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i))
146#define reserve(m, i) (map_entry(m, i) |= gpio_bit(i))
147#define unreserve(m, i) (map_entry(m, i) &= ~gpio_bit(i))
148#define DECLARE_RESERVED_MAP(m, c) static unsigned short reserved_##m##_map[c]
149
150DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM);
Michael Hennerich382dbe52010-07-13 08:26:10 +0000151DECLARE_RESERVED_MAP(peri, DIV_ROUND_UP(MAX_RESOURCES, GPIO_BANKSIZE));
Mike Frysinger332824b2010-06-02 04:22:01 +0000152DECLARE_RESERVED_MAP(gpio_irq, GPIO_BANK_NUM);
153
154inline int check_gpio(unsigned gpio)
155{
Mike Frysinger332824b2010-06-02 04:22:01 +0000156 if (gpio >= MAX_BLACKFIN_GPIOS)
157 return -EINVAL;
158 return 0;
159}
160
Mike Frysingera2d03a12008-10-28 15:53:37 +0800161static void port_setup(unsigned gpio, unsigned short usage)
162{
Michael Hennerich621dd242009-09-28 12:23:41 +0000163#if defined(BF538_FAMILY)
164 /*
165 * BF538/9 Port C,D and E are special.
166 * Inverted PORT_FER polarity on CDE and no PORF_FER on F
167 * Regular PORT F GPIOs are handled here, CDE are exclusively
168 * managed by GPIOLIB
169 */
170
171 if (gpio < MAX_BLACKFIN_GPIOS || gpio >= MAX_RESOURCES)
172 return;
173
174 gpio -= MAX_BLACKFIN_GPIOS;
175
176 if (usage == GPIO_USAGE)
177 *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
178 else
179 *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
180 SSYNC();
181 return;
182#endif
183
Mike Frysingera2d03a12008-10-28 15:53:37 +0800184 if (check_gpio(gpio))
185 return;
186
Mike Frysinger269647d2009-03-28 20:32:57 +0800187#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Mike Frysingera2d03a12008-10-28 15:53:37 +0800188 if (usage == GPIO_USAGE)
189 *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
190 else
191 *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
192 SSYNC();
Bryan Wu1394f032007-05-06 14:50:22 -0700193#endif
Mike Frysingera2d03a12008-10-28 15:53:37 +0800194}
Bryan Wu1394f032007-05-06 14:50:22 -0700195
Michael Hennerichc58c2142007-10-04 00:35:05 +0800196#ifdef BF537_FAMILY
steven miao05bbec32010-09-17 03:03:17 +0000197static const s8 port_mux[] = {
198 [GPIO_PF0] = 3,
199 [GPIO_PF1] = 3,
200 [GPIO_PF2] = 4,
201 [GPIO_PF3] = 4,
202 [GPIO_PF4] = 5,
203 [GPIO_PF5] = 6,
204 [GPIO_PF6] = 7,
205 [GPIO_PF7] = 8,
206 [GPIO_PF8 ... GPIO_PF15] = -1,
207 [GPIO_PG0 ... GPIO_PG7] = -1,
208 [GPIO_PG8] = 9,
209 [GPIO_PG9] = 9,
210 [GPIO_PG10] = 10,
211 [GPIO_PG11] = 10,
212 [GPIO_PG12] = 10,
213 [GPIO_PG13] = 11,
214 [GPIO_PG14] = 11,
215 [GPIO_PG15] = 11,
216 [GPIO_PH0 ... GPIO_PH15] = -1,
217 [PORT_PJ0 ... PORT_PJ3] = -1,
218 [PORT_PJ4] = 1,
219 [PORT_PJ5] = 1,
220 [PORT_PJ6 ... PORT_PJ9] = -1,
221 [PORT_PJ10] = 0,
222 [PORT_PJ11] = 0,
Michael Hennerichc58c2142007-10-04 00:35:05 +0800223};
224
steven miao05bbec32010-09-17 03:03:17 +0000225static int portmux_group_check(unsigned short per)
226{
227 u16 ident = P_IDENT(per);
228 u16 function = P_FUNCT2MUX(per);
229 s8 offset = port_mux[ident];
Sonic Zhangf70de482013-07-01 11:24:46 +0800230 u16 m, pmux, pfunc, mask;
steven miao05bbec32010-09-17 03:03:17 +0000231
232 if (offset < 0)
233 return 0;
234
235 pmux = bfin_read_PORT_MUX();
236 for (m = 0; m < ARRAY_SIZE(port_mux); ++m) {
237 if (m == ident)
238 continue;
239 if (port_mux[m] != offset)
240 continue;
241 if (!is_reserved(peri, m, 1))
242 continue;
243
244 if (offset == 1)
Sonic Zhangf70de482013-07-01 11:24:46 +0800245 mask = 3;
steven miao05bbec32010-09-17 03:03:17 +0000246 else
Sonic Zhangf70de482013-07-01 11:24:46 +0800247 mask = 1;
248
249 pfunc = (pmux >> offset) & mask;
250 if (pfunc != (function & mask)) {
steven miao05bbec32010-09-17 03:03:17 +0000251 pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",
252 ident, function, m, pfunc);
253 return -EINVAL;
254 }
255 }
256
257 return 0;
258}
259
Mike Frysingerf5563092009-02-04 16:49:45 +0800260static void portmux_setup(unsigned short per)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800261{
steven miao05bbec32010-09-17 03:03:17 +0000262 u16 ident = P_IDENT(per);
Mike Frysingerf5563092009-02-04 16:49:45 +0800263 u16 function = P_FUNCT2MUX(per);
steven miao05bbec32010-09-17 03:03:17 +0000264 s8 offset = port_mux[ident];
Sonic Zhangf70de482013-07-01 11:24:46 +0800265 u16 pmux, mask;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800266
steven miao05bbec32010-09-17 03:03:17 +0000267 if (offset == -1)
268 return;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800269
steven miao05bbec32010-09-17 03:03:17 +0000270 pmux = bfin_read_PORT_MUX();
Sonic Zhangf70de482013-07-01 11:24:46 +0800271 if (offset == 1)
272 mask = 3;
steven miao05bbec32010-09-17 03:03:17 +0000273 else
Sonic Zhangf70de482013-07-01 11:24:46 +0800274 mask = 1;
275
276 pmux &= ~(mask << offset);
277 pmux |= ((function & mask) << offset);
278
steven miao05bbec32010-09-17 03:03:17 +0000279 bfin_write_PORT_MUX(pmux);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800280}
Mike Frysinger269647d2009-03-28 20:32:57 +0800281#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
steven miao05bbec32010-09-17 03:03:17 +0000282static int portmux_group_check(unsigned short per)
283{
284 u16 ident = P_IDENT(per);
285 u16 function = P_FUNCT2MUX(per);
286 u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
287 u16 pin, gpiopin, pfunc;
288
289 for (pin = 0; pin < GPIO_BANKSIZE; ++pin) {
290 if (offset != pmux_offset[gpio_bank(ident)][pin])
291 continue;
292
293 gpiopin = gpio_bank(ident) * GPIO_BANKSIZE + pin;
294 if (gpiopin == ident)
295 continue;
296 if (!is_reserved(peri, gpiopin, 1))
297 continue;
298
299 pfunc = *port_mux[gpio_bank(ident)];
300 pfunc = (pfunc >> offset) & 3;
301 if (pfunc != function) {
302 pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",
303 ident, function, gpiopin, pfunc);
304 return -EINVAL;
305 }
306 }
307
308 return 0;
309}
310
Mike Frysingerf5563092009-02-04 16:49:45 +0800311inline void portmux_setup(unsigned short per)
Michael Hennerich59003142007-10-21 16:54:27 +0800312{
steven miao05bbec32010-09-17 03:03:17 +0000313 u16 ident = P_IDENT(per);
314 u16 function = P_FUNCT2MUX(per);
Michael Hennerich59003142007-10-21 16:54:27 +0800315 u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
steven miao05bbec32010-09-17 03:03:17 +0000316 u16 pmux;
Michael Hennerich59003142007-10-21 16:54:27 +0800317
318 pmux = *port_mux[gpio_bank(ident)];
steven miao05bbec32010-09-17 03:03:17 +0000319 if (((pmux >> offset) & 3) == function)
320 return;
Michael Hennerich59003142007-10-21 16:54:27 +0800321 pmux &= ~(3 << offset);
322 pmux |= (function & 3) << offset;
323 *port_mux[gpio_bank(ident)] = pmux;
324 SSYNC();
325}
Michael Hennerichc58c2142007-10-04 00:35:05 +0800326#else
327# define portmux_setup(...) do { } while (0)
steven miao05bbec32010-09-17 03:03:17 +0000328static int portmux_group_check(unsigned short per)
329{
330 return 0;
331}
Michael Hennerichc58c2142007-10-04 00:35:05 +0800332#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700333
Bryan Wu1394f032007-05-06 14:50:22 -0700334/***********************************************************
335*
336* FUNCTIONS: Blackfin General Purpose Ports Access Functions
337*
338* INPUTS/OUTPUTS:
339* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
340*
341*
342* DESCRIPTION: These functions abstract direct register access
343* to Blackfin processor General Purpose
344* Ports Regsiters
345*
346* CAUTION: These functions do not belong to the GPIO Driver API
347*************************************************************
348* MODIFICATION HISTORY :
349**************************************************************/
350
351/* Set a specific bit */
352
353#define SET_GPIO(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800354void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
Bryan Wu1394f032007-05-06 14:50:22 -0700355{ \
356 unsigned long flags; \
David Howells3b139cd2010-10-07 14:08:52 +0100357 flags = hard_local_irq_save(); \
Bryan Wu1394f032007-05-06 14:50:22 -0700358 if (arg) \
Mike Frysingerf5563092009-02-04 16:49:45 +0800359 gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
Bryan Wu1394f032007-05-06 14:50:22 -0700360 else \
Mike Frysingerf5563092009-02-04 16:49:45 +0800361 gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
Michael Hennerich2b393312007-10-10 16:58:49 +0800362 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100363 hard_local_irq_restore(flags); \
Bryan Wu1394f032007-05-06 14:50:22 -0700364} \
365EXPORT_SYMBOL(set_gpio_ ## name);
366
Mike Frysingerf5563092009-02-04 16:49:45 +0800367SET_GPIO(dir) /* set_gpio_dir() */
368SET_GPIO(inen) /* set_gpio_inen() */
369SET_GPIO(polar) /* set_gpio_polar() */
370SET_GPIO(edge) /* set_gpio_edge() */
371SET_GPIO(both) /* set_gpio_both() */
Bryan Wu1394f032007-05-06 14:50:22 -0700372
373
Michael Hennerich2b393312007-10-10 16:58:49 +0800374#define SET_GPIO_SC(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800375void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800376{ \
377 unsigned long flags; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800378 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100379 flags = hard_local_irq_save(); \
Michael Hennerich2b393312007-10-10 16:58:49 +0800380 if (arg) \
Mike Frysingerf5563092009-02-04 16:49:45 +0800381 gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
Michael Hennerich2b393312007-10-10 16:58:49 +0800382 else \
Mike Frysingerf5563092009-02-04 16:49:45 +0800383 gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
384 if (ANOMALY_05000311 || ANOMALY_05000323) { \
385 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100386 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800387 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800388} \
389EXPORT_SYMBOL(set_gpio_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700390
391SET_GPIO_SC(maska)
392SET_GPIO_SC(maskb)
Bryan Wu1394f032007-05-06 14:50:22 -0700393SET_GPIO_SC(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700394
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800395void set_gpio_toggle(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -0700396{
397 unsigned long flags;
Mike Frysingerf5563092009-02-04 16:49:45 +0800398 if (ANOMALY_05000311 || ANOMALY_05000323)
David Howells3b139cd2010-10-07 14:08:52 +0100399 flags = hard_local_irq_save();
Mike Frysingerf5563092009-02-04 16:49:45 +0800400 gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
401 if (ANOMALY_05000311 || ANOMALY_05000323) {
402 AWA_DUMMY_READ(toggle);
David Howells3b139cd2010-10-07 14:08:52 +0100403 hard_local_irq_restore(flags);
Mike Frysingerf5563092009-02-04 16:49:45 +0800404 }
Bryan Wu1394f032007-05-06 14:50:22 -0700405}
Bryan Wu1394f032007-05-06 14:50:22 -0700406EXPORT_SYMBOL(set_gpio_toggle);
407
408
409/*Set current PORT date (16-bit word)*/
410
Michael Hennerich2b393312007-10-10 16:58:49 +0800411#define SET_GPIO_P(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800412void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800413{ \
414 unsigned long flags; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800415 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100416 flags = hard_local_irq_save(); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800417 gpio_array[gpio_bank(gpio)]->name = arg; \
418 if (ANOMALY_05000311 || ANOMALY_05000323) { \
419 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100420 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800421 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800422} \
423EXPORT_SYMBOL(set_gpiop_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700424
Michael Hennerich2b393312007-10-10 16:58:49 +0800425SET_GPIO_P(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700426SET_GPIO_P(dir)
427SET_GPIO_P(inen)
428SET_GPIO_P(polar)
429SET_GPIO_P(edge)
430SET_GPIO_P(both)
431SET_GPIO_P(maska)
432SET_GPIO_P(maskb)
433
Bryan Wu1394f032007-05-06 14:50:22 -0700434/* Get a specific bit */
Michael Hennerich2b393312007-10-10 16:58:49 +0800435#define GET_GPIO(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800436unsigned short get_gpio_ ## name(unsigned gpio) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800437{ \
438 unsigned long flags; \
439 unsigned short ret; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800440 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100441 flags = hard_local_irq_save(); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800442 ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \
443 if (ANOMALY_05000311 || ANOMALY_05000323) { \
444 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100445 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800446 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800447 return ret; \
448} \
449EXPORT_SYMBOL(get_gpio_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700450
Michael Hennerich2b393312007-10-10 16:58:49 +0800451GET_GPIO(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700452GET_GPIO(dir)
453GET_GPIO(inen)
454GET_GPIO(polar)
455GET_GPIO(edge)
456GET_GPIO(both)
457GET_GPIO(maska)
458GET_GPIO(maskb)
459
Bryan Wu1394f032007-05-06 14:50:22 -0700460/*Get current PORT date (16-bit word)*/
461
Michael Hennerich2b393312007-10-10 16:58:49 +0800462#define GET_GPIO_P(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800463unsigned short get_gpiop_ ## name(unsigned gpio) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800464{ \
465 unsigned long flags; \
466 unsigned short ret; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800467 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100468 flags = hard_local_irq_save(); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800469 ret = (gpio_array[gpio_bank(gpio)]->name); \
470 if (ANOMALY_05000311 || ANOMALY_05000323) { \
471 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100472 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800473 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800474 return ret; \
475} \
476EXPORT_SYMBOL(get_gpiop_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700477
Michael Hennerich2b393312007-10-10 16:58:49 +0800478GET_GPIO_P(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700479GET_GPIO_P(dir)
480GET_GPIO_P(inen)
481GET_GPIO_P(polar)
482GET_GPIO_P(edge)
483GET_GPIO_P(both)
484GET_GPIO_P(maska)
485GET_GPIO_P(maskb)
486
Bryan Wu1394f032007-05-06 14:50:22 -0700487
488#ifdef CONFIG_PM
Mike Frysinger332824b2010-06-02 04:22:01 +0000489DECLARE_RESERVED_MAP(wakeup, GPIO_BANK_NUM);
Mike Frysingerf5563092009-02-04 16:49:45 +0800490
491static const unsigned int sic_iwr_irqs[] = {
492#if defined(BF533_FAMILY)
493 IRQ_PROG_INTB
494#elif defined(BF537_FAMILY)
Mike Frysinger8c054102011-04-15 13:04:59 -0400495 IRQ_PF_INTB_WATCH, IRQ_PORTG_INTB, IRQ_PH_INTB_MAC_TX
Mike Frysingerf5563092009-02-04 16:49:45 +0800496#elif defined(BF538_FAMILY)
497 IRQ_PORTF_INTB
Mike Frysinger269647d2009-03-28 20:32:57 +0800498#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800499 IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB
500#elif defined(BF561_FAMILY)
501 IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB
502#else
503# error no SIC_IWR defined
504#endif
505};
506
Bryan Wu1394f032007-05-06 14:50:22 -0700507/***********************************************************
508*
509* FUNCTIONS: Blackfin PM Setup API
510*
511* INPUTS/OUTPUTS:
512* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
513* type -
514* PM_WAKE_RISING
515* PM_WAKE_FALLING
516* PM_WAKE_HIGH
517* PM_WAKE_LOW
518* PM_WAKE_BOTH_EDGES
519*
520* DESCRIPTION: Blackfin PM Driver API
521*
522* CAUTION:
523*************************************************************
524* MODIFICATION HISTORY :
525**************************************************************/
Sonic Zhang54e4ff42013-05-30 18:37:28 +0800526int bfin_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)
Bryan Wu1394f032007-05-06 14:50:22 -0700527{
528 unsigned long flags;
529
530 if (check_gpio(gpio) < 0)
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000531 return -EINVAL;
Bryan Wu1394f032007-05-06 14:50:22 -0700532
David Howells3b139cd2010-10-07 14:08:52 +0100533 flags = hard_local_irq_save();
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000534 if (ctrl)
Mike Frysinger332824b2010-06-02 04:22:01 +0000535 reserve(wakeup, gpio);
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000536 else
Mike Frysinger332824b2010-06-02 04:22:01 +0000537 unreserve(wakeup, gpio);
Bryan Wu1394f032007-05-06 14:50:22 -0700538
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000539 set_gpio_maskb(gpio, ctrl);
David Howells3b139cd2010-10-07 14:08:52 +0100540 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700541
542 return 0;
543}
544
Sonic Zhang54e4ff42013-05-30 18:37:28 +0800545int bfin_gpio_pm_standby_ctrl(unsigned ctrl)
Bryan Wu1394f032007-05-06 14:50:22 -0700546{
547 u16 bank, mask, i;
548
Mike Frysinger1f83b8f2007-07-12 22:58:21 +0800549 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Mike Frysinger332824b2010-06-02 04:22:01 +0000550 mask = map_entry(wakeup, i);
Bryan Wu1394f032007-05-06 14:50:22 -0700551 bank = gpio_bank(i);
552
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000553 if (mask)
554 bfin_internal_set_wake(sic_iwr_irqs[bank], ctrl);
Bryan Wu1394f032007-05-06 14:50:22 -0700555 }
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000556 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -0700557}
558
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800559void bfin_gpio_pm_hibernate_suspend(void)
560{
561 int i, bank;
562
Mike Frysinger9466a052011-06-27 14:46:14 -0400563#ifdef BF538_FAMILY
564 for (i = 0; i < ARRAY_SIZE(port_fer_saved); ++i)
565 port_fer_saved[i] = *port_fer[i];
566#endif
567
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800568 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
569 bank = gpio_bank(i);
570
Mike Frysinger269647d2009-03-28 20:32:57 +0800571#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800572 gpio_bank_saved[bank].fer = *port_fer[bank];
Mike Frysinger269647d2009-03-28 20:32:57 +0800573#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800574 gpio_bank_saved[bank].mux = *port_mux[bank];
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800575#else
Mike Frysingerf5563092009-02-04 16:49:45 +0800576 if (bank == 0)
577 gpio_bank_saved[bank].mux = bfin_read_PORT_MUX();
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800578#endif
579#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800580 gpio_bank_saved[bank].data = gpio_array[bank]->data;
581 gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
582 gpio_bank_saved[bank].polar = gpio_array[bank]->polar;
583 gpio_bank_saved[bank].dir = gpio_array[bank]->dir;
584 gpio_bank_saved[bank].edge = gpio_array[bank]->edge;
585 gpio_bank_saved[bank].both = gpio_array[bank]->both;
586 gpio_bank_saved[bank].maska = gpio_array[bank]->maska;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800587 }
588
Mike Frysinger9466a052011-06-27 14:46:14 -0400589#ifdef BFIN_SPECIAL_GPIO_BANKS
590 bfin_special_gpio_pm_hibernate_suspend();
591#endif
592
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800593 AWA_DUMMY_READ(maska);
594}
595
596void bfin_gpio_pm_hibernate_restore(void)
597{
598 int i, bank;
599
Mike Frysinger9466a052011-06-27 14:46:14 -0400600#ifdef BF538_FAMILY
601 for (i = 0; i < ARRAY_SIZE(port_fer_saved); ++i)
602 *port_fer[i] = port_fer_saved[i];
603#endif
604
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800605 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Mike Frysingerf5563092009-02-04 16:49:45 +0800606 bank = gpio_bank(i);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800607
Mike Frysinger269647d2009-03-28 20:32:57 +0800608#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
609#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800610 *port_mux[bank] = gpio_bank_saved[bank].mux;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800611#else
Mike Frysingerf5563092009-02-04 16:49:45 +0800612 if (bank == 0)
613 bfin_write_PORT_MUX(gpio_bank_saved[bank].mux);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800614#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800615 *port_fer[bank] = gpio_bank_saved[bank].fer;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800616#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800617 gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
Michael Hennerichc03c2a82009-07-08 12:04:43 +0000618 gpio_array[bank]->data_set = gpio_bank_saved[bank].data
619 & gpio_bank_saved[bank].dir;
Mike Frysingerf5563092009-02-04 16:49:45 +0800620 gpio_array[bank]->dir = gpio_bank_saved[bank].dir;
621 gpio_array[bank]->polar = gpio_bank_saved[bank].polar;
622 gpio_array[bank]->edge = gpio_bank_saved[bank].edge;
623 gpio_array[bank]->both = gpio_bank_saved[bank].both;
Mike Frysingerf5563092009-02-04 16:49:45 +0800624 gpio_array[bank]->maska = gpio_bank_saved[bank].maska;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800625 }
Mike Frysinger9466a052011-06-27 14:46:14 -0400626
627#ifdef BFIN_SPECIAL_GPIO_BANKS
628 bfin_special_gpio_pm_hibernate_restore();
629#endif
630
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800631 AWA_DUMMY_READ(maska);
632}
633
634
Bryan Wu1394f032007-05-06 14:50:22 -0700635#endif
636
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800637/***********************************************************
638*
Mike Frysinger812ae982010-07-05 08:40:41 +0000639* FUNCTIONS: Blackfin Peripheral Resource Allocation
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800640* and PortMux Setup
641*
642* INPUTS/OUTPUTS:
643* per Peripheral Identifier
644* label String
645*
646* DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API
647*
648* CAUTION:
649*************************************************************
650* MODIFICATION HISTORY :
651**************************************************************/
Michael Hennerichc58c2142007-10-04 00:35:05 +0800652
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800653int peripheral_request(unsigned short per, const char *label)
654{
655 unsigned long flags;
656 unsigned short ident = P_IDENT(per);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800657
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800658 /*
659 * Don't cares are pins with only one dedicated function
660 */
661
662 if (per & P_DONTCARE)
663 return 0;
664
665 if (!(per & P_DEFINED))
666 return -ENODEV;
667
Barry Song89e84ee2009-09-16 04:36:29 +0000668 BUG_ON(ident >= MAX_RESOURCES);
669
David Howells3b139cd2010-10-07 14:08:52 +0100670 flags = hard_local_irq_save();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800671
Mike Frysinger6a87d292008-10-28 16:16:29 +0800672 /* If a pin can be muxed as either GPIO or peripheral, make
673 * sure it is not already a GPIO pin when we request it.
674 */
Mike Frysinger332824b2010-06-02 04:22:01 +0000675 if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800676 if (system_state == SYSTEM_BOOTING)
677 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800678 printk(KERN_ERR
Mike Frysinger6c7ec0e2008-10-28 15:49:59 +0800679 "%s: Peripheral %d is already reserved as GPIO by %s !\n",
Harvey Harrisonb85d8582008-04-23 09:39:01 +0800680 __func__, ident, get_label(ident));
David Howells3b139cd2010-10-07 14:08:52 +0100681 hard_local_irq_restore(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800682 return -EBUSY;
683 }
684
Mike Frysinger332824b2010-06-02 04:22:01 +0000685 if (unlikely(is_reserved(peri, ident, 1))) {
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800686
Mike Frysingerd171c232008-03-26 08:35:46 +0800687 /*
688 * Pin functions like AMC address strobes my
689 * be requested and used by several drivers
690 */
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800691
Mike Frysinger6c7ec0e2008-10-28 15:49:59 +0800692 if (!(per & P_MAYSHARE)) {
Mike Frysingerd171c232008-03-26 08:35:46 +0800693 /*
694 * Allow that the identical pin function can
695 * be requested from the same driver twice
696 */
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800697
Mike Frysingerd171c232008-03-26 08:35:46 +0800698 if (cmp_label(ident, label) == 0)
699 goto anyway;
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800700
Robin Getzd6879c52009-03-29 01:10:30 +0800701 if (system_state == SYSTEM_BOOTING)
702 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800703 printk(KERN_ERR
704 "%s: Peripheral %d function %d is already reserved by %s !\n",
Harvey Harrisonb85d8582008-04-23 09:39:01 +0800705 __func__, ident, P_FUNCT2MUX(per), get_label(ident));
David Howells3b139cd2010-10-07 14:08:52 +0100706 hard_local_irq_restore(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800707 return -EBUSY;
708 }
709 }
710
steven miao05bbec32010-09-17 03:03:17 +0000711 if (unlikely(portmux_group_check(per))) {
712 hard_local_irq_restore(flags);
713 return -EBUSY;
714 }
Mike Frysingerd171c232008-03-26 08:35:46 +0800715 anyway:
Mike Frysinger332824b2010-06-02 04:22:01 +0000716 reserve(peri, ident);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800717
Mike Frysingerf5563092009-02-04 16:49:45 +0800718 portmux_setup(per);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800719 port_setup(ident, PERIPHERAL_USAGE);
720
David Howells3b139cd2010-10-07 14:08:52 +0100721 hard_local_irq_restore(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800722 set_label(ident, label);
723
724 return 0;
725}
726EXPORT_SYMBOL(peripheral_request);
727
Mike Frysinger68179372008-04-24 05:04:24 +0800728int peripheral_request_list(const unsigned short per[], const char *label)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800729{
730 u16 cnt;
731 int ret;
732
733 for (cnt = 0; per[cnt] != 0; cnt++) {
Michael Hennerich314c98d2007-07-24 18:03:45 +0800734
Michael Hennerichc58c2142007-10-04 00:35:05 +0800735 ret = peripheral_request(per[cnt], label);
Michael Hennerich314c98d2007-07-24 18:03:45 +0800736
737 if (ret < 0) {
Mike Frysingerd171c232008-03-26 08:35:46 +0800738 for ( ; cnt > 0; cnt--)
Michael Hennerich314c98d2007-07-24 18:03:45 +0800739 peripheral_free(per[cnt - 1]);
Mike Frysingerd171c232008-03-26 08:35:46 +0800740
741 return ret;
Michael Hennerich314c98d2007-07-24 18:03:45 +0800742 }
Michael Hennerichc58c2142007-10-04 00:35:05 +0800743 }
744
745 return 0;
746}
747EXPORT_SYMBOL(peripheral_request_list);
748
749void peripheral_free(unsigned short per)
750{
751 unsigned long flags;
752 unsigned short ident = P_IDENT(per);
753
754 if (per & P_DONTCARE)
755 return;
756
757 if (!(per & P_DEFINED))
758 return;
759
David Howells3b139cd2010-10-07 14:08:52 +0100760 flags = hard_local_irq_save();
Michael Hennerichc58c2142007-10-04 00:35:05 +0800761
Mike Frysinger332824b2010-06-02 04:22:01 +0000762 if (unlikely(!is_reserved(peri, ident, 0))) {
David Howells3b139cd2010-10-07 14:08:52 +0100763 hard_local_irq_restore(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800764 return;
765 }
766
Mike Frysingerd171c232008-03-26 08:35:46 +0800767 if (!(per & P_MAYSHARE))
Michael Hennerichc58c2142007-10-04 00:35:05 +0800768 port_setup(ident, GPIO_USAGE);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800769
Mike Frysinger332824b2010-06-02 04:22:01 +0000770 unreserve(peri, ident);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800771
Michael Hennerich2acde902007-10-11 00:24:40 +0800772 set_label(ident, "free");
773
David Howells3b139cd2010-10-07 14:08:52 +0100774 hard_local_irq_restore(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800775}
776EXPORT_SYMBOL(peripheral_free);
777
Mike Frysinger68179372008-04-24 05:04:24 +0800778void peripheral_free_list(const unsigned short per[])
Michael Hennerichc58c2142007-10-04 00:35:05 +0800779{
780 u16 cnt;
Mike Frysingerd171c232008-03-26 08:35:46 +0800781 for (cnt = 0; per[cnt] != 0; cnt++)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800782 peripheral_free(per[cnt]);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800783}
784EXPORT_SYMBOL(peripheral_free_list);
785
Bryan Wu1394f032007-05-06 14:50:22 -0700786/***********************************************************
787*
788* FUNCTIONS: Blackfin GPIO Driver
789*
790* INPUTS/OUTPUTS:
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800791* gpio PIO Number between 0 and MAX_BLACKFIN_GPIOS
792* label String
Bryan Wu1394f032007-05-06 14:50:22 -0700793*
794* DESCRIPTION: Blackfin GPIO Driver API
795*
796* CAUTION:
797*************************************************************
798* MODIFICATION HISTORY :
799**************************************************************/
800
Michael Hennericha4f0b32c2008-11-18 17:48:22 +0800801int bfin_gpio_request(unsigned gpio, const char *label)
Bryan Wu1394f032007-05-06 14:50:22 -0700802{
803 unsigned long flags;
804
805 if (check_gpio(gpio) < 0)
806 return -EINVAL;
807
David Howells3b139cd2010-10-07 14:08:52 +0100808 flags = hard_local_irq_save();
Bryan Wu1394f032007-05-06 14:50:22 -0700809
Michael Hennerich2acde902007-10-11 00:24:40 +0800810 /*
811 * Allow that the identical GPIO can
812 * be requested from the same driver twice
813 * Do nothing and return -
814 */
815
816 if (cmp_label(gpio, label) == 0) {
David Howells3b139cd2010-10-07 14:08:52 +0100817 hard_local_irq_restore(flags);
Michael Hennerich2acde902007-10-11 00:24:40 +0800818 return 0;
819 }
820
Mike Frysinger332824b2010-06-02 04:22:01 +0000821 if (unlikely(is_reserved(gpio, gpio, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800822 if (system_state == SYSTEM_BOOTING)
823 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800824 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
Graf Yang9570ff42009-01-07 23:14:38 +0800825 gpio, get_label(gpio));
David Howells3b139cd2010-10-07 14:08:52 +0100826 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700827 return -EBUSY;
828 }
Mike Frysinger332824b2010-06-02 04:22:01 +0000829 if (unlikely(is_reserved(peri, gpio, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800830 if (system_state == SYSTEM_BOOTING)
831 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800832 printk(KERN_ERR
833 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
834 gpio, get_label(gpio));
David Howells3b139cd2010-10-07 14:08:52 +0100835 hard_local_irq_restore(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800836 return -EBUSY;
837 }
Mike Frysinger332824b2010-06-02 04:22:01 +0000838 if (unlikely(is_reserved(gpio_irq, gpio, 1))) {
Graf Yang9570ff42009-01-07 23:14:38 +0800839 printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!"
840 " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio);
Sonic Zhang54e4ff42013-05-30 18:37:28 +0800841 } else { /* Reset POLAR setting when acquiring a gpio for the first time */
Michael Hennericha2be3932009-02-04 16:49:45 +0800842 set_gpio_polar(gpio, 0);
843 }
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800844
Mike Frysinger332824b2010-06-02 04:22:01 +0000845 reserve(gpio, gpio);
Graf Yang9570ff42009-01-07 23:14:38 +0800846 set_label(gpio, label);
Bryan Wu1394f032007-05-06 14:50:22 -0700847
David Howells3b139cd2010-10-07 14:08:52 +0100848 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700849
850 port_setup(gpio, GPIO_USAGE);
851
852 return 0;
853}
Michael Hennericha4f0b32c2008-11-18 17:48:22 +0800854EXPORT_SYMBOL(bfin_gpio_request);
Bryan Wu1394f032007-05-06 14:50:22 -0700855
Michael Hennericha4f0b32c2008-11-18 17:48:22 +0800856void bfin_gpio_free(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -0700857{
858 unsigned long flags;
859
860 if (check_gpio(gpio) < 0)
861 return;
862
Uwe Kleine-Koenig45c4f2a2009-02-04 17:02:30 +0800863 might_sleep();
864
David Howells3b139cd2010-10-07 14:08:52 +0100865 flags = hard_local_irq_save();
Bryan Wu1394f032007-05-06 14:50:22 -0700866
Mike Frysinger332824b2010-06-02 04:22:01 +0000867 if (unlikely(!is_reserved(gpio, gpio, 0))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800868 if (system_state == SYSTEM_BOOTING)
869 dump_stack();
Mike Frysingerf85c4ab2008-03-26 08:34:23 +0800870 gpio_error(gpio);
David Howells3b139cd2010-10-07 14:08:52 +0100871 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700872 return;
873 }
874
Mike Frysinger332824b2010-06-02 04:22:01 +0000875 unreserve(gpio, gpio);
Bryan Wu1394f032007-05-06 14:50:22 -0700876
Michael Hennerich2acde902007-10-11 00:24:40 +0800877 set_label(gpio, "free");
878
David Howells3b139cd2010-10-07 14:08:52 +0100879 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700880}
Michael Hennericha4f0b32c2008-11-18 17:48:22 +0800881EXPORT_SYMBOL(bfin_gpio_free);
Bryan Wu1394f032007-05-06 14:50:22 -0700882
Michael Hennerich621dd242009-09-28 12:23:41 +0000883#ifdef BFIN_SPECIAL_GPIO_BANKS
Mike Frysinger332824b2010-06-02 04:22:01 +0000884DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES));
Michael Hennerich621dd242009-09-28 12:23:41 +0000885
886int bfin_special_gpio_request(unsigned gpio, const char *label)
887{
888 unsigned long flags;
889
David Howells3b139cd2010-10-07 14:08:52 +0100890 flags = hard_local_irq_save();
Michael Hennerich621dd242009-09-28 12:23:41 +0000891
892 /*
893 * Allow that the identical GPIO can
894 * be requested from the same driver twice
895 * Do nothing and return -
896 */
897
898 if (cmp_label(gpio, label) == 0) {
David Howells3b139cd2010-10-07 14:08:52 +0100899 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +0000900 return 0;
901 }
902
Mike Frysinger332824b2010-06-02 04:22:01 +0000903 if (unlikely(is_reserved(special_gpio, gpio, 1))) {
David Howells3b139cd2010-10-07 14:08:52 +0100904 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +0000905 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
906 gpio, get_label(gpio));
907
908 return -EBUSY;
909 }
Mike Frysinger332824b2010-06-02 04:22:01 +0000910 if (unlikely(is_reserved(peri, gpio, 1))) {
David Howells3b139cd2010-10-07 14:08:52 +0100911 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +0000912 printk(KERN_ERR
913 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
914 gpio, get_label(gpio));
915
916 return -EBUSY;
917 }
918
Mike Frysinger332824b2010-06-02 04:22:01 +0000919 reserve(special_gpio, gpio);
920 reserve(peri, gpio);
Michael Hennerich621dd242009-09-28 12:23:41 +0000921
922 set_label(gpio, label);
David Howells3b139cd2010-10-07 14:08:52 +0100923 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +0000924 port_setup(gpio, GPIO_USAGE);
925
926 return 0;
927}
928EXPORT_SYMBOL(bfin_special_gpio_request);
929
930void bfin_special_gpio_free(unsigned gpio)
931{
932 unsigned long flags;
933
934 might_sleep();
935
David Howells3b139cd2010-10-07 14:08:52 +0100936 flags = hard_local_irq_save();
Michael Hennerich621dd242009-09-28 12:23:41 +0000937
Mike Frysinger332824b2010-06-02 04:22:01 +0000938 if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
Michael Hennerich621dd242009-09-28 12:23:41 +0000939 gpio_error(gpio);
David Howells3b139cd2010-10-07 14:08:52 +0100940 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +0000941 return;
942 }
943
Mike Frysinger332824b2010-06-02 04:22:01 +0000944 unreserve(special_gpio, gpio);
945 unreserve(peri, gpio);
Michael Hennerich621dd242009-09-28 12:23:41 +0000946 set_label(gpio, "free");
David Howells3b139cd2010-10-07 14:08:52 +0100947 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +0000948}
949EXPORT_SYMBOL(bfin_special_gpio_free);
950#endif
951
952
Graf Yang9570ff42009-01-07 23:14:38 +0800953int bfin_gpio_irq_request(unsigned gpio, const char *label)
954{
955 unsigned long flags;
956
957 if (check_gpio(gpio) < 0)
958 return -EINVAL;
959
David Howells3b139cd2010-10-07 14:08:52 +0100960 flags = hard_local_irq_save();
Graf Yang9570ff42009-01-07 23:14:38 +0800961
Mike Frysinger332824b2010-06-02 04:22:01 +0000962 if (unlikely(is_reserved(peri, gpio, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800963 if (system_state == SYSTEM_BOOTING)
964 dump_stack();
Graf Yang9570ff42009-01-07 23:14:38 +0800965 printk(KERN_ERR
966 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
967 gpio, get_label(gpio));
David Howells3b139cd2010-10-07 14:08:52 +0100968 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +0800969 return -EBUSY;
970 }
Mike Frysinger332824b2010-06-02 04:22:01 +0000971 if (unlikely(is_reserved(gpio, gpio, 1)))
Graf Yang9570ff42009-01-07 23:14:38 +0800972 printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved by %s! "
973 "(Documentation/blackfin/bfin-gpio-notes.txt)\n",
974 gpio, get_label(gpio));
975
Mike Frysinger332824b2010-06-02 04:22:01 +0000976 reserve(gpio_irq, gpio);
Graf Yang9570ff42009-01-07 23:14:38 +0800977 set_label(gpio, label);
978
David Howells3b139cd2010-10-07 14:08:52 +0100979 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +0800980
981 port_setup(gpio, GPIO_USAGE);
982
983 return 0;
984}
985
986void bfin_gpio_irq_free(unsigned gpio)
987{
988 unsigned long flags;
989
990 if (check_gpio(gpio) < 0)
991 return;
992
David Howells3b139cd2010-10-07 14:08:52 +0100993 flags = hard_local_irq_save();
Graf Yang9570ff42009-01-07 23:14:38 +0800994
Mike Frysinger332824b2010-06-02 04:22:01 +0000995 if (unlikely(!is_reserved(gpio_irq, gpio, 0))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800996 if (system_state == SYSTEM_BOOTING)
997 dump_stack();
Graf Yang9570ff42009-01-07 23:14:38 +0800998 gpio_error(gpio);
David Howells3b139cd2010-10-07 14:08:52 +0100999 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001000 return;
1001 }
1002
Mike Frysinger332824b2010-06-02 04:22:01 +00001003 unreserve(gpio_irq, gpio);
Graf Yang9570ff42009-01-07 23:14:38 +08001004
1005 set_label(gpio, "free");
1006
David Howells3b139cd2010-10-07 14:08:52 +01001007 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001008}
1009
Mike Frysingerf5563092009-02-04 16:49:45 +08001010static inline void __bfin_gpio_direction_input(unsigned gpio)
1011{
Mike Frysingerf5563092009-02-04 16:49:45 +08001012 gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
Mike Frysingerf5563092009-02-04 16:49:45 +08001013 gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
Michael Hennerich803a8d22008-05-17 16:01:51 +08001014}
Michael Hennerich803a8d22008-05-17 16:01:51 +08001015
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001016int bfin_gpio_direction_input(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -07001017{
1018 unsigned long flags;
1019
Mike Frysinger332824b2010-06-02 04:22:01 +00001020 if (unlikely(!is_reserved(gpio, gpio, 0))) {
Michael Hennerichacbcd262008-01-22 18:36:20 +08001021 gpio_error(gpio);
1022 return -EINVAL;
1023 }
Bryan Wu1394f032007-05-06 14:50:22 -07001024
David Howells3b139cd2010-10-07 14:08:52 +01001025 flags = hard_local_irq_save();
Mike Frysingerf5563092009-02-04 16:49:45 +08001026 __bfin_gpio_direction_input(gpio);
Michael Hennerich2b393312007-10-10 16:58:49 +08001027 AWA_DUMMY_READ(inen);
David Howells3b139cd2010-10-07 14:08:52 +01001028 hard_local_irq_restore(flags);
Michael Hennerichacbcd262008-01-22 18:36:20 +08001029
1030 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -07001031}
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001032EXPORT_SYMBOL(bfin_gpio_direction_input);
Bryan Wu1394f032007-05-06 14:50:22 -07001033
Mike Frysingerf5563092009-02-04 16:49:45 +08001034void bfin_gpio_irq_prepare(unsigned gpio)
1035{
Mike Frysingerf5563092009-02-04 16:49:45 +08001036 port_setup(gpio, GPIO_USAGE);
Mike Frysingerf5563092009-02-04 16:49:45 +08001037}
1038
1039void bfin_gpio_set_value(unsigned gpio, int arg)
1040{
1041 if (arg)
1042 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
1043 else
1044 gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
1045}
1046EXPORT_SYMBOL(bfin_gpio_set_value);
1047
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001048int bfin_gpio_direction_output(unsigned gpio, int value)
Bryan Wu1394f032007-05-06 14:50:22 -07001049{
1050 unsigned long flags;
1051
Mike Frysinger332824b2010-06-02 04:22:01 +00001052 if (unlikely(!is_reserved(gpio, gpio, 0))) {
Michael Hennerichacbcd262008-01-22 18:36:20 +08001053 gpio_error(gpio);
1054 return -EINVAL;
1055 }
Bryan Wu1394f032007-05-06 14:50:22 -07001056
David Howells3b139cd2010-10-07 14:08:52 +01001057 flags = hard_local_irq_save();
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001058
Mike Frysingerf5563092009-02-04 16:49:45 +08001059 gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
1060 gpio_set_value(gpio, value);
Mike Frysingerf5563092009-02-04 16:49:45 +08001061 gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001062
Michael Hennerich2b393312007-10-10 16:58:49 +08001063 AWA_DUMMY_READ(dir);
David Howells3b139cd2010-10-07 14:08:52 +01001064 hard_local_irq_restore(flags);
Michael Hennerichacbcd262008-01-22 18:36:20 +08001065
1066 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -07001067}
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001068EXPORT_SYMBOL(bfin_gpio_direction_output);
Mike Frysinger168f1212007-10-11 00:22:35 +08001069
Mike Frysingerf5563092009-02-04 16:49:45 +08001070int bfin_gpio_get_value(unsigned gpio)
1071{
Mike Frysingerf5563092009-02-04 16:49:45 +08001072 unsigned long flags;
1073
1074 if (unlikely(get_gpio_edge(gpio))) {
1075 int ret;
David Howells3b139cd2010-10-07 14:08:52 +01001076 flags = hard_local_irq_save();
Mike Frysingerf5563092009-02-04 16:49:45 +08001077 set_gpio_edge(gpio, 0);
1078 ret = get_gpio_data(gpio);
1079 set_gpio_edge(gpio, 1);
David Howells3b139cd2010-10-07 14:08:52 +01001080 hard_local_irq_restore(flags);
Mike Frysingerf5563092009-02-04 16:49:45 +08001081 return ret;
1082 } else
1083 return get_gpio_data(gpio);
Mike Frysingerf5563092009-02-04 16:49:45 +08001084}
1085EXPORT_SYMBOL(bfin_gpio_get_value);
1086
Mike Frysinger168f1212007-10-11 00:22:35 +08001087/* If we are booting from SPI and our board lacks a strong enough pull up,
1088 * the core can reset and execute the bootrom faster than the resistor can
1089 * pull the signal logically high. To work around this (common) error in
1090 * board design, we explicitly set the pin back to GPIO mode, force /CS
1091 * high, and wait for the electrons to do their thing.
1092 *
1093 * This function only makes sense to be called from reset code, but it
1094 * lives here as we need to force all the GPIO states w/out going through
1095 * BUG() checks and such.
1096 */
Sonic Zhangb52dae32009-02-04 16:49:45 +08001097void bfin_reset_boot_spi_cs(unsigned short pin)
Mike Frysinger168f1212007-10-11 00:22:35 +08001098{
Sonic Zhangb52dae32009-02-04 16:49:45 +08001099 unsigned short gpio = P_IDENT(pin);
Michael Hennerich4d5f4ed2007-08-27 16:46:17 +08001100 port_setup(gpio, GPIO_USAGE);
Mike Frysingerf5563092009-02-04 16:49:45 +08001101 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001102 AWA_DUMMY_READ(data_set);
Mike Frysinger168f1212007-10-11 00:22:35 +08001103 udelay(1);
1104}
Michael Hennerichd2b11a42007-08-28 16:47:46 +08001105
Mike Frysinger1545a112007-12-24 16:54:48 +08001106#if defined(CONFIG_PROC_FS)
Alexey Dobriyan6362ec22011-05-14 19:48:46 +03001107static int gpio_proc_show(struct seq_file *m, void *v)
Mike Frysinger1545a112007-12-24 16:54:48 +08001108{
Alexey Dobriyan6362ec22011-05-14 19:48:46 +03001109 int c, irq, gpio;
Mike Frysinger1545a112007-12-24 16:54:48 +08001110
1111 for (c = 0; c < MAX_RESOURCES; c++) {
Mike Frysinger332824b2010-06-02 04:22:01 +00001112 irq = is_reserved(gpio_irq, c, 1);
1113 gpio = is_reserved(gpio, c, 1);
Graf Yang9570ff42009-01-07 23:14:38 +08001114 if (!check_gpio(c) && (gpio || irq))
Alexey Dobriyan6362ec22011-05-14 19:48:46 +03001115 seq_printf(m, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c,
Graf Yang9570ff42009-01-07 23:14:38 +08001116 get_label(c), (gpio && irq) ? " *" : "",
1117 get_gpio_dir(c) ? "OUTPUT" : "INPUT");
Mike Frysinger332824b2010-06-02 04:22:01 +00001118 else if (is_reserved(peri, c, 1))
Alexey Dobriyan6362ec22011-05-14 19:48:46 +03001119 seq_printf(m, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c));
Mike Frysinger1545a112007-12-24 16:54:48 +08001120 else
1121 continue;
Mike Frysinger1545a112007-12-24 16:54:48 +08001122 }
Alexey Dobriyan6362ec22011-05-14 19:48:46 +03001123
1124 return 0;
Mike Frysinger1545a112007-12-24 16:54:48 +08001125}
1126
Alexey Dobriyan6362ec22011-05-14 19:48:46 +03001127static int gpio_proc_open(struct inode *inode, struct file *file)
1128{
1129 return single_open(file, gpio_proc_show, NULL);
1130}
1131
1132static const struct file_operations gpio_proc_ops = {
1133 .open = gpio_proc_open,
1134 .read = seq_read,
1135 .llseek = seq_lseek,
1136 .release = single_release,
1137};
1138
Mike Frysinger1545a112007-12-24 16:54:48 +08001139static __init int gpio_register_proc(void)
1140{
1141 struct proc_dir_entry *proc_gpio;
1142
Steven Miaoce860912012-08-16 13:41:47 +08001143 proc_gpio = proc_create("gpio", 0, NULL, &gpio_proc_ops);
1144 return proc_gpio == NULL;
Mike Frysinger1545a112007-12-24 16:54:48 +08001145}
Mike Frysinger1545a112007-12-24 16:54:48 +08001146__initcall(gpio_register_proc);
1147#endif
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001148
1149#ifdef CONFIG_GPIOLIB
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001150static int bfin_gpiolib_direction_input(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001151{
1152 return bfin_gpio_direction_input(gpio);
1153}
1154
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001155static int bfin_gpiolib_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001156{
1157 return bfin_gpio_direction_output(gpio, level);
1158}
1159
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001160static int bfin_gpiolib_get_value(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001161{
1162 return bfin_gpio_get_value(gpio);
1163}
1164
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001165static void bfin_gpiolib_set_value(struct gpio_chip *chip, unsigned gpio, int value)
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001166{
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001167 return bfin_gpio_set_value(gpio, value);
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001168}
1169
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001170static int bfin_gpiolib_gpio_request(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001171{
1172 return bfin_gpio_request(gpio, chip->label);
1173}
1174
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001175static void bfin_gpiolib_gpio_free(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001176{
1177 return bfin_gpio_free(gpio);
1178}
1179
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001180static int bfin_gpiolib_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
Joachim Eastwood7f4f69f2010-02-10 12:31:41 +01001181{
1182 return gpio + GPIO_IRQ_BASE;
1183}
1184
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001185static struct gpio_chip bfin_chip = {
Michael Hennerichedd07992009-12-16 08:45:17 +00001186 .label = "BFIN-GPIO",
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001187 .direction_input = bfin_gpiolib_direction_input,
1188 .get = bfin_gpiolib_get_value,
1189 .direction_output = bfin_gpiolib_direction_output,
1190 .set = bfin_gpiolib_set_value,
1191 .request = bfin_gpiolib_gpio_request,
1192 .free = bfin_gpiolib_gpio_free,
Joachim Eastwood7f4f69f2010-02-10 12:31:41 +01001193 .to_irq = bfin_gpiolib_gpio_to_irq,
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001194 .base = 0,
1195 .ngpio = MAX_BLACKFIN_GPIOS,
1196};
1197
1198static int __init bfin_gpiolib_setup(void)
1199{
1200 return gpiochip_add(&bfin_chip);
1201}
1202arch_initcall(bfin_gpiolib_setup);
1203#endif