基于xilinx zynq平台。
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/uaccess.h>
#include <linux/kdev_t.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include<linux/types.h>
#include<linux/device.h>
#include <linux/miscdevice.h>
#define LED_DATA 0x41200000
#define LED_CTRL 0x41200004
dev_t led_devt;
void __iomem *baseaddr;
static int led_major=25;
struct cdev *led_dev;
int led_value;
void led_gpio_set(void){
iowrite32(led_value, baseaddr);
}
static int led_open(struct inode *inode, struct file *filp){
struct resource *res;
int reg;
printk("begin: open led\n");
filp->private_data=inode->i_cdev;
res=request_mem_region(LED_DATA, 0x10000, "LED");
if(!res){
printk("failed requesting resource\n");
return 0;
}
printk("begin: remap led\n");
baseaddr=ioremap(LED_DATA, 0x10000);
if(!baseaddr){
printk("ERROR: couldn't allocate baseaddr\n");
return 0;
}
printk("baseaddr is %x\n", baseaddr);
printk("begin: read led\n");
reg=ioread32(baseaddr);
printk("begin: write led %d\n", reg);
reg &= 0xFFFFFFF0;
iowrite32(reg, baseaddr+4);
printk("SUCCESS: gpio init\n");
return 0;
}
static int led_release(struct inode *inode, struct file *filp){
iounmap(baseaddr);
release_mem_region(LED_DATA, 0x10000);
return 0;
}
ssize_t led_read(struct file * filp, char __user *buf, size_t cnt, loff_t *f_ops){
if(copy_to_user(buf, &led_value, cnt))
return -EFAULT;
return 1;
}
ssize_t led_write(struct file * filp, const char __user *buf, size_t cnt, loff_t *f_ops){
if(copy_from_user(&led_value, buf, cnt))
return -EFAULT;
led_gpio_set();
return 1;
}
static long led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){
return 1;
}
struct file_operations led_fops={
.owner=THIS_MODULE,
.read=led_read,
.write=led_write,
.unlocked_ioctl=led_ioctl,
.open=led_open,
.release=led_release,
};
static void led_setup_dev(int index){
int err;
int devno;
devno=MKDEV(led_major, index);
printk("MKDEV devno %d\n", devno);
cdev_init(led_dev, &led_fops);
printk("cdev_init %d\n", devno);
led_dev->owner=THIS_MODULE;
led_dev->ops=&led_fops;
err=cdev_add(led_dev, devno, 1);
if(err)
printk(KERN_ERR "ERROR: %d adding LED%d", err, index);
printk("SUCCESS: add dev %d\n", devno);
}
static int __init led_init(void){
int result;
printk("INIT:------------\n");
result=alloc_chrdev_region(&led_devt, 0, 1, "LED");
led_major=MAJOR(led_devt);
if(result<0){
printk(KERN_ERR "ERROR: allocate chrdev %d", led_devt);
return result;
}
printk("SUCCESS: allocate chrdev %d\n", led_devt);
led_dev=cdev_alloc();
if(!led_dev){
printk(KERN_ERR "ERROR: allocate device mem %d", led_devt);
result=-ENOMEM;
goto fail_malloc;
}
printk("SUCCESS: allocate device mem %d\n", led_devt);
led_setup_dev(0);
printk("SUCCESS: init device %d\n", led_devt);
return 0;
fail_malloc:
unregister_chrdev_region(led_devt, 1);
return result;
}
static void __exit led_cleanup(void){
cdev_del(led_dev);
unregister_chrdev_region(led_devt, 1);
printk("SUCCESS: exit device %d\n", led_devt);
}
module_init(led_init);
module_exit(led_cleanup);
MODULE_AUTHOR("Pingbo An");
MODULE_LICENSE("GPL v2");