blob: 02796b88443de4ebd2aef9e089f0893723607695 [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>
Bryan Wu1394f032007-05-06 14:50:22 -070014#include <asm/blackfin.h>
15#include <asm/gpio.h>
Michael Hennerichc58c2142007-10-04 00:35:05 +080016#include <asm/portmux.h>
Bryan Wu1394f032007-05-06 14:50:22 -070017#include <linux/irq.h>
Mike Frysinger6327a572011-04-15 03:06:59 -040018#include <asm/irq_handler.h>
Bryan Wu1394f032007-05-06 14:50:22 -070019
Michael Hennerich2b393312007-10-10 16:58:49 +080020#if ANOMALY_05000311 || ANOMALY_05000323
21enum {
22 AWA_data = SYSCR,
23 AWA_data_clear = SYSCR,
24 AWA_data_set = SYSCR,
25 AWA_toggle = SYSCR,
Graf Yang6ed83942008-04-24 04:43:14 +080026 AWA_maska = BFIN_UART_SCR,
27 AWA_maska_clear = BFIN_UART_SCR,
28 AWA_maska_set = BFIN_UART_SCR,
29 AWA_maska_toggle = BFIN_UART_SCR,
30 AWA_maskb = BFIN_UART_GCTL,
31 AWA_maskb_clear = BFIN_UART_GCTL,
32 AWA_maskb_set = BFIN_UART_GCTL,
33 AWA_maskb_toggle = BFIN_UART_GCTL,
Michael Hennerich2b393312007-10-10 16:58:49 +080034 AWA_dir = SPORT1_STAT,
35 AWA_polar = SPORT1_STAT,
36 AWA_edge = SPORT1_STAT,
37 AWA_both = SPORT1_STAT,
38#if ANOMALY_05000311
39 AWA_inen = TIMER_ENABLE,
40#elif ANOMALY_05000323
41 AWA_inen = DMA1_1_CONFIG,
42#endif
43};
44 /* Anomaly Workaround */
45#define AWA_DUMMY_READ(name) bfin_read16(AWA_ ## name)
46#else
47#define AWA_DUMMY_READ(...) do { } while (0)
48#endif
49
Mike Frysingerf5563092009-02-04 16:49:45 +080050static struct gpio_port_t * const gpio_array[] = {
Michael Hennerichdc26aec2008-11-18 17:48:22 +080051#if defined(BF533_FAMILY) || defined(BF538_FAMILY)
Bryan Wu1394f032007-05-06 14:50:22 -070052 (struct gpio_port_t *) FIO_FLAG_D,
Mike Frysinger269647d2009-03-28 20:32:57 +080053#elif defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Bryan Wu1394f032007-05-06 14:50:22 -070054 (struct gpio_port_t *) PORTFIO,
55 (struct gpio_port_t *) PORTGIO,
56 (struct gpio_port_t *) PORTHIO,
Mike Frysingerf5563092009-02-04 16:49:45 +080057#elif defined(BF561_FAMILY)
58 (struct gpio_port_t *) FIO0_FLAG_D,
59 (struct gpio_port_t *) FIO1_FLAG_D,
60 (struct gpio_port_t *) FIO2_FLAG_D,
Mike Frysinger269647d2009-03-28 20:32:57 +080061#elif defined(CONFIG_BF54x)
Mike Frysingerf5563092009-02-04 16:49:45 +080062 (struct gpio_port_t *)PORTA_FER,
63 (struct gpio_port_t *)PORTB_FER,
64 (struct gpio_port_t *)PORTC_FER,
65 (struct gpio_port_t *)PORTD_FER,
66 (struct gpio_port_t *)PORTE_FER,
67 (struct gpio_port_t *)PORTF_FER,
68 (struct gpio_port_t *)PORTG_FER,
69 (struct gpio_port_t *)PORTH_FER,
70 (struct gpio_port_t *)PORTI_FER,
71 (struct gpio_port_t *)PORTJ_FER,
72#else
73# error no gpio arrays defined
74#endif
Bryan Wu1394f032007-05-06 14:50:22 -070075};
76
Mike Frysinger269647d2009-03-28 20:32:57 +080077#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +080078static unsigned short * const port_fer[] = {
Bryan Wu1394f032007-05-06 14:50:22 -070079 (unsigned short *) PORTF_FER,
80 (unsigned short *) PORTG_FER,
81 (unsigned short *) PORTH_FER,
82};
Bryan Wu1394f032007-05-06 14:50:22 -070083
Mike Frysingerf5563092009-02-04 16:49:45 +080084# if !defined(BF537_FAMILY)
85static unsigned short * const port_mux[] = {
Michael Hennerich59003142007-10-21 16:54:27 +080086 (unsigned short *) PORTF_MUX,
87 (unsigned short *) PORTG_MUX,
88 (unsigned short *) PORTH_MUX,
89};
90
91static const
Graf Yang0ce5eaf2009-02-04 16:49:45 +080092u8 pmux_offset[][16] = {
Mike Frysinger269647d2009-03-28 20:32:57 +080093# if defined(CONFIG_BF52x)
Graf Yang0ce5eaf2009-02-04 16:49:45 +080094 { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */
95 { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */
96 { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */
Mike Frysinger269647d2009-03-28 20:32:57 +080097# elif defined(CONFIG_BF51x)
Graf Yang0ce5eaf2009-02-04 16:49:45 +080098 { 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */
99 { 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */
100 { 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */
101# endif
102};
Mike Frysingerf5563092009-02-04 16:49:45 +0800103# endif
Graf Yang0ce5eaf2009-02-04 16:49:45 +0800104
Michael Hennerich621dd242009-09-28 12:23:41 +0000105#elif defined(BF538_FAMILY)
106static unsigned short * const port_fer[] = {
107 (unsigned short *) PORTCIO_FER,
108 (unsigned short *) PORTDIO_FER,
109 (unsigned short *) PORTEIO_FER,
110};
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800111#endif
112
Mike Frysinger812ae982010-07-05 08:40:41 +0000113#define RESOURCE_LABEL_SIZE 16
Michael Hennerich8c613622007-08-03 17:48:09 +0800114
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800115static struct str_ident {
Michael Hennerich8c613622007-08-03 17:48:09 +0800116 char name[RESOURCE_LABEL_SIZE];
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800117} str_ident[MAX_RESOURCES];
Bryan Wu1394f032007-05-06 14:50:22 -0700118
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800119#if defined(CONFIG_PM)
Bryan Wu397861c2008-11-18 17:48:22 +0800120static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM];
Mike Frysinger9466a052011-06-27 14:46:14 -0400121# ifdef BF538_FAMILY
122static unsigned short port_fer_saved[3];
123# endif
Bryan Wu1394f032007-05-06 14:50:22 -0700124#endif
125
Mike Frysinger74c04502008-10-08 16:13:17 +0800126static void gpio_error(unsigned gpio)
Michael Hennerichacbcd262008-01-22 18:36:20 +0800127{
128 printk(KERN_ERR "bfin-gpio: GPIO %d wasn't requested!\n", gpio);
129}
130
Michael Hennerichc58c2142007-10-04 00:35:05 +0800131static void set_label(unsigned short ident, const char *label)
132{
Michael Henneriche9fae182008-10-13 11:35:22 +0800133 if (label) {
Michael Hennerich8c613622007-08-03 17:48:09 +0800134 strncpy(str_ident[ident].name, label,
Michael Hennerichc58c2142007-10-04 00:35:05 +0800135 RESOURCE_LABEL_SIZE);
Michael Hennerich8c613622007-08-03 17:48:09 +0800136 str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800137 }
138}
139
140static char *get_label(unsigned short ident)
141{
Michael Hennerich8c613622007-08-03 17:48:09 +0800142 return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN");
Michael Hennerichc58c2142007-10-04 00:35:05 +0800143}
144
145static int cmp_label(unsigned short ident, const char *label)
146{
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800147 if (label == NULL) {
148 dump_stack();
149 printk(KERN_ERR "Please provide none-null label\n");
150 }
151
Michael Henneriche9fae182008-10-13 11:35:22 +0800152 if (label)
Mike Frysinger1f7d3732008-10-28 15:47:11 +0800153 return strcmp(str_ident[ident].name, label);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800154 else
155 return -EINVAL;
156}
157
Mike Frysinger332824b2010-06-02 04:22:01 +0000158#define map_entry(m, i) reserved_##m##_map[gpio_bank(i)]
159#define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i))
160#define reserve(m, i) (map_entry(m, i) |= gpio_bit(i))
161#define unreserve(m, i) (map_entry(m, i) &= ~gpio_bit(i))
162#define DECLARE_RESERVED_MAP(m, c) static unsigned short reserved_##m##_map[c]
163
164DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM);
Michael Hennerich382dbe52010-07-13 08:26:10 +0000165DECLARE_RESERVED_MAP(peri, DIV_ROUND_UP(MAX_RESOURCES, GPIO_BANKSIZE));
Mike Frysinger332824b2010-06-02 04:22:01 +0000166DECLARE_RESERVED_MAP(gpio_irq, GPIO_BANK_NUM);
167
168inline int check_gpio(unsigned gpio)
169{
170#if defined(CONFIG_BF54x)
171 if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
172 || gpio == GPIO_PH14 || gpio == GPIO_PH15
173 || gpio == GPIO_PJ14 || gpio == GPIO_PJ15)
174 return -EINVAL;
175#endif
176 if (gpio >= MAX_BLACKFIN_GPIOS)
177 return -EINVAL;
178 return 0;
179}
180
Mike Frysingera2d03a12008-10-28 15:53:37 +0800181static void port_setup(unsigned gpio, unsigned short usage)
182{
Michael Hennerich621dd242009-09-28 12:23:41 +0000183#if defined(BF538_FAMILY)
184 /*
185 * BF538/9 Port C,D and E are special.
186 * Inverted PORT_FER polarity on CDE and no PORF_FER on F
187 * Regular PORT F GPIOs are handled here, CDE are exclusively
188 * managed by GPIOLIB
189 */
190
191 if (gpio < MAX_BLACKFIN_GPIOS || gpio >= MAX_RESOURCES)
192 return;
193
194 gpio -= MAX_BLACKFIN_GPIOS;
195
196 if (usage == GPIO_USAGE)
197 *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
198 else
199 *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
200 SSYNC();
201 return;
202#endif
203
Mike Frysingera2d03a12008-10-28 15:53:37 +0800204 if (check_gpio(gpio))
205 return;
206
Mike Frysinger269647d2009-03-28 20:32:57 +0800207#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Mike Frysingera2d03a12008-10-28 15:53:37 +0800208 if (usage == GPIO_USAGE)
209 *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
210 else
211 *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
212 SSYNC();
Mike Frysinger269647d2009-03-28 20:32:57 +0800213#elif defined(CONFIG_BF54x)
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800214 if (usage == GPIO_USAGE)
215 gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
216 else
217 gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
218 SSYNC();
Bryan Wu1394f032007-05-06 14:50:22 -0700219#endif
Mike Frysingera2d03a12008-10-28 15:53:37 +0800220}
Bryan Wu1394f032007-05-06 14:50:22 -0700221
Michael Hennerichc58c2142007-10-04 00:35:05 +0800222#ifdef BF537_FAMILY
steven miao05bbec32010-09-17 03:03:17 +0000223static const s8 port_mux[] = {
224 [GPIO_PF0] = 3,
225 [GPIO_PF1] = 3,
226 [GPIO_PF2] = 4,
227 [GPIO_PF3] = 4,
228 [GPIO_PF4] = 5,
229 [GPIO_PF5] = 6,
230 [GPIO_PF6] = 7,
231 [GPIO_PF7] = 8,
232 [GPIO_PF8 ... GPIO_PF15] = -1,
233 [GPIO_PG0 ... GPIO_PG7] = -1,
234 [GPIO_PG8] = 9,
235 [GPIO_PG9] = 9,
236 [GPIO_PG10] = 10,
237 [GPIO_PG11] = 10,
238 [GPIO_PG12] = 10,
239 [GPIO_PG13] = 11,
240 [GPIO_PG14] = 11,
241 [GPIO_PG15] = 11,
242 [GPIO_PH0 ... GPIO_PH15] = -1,
243 [PORT_PJ0 ... PORT_PJ3] = -1,
244 [PORT_PJ4] = 1,
245 [PORT_PJ5] = 1,
246 [PORT_PJ6 ... PORT_PJ9] = -1,
247 [PORT_PJ10] = 0,
248 [PORT_PJ11] = 0,
Michael Hennerichc58c2142007-10-04 00:35:05 +0800249};
250
steven miao05bbec32010-09-17 03:03:17 +0000251static int portmux_group_check(unsigned short per)
252{
253 u16 ident = P_IDENT(per);
254 u16 function = P_FUNCT2MUX(per);
255 s8 offset = port_mux[ident];
256 u16 m, pmux, pfunc;
257
258 if (offset < 0)
259 return 0;
260
261 pmux = bfin_read_PORT_MUX();
262 for (m = 0; m < ARRAY_SIZE(port_mux); ++m) {
263 if (m == ident)
264 continue;
265 if (port_mux[m] != offset)
266 continue;
267 if (!is_reserved(peri, m, 1))
268 continue;
269
270 if (offset == 1)
271 pfunc = (pmux >> offset) & 3;
272 else
273 pfunc = (pmux >> offset) & 1;
274 if (pfunc != function) {
275 pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",
276 ident, function, m, pfunc);
277 return -EINVAL;
278 }
279 }
280
281 return 0;
282}
283
Mike Frysingerf5563092009-02-04 16:49:45 +0800284static void portmux_setup(unsigned short per)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800285{
steven miao05bbec32010-09-17 03:03:17 +0000286 u16 ident = P_IDENT(per);
Mike Frysingerf5563092009-02-04 16:49:45 +0800287 u16 function = P_FUNCT2MUX(per);
steven miao05bbec32010-09-17 03:03:17 +0000288 s8 offset = port_mux[ident];
289 u16 pmux;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800290
steven miao05bbec32010-09-17 03:03:17 +0000291 if (offset == -1)
292 return;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800293
steven miao05bbec32010-09-17 03:03:17 +0000294 pmux = bfin_read_PORT_MUX();
295 if (offset != 1)
296 pmux &= ~(1 << offset);
297 else
298 pmux &= ~(3 << 1);
299 pmux |= (function << offset);
300 bfin_write_PORT_MUX(pmux);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800301}
Mike Frysinger269647d2009-03-28 20:32:57 +0800302#elif defined(CONFIG_BF54x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800303inline void portmux_setup(unsigned short per)
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800304{
Mike Frysingerf5563092009-02-04 16:49:45 +0800305 u16 ident = P_IDENT(per);
306 u16 function = P_FUNCT2MUX(per);
steven miao05bbec32010-09-17 03:03:17 +0000307 u32 pmux;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800308
Mike Frysingerf5563092009-02-04 16:49:45 +0800309 pmux = gpio_array[gpio_bank(ident)]->port_mux;
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800310
Mike Frysingerf5563092009-02-04 16:49:45 +0800311 pmux &= ~(0x3 << (2 * gpio_sub_n(ident)));
312 pmux |= (function & 0x3) << (2 * gpio_sub_n(ident));
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800313
Mike Frysingerf5563092009-02-04 16:49:45 +0800314 gpio_array[gpio_bank(ident)]->port_mux = pmux;
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800315}
316
Mike Frysingerf5563092009-02-04 16:49:45 +0800317inline u16 get_portmux(unsigned short per)
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800318{
Mike Frysingerf5563092009-02-04 16:49:45 +0800319 u16 ident = P_IDENT(per);
steven miao05bbec32010-09-17 03:03:17 +0000320 u32 pmux = gpio_array[gpio_bank(ident)]->port_mux;
Mike Frysingerf5563092009-02-04 16:49:45 +0800321 return (pmux >> (2 * gpio_sub_n(ident)) & 0x3);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800322}
steven miao05bbec32010-09-17 03:03:17 +0000323static int portmux_group_check(unsigned short per)
324{
325 return 0;
326}
Mike Frysinger269647d2009-03-28 20:32:57 +0800327#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
steven miao05bbec32010-09-17 03:03:17 +0000328static int portmux_group_check(unsigned short per)
329{
330 u16 ident = P_IDENT(per);
331 u16 function = P_FUNCT2MUX(per);
332 u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
333 u16 pin, gpiopin, pfunc;
334
335 for (pin = 0; pin < GPIO_BANKSIZE; ++pin) {
336 if (offset != pmux_offset[gpio_bank(ident)][pin])
337 continue;
338
339 gpiopin = gpio_bank(ident) * GPIO_BANKSIZE + pin;
340 if (gpiopin == ident)
341 continue;
342 if (!is_reserved(peri, gpiopin, 1))
343 continue;
344
345 pfunc = *port_mux[gpio_bank(ident)];
346 pfunc = (pfunc >> offset) & 3;
347 if (pfunc != function) {
348 pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",
349 ident, function, gpiopin, pfunc);
350 return -EINVAL;
351 }
352 }
353
354 return 0;
355}
356
Mike Frysingerf5563092009-02-04 16:49:45 +0800357inline void portmux_setup(unsigned short per)
Michael Hennerich59003142007-10-21 16:54:27 +0800358{
steven miao05bbec32010-09-17 03:03:17 +0000359 u16 ident = P_IDENT(per);
360 u16 function = P_FUNCT2MUX(per);
Michael Hennerich59003142007-10-21 16:54:27 +0800361 u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
steven miao05bbec32010-09-17 03:03:17 +0000362 u16 pmux;
Michael Hennerich59003142007-10-21 16:54:27 +0800363
364 pmux = *port_mux[gpio_bank(ident)];
steven miao05bbec32010-09-17 03:03:17 +0000365 if (((pmux >> offset) & 3) == function)
366 return;
Michael Hennerich59003142007-10-21 16:54:27 +0800367 pmux &= ~(3 << offset);
368 pmux |= (function & 3) << offset;
369 *port_mux[gpio_bank(ident)] = pmux;
370 SSYNC();
371}
Michael Hennerichc58c2142007-10-04 00:35:05 +0800372#else
373# define portmux_setup(...) do { } while (0)
steven miao05bbec32010-09-17 03:03:17 +0000374static int portmux_group_check(unsigned short per)
375{
376 return 0;
377}
Michael Hennerichc58c2142007-10-04 00:35:05 +0800378#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700379
Mike Frysinger269647d2009-03-28 20:32:57 +0800380#ifndef CONFIG_BF54x
Bryan Wu1394f032007-05-06 14:50:22 -0700381/***********************************************************
382*
383* FUNCTIONS: Blackfin General Purpose Ports Access Functions
384*
385* INPUTS/OUTPUTS:
386* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
387*
388*
389* DESCRIPTION: These functions abstract direct register access
390* to Blackfin processor General Purpose
391* Ports Regsiters
392*
393* CAUTION: These functions do not belong to the GPIO Driver API
394*************************************************************
395* MODIFICATION HISTORY :
396**************************************************************/
397
398/* Set a specific bit */
399
400#define SET_GPIO(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800401void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
Bryan Wu1394f032007-05-06 14:50:22 -0700402{ \
403 unsigned long flags; \
David Howells3b139cd2010-10-07 14:08:52 +0100404 flags = hard_local_irq_save(); \
Bryan Wu1394f032007-05-06 14:50:22 -0700405 if (arg) \
Mike Frysingerf5563092009-02-04 16:49:45 +0800406 gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
Bryan Wu1394f032007-05-06 14:50:22 -0700407 else \
Mike Frysingerf5563092009-02-04 16:49:45 +0800408 gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
Michael Hennerich2b393312007-10-10 16:58:49 +0800409 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100410 hard_local_irq_restore(flags); \
Bryan Wu1394f032007-05-06 14:50:22 -0700411} \
412EXPORT_SYMBOL(set_gpio_ ## name);
413
Mike Frysingerf5563092009-02-04 16:49:45 +0800414SET_GPIO(dir) /* set_gpio_dir() */
415SET_GPIO(inen) /* set_gpio_inen() */
416SET_GPIO(polar) /* set_gpio_polar() */
417SET_GPIO(edge) /* set_gpio_edge() */
418SET_GPIO(both) /* set_gpio_both() */
Bryan Wu1394f032007-05-06 14:50:22 -0700419
420
Michael Hennerich2b393312007-10-10 16:58:49 +0800421#define SET_GPIO_SC(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800422void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800423{ \
424 unsigned long flags; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800425 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100426 flags = hard_local_irq_save(); \
Michael Hennerich2b393312007-10-10 16:58:49 +0800427 if (arg) \
Mike Frysingerf5563092009-02-04 16:49:45 +0800428 gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
Michael Hennerich2b393312007-10-10 16:58:49 +0800429 else \
Mike Frysingerf5563092009-02-04 16:49:45 +0800430 gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
431 if (ANOMALY_05000311 || ANOMALY_05000323) { \
432 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100433 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800434 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800435} \
436EXPORT_SYMBOL(set_gpio_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700437
438SET_GPIO_SC(maska)
439SET_GPIO_SC(maskb)
Bryan Wu1394f032007-05-06 14:50:22 -0700440SET_GPIO_SC(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700441
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800442void set_gpio_toggle(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -0700443{
444 unsigned long flags;
Mike Frysingerf5563092009-02-04 16:49:45 +0800445 if (ANOMALY_05000311 || ANOMALY_05000323)
David Howells3b139cd2010-10-07 14:08:52 +0100446 flags = hard_local_irq_save();
Mike Frysingerf5563092009-02-04 16:49:45 +0800447 gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
448 if (ANOMALY_05000311 || ANOMALY_05000323) {
449 AWA_DUMMY_READ(toggle);
David Howells3b139cd2010-10-07 14:08:52 +0100450 hard_local_irq_restore(flags);
Mike Frysingerf5563092009-02-04 16:49:45 +0800451 }
Bryan Wu1394f032007-05-06 14:50:22 -0700452}
Bryan Wu1394f032007-05-06 14:50:22 -0700453EXPORT_SYMBOL(set_gpio_toggle);
454
455
456/*Set current PORT date (16-bit word)*/
457
Michael Hennerich2b393312007-10-10 16:58:49 +0800458#define SET_GPIO_P(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800459void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800460{ \
461 unsigned long flags; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800462 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100463 flags = hard_local_irq_save(); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800464 gpio_array[gpio_bank(gpio)]->name = arg; \
465 if (ANOMALY_05000311 || ANOMALY_05000323) { \
466 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100467 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800468 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800469} \
470EXPORT_SYMBOL(set_gpiop_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700471
Michael Hennerich2b393312007-10-10 16:58:49 +0800472SET_GPIO_P(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700473SET_GPIO_P(dir)
474SET_GPIO_P(inen)
475SET_GPIO_P(polar)
476SET_GPIO_P(edge)
477SET_GPIO_P(both)
478SET_GPIO_P(maska)
479SET_GPIO_P(maskb)
480
Bryan Wu1394f032007-05-06 14:50:22 -0700481/* Get a specific bit */
Michael Hennerich2b393312007-10-10 16:58:49 +0800482#define GET_GPIO(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800483unsigned short get_gpio_ ## name(unsigned gpio) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800484{ \
485 unsigned long flags; \
486 unsigned short ret; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800487 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100488 flags = hard_local_irq_save(); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800489 ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \
490 if (ANOMALY_05000311 || ANOMALY_05000323) { \
491 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100492 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800493 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800494 return ret; \
495} \
496EXPORT_SYMBOL(get_gpio_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700497
Michael Hennerich2b393312007-10-10 16:58:49 +0800498GET_GPIO(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700499GET_GPIO(dir)
500GET_GPIO(inen)
501GET_GPIO(polar)
502GET_GPIO(edge)
503GET_GPIO(both)
504GET_GPIO(maska)
505GET_GPIO(maskb)
506
Bryan Wu1394f032007-05-06 14:50:22 -0700507/*Get current PORT date (16-bit word)*/
508
Michael Hennerich2b393312007-10-10 16:58:49 +0800509#define GET_GPIO_P(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800510unsigned short get_gpiop_ ## name(unsigned gpio) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800511{ \
512 unsigned long flags; \
513 unsigned short ret; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800514 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100515 flags = hard_local_irq_save(); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800516 ret = (gpio_array[gpio_bank(gpio)]->name); \
517 if (ANOMALY_05000311 || ANOMALY_05000323) { \
518 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100519 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800520 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800521 return ret; \
522} \
523EXPORT_SYMBOL(get_gpiop_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700524
Michael Hennerich2b393312007-10-10 16:58:49 +0800525GET_GPIO_P(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700526GET_GPIO_P(dir)
527GET_GPIO_P(inen)
528GET_GPIO_P(polar)
529GET_GPIO_P(edge)
530GET_GPIO_P(both)
531GET_GPIO_P(maska)
532GET_GPIO_P(maskb)
533
Bryan Wu1394f032007-05-06 14:50:22 -0700534
535#ifdef CONFIG_PM
Mike Frysinger332824b2010-06-02 04:22:01 +0000536DECLARE_RESERVED_MAP(wakeup, GPIO_BANK_NUM);
Mike Frysingerf5563092009-02-04 16:49:45 +0800537
538static const unsigned int sic_iwr_irqs[] = {
539#if defined(BF533_FAMILY)
540 IRQ_PROG_INTB
541#elif defined(BF537_FAMILY)
Mike Frysinger8c054102011-04-15 13:04:59 -0400542 IRQ_PF_INTB_WATCH, IRQ_PORTG_INTB, IRQ_PH_INTB_MAC_TX
Mike Frysingerf5563092009-02-04 16:49:45 +0800543#elif defined(BF538_FAMILY)
544 IRQ_PORTF_INTB
Mike Frysinger269647d2009-03-28 20:32:57 +0800545#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800546 IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB
547#elif defined(BF561_FAMILY)
548 IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB
549#else
550# error no SIC_IWR defined
551#endif
552};
553
Bryan Wu1394f032007-05-06 14:50:22 -0700554/***********************************************************
555*
556* FUNCTIONS: Blackfin PM Setup API
557*
558* INPUTS/OUTPUTS:
559* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
560* type -
561* PM_WAKE_RISING
562* PM_WAKE_FALLING
563* PM_WAKE_HIGH
564* PM_WAKE_LOW
565* PM_WAKE_BOTH_EDGES
566*
567* DESCRIPTION: Blackfin PM Driver API
568*
569* CAUTION:
570*************************************************************
571* MODIFICATION HISTORY :
572**************************************************************/
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000573int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)
Bryan Wu1394f032007-05-06 14:50:22 -0700574{
575 unsigned long flags;
576
577 if (check_gpio(gpio) < 0)
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000578 return -EINVAL;
Bryan Wu1394f032007-05-06 14:50:22 -0700579
David Howells3b139cd2010-10-07 14:08:52 +0100580 flags = hard_local_irq_save();
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000581 if (ctrl)
Mike Frysinger332824b2010-06-02 04:22:01 +0000582 reserve(wakeup, gpio);
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000583 else
Mike Frysinger332824b2010-06-02 04:22:01 +0000584 unreserve(wakeup, gpio);
Bryan Wu1394f032007-05-06 14:50:22 -0700585
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000586 set_gpio_maskb(gpio, ctrl);
David Howells3b139cd2010-10-07 14:08:52 +0100587 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700588
589 return 0;
590}
591
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000592int bfin_pm_standby_ctrl(unsigned ctrl)
Bryan Wu1394f032007-05-06 14:50:22 -0700593{
594 u16 bank, mask, i;
595
Mike Frysinger1f83b8f2007-07-12 22:58:21 +0800596 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Mike Frysinger332824b2010-06-02 04:22:01 +0000597 mask = map_entry(wakeup, i);
Bryan Wu1394f032007-05-06 14:50:22 -0700598 bank = gpio_bank(i);
599
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000600 if (mask)
601 bfin_internal_set_wake(sic_iwr_irqs[bank], ctrl);
Bryan Wu1394f032007-05-06 14:50:22 -0700602 }
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000603 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -0700604}
605
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800606void bfin_gpio_pm_hibernate_suspend(void)
607{
608 int i, bank;
609
Mike Frysinger9466a052011-06-27 14:46:14 -0400610#ifdef BF538_FAMILY
611 for (i = 0; i < ARRAY_SIZE(port_fer_saved); ++i)
612 port_fer_saved[i] = *port_fer[i];
613#endif
614
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800615 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
616 bank = gpio_bank(i);
617
Mike Frysinger269647d2009-03-28 20:32:57 +0800618#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800619 gpio_bank_saved[bank].fer = *port_fer[bank];
Mike Frysinger269647d2009-03-28 20:32:57 +0800620#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800621 gpio_bank_saved[bank].mux = *port_mux[bank];
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800622#else
Mike Frysingerf5563092009-02-04 16:49:45 +0800623 if (bank == 0)
624 gpio_bank_saved[bank].mux = bfin_read_PORT_MUX();
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800625#endif
626#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800627 gpio_bank_saved[bank].data = gpio_array[bank]->data;
628 gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
629 gpio_bank_saved[bank].polar = gpio_array[bank]->polar;
630 gpio_bank_saved[bank].dir = gpio_array[bank]->dir;
631 gpio_bank_saved[bank].edge = gpio_array[bank]->edge;
632 gpio_bank_saved[bank].both = gpio_array[bank]->both;
633 gpio_bank_saved[bank].maska = gpio_array[bank]->maska;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800634 }
635
Mike Frysinger9466a052011-06-27 14:46:14 -0400636#ifdef BFIN_SPECIAL_GPIO_BANKS
637 bfin_special_gpio_pm_hibernate_suspend();
638#endif
639
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800640 AWA_DUMMY_READ(maska);
641}
642
643void bfin_gpio_pm_hibernate_restore(void)
644{
645 int i, bank;
646
Mike Frysinger9466a052011-06-27 14:46:14 -0400647#ifdef BF538_FAMILY
648 for (i = 0; i < ARRAY_SIZE(port_fer_saved); ++i)
649 *port_fer[i] = port_fer_saved[i];
650#endif
651
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800652 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Mike Frysingerf5563092009-02-04 16:49:45 +0800653 bank = gpio_bank(i);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800654
Mike Frysinger269647d2009-03-28 20:32:57 +0800655#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
656#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800657 *port_mux[bank] = gpio_bank_saved[bank].mux;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800658#else
Mike Frysingerf5563092009-02-04 16:49:45 +0800659 if (bank == 0)
660 bfin_write_PORT_MUX(gpio_bank_saved[bank].mux);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800661#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800662 *port_fer[bank] = gpio_bank_saved[bank].fer;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800663#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800664 gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
Michael Hennerichc03c2a82009-07-08 12:04:43 +0000665 gpio_array[bank]->data_set = gpio_bank_saved[bank].data
666 & gpio_bank_saved[bank].dir;
Mike Frysingerf5563092009-02-04 16:49:45 +0800667 gpio_array[bank]->dir = gpio_bank_saved[bank].dir;
668 gpio_array[bank]->polar = gpio_bank_saved[bank].polar;
669 gpio_array[bank]->edge = gpio_bank_saved[bank].edge;
670 gpio_array[bank]->both = gpio_bank_saved[bank].both;
Mike Frysingerf5563092009-02-04 16:49:45 +0800671 gpio_array[bank]->maska = gpio_bank_saved[bank].maska;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800672 }
Mike Frysinger9466a052011-06-27 14:46:14 -0400673
674#ifdef BFIN_SPECIAL_GPIO_BANKS
675 bfin_special_gpio_pm_hibernate_restore();
676#endif
677
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800678 AWA_DUMMY_READ(maska);
679}
680
681
Bryan Wu1394f032007-05-06 14:50:22 -0700682#endif
Mike Frysinger269647d2009-03-28 20:32:57 +0800683#else /* CONFIG_BF54x */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800684#ifdef CONFIG_PM
685
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000686int bfin_pm_standby_ctrl(unsigned ctrl)
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800687{
688 return 0;
689}
690
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800691void bfin_gpio_pm_hibernate_suspend(void)
692{
693 int i, bank;
694
695 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
696 bank = gpio_bank(i);
697
Mike Frysingerf5563092009-02-04 16:49:45 +0800698 gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer;
699 gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux;
700 gpio_bank_saved[bank].data = gpio_array[bank]->data;
Mike Frysingerf5563092009-02-04 16:49:45 +0800701 gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
702 gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800703 }
704}
705
706void bfin_gpio_pm_hibernate_restore(void)
707{
708 int i, bank;
709
710 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Mike Frysingerf5563092009-02-04 16:49:45 +0800711 bank = gpio_bank(i);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800712
Mike Frysingerf5563092009-02-04 16:49:45 +0800713 gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux;
714 gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer;
715 gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
Mike Frysingerf5563092009-02-04 16:49:45 +0800716 gpio_array[bank]->data_set = gpio_bank_saved[bank].data
Mike Frysingerfdfb0be2011-06-27 17:23:48 -0400717 & gpio_bank_saved[bank].dir;
718 gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800719 }
720}
721#endif
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800722
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800723unsigned short get_gpio_dir(unsigned gpio)
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800724{
Mike Frysingerf5563092009-02-04 16:49:45 +0800725 return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio)));
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800726}
727EXPORT_SYMBOL(get_gpio_dir);
728
Mike Frysinger269647d2009-03-28 20:32:57 +0800729#endif /* CONFIG_BF54x */
Bryan Wu1394f032007-05-06 14:50:22 -0700730
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800731/***********************************************************
732*
Mike Frysinger812ae982010-07-05 08:40:41 +0000733* FUNCTIONS: Blackfin Peripheral Resource Allocation
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800734* and PortMux Setup
735*
736* INPUTS/OUTPUTS:
737* per Peripheral Identifier
738* label String
739*
740* DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API
741*
742* CAUTION:
743*************************************************************
744* MODIFICATION HISTORY :
745**************************************************************/
Michael Hennerichc58c2142007-10-04 00:35:05 +0800746
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800747int peripheral_request(unsigned short per, const char *label)
748{
749 unsigned long flags;
750 unsigned short ident = P_IDENT(per);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800751
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800752 /*
753 * Don't cares are pins with only one dedicated function
754 */
755
756 if (per & P_DONTCARE)
757 return 0;
758
759 if (!(per & P_DEFINED))
760 return -ENODEV;
761
Barry Song89e84ee2009-09-16 04:36:29 +0000762 BUG_ON(ident >= MAX_RESOURCES);
763
David Howells3b139cd2010-10-07 14:08:52 +0100764 flags = hard_local_irq_save();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800765
Mike Frysinger6a87d292008-10-28 16:16:29 +0800766 /* If a pin can be muxed as either GPIO or peripheral, make
767 * sure it is not already a GPIO pin when we request it.
768 */
Mike Frysinger332824b2010-06-02 04:22:01 +0000769 if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800770 if (system_state == SYSTEM_BOOTING)
771 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800772 printk(KERN_ERR
Mike Frysinger6c7ec0e2008-10-28 15:49:59 +0800773 "%s: Peripheral %d is already reserved as GPIO by %s !\n",
Harvey Harrisonb85d8582008-04-23 09:39:01 +0800774 __func__, ident, get_label(ident));
David Howells3b139cd2010-10-07 14:08:52 +0100775 hard_local_irq_restore(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800776 return -EBUSY;
777 }
778
Mike Frysinger332824b2010-06-02 04:22:01 +0000779 if (unlikely(is_reserved(peri, ident, 1))) {
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800780
Mike Frysingerd171c232008-03-26 08:35:46 +0800781 /*
782 * Pin functions like AMC address strobes my
783 * be requested and used by several drivers
784 */
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800785
Mike Frysinger269647d2009-03-28 20:32:57 +0800786#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +0800787 if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) {
Mike Frysinger6c7ec0e2008-10-28 15:49:59 +0800788#else
789 if (!(per & P_MAYSHARE)) {
790#endif
Mike Frysingerd171c232008-03-26 08:35:46 +0800791 /*
792 * Allow that the identical pin function can
793 * be requested from the same driver twice
794 */
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800795
Mike Frysingerd171c232008-03-26 08:35:46 +0800796 if (cmp_label(ident, label) == 0)
797 goto anyway;
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800798
Robin Getzd6879c52009-03-29 01:10:30 +0800799 if (system_state == SYSTEM_BOOTING)
800 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800801 printk(KERN_ERR
802 "%s: Peripheral %d function %d is already reserved by %s !\n",
Harvey Harrisonb85d8582008-04-23 09:39:01 +0800803 __func__, ident, P_FUNCT2MUX(per), get_label(ident));
David Howells3b139cd2010-10-07 14:08:52 +0100804 hard_local_irq_restore(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800805 return -EBUSY;
806 }
807 }
808
steven miao05bbec32010-09-17 03:03:17 +0000809 if (unlikely(portmux_group_check(per))) {
810 hard_local_irq_restore(flags);
811 return -EBUSY;
812 }
Mike Frysingerd171c232008-03-26 08:35:46 +0800813 anyway:
Mike Frysinger332824b2010-06-02 04:22:01 +0000814 reserve(peri, ident);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800815
Mike Frysingerf5563092009-02-04 16:49:45 +0800816 portmux_setup(per);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800817 port_setup(ident, PERIPHERAL_USAGE);
818
David Howells3b139cd2010-10-07 14:08:52 +0100819 hard_local_irq_restore(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800820 set_label(ident, label);
821
822 return 0;
823}
824EXPORT_SYMBOL(peripheral_request);
825
Mike Frysinger68179372008-04-24 05:04:24 +0800826int peripheral_request_list(const unsigned short per[], const char *label)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800827{
828 u16 cnt;
829 int ret;
830
831 for (cnt = 0; per[cnt] != 0; cnt++) {
Michael Hennerich314c98d2007-07-24 18:03:45 +0800832
Michael Hennerichc58c2142007-10-04 00:35:05 +0800833 ret = peripheral_request(per[cnt], label);
Michael Hennerich314c98d2007-07-24 18:03:45 +0800834
835 if (ret < 0) {
Mike Frysingerd171c232008-03-26 08:35:46 +0800836 for ( ; cnt > 0; cnt--)
Michael Hennerich314c98d2007-07-24 18:03:45 +0800837 peripheral_free(per[cnt - 1]);
Mike Frysingerd171c232008-03-26 08:35:46 +0800838
839 return ret;
Michael Hennerich314c98d2007-07-24 18:03:45 +0800840 }
Michael Hennerichc58c2142007-10-04 00:35:05 +0800841 }
842
843 return 0;
844}
845EXPORT_SYMBOL(peripheral_request_list);
846
847void peripheral_free(unsigned short per)
848{
849 unsigned long flags;
850 unsigned short ident = P_IDENT(per);
851
852 if (per & P_DONTCARE)
853 return;
854
855 if (!(per & P_DEFINED))
856 return;
857
David Howells3b139cd2010-10-07 14:08:52 +0100858 flags = hard_local_irq_save();
Michael Hennerichc58c2142007-10-04 00:35:05 +0800859
Mike Frysinger332824b2010-06-02 04:22:01 +0000860 if (unlikely(!is_reserved(peri, ident, 0))) {
David Howells3b139cd2010-10-07 14:08:52 +0100861 hard_local_irq_restore(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800862 return;
863 }
864
Mike Frysingerd171c232008-03-26 08:35:46 +0800865 if (!(per & P_MAYSHARE))
Michael Hennerichc58c2142007-10-04 00:35:05 +0800866 port_setup(ident, GPIO_USAGE);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800867
Mike Frysinger332824b2010-06-02 04:22:01 +0000868 unreserve(peri, ident);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800869
Michael Hennerich2acde902007-10-11 00:24:40 +0800870 set_label(ident, "free");
871
David Howells3b139cd2010-10-07 14:08:52 +0100872 hard_local_irq_restore(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800873}
874EXPORT_SYMBOL(peripheral_free);
875
Mike Frysinger68179372008-04-24 05:04:24 +0800876void peripheral_free_list(const unsigned short per[])
Michael Hennerichc58c2142007-10-04 00:35:05 +0800877{
878 u16 cnt;
Mike Frysingerd171c232008-03-26 08:35:46 +0800879 for (cnt = 0; per[cnt] != 0; cnt++)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800880 peripheral_free(per[cnt]);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800881}
882EXPORT_SYMBOL(peripheral_free_list);
883
Bryan Wu1394f032007-05-06 14:50:22 -0700884/***********************************************************
885*
886* FUNCTIONS: Blackfin GPIO Driver
887*
888* INPUTS/OUTPUTS:
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800889* gpio PIO Number between 0 and MAX_BLACKFIN_GPIOS
890* label String
Bryan Wu1394f032007-05-06 14:50:22 -0700891*
892* DESCRIPTION: Blackfin GPIO Driver API
893*
894* CAUTION:
895*************************************************************
896* MODIFICATION HISTORY :
897**************************************************************/
898
Michael Hennericha4f0b322008-11-18 17:48:22 +0800899int bfin_gpio_request(unsigned gpio, const char *label)
Bryan Wu1394f032007-05-06 14:50:22 -0700900{
901 unsigned long flags;
902
903 if (check_gpio(gpio) < 0)
904 return -EINVAL;
905
David Howells3b139cd2010-10-07 14:08:52 +0100906 flags = hard_local_irq_save();
Bryan Wu1394f032007-05-06 14:50:22 -0700907
Michael Hennerich2acde902007-10-11 00:24:40 +0800908 /*
909 * Allow that the identical GPIO can
910 * be requested from the same driver twice
911 * Do nothing and return -
912 */
913
914 if (cmp_label(gpio, label) == 0) {
David Howells3b139cd2010-10-07 14:08:52 +0100915 hard_local_irq_restore(flags);
Michael Hennerich2acde902007-10-11 00:24:40 +0800916 return 0;
917 }
918
Mike Frysinger332824b2010-06-02 04:22:01 +0000919 if (unlikely(is_reserved(gpio, gpio, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800920 if (system_state == SYSTEM_BOOTING)
921 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800922 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
Graf Yang9570ff42009-01-07 23:14:38 +0800923 gpio, get_label(gpio));
David Howells3b139cd2010-10-07 14:08:52 +0100924 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700925 return -EBUSY;
926 }
Mike Frysinger332824b2010-06-02 04:22:01 +0000927 if (unlikely(is_reserved(peri, gpio, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800928 if (system_state == SYSTEM_BOOTING)
929 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800930 printk(KERN_ERR
931 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
932 gpio, get_label(gpio));
David Howells3b139cd2010-10-07 14:08:52 +0100933 hard_local_irq_restore(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800934 return -EBUSY;
935 }
Mike Frysinger332824b2010-06-02 04:22:01 +0000936 if (unlikely(is_reserved(gpio_irq, gpio, 1))) {
Graf Yang9570ff42009-01-07 23:14:38 +0800937 printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!"
938 " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio);
Michael Hennericha2be3932009-02-04 16:49:45 +0800939 }
Mike Frysinger269647d2009-03-28 20:32:57 +0800940#ifndef CONFIG_BF54x
Michael Hennericha2be3932009-02-04 16:49:45 +0800941 else { /* Reset POLAR setting when acquiring a gpio for the first time */
942 set_gpio_polar(gpio, 0);
943 }
944#endif
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800945
Mike Frysinger332824b2010-06-02 04:22:01 +0000946 reserve(gpio, gpio);
Graf Yang9570ff42009-01-07 23:14:38 +0800947 set_label(gpio, label);
Bryan Wu1394f032007-05-06 14:50:22 -0700948
David Howells3b139cd2010-10-07 14:08:52 +0100949 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700950
951 port_setup(gpio, GPIO_USAGE);
952
953 return 0;
954}
Michael Hennericha4f0b322008-11-18 17:48:22 +0800955EXPORT_SYMBOL(bfin_gpio_request);
Bryan Wu1394f032007-05-06 14:50:22 -0700956
Michael Hennericha4f0b322008-11-18 17:48:22 +0800957void bfin_gpio_free(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -0700958{
959 unsigned long flags;
960
961 if (check_gpio(gpio) < 0)
962 return;
963
Uwe Kleine-Koenig45c4f2a2009-02-04 17:02:30 +0800964 might_sleep();
965
David Howells3b139cd2010-10-07 14:08:52 +0100966 flags = hard_local_irq_save();
Bryan Wu1394f032007-05-06 14:50:22 -0700967
Mike Frysinger332824b2010-06-02 04:22:01 +0000968 if (unlikely(!is_reserved(gpio, gpio, 0))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800969 if (system_state == SYSTEM_BOOTING)
970 dump_stack();
Mike Frysingerf85c4ab2008-03-26 08:34:23 +0800971 gpio_error(gpio);
David Howells3b139cd2010-10-07 14:08:52 +0100972 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700973 return;
974 }
975
Mike Frysinger332824b2010-06-02 04:22:01 +0000976 unreserve(gpio, gpio);
Bryan Wu1394f032007-05-06 14:50:22 -0700977
Michael Hennerich2acde902007-10-11 00:24:40 +0800978 set_label(gpio, "free");
979
David Howells3b139cd2010-10-07 14:08:52 +0100980 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700981}
Michael Hennericha4f0b322008-11-18 17:48:22 +0800982EXPORT_SYMBOL(bfin_gpio_free);
Bryan Wu1394f032007-05-06 14:50:22 -0700983
Michael Hennerich621dd242009-09-28 12:23:41 +0000984#ifdef BFIN_SPECIAL_GPIO_BANKS
Mike Frysinger332824b2010-06-02 04:22:01 +0000985DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES));
Michael Hennerich621dd242009-09-28 12:23:41 +0000986
987int bfin_special_gpio_request(unsigned gpio, const char *label)
988{
989 unsigned long flags;
990
David Howells3b139cd2010-10-07 14:08:52 +0100991 flags = hard_local_irq_save();
Michael Hennerich621dd242009-09-28 12:23:41 +0000992
993 /*
994 * Allow that the identical GPIO can
995 * be requested from the same driver twice
996 * Do nothing and return -
997 */
998
999 if (cmp_label(gpio, label) == 0) {
David Howells3b139cd2010-10-07 14:08:52 +01001000 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +00001001 return 0;
1002 }
1003
Mike Frysinger332824b2010-06-02 04:22:01 +00001004 if (unlikely(is_reserved(special_gpio, gpio, 1))) {
David Howells3b139cd2010-10-07 14:08:52 +01001005 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +00001006 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
1007 gpio, get_label(gpio));
1008
1009 return -EBUSY;
1010 }
Mike Frysinger332824b2010-06-02 04:22:01 +00001011 if (unlikely(is_reserved(peri, gpio, 1))) {
David Howells3b139cd2010-10-07 14:08:52 +01001012 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +00001013 printk(KERN_ERR
1014 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
1015 gpio, get_label(gpio));
1016
1017 return -EBUSY;
1018 }
1019
Mike Frysinger332824b2010-06-02 04:22:01 +00001020 reserve(special_gpio, gpio);
1021 reserve(peri, gpio);
Michael Hennerich621dd242009-09-28 12:23:41 +00001022
1023 set_label(gpio, label);
David Howells3b139cd2010-10-07 14:08:52 +01001024 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +00001025 port_setup(gpio, GPIO_USAGE);
1026
1027 return 0;
1028}
1029EXPORT_SYMBOL(bfin_special_gpio_request);
1030
1031void bfin_special_gpio_free(unsigned gpio)
1032{
1033 unsigned long flags;
1034
1035 might_sleep();
1036
David Howells3b139cd2010-10-07 14:08:52 +01001037 flags = hard_local_irq_save();
Michael Hennerich621dd242009-09-28 12:23:41 +00001038
Mike Frysinger332824b2010-06-02 04:22:01 +00001039 if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
Michael Hennerich621dd242009-09-28 12:23:41 +00001040 gpio_error(gpio);
David Howells3b139cd2010-10-07 14:08:52 +01001041 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +00001042 return;
1043 }
1044
Mike Frysinger332824b2010-06-02 04:22:01 +00001045 unreserve(special_gpio, gpio);
1046 unreserve(peri, gpio);
Michael Hennerich621dd242009-09-28 12:23:41 +00001047 set_label(gpio, "free");
David Howells3b139cd2010-10-07 14:08:52 +01001048 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +00001049}
1050EXPORT_SYMBOL(bfin_special_gpio_free);
1051#endif
1052
1053
Graf Yang9570ff42009-01-07 23:14:38 +08001054int bfin_gpio_irq_request(unsigned gpio, const char *label)
1055{
1056 unsigned long flags;
1057
1058 if (check_gpio(gpio) < 0)
1059 return -EINVAL;
1060
David Howells3b139cd2010-10-07 14:08:52 +01001061 flags = hard_local_irq_save();
Graf Yang9570ff42009-01-07 23:14:38 +08001062
Mike Frysinger332824b2010-06-02 04:22:01 +00001063 if (unlikely(is_reserved(peri, gpio, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +08001064 if (system_state == SYSTEM_BOOTING)
1065 dump_stack();
Graf Yang9570ff42009-01-07 23:14:38 +08001066 printk(KERN_ERR
1067 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
1068 gpio, get_label(gpio));
David Howells3b139cd2010-10-07 14:08:52 +01001069 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001070 return -EBUSY;
1071 }
Mike Frysinger332824b2010-06-02 04:22:01 +00001072 if (unlikely(is_reserved(gpio, gpio, 1)))
Graf Yang9570ff42009-01-07 23:14:38 +08001073 printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved by %s! "
1074 "(Documentation/blackfin/bfin-gpio-notes.txt)\n",
1075 gpio, get_label(gpio));
1076
Mike Frysinger332824b2010-06-02 04:22:01 +00001077 reserve(gpio_irq, gpio);
Graf Yang9570ff42009-01-07 23:14:38 +08001078 set_label(gpio, label);
1079
David Howells3b139cd2010-10-07 14:08:52 +01001080 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001081
1082 port_setup(gpio, GPIO_USAGE);
1083
1084 return 0;
1085}
1086
1087void bfin_gpio_irq_free(unsigned gpio)
1088{
1089 unsigned long flags;
1090
1091 if (check_gpio(gpio) < 0)
1092 return;
1093
David Howells3b139cd2010-10-07 14:08:52 +01001094 flags = hard_local_irq_save();
Graf Yang9570ff42009-01-07 23:14:38 +08001095
Mike Frysinger332824b2010-06-02 04:22:01 +00001096 if (unlikely(!is_reserved(gpio_irq, gpio, 0))) {
Robin Getzd6879c52009-03-29 01:10:30 +08001097 if (system_state == SYSTEM_BOOTING)
1098 dump_stack();
Graf Yang9570ff42009-01-07 23:14:38 +08001099 gpio_error(gpio);
David Howells3b139cd2010-10-07 14:08:52 +01001100 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001101 return;
1102 }
1103
Mike Frysinger332824b2010-06-02 04:22:01 +00001104 unreserve(gpio_irq, gpio);
Graf Yang9570ff42009-01-07 23:14:38 +08001105
1106 set_label(gpio, "free");
1107
David Howells3b139cd2010-10-07 14:08:52 +01001108 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001109}
1110
Mike Frysingerf5563092009-02-04 16:49:45 +08001111static inline void __bfin_gpio_direction_input(unsigned gpio)
1112{
Mike Frysinger269647d2009-03-28 20:32:57 +08001113#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001114 gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
Michael Hennerichd2b11a42007-08-28 16:47:46 +08001115#else
Mike Frysingerf5563092009-02-04 16:49:45 +08001116 gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
1117#endif
1118 gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
Michael Hennerich803a8d22008-05-17 16:01:51 +08001119}
Michael Hennerich803a8d22008-05-17 16:01:51 +08001120
Michael Hennericha4f0b322008-11-18 17:48:22 +08001121int bfin_gpio_direction_input(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -07001122{
1123 unsigned long flags;
1124
Mike Frysinger332824b2010-06-02 04:22:01 +00001125 if (unlikely(!is_reserved(gpio, gpio, 0))) {
Michael Hennerichacbcd262008-01-22 18:36:20 +08001126 gpio_error(gpio);
1127 return -EINVAL;
1128 }
Bryan Wu1394f032007-05-06 14:50:22 -07001129
David Howells3b139cd2010-10-07 14:08:52 +01001130 flags = hard_local_irq_save();
Mike Frysingerf5563092009-02-04 16:49:45 +08001131 __bfin_gpio_direction_input(gpio);
Michael Hennerich2b393312007-10-10 16:58:49 +08001132 AWA_DUMMY_READ(inen);
David Howells3b139cd2010-10-07 14:08:52 +01001133 hard_local_irq_restore(flags);
Michael Hennerichacbcd262008-01-22 18:36:20 +08001134
1135 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -07001136}
Michael Hennericha4f0b322008-11-18 17:48:22 +08001137EXPORT_SYMBOL(bfin_gpio_direction_input);
Bryan Wu1394f032007-05-06 14:50:22 -07001138
Mike Frysingerf5563092009-02-04 16:49:45 +08001139void bfin_gpio_irq_prepare(unsigned gpio)
1140{
Mike Frysinger269647d2009-03-28 20:32:57 +08001141#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001142 unsigned long flags;
1143#endif
1144
1145 port_setup(gpio, GPIO_USAGE);
1146
Mike Frysinger269647d2009-03-28 20:32:57 +08001147#ifdef CONFIG_BF54x
David Howells3b139cd2010-10-07 14:08:52 +01001148 flags = hard_local_irq_save();
Mike Frysingerf5563092009-02-04 16:49:45 +08001149 __bfin_gpio_direction_input(gpio);
David Howells3b139cd2010-10-07 14:08:52 +01001150 hard_local_irq_restore(flags);
Mike Frysingerf5563092009-02-04 16:49:45 +08001151#endif
1152}
1153
1154void bfin_gpio_set_value(unsigned gpio, int arg)
1155{
1156 if (arg)
1157 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
1158 else
1159 gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
1160}
1161EXPORT_SYMBOL(bfin_gpio_set_value);
1162
Michael Hennericha4f0b322008-11-18 17:48:22 +08001163int bfin_gpio_direction_output(unsigned gpio, int value)
Bryan Wu1394f032007-05-06 14:50:22 -07001164{
1165 unsigned long flags;
1166
Mike Frysinger332824b2010-06-02 04:22:01 +00001167 if (unlikely(!is_reserved(gpio, gpio, 0))) {
Michael Hennerichacbcd262008-01-22 18:36:20 +08001168 gpio_error(gpio);
1169 return -EINVAL;
1170 }
Bryan Wu1394f032007-05-06 14:50:22 -07001171
David Howells3b139cd2010-10-07 14:08:52 +01001172 flags = hard_local_irq_save();
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001173
Mike Frysingerf5563092009-02-04 16:49:45 +08001174 gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
1175 gpio_set_value(gpio, value);
Mike Frysinger269647d2009-03-28 20:32:57 +08001176#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001177 gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
1178#else
1179 gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
1180#endif
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001181
Michael Hennerich2b393312007-10-10 16:58:49 +08001182 AWA_DUMMY_READ(dir);
David Howells3b139cd2010-10-07 14:08:52 +01001183 hard_local_irq_restore(flags);
Michael Hennerichacbcd262008-01-22 18:36:20 +08001184
1185 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -07001186}
Michael Hennericha4f0b322008-11-18 17:48:22 +08001187EXPORT_SYMBOL(bfin_gpio_direction_output);
Mike Frysinger168f1212007-10-11 00:22:35 +08001188
Mike Frysingerf5563092009-02-04 16:49:45 +08001189int bfin_gpio_get_value(unsigned gpio)
1190{
Mike Frysinger269647d2009-03-28 20:32:57 +08001191#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001192 return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)));
1193#else
1194 unsigned long flags;
1195
1196 if (unlikely(get_gpio_edge(gpio))) {
1197 int ret;
David Howells3b139cd2010-10-07 14:08:52 +01001198 flags = hard_local_irq_save();
Mike Frysingerf5563092009-02-04 16:49:45 +08001199 set_gpio_edge(gpio, 0);
1200 ret = get_gpio_data(gpio);
1201 set_gpio_edge(gpio, 1);
David Howells3b139cd2010-10-07 14:08:52 +01001202 hard_local_irq_restore(flags);
Mike Frysingerf5563092009-02-04 16:49:45 +08001203 return ret;
1204 } else
1205 return get_gpio_data(gpio);
1206#endif
1207}
1208EXPORT_SYMBOL(bfin_gpio_get_value);
1209
Mike Frysinger168f1212007-10-11 00:22:35 +08001210/* If we are booting from SPI and our board lacks a strong enough pull up,
1211 * the core can reset and execute the bootrom faster than the resistor can
1212 * pull the signal logically high. To work around this (common) error in
1213 * board design, we explicitly set the pin back to GPIO mode, force /CS
1214 * high, and wait for the electrons to do their thing.
1215 *
1216 * This function only makes sense to be called from reset code, but it
1217 * lives here as we need to force all the GPIO states w/out going through
1218 * BUG() checks and such.
1219 */
Sonic Zhangb52dae32009-02-04 16:49:45 +08001220void bfin_reset_boot_spi_cs(unsigned short pin)
Mike Frysinger168f1212007-10-11 00:22:35 +08001221{
Sonic Zhangb52dae32009-02-04 16:49:45 +08001222 unsigned short gpio = P_IDENT(pin);
Michael Hennerich4d5f4ed2007-08-27 16:46:17 +08001223 port_setup(gpio, GPIO_USAGE);
Mike Frysingerf5563092009-02-04 16:49:45 +08001224 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001225 AWA_DUMMY_READ(data_set);
Mike Frysinger168f1212007-10-11 00:22:35 +08001226 udelay(1);
1227}
Michael Hennerichd2b11a42007-08-28 16:47:46 +08001228
Mike Frysinger1545a112007-12-24 16:54:48 +08001229#if defined(CONFIG_PROC_FS)
Alexey Dobriyan6362ec22011-05-14 19:48:46 +03001230static int gpio_proc_show(struct seq_file *m, void *v)
Mike Frysinger1545a112007-12-24 16:54:48 +08001231{
Alexey Dobriyan6362ec22011-05-14 19:48:46 +03001232 int c, irq, gpio;
Mike Frysinger1545a112007-12-24 16:54:48 +08001233
1234 for (c = 0; c < MAX_RESOURCES; c++) {
Mike Frysinger332824b2010-06-02 04:22:01 +00001235 irq = is_reserved(gpio_irq, c, 1);
1236 gpio = is_reserved(gpio, c, 1);
Graf Yang9570ff42009-01-07 23:14:38 +08001237 if (!check_gpio(c) && (gpio || irq))
Alexey Dobriyan6362ec22011-05-14 19:48:46 +03001238 seq_printf(m, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c,
Graf Yang9570ff42009-01-07 23:14:38 +08001239 get_label(c), (gpio && irq) ? " *" : "",
1240 get_gpio_dir(c) ? "OUTPUT" : "INPUT");
Mike Frysinger332824b2010-06-02 04:22:01 +00001241 else if (is_reserved(peri, c, 1))
Alexey Dobriyan6362ec22011-05-14 19:48:46 +03001242 seq_printf(m, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c));
Mike Frysinger1545a112007-12-24 16:54:48 +08001243 else
1244 continue;
Mike Frysinger1545a112007-12-24 16:54:48 +08001245 }
Alexey Dobriyan6362ec22011-05-14 19:48:46 +03001246
1247 return 0;
Mike Frysinger1545a112007-12-24 16:54:48 +08001248}
1249
Alexey Dobriyan6362ec22011-05-14 19:48:46 +03001250static int gpio_proc_open(struct inode *inode, struct file *file)
1251{
1252 return single_open(file, gpio_proc_show, NULL);
1253}
1254
1255static const struct file_operations gpio_proc_ops = {
1256 .open = gpio_proc_open,
1257 .read = seq_read,
1258 .llseek = seq_lseek,
1259 .release = single_release,
1260};
1261
Mike Frysinger1545a112007-12-24 16:54:48 +08001262static __init int gpio_register_proc(void)
1263{
1264 struct proc_dir_entry *proc_gpio;
1265
Alexey Dobriyan6362ec22011-05-14 19:48:46 +03001266 proc_gpio = proc_create("gpio", S_IRUGO, NULL, &gpio_proc_ops);
Mike Frysinger1545a112007-12-24 16:54:48 +08001267 return proc_gpio != NULL;
1268}
Mike Frysinger1545a112007-12-24 16:54:48 +08001269__initcall(gpio_register_proc);
1270#endif
Michael Hennericha4f0b322008-11-18 17:48:22 +08001271
1272#ifdef CONFIG_GPIOLIB
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001273static int bfin_gpiolib_direction_input(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b322008-11-18 17:48:22 +08001274{
1275 return bfin_gpio_direction_input(gpio);
1276}
1277
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001278static int bfin_gpiolib_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
Michael Hennericha4f0b322008-11-18 17:48:22 +08001279{
1280 return bfin_gpio_direction_output(gpio, level);
1281}
1282
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001283static int bfin_gpiolib_get_value(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b322008-11-18 17:48:22 +08001284{
1285 return bfin_gpio_get_value(gpio);
1286}
1287
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001288static void bfin_gpiolib_set_value(struct gpio_chip *chip, unsigned gpio, int value)
Michael Hennericha4f0b322008-11-18 17:48:22 +08001289{
Michael Hennericha4f0b322008-11-18 17:48:22 +08001290 return bfin_gpio_set_value(gpio, value);
Michael Hennericha4f0b322008-11-18 17:48:22 +08001291}
1292
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001293static int bfin_gpiolib_gpio_request(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b322008-11-18 17:48:22 +08001294{
1295 return bfin_gpio_request(gpio, chip->label);
1296}
1297
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001298static void bfin_gpiolib_gpio_free(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b322008-11-18 17:48:22 +08001299{
1300 return bfin_gpio_free(gpio);
1301}
1302
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001303static int bfin_gpiolib_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
Joachim Eastwood7f4f69f2010-02-10 12:31:41 +01001304{
1305 return gpio + GPIO_IRQ_BASE;
1306}
1307
Michael Hennericha4f0b322008-11-18 17:48:22 +08001308static struct gpio_chip bfin_chip = {
Michael Hennerichedd07992009-12-16 08:45:17 +00001309 .label = "BFIN-GPIO",
Michael Hennericha4f0b322008-11-18 17:48:22 +08001310 .direction_input = bfin_gpiolib_direction_input,
1311 .get = bfin_gpiolib_get_value,
1312 .direction_output = bfin_gpiolib_direction_output,
1313 .set = bfin_gpiolib_set_value,
1314 .request = bfin_gpiolib_gpio_request,
1315 .free = bfin_gpiolib_gpio_free,
Joachim Eastwood7f4f69f2010-02-10 12:31:41 +01001316 .to_irq = bfin_gpiolib_gpio_to_irq,
Michael Hennericha4f0b322008-11-18 17:48:22 +08001317 .base = 0,
1318 .ngpio = MAX_BLACKFIN_GPIOS,
1319};
1320
1321static int __init bfin_gpiolib_setup(void)
1322{
1323 return gpiochip_add(&bfin_chip);
1324}
1325arch_initcall(bfin_gpiolib_setup);
1326#endif