GPIO控制驱动,生成mtgpio使JNI可操作

JNI是Java Native Interface的缩写,通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植。JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。

1.DTS设备树文件匹配驱动配置

 46 / {
 47     model = "AIO-3399JD4 Board mipi (Android)";
 48     compatible = "rockchip,android", "rockchip,rk3399-raindi-mipi", "rockchip,rk3399";
 49
 50     rd_gpio: rd_gpio{
 51         status = "okay";
 52         compatible = "rockchip,rd_gpio";
 53         rd-gpio1 = <&gpio1 9 GPIO_ACTIVE_LOW>;//GPIO1_B1 -> GPIO41
 54         rd-gpio2 = <&gpio2 28 GPIO_ACTIVE_LOW>;//GPIO2_D4 -> GPIO92 GPIO2_A1 -> 65
 55     };
 56 };

2.gpio驱动:kernel/drivers/misc/rd_gpio.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/semaphore.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
#include <asm/delay.h>

#if 0
#define GPIO_IOC_MAGIC                              'G'
#define IOCTL_GPIO_SETINPUT                         _IOW(GPIO_IOC_MAGIC, 0, int)
#define IOCTL_GPIO_SETOUTHIGH                       _IOW(GPIO_IOC_MAGIC, 1, int)
#define IOCTL_GPIO_SETOUTLOW                        _IOW(GPIO_IOC_MAGIC, 2, int)
#define IOCTL_GPIO_GETVALUE                         _IOR(GPIO_IOC_MAGIC, 3, int)
#define GPIO_IOC_MAXNR                              3
#else
#define GPIO_IOC_MAGIC 0x90
#define GPIO_BASE_OFFSET        911
#define GPIO_IOCQMODE           _IOR(GPIO_IOC_MAGIC, 0x01, uint32_t)
#define GPIO_IOCTMODE0          _IOW(GPIO_IOC_MAGIC, 0x02, uint32_t)
#define GPIO_IOCTMODE1          _IOW(GPIO_IOC_MAGIC, 0x03, uint32_t)
#define GPIO_IOCTMODE2          _IOW(GPIO_IOC_MAGIC, 0x04, uint32_t)
#define GPIO_IOCTMODE3          _IOW(GPIO_IOC_MAGIC, 0x05, uint32_t)
#define GPIO_IOCQDIR            _IOR(GPIO_IOC_MAGIC, 0x06, uint32_t)
#define GPIO_IOCSDIRIN          _IOW(GPIO_IOC_MAGIC, 0x07, uint32_t)
#define GPIO_IOCSDIROUT         _IOW(GPIO_IOC_MAGIC, 0x08, uint32_t)
#define GPIO_IOCQPULLEN         _IOR(GPIO_IOC_MAGIC, 0x09, uint32_t)
#define GPIO_IOCSPULLENABLE     _IOW(GPIO_IOC_MAGIC, 0x0A, uint32_t)
#define GPIO_IOCSPULLDISABLE    _IOW(GPIO_IOC_MAGIC, 0x0B, uint32_t)
#define GPIO_IOCQPULL           _IOR(GPIO_IOC_MAGIC, 0x0C, uint32_t)
#define GPIO_IOCSPULLDOWN       _IOW(GPIO_IOC_MAGIC, 0x0D, uint32_t)
#define GPIO_IOCSPULLUP         _IOW(GPIO_IOC_MAGIC, 0x0E, uint32_t)
#define GPIO_IOCQINV            _IOR(GPIO_IOC_MAGIC, 0x0F, uint32_t)
#define GPIO_IOCSINVENABLE      _IOW(GPIO_IOC_MAGIC, 0x10, uint32_t)
#define GPIO_IOCSINVDISABLE     _IOW(GPIO_IOC_MAGIC, 0x11, uint32_t)
#define GPIO_IOCQDATAIN         _IOR(GPIO_IOC_MAGIC, 0x12, uint32_t)
#define GPIO_IOCQDATAOUT        _IOR(GPIO_IOC_MAGIC, 0x13, uint32_t)
#define GPIO_IOCSDATALOW        _IOW(GPIO_IOC_MAGIC, 0x14, uint32_t)
#define GPIO_IOCSDATAHIGH       _IOW(GPIO_IOC_MAGIC, 0x15, uint32_t)
#endif

struct rd_gpio_info{
    unsigned rd_gpio1;
    unsigned rd_gpio2;
}rd_gpio;

static ssize_t rd_gpios_show(struct device *dev,
                                struct device_attribute *attr,
                                char *buf)
{
    return scnprintf(buf, PAGE_SIZE,"PIN0:%d.PIN1:%d.\n",gpio_get_value(rd_gpio.rd_gpio1),
            gpio_get_value(rd_gpio.rd_gpio2));
}

static ssize_t rd_gpios_store(struct device *dev, 
                                struct device_attribute *attr,
                                const char *buf, size_t size)
{
    int value;
    int gpioNo;

    if (sscanf(buf, "%d,%d", &gpioNo,&value) != 2) {
        printk(KERN_ERR "%s: sscanf  %s is wrong \n", __func__,buf);
        return -EINVAL;
    }

    printk("setup gpio%d:%d\n",gpioNo,value);
    gpio_direction_output((uint16_t)gpioNo, value);

    return size;
}

//static DEVICE_ATTR(gpios, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, rd_gpios_show, rd_gpios_store);
static DEVICE_ATTR(gpios, S_IRUSR | S_IWUSR, rd_gpios_show, rd_gpios_store);

static struct attribute *rd_sysfs_attr[] = {
    &dev_attr_gpios.attr,
    NULL
};

static struct attribute_group rd_attribute_group = {
    .attrs = rd_sysfs_attr,
};


static int rd_gpio_is_valid(u32 pin)
{
    if(!gpio_is_valid(pin)){
        printk("rd-gpio: %d is invalid\n", pin);
        return -ENODEV;
    }

    return 0;
}


/*****************************************************************************/
/* File operation                                                            */
/*****************************************************************************/
static int gpio_open(struct inode *inode, struct file *file)
{
    printk("raindi gpio open \n");
    return 0;
}
/*---------------------------------------------------------------------------*/
static int gpio_release(struct inode *inode, struct file *file)
{
    printk("raindi gpio release\n");
    return 0;
}

static long gpio_ioctl(struct file *file,
                             unsigned int cmd, unsigned long arg)
{
    long ret = 0;
    u32 pin;

    pin = (u32)arg;
   
    printk("setup rd gpio cmd:%x  pin:%d\n",cmd,pin);

    if(!rd_gpio_is_valid(pin)){

        switch(cmd)
        {
            case GPIO_IOCQMODE:
            case GPIO_IOCTMODE0:
            case GPIO_IOCTMODE1:
            case GPIO_IOCTMODE2:
            case GPIO_IOCTMODE3:
            case GPIO_IOCQDIR:
            case GPIO_IOCSDIRIN:
            {
                gpio_direction_input(pin);
                break;
            }
            case GPIO_IOCSDIROUT:
            case GPIO_IOCQPULLEN:
            case GPIO_IOCSPULLENABLE:
            case GPIO_IOCSPULLDISABLE:
            case GPIO_IOCQPULL:
            case GPIO_IOCSPULLDOWN:
            case GPIO_IOCSPULLUP:
            case GPIO_IOCQINV:
            case GPIO_IOCSINVENABLE:
            case GPIO_IOCSINVDISABLE:
                break;
            case GPIO_IOCQDATAIN:
            case GPIO_IOCQDATAOUT:
            {
                ret = __gpio_get_value(pin);
                break;
            }
            case GPIO_IOCSDATALOW:
            {
                gpio_direction_output(pin, 0);
                break;
            }
            case GPIO_IOCSDATAHIGH:
            {
                gpio_direction_output(pin, 1);
                break;
            }

            default:
            {
                ret = -EPERM;
                break;
            }
        }
    }else {
        ret = -EPERM ;
    }

    if (ret == -EACCES)
        printk(" cmd = 0x%8X, invalid pointer\n", cmd);
    else if (ret < 0)
        printk(" cmd = 0x%8X, err = %ld\n", cmd, ret);

    return ret;
}


static struct file_operations rd_gpio_fops =
{
    .owner=        THIS_MODULE,
    .unlocked_ioctl=    gpio_ioctl,
    .compat_ioctl =     gpio_ioctl,
    .open=         gpio_open,
    .release=      gpio_release,
};
static struct miscdevice rd_gpio_device = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = "mtgpio",
    .fops = &rd_gpio_fops,
};



static int rd_gpio_probe(struct platform_device *pdev)
{
    int ret = 0;
    int gpio;
    int enable_value = 0;
    enum of_gpio_flags flag;
    struct rd_gpio_info *gpio_info;
    struct device_node *rd_gpio_node = pdev->dev.of_node;
    struct miscdevice *rd_misc = &rd_gpio_device;
 
    gpio_info = devm_kzalloc(&pdev->dev,sizeof(*gpio_info), GFP_KERNEL);
    if (!gpio_info) {
        dev_err(&pdev->dev, "devm_kzalloc failed!\n");
            return -ENOMEM;
    }
 
    gpio = of_get_named_gpio_flags(rd_gpio_node, "rd-gpio1", 0, &flag);
    if (!gpio_is_valid(gpio)) {
        dev_err(&pdev->dev, "rd-gpio1: %d is invalid\n", gpio);
        return -ENODEV;
    }
    if (gpio_request(gpio, "rd-gpio1")) {
        dev_err(&pdev->dev, "rd-gpio1: %d request failed!\n", gpio);
        gpio_free(gpio);
        return -ENODEV;
    }

    rd_gpio.rd_gpio1 = gpio;
    enable_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0:1;
    gpio_direction_output(gpio, enable_value);
    printk("rd_gpio1 gpio output: %d\n", enable_value);
 
    gpio = of_get_named_gpio_flags(rd_gpio_node, "rd-gpio2", 0, &flag);
    if (!gpio_is_valid(gpio)) {
        dev_err(&pdev->dev, "rd-gpio2: %d is invalid\n", gpio);
        return -ENODEV;
    }
    if(gpio_request(gpio, "rd-gpio2")){
        dev_err(&pdev->dev, "rd2-gpio2: %d request failed!\n", gpio);
        gpio_free(gpio);
        return -ENODEV;
    }
    
    rd_gpio.rd_gpio2 = gpio;
    enable_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0:1;
    gpio_direction_output(gpio, enable_value);
    printk("rd_gpio2 gpio output: %d\n", enable_value);

    ret = sysfs_create_group(&pdev->dev.kobj, &rd_attribute_group);
    //ret = class_register(&rd_class);
    if (ret < 0) {
        printk("rd Sysfs registration failed.\n");
        devm_kfree(&pdev->dev,gpio_info);
    }

    if ((ret = misc_register(rd_misc)))
        dev_err(&pdev->dev,"register rd_gpio misc device failed\n");

    return 0;
}

static const struct of_device_id rd_dt_ids[] = {
    { .compatible = "rockchip,rd_gpio", },
    {}
};

static struct platform_driver rd_gpio_driver = {
    .driver = {
        .name = "rd_gpio",
        .owner = THIS_MODULE,
        .of_match_table = rd_dt_ids,
    },
    .probe = rd_gpio_probe,
};
 
static int __init rd_gpio_init(void)
{
    return platform_driver_register(&rd_gpio_driver);
}
 
static void __exit rd_gpio_exit(void)
{
    platform_driver_unregister(&rd_gpio_driver);
}

module_init(rd_gpio_init);
module_exit(rd_gpio_exit);


MODULE_DESCRIPTION("Driver for GPIO");
MODULE_AUTHOR("w");
MODULE_LICENSE("GPL");

3.在同级目录下Makefile文件添加编译

obj-y               += rd_gpio.o
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值