static struct resource s3c_i2c_resource[] = { [0] = {//i2c-0 .start = S3C_PA_IIC, .end = S3C_PA_IIC + SZ_4K - 1, .flags = IORESOURCE_MEM, }, [1] = {//i2c-1 .start = IRQ_IIC, .end = IRQ_IIC, .flags = IORESOURCE_IRQ, }, };/i2c适配器初始化时数据
static struct s3c2410_platform_i2c default_i2c_data0 __initdata = { .flags = 0, .slave_addr = 0x10, .frequency = 100*1000, .sda_delay = 100, };
//声明i2c适配器为platform_device
struct platform_device s3c_device_i2c0 = { .name = "s3c2410-i2c", #ifdef CONFIG_S3C_DEV_I2C1 .id = 0, #else .id = -1, #endif .num_resources = ARRAY_SIZE(s3c_i2c_resource), .resource = s3c_i2c_resource, }; static struct s3c2410_platform_i2c default_i2c_data0 __initdata = { .flags = 0, .slave_addr = 0x10, .frequency = 100*1000, .sda_delay = 100, };//添加i2c适配器:
static struct platform_device *smdk2440_devices[] __initdata = { ... &s3c_device_i2c0, ... };//添加plat_from_data
void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd) { struct s3c2410_platform_i2c *npd; if (!pd) pd = &default_i2c_data0; npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); if (!npd) printk(KERN_ERR "%s: no memory for platform data\n", __func__); else if (!npd->cfg_gpio) npd->cfg_gpio = s3c_i2c0_cfg_gpio; //i2c引脚配置 s3c_device_i2c0.dev.platform_data = npd; //挂接plat_form_data数据 }//定义好上面相关结构后,在smdk2440_machine_init()中被注册和添加成platform_device
static void __init smdk2440_machine_init(void) { s3c24xx_fb_set_platdata(&smdk2440_fb_info); s3c_i2c0_set_platdata(NULL); ... //注册和添加platform_device platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices)); ... }其中 smdk2440_machine_init在被赋值在MACHINE_START中
platform_add_devices()-->platform_device_register()--> platform_device_add()--> device-->add()platfrom_bus_init()时也将添加一个名叫platform的设备(struct device platform_bus):
plat_form_bus_init()-->device_register()-->device_register() -->device-->add()但这个设备是虚拟的,所有platform_device_add()后的设备都是在/devices/platform/下
if (!pdev->dev.parent) pdev->dev.parent = &platform_bus;我想这也就是platform_device_register()和device_register()区别吧
static struct platform_driver s3c2440_i2c_driver = { .probe = s3c24xx_i2c_probe, .remove = s3c24xx_i2c_remove, .suspend_late = s3c24xx_i2c_suspend_late, .resume = s3c24xx_i2c_resume, .driver = { .owner = THIS_MODULE, .name = "s3c2440-i2c", // }, };
//初始化并注册platform_driver
static int __init i2c_adap_s3c_init(void) { int ret; ret = platform_driver_register(&s3c2410_i2c_driver);// if (ret == 0) { printk("register s3c2440_i2c_driver.....\n"); ret = platform_driver_register(&s3c2440_i2c_driver); if (ret) { printk("register s3c2410_i2c_driver.....\n"); platform_driver_unregister(&s3c2410_i2c_driver); } } return ret; } subsys_initcall(i2c_adap_s3c_init);这样适配器就和驱动绑定上了,过程是这样的:
platform_driver_register()-->driver_register()-->bus_add_driver()-->driver_attach() __driver_attach()-->driver_probe_device()-->s3c24xx_i2c_probe()并且在s3c24xx_i2c_probe()的时候调用
i2c_add_numbered_adapter(&i2c->adap);最后添加自己为i2c总线的适配器。这样分析过程也就结束了。