Path: blob/master/arch/blackfin/kernel/bfin_gpio.c
10817 views
/*1* GPIO Abstraction Layer2*3* Copyright 2006-2010 Analog Devices Inc.4*5* Licensed under the GPL-2 or later6*/78#include <linux/delay.h>9#include <linux/module.h>10#include <linux/err.h>11#include <linux/proc_fs.h>12#include <linux/seq_file.h>13#include <asm/blackfin.h>14#include <asm/gpio.h>15#include <asm/portmux.h>16#include <linux/irq.h>17#include <asm/irq_handler.h>1819#if ANOMALY_05000311 || ANOMALY_0500032320enum {21AWA_data = SYSCR,22AWA_data_clear = SYSCR,23AWA_data_set = SYSCR,24AWA_toggle = SYSCR,25AWA_maska = BFIN_UART_SCR,26AWA_maska_clear = BFIN_UART_SCR,27AWA_maska_set = BFIN_UART_SCR,28AWA_maska_toggle = BFIN_UART_SCR,29AWA_maskb = BFIN_UART_GCTL,30AWA_maskb_clear = BFIN_UART_GCTL,31AWA_maskb_set = BFIN_UART_GCTL,32AWA_maskb_toggle = BFIN_UART_GCTL,33AWA_dir = SPORT1_STAT,34AWA_polar = SPORT1_STAT,35AWA_edge = SPORT1_STAT,36AWA_both = SPORT1_STAT,37#if ANOMALY_0500031138AWA_inen = TIMER_ENABLE,39#elif ANOMALY_0500032340AWA_inen = DMA1_1_CONFIG,41#endif42};43/* Anomaly Workaround */44#define AWA_DUMMY_READ(name) bfin_read16(AWA_ ## name)45#else46#define AWA_DUMMY_READ(...) do { } while (0)47#endif4849static struct gpio_port_t * const gpio_array[] = {50#if defined(BF533_FAMILY) || defined(BF538_FAMILY)51(struct gpio_port_t *) FIO_FLAG_D,52#elif defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)53(struct gpio_port_t *) PORTFIO,54(struct gpio_port_t *) PORTGIO,55(struct gpio_port_t *) PORTHIO,56#elif defined(BF561_FAMILY)57(struct gpio_port_t *) FIO0_FLAG_D,58(struct gpio_port_t *) FIO1_FLAG_D,59(struct gpio_port_t *) FIO2_FLAG_D,60#elif defined(CONFIG_BF54x)61(struct gpio_port_t *)PORTA_FER,62(struct gpio_port_t *)PORTB_FER,63(struct gpio_port_t *)PORTC_FER,64(struct gpio_port_t *)PORTD_FER,65(struct gpio_port_t *)PORTE_FER,66(struct gpio_port_t *)PORTF_FER,67(struct gpio_port_t *)PORTG_FER,68(struct gpio_port_t *)PORTH_FER,69(struct gpio_port_t *)PORTI_FER,70(struct gpio_port_t *)PORTJ_FER,71#else72# error no gpio arrays defined73#endif74};7576#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)77static unsigned short * const port_fer[] = {78(unsigned short *) PORTF_FER,79(unsigned short *) PORTG_FER,80(unsigned short *) PORTH_FER,81};8283# if !defined(BF537_FAMILY)84static unsigned short * const port_mux[] = {85(unsigned short *) PORTF_MUX,86(unsigned short *) PORTG_MUX,87(unsigned short *) PORTH_MUX,88};8990static const91u8 pmux_offset[][16] = {92# if defined(CONFIG_BF52x)93{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */94{ 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */95{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */96# elif defined(CONFIG_BF51x)97{ 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */98{ 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */99{ 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */100# endif101};102# endif103104#elif defined(BF538_FAMILY)105static unsigned short * const port_fer[] = {106(unsigned short *) PORTCIO_FER,107(unsigned short *) PORTDIO_FER,108(unsigned short *) PORTEIO_FER,109};110#endif111112#define RESOURCE_LABEL_SIZE 16113114static struct str_ident {115char name[RESOURCE_LABEL_SIZE];116} str_ident[MAX_RESOURCES];117118#if defined(CONFIG_PM)119static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM];120#endif121122static void gpio_error(unsigned gpio)123{124printk(KERN_ERR "bfin-gpio: GPIO %d wasn't requested!\n", gpio);125}126127static void set_label(unsigned short ident, const char *label)128{129if (label) {130strncpy(str_ident[ident].name, label,131RESOURCE_LABEL_SIZE);132str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0;133}134}135136static char *get_label(unsigned short ident)137{138return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN");139}140141static int cmp_label(unsigned short ident, const char *label)142{143if (label == NULL) {144dump_stack();145printk(KERN_ERR "Please provide none-null label\n");146}147148if (label)149return strcmp(str_ident[ident].name, label);150else151return -EINVAL;152}153154#define map_entry(m, i) reserved_##m##_map[gpio_bank(i)]155#define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i))156#define reserve(m, i) (map_entry(m, i) |= gpio_bit(i))157#define unreserve(m, i) (map_entry(m, i) &= ~gpio_bit(i))158#define DECLARE_RESERVED_MAP(m, c) static unsigned short reserved_##m##_map[c]159160DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM);161DECLARE_RESERVED_MAP(peri, DIV_ROUND_UP(MAX_RESOURCES, GPIO_BANKSIZE));162DECLARE_RESERVED_MAP(gpio_irq, GPIO_BANK_NUM);163164inline int check_gpio(unsigned gpio)165{166#if defined(CONFIG_BF54x)167if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15168|| gpio == GPIO_PH14 || gpio == GPIO_PH15169|| gpio == GPIO_PJ14 || gpio == GPIO_PJ15)170return -EINVAL;171#endif172if (gpio >= MAX_BLACKFIN_GPIOS)173return -EINVAL;174return 0;175}176177static void port_setup(unsigned gpio, unsigned short usage)178{179#if defined(BF538_FAMILY)180/*181* BF538/9 Port C,D and E are special.182* Inverted PORT_FER polarity on CDE and no PORF_FER on F183* Regular PORT F GPIOs are handled here, CDE are exclusively184* managed by GPIOLIB185*/186187if (gpio < MAX_BLACKFIN_GPIOS || gpio >= MAX_RESOURCES)188return;189190gpio -= MAX_BLACKFIN_GPIOS;191192if (usage == GPIO_USAGE)193*port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);194else195*port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);196SSYNC();197return;198#endif199200if (check_gpio(gpio))201return;202203#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)204if (usage == GPIO_USAGE)205*port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);206else207*port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);208SSYNC();209#elif defined(CONFIG_BF54x)210if (usage == GPIO_USAGE)211gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);212else213gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);214SSYNC();215#endif216}217218#ifdef BF537_FAMILY219static const s8 port_mux[] = {220[GPIO_PF0] = 3,221[GPIO_PF1] = 3,222[GPIO_PF2] = 4,223[GPIO_PF3] = 4,224[GPIO_PF4] = 5,225[GPIO_PF5] = 6,226[GPIO_PF6] = 7,227[GPIO_PF7] = 8,228[GPIO_PF8 ... GPIO_PF15] = -1,229[GPIO_PG0 ... GPIO_PG7] = -1,230[GPIO_PG8] = 9,231[GPIO_PG9] = 9,232[GPIO_PG10] = 10,233[GPIO_PG11] = 10,234[GPIO_PG12] = 10,235[GPIO_PG13] = 11,236[GPIO_PG14] = 11,237[GPIO_PG15] = 11,238[GPIO_PH0 ... GPIO_PH15] = -1,239[PORT_PJ0 ... PORT_PJ3] = -1,240[PORT_PJ4] = 1,241[PORT_PJ5] = 1,242[PORT_PJ6 ... PORT_PJ9] = -1,243[PORT_PJ10] = 0,244[PORT_PJ11] = 0,245};246247static int portmux_group_check(unsigned short per)248{249u16 ident = P_IDENT(per);250u16 function = P_FUNCT2MUX(per);251s8 offset = port_mux[ident];252u16 m, pmux, pfunc;253254if (offset < 0)255return 0;256257pmux = bfin_read_PORT_MUX();258for (m = 0; m < ARRAY_SIZE(port_mux); ++m) {259if (m == ident)260continue;261if (port_mux[m] != offset)262continue;263if (!is_reserved(peri, m, 1))264continue;265266if (offset == 1)267pfunc = (pmux >> offset) & 3;268else269pfunc = (pmux >> offset) & 1;270if (pfunc != function) {271pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",272ident, function, m, pfunc);273return -EINVAL;274}275}276277return 0;278}279280static void portmux_setup(unsigned short per)281{282u16 ident = P_IDENT(per);283u16 function = P_FUNCT2MUX(per);284s8 offset = port_mux[ident];285u16 pmux;286287if (offset == -1)288return;289290pmux = bfin_read_PORT_MUX();291if (offset != 1)292pmux &= ~(1 << offset);293else294pmux &= ~(3 << 1);295pmux |= (function << offset);296bfin_write_PORT_MUX(pmux);297}298#elif defined(CONFIG_BF54x)299inline void portmux_setup(unsigned short per)300{301u16 ident = P_IDENT(per);302u16 function = P_FUNCT2MUX(per);303u32 pmux;304305pmux = gpio_array[gpio_bank(ident)]->port_mux;306307pmux &= ~(0x3 << (2 * gpio_sub_n(ident)));308pmux |= (function & 0x3) << (2 * gpio_sub_n(ident));309310gpio_array[gpio_bank(ident)]->port_mux = pmux;311}312313inline u16 get_portmux(unsigned short per)314{315u16 ident = P_IDENT(per);316u32 pmux = gpio_array[gpio_bank(ident)]->port_mux;317return (pmux >> (2 * gpio_sub_n(ident)) & 0x3);318}319static int portmux_group_check(unsigned short per)320{321return 0;322}323#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)324static int portmux_group_check(unsigned short per)325{326u16 ident = P_IDENT(per);327u16 function = P_FUNCT2MUX(per);328u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];329u16 pin, gpiopin, pfunc;330331for (pin = 0; pin < GPIO_BANKSIZE; ++pin) {332if (offset != pmux_offset[gpio_bank(ident)][pin])333continue;334335gpiopin = gpio_bank(ident) * GPIO_BANKSIZE + pin;336if (gpiopin == ident)337continue;338if (!is_reserved(peri, gpiopin, 1))339continue;340341pfunc = *port_mux[gpio_bank(ident)];342pfunc = (pfunc >> offset) & 3;343if (pfunc != function) {344pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",345ident, function, gpiopin, pfunc);346return -EINVAL;347}348}349350return 0;351}352353inline void portmux_setup(unsigned short per)354{355u16 ident = P_IDENT(per);356u16 function = P_FUNCT2MUX(per);357u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];358u16 pmux;359360pmux = *port_mux[gpio_bank(ident)];361if (((pmux >> offset) & 3) == function)362return;363pmux &= ~(3 << offset);364pmux |= (function & 3) << offset;365*port_mux[gpio_bank(ident)] = pmux;366SSYNC();367}368#else369# define portmux_setup(...) do { } while (0)370static int portmux_group_check(unsigned short per)371{372return 0;373}374#endif375376#ifndef CONFIG_BF54x377/***********************************************************378*379* FUNCTIONS: Blackfin General Purpose Ports Access Functions380*381* INPUTS/OUTPUTS:382* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS383*384*385* DESCRIPTION: These functions abstract direct register access386* to Blackfin processor General Purpose387* Ports Regsiters388*389* CAUTION: These functions do not belong to the GPIO Driver API390*************************************************************391* MODIFICATION HISTORY :392**************************************************************/393394/* Set a specific bit */395396#define SET_GPIO(name) \397void set_gpio_ ## name(unsigned gpio, unsigned short arg) \398{ \399unsigned long flags; \400flags = hard_local_irq_save(); \401if (arg) \402gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \403else \404gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \405AWA_DUMMY_READ(name); \406hard_local_irq_restore(flags); \407} \408EXPORT_SYMBOL(set_gpio_ ## name);409410SET_GPIO(dir) /* set_gpio_dir() */411SET_GPIO(inen) /* set_gpio_inen() */412SET_GPIO(polar) /* set_gpio_polar() */413SET_GPIO(edge) /* set_gpio_edge() */414SET_GPIO(both) /* set_gpio_both() */415416417#define SET_GPIO_SC(name) \418void set_gpio_ ## name(unsigned gpio, unsigned short arg) \419{ \420unsigned long flags; \421if (ANOMALY_05000311 || ANOMALY_05000323) \422flags = hard_local_irq_save(); \423if (arg) \424gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \425else \426gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \427if (ANOMALY_05000311 || ANOMALY_05000323) { \428AWA_DUMMY_READ(name); \429hard_local_irq_restore(flags); \430} \431} \432EXPORT_SYMBOL(set_gpio_ ## name);433434SET_GPIO_SC(maska)435SET_GPIO_SC(maskb)436SET_GPIO_SC(data)437438void set_gpio_toggle(unsigned gpio)439{440unsigned long flags;441if (ANOMALY_05000311 || ANOMALY_05000323)442flags = hard_local_irq_save();443gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio);444if (ANOMALY_05000311 || ANOMALY_05000323) {445AWA_DUMMY_READ(toggle);446hard_local_irq_restore(flags);447}448}449EXPORT_SYMBOL(set_gpio_toggle);450451452/*Set current PORT date (16-bit word)*/453454#define SET_GPIO_P(name) \455void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \456{ \457unsigned long flags; \458if (ANOMALY_05000311 || ANOMALY_05000323) \459flags = hard_local_irq_save(); \460gpio_array[gpio_bank(gpio)]->name = arg; \461if (ANOMALY_05000311 || ANOMALY_05000323) { \462AWA_DUMMY_READ(name); \463hard_local_irq_restore(flags); \464} \465} \466EXPORT_SYMBOL(set_gpiop_ ## name);467468SET_GPIO_P(data)469SET_GPIO_P(dir)470SET_GPIO_P(inen)471SET_GPIO_P(polar)472SET_GPIO_P(edge)473SET_GPIO_P(both)474SET_GPIO_P(maska)475SET_GPIO_P(maskb)476477/* Get a specific bit */478#define GET_GPIO(name) \479unsigned short get_gpio_ ## name(unsigned gpio) \480{ \481unsigned long flags; \482unsigned short ret; \483if (ANOMALY_05000311 || ANOMALY_05000323) \484flags = hard_local_irq_save(); \485ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \486if (ANOMALY_05000311 || ANOMALY_05000323) { \487AWA_DUMMY_READ(name); \488hard_local_irq_restore(flags); \489} \490return ret; \491} \492EXPORT_SYMBOL(get_gpio_ ## name);493494GET_GPIO(data)495GET_GPIO(dir)496GET_GPIO(inen)497GET_GPIO(polar)498GET_GPIO(edge)499GET_GPIO(both)500GET_GPIO(maska)501GET_GPIO(maskb)502503/*Get current PORT date (16-bit word)*/504505#define GET_GPIO_P(name) \506unsigned short get_gpiop_ ## name(unsigned gpio) \507{ \508unsigned long flags; \509unsigned short ret; \510if (ANOMALY_05000311 || ANOMALY_05000323) \511flags = hard_local_irq_save(); \512ret = (gpio_array[gpio_bank(gpio)]->name); \513if (ANOMALY_05000311 || ANOMALY_05000323) { \514AWA_DUMMY_READ(name); \515hard_local_irq_restore(flags); \516} \517return ret; \518} \519EXPORT_SYMBOL(get_gpiop_ ## name);520521GET_GPIO_P(data)522GET_GPIO_P(dir)523GET_GPIO_P(inen)524GET_GPIO_P(polar)525GET_GPIO_P(edge)526GET_GPIO_P(both)527GET_GPIO_P(maska)528GET_GPIO_P(maskb)529530531#ifdef CONFIG_PM532DECLARE_RESERVED_MAP(wakeup, GPIO_BANK_NUM);533534static const unsigned int sic_iwr_irqs[] = {535#if defined(BF533_FAMILY)536IRQ_PROG_INTB537#elif defined(BF537_FAMILY)538IRQ_PF_INTB_WATCH, IRQ_PORTG_INTB, IRQ_PH_INTB_MAC_TX539#elif defined(BF538_FAMILY)540IRQ_PORTF_INTB541#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)542IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB543#elif defined(BF561_FAMILY)544IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB545#else546# error no SIC_IWR defined547#endif548};549550/***********************************************************551*552* FUNCTIONS: Blackfin PM Setup API553*554* INPUTS/OUTPUTS:555* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS556* type -557* PM_WAKE_RISING558* PM_WAKE_FALLING559* PM_WAKE_HIGH560* PM_WAKE_LOW561* PM_WAKE_BOTH_EDGES562*563* DESCRIPTION: Blackfin PM Driver API564*565* CAUTION:566*************************************************************567* MODIFICATION HISTORY :568**************************************************************/569int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)570{571unsigned long flags;572573if (check_gpio(gpio) < 0)574return -EINVAL;575576flags = hard_local_irq_save();577if (ctrl)578reserve(wakeup, gpio);579else580unreserve(wakeup, gpio);581582set_gpio_maskb(gpio, ctrl);583hard_local_irq_restore(flags);584585return 0;586}587588int bfin_pm_standby_ctrl(unsigned ctrl)589{590u16 bank, mask, i;591592for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {593mask = map_entry(wakeup, i);594bank = gpio_bank(i);595596if (mask)597bfin_internal_set_wake(sic_iwr_irqs[bank], ctrl);598}599return 0;600}601602void bfin_gpio_pm_hibernate_suspend(void)603{604int i, bank;605606for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {607bank = gpio_bank(i);608609#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)610gpio_bank_saved[bank].fer = *port_fer[bank];611#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)612gpio_bank_saved[bank].mux = *port_mux[bank];613#else614if (bank == 0)615gpio_bank_saved[bank].mux = bfin_read_PORT_MUX();616#endif617#endif618gpio_bank_saved[bank].data = gpio_array[bank]->data;619gpio_bank_saved[bank].inen = gpio_array[bank]->inen;620gpio_bank_saved[bank].polar = gpio_array[bank]->polar;621gpio_bank_saved[bank].dir = gpio_array[bank]->dir;622gpio_bank_saved[bank].edge = gpio_array[bank]->edge;623gpio_bank_saved[bank].both = gpio_array[bank]->both;624gpio_bank_saved[bank].maska = gpio_array[bank]->maska;625}626627AWA_DUMMY_READ(maska);628}629630void bfin_gpio_pm_hibernate_restore(void)631{632int i, bank;633634for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {635bank = gpio_bank(i);636637#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)638#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)639*port_mux[bank] = gpio_bank_saved[bank].mux;640#else641if (bank == 0)642bfin_write_PORT_MUX(gpio_bank_saved[bank].mux);643#endif644*port_fer[bank] = gpio_bank_saved[bank].fer;645#endif646gpio_array[bank]->inen = gpio_bank_saved[bank].inen;647gpio_array[bank]->data_set = gpio_bank_saved[bank].data648& gpio_bank_saved[bank].dir;649gpio_array[bank]->dir = gpio_bank_saved[bank].dir;650gpio_array[bank]->polar = gpio_bank_saved[bank].polar;651gpio_array[bank]->edge = gpio_bank_saved[bank].edge;652gpio_array[bank]->both = gpio_bank_saved[bank].both;653gpio_array[bank]->maska = gpio_bank_saved[bank].maska;654}655AWA_DUMMY_READ(maska);656}657658659#endif660#else /* CONFIG_BF54x */661#ifdef CONFIG_PM662663int bfin_pm_standby_ctrl(unsigned ctrl)664{665return 0;666}667668void bfin_gpio_pm_hibernate_suspend(void)669{670int i, bank;671672for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {673bank = gpio_bank(i);674675gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer;676gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux;677gpio_bank_saved[bank].data = gpio_array[bank]->data;678gpio_bank_saved[bank].inen = gpio_array[bank]->inen;679gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set;680}681}682683void bfin_gpio_pm_hibernate_restore(void)684{685int i, bank;686687for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {688bank = gpio_bank(i);689690gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux;691gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer;692gpio_array[bank]->inen = gpio_bank_saved[bank].inen;693gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir;694gpio_array[bank]->data_set = gpio_bank_saved[bank].data695| gpio_bank_saved[bank].dir;696}697}698#endif699700unsigned short get_gpio_dir(unsigned gpio)701{702return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio)));703}704EXPORT_SYMBOL(get_gpio_dir);705706#endif /* CONFIG_BF54x */707708/***********************************************************709*710* FUNCTIONS: Blackfin Peripheral Resource Allocation711* and PortMux Setup712*713* INPUTS/OUTPUTS:714* per Peripheral Identifier715* label String716*717* DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API718*719* CAUTION:720*************************************************************721* MODIFICATION HISTORY :722**************************************************************/723724int peripheral_request(unsigned short per, const char *label)725{726unsigned long flags;727unsigned short ident = P_IDENT(per);728729/*730* Don't cares are pins with only one dedicated function731*/732733if (per & P_DONTCARE)734return 0;735736if (!(per & P_DEFINED))737return -ENODEV;738739BUG_ON(ident >= MAX_RESOURCES);740741flags = hard_local_irq_save();742743/* If a pin can be muxed as either GPIO or peripheral, make744* sure it is not already a GPIO pin when we request it.745*/746if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) {747if (system_state == SYSTEM_BOOTING)748dump_stack();749printk(KERN_ERR750"%s: Peripheral %d is already reserved as GPIO by %s !\n",751__func__, ident, get_label(ident));752hard_local_irq_restore(flags);753return -EBUSY;754}755756if (unlikely(is_reserved(peri, ident, 1))) {757758/*759* Pin functions like AMC address strobes my760* be requested and used by several drivers761*/762763#ifdef CONFIG_BF54x764if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) {765#else766if (!(per & P_MAYSHARE)) {767#endif768/*769* Allow that the identical pin function can770* be requested from the same driver twice771*/772773if (cmp_label(ident, label) == 0)774goto anyway;775776if (system_state == SYSTEM_BOOTING)777dump_stack();778printk(KERN_ERR779"%s: Peripheral %d function %d is already reserved by %s !\n",780__func__, ident, P_FUNCT2MUX(per), get_label(ident));781hard_local_irq_restore(flags);782return -EBUSY;783}784}785786if (unlikely(portmux_group_check(per))) {787hard_local_irq_restore(flags);788return -EBUSY;789}790anyway:791reserve(peri, ident);792793portmux_setup(per);794port_setup(ident, PERIPHERAL_USAGE);795796hard_local_irq_restore(flags);797set_label(ident, label);798799return 0;800}801EXPORT_SYMBOL(peripheral_request);802803int peripheral_request_list(const unsigned short per[], const char *label)804{805u16 cnt;806int ret;807808for (cnt = 0; per[cnt] != 0; cnt++) {809810ret = peripheral_request(per[cnt], label);811812if (ret < 0) {813for ( ; cnt > 0; cnt--)814peripheral_free(per[cnt - 1]);815816return ret;817}818}819820return 0;821}822EXPORT_SYMBOL(peripheral_request_list);823824void peripheral_free(unsigned short per)825{826unsigned long flags;827unsigned short ident = P_IDENT(per);828829if (per & P_DONTCARE)830return;831832if (!(per & P_DEFINED))833return;834835flags = hard_local_irq_save();836837if (unlikely(!is_reserved(peri, ident, 0))) {838hard_local_irq_restore(flags);839return;840}841842if (!(per & P_MAYSHARE))843port_setup(ident, GPIO_USAGE);844845unreserve(peri, ident);846847set_label(ident, "free");848849hard_local_irq_restore(flags);850}851EXPORT_SYMBOL(peripheral_free);852853void peripheral_free_list(const unsigned short per[])854{855u16 cnt;856for (cnt = 0; per[cnt] != 0; cnt++)857peripheral_free(per[cnt]);858}859EXPORT_SYMBOL(peripheral_free_list);860861/***********************************************************862*863* FUNCTIONS: Blackfin GPIO Driver864*865* INPUTS/OUTPUTS:866* gpio PIO Number between 0 and MAX_BLACKFIN_GPIOS867* label String868*869* DESCRIPTION: Blackfin GPIO Driver API870*871* CAUTION:872*************************************************************873* MODIFICATION HISTORY :874**************************************************************/875876int bfin_gpio_request(unsigned gpio, const char *label)877{878unsigned long flags;879880if (check_gpio(gpio) < 0)881return -EINVAL;882883flags = hard_local_irq_save();884885/*886* Allow that the identical GPIO can887* be requested from the same driver twice888* Do nothing and return -889*/890891if (cmp_label(gpio, label) == 0) {892hard_local_irq_restore(flags);893return 0;894}895896if (unlikely(is_reserved(gpio, gpio, 1))) {897if (system_state == SYSTEM_BOOTING)898dump_stack();899printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",900gpio, get_label(gpio));901hard_local_irq_restore(flags);902return -EBUSY;903}904if (unlikely(is_reserved(peri, gpio, 1))) {905if (system_state == SYSTEM_BOOTING)906dump_stack();907printk(KERN_ERR908"bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",909gpio, get_label(gpio));910hard_local_irq_restore(flags);911return -EBUSY;912}913if (unlikely(is_reserved(gpio_irq, gpio, 1))) {914printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!"915" (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio);916}917#ifndef CONFIG_BF54x918else { /* Reset POLAR setting when acquiring a gpio for the first time */919set_gpio_polar(gpio, 0);920}921#endif922923reserve(gpio, gpio);924set_label(gpio, label);925926hard_local_irq_restore(flags);927928port_setup(gpio, GPIO_USAGE);929930return 0;931}932EXPORT_SYMBOL(bfin_gpio_request);933934void bfin_gpio_free(unsigned gpio)935{936unsigned long flags;937938if (check_gpio(gpio) < 0)939return;940941might_sleep();942943flags = hard_local_irq_save();944945if (unlikely(!is_reserved(gpio, gpio, 0))) {946if (system_state == SYSTEM_BOOTING)947dump_stack();948gpio_error(gpio);949hard_local_irq_restore(flags);950return;951}952953unreserve(gpio, gpio);954955set_label(gpio, "free");956957hard_local_irq_restore(flags);958}959EXPORT_SYMBOL(bfin_gpio_free);960961#ifdef BFIN_SPECIAL_GPIO_BANKS962DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES));963964int bfin_special_gpio_request(unsigned gpio, const char *label)965{966unsigned long flags;967968flags = hard_local_irq_save();969970/*971* Allow that the identical GPIO can972* be requested from the same driver twice973* Do nothing and return -974*/975976if (cmp_label(gpio, label) == 0) {977hard_local_irq_restore(flags);978return 0;979}980981if (unlikely(is_reserved(special_gpio, gpio, 1))) {982hard_local_irq_restore(flags);983printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",984gpio, get_label(gpio));985986return -EBUSY;987}988if (unlikely(is_reserved(peri, gpio, 1))) {989hard_local_irq_restore(flags);990printk(KERN_ERR991"bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",992gpio, get_label(gpio));993994return -EBUSY;995}996997reserve(special_gpio, gpio);998reserve(peri, gpio);9991000set_label(gpio, label);1001hard_local_irq_restore(flags);1002port_setup(gpio, GPIO_USAGE);10031004return 0;1005}1006EXPORT_SYMBOL(bfin_special_gpio_request);10071008void bfin_special_gpio_free(unsigned gpio)1009{1010unsigned long flags;10111012might_sleep();10131014flags = hard_local_irq_save();10151016if (unlikely(!is_reserved(special_gpio, gpio, 0))) {1017gpio_error(gpio);1018hard_local_irq_restore(flags);1019return;1020}10211022unreserve(special_gpio, gpio);1023unreserve(peri, gpio);1024set_label(gpio, "free");1025hard_local_irq_restore(flags);1026}1027EXPORT_SYMBOL(bfin_special_gpio_free);1028#endif102910301031int bfin_gpio_irq_request(unsigned gpio, const char *label)1032{1033unsigned long flags;10341035if (check_gpio(gpio) < 0)1036return -EINVAL;10371038flags = hard_local_irq_save();10391040if (unlikely(is_reserved(peri, gpio, 1))) {1041if (system_state == SYSTEM_BOOTING)1042dump_stack();1043printk(KERN_ERR1044"bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",1045gpio, get_label(gpio));1046hard_local_irq_restore(flags);1047return -EBUSY;1048}1049if (unlikely(is_reserved(gpio, gpio, 1)))1050printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved by %s! "1051"(Documentation/blackfin/bfin-gpio-notes.txt)\n",1052gpio, get_label(gpio));10531054reserve(gpio_irq, gpio);1055set_label(gpio, label);10561057hard_local_irq_restore(flags);10581059port_setup(gpio, GPIO_USAGE);10601061return 0;1062}10631064void bfin_gpio_irq_free(unsigned gpio)1065{1066unsigned long flags;10671068if (check_gpio(gpio) < 0)1069return;10701071flags = hard_local_irq_save();10721073if (unlikely(!is_reserved(gpio_irq, gpio, 0))) {1074if (system_state == SYSTEM_BOOTING)1075dump_stack();1076gpio_error(gpio);1077hard_local_irq_restore(flags);1078return;1079}10801081unreserve(gpio_irq, gpio);10821083set_label(gpio, "free");10841085hard_local_irq_restore(flags);1086}10871088static inline void __bfin_gpio_direction_input(unsigned gpio)1089{1090#ifdef CONFIG_BF54x1091gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);1092#else1093gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);1094#endif1095gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);1096}10971098int bfin_gpio_direction_input(unsigned gpio)1099{1100unsigned long flags;11011102if (unlikely(!is_reserved(gpio, gpio, 0))) {1103gpio_error(gpio);1104return -EINVAL;1105}11061107flags = hard_local_irq_save();1108__bfin_gpio_direction_input(gpio);1109AWA_DUMMY_READ(inen);1110hard_local_irq_restore(flags);11111112return 0;1113}1114EXPORT_SYMBOL(bfin_gpio_direction_input);11151116void bfin_gpio_irq_prepare(unsigned gpio)1117{1118#ifdef CONFIG_BF54x1119unsigned long flags;1120#endif11211122port_setup(gpio, GPIO_USAGE);11231124#ifdef CONFIG_BF54x1125flags = hard_local_irq_save();1126__bfin_gpio_direction_input(gpio);1127hard_local_irq_restore(flags);1128#endif1129}11301131void bfin_gpio_set_value(unsigned gpio, int arg)1132{1133if (arg)1134gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);1135else1136gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);1137}1138EXPORT_SYMBOL(bfin_gpio_set_value);11391140int bfin_gpio_direction_output(unsigned gpio, int value)1141{1142unsigned long flags;11431144if (unlikely(!is_reserved(gpio, gpio, 0))) {1145gpio_error(gpio);1146return -EINVAL;1147}11481149flags = hard_local_irq_save();11501151gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);1152gpio_set_value(gpio, value);1153#ifdef CONFIG_BF54x1154gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);1155#else1156gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);1157#endif11581159AWA_DUMMY_READ(dir);1160hard_local_irq_restore(flags);11611162return 0;1163}1164EXPORT_SYMBOL(bfin_gpio_direction_output);11651166int bfin_gpio_get_value(unsigned gpio)1167{1168#ifdef CONFIG_BF54x1169return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)));1170#else1171unsigned long flags;11721173if (unlikely(get_gpio_edge(gpio))) {1174int ret;1175flags = hard_local_irq_save();1176set_gpio_edge(gpio, 0);1177ret = get_gpio_data(gpio);1178set_gpio_edge(gpio, 1);1179hard_local_irq_restore(flags);1180return ret;1181} else1182return get_gpio_data(gpio);1183#endif1184}1185EXPORT_SYMBOL(bfin_gpio_get_value);11861187/* If we are booting from SPI and our board lacks a strong enough pull up,1188* the core can reset and execute the bootrom faster than the resistor can1189* pull the signal logically high. To work around this (common) error in1190* board design, we explicitly set the pin back to GPIO mode, force /CS1191* high, and wait for the electrons to do their thing.1192*1193* This function only makes sense to be called from reset code, but it1194* lives here as we need to force all the GPIO states w/out going through1195* BUG() checks and such.1196*/1197void bfin_reset_boot_spi_cs(unsigned short pin)1198{1199unsigned short gpio = P_IDENT(pin);1200port_setup(gpio, GPIO_USAGE);1201gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);1202AWA_DUMMY_READ(data_set);1203udelay(1);1204}12051206#if defined(CONFIG_PROC_FS)1207static int gpio_proc_show(struct seq_file *m, void *v)1208{1209int c, irq, gpio;12101211for (c = 0; c < MAX_RESOURCES; c++) {1212irq = is_reserved(gpio_irq, c, 1);1213gpio = is_reserved(gpio, c, 1);1214if (!check_gpio(c) && (gpio || irq))1215seq_printf(m, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c,1216get_label(c), (gpio && irq) ? " *" : "",1217get_gpio_dir(c) ? "OUTPUT" : "INPUT");1218else if (is_reserved(peri, c, 1))1219seq_printf(m, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c));1220else1221continue;1222}12231224return 0;1225}12261227static int gpio_proc_open(struct inode *inode, struct file *file)1228{1229return single_open(file, gpio_proc_show, NULL);1230}12311232static const struct file_operations gpio_proc_ops = {1233.open = gpio_proc_open,1234.read = seq_read,1235.llseek = seq_lseek,1236.release = single_release,1237};12381239static __init int gpio_register_proc(void)1240{1241struct proc_dir_entry *proc_gpio;12421243proc_gpio = proc_create("gpio", S_IRUGO, NULL, &gpio_proc_ops);1244return proc_gpio != NULL;1245}1246__initcall(gpio_register_proc);1247#endif12481249#ifdef CONFIG_GPIOLIB1250static int bfin_gpiolib_direction_input(struct gpio_chip *chip, unsigned gpio)1251{1252return bfin_gpio_direction_input(gpio);1253}12541255static int bfin_gpiolib_direction_output(struct gpio_chip *chip, unsigned gpio, int level)1256{1257return bfin_gpio_direction_output(gpio, level);1258}12591260static int bfin_gpiolib_get_value(struct gpio_chip *chip, unsigned gpio)1261{1262return bfin_gpio_get_value(gpio);1263}12641265static void bfin_gpiolib_set_value(struct gpio_chip *chip, unsigned gpio, int value)1266{1267return bfin_gpio_set_value(gpio, value);1268}12691270static int bfin_gpiolib_gpio_request(struct gpio_chip *chip, unsigned gpio)1271{1272return bfin_gpio_request(gpio, chip->label);1273}12741275static void bfin_gpiolib_gpio_free(struct gpio_chip *chip, unsigned gpio)1276{1277return bfin_gpio_free(gpio);1278}12791280static int bfin_gpiolib_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)1281{1282return gpio + GPIO_IRQ_BASE;1283}12841285static struct gpio_chip bfin_chip = {1286.label = "BFIN-GPIO",1287.direction_input = bfin_gpiolib_direction_input,1288.get = bfin_gpiolib_get_value,1289.direction_output = bfin_gpiolib_direction_output,1290.set = bfin_gpiolib_set_value,1291.request = bfin_gpiolib_gpio_request,1292.free = bfin_gpiolib_gpio_free,1293.to_irq = bfin_gpiolib_gpio_to_irq,1294.base = 0,1295.ngpio = MAX_BLACKFIN_GPIOS,1296};12971298static int __init bfin_gpiolib_setup(void)1299{1300return gpiochip_add(&bfin_chip);1301}1302arch_initcall(bfin_gpiolib_setup);1303#endif130413051306