您的位置:首页 > 其它

三星6410 uart平台设备添加流程分析

2013-11-04 15:09 656 查看
查找mach-xxx.c文件,platform_device数组中并没有uart设备。但看uart驱动,发现采用的还是platform方式注册的,那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平台设备变量初始化好了之后才被添加到系统。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: