⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gpio.c

📁 linux 内核源代码
💻 C
字号:
/* * arch/arm/mach-pnx4008/gpio.c * * PNX4008 GPIO driver * * Author: Dmitry Chigirev <source@mvista.com> * * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips: * Copyright (c) 2005 Koninklijke Philips Electronics N.V. * * 2005 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */#include <linux/types.h>#include <linux/kernel.h>#include <linux/module.h>#include <asm/semaphore.h>#include <asm/io.h>#include <asm/arch/platform.h>#include <asm/arch/gpio.h>/* register definitions */#define PIO_VA_BASE	IO_ADDRESS(PNX4008_PIO_BASE)#define PIO_INP_STATE	(0x00U)#define PIO_OUTP_SET	(0x04U)#define PIO_OUTP_CLR	(0x08U)#define PIO_OUTP_STATE	(0x0CU)#define PIO_DRV_SET	(0x10U)#define PIO_DRV_CLR	(0x14U)#define PIO_DRV_STATE	(0x18U)#define PIO_SDINP_STATE	(0x1CU)#define PIO_SDOUTP_SET	(0x20U)#define PIO_SDOUTP_CLR	(0x24U)#define PIO_MUX_SET	(0x28U)#define PIO_MUX_CLR	(0x2CU)#define PIO_MUX_STATE	(0x30U)static inline void gpio_lock(void){	local_irq_disable();}static inline void gpio_unlock(void){	local_irq_enable();}/* Inline functions */static inline int gpio_read_bit(u32 reg, int gpio){	u32 bit, val;	int ret = -EFAULT;	if (gpio < 0)		goto out;	bit = GPIO_BIT(gpio);	if (bit) {		val = __raw_readl(PIO_VA_BASE + reg);		ret = (val & bit) ? 1 : 0;	}out:	return ret;}static inline int gpio_set_bit(u32 reg, int gpio){	u32 bit, val;	int ret = -EFAULT;	if (gpio < 0)		goto out;	bit = GPIO_BIT(gpio);	if (bit) {		val = __raw_readl(PIO_VA_BASE + reg);		val |= bit;		__raw_writel(val, PIO_VA_BASE + reg);		ret = 0;	}out:	return ret;}/* Very simple access control, bitmap for allocated/free */static unsigned long access_map[4];#define INP_INDEX	0#define OUTP_INDEX	1#define GPIO_INDEX	2#define MUX_INDEX	3/*GPIO to Input Mapping */static short gpio_to_inp_map[32] = {	-1, -1, -1, -1, -1, -1, -1, -1,	-1, -1, -1, -1, -1, -1, -1, -1,	-1, -1, -1, -1, -1, -1, -1, -1,	-1, 10, 11, 12, 13, 14, 24, -1};/*GPIO to Mux Mapping */static short gpio_to_mux_map[32] = {	-1, -1, -1, -1, -1, -1, -1, -1,	-1, -1, -1, -1, -1, -1, -1, -1,	-1, -1, -1, -1, -1, -1, -1, -1,	-1, -1, -1, 0, 1, 4, 5, -1};/*Output to Mux Mapping */static short outp_to_mux_map[32] = {	-1, -1, -1, 6, -1, -1, -1, -1,	-1, -1, -1, -1, -1, -1, -1, -1,	-1, -1, -1, -1, -1, 2, -1, -1,	-1, -1, -1, -1, -1, -1, -1, -1};int pnx4008_gpio_register_pin(unsigned short pin){	unsigned long bit = GPIO_BIT(pin);	int ret = -EBUSY;	/* Already in use */	gpio_lock();	if (GPIO_ISBID(pin)) {		if (access_map[GPIO_INDEX] & bit)			goto out;		access_map[GPIO_INDEX] |= bit;	} else if (GPIO_ISRAM(pin)) {		if (access_map[GPIO_INDEX] & bit)			goto out;		access_map[GPIO_INDEX] |= bit;	} else if (GPIO_ISMUX(pin)) {		if (access_map[MUX_INDEX] & bit)			goto out;		access_map[MUX_INDEX] |= bit;	} else if (GPIO_ISOUT(pin)) {		if (access_map[OUTP_INDEX] & bit)			goto out;		access_map[OUTP_INDEX] |= bit;	} else if (GPIO_ISIN(pin)) {		if (access_map[INP_INDEX] & bit)			goto out;		access_map[INP_INDEX] |= bit;	} else		goto out;	ret = 0;out:	gpio_unlock();	return ret;}EXPORT_SYMBOL(pnx4008_gpio_register_pin);int pnx4008_gpio_unregister_pin(unsigned short pin){	unsigned long bit = GPIO_BIT(pin);	int ret = -EFAULT;	/* Not registered */	gpio_lock();	if (GPIO_ISBID(pin)) {		if (~access_map[GPIO_INDEX] & bit)			goto out;		access_map[GPIO_INDEX] &= ~bit;	} else if (GPIO_ISRAM(pin)) {		if (~access_map[GPIO_INDEX] & bit)			goto out;		access_map[GPIO_INDEX] &= ~bit;	} else if (GPIO_ISMUX(pin)) {		if (~access_map[MUX_INDEX] & bit)			goto out;		access_map[MUX_INDEX] &= ~bit;	} else if (GPIO_ISOUT(pin)) {		if (~access_map[OUTP_INDEX] & bit)			goto out;		access_map[OUTP_INDEX] &= ~bit;	} else if (GPIO_ISIN(pin)) {		if (~access_map[INP_INDEX] & bit)			goto out;		access_map[INP_INDEX] &= ~bit;	} else		goto out;	ret = 0;out:	gpio_unlock();	return ret;}EXPORT_SYMBOL(pnx4008_gpio_unregister_pin);unsigned long pnx4008_gpio_read_pin(unsigned short pin){	unsigned long ret = -EFAULT;	int gpio = GPIO_BIT_MASK(pin);	gpio_lock();	if (GPIO_ISOUT(pin)) {		ret = gpio_read_bit(PIO_OUTP_STATE, gpio);	} else if (GPIO_ISRAM(pin)) {		if (gpio_read_bit(PIO_DRV_STATE, gpio) == 0) {			ret = gpio_read_bit(PIO_SDINP_STATE, gpio);		}	} else if (GPIO_ISBID(pin)) {		ret = gpio_read_bit(PIO_DRV_STATE, gpio);		if (ret > 0)			ret = gpio_read_bit(PIO_OUTP_STATE, gpio);		else if (ret == 0)			ret =			    gpio_read_bit(PIO_INP_STATE, gpio_to_inp_map[gpio]);	} else if (GPIO_ISIN(pin)) {		ret = gpio_read_bit(PIO_INP_STATE, gpio);	}	gpio_unlock();	return ret;}EXPORT_SYMBOL(pnx4008_gpio_read_pin);/* Write Value to output */int pnx4008_gpio_write_pin(unsigned short pin, int output){	int gpio = GPIO_BIT_MASK(pin);	int ret = -EFAULT;	gpio_lock();	if (GPIO_ISOUT(pin)) {		printk( "writing '%x' to '%x'\n",				gpio, output ? PIO_OUTP_SET : PIO_OUTP_CLR );		ret = gpio_set_bit(output ? PIO_OUTP_SET : PIO_OUTP_CLR, gpio);	} else if (GPIO_ISRAM(pin)) {		if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)			ret = gpio_set_bit(output ? PIO_SDOUTP_SET :					   PIO_SDOUTP_CLR, gpio);	} else if (GPIO_ISBID(pin)) {		if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)			ret = gpio_set_bit(output ? PIO_OUTP_SET :					   PIO_OUTP_CLR, gpio);	}	gpio_unlock();	return ret;}EXPORT_SYMBOL(pnx4008_gpio_write_pin);/* Value = 1 : Set GPIO pin as output *//* Value = 0 : Set GPIO pin as input */int pnx4008_gpio_set_pin_direction(unsigned short pin, int output){	int gpio = GPIO_BIT_MASK(pin);	int ret = -EFAULT;	gpio_lock();	if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {		ret = gpio_set_bit(output ? PIO_DRV_SET : PIO_DRV_CLR, gpio);	}	gpio_unlock();	return ret;}EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction);/* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/int pnx4008_gpio_read_pin_direction(unsigned short pin){	int gpio = GPIO_BIT_MASK(pin);	int ret = -EFAULT;	gpio_lock();	if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {		ret = gpio_read_bit(PIO_DRV_STATE, gpio);	}	gpio_unlock();	return ret;}EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction);/* Value = 1 : Set pin to muxed function  *//* Value = 0 : Set pin as GPIO */int pnx4008_gpio_set_pin_mux(unsigned short pin, int output){	int gpio = GPIO_BIT_MASK(pin);	int ret = -EFAULT;	gpio_lock();	if (GPIO_ISBID(pin)) {		ret =		    gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,				 gpio_to_mux_map[gpio]);	} else if (GPIO_ISOUT(pin)) {		ret =		    gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,				 outp_to_mux_map[gpio]);	} else if (GPIO_ISMUX(pin)) {		ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, gpio);	}	gpio_unlock();	return ret;}EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux);/* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/int pnx4008_gpio_read_pin_mux(unsigned short pin){	int gpio = GPIO_BIT_MASK(pin);	int ret = -EFAULT;	gpio_lock();	if (GPIO_ISBID(pin)) {		ret = gpio_read_bit(PIO_MUX_STATE, gpio_to_mux_map[gpio]);	} else if (GPIO_ISOUT(pin)) {		ret = gpio_read_bit(PIO_MUX_STATE, outp_to_mux_map[gpio]);	} else if (GPIO_ISMUX(pin)) {		ret = gpio_read_bit(PIO_MUX_STATE, gpio);	}	gpio_unlock();	return ret;}EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux);

⌨️ 快捷键说明

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