bfin_gpio.c

来自「linux 内核源代码」· C语言 代码 · 共 1,197 行 · 第 1/2 页

C
1,197
字号
	unsigned long flags; \	unsigned short ret; \	local_irq_save(flags); \	ret = (gpio_bankb[gpio_bank(gpio)]->name); \	AWA_DUMMY_READ(name); \	local_irq_restore(flags); \	return ret; \} \EXPORT_SYMBOL(get_gpiop_ ## name);#else#define GET_GPIO_P(name) \unsigned short get_gpiop_ ## name(unsigned short gpio) \{ \	return (gpio_bankb[gpio_bank(gpio)]->name);\} \EXPORT_SYMBOL(get_gpiop_ ## name);#endifGET_GPIO_P(data)GET_GPIO_P(dir)GET_GPIO_P(inen)GET_GPIO_P(polar)GET_GPIO_P(edge)GET_GPIO_P(both)GET_GPIO_P(maska)GET_GPIO_P(maskb)#ifdef CONFIG_PM/************************************************************* FUNCTIONS: Blackfin PM Setup API** INPUTS/OUTPUTS:* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS* type -*	PM_WAKE_RISING*	PM_WAKE_FALLING*	PM_WAKE_HIGH*	PM_WAKE_LOW*	PM_WAKE_BOTH_EDGES** DESCRIPTION: Blackfin PM Driver API** CAUTION:************************************************************** MODIFICATION HISTORY :**************************************************************/int gpio_pm_wakeup_request(unsigned short gpio, unsigned char type){	unsigned long flags;	if ((check_gpio(gpio) < 0) || !type)		return -EINVAL;	local_irq_save(flags);	wakeup_map[gpio_bank(gpio)] |= gpio_bit(gpio);	wakeup_flags_map[gpio] = type;	local_irq_restore(flags);	return 0;}EXPORT_SYMBOL(gpio_pm_wakeup_request);void gpio_pm_wakeup_free(unsigned short gpio){	unsigned long flags;	if (check_gpio(gpio) < 0)		return;	local_irq_save(flags);	wakeup_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);	local_irq_restore(flags);}EXPORT_SYMBOL(gpio_pm_wakeup_free);static int bfin_gpio_wakeup_type(unsigned short 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);	if ((type & (PM_WAKE_FALLING | PM_WAKE_LOW)))		set_gpio_polar(gpio, 1);	else		set_gpio_polar(gpio, 0);	SSYNC();	return 0;}u32 gpio_pm_setup(void){	u32 sic_iwr = 0;	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_bankb[bank]->maskb;		gpio_bankb[bank]->maskb = 0;		if (mask) {#ifdef BF537_FAMILY			gpio_bank_saved[bank].fer   = *port_fer[bank];#endif			gpio_bank_saved[bank].inen  = gpio_bankb[bank]->inen;			gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar;			gpio_bank_saved[bank].dir   = gpio_bankb[bank]->dir;			gpio_bank_saved[bank].edge  = gpio_bankb[bank]->edge;			gpio_bank_saved[bank].both  = gpio_bankb[bank]->both;			gpio_bank_saved[bank].reserved =						reserved_gpio_map[bank];			gpio = i;			while (mask) {				if (mask & 1) {					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;			}			sic_iwr |= 1 <<				(sic_iwr_irqs[bank] - (IRQ_CORETMR + 1));			gpio_bankb[bank]->maskb_set = wakeup_map[gpio_bank(i)];		}	}	AWA_DUMMY_READ(maskb_set);	if (sic_iwr)		return sic_iwr;	else		return IWR_ENABLE_ALL;}void gpio_pm_restore(void){	u16 bank, mask, i;	for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {		mask = wakeup_map[gpio_bank(i)];		bank = gpio_bank(i);		if (mask) {#ifdef BF537_FAMILY			*port_fer[bank]   	= gpio_bank_saved[bank].fer;#endif			gpio_bankb[bank]->inen  = gpio_bank_saved[bank].inen;			gpio_bankb[bank]->dir   = gpio_bank_saved[bank].dir;			gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar;			gpio_bankb[bank]->edge  = gpio_bank_saved[bank].edge;			gpio_bankb[bank]->both  = gpio_bank_saved[bank].both;			reserved_gpio_map[bank] =					gpio_bank_saved[bank].reserved;		}		gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb;	}	AWA_DUMMY_READ(maskb);}#endif#endif /* BF548_FAMILY *//************************************************************* FUNCTIONS: 	Blackfin Peripheral Resource Allocation*		and PortMux Setup** INPUTS/OUTPUTS:* per	Peripheral Identifier* label	String** DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API** CAUTION:************************************************************** MODIFICATION HISTORY :**************************************************************/#ifdef BF548_FAMILYint peripheral_request(unsigned short per, const char *label){	unsigned long flags;	unsigned short ident = P_IDENT(per);	/*	 * Don't cares are pins with only one dedicated function	 */	if (per & P_DONTCARE)		return 0;	if (!(per & P_DEFINED))		return -ENODEV;	if (check_gpio(ident) < 0)		return -EINVAL;	local_irq_save(flags);	if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {		printk(KERN_ERR		    "%s: Peripheral %d is already reserved as GPIO by %s !\n",		       __FUNCTION__, ident, get_label(ident));		dump_stack();		local_irq_restore(flags);		return -EBUSY;	}	if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {		u16 funct = get_portmux(ident);	/*	 * Pin functions like AMC address strobes my	 * be requested and used by several drivers	 */		if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) {		/*		 * Allow that the identical pin function can		 * be requested from the same driver twice		 */		if (cmp_label(ident, label) == 0)			goto anyway;			printk(KERN_ERR			       "%s: Peripheral %d function %d is already reserved by %s !\n",			       __FUNCTION__, ident, P_FUNCT2MUX(per), get_label(ident));			dump_stack();			local_irq_restore(flags);			return -EBUSY;		}	}anyway:	reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);	portmux_setup(ident, P_FUNCT2MUX(per));	port_setup(ident, PERIPHERAL_USAGE);	local_irq_restore(flags);	set_label(ident, label);	return 0;}EXPORT_SYMBOL(peripheral_request);#elseint peripheral_request(unsigned short per, const char *label){	unsigned long flags;	unsigned short ident = P_IDENT(per);	/*	 * Don't cares are pins with only one dedicated function	 */	if (per & P_DONTCARE)		return 0;	if (!(per & P_DEFINED))		return -ENODEV;	local_irq_save(flags);	if (!check_gpio(ident)) {	if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {		printk(KERN_ERR		       "%s: Peripheral %d is already reserved as GPIO by %s !\n",		       __FUNCTION__, ident, get_label(ident));		dump_stack();		local_irq_restore(flags);		return -EBUSY;	}	}	if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {	/*	 * Pin functions like AMC address strobes my	 * be requested and used by several drivers	 */	if (!(per & P_MAYSHARE)) {	/*	 * Allow that the identical pin function can	 * be requested from the same driver twice	 */		if (cmp_label(ident, label) == 0)			goto anyway;			printk(KERN_ERR			       "%s: Peripheral %d function %d is already"			       " reserved by %s !\n",			       __FUNCTION__, ident, P_FUNCT2MUX(per),				get_label(ident));			dump_stack();			local_irq_restore(flags);			return -EBUSY;		}	}anyway:	portmux_setup(per, P_FUNCT2MUX(per));	port_setup(ident, PERIPHERAL_USAGE);	reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);	local_irq_restore(flags);	set_label(ident, label);	return 0;}EXPORT_SYMBOL(peripheral_request);#endifint peripheral_request_list(unsigned short per[], const char *label){	u16 cnt;	int ret;	for (cnt = 0; per[cnt] != 0; cnt++) {		ret = peripheral_request(per[cnt], label);		if (ret < 0) {			for ( ; cnt > 0; cnt--) {				peripheral_free(per[cnt - 1]);			}		return ret;		}	}	return 0;}EXPORT_SYMBOL(peripheral_request_list);void peripheral_free(unsigned short per){	unsigned long flags;	unsigned short ident = P_IDENT(per);	if (per & P_DONTCARE)		return;	if (!(per & P_DEFINED))		return;	if (check_gpio(ident) < 0)		return;	local_irq_save(flags);	if (unlikely(!(reserved_peri_map[gpio_bank(ident)]			 & gpio_bit(ident)))) {		local_irq_restore(flags);		return;	}	if (!(per & P_MAYSHARE)) {		port_setup(ident, GPIO_USAGE);	}	reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident);	set_label(ident, "free");	local_irq_restore(flags);}EXPORT_SYMBOL(peripheral_free);void peripheral_free_list(unsigned short per[]){	u16 cnt;	for (cnt = 0; per[cnt] != 0; cnt++) {		peripheral_free(per[cnt]);	}}EXPORT_SYMBOL(peripheral_free_list);/************************************************************* FUNCTIONS: Blackfin GPIO Driver** INPUTS/OUTPUTS:* gpio	PIO Number between 0 and MAX_BLACKFIN_GPIOS* label	String** DESCRIPTION: Blackfin GPIO Driver API** CAUTION:************************************************************** MODIFICATION HISTORY :**************************************************************/int gpio_request(unsigned short gpio, const char *label){	unsigned long flags;	if (check_gpio(gpio) < 0)		return -EINVAL;	local_irq_save(flags);	/*	 * Allow that the identical GPIO can	 * be requested from the same driver twice	 * Do nothing and return -	 */	if (cmp_label(gpio, label) == 0) {		local_irq_restore(flags);		return 0;	}	if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {		printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",			 gpio, get_label(gpio));		dump_stack();		local_irq_restore(flags);		return -EBUSY;	}	if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {		printk(KERN_ERR		       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",		       gpio, get_label(gpio));		dump_stack();		local_irq_restore(flags);		return -EBUSY;	}	reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);	local_irq_restore(flags);	port_setup(gpio, GPIO_USAGE);	set_label(gpio, label);	return 0;}EXPORT_SYMBOL(gpio_request);void gpio_free(unsigned short gpio){	unsigned long flags;	if (check_gpio(gpio) < 0)		return;	local_irq_save(flags);	if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {		printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio);		dump_stack();		local_irq_restore(flags);		return;	}	default_gpio(gpio);	reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);	set_label(gpio, "free");	local_irq_restore(flags);}EXPORT_SYMBOL(gpio_free);#ifdef BF548_FAMILYvoid gpio_direction_input(unsigned short gpio){	unsigned long flags;	BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));	local_irq_save(flags);	gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);	gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);	local_irq_restore(flags);}EXPORT_SYMBOL(gpio_direction_input);void gpio_direction_output(unsigned short gpio){	unsigned long flags;	BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));	local_irq_save(flags);	gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio);	gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio);	local_irq_restore(flags);}EXPORT_SYMBOL(gpio_direction_output);void gpio_set_value(unsigned short gpio, unsigned short arg){	if (arg)		gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio);	else		gpio_array[gpio_bank(gpio)]->port_clear = gpio_bit(gpio);}EXPORT_SYMBOL(gpio_set_value);unsigned short gpio_get_value(unsigned short gpio){	return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio)));}EXPORT_SYMBOL(gpio_get_value);#elsevoid gpio_direction_input(unsigned short gpio){	unsigned long flags;	BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));	local_irq_save(flags);	gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);	gpio_bankb[gpio_bank(gpio)]->inen |= gpio_bit(gpio);	AWA_DUMMY_READ(inen);	local_irq_restore(flags);}EXPORT_SYMBOL(gpio_direction_input);void gpio_direction_output(unsigned short gpio){	unsigned long flags;	BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));	local_irq_save(flags);	gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);	gpio_bankb[gpio_bank(gpio)]->dir |= gpio_bit(gpio);	AWA_DUMMY_READ(dir);	local_irq_restore(flags);}EXPORT_SYMBOL(gpio_direction_output);/* If we are booting from SPI and our board lacks a strong enough pull up, * the core can reset and execute the bootrom faster than the resistor can * pull the signal logically high.  To work around this (common) error in * board design, we explicitly set the pin back to GPIO mode, force /CS * high, and wait for the electrons to do their thing. * * This function only makes sense to be called from reset code, but it * lives here as we need to force all the GPIO states w/out going through * BUG() checks and such. */void bfin_gpio_reset_spi0_ssel1(void){	u16 gpio = P_IDENT(P_SPI0_SSEL1);	port_setup(gpio, GPIO_USAGE);	gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio);	udelay(1);}#endif /*BF548_FAMILY */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?