Tiny6410的linux驱动程序:
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>
#include<linux/ioport.h>
#include<asm/io.h>
#include<asm/uaccess.h>
#include<linux/miscdevice.h>
#include<linux/fs.h>
#define DEVICE_NAME "tiny6410-led"
#define LED_IOC_MAGIC 'l'
#define LED_IOCGETDAT _IOR(LED_IOC_MAGIC,1,int) //定义ioctl命令从驱动程序当中获取参数
#define LED_IOCSETDAT _IOW(LED_IOC_MAGIC,2,int) //定义ioctl命令向驱动程序当中传递参数
#define LED_IOC_MAXNR 2
#define GPIOK_CON0_VA GPIOK_VA_BASE
#define GPIOK_CON1_VA GPIOK_VA_BASE+0X4
#define GPIOK_DAT_VA GPIOK_VA_BASE+0X8
#define GPIOK_PUD_VA GPIOK_VA_BASE+0XC
#define GPIOK_PA_BASE 0x7f008800
unsigned long GPIOK_VA_BASE;
static struct resource tiny6410_led_resource={
.name = "led io-mem",
.start = GPIOK_PA_BASE,
.end = GPIOK_PA_BASE+0x10,
.flags = IORESOURCE_MEM,
};
static void tiny6410_led_pin_setup(void)
{
unsigned long start = tiny6410_led_resource.start;
unsigned long size = tiny6410_led_resource.end-start;
unsigned long tmp;
request_mem_region(start,size,tiny6410_led_resource.name);//分配I/O内存
GPIOK_VA_BASE = (unsigned long)ioremap(start,size); //映射
printk("<1> [GPIOK_VA_BASE=0x%lx]\n",GPIOK_VA_BASE);
tmp=readl((void*)GPIOK_CON0_VA); //操作
tmp=(tmp & ~(0xffffU<<16))|(0x1111U<<16);
writel(tmp,(void *)GPIOK_CON0_VA);
tmp=readl((void *)GPIOK_DAT_VA);
tmp|=(0xF<<4);
writel(tmp,(void *)GPIOK_DAT_VA);
}
static void tiny6410_led_pin_release(void)
{
iounmap((void*)GPIOK_VA_BASE); //解除映射I/O内存
release_mem_region(tiny6410_led_resource.start,tiny6410_led_resource.end-tiny6410_led_resource.start); //释放I/O内存。
}
static unsigned long tiny6410_led_getdat(void)
{
return((readl((void *)GPIOK_DAT_VA)>>4)&0xf);
}
static void tiny6410_led_setdat(int dat)
{
unsigned long tmp;
tmp = readl((void *)GPIOK_DAT_VA);
tmp = (tmp&~(0xf<<4))|((dat&0xf)<<4);
writel(tmp,(void *)GPIOK_DAT_VA);
}
static long led_ioctl(struct file *filp,unsigned int cmd,unsigned long arg) //实现unlocked_ioctl设备方法
{
int ioarg,ret;
if(_IOC_TYPE(cmd)!=LED_IOC_MAGIC)
return -EINVAL;
if(_IOC_NR(cmd)>LED_IOC_MAXNR)
return -EINVAL;
switch (cmd){
case LED_IOCGETDAT:
ioarg = tiny6410_led_getdat();
ret = put_user(ioarg,(int *)arg);
break;
case LED_IOCSETDAT:
ret = get_user(ioarg,(int *)arg);
tiny6410_led_setdat(ioarg);
break;
default:
return -EINVAL;
}
return ret;
}
static struct file_operations dev_fops = { //定义了file_operations dev_fops
.owner = ((struct module *)0),
.unlocked_ioctl = led_ioctl,
};
static struct miscdevice misc={
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
static int __init dev_init(void)
{
int ret;
tiny6410_led_pin_setup();
ret=misc_register(&misc); //注册一个混杂设备。
printk(DEVICE_NAME" initialized minor=%d\n",misc.minor);\
return ret;
}
static void __exit dev_exit(void)
{
tiny6410_led_pin_release();
misc_deregister(&misc);
}
module_init(dev_init);
module_exit(dev_exit);
Makefile程序编写:
ifneq ($(KERNELRELEASE),)
obj-m :=led.o
else
KDIR := /lib/modules/`uname -r`/build //指示内核源代码的路径。
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers
endif