1、通过 echo "on" >dev/io_led0 点亮 gpio7_b5 led
通过 echo "off" >dev/io_led0 熄灭 gpio7_b5 led
/*************************************************************************
> File Name: chr_dev.c
> Author: Bond
> Created Time: 2021年03月30日 星期三 13时44分36秒
************************************************************************/
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <asm/io.h>
#define DBUG true
#define DEBUG(x...) if(DBUG){printk(x);}
#define DEV_MAJOR 230
#define MAYJOR_MAGIC 'c'
#define GLOBALMEM_SIZE 0x1000
#define DEVICE_NUM 1
#define MEM_CLEAR _IOWR(MAYJOR_MAGIC,0,int)
volatile unsigned long *grf_gpio7b_iomux = NULL;
volatile unsigned long *grf_gpio7b_p = NULL;
volatile unsigned long *grf_gpio7b_spdr = NULL;
volatile unsigned long *grf_gpio7b_spdd = NULL;
static int devmem_major = DEV_MAJOR;
module_param(devmem_major,int,S_IRUGO);
struct chrmem_dev{
struct device *dev_devcie;
struct cdev c_dev;
};
struct class *dev_class;
static struct chrmem_dev *pchrmem_dev;
static int chr_dev_open(struct inode *inode, struct file *filp){
return 0;
}
static int chr_dev_release(struct inode *inode,struct file* filp){
return 0;
}
static long chr_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){
return 0;
}
static ssize_t chr_dev_read(struct file *filp, char __user *buffer, size_t size, loff_t *f_pos){
int ret=0;
return ret;
}
static ssize_t chr_dev_write(struct file *filp,
const char __user *buffer,
size_t size,
loff_t *f_pos)
{
int ret;
char kbuf[10];
memset(kbuf,0,10);
ret = copy_from_user(kbuf,buffer,size);
if(ret){
return -EFAULT;
}
*grf_gpio7b_iomux = (~((1<<11)|(1<<10)))|(0xffff<<16);
*grf_gpio7b_spdd |=(1<<13);
if(!strncmp("on",kbuf,strlen("on"))){
*grf_gpio7b_spdr |=(1<<13);
}else if(!strncmp("off",kbuf,strlen("off"))){
*grf_gpio7b_spdr &=~(1<<13);
}
return size;
}
static loff_t chr_dev_llseek(struct file *filp, loff_t offset, int orignal){
loff_t ret = 0;
return ret;
}
static const struct file_operations chr_dev_fops = {
.owner = THIS_MODULE,
.open = chr_dev_open,
.read = chr_dev_read,
.write = chr_dev_write,
.llseek = chr_dev_llseek,
.release = chr_dev_release,
.unlocked_ioctl = chr_dev_ioctl,
};
static int chr_dev_setup(struct chrmem_dev *dev,struct class *dev_class,int index){
int err,devno;
devno = MKDEV(devmem_major,index);
cdev_init(&dev->c_dev,&chr_dev_fops);
dev->c_dev.owner = THIS_MODULE;
err = cdev_add(&dev->c_dev,devno,1);
dev->dev_devcie = device_create(dev_class,NULL,devno,NULL,"io_led%d",index);
return err;
}
static int __init chr_dev_init(void){
int ret = 0,i = 0;
dev_t devno = MKDEV(DEV_MAJOR,0);
grf_gpio7b_iomux = (volatile unsigned long*)ioremap(0xff770070,4);
grf_gpio7b_p = (volatile unsigned long*)ioremap(0xff7701a4,4);
grf_gpio7b_spdr = (volatile unsigned long*)ioremap(0xff7e0000,4);
grf_gpio7b_spdd = (volatile unsigned long*)ioremap(0xff7e0004,4);
if(devmem_major){
ret = register_chrdev_region(devno,DEVICE_NUM,"chrdevmem");
}else{
ret = alloc_chrdev_region(&devno,0,DEVICE_NUM,"chrdevmem");
devmem_major = MAJOR(devno);
}
if(ret){
return -ENOTBLK;
}
pchrmem_dev = kzalloc(sizeof(struct chrmem_dev)*DEVICE_NUM,GFP_KERNEL);
if(!pchrmem_dev){
ret = -ENOMEM;
goto fail_kzalloc;
}
dev_class = class_create(THIS_MODULE,"io_chr");
for(i=0;i<DEVICE_NUM;i++){
chr_dev_setup(pchrmem_dev+i,dev_class,i);
}
return ret;
fail_kzalloc:
unregister_chrdev_region(devno,DEVICE_NUM);
return ret;
}
static void __exit chr_dev_exit(void){
int i=0;
iounmap(grf_gpio7b_iomux);
iounmap(grf_gpio7b_p);
iounmap(grf_gpio7b_spdd);
iounmap(grf_gpio7b_spdr);
unregister_chrdev_region(MKDEV(devmem_major,0), DEVICE_NUM); // жÔØ
kfree(pchrmem_dev);
for(i=0;i<DEVICE_NUM;i++){
device_destroy(dev_class,MKDEV(devmem_major,i));
}
class_destroy(dev_class);
}
module_init(chr_dev_init);
module_exit(chr_dev_exit);
MODULE_AUTHOR("Bond <xxxx@163.com>");
MODULE_DESCRIPTION("char dev driver");
MODULE_LICENSE("GPL");