瑞芯微Rockchip开发者社区
直播中

青sky

8年用户 1272经验值
擅长:模拟技术
私信 关注
[问答]

请问一下RK3288 LED的驱动平台设备是如何去实现的

请问一下RK3288 LED的驱动平台设备是如何去实现的?

回帖(2)

陈茹

2022-3-3 15:49:58
platform接口学习

//返回dev中类型为type的,第num个资源
struct resource *platform_get_resource(struct platfrom_device *dev,
                        unsigned int type, unsigned int num);

//返回该dev所用的第num个中断号
int platform_get_irq(struct platform_device *dev, unsigned int num);

//通过名字返回dev的给类型的资源
struct resource *platform_get_resource_byname(struct platform_device *dev,
                        unsigned int type, const char *name);

//名字名称给dev的中断号
)int platform_dev_irq_byname(结构体平台_开发者,*

对o返回的设备_开发板_获取程序


,继续的预测板_一个_led。 chip_demoo_gpio.c,一个是资源文件一个是硬件操作代码。
所以这次的修改方向是



  • board_A_led修改成platform_device结构,主要是资源文件。
  • chip_demoo_gpio.c修改成platform_driver结构。主要是芯片引脚相关的操作,并且当probe和remove时包含具体字符设备创建。
  • leddrv.c则是负责和应用层的交互,还有字符设备的注册,class的创建。


我理解的平台总线的结构:



  • platform_device是一个led单独的模块,它只是一些资源的定义。相关的文件主要是board_A_led.c
  • platform_driver是对芯片的的驱动抽象化,是对芯片引脚的配置,probe和remove是通过对platform_device提供的资源去注册具体的字符设备。同时在chip_demo_gpio文件中还有led的引脚初始化,led的控制的实现函数。相关文件是chip_demo_gpio.c和leddrv.h,具体led引脚接口是用led_opr.h声明的。
  • 而led的驱动设置,如字符设备相关的操作,还是在leddrv.c中。led的内容是与应用层接***互,如open,wirte,close,read相关的实现。但是led的init和ctl函数只是调用。操作引脚的指针是通过register_led_operations传递的。



代码内容


Makefile


KERN_DIR = /home/book/Documents/100ask_firefly-rk3288/linux-4.4

all:
        make -C $(KERN_DIR) M=`pwd` modules
        $(CROSS_COMPILE)gcc -o led_app led_app.c -Wno-error=未使用但设置变量

clean:
        make -C $(KERN_DIR) M=`pwd` modules clean
        rm -rf modules.order
        rm -f hello_drv_test


#myled_drv-y:=led_drv.o board_demoo.o
obj-m += board_A_led.o chip_demoo_gpio.o led_drv.o

board_A_led.c:


#include
#include
#include
#include "led_resource.h"

struct resource led_resources [] = {
        {
                .start = GROUP_PIN(8,1),
                .flags = IORESOURCE_IRQ,
                .name = "myled0",
        },
        {
                .start = GROUP_PIN(8,2),
                .flags = IORESOURCE_IRQ,
                .name = "myled1",
        },
} ;

struct resource *get_led_resource(void)
{
    return led_resources;
}

static void led_dev_release(struct device *pdev)
{

}

static struct platform_device led_device = {
        .name = "myled",
        .resource = led_resources,
        .num_resources = ARRAY_SIZE(led_resources),
        .dev = {
                .release = led_dev_release,
        },
};

静态 int led_device_init(void)
{
        int err;
        错误 = platform_device_register(&led_device);
        返回错误;
}

静态无效 led_device_exit(void)
{
        platform_device_unregister(&led_device);
}

module_init(led_device_init);
module_exit(led_device_exit);
MODULE_LICENSE("GPL");

chip_demoo_gpio.c:


#include
#include
#include
#include
#include
#包括“led_resource.h”
#include“
#include "led_drv.h"

static unsigned int led_pins[100];
静态整数 resPinCount;

#define CRU_BASE_PHY_ADDRESS ((unsigned long)(0xff760000))
#define GRF_BASE_PHY_ADDRESS ((unsigned long)(0xff770000))
#define GPIO8_BASE_PHY_ADDRESS ((unsigned long)(0xff7f0000))


#define CRU_CLKGATE14_PHY_CON (0x0198)
#define GRF_008ADDRESS ((unsigned long)(0xff7f0000))
#define GRF_0008A GPIO_SWPORTA_PHY_DR (0x0000)
#define GPIO_SWPORTA_PHY_DDR (0x0004)

static volatile unsigned int *CRU_CLKGATE14_CON;
静态易失性无符号整数*GRF_GPIO8A_IOMUX;
静态易失无符号整数 *GPIO8_SWPORTA_DDR;
静态易失无符号整数 *GPIO8_SWPORTA_DR;

静态 int board_demo_led_init(int which)
{
   
        printk("%s 哪个 %d", __FUNCTION__, which);
        if(GROUP(led_pins[which]) == 8) {
                if(!CRU_CLKGATE14_CON) {
                        CRU_CLKGATE14_CON = ioremap(CRU_BASE_PHY_ADDRESS + CRU_CLKGATE14_PHY_CON, 4);
                        GRF_GPIO8A_IOMUX = ioremap(GRF_BASE_PHY_ADDRESS + GRF_GPIO8A_PHY_IOMUX, 4);
                        GPIO8_SWPORTA_DDR = ioremap(GPIO8_BASE_PHY_ADDRESS + GPIO_SWPORTA_PHY_DDR, 4);
                        GPIO8_SWPORTA_DR = ioremap(GPIO8_BASE_PHY_ADDRESS + GPIO_SWPORTA_PHY_DR, 4);
                }

                if(PIN(led_pins[which]) == 1) {
                        *CRU_CLKGATE14_CON = (1<<(8+16)) | (0<<8);
                        *GRF_GPIO8A_IOMUX |= (3<<(2+16)) | (0<<2);
                        *GPIO8_SWPORTA_DDR |= (1<<1);
                } else if(PIN(led_pins[which]) == 2) {
                        *CRU_CLKGATE14_CON = (1<<(8+16)) | (0<<8);
                        *GRF_GPIO8A_IOMUX |= (3<<(4+16)) | (0<<4);
                        *GPIO8_SWPORTA_DDR |= (1<<2);
                }
        }

        返回 0;

}

static int board_demo_led_ctrl(int which, char status)
{
        printk("%s which %d, status %c", __FUNCTION__, which, status);
        if(PIN(led_pins[which]) == 1) {
                if(status) { /* on: 输出 0 */
                        *GPIO8_SWPORTA_DR &= ~(1<<1);
                } else { /* 关闭:输出 1 */
                        *GPIO8_SWPORTA_DR |= (1<<1);
                }
        } else if(PIN(led_pins[which]) == 2) {
                if(status) {
                        *GPIO8_SWPORTA_DR &= ~(1<<2);
                } else {
                        *GPIO8_SWPORTA_DR |= (1<<2);
                }
        }
        返回 0;
}

静态结构 led_operations led_opr = {
        .init = board_demo_led_init,
        .ctl = board_demo_led_ctrl,
};

结构 led_operations *get_board_led_ops(void)
{
        返回 &led_opr;
}

静态 int led_platform_driver_probe(struct platform_device *pdev)
{
        int i = 0;
        结构资源 *res;
        while(1) {
                //1. 获取板 A LED 资源
                res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
                if(res == NULL) {
                        中断;
                }
                led_pins = res->开始;
                resPinCount++;

                //2。创建设备
                led_class_create_device(i);
                我++;
        }
        返回 0;
}

static int led_platform_driver_remove(struct platform_device *pdev)
{
        struct resource *res;
        while(1) {
                //1. get board a led resource
                res = platform_get_resource(pdev, IORESOURCE_IRQ, resPinCount);
                if(res == NULL) {
                        break;
                }
                //2. destory device
                led_class_destroy_device(resPinCount);
                resPinCount--;
        }
        return 0;
}

static struct platform_driver led_driver = {
        .driver = {
                .name = "myled",
        },
        .probe = led_platform_driver_probe,
        .remove = led_platform_driver_remove,
};

static int led_platform_driver_init(void)
{
        int err;
        err = platform_driver_register(&led_driver);
        register_led_operations(&led_opr);
        return 0;
}

static void led_platform_driver_exit(void)
{
        platform_driver_unregister(&led_driver);
}

module_init(led_platform_driver_init);
module_exit(led_platform_driver_exit);
MODULE_LICENSE("GPL");

led_drv.c


#include
#include
#include
#include
#include
#include
#include
#include
#include

#include "led_ops.h"
#include "led_drv.h"

static int major = 0;
static struct class *led_class;
struct led_operations *p_led_ops;

void led_class_create_device(int index)
{
        device_create(led_class, NULL, MKDEV(major, index), NULL, "myled%d", index);
}

void led_class_destroy_device(int index)
{
        device_destroy(led_class, MKDEV(major, index));
}

void register_led_operations(struct led_operations *led_opr)
{
        p_led_ops = led_opr;
}

EXPORT_SYMBOL(led_class_create_device);
EXPORT_SYMBOL(led_class_destroy_device);
EXPORT_SYMBOL(register_led_operations);

static int led_drv_open(struct inode *node, struct file *file)
{
        int minor = iminor(node);
        printk("%s %s line %dn", __FILE__, __FUNCTION__, __LINE__);

        p_led_ops->init(minor);      
        return 0;
}

static ssize_t led_drv_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
{
        printk("%s %s line %dn", __FILE__, __FUNCTION__, __LINE__);
        return 0;
}

static ssize_t led_drv_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
        int err;
        char status;
        struct inode *inode = file_inode(file);
        int minor = iminor(inode);

        printk("%s %s line %dn", __FILE__, __FUNCTION__, __LINE__);
        err = copy_from_user(&status, buf, 1);
        printk("write status:%x n", status);

        p_led_ops->ctl(minor, status);
      
        return 1;
}

举报

胡书琴

2022-3-3 15:50:02
static int led_drv_close(struct inode *node, struct file *file)
{
        printk("%s %s line %dn", __FILE__, __FUNCTION__, __LINE__);
        return 0;
}


static struct file_operations led_drv = {
        .owner = THIS_MODULE,
        .open = led_drv_open,
        .read = led_drv_read,
        .write = led_drv_write,
        .release = led_drv_close,
};

static int __init led_drv_init(void)
{
        int err;
        major = register_chrdev(0, "myled", &led_drv);

        led_class = class_create(THIS_MODULE, "led_class");
        err = PTR_ERR(led_class);
        if(IS_ERR(led_class)) {
                unregister_chrdev(major, "myled");      
                printk(KERN_WARNING "class creatge failed %dn", err);
                return -1;
        }
      
        printk("%s %sled_drv_initn", __FILE__, __FUNCTION__);
        return 0;
}

static void __exit led_drv_exit(void)
{
        printk("%s %sled_drv_exitn", __FILE__, __FUNCTION__);

        class_destroy(led_class);
        unregister_chrdev(major, "myled");      
}

module_init(led_drv_init);
module_exit(led_drv_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("chen");

led_drv.h


#ifndef __LED_DRV_H_         
#define __LED_DRV_H_

void led_class_create_device(int index);
void led_class_destroy_device(int index);
void register_led_operations(struct led_operations *led_opr);

#endif

led_ops.h


#ifndef __LED_OPS_H_
#define __LED_OPS_H_

struct led_operations {
        int (*init)(int which);                        /* init led, which:led num  */
        int (*ctl)(int which, char status);                /* control led, whic:led num,status:0-On 1-Off */
};

struct led_operations *get_board_led_ops(void);

#endif

led_resource.h


#ifndef _LED_RESOUCE_H
#define _LED_RESOUCE_H

/* bit[31:16] = group */
/* bit[15:0] = which pin */
#define GROUP(x)    (x>>16)
#define PIN(x)      (x&0xffff)
#define GROUP_PIN(g, p) ((g<<16| (p)))

struct resource *get_led_resource(void);

#endif

led_app.c:


#include
#include
#include
#include
#include
#include

void showUsage(void)
{
        printf("app [dev_path] [on,off]n");
}

int main(int argc, char *argv[])
{
        char status;
        if(argc < 3) {
                showUsage();
                return -1;
        }

        int fd = open(argv[1], O_RDWR);
        if(fd < 0) {
                printf("app open device failed path:%s", argv[1]);
                return -1;
        }

        if(0 == strcmp(argv[2], "on")) {
                status = 1;
                int ret = write(fd, &status, 1);
                if(ret <= 0) {
                        printf("app 写入设备失败 %s",argv[2]);
                        返回-1;
                } else {
                        printf("app write device %x", status);
                }

        } else if(0 == strcmp(argv[2], "off")) {
                status = 0;
                int ret = write(fd, &status, 1);
                if(ret <= 0) {
                        printf("app write device fialed %s",argv[2]);
                        返回-1;
                } else {
                        printf("app write device %x", status);
                }
        }


        返回 0;
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分