blob: 22705eeff34f5b64c4f510cc4a781a18d6afc0f8 [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
Yi Li6a01f232009-01-07 23:14:39 +0800765 local_irq_save_hw(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800766
Mike Frysinger6a87d292008-10-28 16:16:29 +0800767 /* If a pin can be muxed as either GPIO or peripheral, make
768 * sure it is not already a GPIO pin when we request it.
769 */
770 if (unlikely(!check_gpio(ident) &&
771 reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800772 if (system_state == SYSTEM_BOOTING)
773 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800774 printk(KERN_ERR
Mike Frysinger6c7ec0e2008-10-28 15:49:59 +0800775 "%s: Peripheral %d is already reserved as GPIO by %s !\n",
Harvey Harrisonb85d8582008-04-23 09:39:01 +0800776 __func__, ident, get_label(ident));
Yi Li6a01f232009-01-07 23:14:39 +0800777 local_irq_restore_hw(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800778 return -EBUSY;
779 }
780
781 if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
782
Mike Frysingerd171c232008-03-26 08:35:46 +0800783 /*
784 * Pin functions like AMC address strobes my
785 * be requested and used by several drivers
786 */
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800787
Mike Frysinger269647d2009-03-28 20:32:57 +0800788#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +0800789 if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) {
Mike Frysinger6c7ec0e2008-10-28 15:49:59 +0800790#else
791 if (!(per & P_MAYSHARE)) {
792#endif
Mike Frysingerd171c232008-03-26 08:35:46 +0800793 /*
794 * Allow that the identical pin function can
795 * be requested from the same driver twice
796 */
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800797
Mike Frysingerd171c232008-03-26 08:35:46 +0800798 if (cmp_label(ident, label) == 0)
799 goto anyway;
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800800
Robin Getzd6879c52009-03-29 01:10:30 +0800801 if (system_state == SYSTEM_BOOTING)
802 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800803 printk(KERN_ERR
804 "%s: Peripheral %d function %d is already reserved by %s !\n",
Harvey Harrisonb85d8582008-04-23 09:39:01 +0800805 __func__, ident, P_FUNCT2MUX(per), get_label(ident));
Yi Li6a01f232009-01-07 23:14:39 +0800806 local_irq_restore_hw(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800807 return -EBUSY;
808 }
809 }
810
Mike Frysingerd171c232008-03-26 08:35:46 +0800811 anyway:
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800812 reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
813
Mike Frysingerf5563092009-02-04 16:49:45 +0800814 portmux_setup(per);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800815 port_setup(ident, PERIPHERAL_USAGE);
816
Yi Li6a01f232009-01-07 23:14:39 +0800817 local_irq_restore_hw(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800818 set_label(ident, label);
819
820 return 0;
821}
822EXPORT_SYMBOL(peripheral_request);
823
Mike Frysinger68179372008-04-24 05:04:24 +0800824int peripheral_request_list(const unsigned short per[], const char *label)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800825{
826 u16 cnt;
827 int ret;
828
829 for (cnt = 0; per[cnt] != 0; cnt++) {
Michael Hennerich314c98d2007-07-24 18:03:45 +0800830
Michael Hennerichc58c2142007-10-04 00:35:05 +0800831 ret = peripheral_request(per[cnt], label);
Michael Hennerich314c98d2007-07-24 18:03:45 +0800832
833 if (ret < 0) {
Mike Frysingerd171c232008-03-26 08:35:46 +0800834 for ( ; cnt > 0; cnt--)
Michael Hennerich314c98d2007-07-24 18:03:45 +0800835 peripheral_free(per[cnt - 1]);
Mike Frysingerd171c232008-03-26 08:35:46 +0800836
837 return ret;
Michael Hennerich314c98d2007-07-24 18:03:45 +0800838 }
Michael Hennerichc58c2142007-10-04 00:35:05 +0800839 }
840
841 return 0;
842}
843EXPORT_SYMBOL(peripheral_request_list);
844
845void peripheral_free(unsigned short per)
846{
847 unsigned long flags;
848 unsigned short ident = P_IDENT(per);
849
850 if (per & P_DONTCARE)
851 return;
852
853 if (!(per & P_DEFINED))
854 return;
855
Yi Li6a01f232009-01-07 23:14:39 +0800856 local_irq_save_hw(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800857
Mike Frysingerd171c232008-03-26 08:35:46 +0800858 if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) {
Yi Li6a01f232009-01-07 23:14:39 +0800859 local_irq_restore_hw(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800860 return;
861 }
862
Mike Frysingerd171c232008-03-26 08:35:46 +0800863 if (!(per & P_MAYSHARE))
Michael Hennerichc58c2142007-10-04 00:35:05 +0800864 port_setup(ident, GPIO_USAGE);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800865
866 reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident);
867
Michael Hennerich2acde902007-10-11 00:24:40 +0800868 set_label(ident, "free");
869
Yi Li6a01f232009-01-07 23:14:39 +0800870 local_irq_restore_hw(flags);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800871}
872EXPORT_SYMBOL(peripheral_free);
873
Mike Frysinger68179372008-04-24 05:04:24 +0800874void peripheral_free_list(const unsigned short per[])
Michael Hennerichc58c2142007-10-04 00:35:05 +0800875{
876 u16 cnt;
Mike Frysingerd171c232008-03-26 08:35:46 +0800877 for (cnt = 0; per[cnt] != 0; cnt++)
Michael Hennerichc58c2142007-10-04 00:35:05 +0800878 peripheral_free(per[cnt]);
Michael Hennerichc58c2142007-10-04 00:35:05 +0800879}
880EXPORT_SYMBOL(peripheral_free_list);
881
Bryan Wu1394f032007-05-06 14:50:22 -0700882/***********************************************************
883*
884* FUNCTIONS: Blackfin GPIO Driver
885*
886* INPUTS/OUTPUTS:
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800887* gpio PIO Number between 0 and MAX_BLACKFIN_GPIOS
888* label String
Bryan Wu1394f032007-05-06 14:50:22 -0700889*
890* DESCRIPTION: Blackfin GPIO Driver API
891*
892* CAUTION:
893*************************************************************
894* MODIFICATION HISTORY :
895**************************************************************/
896
Michael Hennericha4f0b322008-11-18 17:48:22 +0800897int bfin_gpio_request(unsigned gpio, const char *label)
Bryan Wu1394f032007-05-06 14:50:22 -0700898{
899 unsigned long flags;
900
901 if (check_gpio(gpio) < 0)
902 return -EINVAL;
903
Yi Li6a01f232009-01-07 23:14:39 +0800904 local_irq_save_hw(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700905
Michael Hennerich2acde902007-10-11 00:24:40 +0800906 /*
907 * Allow that the identical GPIO can
908 * be requested from the same driver twice
909 * Do nothing and return -
910 */
911
912 if (cmp_label(gpio, label) == 0) {
Yi Li6a01f232009-01-07 23:14:39 +0800913 local_irq_restore_hw(flags);
Michael Hennerich2acde902007-10-11 00:24:40 +0800914 return 0;
915 }
916
Michael Hennerichc58c2142007-10-04 00:35:05 +0800917 if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800918 if (system_state == SYSTEM_BOOTING)
919 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800920 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
Graf Yang9570ff42009-01-07 23:14:38 +0800921 gpio, get_label(gpio));
Yi Li6a01f232009-01-07 23:14:39 +0800922 local_irq_restore_hw(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700923 return -EBUSY;
924 }
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800925 if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800926 if (system_state == SYSTEM_BOOTING)
927 dump_stack();
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800928 printk(KERN_ERR
929 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
930 gpio, get_label(gpio));
Yi Li6a01f232009-01-07 23:14:39 +0800931 local_irq_restore_hw(flags);
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800932 return -EBUSY;
933 }
Michael Hennericha2be3932009-02-04 16:49:45 +0800934 if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
Graf Yang9570ff42009-01-07 23:14:38 +0800935 printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!"
936 " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio);
Michael Hennericha2be3932009-02-04 16:49:45 +0800937 }
Mike Frysinger269647d2009-03-28 20:32:57 +0800938#ifndef CONFIG_BF54x
Michael Hennericha2be3932009-02-04 16:49:45 +0800939 else { /* Reset POLAR setting when acquiring a gpio for the first time */
940 set_gpio_polar(gpio, 0);
941 }
942#endif
Michael Hennerichd2b11a42007-08-28 16:47:46 +0800943
Michael Hennerichc58c2142007-10-04 00:35:05 +0800944 reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
Graf Yang9570ff42009-01-07 23:14:38 +0800945 set_label(gpio, label);
Bryan Wu1394f032007-05-06 14:50:22 -0700946
Yi Li6a01f232009-01-07 23:14:39 +0800947 local_irq_restore_hw(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700948
949 port_setup(gpio, GPIO_USAGE);
950
951 return 0;
952}
Michael Hennericha4f0b322008-11-18 17:48:22 +0800953EXPORT_SYMBOL(bfin_gpio_request);
Bryan Wu1394f032007-05-06 14:50:22 -0700954
Michael Hennericha4f0b322008-11-18 17:48:22 +0800955void bfin_gpio_free(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -0700956{
957 unsigned long flags;
958
959 if (check_gpio(gpio) < 0)
960 return;
961
Uwe Kleine-Koenig45c4f2a2009-02-04 17:02:30 +0800962 might_sleep();
963
Yi Li6a01f232009-01-07 23:14:39 +0800964 local_irq_save_hw(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700965
Michael Hennerichc58c2142007-10-04 00:35:05 +0800966 if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800967 if (system_state == SYSTEM_BOOTING)
968 dump_stack();
Mike Frysingerf85c4ab2008-03-26 08:34:23 +0800969 gpio_error(gpio);
Yi Li6a01f232009-01-07 23:14:39 +0800970 local_irq_restore_hw(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700971 return;
972 }
973
Michael Hennerichc58c2142007-10-04 00:35:05 +0800974 reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
Bryan Wu1394f032007-05-06 14:50:22 -0700975
Michael Hennerich2acde902007-10-11 00:24:40 +0800976 set_label(gpio, "free");
977
Yi Li6a01f232009-01-07 23:14:39 +0800978 local_irq_restore_hw(flags);
Bryan Wu1394f032007-05-06 14:50:22 -0700979}
Michael Hennericha4f0b322008-11-18 17:48:22 +0800980EXPORT_SYMBOL(bfin_gpio_free);
Bryan Wu1394f032007-05-06 14:50:22 -0700981
Graf Yang9570ff42009-01-07 23:14:38 +0800982int bfin_gpio_irq_request(unsigned gpio, const char *label)
983{
984 unsigned long flags;
985
986 if (check_gpio(gpio) < 0)
987 return -EINVAL;
988
Yi Li6a01f232009-01-07 23:14:39 +0800989 local_irq_save_hw(flags);
Graf Yang9570ff42009-01-07 23:14:38 +0800990
Graf Yang9570ff42009-01-07 23:14:38 +0800991 if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
Robin Getzd6879c52009-03-29 01:10:30 +0800992 if (system_state == SYSTEM_BOOTING)
993 dump_stack();
Graf Yang9570ff42009-01-07 23:14:38 +0800994 printk(KERN_ERR
995 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
996 gpio, get_label(gpio));
Yi Li6a01f232009-01-07 23:14:39 +0800997 local_irq_restore_hw(flags);
Graf Yang9570ff42009-01-07 23:14:38 +0800998 return -EBUSY;
999 }
1000 if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))
1001 printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved by %s! "
1002 "(Documentation/blackfin/bfin-gpio-notes.txt)\n",
1003 gpio, get_label(gpio));
1004
1005 reserved_gpio_irq_map[gpio_bank(gpio)] |= gpio_bit(gpio);
1006 set_label(gpio, label);
1007
Yi Li6a01f232009-01-07 23:14:39 +08001008 local_irq_restore_hw(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001009
1010 port_setup(gpio, GPIO_USAGE);
1011
1012 return 0;
1013}
1014
1015void bfin_gpio_irq_free(unsigned gpio)
1016{
1017 unsigned long flags;
1018
1019 if (check_gpio(gpio) < 0)
1020 return;
1021
Yi Li6a01f232009-01-07 23:14:39 +08001022 local_irq_save_hw(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001023
1024 if (unlikely(!(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
Robin Getzd6879c52009-03-29 01:10:30 +08001025 if (system_state == SYSTEM_BOOTING)
1026 dump_stack();
Graf Yang9570ff42009-01-07 23:14:38 +08001027 gpio_error(gpio);
Yi Li6a01f232009-01-07 23:14:39 +08001028 local_irq_restore_hw(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001029 return;
1030 }
1031
1032 reserved_gpio_irq_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
1033
1034 set_label(gpio, "free");
1035
Yi Li6a01f232009-01-07 23:14:39 +08001036 local_irq_restore_hw(flags);
Graf Yang9570ff42009-01-07 23:14:38 +08001037}
1038
Mike Frysingerf5563092009-02-04 16:49:45 +08001039static inline void __bfin_gpio_direction_input(unsigned gpio)
1040{
Mike Frysinger269647d2009-03-28 20:32:57 +08001041#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001042 gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
Michael Hennerichd2b11a42007-08-28 16:47:46 +08001043#else
Mike Frysingerf5563092009-02-04 16:49:45 +08001044 gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
1045#endif
1046 gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
Michael Hennerich803a8d22008-05-17 16:01:51 +08001047}
Michael Hennerich803a8d22008-05-17 16:01:51 +08001048
Michael Hennericha4f0b322008-11-18 17:48:22 +08001049int bfin_gpio_direction_input(unsigned gpio)
Bryan Wu1394f032007-05-06 14:50:22 -07001050{
1051 unsigned long flags;
1052
Michael Hennerichacbcd262008-01-22 18:36:20 +08001053 if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
1054 gpio_error(gpio);
1055 return -EINVAL;
1056 }
Bryan Wu1394f032007-05-06 14:50:22 -07001057
Yi Li6a01f232009-01-07 23:14:39 +08001058 local_irq_save_hw(flags);
Mike Frysingerf5563092009-02-04 16:49:45 +08001059 __bfin_gpio_direction_input(gpio);
Michael Hennerich2b393312007-10-10 16:58:49 +08001060 AWA_DUMMY_READ(inen);
Yi Li6a01f232009-01-07 23:14:39 +08001061 local_irq_restore_hw(flags);
Michael Hennerichacbcd262008-01-22 18:36:20 +08001062
1063 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -07001064}
Michael Hennericha4f0b322008-11-18 17:48:22 +08001065EXPORT_SYMBOL(bfin_gpio_direction_input);
Bryan Wu1394f032007-05-06 14:50:22 -07001066
Mike Frysingerf5563092009-02-04 16:49:45 +08001067void bfin_gpio_irq_prepare(unsigned gpio)
1068{
Mike Frysinger269647d2009-03-28 20:32:57 +08001069#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001070 unsigned long flags;
1071#endif
1072
1073 port_setup(gpio, GPIO_USAGE);
1074
Mike Frysinger269647d2009-03-28 20:32:57 +08001075#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001076 local_irq_save_hw(flags);
1077 __bfin_gpio_direction_input(gpio);
1078 local_irq_restore_hw(flags);
1079#endif
1080}
1081
1082void bfin_gpio_set_value(unsigned gpio, int arg)
1083{
1084 if (arg)
1085 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
1086 else
1087 gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
1088}
1089EXPORT_SYMBOL(bfin_gpio_set_value);
1090
Michael Hennericha4f0b322008-11-18 17:48:22 +08001091int bfin_gpio_direction_output(unsigned gpio, int value)
Bryan Wu1394f032007-05-06 14:50:22 -07001092{
1093 unsigned long flags;
1094
Michael Hennerichacbcd262008-01-22 18:36:20 +08001095 if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
1096 gpio_error(gpio);
1097 return -EINVAL;
1098 }
Bryan Wu1394f032007-05-06 14:50:22 -07001099
Yi Li6a01f232009-01-07 23:14:39 +08001100 local_irq_save_hw(flags);
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001101
Mike Frysingerf5563092009-02-04 16:49:45 +08001102 gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
1103 gpio_set_value(gpio, value);
Mike Frysinger269647d2009-03-28 20:32:57 +08001104#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001105 gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
1106#else
1107 gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
1108#endif
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001109
Michael Hennerich2b393312007-10-10 16:58:49 +08001110 AWA_DUMMY_READ(dir);
Yi Li6a01f232009-01-07 23:14:39 +08001111 local_irq_restore_hw(flags);
Michael Hennerichacbcd262008-01-22 18:36:20 +08001112
1113 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -07001114}
Michael Hennericha4f0b322008-11-18 17:48:22 +08001115EXPORT_SYMBOL(bfin_gpio_direction_output);
Mike Frysinger168f1212007-10-11 00:22:35 +08001116
Mike Frysingerf5563092009-02-04 16:49:45 +08001117int bfin_gpio_get_value(unsigned gpio)
1118{
Mike Frysinger269647d2009-03-28 20:32:57 +08001119#ifdef CONFIG_BF54x
Mike Frysingerf5563092009-02-04 16:49:45 +08001120 return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)));
1121#else
1122 unsigned long flags;
1123
1124 if (unlikely(get_gpio_edge(gpio))) {
1125 int ret;
1126 local_irq_save_hw(flags);
1127 set_gpio_edge(gpio, 0);
1128 ret = get_gpio_data(gpio);
1129 set_gpio_edge(gpio, 1);
1130 local_irq_restore_hw(flags);
1131 return ret;
1132 } else
1133 return get_gpio_data(gpio);
1134#endif
1135}
1136EXPORT_SYMBOL(bfin_gpio_get_value);
1137
Mike Frysinger168f1212007-10-11 00:22:35 +08001138/* If we are booting from SPI and our board lacks a strong enough pull up,
1139 * the core can reset and execute the bootrom faster than the resistor can
1140 * pull the signal logically high. To work around this (common) error in
1141 * board design, we explicitly set the pin back to GPIO mode, force /CS
1142 * high, and wait for the electrons to do their thing.
1143 *
1144 * This function only makes sense to be called from reset code, but it
1145 * lives here as we need to force all the GPIO states w/out going through
1146 * BUG() checks and such.
1147 */
Sonic Zhangb52dae32009-02-04 16:49:45 +08001148void bfin_reset_boot_spi_cs(unsigned short pin)
Mike Frysinger168f1212007-10-11 00:22:35 +08001149{
Sonic Zhangb52dae32009-02-04 16:49:45 +08001150 unsigned short gpio = P_IDENT(pin);
Michael Hennerich4d5f4ed2007-08-27 16:46:17 +08001151 port_setup(gpio, GPIO_USAGE);
Mike Frysingerf5563092009-02-04 16:49:45 +08001152 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
Michael Hennericha2c8cfe2008-01-22 17:20:10 +08001153 AWA_DUMMY_READ(data_set);
Mike Frysinger168f1212007-10-11 00:22:35 +08001154 udelay(1);
1155}
Michael Hennerichd2b11a42007-08-28 16:47:46 +08001156
Mike Frysinger1545a112007-12-24 16:54:48 +08001157#if defined(CONFIG_PROC_FS)
1158static int gpio_proc_read(char *buf, char **start, off_t offset,
1159 int len, int *unused_i, void *unused_v)
1160{
Graf Yang9570ff42009-01-07 23:14:38 +08001161 int c, irq, gpio, outlen = 0;
Mike Frysinger1545a112007-12-24 16:54:48 +08001162
1163 for (c = 0; c < MAX_RESOURCES; c++) {
Graf Yang9570ff42009-01-07 23:14:38 +08001164 irq = reserved_gpio_irq_map[gpio_bank(c)] & gpio_bit(c);
1165 gpio = reserved_gpio_map[gpio_bank(c)] & gpio_bit(c);
1166 if (!check_gpio(c) && (gpio || irq))
1167 len = sprintf(buf, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c,
1168 get_label(c), (gpio && irq) ? " *" : "",
1169 get_gpio_dir(c) ? "OUTPUT" : "INPUT");
Mike Frysinger1545a112007-12-24 16:54:48 +08001170 else if (reserved_peri_map[gpio_bank(c)] & gpio_bit(c))
Graf Yang8eb3e3b2008-11-18 17:48:22 +08001171 len = sprintf(buf, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c));
Mike Frysinger1545a112007-12-24 16:54:48 +08001172 else
1173 continue;
1174 buf += len;
1175 outlen += len;
1176 }
1177 return outlen;
1178}
1179
1180static __init int gpio_register_proc(void)
1181{
1182 struct proc_dir_entry *proc_gpio;
1183
1184 proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL);
1185 if (proc_gpio)
1186 proc_gpio->read_proc = gpio_proc_read;
1187 return proc_gpio != NULL;
1188}
Mike Frysinger1545a112007-12-24 16:54:48 +08001189__initcall(gpio_register_proc);
1190#endif
Michael Hennericha4f0b322008-11-18 17:48:22 +08001191
1192#ifdef CONFIG_GPIOLIB
1193int bfin_gpiolib_direction_input(struct gpio_chip *chip, unsigned gpio)
1194{
1195 return bfin_gpio_direction_input(gpio);
1196}
1197
1198int bfin_gpiolib_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
1199{
1200 return bfin_gpio_direction_output(gpio, level);
1201}
1202
1203int bfin_gpiolib_get_value(struct gpio_chip *chip, unsigned gpio)
1204{
1205 return bfin_gpio_get_value(gpio);
1206}
1207
1208void bfin_gpiolib_set_value(struct gpio_chip *chip, unsigned gpio, int value)
1209{
Michael Hennericha4f0b322008-11-18 17:48:22 +08001210 return bfin_gpio_set_value(gpio, value);
Michael Hennericha4f0b322008-11-18 17:48:22 +08001211}
1212
1213int bfin_gpiolib_gpio_request(struct gpio_chip *chip, unsigned gpio)
1214{
1215 return bfin_gpio_request(gpio, chip->label);
1216}
1217
1218void bfin_gpiolib_gpio_free(struct gpio_chip *chip, unsigned gpio)
1219{
1220 return bfin_gpio_free(gpio);
1221}
1222
1223static struct gpio_chip bfin_chip = {
1224 .label = "Blackfin-GPIOlib",
1225 .direction_input = bfin_gpiolib_direction_input,
1226 .get = bfin_gpiolib_get_value,
1227 .direction_output = bfin_gpiolib_direction_output,
1228 .set = bfin_gpiolib_set_value,
1229 .request = bfin_gpiolib_gpio_request,
1230 .free = bfin_gpiolib_gpio_free,
1231 .base = 0,
1232 .ngpio = MAX_BLACKFIN_GPIOS,
1233};
1234
1235static int __init bfin_gpiolib_setup(void)
1236{
1237 return gpiochip_add(&bfin_chip);
1238}
1239arch_initcall(bfin_gpiolib_setup);
1240#endif