开发板是飞凌OK210
arch/arm/mach-s5pv210/mach-smdkc110.c
首先是UART的寄存器默认配置信息:
/* Following are default values for UCON, ULCON and UFCON UART registers */ #define S5PV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL | S3C2410_UCON_TXIRQMODE | S3C2410_UCON_RXIRQMODE | S3C2410_UCON_RXFIFO_TOI | S3C2443_UCON_RXERR_IRQEN) #define S5PV210_ULCON_DEFAULT S3C2410_LCON_CS8 #define S5PV210_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | S5PV210_UFCON_TXTRIG4 | S5PV210_UFCON_RXTRIG4) static struct s3c2410_uartcfg smdkc110_uartcfgs[] __initdata = { { .hwport = 0, .flags = 0, .ucon = S5PV210_UCON_DEFAULT, .ulcon = S5PV210_ULCON_DEFAULT, .ufcon = S5PV210_UFCON_DEFAULT, }, { .hwport = 1, .flags = 0, .ucon = S5PV210_UCON_DEFAULT, .ulcon = S5PV210_ULCON_DEFAULT, .ufcon = S5PV210_UFCON_DEFAULT, }, #ifndef CONFIG_FIQ_DEBUGGER { .hwport = 2, .flags = 0, .ucon = S5PV210_UCON_DEFAULT, .ulcon = S5PV210_ULCON_DEFAULT, .ufcon = S5PV210_UFCON_DEFAULT, }, #endif { .hwport = 3, .flags = 0, .ucon = S5PV210_UCON_DEFAULT, .ulcon = S5PV210_ULCON_DEFAULT, .ufcon = S5PV210_UFCON_DEFAULT, }, };
下面是添加platform device的具体过程:
1.
/*调用MACHINE_START宏 MACHINE_START和MACHINE_END框起了一个machine_desc结构体的声明并根据MACHINE_START宏的参数初始化其.nr和.name成员 并将该结构体标记编译到.arch.info.init段 在MACHINE_START和MACHINE_END宏之间可以初始化machine_desc结构体的剩余成员 */ #ifdef CONFIG_MACH_SMDKC110 MACHINE_START(SMDKC110, "SMDKC110") #elif CONFIG_MACH_SMDKV210 MACHINE_START(SMDKV210, "SMDKV210") #endif /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ .phys_io = S3C_PA_UART & 0xfff00000, .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc, .boot_params = S5P_PA_SDRAM + 0x100, .init_irq = s5pv210_init_irq,//板级中断初始化函数 .map_io = smdkc110_map_io,//板级io初始化函数 .init_machine = smdkc110_machine_init,//板级初始化函数 .timer = &s5p_systimer, MACHINE_END
2.
static void __init smdkc110_map_io(void) { s5p_init_io(NULL, 0, S5P_VA_CHIPID); s3c24xx_init_clocks(24000000); s5pv210_gpiolib_init(); s3c24xx_init_uarts(smdkc110_uartcfgs, ARRAY_SIZE(smdkc110_uartcfgs)); s5p_reserve_bootmem(smdkc110_media_devs, ARRAY_SIZE(smdkc110_media_devs)); #ifdef CONFIG_MTD_ONENAND s5pc110_device_onenand.name = "s5pc110-onenand"; #endif #ifdef CONFIG_MTD_NAND s3c_device_nand.name = "s5pv210-nand"; #endif s5p_device_rtc.name = "smdkc110-rtc"; }
3.
/* table of supported CPUs */
static struct cpu_table cpu_ids[] __initdata = { { .idcode = 0x43110000, .idmask = 0xfffff000, .map_io = s5pv210_map_io, .init_clocks = s5pv210_init_clocks, .init_uarts = s5pv210_init_uarts, .init = s5pv210_init, .name = name_s5pv210, }, };
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 "); } else (cpu->init_uarts)(cfg, no);//这里最终会调用上面的s5pv210_init_uarts }
4.
#define s5pv210_init_uarts s5pv210_common_init_uarts
/* uart registration process */ void __init s5pv210_common_init_uarts(struct s3c2410_uartcfg *cfg, int no) { struct s3c2410_uartcfg *tcfg = cfg; u32 ucnt; for (ucnt = 0; ucnt < no; ucnt++, tcfg++) { if (!tcfg->clocks) { tcfg->clocks = s5pv210_serial_clocks; tcfg->clocks_size = ARRAY_SIZE(s5pv210_serial_clocks); } } s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no); }
5.
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;//将cfg挂到platdev->dev.platform_data上 } nr_uarts = no; }
static int __init s3c_arch_init(void) { int ret; // do the correct init for cpu if (cpu == NULL) panic("s3c_arch_init: NULL cpu "); ret = (cpu->init)(); if (ret != 0) return ret; ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts); return ret; } arch_initcall(s3c_arch_init);