rk3128 gpio开发

一、Rk3128 led 驱动

1、关于dts文件描述

瑞芯微平台上所有的gpio资源都是描述在dts 文件当中

dts 文件一般存放在kernel目录下 arch/arm/boot/dts/ 里面

全志平台的配置文件 一般为 sys_config.fex

存放路径lichee/brandy/pack/chips/sun8iw1p1/configs/android/

配置文件主要功能是用来统一管理cpu 平台资源,方便查看和修改

 

2、修改配置文件

cd /home/rk3128_4.4_tb01_new_v3/kernel/

vim arch/arm/boot/dts/rk3128-box.dts

新增gpio 管脚控制,描述如下,使用了 GPIO0_B0/GPIO0_D2/GPIO3_C5 

        work_led{

                compatible = "WorkLed";

                RED = <&gpio0 GPIO_B0 GPIO_ACTIVE_LOW>;

                GREEN = <&gpio0 GPIO_D2 GPIO_ACTIVE_LOW>;

                BULE = <&gpio3 GPIO_C5 GPIO_ACTIVE_LOW>;

                status = "okay";

        };

compatible 为驱动当中平台总线匹配的名字 WorkLed

RED = <&gpio0 GPIO_B0 GPIO_ACTIVE_LOW>;

描述的管脚名称为RED, 管脚IO 为: gpio 0组,B0这个管脚

status : 资源的状态状态,okay :表示使能 disable: 表示关闭

 

3、编写驱动代码

驱动探测函数当中匹配的名字为:WorkLed

static const struct of_device_id of_workled_match[] = {

        { .compatible = "WorkLed", },

        {},

};

static struct platform_driver workled_driver = {

        .probe          = workled_probe,

        .remove         = workled_remove,

        .driver         = {

                .name   = "rk3128_led",

                .owner  = THIS_MODULE,

                .of_match_table = of_match_ptr(of_workled_match),

        },

};

4、采用平台总线进行注册获取IO资源

platform_driver_register(&workled_driver);

5、申请gpio 资源

探测到之后,在workled_probe 函数当中申请gpio 资源

通过如下函数进行申请管脚

unsigned int pin = of_get_named_gpio(pdev->dev.of_node, “RED”, 0);

devm_gpio_request(&pdev->dev,Led[i].pin, “RED”);

通过如下函数进行操作gpio 引脚

gpio_direction_output(pin,1);  //设置管脚为输出模式,输出高电平

gpio_direction_input(pin); //设置管脚为输入模式

gpio_set_value(pin,1); //设置管脚输出高电平

int state = gpio_get_value(pin);  //获取管脚电平状态

6、完整驱动代码如下

workled.c

#include <linux/init.h>

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/miscdevice.h>

#include <linux/interrupt.h>

#include <linux/mm.h>

#include <linux/gpio.h>

#include <linux/of_gpio.h>

#include <linux/input.h>

#include <linux/slab.h>

#include <linux/timer.h>

#include <linux/time.h>

#include <linux/jiffies.h>

#include <linux/platform_device.h>

 

#define DEBUG 1

#ifdef DEBUG

#define dbg(x...) printk(x)

#else

#define dbg(x...) (void)(0)

#endif

 

#define RED_LED         0x01

#define GREEN_LED       0x02

#define BULE_LED        0x03

 

#define WORK_LED_SIZE   (sizeof(Led)/sizeof(WorkLed))

typedef struct{

        unsigned int pin;

        char name[16];

}WorkLed;

 

static struct platform_device *getpdev=NULL;

 

WorkLed Led[3]={{0,"RED"},{0,"GREEN"},{0,"BULE"}};

static int workled_open(struct inode *inode, struct file *filp)

{

    dbg("workled has been open!\n");

    return -1;

}

static int workled_release(struct inode *inode, struct file *filp)

{

    dbg("workled has not been open yet!\n");

    return -1;

}

 

static ssize_t workled_read(struct file *filp, char *buf,

        size_t count, loff_t fpos)

{

    dbg("workled read!\n");

    return 0;

}

 

static ssize_t workled_write(struct file *filp, char *buf,

        size_t count, loff_t fpos)

{

    dbg("workled write!\n");

    return 0;

}

 

static void ctrl_workled(unsigned int pin,int state)

{

        if(state)

        {

                if (gpio_is_valid(pin)&&pin!=0)

                {

                        gpio_set_value(pin,0);  //close  led

                }

        }else{

                if (gpio_is_valid(pin)&&pin!=0)

                {

                        gpio_set_value(pin,1);  // open led

                }

        }

}

int workled_ioctl(struct inode *inode, struct file *filp,

        unsigned int cmd, unsigned long arg)

{

        dbg("cmd:%d arg:%d\n", cmd, arg);

        switch(cmd)

        {

                case RED_LED:

                        ctrl_workled(Led[0].pin,arg);

                        break;

                case GREEN_LED:

                        ctrl_workled(Led[1].pin,arg);

                        break;

                case BULE_LED:

                        ctrl_workled(Led[2].pin,arg);

                        break;

                default:

                        break;

        }

        return 0;

}

struct file_operations fops =

{

    .owner              =   THIS_MODULE,

    .open               =   workled_open,

    .release            =   workled_release,

    .write              =   workled_write,

    .read               =   workled_read,

    .unlocked_ioctl     =   workled_ioctl

};

 

static struct miscdevice dev =

{

    .minor  =   MISC_DYNAMIC_MINOR,

    .fops    =   &fops,

    .name   =   "workled",

    .nodename = "workled_node"

};

static void gpioFree(unsigned int pin)

{

        if (gpio_is_valid(pin)&&pin!=0){

                gpio_free(pin);

        }

}

static int request_WorkLed(struct platform_device *pdev)

{

        int i,free;

        int err = 0;

        for(i=0;i<WORK_LED_SIZE;i++)

        {

                Led[i].pin = of_get_named_gpio(pdev->dev.of_node, Led[i].name, 0);

                if (!gpio_is_valid(Led[i].pin))

                {

                        dbg("invalid Led[%d].pin: %d \n",i,Led[i].pin);

                        goto err1;

                }

                if (devm_gpio_request(&pdev->dev,Led[i].pin, Led[i].name))

                {

                        dbg("devm_gpio_request Led[%d].pin 0x%2x request failed name =%s \n",i,Led[i].pin,Led[i].name);

                        goto err1;

                }

        }

        gpio_direction_output(Led[0].pin,1);

        gpio_direction_output(Led[1].pin,1);

        dbg("gpio request ok .......\n");

        return 0;

err1:

        free=i;

        //for(i=0;i<free;i++)  //bug

        for(i=0;i<WORK_LED_SIZE;i++)

        {

                gpioFree(Led[i].pin);

                Led[i].pin=0;

        }

        return -1;

}

static void free_WorkLed(void)

{

        int i=0;

        for(i=0;i<WORK_LED_SIZE;i++)

        {

                dbg("free gpio Led[%d].pin = %d\n",i,Led[i].pin);

                gpioFree(Led[i].pin);

        }

}

 

static int workled_probe(struct platform_device *pdev)

{

        getpdev = pdev;

        request_WorkLed(pdev);

        return misc_register(&dev);

}

static int workled_remove(struct platform_device *pdev)

{

        dbg("key remove ok \n");

        return 0;

}

static const struct of_device_id of_workled_match[] = {

        { .compatible = "WorkLed", },

        {},

};

 

static struct platform_driver workled_driver = {

        .probe          = workled_probe,

        .remove         = workled_remove,

        .driver         = {

                .name   = "rk3128_led",

                .owner  = THIS_MODULE,

                .of_match_table = of_match_ptr(of_workled_match),

        },

};

static int __init workled_init(void)

{

        dbg("workled init ! ... \n");

        return platform_driver_register(&workled_driver);

}

static void __exit workled_exit(void)

{

    platform_driver_unregister(&workled_driver);

    //free_WorkLed();

    misc_deregister(&dev);

    dbg("workled exit ok!\n");

}

module_init(workled_init);

module_exit(workled_exit);

MODULE_LICENSE("Dual BSD/GPL");

7Makefile 如下 

CONFIG_CHARDEV ?=m

obj-$(CONFIG_CHARDEV) +=workled.o

 

KERN_DIR =/home/rk3128/rk3128_4.4_tb01_v3/kernel/

 

modules:

        $(MAKE) -C $(KERN_DIR) M=$(PWD) modules

clean:

        rm -rf  chartest *.o *~core .depend. *.cmd *.ko *.mod.c .tmp_versions

8、将驱动上传到板子,进行调试

adb push *.ko /mnt/sdcard/

adb登录板子,转载驱动调试

adb shell  

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值