现在的位置: 首页 > 综合 > 正文

iic三

2013年07月22日 ⁄ 综合 ⁄ 共 4540字 ⁄ 字号 评论关闭

int i2c_add_numbered_adapter(struct i2c_adapter *adap)
{
        int     id;
        int     status;

        if (adap->nr & ~MAX_ID_MASK)
                return -EINVAL;

retry:
        if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
                return -ENOMEM;

        mutex_lock(&core_lock);
        /* "above" here means "above or equal to", sigh;
         * we need the "equal to" result to force the result
         */
        status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id);
        if (status == 0 && id != adap->nr) {
                status = -EBUSY;
                idr_remove(&i2c_adapter_idr, id);
        }
        mutex_unlock(&core_lock);

        if (status == -EAGAIN)
                goto retry;

        if (status == 0)
                status = i2c_register_adapter(adap);
        return status;
}

 

static int i2c_register_adapter(struct i2c_adapter *adap)
{
        int res = 0, dummy;

        /* Can't register until after driver model init */
        if (unlikely(WARN_ON(!i2c_bus_type.p))) {
                res = -EAGAIN;
                goto out_list;
        }

        mutex_init(&adap->bus_lock);

        /* Set default timeout to 1 second if not already set */
        if (adap->timeout == 0)
                adap->timeout = HZ;

        dev_set_name(&adap->dev, "i2c-%d", adap->nr);//I2C控制器的设备名字
        adap->dev.release = &i2c_adapter_dev_release;
        adap->dev.class = &i2c_adapter_class;
        res = device_register(&adap->dev); //注册I2C控制器设备
        if (res)
                goto out_list;

 

        dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);

        /* create pre-declared device nodes */
        if (adap->nr < __i2c_first_dynamic_bus_num)
                i2c_scan_static_board_info(adap);  //主意这里了,准备添加I2C从设备了,通过遍历那个什么链表,然后和adapter的nr进行比较,相等,说明有控制器存在

        /* Notify drivers */
        mutex_lock(&core_lock);
        dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap,
                                 i2c_do_add_adapter);
        mutex_unlock(&core_lock);

        return 0;

out_list:
        mutex_lock(&core_lock);
        idr_remove(&i2c_adapter_idr, adap->nr);
        mutex_unlock(&core_lock);
        return res;
}

static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
{
        struct i2c_devinfo      *devinfo;

        down_read(&__i2c_board_lock);
        list_for_each_entry(devinfo, &__i2c_board_list, list) {
                if (devinfo->busnum == adapter->nr            /////////////此处就是之前用i2c_register_boardinfo时候给出的从设备的控制器号
                                && !i2c_new_device(adapter,
                                                &devinfo->board_info))
                        dev_err(&adapter->dev,
                                "Can't create device at 0x%02x\n",
                                devinfo->board_info.addr);
        }
        up_read(&__i2c_board_lock);
}

struct i2c_client *
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
{
        struct i2c_client       *client;
        int                     status;

        client = kzalloc(sizeof *client, GFP_KERNEL);
        if (!client)
                return NULL;

        client->adapter = adap;                     //这里设置主控制器,当VFS调用file operations时,会调用adapter里的那个什么算法

        client->dev.platform_data = info->platform_data;

        if (info->archdata)
                client->dev.archdata = *info->archdata;

        client->flags = info->flags;
        client->addr = info->addr;                 //从设备的地址
        client->irq = info->irq;                       
//从设备的中断号

        strlcpy(client->name,
info->type
, sizeof(client->name));        //设备的名字,总线会根据此和device_driver中ID_TABLE中的每个成员进行配对,最后调用probe函数

 

        status = i2c_check_addr(adap, client->addr);
        if (status)
                goto out_err;

        client->dev.parent = &client->adapter->dev;
        client->dev.bus = &i2c_bus_type;
        client->dev.release = i2c_client_dev_release;

        dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
                     client->addr);
        status = device_register(&client->dev);
        if (status)
                goto out_err;

        dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",
                client->name, dev_name(&client->dev));

        return client;

out_err:
        dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "
                "(%d)\n", client->name, client->addr, status);
        kfree(client);

         return NULL;
}

static int i2c_do_add_adapter(struct device_driver *d, void *data)
{
        struct i2c_driver *driver = to_i2c_driver(d);
        struct i2c_adapter *adap = data;

        /* Detect supported devices on that bus, and instantiate them */
        i2c_detect(adap, driver);

        /* Let legacy drivers scan this bus for matching devices */
        if (driver->attach_adapter) {
                /* We ignore the return code; if it fails, too bad */
                driver->attach_adapter(adap);
        }
        return 0;
}

 

 

 

 

抱歉!评论已关闭.