요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
=====================================
Linux I2C slave interface description
=====================================
by Wolfram Sang <[email protected]> in 2014-15
Linux can also be an I2C slave if the I2C controller in use has slave
functionality. For that to work, one needs slave support in the bus driver plus
a hardware independent software backend providing the actual functionality. An
example for the latter is the slave-eeprom driver, which acts as a dual memory
driver. While another I2C master on the bus can access it like a regular
EEPROM, the Linux I2C slave can access the content via sysfs and handle data as
needed. The backend driver and the I2C bus driver communicate via events. Here
is a small graph visualizing the data flow and the means by which data is
transported. The dotted line marks only one example. The backend could also
use a character device, be in-kernel only, or something completely different::
e.g. sysfs I2C slave events I/O registers
+-----------+ v +---------+ v +--------+ v +------------+
| Userspace +........+ Backend +-----------+ Driver +-----+ Controller |
+-----------+ +---------+ +--------+ +------------+
| |
----------------------------------------------------------------+-- I2C
--------------------------------------------------------------+---- Bus
Note: Technically, there is also the I2C core between the backend and the
driver. However, at this time of writing, the layer is transparent.
User manual
===========
I2C slave backends behave like standard I2C clients. So, you can instantiate
them as described in the document instantiating-devices.rst. The only
difference is that i2c slave backends have their own address space. So, you
have to add 0x1000 to the address you would originally request. An example for
instantiating the slave-eeprom driver from userspace at the 7 bit address 0x64
on bus 1::
# echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-1/new_device
Each backend should come with separate documentation to describe its specific
behaviour and setup.
Developer manual
================
First, the events which are used by the bus driver and the backend will be
described in detail. After that, some implementation hints for extending bus
drivers and writing backends will be given.
I2C slave events
----------------
The bus driver sends an event to the backend using the following function::
ret = i2c_slave_event(client, event, &val)
'client' describes the I2C slave device. 'event' is one of the special event
types described hereafter. 'val' holds an u8 value for the data byte to be
read/written and is thus bidirectional. The pointer to val must always be
provided even if val is not used for an event, i.e. don't use NULL here. 'ret'
is the return value from the backend. Mandatory events must be provided by the
bus drivers and must be checked for by backend drivers.
Event types:
* I2C_SLAVE_WRITE_REQUESTED (mandatory)
'val': unused
'ret': 0 if the backend is ready, otherwise some errno
Another I2C master wants to write data to us. This event should be sent once
our own address and the write bit was detected. The data did not arrive yet, so
there is nothing to process or return. After returning, the bus driver must
always ack the address phase. If 'ret' is zero, backend initialization or
wakeup is done and further data may be received. If 'ret' is an errno, the bus
driver should nack all incoming bytes until the next stop condition to enforce
a retry of the transmission.
* I2C_SLAVE_READ_REQUESTED (mandatory)
'val': backend returns first byte to be sent
'ret': always 0
Another I2C master wants to read data from us. This event should be sent once
our own address and the read bit was detected. After returning, the bus driver
should transmit the first byte.
* I2C_SLAVE_WRITE_RECEIVED (mandatory)
'val': bus driver delivers received byte
'ret': 0 if the byte should be acked, some errno if the byte should be nacked
Another I2C master has sent a byte to us which needs to be set in 'val'. If 'ret'
is zero, the bus driver should ack this byte. If 'ret' is an errno, then the byte
should be nacked.
* I2C_SLAVE_READ_PROCESSED (mandatory)
'val': backend returns next byte to be sent
'ret': always 0
The bus driver requests the next byte to be sent to another I2C master in
'val'. Important: This does not mean that the previous byte has been acked, it
only means that the previous byte is shifted out to the bus! To ensure seamless
transmission, most hardware requests the next byte when the previous one is
still shifted out. If the master sends NACK and stops reading after the byte
currently shifted out, this byte requested here is never used. It very likely
needs to be sent again on the next I2C_SLAVE_READ_REQUEST, depending a bit on
your backend, though.
* I2C_SLAVE_STOP (mandatory)
'val': unused
'ret': always 0
A stop condition was received. This can happen anytime and the backend should
reset its state machine for I2C transfers to be able to receive new requests.
Software backends
-----------------
If you want to write a software backend:
* use a standard i2c_driver and its matching mechanisms
* write the slave_callback which handles the above slave events
(best using a state machine)
* register this callback via i2c_slave_register()
Check the i2c-slave-eeprom driver as an example.
Bus driver support
------------------
If you want to add slave support to the bus driver:
* implement calls to register/unregister the slave and add those to the
struct i2c_algorithm. When registering, you probably need to set the I2C
slave address and enable slave specific interrupts. If you use runtime pm, you
should use pm_runtime_get_sync() because your device usually needs to be
powered on always to be able to detect its slave address. When unregistering,
do the inverse of the above.
* Catch the slave interrupts and send appropriate i2c_slave_events to the backend.
Note that most hardware supports being master _and_ slave on the same bus. So,
if you extend a bus driver, please make sure that the driver supports that as
well. In almost all cases, slave support does not need to disable the master
functionality.
Check the i2c-rcar driver as an example.
About ACK/NACK
--------------
It is good behaviour to always ACK the address phase, so the master knows if a
device is basically present or if it mysteriously disappeared. Using NACK to
state being busy is troublesome. SMBus demands to always ACK the address phase,
while the I2C specification is more loose on that. Most I2C controllers also
automatically ACK when detecting their slave addresses, so there is no option
to NACK them. For those reasons, this API does not support NACK in the address
phase.
Currently, there is no slave event to report if the master did ACK or NACK a
byte when it reads from us. We could make this an optional event if the need
arises. However, cases should be extremely rare because the master is expected
to send STOP after that and we have an event for that. Also, keep in mind not
all I2C controllers have the possibility to report that event.
About buffers
-------------
During development of this API, the question of using buffers instead of just
bytes came up. Such an extension might be possible, usefulness is unclear at
this time of writing. Some points to keep in mind when using buffers:
* Buffers should be opt-in and backend drivers will always have to support
byte-based transactions as the ultimate fallback anyhow because this is how
the majority of HW works.
* For backends simulating hardware registers, buffers are largely not helpful
because after each byte written an action should be immediately triggered.
For reads, the data kept in the buffer might get stale if the backend just
updated a register because of internal processing.
* A master can send STOP at any time. For partially transferred buffers, this
means additional code to handle this exception. Such code tends to be
error-prone.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Linux I2C 슬레이브 인터페이스의 구성
1-29이 문서는 Wolfram Sang이 2014~2015년에 작성했습니다. 사용하는 I2C 컨트롤러가 슬레이브 기능을 제공한다면 Linux도 I2C 슬레이브로 동작할 수 있습니다.
이를 위해서는 버스 드라이버의 슬레이브 지원과 실제 기능을 제공하는 하드웨어 독립 소프트웨어 백엔드가 모두 필요합니다. 예를 들어 `slave-eeprom` 드라이버는 이중 메모리 드라이버처럼 동작합니다. 버스의 다른 I2C 마스터는 일반 EEPROM처럼 접근하고, Linux I2C 슬레이브 쪽은 sysfs를 통해 같은 내용을 읽고 필요한 방식으로 데이터를 처리합니다.
백엔드 드라이버와 I2C 버스 드라이버는 이벤트로 통신합니다. 원문의 점선은 사용자 공간과 백엔드를 sysfs로 연결하는 한 가지 예일 뿐입니다. 백엔드는 문자 장치를 제공하거나, 커널 내부에서만 동작하거나, 완전히 다른 인터페이스를 사용할 수도 있습니다.
원문의 ASCII 그림을 같은 계층과 전달 수단으로 구조화했습니다.
외부 마스터 요청과 사용자 공간 접근이 백엔드에서 만나는 흐름입니다.
기술적으로 백엔드와 버스 드라이버 사이에는 I2C core도 있습니다. 다만 이 문서 작성 시점의 슬레이브 이벤트 경로에서는 해당 계층이 투명하므로 그림에서 생략했습니다.
=====================================
Linux I2C slave interface description
=====================================
by Wolfram Sang <[email protected]> in 2014-15
Linux can also be an I2C slave if the I2C controller in use has slave
functionality. For that to work, one needs slave support in the bus driver plus
a hardware independent software backend providing the actual functionality. An
example for the latter is the slave-eeprom driver, which acts as a dual memory
driver. While another I2C master on the bus can access it like a regular
EEPROM, the Linux I2C slave can access the content via sysfs and handle data as
needed. The backend driver and the I2C bus driver communicate via events. Here
is a small graph visualizing the data flow and the means by which data is
transported. The dotted line marks only one example. The backend could also
use a character device, be in-kernel only, or something completely different::
e.g. sysfs I2C slave events I/O registers
+-----------+ v +---------+ v +--------+ v +------------+
| Userspace +........+ Backend +-----------+ Driver +-----+ Controller |
+-----------+ +---------+ +--------+ +------------+
| |
----------------------------------------------------------------+-- I2C
--------------------------------------------------------------+---- Bus
Note: Technically, there is also the I2C core between the backend and the
driver. However, at this time of writing, the layer is transparent.
사용자 설정과 개발자 인터페이스의 출발점
30-52I2C 슬레이브 백엔드는 표준 I2C 클라이언트처럼 동작하므로 `instantiating-devices.rst`에 설명된 방식으로 생성할 수 있습니다. 차이는 슬레이브 백엔드가 별도의 주소 공간을 사용한다는 점입니다.
요청하려는 원래 7비트 주소에 `0x1000`을 더해야 합니다. 예를 들어 버스 1의 7비트 주소 `0x64`에 `slave-eeprom`을 만들 때는 `0x1064`를 `new_device`에 기록합니다.
# echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-1/new_device
일반 I2C 주소와 생성 인터페이스의 값을 구분합니다.
각 백엔드는 고유한 동작과 설정을 설명하는 별도 문서를 제공해야 합니다.
개발자 설명은 먼저 버스 드라이버와 백엔드가 공유하는 이벤트를 정의하고, 이어서 기존 버스 드라이버에 슬레이브 기능을 추가하는 방법과 새 백엔드를 작성하는 방법을 안내합니다.
User manual
===========
I2C slave backends behave like standard I2C clients. So, you can instantiate
them as described in the document instantiating-devices.rst. The only
difference is that i2c slave backends have their own address space. So, you
have to add 0x1000 to the address you would originally request. An example for
instantiating the slave-eeprom driver from userspace at the 7 bit address 0x64
on bus 1::
# echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-1/new_device
Each backend should come with separate documentation to describe its specific
behaviour and setup.
Developer manual
================
First, the events which are used by the bus driver and the backend will be
described in detail. After that, some implementation hints for extending bus
drivers and writing backends will be given.
필수 I2C 슬레이브 이벤트
53-128버스 드라이버는 `ret = i2c_slave_event(client, event, &val)`을 호출해 백엔드에 이벤트를 보냅니다. `client`는 I2C 슬레이브 장치, `event`는 아래의 특수 이벤트 유형, `val`은 읽거나 쓸 데이터 바이트를 담는 양방향 `u8` 값입니다.
이벤트가 `val`을 사용하지 않더라도 `&val` 포인터는 항상 제공해야 하며 `NULL`을 전달하면 안 됩니다. `ret`은 백엔드의 반환값입니다. 버스 드라이버는 필수 이벤트를 모두 제공해야 하고, 백엔드는 그 이벤트를 검사해야 합니다.
각 이벤트에서 `val`과 `ret`이 의미하는 바를 정리합니다.
`I2C_SLAVE_WRITE_REQUESTED`는 다른 마스터가 우리 주소와 write 비트를 보냈을 때 한 번 전달합니다. 아직 데이터 바이트는 도착하지 않았으므로 처리하거나 반환할 데이터가 없습니다. 버스 드라이버는 이 콜백이 끝난 뒤 주소 단계를 항상 ACK해야 합니다.
반환값이 0이면 백엔드의 초기화 또는 깨우기가 끝나 이후 데이터를 받을 수 있습니다. errno이면 전송을 다시 시도하게 만들기 위해 다음 STOP 조건까지 들어오는 모든 데이터 바이트를 NACK하는 것이 권장됩니다.
`I2C_SLAVE_READ_REQUESTED`는 다른 마스터가 우리 주소와 read 비트를 보냈을 때 한 번 전달합니다. 백엔드는 `val`에 첫 바이트를 넣고, 버스 드라이버는 콜백이 끝난 뒤 그 바이트를 전송합니다.
`I2C_SLAVE_WRITE_RECEIVED`에서는 다른 마스터가 보낸 바이트를 버스 드라이버가 `val`에 넣습니다. 백엔드가 0을 반환하면 해당 바이트를 ACK하고, errno를 반환하면 NACK합니다.
`I2C_SLAVE_READ_PROCESSED`는 다른 마스터에게 보낼 다음 바이트를 요청합니다. 이 이벤트는 이전 바이트가 마스터에게 ACK되었다는 뜻이 아니라, 이전 바이트가 버스로 시프트 아웃되고 있다는 뜻입니다. 대부분의 하드웨어는 끊김 없는 전송을 위해 이전 바이트가 나가는 동안 다음 바이트를 미리 요청합니다.
마스터가 현재 전송 중인 바이트 뒤에 NACK를 보내 읽기를 중단하면 이번 이벤트로 준비한 다음 바이트는 사용되지 않습니다. 백엔드의 의미에 따라 다음 `I2C_SLAVE_READ_REQUESTED` 때 이 바이트를 다시 보내야 할 가능성이 큽니다.
`I2C_SLAVE_STOP`은 STOP 조건을 수신했음을 알립니다. STOP은 언제든 발생할 수 있으므로 백엔드는 새 요청을 받을 수 있도록 I2C 전송 상태 머신을 초기화해야 합니다.
주소 선택부터 STOP까지 이벤트와 응답을 연결합니다.
첫 바이트와 선행 준비되는 다음 바이트를 구분합니다.
I2C slave events
----------------
The bus driver sends an event to the backend using the following function::
ret = i2c_slave_event(client, event, &val)
'client' describes the I2C slave device. 'event' is one of the special event
types described hereafter. 'val' holds an u8 value for the data byte to be
read/written and is thus bidirectional. The pointer to val must always be
provided even if val is not used for an event, i.e. don't use NULL here. 'ret'
is the return value from the backend. Mandatory events must be provided by the
bus drivers and must be checked for by backend drivers.
Event types:
* I2C_SLAVE_WRITE_REQUESTED (mandatory)
'val': unused
'ret': 0 if the backend is ready, otherwise some errno
Another I2C master wants to write data to us. This event should be sent once
our own address and the write bit was detected. The data did not arrive yet, so
there is nothing to process or return. After returning, the bus driver must
always ack the address phase. If 'ret' is zero, backend initialization or
wakeup is done and further data may be received. If 'ret' is an errno, the bus
driver should nack all incoming bytes until the next stop condition to enforce
a retry of the transmission.
* I2C_SLAVE_READ_REQUESTED (mandatory)
'val': backend returns first byte to be sent
'ret': always 0
Another I2C master wants to read data from us. This event should be sent once
our own address and the read bit was detected. After returning, the bus driver
should transmit the first byte.
* I2C_SLAVE_WRITE_RECEIVED (mandatory)
'val': bus driver delivers received byte
'ret': 0 if the byte should be acked, some errno if the byte should be nacked
Another I2C master has sent a byte to us which needs to be set in 'val'. If 'ret'
is zero, the bus driver should ack this byte. If 'ret' is an errno, then the byte
should be nacked.
* I2C_SLAVE_READ_PROCESSED (mandatory)
'val': backend returns next byte to be sent
'ret': always 0
The bus driver requests the next byte to be sent to another I2C master in
'val'. Important: This does not mean that the previous byte has been acked, it
only means that the previous byte is shifted out to the bus! To ensure seamless
transmission, most hardware requests the next byte when the previous one is
still shifted out. If the master sends NACK and stops reading after the byte
currently shifted out, this byte requested here is never used. It very likely
needs to be sent again on the next I2C_SLAVE_READ_REQUEST, depending a bit on
your backend, though.
* I2C_SLAVE_STOP (mandatory)
'val': unused
'ret': always 0
A stop condition was received. This can happen anytime and the backend should
reset its state machine for I2C transfers to be able to receive new requests.
소프트웨어 백엔드와 버스 드라이버 구현
129-163소프트웨어 백엔드를 작성할 때는 표준 `i2c_driver`와 그 매칭 메커니즘을 사용합니다. 위 슬레이브 이벤트를 처리하는 `slave_callback`을 상태 머신 형태로 작성하고 `i2c_slave_register()`로 등록합니다. 실제 구현 예는 `i2c-slave-eeprom` 드라이버입니다.
표준 I2C 드라이버에서 슬레이브 콜백을 연결하는 순서입니다.
버스 드라이버에 슬레이브 지원을 추가할 때는 슬레이브 등록과 등록 해제 호출을 구현하고 `struct i2c_algorithm`에 연결합니다. 등록할 때 보통 슬레이브 주소를 설정하고 슬레이브 전용 인터럽트를 활성화해야 합니다.
런타임 전원 관리를 사용한다면 장치가 자기 슬레이브 주소를 항상 감지할 수 있도록 대개 계속 전원이 켜져 있어야 하므로 `pm_runtime_get_sync()`를 사용해야 합니다. 등록 해제 시에는 주소, 인터럽트, 전원 참조 설정을 반대로 되돌립니다.
컨트롤러의 슬레이브 인터럽트를 처리해 상태에 맞는 `i2c_slave_event`를 백엔드에 보내야 합니다.
대부분의 하드웨어는 같은 버스에서 마스터와 슬레이브 역할을 동시에 지원합니다. 버스 드라이버를 확장할 때도 두 역할을 함께 지원해야 하며, 거의 모든 경우 슬레이브 지원 때문에 마스터 기능을 끌 필요는 없습니다. 참고 구현은 `i2c-rcar` 드라이버입니다.
등록부터 이벤트 전달과 해제까지의 책임입니다.
Software backends
-----------------
If you want to write a software backend:
* use a standard i2c_driver and its matching mechanisms
* write the slave_callback which handles the above slave events
(best using a state machine)
* register this callback via i2c_slave_register()
Check the i2c-slave-eeprom driver as an example.
Bus driver support
------------------
If you want to add slave support to the bus driver:
* implement calls to register/unregister the slave and add those to the
struct i2c_algorithm. When registering, you probably need to set the I2C
slave address and enable slave specific interrupts. If you use runtime pm, you
should use pm_runtime_get_sync() because your device usually needs to be
powered on always to be able to detect its slave address. When unregistering,
do the inverse of the above.
* Catch the slave interrupts and send appropriate i2c_slave_events to the backend.
Note that most hardware supports being master _and_ slave on the same bus. So,
if you extend a bus driver, please make sure that the driver supports that as
well. In almost all cases, slave support does not need to disable the master
functionality.
Check the i2c-rcar driver as an example.
주소 ACK 정책과 바이트 단위 API
164-201주소 단계는 항상 ACK하는 것이 바람직합니다. 그래야 마스터가 장치가 기본적으로 존재하는지, 갑자기 사라졌는지를 구분할 수 있습니다. 바쁨을 알리기 위해 주소를 NACK하는 방식은 문제가 많습니다.
SMBus는 주소 단계를 항상 ACK할 것을 요구하지만 I2C 규격은 더 느슨합니다. 또한 많은 I2C 컨트롤러가 자기 슬레이브 주소를 감지하면 자동으로 ACK해 소프트웨어가 NACK할 선택지가 없습니다. 이런 이유로 이 API는 주소 단계 NACK를 지원하지 않습니다.
현재 마스터가 우리에게서 바이트를 읽을 때 그 바이트를 ACK했는지 NACK했는지를 보고하는 슬레이브 이벤트는 없습니다. 필요해지면 선택적 이벤트로 추가할 수 있지만, 마스터는 보통 직후 STOP을 보내고 이미 STOP 이벤트가 있으므로 실제 필요 사례는 매우 드뭅니다. 모든 I2C 컨트롤러가 바이트 ACK/NACK 보고 기능을 제공하는 것도 아닙니다.
주소 단계와 데이터 단계의 지원 범위를 구분합니다.
API 개발 중 바이트 대신 버퍼를 사용하는 방안도 논의됐습니다. 확장은 가능할 수 있지만 이 문서 작성 시점에는 유용성이 명확하지 않습니다.
버퍼 지원은 선택 기능이어야 하고, 백엔드는 최종 대체 경로로 바이트 단위 전송을 항상 지원해야 합니다. 대다수 하드웨어가 바이트 단위로 동작하기 때문입니다.
하드웨어 레지스터를 모사하는 백엔드에서는 각 쓰기 바이트 직후 동작을 일으켜야 하므로 버퍼가 대체로 도움이 되지 않습니다. 읽기에서도 내부 처리로 레지스터가 갱신되면 버퍼에 미리 담긴 데이터가 오래된 값이 될 수 있습니다.
마스터는 언제든 STOP을 보낼 수 있습니다. 부분 전송된 버퍼를 처리하는 예외 코드가 추가로 필요하고, 이런 코드는 오류가 생기기 쉽습니다.
바이트 API를 기본으로 유지해야 하는 이유입니다.
About ACK/NACK
--------------
It is good behaviour to always ACK the address phase, so the master knows if a
device is basically present or if it mysteriously disappeared. Using NACK to
state being busy is troublesome. SMBus demands to always ACK the address phase,
while the I2C specification is more loose on that. Most I2C controllers also
automatically ACK when detecting their slave addresses, so there is no option
to NACK them. For those reasons, this API does not support NACK in the address
phase.
Currently, there is no slave event to report if the master did ACK or NACK a
byte when it reads from us. We could make this an optional event if the need
arises. However, cases should be extremely rare because the master is expected
to send STOP after that and we have an event for that. Also, keep in mind not
all I2C controllers have the possibility to report that event.
About buffers
-------------
During development of this API, the question of using buffers instead of just
bytes came up. Such an extension might be possible, usefulness is unclear at
this time of writing. Some points to keep in mind when using buffers:
* Buffers should be opt-in and backend drivers will always have to support
byte-based transactions as the ultimate fallback anyhow because this is how
the majority of HW works.
* For backends simulating hardware registers, buffers are largely not helpful
because after each byte written an action should be immediately triggered.
For reads, the data kept in the buffer might get stale if the backend just
updated a register because of internal processing.
* A master can send STOP at any time. For partially transferred buffers, this
means additional code to handle this exception. Such code tends to be
error-prone.
요약·해설
slave-interface.rst:1-201I2C 슬레이브 프레임워크는 컨트롤러 버스 드라이버와 하드웨어 독립 백엔드를 필수 이벤트로 연결합니다. 주소 단계는 항상 ACK하고, 데이터 바이트 처리와 STOP 기반 상태 초기화는 백엔드 상태 머신이 담당합니다.
원문 분량과 핵심 검토 대상을 요약합니다.
문서의 주요 동작을 압축합니다.