三星6410 uart平臺設備添加流程分析

查找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 <[email protected]> */
	.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平臺設備變量初始化好了之後才被添加到系統。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章