Linux内核启动过程中注册platform驱动模型
来源:互联网 发布:知豆电动汽车价格 编辑:程序博客网 时间:2024/06/05 11:00
static int __init kernel_init(void * unused){ lock_kernel(); /* * init can allocate pages on any node */ set_mems_allowed(node_possible_map); /* * init can run on any cpu. */ set_cpus_allowed_ptr(current, cpu_all_mask); /* * Tell the world that we're going to be the grim * reaper of innocent orphaned children. * * We don't want people to have to make incorrect * assumptions about where in the task array this * can be found. */ init_pid_ns.child_reaper = current; cad_pid = task_pid(current); smp_prepare_cpus(setup_max_cpus); do_pre_smp_initcalls(); start_boot_trace(); smp_init(); sched_init_smp(); do_basic_setup(); /* * check if there is an early userspace init. If yes, let it do all * the work */ if (!ramdisk_execute_command) ramdisk_execute_command = "/init"; if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) { ramdisk_execute_command = NULL; prepare_namespace(); } /* * Ok, we have completed the initial bootup, and * we're essentially up and running. Get rid of the * initmem segments and start the user-mode stuff.. */ init_post(); return 0;}
/* * Ok, the machine is now initialized. None of the devices * have been touched yet, but the CPU subsystem is up and * running, and memory and process management works. * * Now we can finally start doing some real work.. */static void __init do_basic_setup(void){ init_workqueues(); cpuset_init_smp(); usermodehelper_init(); init_tmpfs(); driver_init(); init_irq_proc(); do_ctors(); do_initcalls();}
这个函数向内核注册了一种总线。他首先由/drivers/base/init.c中的driver_init函数调用,driver_init函数由/init/main.c中的do_basic_setup函数调用,do_basic_setup这个函数由kernel_init调用,所以platform总线是在内核初始化的时候就注册进了内核。int __init platform_bus_init(void){ int error; early_platform_cleanup(); error = device_register(&platform_bus); //总线也是设备,所以也要进行设备的注册 if (error) return error; error = bus_register(&platform_bus_type); //注册platform_bus_type总线到内核 if (error) device_unregister(&platform_bus); return error;}
/** * driver_init - initialize driver model. * * Call the driver model init functions to initialize their * subsystems. Called early from init/main.c. */void __init driver_init(void){ /* These are the core pieces */ devtmpfs_init(); devices_init(); buses_init(); classes_init(); firmware_init(); hypervisor_init(); /* These are also core pieces, but must come after the * core core pieces. */ platform_bus_init(); system_bus_init(); cpu_dev_init(); memory_dev_init();}
platform总线也是一种设备,这里初始化一个device结构,设备名称platform,因为没有指定父设备,所以注册后将会在/sys/device/下出现platform目录。struct device platform_bus = { .init_name = "platform",};
platform_dev_attrs 设备属性struct bus_type platform_bus_type = { .name = "platform", .dev_attrs = platform_dev_attrs, .match = platform_match, .uevent = platform_uevent, .pm = &platform_dev_pm_ops,};
platform_match match函数,这个函数在当属于platform的设备或者驱动注册到内核时就会调用,完成设备与驱动的匹配 工作。
platform_uevent 热插拔操作函数
(2) mini2440_devices是一个platform_device指针数组,详见后面的代码
devs.c中的对应的头文件定义在 kernel/arch/arm/plat-s3c/include/plat/devs.h/* RTC */static struct resource s3c_rtc_resource[] = { [0] = { //IO端口资源范围 .start = S3C24XX_PA_RTC, .end = S3C24XX_PA_RTC + 0xff, .flags = IORESOURCE_MEM, }, [1] = { //RTC报警中断资源 .start = IRQ_RTC, .end = IRQ_RTC, .flags = IORESOURCE_IRQ, }, [2] = { //TICK节拍时间中断资源 .start = IRQ_TICK, .end = IRQ_TICK, .flags = IORESOURCE_IRQ }};struct platform_device s3c_device_rtc = { //定义RTC平台设备 .name = "s3c2410-rtc", //设备名称 .id = -1, .num_resources = ARRAY_SIZE(s3c_rtc_resource), //资源数量 .resource = s3c_rtc_resource, //引用上面定义的资源};EXPORT_SYMBOL(s3c_device_rtc); //导出该内核函数的符号,即入口地址
mini2440平台设备的系统入口文件为mach-mini2440.cextern struct platform_device s3c_device_fb;extern struct platform_device s3c_device_usb;extern struct platform_device s3c_device_lcd;extern struct platform_device s3c_device_wdt;extern struct platform_device s3c_device_i2c0;extern struct platform_device s3c_device_i2c1;extern struct platform_device s3c_device_rtc;extern struct platform_device s3c_device_adc;extern struct platform_device s3c_device_sdi;extern struct platform_device s3c_device_iis;
平台设备驱动程序:一般在kernel/drivers/下,这里以RTC为例,可以看到kernel/drivers/rtc/rtc-s3c.c:/* devices we initialise */static struct platform_device *mini2440_devices[] __initdata = { //平台设备数组,定义的平台设备要加入此处 &s3c_device_usb, &s3c_device_rtc,//RTC平台设备 &s3c_device_lcd, &s3c_device_wdt, &s3c_device_i2c0, &s3c_device_iis, &mini2440_device_eth, &s3c24xx_uda134x, &s3c_device_nand, &s3c_device_sdi, &s3c_device_usbgadget,};static void __init mini2440_machine_init(void){#if defined (LCD_WIDTH) s3c24xx_fb_set_platdata(&mini2440_fb_info);#endif s3c_i2c0_set_platdata(NULL); s3c2410_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND); s3c_device_nand.dev.platform_data = &friendly_arm_nand_info; s3c_device_sdi.dev.platform_data = &mini2440_mmc_cfg; platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices)); s3c_pm_init();}
static struct platform_driver s3c2410_rtc_driver = { .probe = s3c_rtc_probe, //rtc探测函数 .remove = __devexit_p(s3c_rtc_remove), //rtc移除函数 .suspend = s3c_rtc_suspend, //rtc挂起函数 .resume = s3c_rtc_resume, //rtc恢复函数 .driver = { .name = "s3c2410-rtc",//这里的名称一定要和系统中定义平台设备的地方一致,这样平台设备和平台驱动才能关联起来 .owner = THIS_MODULE, },};static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics\n";static int __init s3c_rtc_init(void) //驱动模块初始化{ printk(banner); return platform_driver_register(&s3c2410_rtc_driver);//注册rtc平台驱动}static void __exit s3c_rtc_exit(void) //驱动模块注销{ platform_driver_unregister(&s3c2410_rtc_driver);//注销rtc平台驱动}module_init(s3c_rtc_init);module_exit(s3c_rtc_exit);
- Linux内核启动过程中注册platform驱动模型
- linux 内核驱动--Platform Device和Platform_driver注册过程
- linux 内核驱动--Platform Device和Platform_driver注册过程
- linux内核驱动--Platform Device和Platform_driver注册过程
- linux 内核驱动--Platform Device和Platform_driver注册过程
- linux platform驱动注册过程
- linux内核中串口驱动注册过程(tty驱动)
- linux驱动中platform设备驱动模型
- Linux内核中platform驱动模型架构与dm9000网卡驱动移植
- Linux内核中platform驱动模型架构与dm9000网卡驱动移植
- Linux内核中platform驱动模型架构与dm9000网卡驱动移植(2)
- [Linux] 内核中 SPI 设备驱动模型(Platform设备驱动方式)
- linux中platform总线解析(三)(platform驱动的注册)
- Linux platform 驱动模型
- 44 linux内核里的platform设备驱动模型
- Linux2.6内核中基于platform机制的驱动模型
- OpenWRT驱动启动过程【Linux内核-OpenWRT】
- linux platform 驱动模型分析
- C++中冒号,双冒号
- Hibernate处理hql语句封装参数Map集合查询
- K相邻和Kd tree
- 【ACM-Steps1.2】简单字符串处理、简单数学题、进制转换系列8题(二)
- DAG模型
- Linux内核启动过程中注册platform驱动模型
- RPC漏洞的通用分析方法
- CT-代码解释
- Flex中ParentDocument和parent的区别
- ecshop后台通过ajax搜索原理
- 删除svn目录内.svn目录及内容的方法汇总
- 爲什麽 Android手机會取消硬件後退和菜單按鈕
- 关于异常的问题
- MySQL:给表建立索引及索引的显示