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        = 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\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 = 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\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);

 

 

 

 

posted on 2013-10-10 11:41  熊猫酒仙是也  阅读(958)  评论(0编辑  收藏  举报

导航