blob: c4161e03df78523e282cf9793fbaabc1679cffe9 [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 *
Robin Getz96f10502009-09-24 14:11:24 +00004 * Copyright 2006-2009 Analog Devices Inc.
Bryan Wu1394f032007-05-06 14:50:22 -07005 *
Robin Getz96f10502009-09-24 14:11:24 +00006 * Licensed under the GPL-2 or later
Bryan Wu1394f032007-05-06 14:50:22 -07007 */
8
Mike Frysinger168f1212007-10-11 00:22:35 +08009#include <linux/delay.h>
Bryan Wu1394f032007-05-06 14:50:22 -070010#include <linux/module.h>
11#include <linux/err.h>
Mike Frysinger1545a112007-12-24 16:54:48 +080012#include <linux/proc_fs.h>
Bryan Wu1394f032007-05-06 14:50:22 -070013#include <asm/blackfin.h>
14#include <asm/gpio.h>
Michael Hennerichc58c2142007-10-04 00:35:05 +080015#include <asm/portmux.h>
Bryan Wu1394f032007-05-06 14:50:22 -070016#include <linux/irq.h>
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 Hennerichd2b11a42007-08-28 16:47:46 +0800103#endif
104
Bryan Wu397861c2008-11-18 17:48:22 +0800105static unsigned short reserved_gpio_map[GPIO_BANK_NUM];
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800106static unsigned short reserved_peri_map[gpio_bank(MAX_RESOURCES)];
Graf Yang9570ff42009-01-07 23:14:38 +0800107static unsigned short reserved_gpio_irq_map[GPIO_BANK_NUM];
Michael Hennerichc58c2142007-10-04 00:35:05 +0800108
Michael Hennerich8c613622007-08-03 17:48:09 +0800109#define RESOURCE_LABEL_SIZE 16
110
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800111static struct str_ident {
Michael Hennerich8c613622007-08-03 17:48:09 +0800112 char name[RESOURCE_LABEL_SIZE];
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800113} str_ident[MAX_RESOURCES];
Bryan Wu1394f032007-05-06 14:50:22 -0700114
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800115#if defined(CONFIG_PM)
Bryan Wu397861c2008-11-18 17:48:22 +0800116static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM];
Bryan Wu1394f032007-05-06 14:50:22 -0700117#endif
118
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800119inline int check_gpio(unsigned gpio)
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800120{
Mike Frysinger269647d2009-03-28 20:32:57 +0800121#if defined(CONFIG_BF54x)
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800122 if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
123 || gpio == GPIO_PH14 || gpio == GPIO_PH15
Mike Frysinger27228b22008-10-28 15:45:42 +0800124 || gpio == GPIO_PJ14 || gpio == GPIO_PJ15)
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800125 return -EINVAL;
Mike Frysinger27228b22008-10-28 15:45:42 +0800126#endif
Michael Henneriche7613aa2007-06-11 16:37:57 +0800127 if (gpio >= MAX_BLACKFIN_GPIOS)
Bryan Wu1394f032007-05-06 14:50:22 -0700128 return -EINVAL;
129 return 0;
130}
131
Mike Frysinger74c04502008-10-08 16:13:17 +0800132static void gpio_error(unsigned gpio)
Michael Hennerichacbcd262008-01-22 18:36:20 +0800133{
134 printk(KERN_ERR "bfin-gpio: GPIO %d wasn't requested!\n", gpio);
135}
136
Michael Hennerichc58c2142007-10-04 00:35:05 +0800137static void set_label(unsigned short ident, const char *label)
138{
Michael Henneriche9fae182008-10-13 11:35:22 +0800139 if (label) {
Michael Hennerich8c613622007-08-03 17:48:09 +0800140 strncpy(str_ident[ident].name, label,
Michael Hennerichc58c2142007-10-04 00:35:05 +0800141 RESOURCE_LABEL_SIZE);
Michael Hennerich8c613622007-08-03 17:48:09 +0800142 str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800143 }
144}
145
146static char *get_label(unsigned short ident)
147{
Michael Hennerich8c613622007-08-03 17:48:09 +0800148 return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN");
Michael Hennerichc58c2142007-10-04 00:35:05 +0800149}
150
151static int cmp_label(unsigned short ident, const char *label)
152{
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800153 if (label == NULL) {
154 dump_stack();
155 printk(KERN_ERR "Please provide none-null label\n");
156 }
157
Michael Henneriche9fae182008-10-13 11:35:22 +0800158 if (label)
Mike Frysinger1f7d3732008-10-28 15:47:11 +0800159 return strcmp(str_ident[ident].name, label);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800160 else
161 return -EINVAL;
162}
163
Mike Frysingera2d03a12008-10-28 15:53:37 +0800164static void port_setup(unsigned gpio, unsigned short usage)
165{
166 if (check_gpio(gpio))
167 return;
168
Mike Frysinger269647d2009-03-28 20:32:57 +0800169#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Mike Frysingera2d03a12008-10-28 15:53:37 +0800170 if (usage == GPIO_USAGE)
171 *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
172 else
173 *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
174 SSYNC();
Mike Frysinger269647d2009-03-28 20:32:57 +0800175#elif defined(CONFIG_BF54x)
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800176 if (usage == GPIO_USAGE)
177 gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
178 else
179 gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
180 SSYNC();
Bryan Wu1394f032007-05-06 14:50:22 -0700181#endif
Mike Frysingera2d03a12008-10-28 15:53:37 +0800182}
Bryan Wu1394f032007-05-06 14:50:22 -0700183
Michael Hennerichc58c2142007-10-04 00:35:05 +0800184#ifdef BF537_FAMILY
Michael Hennerich8c613622007-08-03 17:48:09 +0800185static struct {
186 unsigned short res;
187 unsigned short offset;
188} port_mux_lut[] = {
189 {.res = P_PPI0_D13, .offset = 11},
190 {.res = P_PPI0_D14, .offset = 11},
191 {.res = P_PPI0_D15, .offset = 11},
192 {.res = P_SPORT1_TFS, .offset = 11},
193 {.res = P_SPORT1_TSCLK, .offset = 11},
194 {.res = P_SPORT1_DTPRI, .offset = 11},
195 {.res = P_PPI0_D10, .offset = 10},
196 {.res = P_PPI0_D11, .offset = 10},
197 {.res = P_PPI0_D12, .offset = 10},
198 {.res = P_SPORT1_RSCLK, .offset = 10},
199 {.res = P_SPORT1_RFS, .offset = 10},
200 {.res = P_SPORT1_DRPRI, .offset = 10},
201 {.res = P_PPI0_D8, .offset = 9},
202 {.res = P_PPI0_D9, .offset = 9},
203 {.res = P_SPORT1_DRSEC, .offset = 9},
204 {.res = P_SPORT1_DTSEC, .offset = 9},
205 {.res = P_TMR2, .offset = 8},
206 {.res = P_PPI0_FS3, .offset = 8},
207 {.res = P_TMR3, .offset = 7},
208 {.res = P_SPI0_SSEL4, .offset = 7},
209 {.res = P_TMR4, .offset = 6},
210 {.res = P_SPI0_SSEL5, .offset = 6},
211 {.res = P_TMR5, .offset = 5},
212 {.res = P_SPI0_SSEL6, .offset = 5},
213 {.res = P_UART1_RX, .offset = 4},
214 {.res = P_UART1_TX, .offset = 4},
215 {.res = P_TMR6, .offset = 4},
216 {.res = P_TMR7, .offset = 4},
217 {.res = P_UART0_RX, .offset = 3},
218 {.res = P_UART0_TX, .offset = 3},
219 {.res = P_DMAR0, .offset = 3},
220 {.res = P_DMAR1, .offset = 3},
221 {.res = P_SPORT0_DTSEC, .offset = 1},
222 {.res = P_SPORT0_DRSEC, .offset = 1},
223 {.res = P_CAN0_RX, .offset = 1},
224 {.res = P_CAN0_TX, .offset = 1},
225 {.res = P_SPI0_SSEL7, .offset = 1},
226 {.res = P_SPORT0_TFS, .offset = 0},
227 {.res = P_SPORT0_DTPRI, .offset = 0},
228 {.res = P_SPI0_SSEL2, .offset = 0},
229 {.res = P_SPI0_SSEL3, .offset = 0},
Michael Hennerichc58c2142007-10-04 00:35:05 +0800230};
231
Mike Frysingerf5563092009-02-04 16:49:45 +0800232static void portmux_setup(unsigned short per)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800233{
Michael Hennerich8c613622007-08-03 17:48:09 +0800234 u16 y, offset, muxreg;
Mike Frysingerf5563092009-02-04 16:49:45 +0800235 u16 function = P_FUNCT2MUX(per);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800236
Michael Hennerich8c613622007-08-03 17:48:09 +0800237 for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) {
238 if (port_mux_lut[y].res == per) {
Michael Hennerichc58c2142007-10-04 00:35:05 +0800239
240 /* SET PORTMUX REG */
241
Michael Hennerich8c613622007-08-03 17:48:09 +0800242 offset = port_mux_lut[y].offset;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800243 muxreg = bfin_read_PORT_MUX();
244
Mike Frysingerd171c232008-03-26 08:35:46 +0800245 if (offset != 1)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800246 muxreg &= ~(1 << offset);
Mike Frysingerd171c232008-03-26 08:35:46 +0800247 else
Michael Hennerichc58c2142007-10-04 00:35:05 +0800248 muxreg &= ~(3 << 1);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800249
250 muxreg |= (function << offset);
251 bfin_write_PORT_MUX(muxreg);
252 }
253 }
254}
Mike Frysinger269647d2009-03-28 20:32:57 +0800255#elif defined(CONFIG_BF54x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800256inline void portmux_setup(unsigned short per)
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800257{
258 u32 pmux;
Mike Frysingerf5563092009-02-04 16:49:45 +0800259 u16 ident = P_IDENT(per);
260 u16 function = P_FUNCT2MUX(per);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800261
Mike Frysingerf5563092009-02-04 16:49:45 +0800262 pmux = gpio_array[gpio_bank(ident)]->port_mux;
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800263
Mike Frysingerf5563092009-02-04 16:49:45 +0800264 pmux &= ~(0x3 << (2 * gpio_sub_n(ident)));
265 pmux |= (function & 0x3) << (2 * gpio_sub_n(ident));
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800266
Mike Frysingerf5563092009-02-04 16:49:45 +0800267 gpio_array[gpio_bank(ident)]->port_mux = pmux;
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800268}
269
Mike Frysingerf5563092009-02-04 16:49:45 +0800270inline u16 get_portmux(unsigned short per)
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800271{
272 u32 pmux;
Mike Frysingerf5563092009-02-04 16:49:45 +0800273 u16 ident = P_IDENT(per);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800274
Mike Frysingerf5563092009-02-04 16:49:45 +0800275 pmux = gpio_array[gpio_bank(ident)]->port_mux;
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800276
Mike Frysingerf5563092009-02-04 16:49:45 +0800277 return (pmux >> (2 * gpio_sub_n(ident)) & 0x3);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800278}
Mike Frysinger269647d2009-03-28 20:32:57 +0800279#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800280inline void portmux_setup(unsigned short per)
Michael Hennerich59003142007-10-21 16:54:27 +0800281{
Mike Frysingerf5563092009-02-04 16:49:45 +0800282 u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per);
Michael Hennerich59003142007-10-21 16:54:27 +0800283 u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
284
285 pmux = *port_mux[gpio_bank(ident)];
286 pmux &= ~(3 << offset);
287 pmux |= (function & 3) << offset;
288 *port_mux[gpio_bank(ident)] = pmux;
289 SSYNC();
290}
Michael Hennerichc58c2142007-10-04 00:35:05 +0800291#else
292# define portmux_setup(...) do { } while (0)
293#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700294
Mike Frysinger269647d2009-03-28 20:32:57 +0800295#ifndef CONFIG_BF54x
Bryan Wu1394f032007-05-06 14:50:22 -0700296/***********************************************************
297*
298* FUNCTIONS: Blackfin General Purpose Ports Access Functions
299*
300* INPUTS/OUTPUTS:
301* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
302*
303*
304* DESCRIPTION: These functions abstract direct register access
305* to Blackfin processor General Purpose
306* Ports Regsiters
307*
308* CAUTION: These functions do not belong to the GPIO Driver API
309*************************************************************
310* MODIFICATION HISTORY :
311**************************************************************/
312
313/* Set a specific bit */
314
315#define SET_GPIO(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800316void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
Bryan Wu1394f032007-05-06 14:50:22 -0700317{ \
318 unsigned long flags; \
Yi Li6a01f232009-01-07 23:14:39 +0800319 local_irq_save_hw(flags); \
Bryan Wu1394f032007-05-06 14:50:22 -0700320 if (arg) \
Mike Frysingerf5563092009-02-04 16:49:45 +0800321 gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
Bryan Wu1394f032007-05-06 14:50:22 -0700322 else \
Mike Frysingerf5563092009-02-04 16:49:45 +0800323 gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
Michael Hennerich2b393312007-10-10 16:58:49 +0800324 AWA_DUMMY_READ(name); \
Yi Li6a01f232009-01-07 23:14:39 +0800325 local_irq_restore_hw(flags); \
Bryan Wu1394f032007-05-06 14:50:22 -0700326} \
327EXPORT_SYMBOL(set_gpio_ ## name);
328
Mike Frysingerf5563092009-02-04 16:49:45 +0800329SET_GPIO(dir) /* set_gpio_dir() */
330SET_GPIO(inen) /* set_gpio_inen() */
331SET_GPIO(polar) /* set_gpio_polar() */
332SET_GPIO(edge) /* set_gpio_edge() */
333SET_GPIO(both) /* set_gpio_both() */
Bryan Wu1394f032007-05-06 14:50:22 -0700334
335
Michael Hennerich2b393312007-10-10 16:58:49 +0800336#define SET_GPIO_SC(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800337void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800338{ \
339 unsigned long flags; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800340 if (ANOMALY_05000311 || ANOMALY_05000323) \
341 local_irq_save_hw(flags); \
Michael Hennerich2b393312007-10-10 16:58:49 +0800342 if (arg) \
Mike Frysingerf5563092009-02-04 16:49:45 +0800343 gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
Michael Hennerich2b393312007-10-10 16:58:49 +0800344 else \
Mike Frysingerf5563092009-02-04 16:49:45 +0800345 gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
346 if (ANOMALY_05000311 || ANOMALY_05000323) { \
347 AWA_DUMMY_READ(name); \
348 local_irq_restore_hw(flags); \
349 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800350} \
351EXPORT_SYMBOL(set_gpio_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700352
353SET_GPIO_SC(maska)
354SET_GPIO_SC(maskb)
Bryan Wu1394f032007-05-06 14:50:22 -0700355SET_GPIO_SC(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700356
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800357void set_gpio_toggle(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -0700358{
359 unsigned long flags;
Mike Frysingerf5563092009-02-04 16:49:45 +0800360 if (ANOMALY_05000311 || ANOMALY_05000323)
361 local_irq_save_hw(flags);
362 gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
363 if (ANOMALY_05000311 || ANOMALY_05000323) {
364 AWA_DUMMY_READ(toggle);
365 local_irq_restore_hw(flags);
366 }
Bryan Wu1394f032007-05-06 14:50:22 -0700367}
Bryan Wu1394f032007-05-06 14:50:22 -0700368EXPORT_SYMBOL(set_gpio_toggle);
369
370
371/*Set current PORT date (16-bit word)*/
372
Michael Hennerich2b393312007-10-10 16:58:49 +0800373#define SET_GPIO_P(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800374void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800375{ \
376 unsigned long flags; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800377 if (ANOMALY_05000311 || ANOMALY_05000323) \
378 local_irq_save_hw(flags); \
379 gpio_array[gpio_bank(gpio)]->name = arg; \
380 if (ANOMALY_05000311 || ANOMALY_05000323) { \
381 AWA_DUMMY_READ(name); \
382 local_irq_restore_hw(flags); \
383 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800384} \
385EXPORT_SYMBOL(set_gpiop_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700386
Michael Hennerich2b393312007-10-10 16:58:49 +0800387SET_GPIO_P(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700388SET_GPIO_P(dir)
389SET_GPIO_P(inen)
390SET_GPIO_P(polar)
391SET_GPIO_P(edge)
392SET_GPIO_P(both)
393SET_GPIO_P(maska)
394SET_GPIO_P(maskb)
395
Bryan Wu1394f032007-05-06 14:50:22 -0700396/* Get a specific bit */
Michael Hennerich2b393312007-10-10 16:58:49 +0800397#define GET_GPIO(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800398unsigned short get_gpio_ ## name(unsigned gpio) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800399{ \
400 unsigned long flags; \
401 unsigned short ret; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800402 if (ANOMALY_05000311 || ANOMALY_05000323) \
403 local_irq_save_hw(flags); \
404 ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \
405 if (ANOMALY_05000311 || ANOMALY_05000323) { \
406 AWA_DUMMY_READ(name); \
407 local_irq_restore_hw(flags); \
408 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800409 return ret; \
410} \
411EXPORT_SYMBOL(get_gpio_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700412
Michael Hennerich2b393312007-10-10 16:58:49 +0800413GET_GPIO(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700414GET_GPIO(dir)
415GET_GPIO(inen)
416GET_GPIO(polar)
417GET_GPIO(edge)
418GET_GPIO(both)
419GET_GPIO(maska)
420GET_GPIO(maskb)
421
Bryan Wu1394f032007-05-06 14:50:22 -0700422/*Get current PORT date (16-bit word)*/
423
Michael Hennerich2b393312007-10-10 16:58:49 +0800424#define GET_GPIO_P(name) \
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800425unsigned short get_gpiop_ ## name(unsigned gpio) \
Michael Hennerich2b393312007-10-10 16:58:49 +0800426{ \
427 unsigned long flags; \
428 unsigned short ret; \
Mike Frysingerf5563092009-02-04 16:49:45 +0800429 if (ANOMALY_05000311 || ANOMALY_05000323) \
430 local_irq_save_hw(flags); \
431 ret = (gpio_array[gpio_bank(gpio)]->name); \
432 if (ANOMALY_05000311 || ANOMALY_05000323) { \
433 AWA_DUMMY_READ(name); \
434 local_irq_restore_hw(flags); \
435 } \
Michael Hennerich2b393312007-10-10 16:58:49 +0800436 return ret; \
437} \
438EXPORT_SYMBOL(get_gpiop_ ## name);
Bryan Wu1394f032007-05-06 14:50:22 -0700439
Michael Hennerich2b393312007-10-10 16:58:49 +0800440GET_GPIO_P(data)
Bryan Wu1394f032007-05-06 14:50:22 -0700441GET_GPIO_P(dir)
442GET_GPIO_P(inen)
443GET_GPIO_P(polar)
444GET_GPIO_P(edge)
445GET_GPIO_P(both)
446GET_GPIO_P(maska)
447GET_GPIO_P(maskb)
448
Bryan Wu1394f032007-05-06 14:50:22 -0700449
450#ifdef CONFIG_PM
Mike Frysingerf5563092009-02-04 16:49:45 +0800451
452static unsigned short wakeup_map[GPIO_BANK_NUM];
453static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS];
454
455static const unsigned int sic_iwr_irqs[] = {
456#if defined(BF533_FAMILY)
457 IRQ_PROG_INTB
458#elif defined(BF537_FAMILY)
459 IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX
460#elif defined(BF538_FAMILY)
461 IRQ_PORTF_INTB
Mike Frysinger269647d2009-03-28 20:32:57 +0800462#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800463 IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB
464#elif defined(BF561_FAMILY)
465 IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB
466#else
467# error no SIC_IWR defined
468#endif
469};
470
Bryan Wu1394f032007-05-06 14:50:22 -0700471/***********************************************************
472*
473* FUNCTIONS: Blackfin PM Setup API
474*
475* INPUTS/OUTPUTS:
476* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
477* type -
478* PM_WAKE_RISING
479* PM_WAKE_FALLING
480* PM_WAKE_HIGH
481* PM_WAKE_LOW
482* PM_WAKE_BOTH_EDGES
483*
484* DESCRIPTION: Blackfin PM Driver API
485*
486* CAUTION:
487*************************************************************
488* MODIFICATION HISTORY :
489**************************************************************/
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800490int gpio_pm_wakeup_request(unsigned gpio, unsigned char type)
Bryan Wu1394f032007-05-06 14:50:22 -0700491{
492 unsigned long flags;
493
494 if ((check_gpio(gpio) < 0) || !type)
495 return -EINVAL;
496
Yi Li6a01f232009-01-07 23:14:39 +0800497 local_irq_save_hw(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700498 wakeup_map[gpio_bank(gpio)] |= gpio_bit(gpio);
499 wakeup_flags_map[gpio] = type;
Yi Li6a01f232009-01-07 23:14:39 +0800500 local_irq_restore_hw(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700501
502 return 0;
503}
504EXPORT_SYMBOL(gpio_pm_wakeup_request);
505
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800506void gpio_pm_wakeup_free(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -0700507{
508 unsigned long flags;
509
510 if (check_gpio(gpio) < 0)
511 return;
512
Yi Li6a01f232009-01-07 23:14:39 +0800513 local_irq_save_hw(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700514
515 wakeup_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
516
Yi Li6a01f232009-01-07 23:14:39 +0800517 local_irq_restore_hw(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700518}
519EXPORT_SYMBOL(gpio_pm_wakeup_free);
520
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800521static int bfin_gpio_wakeup_type(unsigned gpio, unsigned char type)
Bryan Wu1394f032007-05-06 14:50:22 -0700522{
523 port_setup(gpio, GPIO_USAGE);
524 set_gpio_dir(gpio, 0);
525 set_gpio_inen(gpio, 1);
526
527 if (type & (PM_WAKE_RISING | PM_WAKE_FALLING))
528 set_gpio_edge(gpio, 1);
529 else
530 set_gpio_edge(gpio, 0);
531
532 if ((type & (PM_WAKE_BOTH_EDGES)) == (PM_WAKE_BOTH_EDGES))
533 set_gpio_both(gpio, 1);
534 else
535 set_gpio_both(gpio, 0);
536
537 if ((type & (PM_WAKE_FALLING | PM_WAKE_LOW)))
538 set_gpio_polar(gpio, 1);
539 else
540 set_gpio_polar(gpio, 0);
541
542 SSYNC();
543
544 return 0;
545}
546
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800547u32 bfin_pm_standby_setup(void)
Bryan Wu1394f032007-05-06 14:50:22 -0700548{
Bryan Wu1394f032007-05-06 14:50:22 -0700549 u16 bank, mask, i, gpio;
550
Mike Frysinger1f83b8f2007-07-12 22:58:21 +0800551 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Bryan Wu1394f032007-05-06 14:50:22 -0700552 mask = wakeup_map[gpio_bank(i)];
553 bank = gpio_bank(i);
554
Mike Frysingerf5563092009-02-04 16:49:45 +0800555 gpio_bank_saved[bank].maskb = gpio_array[bank]->maskb;
556 gpio_array[bank]->maskb = 0;
Bryan Wu1394f032007-05-06 14:50:22 -0700557
558 if (mask) {
Mike Frysinger269647d2009-03-28 20:32:57 +0800559#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Bryan Wu1394f032007-05-06 14:50:22 -0700560 gpio_bank_saved[bank].fer = *port_fer[bank];
561#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800562 gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
563 gpio_bank_saved[bank].polar = gpio_array[bank]->polar;
564 gpio_bank_saved[bank].dir = gpio_array[bank]->dir;
565 gpio_bank_saved[bank].edge = gpio_array[bank]->edge;
566 gpio_bank_saved[bank].both = gpio_array[bank]->both;
Michael Hennerichc58c2142007-10-04 00:35:05 +0800567 gpio_bank_saved[bank].reserved =
568 reserved_gpio_map[bank];
Bryan Wu1394f032007-05-06 14:50:22 -0700569
570 gpio = i;
571
572 while (mask) {
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800573 if ((mask & 1) && (wakeup_flags_map[gpio] !=
574 PM_WAKE_IGNORE)) {
Michael Hennerichc58c2142007-10-04 00:35:05 +0800575 reserved_gpio_map[gpio_bank(gpio)] |=
Michael Hennerich581d62a2007-06-14 13:30:23 +0800576 gpio_bit(gpio);
577 bfin_gpio_wakeup_type(gpio,
578 wakeup_flags_map[gpio]);
Bryan Wu1394f032007-05-06 14:50:22 -0700579 set_gpio_data(gpio, 0); /*Clear*/
580 }
581 gpio++;
582 mask >>= 1;
583 }
584
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800585 bfin_internal_set_wake(sic_iwr_irqs[bank], 1);
Mike Frysingerf5563092009-02-04 16:49:45 +0800586 gpio_array[bank]->maskb_set = wakeup_map[gpio_bank(i)];
Bryan Wu1394f032007-05-06 14:50:22 -0700587 }
588 }
589
Michael Hennerich2b393312007-10-10 16:58:49 +0800590 AWA_DUMMY_READ(maskb_set);
591
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800592 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -0700593}
594
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800595void bfin_pm_standby_restore(void)
Bryan Wu1394f032007-05-06 14:50:22 -0700596{
597 u16 bank, mask, i;
598
Mike Frysinger1f83b8f2007-07-12 22:58:21 +0800599 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Bryan Wu1394f032007-05-06 14:50:22 -0700600 mask = wakeup_map[gpio_bank(i)];
601 bank = gpio_bank(i);
602
603 if (mask) {
Mike Frysinger269647d2009-03-28 20:32:57 +0800604#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Bryan Wu1394f032007-05-06 14:50:22 -0700605 *port_fer[bank] = gpio_bank_saved[bank].fer;
606#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800607 gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
608 gpio_array[bank]->dir = gpio_bank_saved[bank].dir;
609 gpio_array[bank]->polar = gpio_bank_saved[bank].polar;
610 gpio_array[bank]->edge = gpio_bank_saved[bank].edge;
611 gpio_array[bank]->both = gpio_bank_saved[bank].both;
Michael Hennerich581d62a2007-06-14 13:30:23 +0800612
Michael Hennerichc58c2142007-10-04 00:35:05 +0800613 reserved_gpio_map[bank] =
614 gpio_bank_saved[bank].reserved;
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800615 bfin_internal_set_wake(sic_iwr_irqs[bank], 0);
Bryan Wu1394f032007-05-06 14:50:22 -0700616 }
617
Mike Frysingerf5563092009-02-04 16:49:45 +0800618 gpio_array[bank]->maskb = gpio_bank_saved[bank].maskb;
Bryan Wu1394f032007-05-06 14:50:22 -0700619 }
Michael Hennerich2b393312007-10-10 16:58:49 +0800620 AWA_DUMMY_READ(maskb);
Bryan Wu1394f032007-05-06 14:50:22 -0700621}
622
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800623void bfin_gpio_pm_hibernate_suspend(void)
624{
625 int i, bank;
626
627 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
628 bank = gpio_bank(i);
629
Mike Frysinger269647d2009-03-28 20:32:57 +0800630#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800631 gpio_bank_saved[bank].fer = *port_fer[bank];
Mike Frysinger269647d2009-03-28 20:32:57 +0800632#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800633 gpio_bank_saved[bank].mux = *port_mux[bank];
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800634#else
Mike Frysingerf5563092009-02-04 16:49:45 +0800635 if (bank == 0)
636 gpio_bank_saved[bank].mux = bfin_read_PORT_MUX();
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800637#endif
638#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800639 gpio_bank_saved[bank].data = gpio_array[bank]->data;
640 gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
641 gpio_bank_saved[bank].polar = gpio_array[bank]->polar;
642 gpio_bank_saved[bank].dir = gpio_array[bank]->dir;
643 gpio_bank_saved[bank].edge = gpio_array[bank]->edge;
644 gpio_bank_saved[bank].both = gpio_array[bank]->both;
645 gpio_bank_saved[bank].maska = gpio_array[bank]->maska;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800646 }
647
648 AWA_DUMMY_READ(maska);
649}
650
651void bfin_gpio_pm_hibernate_restore(void)
652{
653 int i, bank;
654
655 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Mike Frysingerf5563092009-02-04 16:49:45 +0800656 bank = gpio_bank(i);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800657
Mike Frysinger269647d2009-03-28 20:32:57 +0800658#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
659#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
Mike Frysingerf5563092009-02-04 16:49:45 +0800660 *port_mux[bank] = gpio_bank_saved[bank].mux;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800661#else
Mike Frysingerf5563092009-02-04 16:49:45 +0800662 if (bank == 0)
663 bfin_write_PORT_MUX(gpio_bank_saved[bank].mux);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800664#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800665 *port_fer[bank] = gpio_bank_saved[bank].fer;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800666#endif
Mike Frysingerf5563092009-02-04 16:49:45 +0800667 gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
Michael Hennerichc03c2a82009-07-08 12:04:43 +0000668 gpio_array[bank]->data_set = gpio_bank_saved[bank].data
669 & gpio_bank_saved[bank].dir;
Mike Frysingerf5563092009-02-04 16:49:45 +0800670 gpio_array[bank]->dir = gpio_bank_saved[bank].dir;
671 gpio_array[bank]->polar = gpio_bank_saved[bank].polar;
672 gpio_array[bank]->edge = gpio_bank_saved[bank].edge;
673 gpio_array[bank]->both = gpio_bank_saved[bank].both;
Mike Frysingerf5563092009-02-04 16:49:45 +0800674 gpio_array[bank]->maska = gpio_bank_saved[bank].maska;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800675 }
676 AWA_DUMMY_READ(maska);
677}
678
679
Bryan Wu1394f032007-05-06 14:50:22 -0700680#endif
Mike Frysinger269647d2009-03-28 20:32:57 +0800681#else /* CONFIG_BF54x */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800682#ifdef CONFIG_PM
683
684u32 bfin_pm_standby_setup(void)
685{
686 return 0;
687}
688
689void bfin_pm_standby_restore(void)
690{
691
692}
693
694void bfin_gpio_pm_hibernate_suspend(void)
695{
696 int i, bank;
697
698 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
699 bank = gpio_bank(i);
700
Mike Frysingerf5563092009-02-04 16:49:45 +0800701 gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer;
702 gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux;
703 gpio_bank_saved[bank].data = gpio_array[bank]->data;
Mike Frysingerf5563092009-02-04 16:49:45 +0800704 gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
705 gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800706 }
707}
708
709void bfin_gpio_pm_hibernate_restore(void)
710{
711 int i, bank;
712
713 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
Mike Frysingerf5563092009-02-04 16:49:45 +0800714 bank = gpio_bank(i);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800715
Mike Frysingerf5563092009-02-04 16:49:45 +0800716 gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux;
717 gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer;
718 gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
719 gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir;
720 gpio_array[bank]->data_set = gpio_bank_saved[bank].data
721 | gpio_bank_saved[bank].dir;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800722 }
723}
724#endif
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800725
Michael Hennericha2c8cfe2008-01-22 17:20:10 +0800726unsigned short get_gpio_dir(unsigned gpio)
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800727{
Mike Frysingerf5563092009-02-04 16:49:45 +0800728 return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio)));
Michael Hennerichfac3cf42007-12-24 20:07:03 +0800729}
730EXPORT_SYMBOL(get_gpio_dir);
731
Mike Frysinger269647d2009-03-28 20:32:57 +0800732#endif /* CONFIG_BF54x */
Bryan Wu1394f032007-05-06 14:50:22 -0700733
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800734/***********************************************************
735*
736* FUNCTIONS: Blackfin Peripheral Resource Allocation
737* and PortMux Setup
738*
739* INPUTS/OUTPUTS:
740* per Peripheral Identifier
741* label String
742*
743* DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API
744*
745* CAUTION:
746*************************************************************
747* MODIFICATION HISTORY :
748**************************************************************/
Michael Hennerichc58c2142007-10-04 00:35:05 +0800749
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800750int peripheral_request(unsigned short per, const char *label)
751{
752 unsigned long flags;
753 unsigned short ident = P_IDENT(per);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800754
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800755 /*
756 * Don't cares are pins with only one dedicated function
757 */
758
759 if (per & P_DONTCARE)
760 return 0;
761
762 if (!(per & P_DEFINED))
763 return -ENODEV;
764
Barry Song89e84ee2009-09-16 04:36:29 +0000765 BUG_ON(ident >= MAX_RESOURCES);
766
Yi Li6a01f232009-01-07 23:14:39 +0800767 local_irq_save_hw(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800768
Mike Frysinger6a87d292008-10-28 16:16:29 +0800769 /* If a pin can be muxed as either GPIO or peripheral, make
770 * sure it is not already a GPIO pin when we request it.
771 */
772 if (unlikely(!check_gpio(ident) &&
773 reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800774 if (system_state == SYSTEM_BOOTING)
775 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800776 printk(KERN_ERR
Mike Frysinger6c7ec0e2008-10-28 15:49:59 +0800777 "%s: Peripheral %d is already reserved as GPIO by %s !\n",
Harvey Harrisonb85d8582008-04-23 09:39:01 +0800778 __func__, ident, get_label(ident));
Yi Li6a01f232009-01-07 23:14:39 +0800779 local_irq_restore_hw(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800780 return -EBUSY;
781 }
782
783 if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
784
Mike Frysingerd171c232008-03-26 08:35:46 +0800785 /*
786 * Pin functions like AMC address strobes my
787 * be requested and used by several drivers
788 */
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800789
Mike Frysinger269647d2009-03-28 20:32:57 +0800790#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +0800791 if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) {
Mike Frysinger6c7ec0e2008-10-28 15:49:59 +0800792#else
793 if (!(per & P_MAYSHARE)) {
794#endif
Mike Frysingerd171c232008-03-26 08:35:46 +0800795 /*
796 * Allow that the identical pin function can
797 * be requested from the same driver twice
798 */
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800799
Mike Frysingerd171c232008-03-26 08:35:46 +0800800 if (cmp_label(ident, label) == 0)
801 goto anyway;
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800802
Robin Getzd6879c52009-03-29 01:10:30 +0800803 if (system_state == SYSTEM_BOOTING)
804 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800805 printk(KERN_ERR
806 "%s: Peripheral %d function %d is already reserved by %s !\n",
Harvey Harrisonb85d8582008-04-23 09:39:01 +0800807 __func__, ident, P_FUNCT2MUX(per), get_label(ident));
Yi Li6a01f232009-01-07 23:14:39 +0800808 local_irq_restore_hw(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800809 return -EBUSY;
810 }
811 }
812
Mike Frysingerd171c232008-03-26 08:35:46 +0800813 anyway:
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800814 reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
815
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
Yi Li6a01f232009-01-07 23:14:39 +0800819 local_irq_restore_hw(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
Yi Li6a01f232009-01-07 23:14:39 +0800858 local_irq_save_hw(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800859
Mike Frysingerd171c232008-03-26 08:35:46 +0800860 if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) {
Yi Li6a01f232009-01-07 23:14:39 +0800861 local_irq_restore_hw(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
868 reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident);
869
Michael Hennerich2acde902007-10-11 00:24:40 +0800870 set_label(ident, "free");
871
Yi Li6a01f232009-01-07 23:14:39 +0800872 local_irq_restore_hw(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
Yi Li6a01f232009-01-07 23:14:39 +0800906 local_irq_save_hw(flags);
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) {
Yi Li6a01f232009-01-07 23:14:39 +0800915 local_irq_restore_hw(flags);
Michael Hennerich2acde902007-10-11 00:24:40 +0800916 return 0;
917 }
918
Michael Hennerichc58c2142007-10-04 00:35:05 +0800919 if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
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));
Yi Li6a01f232009-01-07 23:14:39 +0800924 local_irq_restore_hw(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700925 return -EBUSY;
926 }
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800927 if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
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));
Yi Li6a01f232009-01-07 23:14:39 +0800933 local_irq_restore_hw(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800934 return -EBUSY;
935 }
Michael Hennericha2be3932009-02-04 16:49:45 +0800936 if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
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
Michael Hennerichc58c2142007-10-04 00:35:05 +0800946 reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
Graf Yang9570ff42009-01-07 23:14:38 +0800947 set_label(gpio, label);
Bryan Wu1394f032007-05-06 14:50:22 -0700948
Yi Li6a01f232009-01-07 23:14:39 +0800949 local_irq_restore_hw(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
Yi Li6a01f232009-01-07 23:14:39 +0800966 local_irq_save_hw(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700967
Michael Hennerichc58c2142007-10-04 00:35:05 +0800968 if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
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);
Yi Li6a01f232009-01-07 23:14:39 +0800972 local_irq_restore_hw(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700973 return;
974 }
975
Michael Hennerichc58c2142007-10-04 00:35:05 +0800976 reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
Bryan Wu1394f032007-05-06 14:50:22 -0700977
Michael Hennerich2acde902007-10-11 00:24:40 +0800978 set_label(gpio, "free");
979
Yi Li6a01f232009-01-07 23:14:39 +0800980 local_irq_restore_hw(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
Graf Yang9570ff42009-01-07 23:14:38 +0800984int bfin_gpio_irq_request(unsigned gpio, const char *label)
985{
986 unsigned long flags;
987
988 if (check_gpio(gpio) < 0)
989 return -EINVAL;
990
Yi Li6a01f232009-01-07 23:14:39 +0800991 local_irq_save_hw(flags);
Graf Yang9570ff42009-01-07 23:14:38 +0800992
Graf Yang9570ff42009-01-07 23:14:38 +0800993 if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800994 if (system_state == SYSTEM_BOOTING)
995 dump_stack();
Graf Yang9570ff42009-01-07 23:14:38 +0800996 printk(KERN_ERR
997 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
998 gpio, get_label(gpio));
Yi Li6a01f232009-01-07 23:14:39 +0800999 local_irq_restore_hw(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001000 return -EBUSY;
1001 }
1002 if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))
1003 printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved by %s! "
1004 "(Documentation/blackfin/bfin-gpio-notes.txt)\n",
1005 gpio, get_label(gpio));
1006
1007 reserved_gpio_irq_map[gpio_bank(gpio)] |= gpio_bit(gpio);
1008 set_label(gpio, label);
1009
Yi Li6a01f232009-01-07 23:14:39 +08001010 local_irq_restore_hw(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001011
1012 port_setup(gpio, GPIO_USAGE);
1013
1014 return 0;
1015}
1016
1017void bfin_gpio_irq_free(unsigned gpio)
1018{
1019 unsigned long flags;
1020
1021 if (check_gpio(gpio) < 0)
1022 return;
1023
Yi Li6a01f232009-01-07 23:14:39 +08001024 local_irq_save_hw(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001025
1026 if (unlikely(!(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
Robin Getzd6879c52009-03-29 01:10:30 +08001027 if (system_state == SYSTEM_BOOTING)
1028 dump_stack();
Graf Yang9570ff42009-01-07 23:14:38 +08001029 gpio_error(gpio);
Yi Li6a01f232009-01-07 23:14:39 +08001030 local_irq_restore_hw(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001031 return;
1032 }
1033
1034 reserved_gpio_irq_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
1035
1036 set_label(gpio, "free");
1037
Yi Li6a01f232009-01-07 23:14:39 +08001038 local_irq_restore_hw(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001039}
1040
Mike Frysingerf5563092009-02-04 16:49:45 +08001041static inline void __bfin_gpio_direction_input(unsigned gpio)
1042{
Mike Frysinger269647d2009-03-28 20:32:57 +08001043#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001044 gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
Michael Hennerichd2b11a42007-08-28 16:47:46 +08001045#else
Mike Frysingerf5563092009-02-04 16:49:45 +08001046 gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
1047#endif
1048 gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
Michael Hennerich803a8d22008-05-17 16:01:51 +08001049}
Michael Hennerich803a8d22008-05-17 16:01:51 +08001050
Michael Hennericha4f0b322008-11-18 17:48:22 +08001051int bfin_gpio_direction_input(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -07001052{
1053 unsigned long flags;
1054
Michael Hennerichacbcd262008-01-22 18:36:20 +08001055 if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
1056 gpio_error(gpio);
1057 return -EINVAL;
1058 }
Bryan Wu1394f032007-05-06 14:50:22 -07001059
Yi Li6a01f232009-01-07 23:14:39 +08001060 local_irq_save_hw(flags);
Mike Frysingerf5563092009-02-04 16:49:45 +08001061 __bfin_gpio_direction_input(gpio);
Michael Hennerich2b393312007-10-10 16:58:49 +08001062 AWA_DUMMY_READ(inen);
Yi Li6a01f232009-01-07 23:14:39 +08001063 local_irq_restore_hw(flags);
Michael Hennerichacbcd262008-01-22 18:36:20 +08001064
1065 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -07001066}
Michael Hennericha4f0b322008-11-18 17:48:22 +08001067EXPORT_SYMBOL(bfin_gpio_direction_input);
Bryan Wu1394f032007-05-06 14:50:22 -07001068
Mike Frysingerf5563092009-02-04 16:49:45 +08001069void bfin_gpio_irq_prepare(unsigned gpio)
1070{
Mike Frysinger269647d2009-03-28 20:32:57 +08001071#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001072 unsigned long flags;
1073#endif
1074
1075 port_setup(gpio, GPIO_USAGE);
1076
Mike Frysinger269647d2009-03-28 20:32:57 +08001077#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001078 local_irq_save_hw(flags);
1079 __bfin_gpio_direction_input(gpio);
1080 local_irq_restore_hw(flags);
1081#endif
1082}
1083
1084void bfin_gpio_set_value(unsigned gpio, int arg)
1085{
1086 if (arg)
1087 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
1088 else
1089 gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
1090}
1091EXPORT_SYMBOL(bfin_gpio_set_value);
1092
Michael Hennericha4f0b322008-11-18 17:48:22 +08001093int bfin_gpio_direction_output(unsigned gpio, int value)
Bryan Wu1394f032007-05-06 14:50:22 -07001094{
1095 unsigned long flags;
1096
Michael Hennerichacbcd262008-01-22 18:36:20 +08001097 if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
1098 gpio_error(gpio);
1099 return -EINVAL;
1100 }
Bryan Wu1394f032007-05-06 14:50:22 -07001101
Yi Li6a01f232009-01-07 23:14:39 +08001102 local_irq_save_hw(flags);
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001103
Mike Frysingerf5563092009-02-04 16:49:45 +08001104 gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
1105 gpio_set_value(gpio, value);
Mike Frysinger269647d2009-03-28 20:32:57 +08001106#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001107 gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
1108#else
1109 gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
1110#endif
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001111
Michael Hennerich2b393312007-10-10 16:58:49 +08001112 AWA_DUMMY_READ(dir);
Yi Li6a01f232009-01-07 23:14:39 +08001113 local_irq_restore_hw(flags);
Michael Hennerichacbcd262008-01-22 18:36:20 +08001114
1115 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -07001116}
Michael Hennericha4f0b322008-11-18 17:48:22 +08001117EXPORT_SYMBOL(bfin_gpio_direction_output);
Mike Frysinger168f1212007-10-11 00:22:35 +08001118
Mike Frysingerf5563092009-02-04 16:49:45 +08001119int bfin_gpio_get_value(unsigned gpio)
1120{
Mike Frysinger269647d2009-03-28 20:32:57 +08001121#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001122 return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)));
1123#else
1124 unsigned long flags;
1125
1126 if (unlikely(get_gpio_edge(gpio))) {
1127 int ret;
1128 local_irq_save_hw(flags);
1129 set_gpio_edge(gpio, 0);
1130 ret = get_gpio_data(gpio);
1131 set_gpio_edge(gpio, 1);
1132 local_irq_restore_hw(flags);
1133 return ret;
1134 } else
1135 return get_gpio_data(gpio);
1136#endif
1137}
1138EXPORT_SYMBOL(bfin_gpio_get_value);
1139
Mike Frysinger168f1212007-10-11 00:22:35 +08001140/* If we are booting from SPI and our board lacks a strong enough pull up,
1141 * the core can reset and execute the bootrom faster than the resistor can
1142 * pull the signal logically high. To work around this (common) error in
1143 * board design, we explicitly set the pin back to GPIO mode, force /CS
1144 * high, and wait for the electrons to do their thing.
1145 *
1146 * This function only makes sense to be called from reset code, but it
1147 * lives here as we need to force all the GPIO states w/out going through
1148 * BUG() checks and such.
1149 */
Sonic Zhangb52dae32009-02-04 16:49:45 +08001150void bfin_reset_boot_spi_cs(unsigned short pin)
Mike Frysinger168f1212007-10-11 00:22:35 +08001151{
Sonic Zhangb52dae32009-02-04 16:49:45 +08001152 unsigned short gpio = P_IDENT(pin);
Michael Hennerich4d5f4ed2007-08-27 16:46:17 +08001153 port_setup(gpio, GPIO_USAGE);
Mike Frysingerf5563092009-02-04 16:49:45 +08001154 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001155 AWA_DUMMY_READ(data_set);
Mike Frysinger168f1212007-10-11 00:22:35 +08001156 udelay(1);
1157}
Michael Hennerichd2b11a42007-08-28 16:47:46 +08001158
Mike Frysinger1545a112007-12-24 16:54:48 +08001159#if defined(CONFIG_PROC_FS)
1160static int gpio_proc_read(char *buf, char **start, off_t offset,
1161 int len, int *unused_i, void *unused_v)
1162{
Graf Yang9570ff42009-01-07 23:14:38 +08001163 int c, irq, gpio, outlen = 0;
Mike Frysinger1545a112007-12-24 16:54:48 +08001164
1165 for (c = 0; c < MAX_RESOURCES; c++) {
Graf Yang9570ff42009-01-07 23:14:38 +08001166 irq = reserved_gpio_irq_map[gpio_bank(c)] & gpio_bit(c);
1167 gpio = reserved_gpio_map[gpio_bank(c)] & gpio_bit(c);
1168 if (!check_gpio(c) && (gpio || irq))
1169 len = sprintf(buf, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c,
1170 get_label(c), (gpio && irq) ? " *" : "",
1171 get_gpio_dir(c) ? "OUTPUT" : "INPUT");
Mike Frysinger1545a112007-12-24 16:54:48 +08001172 else if (reserved_peri_map[gpio_bank(c)] & gpio_bit(c))
Graf Yang8eb3e3b2008-11-18 17:48:22 +08001173 len = sprintf(buf, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c));
Mike Frysinger1545a112007-12-24 16:54:48 +08001174 else
1175 continue;
1176 buf += len;
1177 outlen += len;
1178 }
1179 return outlen;
1180}
1181
1182static __init int gpio_register_proc(void)
1183{
1184 struct proc_dir_entry *proc_gpio;
1185
1186 proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL);
1187 if (proc_gpio)
1188 proc_gpio->read_proc = gpio_proc_read;
1189 return proc_gpio != NULL;
1190}
Mike Frysinger1545a112007-12-24 16:54:48 +08001191__initcall(gpio_register_proc);
1192#endif
Michael Hennericha4f0b322008-11-18 17:48:22 +08001193
1194#ifdef CONFIG_GPIOLIB
1195int bfin_gpiolib_direction_input(struct gpio_chip *chip, unsigned gpio)
1196{
1197 return bfin_gpio_direction_input(gpio);
1198}
1199
1200int bfin_gpiolib_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
1201{
1202 return bfin_gpio_direction_output(gpio, level);
1203}
1204
1205int bfin_gpiolib_get_value(struct gpio_chip *chip, unsigned gpio)
1206{
1207 return bfin_gpio_get_value(gpio);
1208}
1209
1210void bfin_gpiolib_set_value(struct gpio_chip *chip, unsigned gpio, int value)
1211{
Michael Hennericha4f0b322008-11-18 17:48:22 +08001212 return bfin_gpio_set_value(gpio, value);
Michael Hennericha4f0b322008-11-18 17:48:22 +08001213}
1214
1215int bfin_gpiolib_gpio_request(struct gpio_chip *chip, unsigned gpio)
1216{
1217 return bfin_gpio_request(gpio, chip->label);
1218}
1219
1220void bfin_gpiolib_gpio_free(struct gpio_chip *chip, unsigned gpio)
1221{
1222 return bfin_gpio_free(gpio);
1223}
1224
1225static struct gpio_chip bfin_chip = {
1226 .label = "Blackfin-GPIOlib",
1227 .direction_input = bfin_gpiolib_direction_input,
1228 .get = bfin_gpiolib_get_value,
1229 .direction_output = bfin_gpiolib_direction_output,
1230 .set = bfin_gpiolib_set_value,
1231 .request = bfin_gpiolib_gpio_request,
1232 .free = bfin_gpiolib_gpio_free,
1233 .base = 0,
1234 .ngpio = MAX_BLACKFIN_GPIOS,
1235};
1236
1237static int __init bfin_gpiolib_setup(void)
1238{
1239 return gpiochip_add(&bfin_chip);
1240}
1241arch_initcall(bfin_gpiolib_setup);
1242#endif