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

📄 at91_mygpio.c

📁 gpio driver for atmel ar91rm92
💻 C
字号:
/*======================================================================	current file::/drivers/at91/mygpio/at91_mygpio.c	Device driver for the GPIO(PIO) control of Atmel AT91RM9200	(c)e-tek Ltd,Shenzhen,Guangdong,China	The original code is created by beeswing<beeswing@21cn.com>. 	20060216 add portb irq handle as a share read		Copyright (C) 2005 beeswing.  	All Rights Reserved.    ======================================================================*/    #include <linux/module.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/proc_fs.h>#include <linux/init.h>#ifdef CONFIG_DEVFS_FS#include <linux/devfs_fs_kernel.h>#endif#include <asm/io.h>#include <asm/arch/hardware.h>#include	"at91_mygpio.h"///#define GPIO_DEBUG	1#define PORT(x)		((x >> 8) & 0x0F)#define GPIO(x)		(x & 0xFF)#define PORT_MAX	NR_GPIO_DEVICES#define GPIO_MAX	32extern AT91PS_SYS AT91_SYS;#ifdef	CONFIG_PORTS_SHARE_IRQ			unsigned long ports_irq_status[4];	static unsigned int port_dev_id[4];	#endif#ifdef CONFIG_DEVFS_FSstatic devfs_handle_t devfs_handle = NULL;#endif//check if gpio or AB select function 1=gpiostatic int check_gpio_fun(AT91PS_PIO PORT, unsigned int num){        return (PORT->PIO_PSR & PIO_GPIO(num)) ? 1 : 0;}//check the direction: 1 = outputstatic int check_gpio_direct(AT91PS_PIO PORT, unsigned int num){        return (PORT->PIO_OSR & PIO_GPIO(num)) ? 1 : 0;}static ssize_t gpio_write(struct file * file, const char * buf, size_t count, loff_t * ppos){	unsigned int gpio_arg = file->private_data;	unsigned int gpio_device = PORT(gpio_arg);	unsigned int pin_num = GPIO(gpio_arg);	AT91PS_PIO AT91_PORT = (AT91PS_PIO)(unsigned long)(AT91C_VA_BASE_SYS + 0x400 + 0x200 * gpio_device);	if (gpio_device >= NR_GPIO_DEVICES)		return -ENODEV;	if (!check_gpio_fun(AT91_PORT, pin_num)) {		printk(KERN_ERR "IO not a gpio!\n");	  	return -EIO;	}	if (!check_gpio_direct(AT91_PORT, pin_num)) {		printk(KERN_ERR "Not a output gpio!\n");	  	return -EIO;	}#ifdef	GPIO_DEBUG	printk("MYgpio write port %d pin %d:data %c!\n", gpio_device,pin_num,*buf);#endif	if ( (*buf) == '1')		AT91_PORT->PIO_SODR = PIO_GPIO(pin_num);	else if ( (*buf) == '0')		AT91_PORT->PIO_CODR = PIO_GPIO(pin_num);	return 1;}//static ssize_t gpio_read (struct file * file, char * buf, size_t count, loff_t * ppos) {	unsigned int gpio_arg = file->private_data;	unsigned int gpio_device = PORT(gpio_arg);	unsigned int pin_num = GPIO(gpio_arg);	AT91PS_PIO AT91_PORT = (AT91PS_PIO)(unsigned long)(AT91C_VA_BASE_SYS + 0x400 + 0x200 * gpio_device);	if (gpio_device >= NR_GPIO_DEVICES)		return -ENODEV;		if (!check_gpio_fun(AT91_PORT, pin_num)) {		printk(KERN_ERR "IO not a gpio!\n");	  	return -EIO;	}	if (check_gpio_direct(AT91_PORT, pin_num)) {		printk(KERN_ERR "Not a input gpio!\n");	 	return -EIO;	}	*buf = (AT91_PORT->PIO_PDSR & PIO_GPIO(pin_num))? '1':'0';	#ifdef	GPIO_DEBUG		printk("MYgpio read port %d pin %d data:%c!\n",gpio_device, pin_num, *buf);#endif	return 1;}//arg include input pin_numstatic int gpio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	unsigned int gpio_device = MINOR(inode->i_rdev);	unsigned int pin_num = GPIO(arg);	AT91PS_PIO AT91_PORT = (AT91PS_PIO)(unsigned long)(AT91C_VA_BASE_SYS + 0x400 + 0x200 * gpio_device);		if (gpio_device >= NR_GPIO_DEVICES)		return -ENODEV;#ifdef	MYGPIO_DEBUG	printk(KERN_INFO "mygpio minor: %X \n",gpio_device);#endif	if (pin_num > GPIO_MAX)	{		printk(KERN_ERR "mygpio IO error in ioctl!\n");		return -EIO;	}	#ifdef	MYGPIO_DEBUG	printk(KERN_INFO "mygpio pin NO: %d\n",pin_num);#endif	//map physical address this method is OK	//move to open function	///AT91_PORT = (AT91PS_PIO)(unsigned long)(AT91C_VA_BASE_SYS + 0x400 + 0x200 * gpio_device);#ifdef	MYGPIO_DEBUG	printk("mygpio ioctl setting cmd:%X Arg: %X port_base: %X \n",cmd,arg,AT91_PORT);#endif	switch (cmd) 	{	 	  case PIO_SET_PASR:		AT91_PORT->PIO_ASR = PIO_GPIO(pin_num); 		AT91_PORT->PIO_PDR = PIO_GPIO(pin_num);		break; 		  case PIO_SET_PBSR:		AT91_PORT->PIO_BSR = PIO_GPIO(pin_num); 		AT91_PORT->PIO_PDR = PIO_GPIO(pin_num); 		break;	  case PIO_SET_GPIO:		AT91_PORT->PIO_PER = PIO_GPIO(pin_num); 		break;	  case PIO_SET_INPUT:		AT91_PORT->PIO_ODR = PIO_GPIO(pin_num); 		break;	  case PIO_SET_OUTPUT:		AT91_PORT->PIO_OER = PIO_GPIO(pin_num); 		break;	  default:                return -EINVAL;	}	(unsigned int) file->private_data = (gpio_device << 8) | pin_num;	return 0;}static int gpio_open(struct inode *inode, struct file *file){	unsigned int gpio_device = MINOR(inode->i_rdev);	//move from ioctl	AT91PS_PIO AT91_PORT = (AT91PS_PIO)(unsigned long)(AT91C_VA_BASE_SYS + 0x400 + 0x200 * gpio_device);	if (gpio_device >= NR_GPIO_DEVICES)		return -ENODEV;		MOD_INC_USE_COUNT;		AT91_SYS->PMC_PCER = 1 << (AT91C_ID_PIOA + gpio_device);	#ifdef	GPIO_DEBUG		printk(KERN_INFO "mygpio open port %d add:%X \n", gpio_device,AT91_PORT);#endif	return 0;}static int gpio_close(struct inode *inode, struct file *file){	unsigned int gpio_device = MINOR(inode->i_rdev);	if (gpio_device >= NR_GPIO_DEVICES)		return -ENODEV;	//disable peripheral clock 	AT91_SYS->PMC_PCDR = 1 << (AT91C_ID_PIOA + gpio_device);	MOD_DEC_USE_COUNT;#ifdef	GPIO_DEBUG		printk(KERN_INFO "mygpio close port %d add:%X \n", gpio_device,AT91_PORT);#endif	return 0;}#ifdef	CONFIG_PORTS_SHARE_IRQstatic void port_interrupt_handle(int irq, void *dev_id, struct pt_regs *regs){	AT91PS_PIO at91_gport = (AT91PS_PIO)(unsigned long)(AT91C_VA_BASE_SYS + 0x400 + 0x200 * (irq - AT91C_ID_PIOA));	ports_irq_status[irq - AT91C_ID_PIOA] = at91_gport->PIO_ISR & at91_gport->PIO_IMR;	//printk("mygpio.c port(%d) irq status = %X\n", irq - AT91C_ID_PIOA, ports_irq_status[irq - AT91C_ID_PIOA]);}#endif//file operationsstatic struct file_operations gpio_fops = {	owner:	THIS_MODULE,	read:	gpio_read,	write:	gpio_write,	ioctl:	gpio_ioctl,	open:	gpio_open,	release:	gpio_close,};/* * Main initialization routine */static int __init init_gpio(void){	unsigned int i;#ifdef CONFIG_DEVFS_FS	unsigned char *devname;	if (devfs_register_chrdev(GPIO_MAJOR, "mygpio", &gpio_fops)) {#else	if (register_chrdev(GPIO_MAJOR, "mygpio", &gpio_fops)) {#endif		printk(KERN_ERR "mygpio: unable to get major %d\n", GPIO_MAJOR);		return -EIO;	}		#ifdef CONFIG_DEVFS_FS	devfs_handle = devfs_mk_dir(NULL, "mygpio", NULL);	if (!devfs_handle) return -EBUSY;			devfs_register_series (devfs_handle, "port%u", NR_GPIO_DEVICES,		\		DEVFS_FL_DEFAULT, 						\		GPIO_MAJOR, 0, S_IFCHR | S_IRUGO | S_IWUGO,			\		&gpio_fops, NULL);#endif#ifdef	CONFIG_PORTS_SHARE_IRQ	for (i = 0; i < PORTS_NUM; i++){			if (request_irq(AT91C_ID_PIOA + i, port_interrupt_handle, SA_SHIRQ, "mygpio", &port_dev_id[i])){			printk(KERN_ERR "can not get assigned ports irq %d\n", AT91C_ID_PIOA+i);		}	}#endif	printk(KERN_INFO "mygpio driver initialized by beeswing!\n");	return 0;}static void __exit gpio_cleanup(void){#ifdef	CONFIG_PORTS_SHARE_IRQ	int i;	for (i = 0; i < PORTS_NUM; i++){		free_irq(AT91C_ID_PIOA + i, &port_dev_id[i]);	}#endif#ifdef CONFIG_DEVFS_FS	devfs_unregister(devfs_handle);	if (devfs_unregister_chrdev(GPIO_MAJOR, "mygpio"))#else	if (unregister_chrdev(GPIO_MAJOR, "mygpio"))#endif	printk(KERN_ERR "at91_mygpio: Unable to release major %d for gpio\n", GPIO_MAJOR);	return;}EXPORT_NO_SYMBOLS;MODULE_AUTHOR("Beeswing");MODULE_DESCRIPTION("GPIO driver for Atmel AT91RM9200");MODULE_LICENSE("GPL");module_init(init_gpio);module_exit(gpio_cleanup);

⌨️ 快捷键说明

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