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;
}