2 * File: arch/blackfin/mach-bf548/gpio.c
4 * Author: Michael Hennerich (hennerich@blackfin.uclinux.org)
7 * Description: GPIO Abstraction Layer
10 * Copyright 2007 Analog Devices Inc.
12 * Bugs: Enter bugs at http://blackfin.uclinux.org/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see the file COPYING, or write
26 * to the Free Software Foundation, Inc.,
27 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 #include <linux/module.h>
31 #include <linux/err.h>
32 #include <asm/blackfin.h>
34 #include <asm/portmux.h>
35 #include <linux/irq.h>
37 static struct gpio_port_t *gpio_array[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
38 (struct gpio_port_t *)PORTA_FER,
39 (struct gpio_port_t *)PORTB_FER,
40 (struct gpio_port_t *)PORTC_FER,
41 (struct gpio_port_t *)PORTD_FER,
42 (struct gpio_port_t *)PORTE_FER,
43 (struct gpio_port_t *)PORTF_FER,
44 (struct gpio_port_t *)PORTG_FER,
45 (struct gpio_port_t *)PORTH_FER,
46 (struct gpio_port_t *)PORTI_FER,
47 (struct gpio_port_t *)PORTJ_FER,
50 static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
51 static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
53 #define MAX_RESOURCES 256
54 #define RESOURCE_LABEL_SIZE 16
57 char name[RESOURCE_LABEL_SIZE];
60 inline int check_gpio(unsigned short gpio)
62 if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
63 || gpio == GPIO_PH14 || gpio == GPIO_PH15
64 || gpio == GPIO_PJ14 || gpio == GPIO_PJ15
65 || gpio > MAX_BLACKFIN_GPIOS)
70 inline void portmux_setup(unsigned short portno, unsigned short function)
74 pmux = gpio_array[gpio_bank(portno)]->port_mux;
76 pmux &= ~(0x3 << (2 * gpio_sub_n(portno)));
77 pmux |= (function & 0x3) << (2 * gpio_sub_n(portno));
79 gpio_array[gpio_bank(portno)]->port_mux = pmux;
82 inline u16 get_portmux(unsigned short portno)
86 pmux = gpio_array[gpio_bank(portno)]->port_mux;
88 return (pmux >> (2 * gpio_sub_n(portno)) & 0x3);
91 static void port_setup(unsigned short gpio, unsigned short usage)
93 if (usage == GPIO_USAGE) {
94 gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
96 gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
100 static int __init bfin_gpio_init(void)
103 str_ident = kcalloc(MAX_RESOURCES,
104 sizeof(struct str_ident), GFP_KERNEL);
105 if (str_ident == NULL)
108 memset(str_ident, 0, MAX_RESOURCES * sizeof(struct str_ident));
110 printk(KERN_INFO "Blackfin GPIO Controller\n");
115 arch_initcall(bfin_gpio_init);
117 static void set_label(unsigned short ident, const char *label)
120 if (label && str_ident) {
121 strncpy(str_ident[ident].name, label,
122 RESOURCE_LABEL_SIZE);
123 str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0;
127 static char *get_label(unsigned short ident)
132 return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN");
135 static int cmp_label(unsigned short ident, const char *label)
137 if (label && str_ident)
138 return strncmp(str_ident[ident].name,
139 label, strlen(label));
144 int peripheral_request(unsigned short per, const char *label)
147 unsigned short ident = P_IDENT(per);
150 * Don't cares are pins with only one dedicated function
153 if (per & P_DONTCARE)
156 if (!(per & P_DEFINED))
159 if (check_gpio(ident) < 0)
162 local_irq_save(flags);
164 if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
166 "%s: Peripheral %d is already reserved as GPIO by %s !\n",
167 __FUNCTION__, ident, get_label(ident));
169 local_irq_restore(flags);
173 if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
175 u16 funct = get_portmux(ident);
178 * Pin functions like AMC address strobes my
179 * be requested and used by several drivers
182 if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) {
185 * Allow that the identical pin function can
186 * be requested from the same driver twice
189 if (cmp_label(ident, label) == 0)
193 "%s: Peripheral %d function %d is already reserved by %s !\n",
194 __FUNCTION__, ident, P_FUNCT2MUX(per), get_label(ident));
196 local_irq_restore(flags);
202 reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
204 portmux_setup(ident, P_FUNCT2MUX(per));
205 port_setup(ident, PERIPHERAL_USAGE);
207 local_irq_restore(flags);
208 set_label(ident, label);
212 EXPORT_SYMBOL(peripheral_request);
214 int peripheral_request_list(unsigned short per[], const char *label)
219 for (cnt = 0; per[cnt] != 0; cnt++) {
221 ret = peripheral_request(per[cnt], label);
224 for ( ; cnt > 0; cnt--) {
225 peripheral_free(per[cnt - 1]);
234 EXPORT_SYMBOL(peripheral_request_list);
236 void peripheral_free(unsigned short per)
239 unsigned short ident = P_IDENT(per);
241 if (per & P_DONTCARE)
244 if (!(per & P_DEFINED))
247 if (check_gpio(ident) < 0)
250 local_irq_save(flags);
252 if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) {
253 local_irq_restore(flags);
257 if (!(per & P_MAYSHARE)) {
258 port_setup(ident, GPIO_USAGE);
261 reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident);
263 local_irq_restore(flags);
265 EXPORT_SYMBOL(peripheral_free);
267 void peripheral_free_list(unsigned short per[])
271 for (cnt = 0; per[cnt] != 0; cnt++) {
272 peripheral_free(per[cnt]);
276 EXPORT_SYMBOL(peripheral_free_list);
278 /***********************************************************
280 * FUNCTIONS: Blackfin GPIO Driver
283 * gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
286 * DESCRIPTION: Blackfin GPIO Driver API
289 *************************************************************
290 * MODIFICATION HISTORY :
291 **************************************************************/
293 int gpio_request(unsigned short gpio, const char *label)
297 if (check_gpio(gpio) < 0)
300 local_irq_save(flags);
302 if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
303 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
304 gpio, get_label(gpio));
306 local_irq_restore(flags);
310 if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
312 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
313 gpio, get_label(gpio));
315 local_irq_restore(flags);
319 reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
321 local_irq_restore(flags);
323 port_setup(gpio, GPIO_USAGE);
324 set_label(gpio, label);
328 EXPORT_SYMBOL(gpio_request);
330 void gpio_free(unsigned short gpio)
334 if (check_gpio(gpio) < 0)
337 local_irq_save(flags);
339 if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
340 printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio);
342 local_irq_restore(flags);
346 reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
348 local_irq_restore(flags);
350 EXPORT_SYMBOL(gpio_free);
352 void gpio_direction_input(unsigned short gpio)
356 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
358 local_irq_save(flags);
359 gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
360 gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
361 local_irq_restore(flags);
363 EXPORT_SYMBOL(gpio_direction_input);
365 void gpio_direction_output(unsigned short gpio)
369 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
371 local_irq_save(flags);
372 gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio);
373 gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio);
374 local_irq_restore(flags);
376 EXPORT_SYMBOL(gpio_direction_output);
378 void gpio_set_value(unsigned short gpio, unsigned short arg)
381 gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio);
383 gpio_array[gpio_bank(gpio)]->port_clear = gpio_bit(gpio);
386 EXPORT_SYMBOL(gpio_set_value);
388 unsigned short gpio_get_value(unsigned short gpio)
390 return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio)));
392 EXPORT_SYMBOL(gpio_get_value);