Wei Dongshan Phase 2 Driver Encyclopedia-003_Layered Separation_Lesson 14 Driver Hierarchical Separation Concept_Bus Driver Device Model

One bus model

Insert picture description here
Brief description: This picture is reproduced from "The Concept of Separation and Layering of Linux Drivers"
.
The device is the code related to the hardware, and the driver is the relatively stable driver code.
When modifying the hardware part, only modify the things in dev.

Second, take gpio-keys.c as an example to analyze

  1. matchFunction analysis
static int platform_match(struct device * dev, struct device_driver * drv)
{
    
    
	struct platform_device *pdev = container_of(dev, struct platform_device, dev);

	return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
}

As you can see from the code, compare the two attributes dev->name and drv->name, and if they are equal, they match!
(1) Input parameter: drv parameter
struct device_driver * drv=gpio_keys_device_driver ->driver->name

//gpio_keys.c
struct platform_driver gpio_keys_device_driver = {
    
    
	.probe		= gpio_keys_probe,
	.remove		= __devexit_p(gpio_keys_remove),
	.driver		= {
    
    
		.name	= "gpio-keys",
	}
};

(2) Input parameter: The dev parameter is
struct device * dev=
not found. There is no dev supported by drv, so it is not easy to analyze. Let's refer to the "9th_led_bus_drv_dev" example written by Teacher Wei Dongshan for analysis

Three take 9th_led_bus_drv_dev as an example to analyze

  1. led_dev code:
...

/*分配资源*/
static struct resource led_resource[] = {
    
    
    [0] = {
    
    
        .start = 0x56000050,//起始地址
        .end   = 0x56000050 + 8 - 1,//终止地址
        .flags = IORESOURCE_MEM,//哪一类资源
    },
    [1] = {
    
    
        .start = 5,//对应的pin脚
        .end   = 5,//对应的pin脚
        .flags = IORESOURCE_IRQ,//哪一类资源
    }

};

static void led_release(struct device * dev)
{
    
    
}


static struct platform_device led_dev = {
    
    
    .name         = "myled",
    .id       = -1,
    .num_resources    = ARRAY_SIZE(led_resource),
    .resource     = led_resource,
    .dev = {
    
     
    	.release = led_release, //
	},
};

/* 注册一个platform_device */
static int led_dev_init(void)
{
    
    
	platform_device_register(&led_dev);
	return 0;
}

static void led_dev_exit(void)
{
    
    
	platform_device_unregister(&led_dev);
}

module_init(led_dev_init);
module_exit(led_dev_exit);

MODULE_LICENSE("GPL");
  1. led.drv code
...

static int major;


static struct class *cls;
static volatile unsigned long *gpio_con;
static volatile unsigned long *gpio_dat;
static int pin;

/*open函数*/
static int led_open(struct inode *inode, struct file *file)
{
    
    
	//printk("first_drv_open\n");
	/* 配置指定的pin脚为输出 */
	*gpio_con &= ~(0x3<<(pin*2));
	*gpio_con |= (0x1<<(pin*2));
	return 0;	
}
/*write函数*/
static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
    
    
	int val;

	//printk("first_drv_write\n");

	copy_from_user(&val, buf, count); //	copy_to_user();

	if (val == 1)
	{
    
    
		// 点灯
		*gpio_dat &= ~(1<<pin);
	}
	else
	{
    
    
		// 灭灯
		*gpio_dat |= (1<<pin);
	}
	
	return 0;
}


static struct file_operations led_fops = {
    
    
    .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    .open   =   led_open,     
	.write	=	led_write,	   
};

static int led_probe(struct platform_device *pdev)
{
    
    
	struct resource		*res;

	/* 根据platform_device的资源进行ioremap */
	
	//从pdev中获取IORESOURCE_MEM类资源中的第0个,把所有属性都赋给res变量
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	gpio_con = ioremap(res->start, res->end - res->start + 1);
	gpio_dat = gpio_con + 1;
	//从pdev中获取IORESOURCE_MEM类资源中的第0个,把所有属性都赋给res变量
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	pin = res->start;

	/* 注册字符设备驱动程序 */

	printk("led_probe, found led\n");

	major = register_chrdev(0, "myled", &led_fops);

	cls = class_create(THIS_MODULE, "myled");

	class_device_create(cls, NULL, MKDEV(major, 0), NULL, "led"); /* /dev/led */
	
	return 0;
}

static int led_remove(struct platform_device *pdev)
{
    
    
	/* 卸载字符设备驱动程序 */
	/* iounmap */
	printk("led_remove, remove led\n");

	class_device_destroy(cls, MKDEV(major, 0));
	class_destroy(cls);
	unregister_chrdev(major, "myled");
	iounmap(gpio_con);
	
	return 0;
}

/* 分配/设置/注册一个platform_driver */
struct platform_driver led_drv = {
    
    
	.probe		= led_probe,
	.remove		= led_remove,
	.driver		= {
    
    
		.name	= "myled",//与上面的dev.name相同,对应match函数
	}
};


static int led_drv_init(void)
{
    
    
	platform_driver_register(&led_drv);
	return 0;
}

static void led_drv_exit(void)
{
    
    
	platform_driver_unregister(&led_drv);
}

module_init(led_drv_init);
module_exit(led_drv_exit);

MODULE_LICENSE("GPL");
  1. experiment
#
# insmod led_drv.ko
# insmod led_dev.ko
led_probe, found led

Guess you like

Origin blog.csdn.net/xiaoaojianghu09/article/details/105104887