I2C 地址转换器

作者:Luca Ceresoli <luca@lucaceresoli.net> 作者:Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

描述

I2C 地址转换器 (ATR) 是一种具有 I2C 从设备父端口(“上游”)和 N 个 I2C 主设备子端口(“下游”)的设备,并将来自上游的事务以修改后的从设备地址转发到适当的下游端口。父总线上使用的地址称为“别名”,并且与子总线的物理从设备地址(可能)不同。 地址转换由硬件完成。

ATR 看起来类似于 i2c-mux,除了
  • 父总线和子总线上的地址可能不同

  • 通常不需要选择子端口;父总线上使用的别名暗示了这一点

ATR 功能可以由具有许多其他功能的芯片提供。内核 i2c-atr 提供了一个帮助程序,用于在驱动程序中实现 ATR。

ATR 在每个子总线上创建一个新的 I2C“子”适配器。 在子总线上添加设备最终会调用驱动程序代码来选择可用的别名。维护适当的可用别名池并为每个新设备选择一个别名由驱动程序实现者负责。 ATR 维护一个当前分配的别名表,并使用它来修改所有定向到子总线上设备的 I2C 事务。

以下是一个典型的例子。

拓扑

                    Slave X @ 0x10
            .-----.   |
.-----.     |     |---+---- B
| CPU |--A--| ATR |
`-----'     |     |---+---- C
            `-----'   |
                    Slave Y @ 0x10

别名表

A、B 和 C 是三个物理 I2C 总线,在电气上彼此独立。 ATR 接收在总线 A 上启动的事务,并根据事务中的设备地址和别名表,将它们传播到总线 B 或总线 C,或者不传播到任何总线。

别名表

客户端

别名

X(总线 B,0x10)

0x20

Y(总线 C,0x10)

0x30

交易

  • 从设备 X 驱动程序请求一个事务(在适配器 B 上),从设备地址 0x10

  • ATR 驱动程序发现从设备 X 在总线 B 上,并且别名为 0x20,使用地址 0x20 重写消息,转发到适配器 A

  • 总线 A 上的物理 I2C 事务,从设备地址 0x20

  • ATR 芯片检测到地址 0x20 上的事务,在表中找到它,将事务传播到总线 B,地址转换为 0x10,保持总线 A 上的时钟拉伸,等待回复

  • 从设备 X 芯片(在总线 B 上)检测到其自己的物理地址 0x10 上的事务,并正常回复

  • ATR 芯片停止时钟拉伸,并在总线 A 上转发回复,地址转换回 0x20

  • ATR 驱动程序接收回复,使用地址 0x10 重写消息,因为它们最初是

  • 从设备 X 驱动程序取回 msgs[],其中包含回复和地址 0x10

用法

  1. 在驱动程序中(通常在 probe 函数中),通过调用 i2c_atr_new() 并传递 attach/detach 回调来添加 ATR

  2. 当调用 attach 回调时,选择适当的别名,在芯片中配置它,并在 alias_id 参数中返回所选别名

  3. 当调用 detach 回调时,从芯片中取消配置别名,并将别名放回池中以供以后使用

I2C ATR 函数和数据结构

enum i2c_atr_flags

I2C ATR 驱动程序的标志

常量

I2C_ATR_F_STATIC

ATR 不支持动态映射,使用静态映射。映射只会因设备从子总线添加或删除而添加或删除。 ATR 池必须足够大,以容纳预计添加到子总线的所有设备。

I2C_ATR_F_PASSTHROUGH

允许未映射的传入地址通过

struct i2c_atr_ops

从 ATR 到设备驱动程序的回调。

定义:

struct i2c_atr_ops {
    int (*attach_addr)(struct i2c_atr *atr, u32 chan_id, u16 addr, u16 alias);
    void (*detach_addr)(struct i2c_atr *atr, u32 chan_id, u16 addr);
};

成员

attach_addr

通知驱动程序有新设备连接到子总线,并为其分配了别名。 驱动程序必须配置硬件以使用该别名。

detach_addr

通知驱动程序设备已断开连接。 驱动程序必须配置硬件以停止使用该别名。

描述

所有这些函数在成功时返回 0,否则返回一个负错误代码。

struct i2c_atr_adap_desc

ATR 下游总线描述符

定义:

struct i2c_atr_adap_desc {
    u32 chan_id;
    struct device *parent;
    struct fwnode_handle *bus_handle;
    size_t num_aliases;
    u16 *aliases;
};

成员

chan_id

新适配器的索引(0 .. max_adapters-1)。此值将传递给 struct i2c_atr_ops 中的回调。

parent

用作新 i2c 适配器父设备的设备,或者为 NULL 以使用 i2c-atr 设备作为父设备。

bus_handle

指向适配器的 i2c 外设的 fwnode 句柄,或 NULL。

num_aliases

此适配器的私有别名池中的别名数量。如果此适配器使用 ATR 的全局别名池,则设置为零。

aliases

适配器使用的私有别名的可选数组,而不是 ATR 的全局别名池。如果 num_aliases > 0,则必须包含确切的 num_aliases 条目,否则将被忽略。

struct i2c_atr *i2c_atr_new(struct i2c_adapter *parent, struct device *dev, const struct i2c_atr_ops *ops, int max_adapters, u32 flags)

分配和初始化 I2C ATR 助手。

参数

struct i2c_adapter *parent

父(上游)适配器

struct device *dev

充当 ATR 的设备

const struct i2c_atr_ops *ops

特定于驱动程序的回调

int max_adapters

子适配器的最大数量

u32 flags

ATR 的标志

描述

新的 ATR 助手连接到父适配器,但没有子适配器。 调用 i2c_atr_add_adapter() 添加一些。

调用 i2c_atr_delete() 删除。

返回

指向新 ATR 助手对象的指针,或 ERR_PTR

void i2c_atr_delete(struct i2c_atr *atr)

删除 I2C ATR 助手。

参数

struct i2c_atr *atr

要删除的 I2C ATR 助手。

描述

前提条件:所有使用 i2c_atr_add_adapter() 添加的适配器必须通过调用 i2c_atr_del_adapter() 来删除。

int i2c_atr_add_adapter(struct i2c_atr *atr, struct i2c_atr_adap_desc *desc)

创建子(“下游”)I2C 总线。

参数

struct i2c_atr *atr

I2C ATR

struct i2c_atr_adap_desc *desc

ATR 适配器描述符

描述

调用此函数后,将出现一条新的 i2c 总线。 在下游总线上添加和删除设备将导致调用 i2c_atr_ops->attach_clienti2c_atr_ops->detach_client 回调,供驱动程序为设备分配别名。

适配器的 fwnode 设置为 bus_handle,或者如果 bus_handle 为 NULL,则该函数会在 i2c-atr 设备的“i2c-atr”节点下查找其 ‘reg’ 属性与 chan_id 匹配的子节点。

调用 i2c_atr_del_adapter() 删除适配器。

返回

成功时为 0,否则为负错误代码。

void i2c_atr_del_adapter(struct i2c_atr *atr, u32 chan_id)

删除 i2c_atr_add_adapter() 添加的子(“下游”)I2C 总线。 如果没有添加 I2C 总线,则此函数不执行任何操作。

参数

struct i2c_atr *atr

I2C ATR

u32 chan_id

要删除的适配器的索引(0 .. max_adapters-1)

void i2c_atr_set_driver_data(struct i2c_atr *atr, void *data)

将私有驱动程序数据设置为 i2c-atr 实例。

参数

struct i2c_atr *atr

I2C ATR

void *data

指向要存储的数据的指针

void *i2c_atr_get_driver_data(struct i2c_atr *atr)

获取存储的驱动程序数据。

参数

struct i2c_atr *atr

I2C ATR

返回

指向存储数据的指针