diff options
Diffstat (limited to 'arch/blackfin/kernel/bfin_gpio.c')
| -rw-r--r-- | arch/blackfin/kernel/bfin_gpio.c | 658 |
1 files changed, 258 insertions, 400 deletions
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index e35e20f00d9..a017359c182 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -1,7 +1,7 @@ /* * GPIO Abstraction Layer * - * Copyright 2006-2009 Analog Devices Inc. + * Copyright 2006-2010 Analog Devices Inc. * * Licensed under the GPL-2 or later */ @@ -10,9 +10,8 @@ #include <linux/module.h> #include <linux/err.h> #include <linux/proc_fs.h> -#include <asm/blackfin.h> -#include <asm/gpio.h> -#include <asm/portmux.h> +#include <linux/seq_file.h> +#include <linux/gpio.h> #include <linux/irq.h> #if ANOMALY_05000311 || ANOMALY_05000323 @@ -56,17 +55,6 @@ static struct gpio_port_t * const gpio_array[] = { (struct gpio_port_t *) FIO0_FLAG_D, (struct gpio_port_t *) FIO1_FLAG_D, (struct gpio_port_t *) FIO2_FLAG_D, -#elif defined(CONFIG_BF54x) - (struct gpio_port_t *)PORTA_FER, - (struct gpio_port_t *)PORTB_FER, - (struct gpio_port_t *)PORTC_FER, - (struct gpio_port_t *)PORTD_FER, - (struct gpio_port_t *)PORTE_FER, - (struct gpio_port_t *)PORTF_FER, - (struct gpio_port_t *)PORTG_FER, - (struct gpio_port_t *)PORTH_FER, - (struct gpio_port_t *)PORTI_FER, - (struct gpio_port_t *)PORTJ_FER, #else # error no gpio arrays defined #endif @@ -108,11 +96,7 @@ static unsigned short * const port_fer[] = { }; #endif -static unsigned short reserved_gpio_map[GPIO_BANK_NUM]; -static unsigned short reserved_peri_map[gpio_bank(MAX_RESOURCES)]; -static unsigned short reserved_gpio_irq_map[GPIO_BANK_NUM]; - -#define RESOURCE_LABEL_SIZE 16 +#define RESOURCE_LABEL_SIZE 16 static struct str_ident { char name[RESOURCE_LABEL_SIZE]; @@ -120,21 +104,11 @@ static struct str_ident { #if defined(CONFIG_PM) static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM]; +# ifdef BF538_FAMILY +static unsigned short port_fer_saved[3]; +# endif #endif -inline int check_gpio(unsigned gpio) -{ -#if defined(CONFIG_BF54x) - if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 - || gpio == GPIO_PH14 || gpio == GPIO_PH15 - || gpio == GPIO_PJ14 || gpio == GPIO_PJ15) - return -EINVAL; -#endif - if (gpio >= MAX_BLACKFIN_GPIOS) - return -EINVAL; - return 0; -} - static void gpio_error(unsigned gpio) { printk(KERN_ERR "bfin-gpio: GPIO %d wasn't requested!\n", gpio); @@ -167,6 +141,23 @@ static int cmp_label(unsigned short ident, const char *label) return -EINVAL; } +#define map_entry(m, i) reserved_##m##_map[gpio_bank(i)] +#define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i)) +#define reserve(m, i) (map_entry(m, i) |= gpio_bit(i)) +#define unreserve(m, i) (map_entry(m, i) &= ~gpio_bit(i)) +#define DECLARE_RESERVED_MAP(m, c) static unsigned short reserved_##m##_map[c] + +DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM); +DECLARE_RESERVED_MAP(peri, DIV_ROUND_UP(MAX_RESOURCES, GPIO_BANKSIZE)); +DECLARE_RESERVED_MAP(gpio_irq, GPIO_BANK_NUM); + +inline int check_gpio(unsigned gpio) +{ + if (gpio >= MAX_BLACKFIN_GPIOS) + return -EINVAL; + return 0; +} + static void port_setup(unsigned gpio, unsigned short usage) { #if defined(BF538_FAMILY) @@ -199,117 +190,134 @@ static void port_setup(unsigned gpio, unsigned short usage) else *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); SSYNC(); -#elif defined(CONFIG_BF54x) - if (usage == GPIO_USAGE) - gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio); - else - gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio); - SSYNC(); #endif } #ifdef BF537_FAMILY -static struct { - unsigned short res; - unsigned short offset; -} port_mux_lut[] = { - {.res = P_PPI0_D13, .offset = 11}, - {.res = P_PPI0_D14, .offset = 11}, - {.res = P_PPI0_D15, .offset = 11}, - {.res = P_SPORT1_TFS, .offset = 11}, - {.res = P_SPORT1_TSCLK, .offset = 11}, - {.res = P_SPORT1_DTPRI, .offset = 11}, - {.res = P_PPI0_D10, .offset = 10}, - {.res = P_PPI0_D11, .offset = 10}, - {.res = P_PPI0_D12, .offset = 10}, - {.res = P_SPORT1_RSCLK, .offset = 10}, - {.res = P_SPORT1_RFS, .offset = 10}, - {.res = P_SPORT1_DRPRI, .offset = 10}, - {.res = P_PPI0_D8, .offset = 9}, - {.res = P_PPI0_D9, .offset = 9}, - {.res = P_SPORT1_DRSEC, .offset = 9}, - {.res = P_SPORT1_DTSEC, .offset = 9}, - {.res = P_TMR2, .offset = 8}, - {.res = P_PPI0_FS3, .offset = 8}, - {.res = P_TMR3, .offset = 7}, - {.res = P_SPI0_SSEL4, .offset = 7}, - {.res = P_TMR4, .offset = 6}, - {.res = P_SPI0_SSEL5, .offset = 6}, - {.res = P_TMR5, .offset = 5}, - {.res = P_SPI0_SSEL6, .offset = 5}, - {.res = P_UART1_RX, .offset = 4}, - {.res = P_UART1_TX, .offset = 4}, - {.res = P_TMR6, .offset = 4}, - {.res = P_TMR7, .offset = 4}, - {.res = P_UART0_RX, .offset = 3}, - {.res = P_UART0_TX, .offset = 3}, - {.res = P_DMAR0, .offset = 3}, - {.res = P_DMAR1, .offset = 3}, - {.res = P_SPORT0_DTSEC, .offset = 1}, - {.res = P_SPORT0_DRSEC, .offset = 1}, - {.res = P_CAN0_RX, .offset = 1}, - {.res = P_CAN0_TX, .offset = 1}, - {.res = P_SPI0_SSEL7, .offset = 1}, - {.res = P_SPORT0_TFS, .offset = 0}, - {.res = P_SPORT0_DTPRI, .offset = 0}, - {.res = P_SPI0_SSEL2, .offset = 0}, - {.res = P_SPI0_SSEL3, .offset = 0}, +static const s8 port_mux[] = { + [GPIO_PF0] = 3, + [GPIO_PF1] = 3, + [GPIO_PF2] = 4, + [GPIO_PF3] = 4, + [GPIO_PF4] = 5, + [GPIO_PF5] = 6, + [GPIO_PF6] = 7, + [GPIO_PF7] = 8, + [GPIO_PF8 ... GPIO_PF15] = -1, + [GPIO_PG0 ... GPIO_PG7] = -1, + [GPIO_PG8] = 9, + [GPIO_PG9] = 9, + [GPIO_PG10] = 10, + [GPIO_PG11] = 10, + [GPIO_PG12] = 10, + [GPIO_PG13] = 11, + [GPIO_PG14] = 11, + [GPIO_PG15] = 11, + [GPIO_PH0 ... GPIO_PH15] = -1, + [PORT_PJ0 ... PORT_PJ3] = -1, + [PORT_PJ4] = 1, + [PORT_PJ5] = 1, + [PORT_PJ6 ... PORT_PJ9] = -1, + [PORT_PJ10] = 0, + [PORT_PJ11] = 0, }; -static void portmux_setup(unsigned short per) +static int portmux_group_check(unsigned short per) { - u16 y, offset, muxreg; + u16 ident = P_IDENT(per); u16 function = P_FUNCT2MUX(per); + s8 offset = port_mux[ident]; + u16 m, pmux, pfunc, mask; - for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) { - if (port_mux_lut[y].res == per) { - - /* SET PORTMUX REG */ + if (offset < 0) + return 0; - offset = port_mux_lut[y].offset; - muxreg = bfin_read_PORT_MUX(); + pmux = bfin_read_PORT_MUX(); + for (m = 0; m < ARRAY_SIZE(port_mux); ++m) { + if (m == ident) + continue; + if (port_mux[m] != offset) + continue; + if (!is_reserved(peri, m, 1)) + continue; - if (offset != 1) - muxreg &= ~(1 << offset); - else - muxreg &= ~(3 << 1); + if (offset == 1) + mask = 3; + else + mask = 1; - muxreg |= (function << offset); - bfin_write_PORT_MUX(muxreg); + pfunc = (pmux >> offset) & mask; + if (pfunc != (function & mask)) { + pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n", + ident, function, m, pfunc); + return -EINVAL; } } + + return 0; } -#elif defined(CONFIG_BF54x) -inline void portmux_setup(unsigned short per) + +static void portmux_setup(unsigned short per) { - u32 pmux; u16 ident = P_IDENT(per); u16 function = P_FUNCT2MUX(per); + s8 offset = port_mux[ident]; + u16 pmux, mask; + + if (offset == -1) + return; - pmux = gpio_array[gpio_bank(ident)]->port_mux; + pmux = bfin_read_PORT_MUX(); + if (offset == 1) + mask = 3; + else + mask = 1; - pmux &= ~(0x3 << (2 * gpio_sub_n(ident))); - pmux |= (function & 0x3) << (2 * gpio_sub_n(ident)); + pmux &= ~(mask << offset); + pmux |= ((function & mask) << offset); - gpio_array[gpio_bank(ident)]->port_mux = pmux; + bfin_write_PORT_MUX(pmux); } - -inline u16 get_portmux(unsigned short per) +#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) +static int portmux_group_check(unsigned short per) { - u32 pmux; u16 ident = P_IDENT(per); + u16 function = P_FUNCT2MUX(per); + u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; + u16 pin, gpiopin, pfunc; - pmux = gpio_array[gpio_bank(ident)]->port_mux; + for (pin = 0; pin < GPIO_BANKSIZE; ++pin) { + if (offset != pmux_offset[gpio_bank(ident)][pin]) + continue; + + gpiopin = gpio_bank(ident) * GPIO_BANKSIZE + pin; + if (gpiopin == ident) + continue; + if (!is_reserved(peri, gpiopin, 1)) + continue; - return (pmux >> (2 * gpio_sub_n(ident)) & 0x3); + pfunc = *port_mux[gpio_bank(ident)]; + pfunc = (pfunc >> offset) & 3; + if (pfunc != function) { + pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n", + ident, function, gpiopin, pfunc); + return -EINVAL; + } + } + + return 0; } -#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) + inline void portmux_setup(unsigned short per) { - u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per); + u16 ident = P_IDENT(per); + u16 function = P_FUNCT2MUX(per); u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; + u16 pmux; pmux = *port_mux[gpio_bank(ident)]; + if (((pmux >> offset) & 3) == function) + return; pmux &= ~(3 << offset); pmux |= (function & 3) << offset; *port_mux[gpio_bank(ident)] = pmux; @@ -317,9 +325,12 @@ inline void portmux_setup(unsigned short per) } #else # define portmux_setup(...) do { } while (0) +static int portmux_group_check(unsigned short per) +{ + return 0; +} #endif -#ifndef CONFIG_BF54x /*********************************************************** * * FUNCTIONS: Blackfin General Purpose Ports Access Functions @@ -343,13 +354,13 @@ inline void portmux_setup(unsigned short per) void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ { \ unsigned long flags; \ - local_irq_save_hw(flags); \ + flags = hard_local_irq_save(); \ if (arg) \ gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ else \ gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \ AWA_DUMMY_READ(name); \ - local_irq_restore_hw(flags); \ + hard_local_irq_restore(flags); \ } \ EXPORT_SYMBOL(set_gpio_ ## name); @@ -365,14 +376,14 @@ void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ { \ unsigned long flags; \ if (ANOMALY_05000311 || ANOMALY_05000323) \ - local_irq_save_hw(flags); \ + flags = hard_local_irq_save(); \ if (arg) \ gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ else \ gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ if (ANOMALY_05000311 || ANOMALY_05000323) { \ AWA_DUMMY_READ(name); \ - local_irq_restore_hw(flags); \ + hard_local_irq_restore(flags); \ } \ } \ EXPORT_SYMBOL(set_gpio_ ## name); @@ -385,11 +396,11 @@ void set_gpio_toggle(unsigned gpio) { unsigned long flags; if (ANOMALY_05000311 || ANOMALY_05000323) - local_irq_save_hw(flags); + flags = hard_local_irq_save(); gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio); if (ANOMALY_05000311 || ANOMALY_05000323) { AWA_DUMMY_READ(toggle); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); } } EXPORT_SYMBOL(set_gpio_toggle); @@ -402,11 +413,11 @@ void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \ { \ unsigned long flags; \ if (ANOMALY_05000311 || ANOMALY_05000323) \ - local_irq_save_hw(flags); \ + flags = hard_local_irq_save(); \ gpio_array[gpio_bank(gpio)]->name = arg; \ if (ANOMALY_05000311 || ANOMALY_05000323) { \ AWA_DUMMY_READ(name); \ - local_irq_restore_hw(flags); \ + hard_local_irq_restore(flags); \ } \ } \ EXPORT_SYMBOL(set_gpiop_ ## name); @@ -427,11 +438,11 @@ unsigned short get_gpio_ ## name(unsigned gpio) \ unsigned long flags; \ unsigned short ret; \ if (ANOMALY_05000311 || ANOMALY_05000323) \ - local_irq_save_hw(flags); \ + flags = hard_local_irq_save(); \ ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \ if (ANOMALY_05000311 || ANOMALY_05000323) { \ AWA_DUMMY_READ(name); \ - local_irq_restore_hw(flags); \ + hard_local_irq_restore(flags); \ } \ return ret; \ } \ @@ -454,11 +465,11 @@ unsigned short get_gpiop_ ## name(unsigned gpio) \ unsigned long flags; \ unsigned short ret; \ if (ANOMALY_05000311 || ANOMALY_05000323) \ - local_irq_save_hw(flags); \ + flags = hard_local_irq_save(); \ ret = (gpio_array[gpio_bank(gpio)]->name); \ if (ANOMALY_05000311 || ANOMALY_05000323) { \ AWA_DUMMY_READ(name); \ - local_irq_restore_hw(flags); \ + hard_local_irq_restore(flags); \ } \ return ret; \ } \ @@ -475,15 +486,13 @@ GET_GPIO_P(maskb) #ifdef CONFIG_PM - -static unsigned short wakeup_map[GPIO_BANK_NUM]; -static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS]; +DECLARE_RESERVED_MAP(wakeup, GPIO_BANK_NUM); static const unsigned int sic_iwr_irqs[] = { #if defined(BF533_FAMILY) IRQ_PROG_INTB #elif defined(BF537_FAMILY) - IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX + IRQ_PF_INTB_WATCH, IRQ_PORTG_INTB, IRQ_PH_INTB_MAC_TX #elif defined(BF538_FAMILY) IRQ_PORTF_INTB #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) @@ -514,143 +523,48 @@ static const unsigned int sic_iwr_irqs[] = { ************************************************************* * MODIFICATION HISTORY : **************************************************************/ -int gpio_pm_wakeup_request(unsigned gpio, unsigned char type) -{ - unsigned long flags; - - if ((check_gpio(gpio) < 0) || !type) - return -EINVAL; - - local_irq_save_hw(flags); - wakeup_map[gpio_bank(gpio)] |= gpio_bit(gpio); - wakeup_flags_map[gpio] = type; - local_irq_restore_hw(flags); - - return 0; -} -EXPORT_SYMBOL(gpio_pm_wakeup_request); - -void gpio_pm_wakeup_free(unsigned gpio) +int bfin_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl) { unsigned long flags; if (check_gpio(gpio) < 0) - return; - - local_irq_save_hw(flags); - - wakeup_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); - - local_irq_restore_hw(flags); -} -EXPORT_SYMBOL(gpio_pm_wakeup_free); - -static int bfin_gpio_wakeup_type(unsigned gpio, unsigned char type) -{ - port_setup(gpio, GPIO_USAGE); - set_gpio_dir(gpio, 0); - set_gpio_inen(gpio, 1); - - if (type & (PM_WAKE_RISING | PM_WAKE_FALLING)) - set_gpio_edge(gpio, 1); - else - set_gpio_edge(gpio, 0); - - if ((type & (PM_WAKE_BOTH_EDGES)) == (PM_WAKE_BOTH_EDGES)) - set_gpio_both(gpio, 1); - else - set_gpio_both(gpio, 0); + return -EINVAL; - if ((type & (PM_WAKE_FALLING | PM_WAKE_LOW))) - set_gpio_polar(gpio, 1); + flags = hard_local_irq_save(); + if (ctrl) + reserve(wakeup, gpio); else - set_gpio_polar(gpio, 0); - - SSYNC(); + unreserve(wakeup, gpio); - return 0; -} - -u32 bfin_pm_standby_setup(void) -{ - u16 bank, mask, i, gpio; - - for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { - mask = wakeup_map[gpio_bank(i)]; - bank = gpio_bank(i); - - gpio_bank_saved[bank].maskb = gpio_array[bank]->maskb; - gpio_array[bank]->maskb = 0; - - if (mask) { -#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) - gpio_bank_saved[bank].fer = *port_fer[bank]; -#endif - gpio_bank_saved[bank].inen = gpio_array[bank]->inen; - gpio_bank_saved[bank].polar = gpio_array[bank]->polar; - gpio_bank_saved[bank].dir = gpio_array[bank]->dir; - gpio_bank_saved[bank].edge = gpio_array[bank]->edge; - gpio_bank_saved[bank].both = gpio_array[bank]->both; - gpio_bank_saved[bank].reserved = - reserved_gpio_map[bank]; - - gpio = i; - - while (mask) { - if ((mask & 1) && (wakeup_flags_map[gpio] != - PM_WAKE_IGNORE)) { - reserved_gpio_map[gpio_bank(gpio)] |= - gpio_bit(gpio); - bfin_gpio_wakeup_type(gpio, - wakeup_flags_map[gpio]); - set_gpio_data(gpio, 0); /*Clear*/ - } - gpio++; - mask >>= 1; - } - - bfin_internal_set_wake(sic_iwr_irqs[bank], 1); - gpio_array[bank]->maskb_set = wakeup_map[gpio_bank(i)]; - } - } - - AWA_DUMMY_READ(maskb_set); + set_gpio_maskb(gpio, ctrl); + hard_local_irq_restore(flags); return 0; } -void bfin_pm_standby_restore(void) +int bfin_gpio_pm_standby_ctrl(unsigned ctrl) { u16 bank, mask, i; for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { - mask = wakeup_map[gpio_bank(i)]; + mask = map_entry(wakeup, i); bank = gpio_bank(i); - if (mask) { -#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) - *port_fer[bank] = gpio_bank_saved[bank].fer; -#endif - gpio_array[bank]->inen = gpio_bank_saved[bank].inen; - gpio_array[bank]->dir = gpio_bank_saved[bank].dir; - gpio_array[bank]->polar = gpio_bank_saved[bank].polar; - gpio_array[bank]->edge = gpio_bank_saved[bank].edge; - gpio_array[bank]->both = gpio_bank_saved[bank].both; - - reserved_gpio_map[bank] = - gpio_bank_saved[bank].reserved; - bfin_internal_set_wake(sic_iwr_irqs[bank], 0); - } - - gpio_array[bank]->maskb = gpio_bank_saved[bank].maskb; + if (mask) + bfin_internal_set_wake(sic_iwr_irqs[bank], ctrl); } - AWA_DUMMY_READ(maskb); + return 0; } void bfin_gpio_pm_hibernate_suspend(void) { int i, bank; +#ifdef BF538_FAMILY + for (i = 0; i < ARRAY_SIZE(port_fer_saved); ++i) + port_fer_saved[i] = *port_fer[i]; +#endif + for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { bank = gpio_bank(i); @@ -672,6 +586,10 @@ void bfin_gpio_pm_hibernate_suspend(void) gpio_bank_saved[bank].maska = gpio_array[bank]->maska; } +#ifdef BFIN_SPECIAL_GPIO_BANKS + bfin_special_gpio_pm_hibernate_suspend(); +#endif + AWA_DUMMY_READ(maska); } @@ -679,6 +597,11 @@ void bfin_gpio_pm_hibernate_restore(void) { int i, bank; +#ifdef BF538_FAMILY + for (i = 0; i < ARRAY_SIZE(port_fer_saved); ++i) + *port_fer[i] = port_fer_saved[i]; +#endif + for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { bank = gpio_bank(i); @@ -700,67 +623,20 @@ void bfin_gpio_pm_hibernate_restore(void) gpio_array[bank]->both = gpio_bank_saved[bank].both; gpio_array[bank]->maska = gpio_bank_saved[bank].maska; } - AWA_DUMMY_READ(maska); -} - +#ifdef BFIN_SPECIAL_GPIO_BANKS + bfin_special_gpio_pm_hibernate_restore(); #endif -#else /* CONFIG_BF54x */ -#ifdef CONFIG_PM - -u32 bfin_pm_standby_setup(void) -{ - return 0; -} - -void bfin_pm_standby_restore(void) -{ - -} - -void bfin_gpio_pm_hibernate_suspend(void) -{ - int i, bank; - for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { - bank = gpio_bank(i); - - gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer; - gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux; - gpio_bank_saved[bank].data = gpio_array[bank]->data; - gpio_bank_saved[bank].inen = gpio_array[bank]->inen; - gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set; - } + AWA_DUMMY_READ(maska); } -void bfin_gpio_pm_hibernate_restore(void) -{ - int i, bank; - - for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { - bank = gpio_bank(i); - gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux; - gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer; - gpio_array[bank]->inen = gpio_bank_saved[bank].inen; - gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir; - gpio_array[bank]->data_set = gpio_bank_saved[bank].data - | gpio_bank_saved[bank].dir; - } -} #endif -unsigned short get_gpio_dir(unsigned gpio) -{ - return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio))); -} -EXPORT_SYMBOL(get_gpio_dir); - -#endif /* CONFIG_BF54x */ - /*********************************************************** * -* FUNCTIONS: Blackfin Peripheral Resource Allocation +* FUNCTIONS: Blackfin Peripheral Resource Allocation * and PortMux Setup * * INPUTS/OUTPUTS: @@ -791,34 +667,29 @@ int peripheral_request(unsigned short per, const char *label) BUG_ON(ident >= MAX_RESOURCES); - local_irq_save_hw(flags); + flags = hard_local_irq_save(); /* If a pin can be muxed as either GPIO or peripheral, make * sure it is not already a GPIO pin when we request it. */ - if (unlikely(!check_gpio(ident) && - reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) { + if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) { if (system_state == SYSTEM_BOOTING) dump_stack(); printk(KERN_ERR "%s: Peripheral %d is already reserved as GPIO by %s !\n", __func__, ident, get_label(ident)); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); return -EBUSY; } - if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) { + if (unlikely(is_reserved(peri, ident, 1))) { /* * Pin functions like AMC address strobes my * be requested and used by several drivers */ -#ifdef CONFIG_BF54x - if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) { -#else if (!(per & P_MAYSHARE)) { -#endif /* * Allow that the identical pin function can * be requested from the same driver twice @@ -832,18 +703,22 @@ int peripheral_request(unsigned short per, const char *label) printk(KERN_ERR "%s: Peripheral %d function %d is already reserved by %s !\n", __func__, ident, P_FUNCT2MUX(per), get_label(ident)); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); return -EBUSY; } } + if (unlikely(portmux_group_check(per))) { + hard_local_irq_restore(flags); + return -EBUSY; + } anyway: - reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident); + reserve(peri, ident); portmux_setup(per); port_setup(ident, PERIPHERAL_USAGE); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); set_label(ident, label); return 0; @@ -882,21 +757,21 @@ void peripheral_free(unsigned short per) if (!(per & P_DEFINED)) return; - local_irq_save_hw(flags); + flags = hard_local_irq_save(); - if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) { - local_irq_restore_hw(flags); + if (unlikely(!is_reserved(peri, ident, 0))) { + hard_local_irq_restore(flags); return; } if (!(per & P_MAYSHARE)) port_setup(ident, GPIO_USAGE); - reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident); + unreserve(peri, ident); set_label(ident, "free"); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); } EXPORT_SYMBOL(peripheral_free); @@ -930,7 +805,7 @@ int bfin_gpio_request(unsigned gpio, const char *label) if (check_gpio(gpio) < 0) return -EINVAL; - local_irq_save_hw(flags); + flags = hard_local_irq_save(); /* * Allow that the identical GPIO can @@ -939,41 +814,38 @@ int bfin_gpio_request(unsigned gpio, const char *label) */ if (cmp_label(gpio, label) == 0) { - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); return 0; } - if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { + if (unlikely(is_reserved(gpio, gpio, 1))) { if (system_state == SYSTEM_BOOTING) dump_stack(); printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n", gpio, get_label(gpio)); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); return -EBUSY; } - if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) { + if (unlikely(is_reserved(peri, gpio, 1))) { if (system_state == SYSTEM_BOOTING) dump_stack(); printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", gpio, get_label(gpio)); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); return -EBUSY; } - if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) { + if (unlikely(is_reserved(gpio_irq, gpio, 1))) { printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!" " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio); - } -#ifndef CONFIG_BF54x - else { /* Reset POLAR setting when acquiring a gpio for the first time */ + } else { /* Reset POLAR setting when acquiring a gpio for the first time */ set_gpio_polar(gpio, 0); } -#endif - reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); + reserve(gpio, gpio); set_label(gpio, label); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); port_setup(gpio, GPIO_USAGE); @@ -990,32 +862,32 @@ void bfin_gpio_free(unsigned gpio) might_sleep(); - local_irq_save_hw(flags); + flags = hard_local_irq_save(); - if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { + if (unlikely(!is_reserved(gpio, gpio, 0))) { if (system_state == SYSTEM_BOOTING) dump_stack(); gpio_error(gpio); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); return; } - reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); + unreserve(gpio, gpio); set_label(gpio, "free"); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); } EXPORT_SYMBOL(bfin_gpio_free); #ifdef BFIN_SPECIAL_GPIO_BANKS -static unsigned short reserved_special_gpio_map[gpio_bank(MAX_RESOURCES)]; +DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES)); int bfin_special_gpio_request(unsigned gpio, const char *label) { unsigned long flags; - local_irq_save_hw(flags); + flags = hard_local_irq_save(); /* * Allow that the identical GPIO can @@ -1024,19 +896,19 @@ int bfin_special_gpio_request(unsigned gpio, const char *label) */ if (cmp_label(gpio, label) == 0) { - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); return 0; } - if (unlikely(reserved_special_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { - local_irq_restore_hw(flags); + if (unlikely(is_reserved(special_gpio, gpio, 1))) { + hard_local_irq_restore(flags); printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n", gpio, get_label(gpio)); return -EBUSY; } - if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) { - local_irq_restore_hw(flags); + if (unlikely(is_reserved(peri, gpio, 1))) { + hard_local_irq_restore(flags); printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", gpio, get_label(gpio)); @@ -1044,11 +916,11 @@ int bfin_special_gpio_request(unsigned gpio, const char *label) return -EBUSY; } - reserved_special_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); - reserved_peri_map[gpio_bank(gpio)] |= gpio_bit(gpio); + reserve(special_gpio, gpio); + reserve(peri, gpio); set_label(gpio, label); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); port_setup(gpio, GPIO_USAGE); return 0; @@ -1061,18 +933,18 @@ void bfin_special_gpio_free(unsigned gpio) might_sleep(); - local_irq_save_hw(flags); + flags = hard_local_irq_save(); - if (unlikely(!(reserved_special_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { + if (unlikely(!is_reserved(special_gpio, gpio, 0))) { gpio_error(gpio); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); return; } - reserved_special_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); - reserved_peri_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); + unreserve(special_gpio, gpio); + unreserve(peri, gpio); set_label(gpio, "free"); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); } EXPORT_SYMBOL(bfin_special_gpio_free); #endif @@ -1085,26 +957,26 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label) if (check_gpio(gpio) < 0) return -EINVAL; - local_irq_save_hw(flags); + flags = hard_local_irq_save(); - if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) { + if (unlikely(is_reserved(peri, gpio, 1))) { if (system_state == SYSTEM_BOOTING) dump_stack(); printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", gpio, get_label(gpio)); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); return -EBUSY; } - if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) + if (unlikely(is_reserved(gpio, gpio, 1))) printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved by %s! " "(Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio, get_label(gpio)); - reserved_gpio_irq_map[gpio_bank(gpio)] |= gpio_bit(gpio); + reserve(gpio_irq, gpio); set_label(gpio, label); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); port_setup(gpio, GPIO_USAGE); @@ -1118,30 +990,26 @@ void bfin_gpio_irq_free(unsigned gpio) if (check_gpio(gpio) < 0) return; - local_irq_save_hw(flags); + flags = hard_local_irq_save(); - if (unlikely(!(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { + if (unlikely(!is_reserved(gpio_irq, gpio, 0))) { if (system_state == SYSTEM_BOOTING) dump_stack(); gpio_error(gpio); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); return; } - reserved_gpio_irq_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); + unreserve(gpio_irq, gpio); set_label(gpio, "free"); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); } static inline void __bfin_gpio_direction_input(unsigned gpio) { -#ifdef CONFIG_BF54x - gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio); -#else gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); -#endif gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio); } @@ -1149,15 +1017,15 @@ int bfin_gpio_direction_input(unsigned gpio) { unsigned long flags; - if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { + if (unlikely(!is_reserved(gpio, gpio, 0))) { gpio_error(gpio); return -EINVAL; } - local_irq_save_hw(flags); + flags = hard_local_irq_save(); __bfin_gpio_direction_input(gpio); AWA_DUMMY_READ(inen); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); return 0; } @@ -1165,17 +1033,7 @@ EXPORT_SYMBOL(bfin_gpio_direction_input); void bfin_gpio_irq_prepare(unsigned gpio) { -#ifdef CONFIG_BF54x - unsigned long flags; -#endif - port_setup(gpio, GPIO_USAGE); - -#ifdef CONFIG_BF54x - local_irq_save_hw(flags); - __bfin_gpio_direction_input(gpio); - local_irq_restore_hw(flags); -#endif } void bfin_gpio_set_value(unsigned gpio, int arg) @@ -1191,23 +1049,19 @@ int bfin_gpio_direction_output(unsigned gpio, int value) { unsigned long flags; - if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { + if (unlikely(!is_reserved(gpio, gpio, 0))) { gpio_error(gpio); return -EINVAL; } - local_irq_save_hw(flags); + flags = hard_local_irq_save(); gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); gpio_set_value(gpio, value); -#ifdef CONFIG_BF54x - gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio); -#else gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio); -#endif AWA_DUMMY_READ(dir); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); return 0; } @@ -1215,22 +1069,18 @@ EXPORT_SYMBOL(bfin_gpio_direction_output); int bfin_gpio_get_value(unsigned gpio) { -#ifdef CONFIG_BF54x - return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio))); -#else unsigned long flags; if (unlikely(get_gpio_edge(gpio))) { int ret; - local_irq_save_hw(flags); + flags = hard_local_irq_save(); set_gpio_edge(gpio, 0); ret = get_gpio_data(gpio); set_gpio_edge(gpio, 1); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); return ret; } else return get_gpio_data(gpio); -#endif } EXPORT_SYMBOL(bfin_gpio_get_value); @@ -1254,36 +1104,44 @@ void bfin_reset_boot_spi_cs(unsigned short pin) } #if defined(CONFIG_PROC_FS) -static int gpio_proc_read(char *buf, char **start, off_t offset, - int len, int *unused_i, void *unused_v) +static int gpio_proc_show(struct seq_file *m, void *v) { - int c, irq, gpio, outlen = 0; + int c, irq, gpio; for (c = 0; c < MAX_RESOURCES; c++) { - irq = reserved_gpio_irq_map[gpio_bank(c)] & gpio_bit(c); - gpio = reserved_gpio_map[gpio_bank(c)] & gpio_bit(c); + irq = is_reserved(gpio_irq, c, 1); + gpio = is_reserved(gpio, c, 1); if (!check_gpio(c) && (gpio || irq)) - len = sprintf(buf, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c, + seq_printf(m, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c, get_label(c), (gpio && irq) ? " *" : "", get_gpio_dir(c) ? "OUTPUT" : "INPUT"); - else if (reserved_peri_map[gpio_bank(c)] & gpio_bit(c)) - len = sprintf(buf, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c)); + else if (is_reserved(peri, c, 1)) + seq_printf(m, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c)); else continue; - buf += len; - outlen += len; } - return outlen; + + return 0; } +static int gpio_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, gpio_proc_show, NULL); +} + +static const struct file_operations gpio_proc_ops = { + .open = gpio_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static __init int gpio_register_proc(void) { struct proc_dir_entry *proc_gpio; - proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL); - if (proc_gpio) - proc_gpio->read_proc = gpio_proc_read; - return proc_gpio != NULL; + proc_gpio = proc_create("gpio", 0, NULL, &gpio_proc_ops); + return proc_gpio == NULL; } __initcall(gpio_register_proc); #endif |
