/* * GPIO Abstraction Layer * * Copyright 2006-2010 Analog Devices Inc. * * Licensed under the GPL-2 or later */ #include #include #include #include #include #include #include #include #include #include #if ANOMALY_05000311 || ANOMALY_05000323 enum { AWA_data = SYSCR, AWA_data_clear = SYSCR, AWA_data_set = SYSCR, AWA_toggle = SYSCR, AWA_maska = BFIN_UART_SCR, AWA_maska_clear = BFIN_UART_SCR, AWA_maska_set = BFIN_UART_SCR, AWA_maska_toggle = BFIN_UART_SCR, AWA_maskb = BFIN_UART_GCTL, AWA_maskb_clear = BFIN_UART_GCTL, AWA_maskb_set = BFIN_UART_GCTL, AWA_maskb_toggle = BFIN_UART_GCTL, AWA_dir = SPORT1_STAT, AWA_polar = SPORT1_STAT, AWA_edge = SPORT1_STAT, AWA_both = SPORT1_STAT, #if ANOMALY_05000311 AWA_inen = TIMER_ENABLE, #elif ANOMALY_05000323 AWA_inen = DMA1_1_CONFIG, #endif }; /* Anomaly Workaround */ #define AWA_DUMMY_READ(name) bfin_read16(AWA_ ## name) #else #define AWA_DUMMY_READ(...) do { } while (0) #endif static struct gpio_port_t * const gpio_array[] = { #if defined(BF533_FAMILY) || defined(BF538_FAMILY) (struct gpio_port_t *) FIO_FLAG_D, #elif defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) (struct gpio_port_t *) PORTFIO, (struct gpio_port_t *) PORTGIO, (struct gpio_port_t *) PORTHIO, #elif defined(BF561_FAMILY) (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) || defined(CONFIG_BF60x) (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, # if defined(CONFIG_BF54x) (struct gpio_port_t *)PORTH_FER, (struct gpio_port_t *)PORTI_FER, (struct gpio_port_t *)PORTJ_FER, # endif #else # error no gpio arrays defined #endif }; #if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) static unsigned short * const port_fer[] = { (unsigned short *) PORTF_FER, (unsigned short *) PORTG_FER, (unsigned short *) PORTH_FER, }; # if !defined(BF537_FAMILY) static unsigned short * const port_mux[] = { (unsigned short *) PORTF_MUX, (unsigned short *) PORTG_MUX, (unsigned short *) PORTH_MUX, }; static const u8 pmux_offset[][16] = { # if defined(CONFIG_BF52x) { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */ { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */ { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */ # elif defined(CONFIG_BF51x) { 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */ { 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */ { 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */ # endif }; # endif #elif defined(BF538_FAMILY) static unsigned short * const port_fer[] = { (unsigned short *) PORTCIO_FER, (unsigned short *) PORTDIO_FER, (unsigned short *) PORTEIO_FER, }; #endif #define RESOURCE_LABEL_SIZE 16 static struct str_ident { char name[RESOURCE_LABEL_SIZE]; } str_ident[MAX_RESOURCES]; #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 static void gpio_error(unsigned gpio) { printk(KERN_ERR "bfin-gpio: GPIO %d wasn't requested!\n", gpio); } static void set_label(unsigned short ident, const char *label) { if (label) { strncpy(str_ident[ident].name, label, RESOURCE_LABEL_SIZE); str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0; } } static char *get_label(unsigned short ident) { return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN"); } static int cmp_label(unsigned short ident, const char *label) { if (label == NULL) { dump_stack(); printk(KERN_ERR "Please provide none-null label\n"); } if (label) return strcmp(str_ident[ident].name, label); else 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 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 port_setup(unsigned gpio, unsigned short usage) { #if defined(BF538_FAMILY) /* * BF538/9 Port C,D and E are special. * Inverted PORT_FER polarity on CDE and no PORF_FER on F * Regular PORT F GPIOs are handled here, CDE are exclusively * managed by GPIOLIB */ if (gpio < MAX_BLACKFIN_GPIOS || gpio >= MAX_RESOURCES) return; gpio -= MAX_BLACKFIN_GPIOS; if (usage == GPIO_USAGE) *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); else *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); SSYNC(); return; #endif if (check_gpio(gpio)) return; #if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) if (usage == GPIO_USAGE) *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); else *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); SSYNC(); #elif defined(CONFIG_BF54x) || defined(CONFIG_BF60x) 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 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,