RK3399 Android7.1系统,GPIO内核驱动开发

1. 方案背景

产品使用的RK3399核心板,电路板外围电路及模块功能自定义,项目需要增加gpio控制的功能。  由于在用户空间,通过系统命令的方式控制GPIO,拉高拉低的速度响应速度比较慢,而通过内核驱动的方式较快,所以需要开发个内核驱动来控制GPIO。
注意,本文使用的是gpio68号引脚,并非控制所有引脚。

2. 编译及驱动源码

1. kernel/drivers/char/Makefile 添加gpio68.o的编译

obj-y				+= gpio68.o

2. 新建 kernel/drivers/char/gpio68.c  源码文件。

gpio68.c 源码如下:

#include <linux/module.h>               /* For module specific items */    
#include <linux/moduleparam.h>          /* For new moduleparam's */    
#include <linux/types.h>                /* For standard types (like size_t) */    
#include <linux/errno.h>                /* For the -ENODEV/... values */    
#include <linux/kernel.h>               /* For printk/panic/... */    
#include <linux/fs.h>                   /* For file operations */    
#include <linux/ioport.h>               /* For io-port access */    
#include <linux/platform_device.h>      /* For platform_driver framework */    
#include <linux/init.h>                 /* For __init/__exit/... */    
#include <linux/uaccess.h>              /* For copy_to_user/put_user/... */    
#include <linux/io.h>                   /* For inb/outb/... */    
#include <linux/gpio.h>    
#include <linux/device.h>    
#include <linux/cdev.h>    
#include <linux/slab.h>               /*kamlloc */    
#include <asm-generic/ioctl.h>    

 //ioctl   
#define CMD_FLAG  'i'    
#define gpio_PWR_ON      _IOR(CMD_FLAG,0x00000001,__u32)      
#define gpio_PWR_OFF     _IOR(CMD_FLAG,0x00000000,__u32)   
#define gpio_lp         68  

static int  major =0;    
static struct class *gpio_class;    
struct cdev_gpio {    
    struct cdev cdev;    
};     
struct cdev_gpio *gpio_dev;    

static long gpio_ioctl(struct file* filp, unsigned int cmd,unsigned long argv)    
{    
    printk(KERN_INFO "entry kernel.... \n");    
    //printk(KERN_INFO "%d\n", gpio_PWR_ON);  
    //void __iomem *ldo_mmio_base = ioremap(0xe46002e4, 4);

    switch(cmd)    
    {    
        case gpio_PWR_ON:    
        {    
            gpio_set_value(gpio_lp,1);  //   
            printk(KERN_INFO "gpio on\n");   
            //iowrite32(0x1700, ldo_mmio_base)  
            break;    
        }    
        case gpio_PWR_OFF:    
        {    
            gpio_set_value(gpio_lp,0);  
            printk(KERN_INFO "gpio off \n");  
            //iowrite32(0x1500, ldo_mmio_base);  
            break;    
        }    
        default:    
            return -EINVAL;    
    }    
    return 0;    
}    


//open    
static int gpio_open(struct inode* i_node,struct file* filp)    
{    
    //printk(KERN_INFO "open init.... \n");    
    int err = gpio_request(gpio_lp,"gpio_pwr");  
    if(err<0)    
    {    
        printk(KERN_INFO "gpio request faile \n");    
        return err;    
    }    
    gpio_direction_output(gpio_lp,1);  
    return 0;    
}    

//close    
static int  gpio_close(struct inode* i_node,struct file* filp)    
{    
    printk(KERN_INFO "close init \n"); 
    gpio_free(gpio_lp);   
    return 0;    
}    

/* file operations */    
struct file_operations fops={    
    .owner  = THIS_MODULE,    
    .open   = gpio_open,    
    .unlocked_ioctl = gpio_ioctl,   
    .release = gpio_close,    
};    

static int __init gpio_init(void)    
{    
    //printk(KERN_INFO "init .... \n");    
    dev_t dev_no;    
    int result,err;    
    err = alloc_chrdev_region(&dev_no,0,1,"my_gpio"); //dynamic request device number    
    if(err<0)    
    {    
        printk(KERN_INFO "ERROR\n");    
        return err;    
    }    
    major = MAJOR(dev_no);    
    gpio_dev = kmalloc(sizeof(struct cdev_gpio),GFP_KERNEL);    
    if(!gpio_dev)    
    {    
        result = -ENOMEM;    
        goto fail_malloc;    
    }    
    memset(gpio_dev,0,sizeof(*gpio_dev));    

    cdev_init(&gpio_dev->cdev,&fops);     
    gpio_dev->cdev.owner = THIS_MODULE;    
    result = cdev_add(&gpio_dev->cdev,dev_no,1);     
    if(result <0)    
    {   printk(KERN_INFO "error\n");    
        goto fail_add;    
    }    
    gpio_class = class_create(THIS_MODULE,"mtgpio68");  //in sys/class create sysfs file    
    device_create(gpio_class,NULL,MKDEV(major,0),NULL,"gpio68"); //dynamic create device file  /dev/mygpio    
    return 0;    
fail_add:    
    kfree(gpio_dev);    
fail_malloc:    
    unregister_chrdev_region(dev_no,1);    
    return result;    

}    

static void __exit gpio_exit(void)    
{    
    dev_t dev_no=MKDEV(major,0);    

    unregister_chrdev_region(dev_no,1);    
    cdev_del(&gpio_dev->cdev);    
    kfree(gpio_dev);    
    device_destroy(gpio_class,dev_no);    
    class_destroy(gpio_class);    
    printk(KERN_INFO "exit........ \n");    
}    
module_init(gpio_init);    
module_exit(gpio_exit);    
MODULE_AUTHOR("");    
MODULE_DESCRIPTION("control_gpio68");    
MODULE_LICENSE("GPL");   

Android 系统编译相关文章

 

 

评论列表: