ARM-Linux S5PV210 UART驱动(6)----platform device的添加

开发板是飞凌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 = ,
.flags = ,
.ucon = S5PV210_UCON_DEFAULT,
.ulcon = S5PV210_ULCON_DEFAULT,
.ufcon = S5PV210_UFCON_DEFAULT,
},
{
.hwport = ,
.flags = ,
.ucon = S5PV210_UCON_DEFAULT,
.ulcon = S5PV210_ULCON_DEFAULT,
.ufcon = S5PV210_UFCON_DEFAULT,
},
#ifndef CONFIG_FIQ_DEBUGGER
{
.hwport = ,
.flags = ,
.ucon = S5PV210_UCON_DEFAULT,
.ulcon = S5PV210_ULCON_DEFAULT,
.ufcon = S5PV210_UFCON_DEFAULT,
},
#endif
{
.hwport = ,
.flags = ,
.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) >> ) & 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, , S5P_VA_CHIPID);
s3c24xx_init_clocks();
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\n");
} 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 = ; 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 = ; 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\n"); ret = (cpu->init)();
if (ret != )
return ret; ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts);
return ret;
} arch_initcall(s3c_arch_init);
上一篇:ARM-Linux S5PV210 UART驱动(5)----串口的open操作(tty_open、uart_open)


下一篇:Linux UART驱动分析