i2c bus 路径
struct bus_type i2c_bus_type = {.name = "i2c",.match = i2c_device_match,.probe = i2c_device_probe,.remove = i2c_device_remove,.shutdown = i2c_device_shutdown,
};
EXPORT_SYMBOL_GPL(i2c_bus_type);static int __init i2c_init(void)
{int retval;retval = of_alias_get_highest_id("i2c");down_write(&__i2c_board_lock);if (retval >= __i2c_first_dynamic_bus_num)__i2c_first_dynamic_bus_num = retval + 1;up_write(&__i2c_board_lock);retval = bus_register(&i2c_bus_type);if (retval)return retval;is_registered = true;#ifdef CONFIG_I2C_COMPATi2c_adapter_compat_class = class_compat_register("i2c-adapter");if (!i2c_adapter_compat_class) {retval = -ENOMEM;goto bus_err;}
#endifretval = i2c_add_driver(&dummy_driver);if (retval)goto class_err;if (IS_ENABLED(CONFIG_OF_DYNAMIC))WARN_ON(of_reconfig_notifier_register(&i2c_of_notifier));if (IS_ENABLED(CONFIG_ACPI))WARN_ON(acpi_reconfig_notifier_register(&i2c_acpi_notifier));return 0;class_err:
#ifdef CONFIG_I2C_COMPATclass_compat_unregister(i2c_adapter_compat_class);
bus_err:
#endifis_registered = false;bus_unregister(&i2c_bus_type);return retval;
}
结合 .name = “i2c”, retval = bus_register(&i2c_bus_type);
这表明命名是 “i2c”,通过bus_register注册到bus 总线目录下。
实际如下图
i2c adaptor 路径
static int i2c_register_adapter(struc
t i2c_adapter *adap)
{int res = -EINVAL;/* Can't register until after driver model init */if (WARN_ON(!is_registered)) {res = -EAGAIN;goto out_list;}/* Sanity checks */if (WARN(!adap->name[0], "i2c adapter has no name"))goto out_list;if (!adap->algo) {pr_err("adapter '%s': no algo supplied!\n", adap->name);goto out_list;}if (!adap->lock_ops)adap->lock_ops = &i2c_adapter_lock_ops;adap->locked_flags = 0;rt_mutex_init(&adap->bus_lock);rt_mutex_init(&adap->mux_lock);mutex_init(&adap->userspace_clients_lock);INIT_LIST_HEAD(&adap->userspace_clients);/* Set default timeout to 1 second if not already set */if (adap->timeout == 0)adap->timeout = HZ;/* register soft irqs for Host Notify */res = i2c_setup_host_notify_irq_domain(adap);if (res) {pr_err("adapter '%s': can't create Host Notify IRQs (%d)\n",adap->name, res);goto out_list;}dev_set_name(&adap->dev, "i2c-%d", adap->nr);adap->dev.bus = &i2c_bus_type;adap->dev.type = &i2c_adapter_type;res = device_register(&adap->dev);if (res) {pr_err("adapter '%s': can't register device (%d)\n", adap->name, res);goto out_list;}res = i2c_setup_smbus_alert(adap);if (res)goto out_reg;device_enable_async_suspend(&adap->dev);pm_runtime_no_callbacks(&adap->dev);pm_suspend_ignore_children(&adap->dev, true);pm_runtime_enable(&adap->dev);res = i2c_init_recovery(adap);if (res == -EPROBE_DEFER)goto out_reg;dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);#ifdef CONFIG_I2C_COMPATres = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,adap->dev.parent);if (res)dev_warn(&adap->dev,"Failed to create compatibility class link\n");
#endif/* create pre-declared device nodes */of_i2c_register_devices(adap);i2c_acpi_install_space_handler(adap);i2c_acpi_register_devices(adap);if (adap->nr < __i2c_first_dynamic_bus_num)i2c_scan_static_board_info(adap);/* Notify drivers */mutex_lock(&core_lock);bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);mutex_unlock(&core_lock);return 0;out_reg:init_completion(&adap->dev_released);device_unregister(&adap->dev);wait_for_completion(&adap->dev_released);
out_list:mutex_lock(&core_lock);idr_remove(&i2c_adapter_idr, adap->nr);mutex_unlock(&core_lock);return res;
}
通过这2行
dev_set_name(&adap->dev, “i2c-%d”, adap->nr);
adap->dev.bus = &i2c_bus_type;
表明适配器的路径在bus 路径的devices下面。命名风格是"i2c-%d",%d是注册的适配器的总线号。实际如下图
i2c client路径
struct i2c_client *
i2c_new_client_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 ERR_PTR(-ENOMEM);client->adapter = adap;client->dev.platform_data = info->platform_data;client->flags = info->flags;client->addr = info->addr;client->init_irq = info->irq;if (!client->init_irq)client->init_irq = i2c_dev_irq_from_resources(info->resources,info->num_resources);strscpy(client->name, info->type, sizeof(client->name));status = i2c_check_addr_validity(client->addr, client->flags);if (status) {dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n",client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);goto out_err_silent;}/* Check for address business */status = i2c_check_addr_busy(adap, i2c_encode_flags_to_addr(client));if (status)goto out_err;client->dev.parent = &client->adapter->dev;client->dev.bus = &i2c_bus_type;client->dev.type = &i2c_client_type;client->dev.of_node = of_node_get(info->of_node);client->dev.fwnode = info->fwnode;device_enable_async_suspend(&client->dev);i2c_dev_set_name(adap, client, info);if (info->swnode) {status = device_add_software_node(&client->dev, info->swnode);if (status) {dev_err(&adap->dev,"Failed to add software node to client %s: %d\n",client->name, status);goto out_err_put_of_node;}}status = device_register(&client->dev);if (status)goto out_remove_swnode;dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",client->name, dev_name(&client->dev));return client;
out_remove_swnode:device_remove_software_node(&client->dev);
out_err_put_of_node:of_node_put(info->of_node);
out_err:dev_err(&adap->dev,"Failed to register i2c client %s at 0x%02x (%d)\n",client->name, client->addr, status);
out_err_silent:kfree(client);return ERR_PTR(status);
}
EXPORT_SYMBOL_GPL(i2c_new_client_device);
client->dev.parent = &client->adapter->dev; 表明client 实体对应的device节点在adapter的目录下,命名由 strscpy(client->name, info->type, sizeof(client->name)); 和 i2c_dev_set_name(adap, client, info)这两项决定。
i2c_dev_set_name 的实现如下
static void i2c_dev_set_name(struct i2c_adapter *adap,struct i2c_client *client,struct i2c_board_info const *info)
{struct acpi_device *adev = ACPI_COMPANION(&client->dev);if (info && info->dev_name) {dev_set_name(&client->dev, "i2c-%s", info->dev_name);return;}if (adev) {dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev));return;}dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),i2c_encode_flags_to_addr(client));
}
static inline int i2c_adapter_id(struct i2c_adapter *adap){return adap->nr;}
static unsigned short i2c_encode_flags_to_addr(struct i2c_client *client)
{unsigned short addr = client->addr;/* For some client flags, add an arbitrary offset to avoid collisions */if (client->flags & I2C_CLIENT_TEN)addr |= I2C_ADDR_OFFSET_TEN_BIT;if (client->flags & I2C_CLIENT_SLAVE)addr |= I2C_ADDR_OFFSET_SLAVE;return addr;
}
#define I2C_ADDR_OFFSET_TEN_BIT 0xa000
#define I2C_ADDR_OFFSET_SLAVE 0x1000
实例如下图
上图第一个红框是常规命名方式,下面的是ACPI的命名方式