Chinaunix首页 | 论坛 | 博客
  • 博客访问: 61635
  • 博文数量: 32
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 167
  • 用 户 组: 普通用户
  • 注册时间: 2011-08-09 11:39
文章分类
文章存档

2013年(1)

2012年(10)

2011年(21)

我的朋友

分类:

2012-04-07 11:32:49

原文地址:s3c2410设备的注册 作者:chenzhufly

s3c2410设备的注册
R.wen

首先是系统在初始化是, platform bus的注册:

struct device platform_bus = {
    .bus_id        = "platform",
};

struct bus_type platform_bus_type = {
    .name        = "platform",
    .match        = platform_match,
    .suspend    = platform_suspend,
    .resume        = platform_resume,
};

int __init platform_bus_init(void)
{
    device_register(&platform_bus);
    return bus_register(&platform_bus_type);
}


设备的注册


static struct platform_device *smdk2410_devices[] __initdata = {
    &s3c_device_usb,
    &s3c_device_lcd,
    &s3c_device_wdt,
    &s3c_device_i2c,
    &s3c_device_iis,
};
//以上这些设备的结构在devs.c中定义, 如下是一个例子:
/* NAND Controller */

static struct resource s3c_nand_resource[] = {
    [0] = {
        .start = S3C2410_PA_NAND,
        .end   = S3C2410_PA_NAND + S3C24XX_SZ_NAND,
        .flags = IORESOURCE_MEM,
    }
};

struct platform_device s3c_device_nand = {
    .name        = "s3c2410-nand",
    .id        = -1,
    .num_resources    = ARRAY_SIZE(s3c_nand_resource),
    .resource    = s3c_nand_resource,
};


所以我们就可以通过上面的方法加入我们想要的设备.

==========================================


//上面的设备列表在加入到板级系统中
static struct s3c24xx_board smdk2410_board __initdata = {
    .devices       = smdk2410_devices,
    .devices_count = ARRAY_SIZE(smdk2410_devices)
};


static void __init smdk2410_map_io(void)
{
    s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
    s3c24xx_init_clocks(0);
    s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
    s3c24xx_set_board(&smdk2410_board); //注意这一步
}

static void __init smdk2410_init_irq(void)
{
    s3c24xx_init_irq();
}

==========================================
//这是通过一个宏来建立一个结构
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
                    * to SMDK2410 */
    /* Maintainer: Jonas Dietsche */
    .phys_ram    = S3C2410_SDRAM_PA,
    .phys_io    = S3C2410_PA_UART,
    .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
    .boot_params    = S3C2410_SDRAM_PA + 0x100,
    .map_io        = smdk2410_map_io,
    .init_irq    = smdk2410_init_irq,
    .timer        = &s3c24xx_timer,
MACHINE_END

//宏定义为如下:
/*
* Set of macros to define architecture features. This is built into
* a table by the linker.
*/
#define MACHINE_START(_type,_name)        \
const struct machine_desc __mach_desc_##_type    \
__attribute__((__section__(".arch.info.init"))) = {    \
    .nr        = MACH_TYPE_##_type,    \
    .name        = _name,

#define MACHINE_END                \
};

由此得到一个名为__mach_desc_SMDK2410_type, 类型为struct machine_desc的结构体.


=====================
再看看s3c24xx_set_board(&smdk2410_board)(in cpu.c)

/* board information */

static struct s3c24xx_board *board;

void s3c24xx_set_board(struct s3c24xx_board *b)
{
    int i;

    board = b; //设置这个全局变量

    if (b->clocks_count != 0) {
        struct clk **ptr = b->clocks;;

        for (i = b->clocks_count; i > 0; i--, ptr++)
            s3c24xx_register_clock(*ptr);
    }
}

而下面这个初始化函数就会用到这个变量了
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;

    if (board != NULL) {
        struct platform_device **ptr = board->devices;
        int i;

        //遍历platform中的每一个设备
        for (i = 0; i < board->devices_count; i++, ptr++) {
            //注册进platform总线中去, 这样在加载驱动的时候就可以
            //找到这些platform device了.
            ret = platform_device_register(*ptr);
       
            if (ret) {
                printk(KERN_ERR "s3c24xx: failed to add board device %s (%d)

@%p\n", (*ptr)->name, ret, *ptr);
            }
        }

        /* mask any error, we may not need all these board
        * devices */
        ret = 0;
    }

    return ret;
}

arch_initcall(s3c_arch_init);



===================================

/**
*    platform_device_register - add a platform-level device
*    @pdev:    platform device we're adding
*
*/
int platform_device_register(struct platform_device * pdev)
{
    int i, ret = 0;

    if (!pdev)
        return -EINVAL;


    //关联父设备
    if (!pdev->dev.parent)
        pdev->dev.parent = &platform_bus;

    pdev->dev.bus = &platform_bus_type;

    //id == -1 的处理, 只是名字的不同
    if (pdev->id != -1)
        snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%u", pdev->name, pdev->id);
    else
        strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);

    //请求分配一些资源
    for (i = 0; i < pdev->num_resources; i++) {
        struct resource *p, *r = &pdev->resource[i];

        if (r->name == NULL)
            r->name = pdev->dev.bus_id;

        p = r->parent;
        if (!p) {
            if (r->flags & IORESOURCE_MEM)
                p = &iomem_resource;
            else if (r->flags & IORESOURCE_IO)
                p = &ioport_resource;
        }

        if (p && request_resource(p, r)) {
            printk(KERN_ERR
                   "%s: failed to claim resource %d\n",
                   pdev->dev.bus_id, i);
            ret = -EBUSY;
            goto failed;
        }
    }

    pr_debug("Registering platform device '%s'. Parent at %s\n",
        pdev->dev.bus_id, pdev->dev.parent->bus_id);

    //将设备注册进bus中, 可以在/sys/bus/platform中看到
    ret = device_register(&pdev->dev);
    if (ret == 0)
        return ret;

failed:
    while (--i >= 0)
        if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO))
            release_resource(&pdev->resource[i]);
    return ret;
}
阅读(847) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~