blob: 170cf90735ba6cb806ee002b7041313760ebae2a [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 Frysinger168f12122007-10-11 00:22:35 +08009#include <linux/delay.h>
Bryan Wu1394f032007-05-06 14:50:22 -070010#include <linux/module.h>
11#include <linux/err.h>
Mike Frysinger1545a112007-12-24 16:54:48 +080012#include <linux/proc_fs.h>
Bryan Wu1394f032007-05-06 14:50:22 -070013#include <asm/blackfin.h>
14#include <asm/gpio.h>
Michael Hennerichc58c2142007-10-04 00:35:05 +080015#include <asm/portmux.h>
Bryan Wu1394f032007-05-06 14:50:22 -070016#include <linux/irq.h>
17
Michael Hennerich2b393312007-10-10 16:58:49 +080018#if ANOMALY_05000311 || ANOMALY_05000323
19enum {
20 AWA_data = SYSCR,
21 AWA_data_clear = SYSCR,
22 AWA_data_set = SYSCR,
23 AWA_toggle = SYSCR,
Graf Yang6ed83942008-04-24 04:43:14 +080024 AWA_maska = BFIN_UART_SCR,
25 AWA_maska_clear = BFIN_UART_SCR,
26 AWA_maska_set = BFIN_UART_SCR,
27 AWA_maska_toggle = BFIN_UART_SCR,
28 AWA_maskb = BFIN_UART_GCTL,
29 AWA_maskb_clear = BFIN_UART_GCTL,
30 AWA_maskb_set = BFIN_UART_GCTL,
31 AWA_maskb_toggle = BFIN_UART_GCTL,
Michael Hennerich2b393312007-10-10 16:58:49 +080032 AWA_dir = SPORT1_STAT,
33 AWA_polar = SPORT1_STAT,
34 AWA_edge = SPORT1_STAT,
35 AWA_both = SPORT1_STAT,
36#if ANOMALY_05000311
37 AWA_inen = TIMER_ENABLE,
38#elif ANOMALY_05000323
39 AWA_inen = DMA1_1_CONFIG,
40#endif
41};
42 /* Anomaly Workaround */
43#define AWA_DUMMY_READ(name) bfin_read16(AWA_ ## name)
44#else
45#define AWA_DUMMY_READ(...) do { } while (0)
46#endif
47
Mike Frysingerf5563092009-02-04 16:49:45 +080048static struct gpio_port_t * const gpio_array[] = {
Michael Hennerichdc26aec2008-11-18 17:48:22 +080049#if defined(BF533_FAMILY) || defined(BF538_FAMILY)
Bryan Wu1394f032007-05-06 14:50:22 -070050 (struct gpio_port_t *) FIO_FLAG_D,
Mike Frysinger269647d2009-03-28 20:32:57 +080051#elif defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Bryan Wu1394f032007-05-06 14:50:22 -070052 (struct gpio_port_t *) PORTFIO,
53 (struct gpio_port_t *) PORTGIO,
54 (struct gpio_port_t *) PORTHIO,
Mike Frysingerf5563092009-02-04 16:49:45 +080055#elif defined(BF561_FAMILY)
56 (struct gpio_port_t *) FIO0_FLAG_D,
57 (struct gpio_port_t *) FIO1_FLAG_D,
58 (struct gpio_port_t *) FIO2_FLAG_D,
Mike Frysinger269647d2009-03-28 20:32:57 +080059#elif defined(CONFIG_BF54x)
Mike Frysingerf5563092009-02-04 16:49:45 +080060 (struct gpio_port_t *)PORTA_FER,
61 (struct gpio_port_t *)PORTB_FER,
62 (struct gpio_port_t *)PORTC_FER,
63 (struct gpio_port_t *)PORTD_FER,
64 (struct gpio_port_t *)PORTE_FER,
65 (struct gpio_port_t *)PORTF_FER,
66 (struct gpio_port_t *)PORTG_FER,
67 (struct gpio_port_t *)PORTH_FER,
68 (struct gpio_port_t *)PORTI_FER,
69 (struct gpio_port_t *)PORTJ_FER,
70#else
71# error no gpio arrays defined
72#endif
Bryan Wu1394f032007-05-06 14:50:22 -070073};
74
Mike Frysinger269647d2009-03-28 20:32:57 +080075#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +080076static unsigned short * const port_fer[] = {
Bryan Wu1394f032007-05-06 14:50:22 -070077 (unsigned short *) PORTF_FER,
78 (unsigned short *) PORTG_FER,
79 (unsigned short *) PORTH_FER,
80};
Bryan Wu1394f032007-05-06 14:50:22 -070081
Mike Frysingerf5563092009-02-04 16:49:45 +080082# if !defined(BF537_FAMILY)
83static unsigned short * const port_mux[] = {
Michael Hennerich59003142007-10-21 16:54:27 +080084 (unsigned short *) PORTF_MUX,
85 (unsigned short *) PORTG_MUX,
86 (unsigned short *) PORTH_MUX,
87};
88
89static const
Graf Yang0ce5eaf2009-02-04 16:49:45 +080090u8 pmux_offset[][16] = {
Mike Frysinger269647d2009-03-28 20:32:57 +080091# if defined(CONFIG_BF52x)
Graf Yang0ce5eaf2009-02-04 16:49:45 +080092 { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */
93 { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */
94 { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */
Mike Frysinger269647d2009-03-28 20:32:57 +080095# elif defined(CONFIG_BF51x)
Graf Yang0ce5eaf2009-02-04 16:49:45 +080096 { 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */
97 { 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */
98 { 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */
99# endif
100};
Mike Frysingerf5563092009-02-04 16:49:45 +0800101# endif
Graf Yang0ce5eaf2009-02-04 16:49:45 +0800102
Michael Hennerich621dd242009-09-28 12:23:41 +0000103#elif defined(BF538_FAMILY)
104static unsigned short * const port_fer[] = {
105 (unsigned short *) PORTCIO_FER,
106 (unsigned short *) PORTDIO_FER,
107 (unsigned short *) PORTEIO_FER,
108};
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800109#endif
110
Mike Frysinger812ae982010-07-05 08:40:41 +0000111#define RESOURCE_LABEL_SIZE 16
Michael Hennerich8c613622007-08-03 17:48:09 +0800112
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800113static struct str_ident {
Michael Hennerich8c613622007-08-03 17:48:09 +0800114 char name[RESOURCE_LABEL_SIZE];
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800115} str_ident[MAX_RESOURCES];
Bryan Wu1394f032007-05-06 14:50:22 -0700116
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800117#if defined(CONFIG_PM)
Bryan Wu397861c2008-11-18 17:48:22 +0800118static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM];
Bryan Wu1394f032007-05-06 14:50:22 -0700119#endif
120
Mike Frysinger74c04502008-10-08 16:13:17 +0800121static void gpio_error(unsigned gpio)
Michael Hennerichacbcd262008-01-22 18:36:20 +0800122{
123 printk(KERN_ERR "bfin-gpio: GPIO %d wasn't requested!\n", gpio);
124}
125
Michael Hennerichc58c2142007-10-04 00:35:05 +0800126static void set_label(unsigned short ident, const char *label)
127{
Michael Henneriche9fae182008-10-13 11:35:22 +0800128 if (label) {
Michael Hennerich8c613622007-08-03 17:48:09 +0800129 strncpy(str_ident[ident].name, label,
Michael Hennerichc58c2142007-10-04 00:35:05 +0800130 RESOURCE_LABEL_SIZE);
Michael Hennerich8c613622007-08-03 17:48:09 +0800131 str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800132 }
133}
134
135static char *get_label(unsigned short ident)
136{
Michael Hennerich8c613622007-08-03 17:48:09 +0800137 return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN");
Michael Hennerichc58c2142007-10-04 00:35:05 +0800138}
139
140static int cmp_label(unsigned short ident, const char *label)
141{
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800142 if (label == NULL) {
143 dump_stack();
144 printk(KERN_ERR "Please provide none-null label\n");
145 }
146
Michael Henneriche9fae182008-10-13 11:35:22 +0800147 if (label)
Mike Frysinger1f7d3732008-10-28 15:47:11 +0800148 return strcmp(str_ident[ident].name, label);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800149 else
150 return -EINVAL;
151}
152
Mike Frysinger332824b2010-06-02 04:22:01 +0000153#define map_entry(m, i) reserved_##m##_map[gpio_bank(i)]
154#define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i))
155#define reserve(m, i) (map_entry(m, i) |= gpio_bit(i))
156#define unreserve(m, i) (map_entry(m, i) &= ~gpio_bit(i))
157#define DECLARE_RESERVED_MAP(m, c) static unsigned short reserved_##m##_map[c]
158
159DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM);
Michael Hennerich382dbe52010-07-13 08:26:10 +0000160DECLARE_RESERVED_MAP(peri, DIV_ROUND_UP(MAX_RESOURCES, GPIO_BANKSIZE));
Mike Frysinger332824b2010-06-02 04:22:01 +0000161DECLARE_RESERVED_MAP(gpio_irq, GPIO_BANK_NUM);
162
163inline int check_gpio(unsigned gpio)
164{
165#if defined(CONFIG_BF54x)
166 if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
167 || gpio == GPIO_PH14 || gpio == GPIO_PH15
168 || gpio == GPIO_PJ14 || gpio == GPIO_PJ15)
169 return -EINVAL;
170#endif
171 if (gpio >= MAX_BLACKFIN_GPIOS)
172 return -EINVAL;
173 return 0;
174}
175
Mike Frysingera2d03a12008-10-28 15:53:37 +0800176static void port_setup(unsigned gpio, unsigned short usage)
177{
Michael Hennerich621dd242009-09-28 12:23:41 +0000178#if defined(BF538_FAMILY)
179 /*
180 * BF538/9 Port C,D and E are special.
181 * Inverted PORT_FER polarity on CDE and no PORF_FER on F
182 * Regular PORT F GPIOs are handled here, CDE are exclusively
183 * managed by GPIOLIB
184 */
185
186 if (gpio < MAX_BLACKFIN_GPIOS || gpio >= MAX_RESOURCES)
187 return;
188
189 gpio -= MAX_BLACKFIN_GPIOS;
190
191 if (usage == GPIO_USAGE)
192 *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
193 else
194 *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
195 SSYNC();
196 return;
197#endif
198
Mike Frysingera2d03a12008-10-28 15:53:37 +0800199 if (check_gpio(gpio))
200 return;
201
Mike Frysinger269647d2009-03-28 20:32:57 +0800202#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Mike Frysingera2d03a12008-10-28 15:53:37 +0800203 if (usage == GPIO_USAGE)
204 *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
205 else
206 *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
207 SSYNC();
Mike Frysinger269647d2009-03-28 20:32:57 +0800208#elif defined(CONFIG_BF54x)
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800209 if (usage == GPIO_USAGE)
210 gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
211 else
212 gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
213 SSYNC();
Bryan Wu1394f032007-05-06 14:50:22 -0700214#endif
Mike Frysingera2d03a12008-10-28 15:53:37 +0800215}
Bryan Wu1394f032007-05-06 14:50:22 -0700216
Michael Hennerichc58c2142007-10-04 00:35:05 +0800217#ifdef BF537_FAMILY
steven miao05bbec32010-09-17 03:03:17 +0000218static const s8 port_mux[] = {
219 [GPIO_PF0] = 3,
220 [GPIO_PF1] = 3,
221 [GPIO_PF2] = 4,
222 [GPIO_PF3] = 4,
223 [GPIO_PF4] = 5,
224 [GPIO_PF5] = 6,
225 [GPIO_PF6] = 7,
226 [GPIO_PF7] = 8,
227 [GPIO_PF8 ... GPIO_PF15] = -1,
228 [GPIO_PG0 ... GPIO_PG7] = -1,
229 [GPIO_PG8] = 9,
230 [GPIO_PG9] = 9,
231 [GPIO_PG10] = 10,
232 [GPIO_PG11] = 10,
233 [GPIO_PG12] = 10,
234 [GPIO_PG13] = 11,
235 [GPIO_PG14] = 11,
236 [GPIO_PG15] = 11,
237 [GPIO_PH0 ... GPIO_PH15] = -1,
238 [PORT_PJ0 ... PORT_PJ3] = -1,
239 [PORT_PJ4] = 1,
240 [PORT_PJ5] = 1,
241 [PORT_PJ6 ... PORT_PJ9] = -1,
242 [PORT_PJ10] = 0,
243 [PORT_PJ11] = 0,
Michael Hennerichc58c2142007-10-04 00:35:05 +0800244};
245
steven miao05bbec32010-09-17 03:03:17 +0000246static int portmux_group_check(unsigned short per)
247{
248 u16 ident = P_IDENT(per);
249 u16 function = P_FUNCT2MUX(per);
250 s8 offset = port_mux[ident];
251 u16 m, pmux, pfunc;
252
253 if (offset < 0)
254 return 0;
255
256 pmux = bfin_read_PORT_MUX();
257 for (m = 0; m < ARRAY_SIZE(port_mux); ++m) {
258 if (m == ident)
259 continue;
260 if (port_mux[m] != offset)
261 continue;
262 if (!is_reserved(peri, m, 1))
263 continue;
264
265 if (offset == 1)
266 pfunc = (pmux >> offset) & 3;
267 else
268 pfunc = (pmux >> offset) & 1;
269 if (pfunc != function) {
270 pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",
271 ident, function, m, pfunc);
272 return -EINVAL;
273 }
274 }
275
276 return 0;
277}
278
Mike Frysingerf5563092009-02-04 16:49:45 +0800279static void portmux_setup(unsigned short per)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800280{
steven miao05bbec32010-09-17 03:03:17 +0000281 u16 ident = P_IDENT(per);
Mike Frysingerf5563092009-02-04 16:49:45 +0800282 u16 function = P_FUNCT2MUX(per);
steven miao05bbec32010-09-17 03:03:17 +0000283 s8 offset = port_mux[ident];
284 u16 pmux;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800285
steven miao05bbec32010-09-17 03:03:17 +0000286 if (offset == -1)
287 return;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800288
steven miao05bbec32010-09-17 03:03:17 +0000289 pmux = bfin_read_PORT_MUX();
290 if (offset != 1)
291 pmux &= ~(1 << offset);
292 else
293 pmux &= ~(3 << 1);
294 pmux |= (function << offset);
295 bfin_write_PORT_MUX(pmux);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800296}
Mike Frysinger269647d2009-03-28 20:32:57 +0800297#elif defined(CONFIG_BF54x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800298inline void portmux_setup(unsigned short per)
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800299{
Mike Frysingerf5563092009-02-04 16:49:45 +0800300 u16 ident = P_IDENT(per);
301 u16 function = P_FUNCT2MUX(per);
steven miao05bbec32010-09-17 03:03:17 +0000302 u32 pmux;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800303
Mike Frysingerf5563092009-02-04 16:49:45 +0800304 pmux = gpio_array[gpio_bank(ident)]->port_mux;
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800305
Mike Frysingerf5563092009-02-04 16:49:45 +0800306 pmux &= ~(0x3 << (2 * gpio_sub_n(ident)));
307 pmux |= (function & 0x3) << (2 * gpio_sub_n(ident));
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800308
Mike Frysingerf5563092009-02-04 16:49:45 +0800309 gpio_array[gpio_bank(ident)]->port_mux = pmux;
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800310}
311
Mike Frysingerf5563092009-02-04 16:49:45 +0800312inline u16 get_portmux(unsigned short per)
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800313{
Mike Frysingerf5563092009-02-04 16:49:45 +0800314 u16 ident = P_IDENT(per);
steven miao05bbec32010-09-17 03:03:17 +0000315 u32 pmux = gpio_array[gpio_bank(ident)]->port_mux;
Mike Frysingerf5563092009-02-04 16:49:45 +0800316 return (pmux >> (2 * gpio_sub_n(ident)) & 0x3);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800317}
steven miao05bbec32010-09-17 03:03:17 +0000318static int portmux_group_check(unsigned short per)
319{
320 return 0;
321}
Mike Frysinger269647d2009-03-28 20:32:57 +0800322#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
steven miao05bbec32010-09-17 03:03:17 +0000323static int portmux_group_check(unsigned short per)
324{
325 u16 ident = P_IDENT(per);
326 u16 function = P_FUNCT2MUX(per);
327 u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
328 u16 pin, gpiopin, pfunc;
329
330 for (pin = 0; pin < GPIO_BANKSIZE; ++pin) {
331 if (offset != pmux_offset[gpio_bank(ident)][pin])
332 continue;
333
334 gpiopin = gpio_bank(ident) * GPIO_BANKSIZE + pin;
335 if (gpiopin == ident)
336 continue;
337 if (!is_reserved(peri, gpiopin, 1))
338 continue;
339
340 pfunc = *port_mux[gpio_bank(ident)];
341 pfunc = (pfunc >> offset) & 3;
342 if (pfunc != function) {
343 pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",
344 ident, function, gpiopin, pfunc);
345 return -EINVAL;
346 }
347 }
348
349 return 0;
350}
351
Mike Frysingerf5563092009-02-04 16:49:45 +0800352inline void portmux_setup(unsigned short per)
Michael Hennerich59003142007-10-21 16:54:27 +0800353{
steven miao05bbec32010-09-17 03:03:17 +0000354 u16 ident = P_IDENT(per);
355 u16 function = P_FUNCT2MUX(per);
Michael Hennerich59003142007-10-21 16:54:27 +0800356 u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
steven miao05bbec32010-09-17 03:03:17 +0000357 u16 pmux;
Michael Hennerich59003142007-10-21 16:54:27 +0800358
359 pmux = *port_mux[gpio_bank(ident)];
steven miao05bbec32010-09-17 03:03:17 +0000360 if (((pmux >> offset) & 3) == function)
361 return;
Michael Hennerich59003142007-10-21 16:54:27 +0800362 pmux &= ~(3 << offset);
363 pmux |= (function & 3) << offset;
364 *port_mux[gpio_bank(ident)] = pmux;
365 SSYNC();
366}
Michael Hennerichc58c2142007-10-04 00:35:05 +0800367#else
368# define portmux_setup(...) do { } while (0)
steven miao05bbec32010-09-17 03:03:17 +0000369static int portmux_group_check(unsigned short per)
370{
371 return 0;
372}
Michael Hennerichc58c2142007-10-04 00:35:05 +0800373#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700374
Mike Frysinger269647d2009-03-28 20:32:57 +0800375#ifndef CONFIG_BF54x
Bryan Wu1394f032007-05-06 14:50:22 -0700376/***********************************************************
377*
378* FUNCTIONS: Blackfin General Purpose Ports Access Functions
379*
380* INPUTS/OUTPUTS:
381* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
382*
383*
384* DESCRIPTION: These functions abstract direct register access
385* to Blackfin processor General Purpose
386* Ports Regsiters
387*
388* CAUTION: These functions do not belong to the GPIO Driver API
389*************************************************************
390* MODIFICATION HISTORY :
391**************************************************************/
392
393/* Set a specific bit */
394
395#define SET_GPIO(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800396void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
Bryan Wu1394f032007-05-06 14:50:22 -0700397{ \
398 unsigned long flags; \
David Howells3b139cd2010-10-07 14:08:52 +0100399 flags = hard_local_irq_save(); \
Bryan Wu1394f032007-05-06 14:50:22 -0700400 if (arg) \
Mike Frysingerf5563092009-02-04 16:49:45 +0800401 gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
Bryan Wu1394f032007-05-06 14:50:22 -0700402 else \
Mike Frysingerf5563092009-02-04 16:49:45 +0800403 gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
Michael Hennerich2b393312007-10-10 16:58:49 +0800404 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100405 hard_local_irq_restore(flags); \
Bryan Wu1394f032007-05-06 14:50:22 -0700406} \
407EXPORT_SYMBOL(set_gpio_ ## name);
408
Mike Frysingerf5563092009-02-04 16:49:45 +0800409SET_GPIO(dir) /* set_gpio_dir() */
410SET_GPIO(inen) /* set_gpio_inen() */
411SET_GPIO(polar) /* set_gpio_polar() */
412SET_GPIO(edge) /* set_gpio_edge() */
413SET_GPIO(both) /* set_gpio_both() */
Bryan Wu1394f032007-05-06 14:50:22 -0700414
415
Michael Hennerich2b393312007-10-10 16:58:49 +0800416#define SET_GPIO_SC(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800417void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800418{ \
419 unsigned long flags; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800420 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100421 flags = hard_local_irq_save(); \
Michael Hennerich2b393312007-10-10 16:58:49 +0800422 if (arg) \
Mike Frysingerf5563092009-02-04 16:49:45 +0800423 gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
Michael Hennerich2b393312007-10-10 16:58:49 +0800424 else \
Mike Frysingerf5563092009-02-04 16:49:45 +0800425 gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
426 if (ANOMALY_05000311 || ANOMALY_05000323) { \
427 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100428 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800429 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800430} \
431EXPORT_SYMBOL(set_gpio_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700432
433SET_GPIO_SC(maska)
434SET_GPIO_SC(maskb)
Bryan Wu1394f032007-05-06 14:50:22 -0700435SET_GPIO_SC(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700436
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800437void set_gpio_toggle(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -0700438{
439 unsigned long flags;
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 gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
443 if (ANOMALY_05000311 || ANOMALY_05000323) {
444 AWA_DUMMY_READ(toggle);
David Howells3b139cd2010-10-07 14:08:52 +0100445 hard_local_irq_restore(flags);
Mike Frysingerf5563092009-02-04 16:49:45 +0800446 }
Bryan Wu1394f032007-05-06 14:50:22 -0700447}
Bryan Wu1394f032007-05-06 14:50:22 -0700448EXPORT_SYMBOL(set_gpio_toggle);
449
450
451/*Set current PORT date (16-bit word)*/
452
Michael Hennerich2b393312007-10-10 16:58:49 +0800453#define SET_GPIO_P(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800454void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800455{ \
456 unsigned long flags; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800457 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100458 flags = hard_local_irq_save(); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800459 gpio_array[gpio_bank(gpio)]->name = arg; \
460 if (ANOMALY_05000311 || ANOMALY_05000323) { \
461 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100462 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800463 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800464} \
465EXPORT_SYMBOL(set_gpiop_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700466
Michael Hennerich2b393312007-10-10 16:58:49 +0800467SET_GPIO_P(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700468SET_GPIO_P(dir)
469SET_GPIO_P(inen)
470SET_GPIO_P(polar)
471SET_GPIO_P(edge)
472SET_GPIO_P(both)
473SET_GPIO_P(maska)
474SET_GPIO_P(maskb)
475
Bryan Wu1394f032007-05-06 14:50:22 -0700476/* Get a specific bit */
Michael Hennerich2b393312007-10-10 16:58:49 +0800477#define GET_GPIO(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800478unsigned short get_gpio_ ## name(unsigned gpio) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800479{ \
480 unsigned long flags; \
481 unsigned short ret; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800482 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100483 flags = hard_local_irq_save(); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800484 ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \
485 if (ANOMALY_05000311 || ANOMALY_05000323) { \
486 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100487 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800488 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800489 return ret; \
490} \
491EXPORT_SYMBOL(get_gpio_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700492
Michael Hennerich2b393312007-10-10 16:58:49 +0800493GET_GPIO(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700494GET_GPIO(dir)
495GET_GPIO(inen)
496GET_GPIO(polar)
497GET_GPIO(edge)
498GET_GPIO(both)
499GET_GPIO(maska)
500GET_GPIO(maskb)
501
Bryan Wu1394f032007-05-06 14:50:22 -0700502/*Get current PORT date (16-bit word)*/
503
Michael Hennerich2b393312007-10-10 16:58:49 +0800504#define GET_GPIO_P(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800505unsigned short get_gpiop_ ## name(unsigned gpio) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800506{ \
507 unsigned long flags; \
508 unsigned short ret; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800509 if (ANOMALY_05000311 || ANOMALY_05000323) \
David Howells3b139cd2010-10-07 14:08:52 +0100510 flags = hard_local_irq_save(); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800511 ret = (gpio_array[gpio_bank(gpio)]->name); \
512 if (ANOMALY_05000311 || ANOMALY_05000323) { \
513 AWA_DUMMY_READ(name); \
David Howells3b139cd2010-10-07 14:08:52 +0100514 hard_local_irq_restore(flags); \
Mike Frysingerf5563092009-02-04 16:49:45 +0800515 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800516 return ret; \
517} \
518EXPORT_SYMBOL(get_gpiop_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700519
Michael Hennerich2b393312007-10-10 16:58:49 +0800520GET_GPIO_P(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700521GET_GPIO_P(dir)
522GET_GPIO_P(inen)
523GET_GPIO_P(polar)
524GET_GPIO_P(edge)
525GET_GPIO_P(both)
526GET_GPIO_P(maska)
527GET_GPIO_P(maskb)
528
Bryan Wu1394f032007-05-06 14:50:22 -0700529
530#ifdef CONFIG_PM
Mike Frysinger332824b2010-06-02 04:22:01 +0000531DECLARE_RESERVED_MAP(wakeup, GPIO_BANK_NUM);
Mike Frysingerf5563092009-02-04 16:49:45 +0800532
533static const unsigned int sic_iwr_irqs[] = {
534#if defined(BF533_FAMILY)
535 IRQ_PROG_INTB
536#elif defined(BF537_FAMILY)
537 IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX
538#elif defined(BF538_FAMILY)
539 IRQ_PORTF_INTB
Mike Frysinger269647d2009-03-28 20:32:57 +0800540#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800541 IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB
542#elif defined(BF561_FAMILY)
543 IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB
544#else
545# error no SIC_IWR defined
546#endif
547};
548
Bryan Wu1394f032007-05-06 14:50:22 -0700549/***********************************************************
550*
551* FUNCTIONS: Blackfin PM Setup API
552*
553* INPUTS/OUTPUTS:
554* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
555* type -
556* PM_WAKE_RISING
557* PM_WAKE_FALLING
558* PM_WAKE_HIGH
559* PM_WAKE_LOW
560* PM_WAKE_BOTH_EDGES
561*
562* DESCRIPTION: Blackfin PM Driver API
563*
564* CAUTION:
565*************************************************************
566* MODIFICATION HISTORY :
567**************************************************************/
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000568int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)
Bryan Wu1394f032007-05-06 14:50:22 -0700569{
570 unsigned long flags;
571
572 if (check_gpio(gpio) < 0)
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000573 return -EINVAL;
Bryan Wu1394f032007-05-06 14:50:22 -0700574
David Howells3b139cd2010-10-07 14:08:52 +0100575 flags = hard_local_irq_save();
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000576 if (ctrl)
Mike Frysinger332824b2010-06-02 04:22:01 +0000577 reserve(wakeup, gpio);
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000578 else
Mike Frysinger332824b2010-06-02 04:22:01 +0000579 unreserve(wakeup, gpio);
Bryan Wu1394f032007-05-06 14:50:22 -0700580
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000581 set_gpio_maskb(gpio, ctrl);
David Howells3b139cd2010-10-07 14:08:52 +0100582 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700583
584 return 0;
585}
586
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000587int bfin_pm_standby_ctrl(unsigned ctrl)
Bryan Wu1394f032007-05-06 14:50:22 -0700588{
589 u16 bank, mask, i;
590
Mike Frysinger1f83b8f2007-07-12 22:58:21 +0800591 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Mike Frysinger332824b2010-06-02 04:22:01 +0000592 mask = map_entry(wakeup, i);
Bryan Wu1394f032007-05-06 14:50:22 -0700593 bank = gpio_bank(i);
594
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000595 if (mask)
596 bfin_internal_set_wake(sic_iwr_irqs[bank], ctrl);
Bryan Wu1394f032007-05-06 14:50:22 -0700597 }
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000598 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -0700599}
600
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800601void bfin_gpio_pm_hibernate_suspend(void)
602{
603 int i, bank;
604
605 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
606 bank = gpio_bank(i);
607
Mike Frysinger269647d2009-03-28 20:32:57 +0800608#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800609 gpio_bank_saved[bank].fer = *port_fer[bank];
Mike Frysinger269647d2009-03-28 20:32:57 +0800610#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800611 gpio_bank_saved[bank].mux = *port_mux[bank];
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800612#else
Mike Frysingerf5563092009-02-04 16:49:45 +0800613 if (bank == 0)
614 gpio_bank_saved[bank].mux = bfin_read_PORT_MUX();
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800615#endif
616#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800617 gpio_bank_saved[bank].data = gpio_array[bank]->data;
618 gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
619 gpio_bank_saved[bank].polar = gpio_array[bank]->polar;
620 gpio_bank_saved[bank].dir = gpio_array[bank]->dir;
621 gpio_bank_saved[bank].edge = gpio_array[bank]->edge;
622 gpio_bank_saved[bank].both = gpio_array[bank]->both;
623 gpio_bank_saved[bank].maska = gpio_array[bank]->maska;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800624 }
625
626 AWA_DUMMY_READ(maska);
627}
628
629void bfin_gpio_pm_hibernate_restore(void)
630{
631 int i, bank;
632
633 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Mike Frysingerf5563092009-02-04 16:49:45 +0800634 bank = gpio_bank(i);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800635
Mike Frysinger269647d2009-03-28 20:32:57 +0800636#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
637#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800638 *port_mux[bank] = gpio_bank_saved[bank].mux;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800639#else
Mike Frysingerf5563092009-02-04 16:49:45 +0800640 if (bank == 0)
641 bfin_write_PORT_MUX(gpio_bank_saved[bank].mux);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800642#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800643 *port_fer[bank] = gpio_bank_saved[bank].fer;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800644#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800645 gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
Michael Hennerichc03c2a872009-07-08 12:04:43 +0000646 gpio_array[bank]->data_set = gpio_bank_saved[bank].data
647 & gpio_bank_saved[bank].dir;
Mike Frysingerf5563092009-02-04 16:49:45 +0800648 gpio_array[bank]->dir = gpio_bank_saved[bank].dir;
649 gpio_array[bank]->polar = gpio_bank_saved[bank].polar;
650 gpio_array[bank]->edge = gpio_bank_saved[bank].edge;
651 gpio_array[bank]->both = gpio_bank_saved[bank].both;
Mike Frysingerf5563092009-02-04 16:49:45 +0800652 gpio_array[bank]->maska = gpio_bank_saved[bank].maska;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800653 }
654 AWA_DUMMY_READ(maska);
655}
656
657
Bryan Wu1394f032007-05-06 14:50:22 -0700658#endif
Mike Frysinger269647d2009-03-28 20:32:57 +0800659#else /* CONFIG_BF54x */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800660#ifdef CONFIG_PM
661
Michael Hennerichbb84dbf2010-03-10 14:26:06 +0000662int bfin_pm_standby_ctrl(unsigned ctrl)
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800663{
664 return 0;
665}
666
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800667void bfin_gpio_pm_hibernate_suspend(void)
668{
669 int i, bank;
670
671 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
672 bank = gpio_bank(i);
673
Mike Frysingerf5563092009-02-04 16:49:45 +0800674 gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer;
675 gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux;
676 gpio_bank_saved[bank].data = gpio_array[bank]->data;
Mike Frysingerf5563092009-02-04 16:49:45 +0800677 gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
678 gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800679 }
680}
681
682void bfin_gpio_pm_hibernate_restore(void)
683{
684 int i, bank;
685
686 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Mike Frysingerf5563092009-02-04 16:49:45 +0800687 bank = gpio_bank(i);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800688
Mike Frysingerf5563092009-02-04 16:49:45 +0800689 gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux;
690 gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer;
691 gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
692 gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir;
693 gpio_array[bank]->data_set = gpio_bank_saved[bank].data
694 | gpio_bank_saved[bank].dir;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800695 }
696}
697#endif
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800698
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800699unsigned short get_gpio_dir(unsigned gpio)
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800700{
Mike Frysingerf5563092009-02-04 16:49:45 +0800701 return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio)));
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800702}
703EXPORT_SYMBOL(get_gpio_dir);
704
Mike Frysinger269647d2009-03-28 20:32:57 +0800705#endif /* CONFIG_BF54x */
Bryan Wu1394f032007-05-06 14:50:22 -0700706
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800707/***********************************************************
708*
Mike Frysinger812ae982010-07-05 08:40:41 +0000709* FUNCTIONS: Blackfin Peripheral Resource Allocation
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800710* and PortMux Setup
711*
712* INPUTS/OUTPUTS:
713* per Peripheral Identifier
714* label String
715*
716* DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API
717*
718* CAUTION:
719*************************************************************
720* MODIFICATION HISTORY :
721**************************************************************/
Michael Hennerichc58c2142007-10-04 00:35:05 +0800722
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800723int peripheral_request(unsigned short per, const char *label)
724{
725 unsigned long flags;
726 unsigned short ident = P_IDENT(per);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800727
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800728 /*
729 * Don't cares are pins with only one dedicated function
730 */
731
732 if (per & P_DONTCARE)
733 return 0;
734
735 if (!(per & P_DEFINED))
736 return -ENODEV;
737
Barry Song89e84ee2009-09-16 04:36:29 +0000738 BUG_ON(ident >= MAX_RESOURCES);
739
David Howells3b139cd2010-10-07 14:08:52 +0100740 flags = hard_local_irq_save();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800741
Mike Frysinger6a87d292008-10-28 16:16:29 +0800742 /* If a pin can be muxed as either GPIO or peripheral, make
743 * sure it is not already a GPIO pin when we request it.
744 */
Mike Frysinger332824b2010-06-02 04:22:01 +0000745 if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800746 if (system_state == SYSTEM_BOOTING)
747 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800748 printk(KERN_ERR
Mike Frysinger6c7ec0e2008-10-28 15:49:59 +0800749 "%s: Peripheral %d is already reserved as GPIO by %s !\n",
Harvey Harrisonb85d8582008-04-23 09:39:01 +0800750 __func__, ident, get_label(ident));
David Howells3b139cd2010-10-07 14:08:52 +0100751 hard_local_irq_restore(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800752 return -EBUSY;
753 }
754
Mike Frysinger332824b2010-06-02 04:22:01 +0000755 if (unlikely(is_reserved(peri, ident, 1))) {
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800756
Mike Frysingerd171c232008-03-26 08:35:46 +0800757 /*
758 * Pin functions like AMC address strobes my
759 * be requested and used by several drivers
760 */
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800761
Mike Frysinger269647d2009-03-28 20:32:57 +0800762#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +0800763 if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) {
Mike Frysinger6c7ec0e2008-10-28 15:49:59 +0800764#else
765 if (!(per & P_MAYSHARE)) {
766#endif
Mike Frysingerd171c232008-03-26 08:35:46 +0800767 /*
768 * Allow that the identical pin function can
769 * be requested from the same driver twice
770 */
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800771
Mike Frysingerd171c232008-03-26 08:35:46 +0800772 if (cmp_label(ident, label) == 0)
773 goto anyway;
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800774
Robin Getzd6879c52009-03-29 01:10:30 +0800775 if (system_state == SYSTEM_BOOTING)
776 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800777 printk(KERN_ERR
778 "%s: Peripheral %d function %d is already reserved by %s !\n",
Harvey Harrisonb85d8582008-04-23 09:39:01 +0800779 __func__, ident, P_FUNCT2MUX(per), get_label(ident));
David Howells3b139cd2010-10-07 14:08:52 +0100780 hard_local_irq_restore(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800781 return -EBUSY;
782 }
783 }
784
steven miao05bbec32010-09-17 03:03:17 +0000785 if (unlikely(portmux_group_check(per))) {
786 hard_local_irq_restore(flags);
787 return -EBUSY;
788 }
Mike Frysingerd171c232008-03-26 08:35:46 +0800789 anyway:
Mike Frysinger332824b2010-06-02 04:22:01 +0000790 reserve(peri, ident);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800791
Mike Frysingerf5563092009-02-04 16:49:45 +0800792 portmux_setup(per);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800793 port_setup(ident, PERIPHERAL_USAGE);
794
David Howells3b139cd2010-10-07 14:08:52 +0100795 hard_local_irq_restore(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800796 set_label(ident, label);
797
798 return 0;
799}
800EXPORT_SYMBOL(peripheral_request);
801
Mike Frysinger68179372008-04-24 05:04:24 +0800802int peripheral_request_list(const unsigned short per[], const char *label)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800803{
804 u16 cnt;
805 int ret;
806
807 for (cnt = 0; per[cnt] != 0; cnt++) {
Michael Hennerich314c98d2007-07-24 18:03:45 +0800808
Michael Hennerichc58c2142007-10-04 00:35:05 +0800809 ret = peripheral_request(per[cnt], label);
Michael Hennerich314c98d2007-07-24 18:03:45 +0800810
811 if (ret < 0) {
Mike Frysingerd171c232008-03-26 08:35:46 +0800812 for ( ; cnt > 0; cnt--)
Michael Hennerich314c98d2007-07-24 18:03:45 +0800813 peripheral_free(per[cnt - 1]);
Mike Frysingerd171c232008-03-26 08:35:46 +0800814
815 return ret;
Michael Hennerich314c98d2007-07-24 18:03:45 +0800816 }
Michael Hennerichc58c2142007-10-04 00:35:05 +0800817 }
818
819 return 0;
820}
821EXPORT_SYMBOL(peripheral_request_list);
822
823void peripheral_free(unsigned short per)
824{
825 unsigned long flags;
826 unsigned short ident = P_IDENT(per);
827
828 if (per & P_DONTCARE)
829 return;
830
831 if (!(per & P_DEFINED))
832 return;
833
David Howells3b139cd2010-10-07 14:08:52 +0100834 flags = hard_local_irq_save();
Michael Hennerichc58c2142007-10-04 00:35:05 +0800835
Mike Frysinger332824b2010-06-02 04:22:01 +0000836 if (unlikely(!is_reserved(peri, ident, 0))) {
David Howells3b139cd2010-10-07 14:08:52 +0100837 hard_local_irq_restore(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800838 return;
839 }
840
Mike Frysingerd171c232008-03-26 08:35:46 +0800841 if (!(per & P_MAYSHARE))
Michael Hennerichc58c2142007-10-04 00:35:05 +0800842 port_setup(ident, GPIO_USAGE);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800843
Mike Frysinger332824b2010-06-02 04:22:01 +0000844 unreserve(peri, ident);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800845
Michael Hennerich2acde902007-10-11 00:24:40 +0800846 set_label(ident, "free");
847
David Howells3b139cd2010-10-07 14:08:52 +0100848 hard_local_irq_restore(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800849}
850EXPORT_SYMBOL(peripheral_free);
851
Mike Frysinger68179372008-04-24 05:04:24 +0800852void peripheral_free_list(const unsigned short per[])
Michael Hennerichc58c2142007-10-04 00:35:05 +0800853{
854 u16 cnt;
Mike Frysingerd171c232008-03-26 08:35:46 +0800855 for (cnt = 0; per[cnt] != 0; cnt++)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800856 peripheral_free(per[cnt]);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800857}
858EXPORT_SYMBOL(peripheral_free_list);
859
Bryan Wu1394f032007-05-06 14:50:22 -0700860/***********************************************************
861*
862* FUNCTIONS: Blackfin GPIO Driver
863*
864* INPUTS/OUTPUTS:
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800865* gpio PIO Number between 0 and MAX_BLACKFIN_GPIOS
866* label String
Bryan Wu1394f032007-05-06 14:50:22 -0700867*
868* DESCRIPTION: Blackfin GPIO Driver API
869*
870* CAUTION:
871*************************************************************
872* MODIFICATION HISTORY :
873**************************************************************/
874
Michael Hennericha4f0b32c2008-11-18 17:48:22 +0800875int bfin_gpio_request(unsigned gpio, const char *label)
Bryan Wu1394f032007-05-06 14:50:22 -0700876{
877 unsigned long flags;
878
879 if (check_gpio(gpio) < 0)
880 return -EINVAL;
881
David Howells3b139cd2010-10-07 14:08:52 +0100882 flags = hard_local_irq_save();
Bryan Wu1394f032007-05-06 14:50:22 -0700883
Michael Hennerich2acde902007-10-11 00:24:40 +0800884 /*
885 * Allow that the identical GPIO can
886 * be requested from the same driver twice
887 * Do nothing and return -
888 */
889
890 if (cmp_label(gpio, label) == 0) {
David Howells3b139cd2010-10-07 14:08:52 +0100891 hard_local_irq_restore(flags);
Michael Hennerich2acde902007-10-11 00:24:40 +0800892 return 0;
893 }
894
Mike Frysinger332824b2010-06-02 04:22:01 +0000895 if (unlikely(is_reserved(gpio, gpio, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800896 if (system_state == SYSTEM_BOOTING)
897 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800898 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
Graf Yang9570ff42009-01-07 23:14:38 +0800899 gpio, get_label(gpio));
David Howells3b139cd2010-10-07 14:08:52 +0100900 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700901 return -EBUSY;
902 }
Mike Frysinger332824b2010-06-02 04:22:01 +0000903 if (unlikely(is_reserved(peri, gpio, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800904 if (system_state == SYSTEM_BOOTING)
905 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800906 printk(KERN_ERR
907 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
908 gpio, get_label(gpio));
David Howells3b139cd2010-10-07 14:08:52 +0100909 hard_local_irq_restore(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800910 return -EBUSY;
911 }
Mike Frysinger332824b2010-06-02 04:22:01 +0000912 if (unlikely(is_reserved(gpio_irq, gpio, 1))) {
Graf Yang9570ff42009-01-07 23:14:38 +0800913 printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!"
914 " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio);
Michael Hennericha2be3932009-02-04 16:49:45 +0800915 }
Mike Frysinger269647d2009-03-28 20:32:57 +0800916#ifndef CONFIG_BF54x
Michael Hennericha2be3932009-02-04 16:49:45 +0800917 else { /* Reset POLAR setting when acquiring a gpio for the first time */
918 set_gpio_polar(gpio, 0);
919 }
920#endif
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800921
Mike Frysinger332824b2010-06-02 04:22:01 +0000922 reserve(gpio, gpio);
Graf Yang9570ff42009-01-07 23:14:38 +0800923 set_label(gpio, label);
Bryan Wu1394f032007-05-06 14:50:22 -0700924
David Howells3b139cd2010-10-07 14:08:52 +0100925 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700926
927 port_setup(gpio, GPIO_USAGE);
928
929 return 0;
930}
Michael Hennericha4f0b32c2008-11-18 17:48:22 +0800931EXPORT_SYMBOL(bfin_gpio_request);
Bryan Wu1394f032007-05-06 14:50:22 -0700932
Michael Hennericha4f0b32c2008-11-18 17:48:22 +0800933void bfin_gpio_free(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -0700934{
935 unsigned long flags;
936
937 if (check_gpio(gpio) < 0)
938 return;
939
Uwe Kleine-Koenig45c4f2a2009-02-04 17:02:30 +0800940 might_sleep();
941
David Howells3b139cd2010-10-07 14:08:52 +0100942 flags = hard_local_irq_save();
Bryan Wu1394f032007-05-06 14:50:22 -0700943
Mike Frysinger332824b2010-06-02 04:22:01 +0000944 if (unlikely(!is_reserved(gpio, gpio, 0))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800945 if (system_state == SYSTEM_BOOTING)
946 dump_stack();
Mike Frysingerf85c4ab2008-03-26 08:34:23 +0800947 gpio_error(gpio);
David Howells3b139cd2010-10-07 14:08:52 +0100948 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700949 return;
950 }
951
Mike Frysinger332824b2010-06-02 04:22:01 +0000952 unreserve(gpio, gpio);
Bryan Wu1394f032007-05-06 14:50:22 -0700953
Michael Hennerich2acde902007-10-11 00:24:40 +0800954 set_label(gpio, "free");
955
David Howells3b139cd2010-10-07 14:08:52 +0100956 hard_local_irq_restore(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700957}
Michael Hennericha4f0b32c2008-11-18 17:48:22 +0800958EXPORT_SYMBOL(bfin_gpio_free);
Bryan Wu1394f032007-05-06 14:50:22 -0700959
Michael Hennerich621dd242009-09-28 12:23:41 +0000960#ifdef BFIN_SPECIAL_GPIO_BANKS
Mike Frysinger332824b2010-06-02 04:22:01 +0000961DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES));
Michael Hennerich621dd242009-09-28 12:23:41 +0000962
963int bfin_special_gpio_request(unsigned gpio, const char *label)
964{
965 unsigned long flags;
966
David Howells3b139cd2010-10-07 14:08:52 +0100967 flags = hard_local_irq_save();
Michael Hennerich621dd242009-09-28 12:23:41 +0000968
969 /*
970 * Allow that the identical GPIO can
971 * be requested from the same driver twice
972 * Do nothing and return -
973 */
974
975 if (cmp_label(gpio, label) == 0) {
David Howells3b139cd2010-10-07 14:08:52 +0100976 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +0000977 return 0;
978 }
979
Mike Frysinger332824b2010-06-02 04:22:01 +0000980 if (unlikely(is_reserved(special_gpio, gpio, 1))) {
David Howells3b139cd2010-10-07 14:08:52 +0100981 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +0000982 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
983 gpio, get_label(gpio));
984
985 return -EBUSY;
986 }
Mike Frysinger332824b2010-06-02 04:22:01 +0000987 if (unlikely(is_reserved(peri, gpio, 1))) {
David Howells3b139cd2010-10-07 14:08:52 +0100988 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +0000989 printk(KERN_ERR
990 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
991 gpio, get_label(gpio));
992
993 return -EBUSY;
994 }
995
Mike Frysinger332824b2010-06-02 04:22:01 +0000996 reserve(special_gpio, gpio);
997 reserve(peri, gpio);
Michael Hennerich621dd242009-09-28 12:23:41 +0000998
999 set_label(gpio, label);
David Howells3b139cd2010-10-07 14:08:52 +01001000 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +00001001 port_setup(gpio, GPIO_USAGE);
1002
1003 return 0;
1004}
1005EXPORT_SYMBOL(bfin_special_gpio_request);
1006
1007void bfin_special_gpio_free(unsigned gpio)
1008{
1009 unsigned long flags;
1010
1011 might_sleep();
1012
David Howells3b139cd2010-10-07 14:08:52 +01001013 flags = hard_local_irq_save();
Michael Hennerich621dd242009-09-28 12:23:41 +00001014
Mike Frysinger332824b2010-06-02 04:22:01 +00001015 if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
Michael Hennerich621dd242009-09-28 12:23:41 +00001016 gpio_error(gpio);
David Howells3b139cd2010-10-07 14:08:52 +01001017 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +00001018 return;
1019 }
1020
Mike Frysinger332824b2010-06-02 04:22:01 +00001021 unreserve(special_gpio, gpio);
1022 unreserve(peri, gpio);
Michael Hennerich621dd242009-09-28 12:23:41 +00001023 set_label(gpio, "free");
David Howells3b139cd2010-10-07 14:08:52 +01001024 hard_local_irq_restore(flags);
Michael Hennerich621dd242009-09-28 12:23:41 +00001025}
1026EXPORT_SYMBOL(bfin_special_gpio_free);
1027#endif
1028
1029
Graf Yang9570ff42009-01-07 23:14:38 +08001030int bfin_gpio_irq_request(unsigned gpio, const char *label)
1031{
1032 unsigned long flags;
1033
1034 if (check_gpio(gpio) < 0)
1035 return -EINVAL;
1036
David Howells3b139cd2010-10-07 14:08:52 +01001037 flags = hard_local_irq_save();
Graf Yang9570ff42009-01-07 23:14:38 +08001038
Mike Frysinger332824b2010-06-02 04:22:01 +00001039 if (unlikely(is_reserved(peri, gpio, 1))) {
Robin Getzd6879c52009-03-29 01:10:30 +08001040 if (system_state == SYSTEM_BOOTING)
1041 dump_stack();
Graf Yang9570ff42009-01-07 23:14:38 +08001042 printk(KERN_ERR
1043 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
1044 gpio, get_label(gpio));
David Howells3b139cd2010-10-07 14:08:52 +01001045 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001046 return -EBUSY;
1047 }
Mike Frysinger332824b2010-06-02 04:22:01 +00001048 if (unlikely(is_reserved(gpio, gpio, 1)))
Graf Yang9570ff42009-01-07 23:14:38 +08001049 printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved by %s! "
1050 "(Documentation/blackfin/bfin-gpio-notes.txt)\n",
1051 gpio, get_label(gpio));
1052
Mike Frysinger332824b2010-06-02 04:22:01 +00001053 reserve(gpio_irq, gpio);
Graf Yang9570ff42009-01-07 23:14:38 +08001054 set_label(gpio, label);
1055
David Howells3b139cd2010-10-07 14:08:52 +01001056 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001057
1058 port_setup(gpio, GPIO_USAGE);
1059
1060 return 0;
1061}
1062
1063void bfin_gpio_irq_free(unsigned gpio)
1064{
1065 unsigned long flags;
1066
1067 if (check_gpio(gpio) < 0)
1068 return;
1069
David Howells3b139cd2010-10-07 14:08:52 +01001070 flags = hard_local_irq_save();
Graf Yang9570ff42009-01-07 23:14:38 +08001071
Mike Frysinger332824b2010-06-02 04:22:01 +00001072 if (unlikely(!is_reserved(gpio_irq, gpio, 0))) {
Robin Getzd6879c52009-03-29 01:10:30 +08001073 if (system_state == SYSTEM_BOOTING)
1074 dump_stack();
Graf Yang9570ff42009-01-07 23:14:38 +08001075 gpio_error(gpio);
David Howells3b139cd2010-10-07 14:08:52 +01001076 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001077 return;
1078 }
1079
Mike Frysinger332824b2010-06-02 04:22:01 +00001080 unreserve(gpio_irq, gpio);
Graf Yang9570ff42009-01-07 23:14:38 +08001081
1082 set_label(gpio, "free");
1083
David Howells3b139cd2010-10-07 14:08:52 +01001084 hard_local_irq_restore(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001085}
1086
Mike Frysingerf5563092009-02-04 16:49:45 +08001087static inline void __bfin_gpio_direction_input(unsigned gpio)
1088{
Mike Frysinger269647d2009-03-28 20:32:57 +08001089#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001090 gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
Michael Hennerichd2b11a42007-08-28 16:47:46 +08001091#else
Mike Frysingerf5563092009-02-04 16:49:45 +08001092 gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
1093#endif
1094 gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
Michael Hennerich803a8d22008-05-17 16:01:51 +08001095}
Michael Hennerich803a8d22008-05-17 16:01:51 +08001096
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001097int bfin_gpio_direction_input(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -07001098{
1099 unsigned long flags;
1100
Mike Frysinger332824b2010-06-02 04:22:01 +00001101 if (unlikely(!is_reserved(gpio, gpio, 0))) {
Michael Hennerichacbcd262008-01-22 18:36:20 +08001102 gpio_error(gpio);
1103 return -EINVAL;
1104 }
Bryan Wu1394f032007-05-06 14:50:22 -07001105
David Howells3b139cd2010-10-07 14:08:52 +01001106 flags = hard_local_irq_save();
Mike Frysingerf5563092009-02-04 16:49:45 +08001107 __bfin_gpio_direction_input(gpio);
Michael Hennerich2b393312007-10-10 16:58:49 +08001108 AWA_DUMMY_READ(inen);
David Howells3b139cd2010-10-07 14:08:52 +01001109 hard_local_irq_restore(flags);
Michael Hennerichacbcd262008-01-22 18:36:20 +08001110
1111 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -07001112}
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001113EXPORT_SYMBOL(bfin_gpio_direction_input);
Bryan Wu1394f032007-05-06 14:50:22 -07001114
Mike Frysingerf5563092009-02-04 16:49:45 +08001115void bfin_gpio_irq_prepare(unsigned gpio)
1116{
Mike Frysinger269647d2009-03-28 20:32:57 +08001117#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001118 unsigned long flags;
1119#endif
1120
1121 port_setup(gpio, GPIO_USAGE);
1122
Mike Frysinger269647d2009-03-28 20:32:57 +08001123#ifdef CONFIG_BF54x
David Howells3b139cd2010-10-07 14:08:52 +01001124 flags = hard_local_irq_save();
Mike Frysingerf5563092009-02-04 16:49:45 +08001125 __bfin_gpio_direction_input(gpio);
David Howells3b139cd2010-10-07 14:08:52 +01001126 hard_local_irq_restore(flags);
Mike Frysingerf5563092009-02-04 16:49:45 +08001127#endif
1128}
1129
1130void bfin_gpio_set_value(unsigned gpio, int arg)
1131{
1132 if (arg)
1133 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
1134 else
1135 gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
1136}
1137EXPORT_SYMBOL(bfin_gpio_set_value);
1138
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001139int bfin_gpio_direction_output(unsigned gpio, int value)
Bryan Wu1394f032007-05-06 14:50:22 -07001140{
1141 unsigned long flags;
1142
Mike Frysinger332824b2010-06-02 04:22:01 +00001143 if (unlikely(!is_reserved(gpio, gpio, 0))) {
Michael Hennerichacbcd262008-01-22 18:36:20 +08001144 gpio_error(gpio);
1145 return -EINVAL;
1146 }
Bryan Wu1394f032007-05-06 14:50:22 -07001147
David Howells3b139cd2010-10-07 14:08:52 +01001148 flags = hard_local_irq_save();
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001149
Mike Frysingerf5563092009-02-04 16:49:45 +08001150 gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
1151 gpio_set_value(gpio, value);
Mike Frysinger269647d2009-03-28 20:32:57 +08001152#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001153 gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
1154#else
1155 gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
1156#endif
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001157
Michael Hennerich2b393312007-10-10 16:58:49 +08001158 AWA_DUMMY_READ(dir);
David Howells3b139cd2010-10-07 14:08:52 +01001159 hard_local_irq_restore(flags);
Michael Hennerichacbcd262008-01-22 18:36:20 +08001160
1161 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -07001162}
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001163EXPORT_SYMBOL(bfin_gpio_direction_output);
Mike Frysinger168f12122007-10-11 00:22:35 +08001164
Mike Frysingerf5563092009-02-04 16:49:45 +08001165int bfin_gpio_get_value(unsigned gpio)
1166{
Mike Frysinger269647d2009-03-28 20:32:57 +08001167#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001168 return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)));
1169#else
1170 unsigned long flags;
1171
1172 if (unlikely(get_gpio_edge(gpio))) {
1173 int ret;
David Howells3b139cd2010-10-07 14:08:52 +01001174 flags = hard_local_irq_save();
Mike Frysingerf5563092009-02-04 16:49:45 +08001175 set_gpio_edge(gpio, 0);
1176 ret = get_gpio_data(gpio);
1177 set_gpio_edge(gpio, 1);
David Howells3b139cd2010-10-07 14:08:52 +01001178 hard_local_irq_restore(flags);
Mike Frysingerf5563092009-02-04 16:49:45 +08001179 return ret;
1180 } else
1181 return get_gpio_data(gpio);
1182#endif
1183}
1184EXPORT_SYMBOL(bfin_gpio_get_value);
1185
Mike Frysinger168f12122007-10-11 00:22:35 +08001186/* If we are booting from SPI and our board lacks a strong enough pull up,
1187 * the core can reset and execute the bootrom faster than the resistor can
1188 * pull the signal logically high. To work around this (common) error in
1189 * board design, we explicitly set the pin back to GPIO mode, force /CS
1190 * high, and wait for the electrons to do their thing.
1191 *
1192 * This function only makes sense to be called from reset code, but it
1193 * lives here as we need to force all the GPIO states w/out going through
1194 * BUG() checks and such.
1195 */
Sonic Zhangb52dae32009-02-04 16:49:45 +08001196void bfin_reset_boot_spi_cs(unsigned short pin)
Mike Frysinger168f12122007-10-11 00:22:35 +08001197{
Sonic Zhangb52dae32009-02-04 16:49:45 +08001198 unsigned short gpio = P_IDENT(pin);
Michael Hennerich4d5f4ed2007-08-27 16:46:17 +08001199 port_setup(gpio, GPIO_USAGE);
Mike Frysingerf5563092009-02-04 16:49:45 +08001200 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001201 AWA_DUMMY_READ(data_set);
Mike Frysinger168f12122007-10-11 00:22:35 +08001202 udelay(1);
1203}
Michael Hennerichd2b11a42007-08-28 16:47:46 +08001204
Mike Frysinger1545a112007-12-24 16:54:48 +08001205#if defined(CONFIG_PROC_FS)
1206static int gpio_proc_read(char *buf, char **start, off_t offset,
1207 int len, int *unused_i, void *unused_v)
1208{
Graf Yang9570ff42009-01-07 23:14:38 +08001209 int c, irq, gpio, outlen = 0;
Mike Frysinger1545a112007-12-24 16:54:48 +08001210
1211 for (c = 0; c < MAX_RESOURCES; c++) {
Mike Frysinger332824b2010-06-02 04:22:01 +00001212 irq = is_reserved(gpio_irq, c, 1);
1213 gpio = is_reserved(gpio, c, 1);
Graf Yang9570ff42009-01-07 23:14:38 +08001214 if (!check_gpio(c) && (gpio || irq))
1215 len = sprintf(buf, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c,
1216 get_label(c), (gpio && irq) ? " *" : "",
1217 get_gpio_dir(c) ? "OUTPUT" : "INPUT");
Mike Frysinger332824b2010-06-02 04:22:01 +00001218 else if (is_reserved(peri, c, 1))
Graf Yang8eb3e3b2008-11-18 17:48:22 +08001219 len = sprintf(buf, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c));
Mike Frysinger1545a112007-12-24 16:54:48 +08001220 else
1221 continue;
1222 buf += len;
1223 outlen += len;
1224 }
1225 return outlen;
1226}
1227
1228static __init int gpio_register_proc(void)
1229{
1230 struct proc_dir_entry *proc_gpio;
1231
1232 proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL);
1233 if (proc_gpio)
1234 proc_gpio->read_proc = gpio_proc_read;
1235 return proc_gpio != NULL;
1236}
Mike Frysinger1545a112007-12-24 16:54:48 +08001237__initcall(gpio_register_proc);
1238#endif
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001239
1240#ifdef CONFIG_GPIOLIB
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001241static int bfin_gpiolib_direction_input(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001242{
1243 return bfin_gpio_direction_input(gpio);
1244}
1245
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001246static int bfin_gpiolib_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001247{
1248 return bfin_gpio_direction_output(gpio, level);
1249}
1250
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001251static int bfin_gpiolib_get_value(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001252{
1253 return bfin_gpio_get_value(gpio);
1254}
1255
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001256static void bfin_gpiolib_set_value(struct gpio_chip *chip, unsigned gpio, int value)
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001257{
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001258 return bfin_gpio_set_value(gpio, value);
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001259}
1260
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001261static int bfin_gpiolib_gpio_request(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001262{
1263 return bfin_gpio_request(gpio, chip->label);
1264}
1265
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001266static void bfin_gpiolib_gpio_free(struct gpio_chip *chip, unsigned gpio)
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001267{
1268 return bfin_gpio_free(gpio);
1269}
1270
Joachim Eastwoodf9c29e82010-02-11 12:41:11 +01001271static int bfin_gpiolib_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
Joachim Eastwood7f4f69f2010-02-10 12:31:41 +01001272{
1273 return gpio + GPIO_IRQ_BASE;
1274}
1275
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001276static struct gpio_chip bfin_chip = {
Michael Hennerichedd07992009-12-16 08:45:17 +00001277 .label = "BFIN-GPIO",
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001278 .direction_input = bfin_gpiolib_direction_input,
1279 .get = bfin_gpiolib_get_value,
1280 .direction_output = bfin_gpiolib_direction_output,
1281 .set = bfin_gpiolib_set_value,
1282 .request = bfin_gpiolib_gpio_request,
1283 .free = bfin_gpiolib_gpio_free,
Joachim Eastwood7f4f69f2010-02-10 12:31:41 +01001284 .to_irq = bfin_gpiolib_gpio_to_irq,
Michael Hennericha4f0b32c2008-11-18 17:48:22 +08001285 .base = 0,
1286 .ngpio = MAX_BLACKFIN_GPIOS,
1287};
1288
1289static int __init bfin_gpiolib_setup(void)
1290{
1291 return gpiochip_add(&bfin_chip);
1292}
1293arch_initcall(bfin_gpiolib_setup);
1294#endif