三星6410 uart平台设备添加流程分析
2013-11-04 15:09
656 查看
查找mach-xxx.c文件,platform_device数组中并没有uart设备。但看uart驱动,发现采用的还是platform方式注册的,那uart设备是在哪里添加的呢?
看下面代码,位于文件arch/arm/plat-samsung/init.c
这里可以发现,在平台初始化代码中,有这么一段arch初始化代码,里面单独调用了platform_add_devices添加uart设备。因此,我们可以知道uart设备实在此处添加的。
但搜索s3c24xx_uart_devs,发现该变量定义为空。
arch/arm/plat-samsung/dev-uart.c:
有个src变量、有一个devs变量,再看下一段代码,
arch/arm/plat-samsung/init.c:
该函数完成了从src到devs的搬移,并添加了额外的信息,完善了整个uart平台设备。那调用在哪里?
arch/arm/mach-s3c64xx.c:
arch/arm/mach-s3c64xx/include/mach/s3c6410.c:
通过宏定义将common_init_uarts定义为了init_uarts,在赋值给cpu_table成员函数init_uarts。
那init_uarts成员函数是在哪里被调用的呢?再回到arch/arm/plat-samsung/init.c:
arch/arm/mach-s3c64xx/mach-mini6410.c:
分析到这里也就差不多了,map_io成员函数会在start_kernel函数中执行,且在rest_init之前,因此会早于所有initcall函数。这就确保了uart平台设备变量初始化好了之后才被添加到系统。
看下面代码,位于文件arch/arm/plat-samsung/init.c
static int __init s3c_arch_init(void) { int ret; // do the correct init for cpu if (cpu == NULL) panic("s3c_arch_init: NULL cpu\n"); ret = (cpu->init)(); if (ret != 0) return ret; ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts); return ret; } arch_initcall(s3c_arch_init);
这里可以发现,在平台初始化代码中,有这么一段arch初始化代码,里面单独调用了platform_add_devices添加uart设备。因此,我们可以知道uart设备实在此处添加的。
但搜索s3c24xx_uart_devs,发现该变量定义为空。
arch/arm/plat-samsung/dev-uart.c:
static struct platform_device s3c24xx_uart_device0 = { .id = 0, }; static struct platform_device s3c24xx_uart_device1 = { .id = 1, }; static struct platform_device s3c24xx_uart_device2 = { .id = 2, }; static struct platform_device s3c24xx_uart_device3 = { .id = 3, }; struct platform_device *s3c24xx_uart_src[4] = { &s3c24xx_uart_device0, &s3c24xx_uart_device1, &s3c24xx_uart_device2, &s3c24xx_uart_device3, }; struct platform_device *s3c24xx_uart_devs[4] = { };
有个src变量、有一个devs变量,再看下一段代码,
arch/arm/plat-samsung/init.c:
void __init s3c24xx_init_uartdevs(char *name, struct s3c24xx_uart_resources *res, struct s3c2410_uartcfg *cfg, int no) { struct platform_device *platdev; struct s3c2410_uartcfg *cfgptr = uart_cfgs; struct s3c24xx_uart_resources *resp; int uart; memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no); for (uart = 0; uart < no; uart++, cfg++, cfgptr++) { platdev = s3c24xx_uart_src[cfgptr->hwport]; resp = res + cfgptr->hwport; s3c24xx_uart_devs[uart] = platdev; platdev->name = name; platdev->resource = resp->resources; platdev->num_resources = resp->nr_resources; platdev->dev.platform_data = cfgptr; } nr_uarts = no; }
该函数完成了从src到devs的搬移,并添加了额外的信息,完善了整个uart平台设备。那调用在哪里?
arch/arm/mach-s3c64xx.c:
void __init s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no) { s3c24xx_init_uartdevs("s3c6400-uart", s3c64xx_uart_resources, cfg, no); }
static const char name_s3c6400[] = "S3C6400"; static const char name_s3c6410[] = "S3C6410"; static struct cpu_table cpu_ids[] __initdata = { { .idcode = 0x36400000, .idmask = 0xfffff000, .map_io = s3c6400_map_io, .init_clocks = s3c6400_init_clocks, .init_uarts = s3c6400_init_uarts, .init = s3c6400_init, .name = name_s3c6400, }, { .idcode = 0x36410100, .idmask = 0xffffff00, .map_io = s3c6410_map_io, .init_clocks = s3c6410_init_clocks, .init_uarts = s3c6410_init_uarts, .init = s3c6410_init, .name = name_s3c6410, }, };
arch/arm/mach-s3c64xx/include/mach/s3c6410.c:
#define s3c6410_init_uarts s3c6400_common_init_uarts
通过宏定义将common_init_uarts定义为了init_uarts,在赋值给cpu_table成员函数init_uarts。
那init_uarts成员函数是在哪里被调用的呢?再回到arch/arm/plat-samsung/init.c:
void __init s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no) { if (cpu == NULL) return; if (cpu->init_uarts == NULL) { printk(KERN_ERR "s3c24xx_init_uarts: cpu has no uart init\n"); } else (cpu->init_uarts)(cfg, no); }
arch/arm/mach-s3c64xx/mach-mini6410.c:
static void __init mini6410_map_io(void) { u32 tmp; s3c64xx_init_io(mini6410_iodesc, ARRAY_SIZE(mini6410_iodesc)); s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(mini6410_uartcfgs, ARRAY_SIZE(mini6410_uartcfgs)); /* set the LCD type */ tmp = __raw_readl(S3C64XX_SPCON); tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK; tmp |= S3C64XX_SPCON_LCD_SEL_RGB; __raw_writel(tmp, S3C64XX_SPCON); /* remove the lcd bypass */ tmp = __raw_readl(S3C64XX_MODEM_MIFPCON); tmp &= ~MIFPCON_LCD_BYPASS; __raw_writel(tmp, S3C64XX_MODEM_MIFPCON); #ifdef CONFIG_VIDEO_SAMSUNG s3c64xx_reserve_bootmem(); #endif }
MACHINE_START(MINI6410, "MINI6410") /* Maintainer: Ben Dooks <ben-linux@fluff.org> */ .boot_params = S3C64XX_PA_SDRAM + 0x100, .init_irq = s3c6410_init_irq, .map_io = mini6410_map_io, .init_machine = mini6410_machine_init, .timer = &s3c24xx_timer, MACHINE_END
分析到这里也就差不多了,map_io成员函数会在start_kernel函数中执行,且在rest_init之前,因此会早于所有initcall函数。这就确保了uart平台设备变量初始化好了之后才被添加到系统。
相关文章推荐
- xen 添加网卡设备初步分析之 network-attach 流程分析
- 今天我以fb设备的注册过程来分析platform设备的添加流程
- MTK 平台支持设备树的添加流程
- 三星6410摄像头测试程序流程分析
- 三星6410摄像头测试程序流程分析
- 三星6410摄像头测试程序流程分析
- 代码流程分析二:Settings-蓝牙分析-点击配对连接设备原理分析
- 嵌入式学习-驱动开发-lesson6.3-UART驱动send和receive流程分析
- 物联网平台机智云Android开源框架入门之旅(五) 分析怎么样把云端设备的信息状态同步到手机显示。
- 操作系统大型实验进展(6)-----Linux 内核文件系统与设备操作流程分析
- u-boot启动流程分析(1)_平台相关部分
- platform设备添加流程(转载)
- 物联网平台机智云Android开源框架入门之旅(三)分析设备详情界面的中如何发送各种指令到云端。
- Uboot在ARM平台下运行流程分析
- 全志平台linux启动流程分析
- platform设备添加流程(转载)
- Cocos2d-x之 IOS工程平台程序启动流程分析
- UBOOT-2012-10在OK6410平台的移植(二)uboot 2012.10启动流程
- Fragment之添加显示流程源码分析
- Android 关机流程分析-案例高通平台