I.MX6 driver goto 使用

简介: /************************************************************************** * I.MX6 driver goto 使用 * 说明: * 在绝大多数地方,我们都被告诉尽可能不要用goto,甚至都没学过goto,但 * 这种语法却在内核驱动中普遍使用。
/**************************************************************************
 *                     I.MX6 driver goto 使用
 * 说明:
 *     在绝大多数地方,我们都被告诉尽可能不要用goto,甚至都没学过goto,但
 * 这种语法却在内核驱动中普遍使用。
 *
 *                                        2016-4-13 深圳 南山平山村 曾剑锋
 *************************************************************************/


#include <linux/module.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>

#define SABRESD_VO_PIN            IMX_GPIO_NR(1, 4)
#define SABRESD_AMPE_PIN          IMX_GPIO_NR(1, 5)
#define SABRESD_SD_PIN            IMX_GPIO_NR(1, 19)
#define SABRESD_DT_PIN            IMX_GPIO_NR(3, 20)

#define SPK_HEIGHT              66
#define SPK_LOW                 67
#define AMP_HEIGHT              68
#define AMP_LOW                 69
#define SD_HEIGHT               70
#define SD_LOW                  71
#define DETECT                  72

#define GPIO_CTRL_DEBUG
#ifdef GPIO_CTRL_DEBUG
    #define mDebug(format, ...) printk("File:%s, Function:%s, Line:%d  "format, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
    #define mDebug(format, ...)
#endif

static int gpioCtrl_open(struct inode *inode, struct file *file)
{
    mDebug("Dev open.\n");

    return 0;
}

static int gpioCtrl_close(struct inode *inode, struct file *file)
{
    mDebug("Dev close.\n");

    return 0;
}

static ssize_t gpioCtrl_read(struct file *file,
                        char __user *buf,
                        size_t count,
                        loff_t *pos)
{
    mDebug("Read data.\n");

    return 0;
}

static long gpioCtrl_ioctl(struct file * file, unsigned int cmd, unsigned long arg) {

    int ret = 0;

    switch ( cmd ) {
    case SPK_HEIGHT :
        gpio_set_value(SABRESD_VO_PIN, 1);
        mDebug("SPK_HEIGHT.\n");
        break;
    case SPK_LOW :
        gpio_set_value(SABRESD_VO_PIN, 0);
        mDebug("SPK_LOW.\n");
        break;
    case AMP_HEIGHT :
        gpio_set_value(SABRESD_AMPE_PIN, 1);
        mDebug("AMP_HEIGHT.\n");
        break;
    case AMP_LOW :
        gpio_set_value(SABRESD_AMPE_PIN, 0);
        mDebug("AMP_LOW.\n");
        break;
    case SD_HEIGHT :
        gpio_set_value(SABRESD_SD_PIN, 1);
        mDebug("SD_HEIGHT.\n");
        break;
    case SD_LOW :
        gpio_set_value(SABRESD_SD_PIN, 0);
        mDebug("SD_LOW.\n");
        break;
    case DETECT :
        ret = gpio_get_value(SABRESD_DT_PIN);
        (*(int *)arg) = ret;
        mDebug("DETECT ret = %d.\n", ret);

        ret = 0;
        break;
    default :
        mDebug("gpioCtrl control error.\n");
        ret =  -1;
        break;
    }
    return ret;
}


struct file_operations fops = {
    .owner      = THIS_MODULE,
    .open       = gpioCtrl_open,
    .release    = gpioCtrl_close,
    .read       = gpioCtrl_read,
    .unlocked_ioctl = gpioCtrl_ioctl,
};

struct miscdevice misc = {
    .minor  = MISC_DYNAMIC_MINOR,
    .name   = "gpioCtrl",
    .fops   = &fops,
};

int __init gpioCtrl_init(void)
{
    int ret;

    ret = gpio_request(SABRESD_VO_PIN, "SABRESD_VO_PIN");
    if ( ret ) {
        mDebug("get SABRESD_VO_PIN gpio FAILED!\n");
        return ret;
    }

    ret = gpio_request(SABRESD_AMPE_PIN, "SABRESD_AMPE_PIN");
    if ( ret ) {
        mDebug("get SABRESD_AMPE_PIN gpio FAILED!\n");
        goto fail1;
    }

    ret = gpio_request(SABRESD_SD_PIN, "SABRESD_SD_PIN");
    if ( ret ) {
        mDebug("get SABRESD_SD_PIN gpio FAILED!\n");
        goto fail2;
    }

    ret = gpio_request(SABRESD_DT_PIN, "SABRESD_DT_PIN");
    if ( ret ) {
        mDebug("get SABRESD_DETECT gpio FAILED!\n");
        goto fail3;
    }

    gpio_direction_output(SABRESD_VO_PIN, 0);
    gpio_direction_output(SABRESD_AMPE_PIN, 1);
    gpio_direction_output(SABRESD_SD_PIN, 1);
    gpio_direction_input(SABRESD_DT_PIN);

    ret = misc_register(&misc);
    if(ret) {
        mDebug("gpioCtrl_misc_register FAILED!\n");
        goto fail4;
    }

    mDebug("gpioCtrl_misc_register over!\n");
    return ret;

fail4:
    gpio_free(SABRESD_DT_PIN);
fail3:
    gpio_free(SABRESD_SD_PIN);
fail2:
    gpio_free(SABRESD_AMPE_PIN);
fail1:
    gpio_free(SABRESD_VO_PIN);
    
    return ret;
}

void __exit gpioCtrl_exit(void)
{
    gpio_set_value(SABRESD_VO_PIN, 0);
    gpio_set_value(SABRESD_AMPE_PIN, 0);
    gpio_set_value(SABRESD_SD_PIN, 0);

    gpio_free(SABRESD_VO_PIN);
    gpio_free(SABRESD_AMPE_PIN);
    gpio_free(SABRESD_SD_PIN);
    gpio_free(SABRESD_DT_PIN);

    misc_deregister(&misc);
}

module_init(gpioCtrl_init);
module_exit(gpioCtrl_exit);

MODULE_LICENSE("GPL");

 

目录
打赏
0
0
0
0
12
分享
相关文章
小程序 define is not defined
小程序 define is not defined
196 0
printk %pF %pS含义【转】
作者:啐楼链接:https://www.zhihu.com/question/37769890/answer/73532192来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
926 0
handle_level_irq 与handle_edge_irq 的区别【转】
转自:http://blog.csdn.net/xavierxiao/article/details/6087277 版权声明:本文为博主原创文章,未经博主允许不得转载。 Linux 里, handle_level_irq  *    Level type interrupts a...
1166 0
I.MX6 bq27441 GPOUT interrupt
/******************************************************************** * I.MX6 bq27441 GPOUT interrupt * 说明: * 由于目前的bq27441驱动中没有GPOUT中断驱动,所以需要另外加上,其 * 中有参考TI的驱动,但是内核版本不一致,所以处理方式也不一致。
819 0
I.MX6 Ethernet UI patch failed
/*********************************************************************** * I.MX6 Ethernet UI patch failed * 说明: * 最近想要在I.MX6的Android上添加Ethernet UI界面,但是使用NXP提供的 * patch,结果失败了。
1146 0
I.MX6 PMU MMPF0100 driver porting
/************************************************************************** * I.MX6 MMPF0100 driver porting * 说明: * 虽然主板上有MMPF0100芯片,却没有注册设备并使用该PMU驱动,真是浪费, * 当然因为需要,所以将PMU的驱动注册起来。
990 0
I.MX6 gpio-keys driver hacking
/**************************************************************************** * I.MX6 gpio-keys driver hacking * 说明: * 1. 本文解读gpio-keys驱动是如何注册,最终处理函数在哪里。
1155 0
I.MX6 U-boot Kernel backlight setting
/********************************************************************* * I.MX6 U-boot Kernel backlight setting * 说明: * 本文主要记录I.MX6 U-boot、Kernel中如何打开、关闭背光设置。
944 0
I.MX6 bq27441 driver hacking
/************************************************************************* * I.MX6 bq27441 driver hacking * 声明: * 本文主要是记录对电池计量芯片bq27441芯片驱动注册过程进行代码跟踪。
801 0
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等