📄 gpio_2440.c
字号:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include "gpio_2440.h"
#define IOPORT_MAJOR 220
#define DEBUG
#ifdef AT91RM9200_GPIO_ZSH
#define BASE_SYS AT91C_VA_BASE_SYS
#define PMC 0x00000c00
#define PCER 0x0010
#define PIOC 0x00000800
#define PER 0x0000
#define OER 0X0010
#define SODR 0X0030
#define CODR 0X0034
#endif
#ifdef S3C2440_GPIO_ZSH
#include <asm/arch/regs-gpio.h>
#endif
int gpio_open(struct inode*,struct file *);
int gpio_release(struct inode*,struct file *);
int gpio_ctl_ioctl(struct inode*,struct file *, unsigned int, unsigned long);
#ifdef AT91RM9200_GPIO_ZSH
int gpio_open(struct inode*inode,struct file *file)
{
unsigned int temp = 0;
printk(KERN_ALERT "gpio_9200: Open!! %x \n", temp);
temp = __raw_readl(BASE_SYS + PMC + PCER + 8);
printk(KERN_ALERT "gpio_9200: PMC_PCER = %x!!\n", temp);
temp |= (1 << 4);
__raw_writel(temp, BASE_SYS + PMC + PCER);
temp = __raw_readl(BASE_SYS + PIOC + PER + 8);
printk(KERN_ALERT "gpio_9200: PIOC_PER = %x!!\n", temp);
temp |= (0x3 << 14);
__raw_writel(temp, BASE_SYS + PIOC + PER);
temp = __raw_readl(BASE_SYS + PIOC + OER + 8);
printk(KERN_ALERT "gpio_9200: PIOC_OER = %x!!\n", temp);
temp |=(0x3 << 14);
__raw_writel(temp, BASE_SYS + PIOC + OER);
return 0;
}
int gpio_release(struct inode *inode,struct file *file)
{
printk(KERN_ALERT "gpio_9200: Release!!\n");
return 0;
}
int gpio_ctl_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
unsigned int temp = 0, ret = 0;
printk(KERN_ALERT "gpio_9200: Ioctl!!\n");
switch(cmd){
case IOSET:
temp = __raw_readl(BASE_SYS + PIOC + SODR + 8);
printk(KERN_ALERT "gpio_9200: PIOC_ODSR = %x!!\n", temp);
if(arg == GPC14) temp |= (0x1 << 14);
else if(arg == GPC15) temp |= (0x1 << 15);
__raw_writel(temp, BASE_SYS + PIOC + SODR);
break;
case IOCLR:
temp = __raw_readl(BASE_SYS + PIOC + SODR + 8);
printk(KERN_ALERT "gpio_9200: PIOC_ODSR = %x!!\n", temp);
if(arg == GPC14) temp |= (0x1 << 14);
else if(arg == GPC15) temp |= (0x1 << 15);
__raw_writel(temp, BASE_SYS + PIOC + SODR + 4);
break;
case IOGET:
printk(KERN_ALERT "gpio_9200: Ioctl -> IOGET!!\n");
temp = __raw_readl(BASE_SYS + PIOC + SODR + 8);
ret = put_user(temp, ((unsigned int *)arg));
break;
}
return ret;
}
#endif
#ifdef S3C2440_GPIO_ZSH
#include <asm/arch/regs-gpio.h>
void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
{
void __iomem *base = S3C2410_GPIO_BASE(pin);
unsigned long mask;
unsigned long con;
unsigned long flags;
if (pin < S3C2410_GPIO_BANKB) {
mask = 1 << S3C2410_GPIO_OFFSET(pin);
} else {
mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
}
local_irq_save(flags);
con = __raw_readl(base + 0x00);
con &= ~mask;
con |= function;
__raw_writel(con, base + 0x00);
local_irq_restore(flags);
}
void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
{
void __iomem *base = S3C2410_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
unsigned long flags;
unsigned long dat;
local_irq_save(flags);
dat = __raw_readl(base + 0x04);
dat &= ~(1 << offs);
dat |= to << offs;
__raw_writel(dat, base + 0x04);
local_irq_restore(flags);
}
unsigned int s3c2410_gpio_getpin(unsigned int pin)
{
void __iomem *base = S3C2410_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
return __raw_readl(base + 0x04) & (1<< offs);
}
int gpio_open(struct inode*inode,struct file *file)
{
unsigned int temp = 0;
printk(KERN_ALERT "gpio_2440: Open!! %x \n", temp);
return 0;
}
int gpio_release(struct inode *inode,struct file *file)
{
printk(KERN_ALERT "gpio_2440: Release!!\n");
return 0;
}
int gpio_ctl_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
unsigned int temp = 0, ret = 0;
printk(KERN_ALERT "gpio_2440: Ioctl!!\n");
switch(cmd){
case IOSET:
s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
if(arg == GPF4) s3c2410_gpio_setpin(S3C2410_GPF4, 1);
else if(arg == GPF5) s3c2410_gpio_setpin(S3C2410_GPF5, 1);
else if(arg == GPF6) s3c2410_gpio_setpin(S3C2410_GPF6, 1);
else if(arg == GPF7) s3c2410_gpio_setpin(S3C2410_GPF7, 1);
break;
case IOCLR:
s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
if(arg == GPF4) s3c2410_gpio_setpin(S3C2410_GPF4, 0);
else if(arg == GPF5) s3c2410_gpio_setpin(S3C2410_GPF5, 0);
else if(arg == GPF6) s3c2410_gpio_setpin(S3C2410_GPF6, 0);
else if(arg == GPF7) s3c2410_gpio_setpin(S3C2410_GPF7, 0);
break;
case IOGET:
printk(KERN_ALERT "gpio_2440: Ioctl -> IOGET!!\n");
s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_INP);
s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_INP);
s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_INP);
s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_INP);
if(arg == GPF4) temp = s3c2410_gpio_getpin(S3C2410_GPF4);
else if(arg == GPF5) temp = s3c2410_gpio_getpin(S3C2410_GPF5);
else if(arg == GPF6) temp = s3c2410_gpio_getpin(S3C2410_GPF6);
else if(arg == GPF7) temp = s3c2410_gpio_getpin(S3C2410_GPF7);
ret = put_user(temp, ((unsigned int *)arg));
break;
}
return ret;
}
#endif
struct file_operations gpio_2440_fops= {
.owner = THIS_MODULE,
.ioctl = gpio_ctl_ioctl,
.open = gpio_open,
.release = gpio_release,
};
struct cdev cdev;
int __init gpio_2440_init(void){
int ret;
dev_t dev = 0;
dev = MKDEV(IOPORT_MAJOR, 0);
ret = register_chrdev_region(dev, 1, "gpio_2440");
if(ret < 0 ) {
printk(KERN_ALERT "gpio_2440: can't get major %d!!\n", IOPORT_MAJOR);
return ret;
}
cdev_init(&cdev, &gpio_2440_fops);
cdev.owner = THIS_MODULE;
cdev.ops = &gpio_2440_fops;
ret = cdev_add(&cdev,dev,1);
if(ret)
printk(KERN_ALERT "gpio_2440: Error %d adding gpio_2440!!\n", ret);
else
printk(KERN_ALERT "gpio_2440:adding gpio_2440 at %x!!\n", dev);
printk(KERN_ALERT "gpio_2440: init!!\n");
return 0;
}
void gpio_2440_exit(void)
{
dev_t dev = 0;
dev = MKDEV(IOPORT_MAJOR, 0);
cdev_del(&cdev);
unregister_chrdev_region(dev, 1);
printk(KERN_WARNING "gpio_2440: exit!!\n");
}
module_init(gpio_2440_init);
module_exit(gpio_2440_exit);
MODULE_AUTHOR("mailzang <mail_zang@163.com> <http://mailzang.bokee.com>");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("GPIO driver For 2440");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -