요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
==================================
PMBus core driver and internal API
==================================
Introduction
============
[from pmbus.org] The Power Management Bus (PMBus) is an open standard
power-management protocol with a fully defined command language that facilitates
communication with power converters and other devices in a power system. The
protocol is implemented over the industry-standard SMBus serial interface and
enables programming, control, and real-time monitoring of compliant power
conversion products. This flexible and highly versatile standard allows for
communication between devices based on both analog and digital technologies, and
provides true interoperability which will reduce design complexity and shorten
time to market for power system designers. Pioneered by leading power supply and
semiconductor companies, this open power system standard is maintained and
promoted by the PMBus Implementers Forum (PMBus-IF), comprising 30+ adopters
with the objective to provide support to, and facilitate adoption among, users.
Unfortunately, while PMBus commands are standardized, there are no mandatory
commands, and manufacturers can add as many non-standard commands as they like.
Also, different PMBUs devices act differently if non-supported commands are
executed. Some devices return an error, some devices return 0xff or 0xffff and
set a status error flag, and some devices may simply hang up.
Despite all those difficulties, a generic PMBus device driver is still useful
and supported since kernel version 2.6.39. However, it was necessary to support
device specific extensions in addition to the core PMBus driver, since it is
simply unknown what new device specific functionality PMBus device developers
come up with next.
To make device specific extensions as scalable as possible, and to avoid having
to modify the core PMBus driver repeatedly for new devices, the PMBus driver was
split into core, generic, and device specific code. The core code (in
pmbus_core.c) provides generic functionality. The generic code (in pmbus.c)
provides support for generic PMBus devices. Device specific code is responsible
for device specific initialization and, if needed, maps device specific
functionality into generic functionality. This is to some degree comparable
to PCI code, where generic code is augmented as needed with quirks for all kinds
of devices.
PMBus device capabilities auto-detection
========================================
For generic PMBus devices, code in pmbus.c attempts to auto-detect all supported
PMBus commands. Auto-detection is somewhat limited, since there are simply too
many variables to consider. For example, it is almost impossible to autodetect
which PMBus commands are paged and which commands are replicated across all
pages (see the PMBus specification for details on multi-page PMBus devices).
For this reason, it often makes sense to provide a device specific driver if not
all commands can be auto-detected. The data structures in this driver can be
used to inform the core driver about functionality supported by individual
chips.
Some commands are always auto-detected. This applies to all limit commands
(lcrit, min, max, and crit attributes) as well as associated alarm attributes.
Limits and alarm attributes are auto-detected because there are simply too many
possible combinations to provide a manual configuration interface.
PMBus internal API
==================
The API between core and device specific PMBus code is defined in
drivers/hwmon/pmbus/pmbus.h. In addition to the internal API, pmbus.h defines
standard PMBus commands and virtual PMBus commands.
Standard PMBus commands
-----------------------
Standard PMBus commands (commands values 0x00 to 0xff) are defined in the PMBUs
specification.
Virtual PMBus commands
----------------------
Virtual PMBus commands are provided to enable support for non-standard
functionality which has been implemented by several chip vendors and is thus
desirable to support.
Virtual PMBus commands start with command value 0x100 and can thus easily be
distinguished from standard PMBus commands (which can not have values larger
than 0xff). Support for virtual PMBus commands is device specific and thus has
to be implemented in device specific code.
Virtual commands are named PMBUS_VIRT_xxx and start with PMBUS_VIRT_BASE. All
virtual commands are word sized.
There are currently two types of virtual commands.
- READ commands are read-only; writes are either ignored or return an error.
- RESET commands are read/write. Reading reset registers returns zero
(used for detection), writing any value causes the associated history to be
reset.
Virtual commands have to be handled in device specific driver code. Chip driver
code returns non-negative values if a virtual command is supported, or a
negative error code if not. The chip driver may return -ENODATA or any other
Linux error code in this case, though an error code other than -ENODATA is
handled more efficiently and thus preferred. Either case, the calling PMBus
core code will abort if the chip driver returns an error code when reading
or writing virtual registers (in other words, the PMBus core code will never
send a virtual command to a chip).
PMBus driver information
------------------------
PMBus driver information, defined in struct pmbus_driver_info, is the main means
for device specific drivers to pass information to the core PMBus driver.
Specifically, it provides the following information.
- For devices supporting its data in Direct Data Format, it provides coefficients
for converting register values into normalized data. This data is usually
provided by chip manufacturers in device datasheets.
- Supported chip functionality can be provided to the core driver. This may be
necessary for chips which react badly if non-supported commands are executed,
and/or to speed up device detection and initialization.
- Several function entry points are provided to support overriding and/or
augmenting generic command execution. This functionality can be used to map
non-standard PMBus commands to standard commands, or to augment standard
command return values with device specific information.
PEC Support
===========
Many PMBus devices support SMBus PEC (Packet Error Checking). If supported
by both the I2C adapter and by the PMBus chip, it is by default enabled.
If PEC is supported, the PMBus core driver adds an attribute named 'pec' to
the I2C device. This attribute can be used to control PEC support in the
communication with the PMBus chip.
API functions
=============
Functions provided by chip driver
---------------------------------
All functions return the command return value (read) or zero (write) if
successful. A return value of -ENODATA indicates that there is no manufacturer
specific command, but that a standard PMBus command may exist. Any other
negative return value indicates that the commands does not exist for this
chip, and that no attempt should be made to read or write the standard
command.
As mentioned above, an exception to this rule applies to virtual commands,
which *must* be handled in driver specific code. See "Virtual PMBus Commands"
above for more details.
Command execution in the core PMBus driver code is as follows::
if (chip_access_function) {
status = chip_access_function();
if (status != -ENODATA)
return status;
}
if (command >= PMBUS_VIRT_BASE) /* For word commands/registers only */
return -EINVAL;
return generic_access();
Chip drivers may provide pointers to the following functions in struct
pmbus_driver_info. All functions are optional.
::
int (*read_byte_data)(struct i2c_client *client, int page, int reg);
Read byte from page <page>, register <reg>.
<page> may be -1, which means "current page".
::
int (*read_word_data)(struct i2c_client *client, int page, int phase,
int reg);
Read word from page <page>, phase <phase>, register <reg>. If the chip does not
support multiple phases, the phase parameter can be ignored. If the chip
supports multiple phases, a phase value of 0xff indicates all phases.
::
int (*write_word_data)(struct i2c_client *client, int page, int reg,
u16 word);
Write word to page <page>, register <reg>.
::
int (*write_byte)(struct i2c_client *client, int page, u8 value);
Write byte to page <page>, register <reg>.
<page> may be -1, which means "current page".
::
int (*identify)(struct i2c_client *client, struct pmbus_driver_info *info);
Determine supported PMBus functionality. This function is only necessary
if a chip driver supports multiple chips, and the chip functionality is not
pre-determined. It is currently only used by the generic pmbus driver
(pmbus.c).
Functions exported by core driver
---------------------------------
Chip drivers are expected to use the following functions to read or write
PMBus registers. Chip drivers may also use direct I2C commands. If direct I2C
commands are used, the chip driver code must not directly modify the current
page, since the selected page is cached in the core driver and the core driver
will assume that it is selected. Using pmbus_set_page() to select a new page
is mandatory.
::
int pmbus_set_page(struct i2c_client *client, u8 page, u8 phase);
Set PMBus page register to <page> and <phase> for subsequent commands.
If the chip does not support multiple phases, the phase parameter is
ignored. Otherwise, a phase value of 0xff selects all phases.
::
int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 phase,
u8 reg);
Read word data from <page>, <phase>, <reg>. Similar to
i2c_smbus_read_word_data(), but selects page and phase first. If the chip does
not support multiple phases, the phase parameter is ignored. Otherwise, a phase
value of 0xff selects all phases.
::
int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg,
u16 word);
Write word data to <page>, <reg>. Similar to i2c_smbus_write_word_data(), but
selects page first.
::
int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
Read byte data from <page>, <reg>. Similar to i2c_smbus_read_byte_data(), but
selects page first. <page> may be -1, which means "current page".
::
int pmbus_write_byte(struct i2c_client *client, int page, u8 value);
Write byte data to <page>, <reg>. Similar to i2c_smbus_write_byte(), but
selects page first. <page> may be -1, which means "current page".
::
void pmbus_clear_faults(struct i2c_client *client);
Execute PMBus "Clear Fault" command on all chip pages.
This function calls the device specific write_byte function if defined.
Therefore, it must _not_ be called from that function.
::
bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
Check if byte register exists. Return true if the register exists, false
otherwise.
This function calls the device specific write_byte function if defined to
obtain the chip status. Therefore, it must _not_ be called from that function.
::
bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
Check if word register exists. Return true if the register exists, false
otherwise.
This function calls the device specific write_byte function if defined to
obtain the chip status. Therefore, it must _not_ be called from that function.
::
int pmbus_do_probe(struct i2c_client *client, struct pmbus_driver_info *info);
Execute probe function. Similar to standard probe function for other drivers,
with the pointer to struct pmbus_driver_info as additional argument. Calls
identify function if supported. Must only be called from device probe
function.
::
const struct pmbus_driver_info
*pmbus_get_driver_info(struct i2c_client *client);
Return pointer to struct pmbus_driver_info as passed to pmbus_do_probe().
PMBus driver platform data
==========================
PMBus platform data is defined in include/linux/pmbus.h. Platform data
currently provides a flags field with four bits used::
#define PMBUS_SKIP_STATUS_CHECK BIT(0)
#define PMBUS_WRITE_PROTECTED BIT(1)
#define PMBUS_NO_CAPABILITY BIT(2)
#define PMBUS_READ_STATUS_AFTER_FAILED_CHECK BIT(3)
#define PMBUS_NO_WRITE_PROTECT BIT(4)
#define PMBUS_USE_COEFFICIENTS_CMD BIT(5)
#define PMBUS_OP_PROTECTED BIT(6)
#define PMBUS_VOUT_PROTECTED BIT(7)
struct pmbus_platform_data {
u32 flags; /* Device specific flags */
/* regulator support */
int num_regulators;
struct regulator_init_data *reg_init_data;
};
Flags
-----
PMBUS_SKIP_STATUS_CHECK
During register detection, skip checking the status register for
communication or command errors.
Some PMBus chips respond with valid data when trying to read an unsupported
register. For such chips, checking the status register is mandatory when
trying to determine if a chip register exists or not.
Other PMBus chips don't support the STATUS_CML register, or report
communication errors for no explicable reason. For such chips, checking the
status register must be disabled.
Some i2c controllers do not support single-byte commands (write commands with
no data, i2c_smbus_write_byte()). With such controllers, clearing the status
register is impossible, and the PMBUS_SKIP_STATUS_CHECK flag must be set.
PMBUS_WRITE_PROTECTED
Set if the chip is write protected and write protection is not determined
by the standard WRITE_PROTECT command.
PMBUS_NO_CAPABILITY
Some PMBus chips don't respond with valid data when reading the CAPABILITY
register. For such chips, this flag should be set so that the PMBus core
driver doesn't use CAPABILITY to determine its behavior.
PMBUS_READ_STATUS_AFTER_FAILED_CHECK
Read the STATUS register after each failed register check.
Some PMBus chips end up in an undefined state when trying to read an
unsupported register. For such chips, it is necessary to reset the
chip pmbus controller to a known state after a failed register check.
This can be done by reading a known register. By setting this flag the
driver will try to read the STATUS register after each failed
register check. This read may fail, but it will put the chip into a
known state.
PMBUS_NO_WRITE_PROTECT
Some PMBus chips respond with invalid data when reading the WRITE_PROTECT
register. For such chips, this flag should be set so that the PMBus core
driver doesn't use the WRITE_PROTECT command to determine its behavior.
PMBUS_USE_COEFFICIENTS_CMD
When this flag is set the PMBus core driver will use the COEFFICIENTS
register to initialize the coefficients for the direct mode format.
PMBUS_OP_PROTECTED
Set if the chip OPERATION command is protected and protection is not
determined by the standard WRITE_PROTECT command.
PMBUS_VOUT_PROTECTED
Set if the chip VOUT_COMMAND command is protected and protection is not
determined by the standard WRITE_PROTECT command.
Module parameter
----------------
pmbus_core.wp: PMBus write protect forced mode
PMBus may come up with a variety of write protection configuration.
'pmbus_core.wp' may be used if a particular write protection is necessary.
The ability to actually alter the protection may also depend on the chip
so the actual runtime write protection configuration may differ from
the requested one. pmbus_core currently support the following value:
* 0: write protection removed.
* 1: Disable all writes except to the WRITE_PROTECT, OPERATION,
PAGE, ON_OFF_CONFIG and VOUT_COMMAND commands.
* 2: Disable all writes except to the WRITE_PROTECT, OPERATION and
PAGE commands.
* 3: Disable all writes except to the WRITE_PROTECT command. Note that
protection should include the PAGE register. This may be problematic
for multi-page chips, if the chips strictly follows the PMBus
specification, preventing the chip from changing the active page.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
PMBus 표준과 코어 분리 구조
1-42PMBus(Power Management Bus)는 완전히 정의된 명령 언어를 갖춘 개방형 전력 관리 프로토콜입니다. 표준 SMBus 직렬 인터페이스 위에서 전력 변환기와 전력 시스템 장치의 프로그래밍, 제어, 실시간 모니터링을 제공합니다.
아날로그·디지털 기술 기반 장치가 상호 운용되도록 해 전력 시스템 설계 복잡도와 출시 시간을 줄입니다. 전원 공급 및 반도체 기업들이 시작했고 30개 이상의 채택사가 참여하는 PMBus Implementers Forum이 유지·보급합니다.
명령이 표준화되어도 필수 명령은 없으며 제조사는 비표준 명령을 자유롭게 추가할 수 있습니다. 미지원 명령을 받았을 때도 장치마다 오류를 반환하거나 `0xff` 또는 `0xffff`와 상태 오류 플래그를 반환하거나 아예 멈출 수 있습니다.
이런 어려움에도 일반 PMBus 드라이버는 커널 2.6.39부터 지원됩니다. 새 장치별 기능을 수용하기 위해 코드를 코어, 일반, 장치별 부분으로 분리했습니다.
`pmbus_core.c`는 공통 기능, `pmbus.c`는 일반 PMBus 장치 지원, 장치별 코드는 초기화와 비표준 기능의 표준 기능 매핑을 담당합니다. PCI의 일반 코드에 장치별 quirk를 보태는 구조와 비슷합니다.
표준의 유연성과 커널 코드의 책임 분리를 정리합니다.
일반 기능 위에 장치별 예외를 겹칩니다.
==================================
PMBus core driver and internal API
==================================
Introduction
============
[from pmbus.org] The Power Management Bus (PMBus) is an open standard
power-management protocol with a fully defined command language that facilitates
communication with power converters and other devices in a power system. The
protocol is implemented over the industry-standard SMBus serial interface and
enables programming, control, and real-time monitoring of compliant power
conversion products. This flexible and highly versatile standard allows for
communication between devices based on both analog and digital technologies, and
provides true interoperability which will reduce design complexity and shorten
time to market for power system designers. Pioneered by leading power supply and
semiconductor companies, this open power system standard is maintained and
promoted by the PMBus Implementers Forum (PMBus-IF), comprising 30+ adopters
with the objective to provide support to, and facilitate adoption among, users.
Unfortunately, while PMBus commands are standardized, there are no mandatory
commands, and manufacturers can add as many non-standard commands as they like.
Also, different PMBUs devices act differently if non-supported commands are
executed. Some devices return an error, some devices return 0xff or 0xffff and
set a status error flag, and some devices may simply hang up.
Despite all those difficulties, a generic PMBus device driver is still useful
and supported since kernel version 2.6.39. However, it was necessary to support
device specific extensions in addition to the core PMBus driver, since it is
simply unknown what new device specific functionality PMBus device developers
come up with next.
To make device specific extensions as scalable as possible, and to avoid having
to modify the core PMBus driver repeatedly for new devices, the PMBus driver was
split into core, generic, and device specific code. The core code (in
pmbus_core.c) provides generic functionality. The generic code (in pmbus.c)
provides support for generic PMBus devices. Device specific code is responsible
for device specific initialization and, if needed, maps device specific
functionality into generic functionality. This is to some degree comparable
to PCI code, where generic code is augmented as needed with quirks for all kinds
of devices.
기능 자동 감지의 범위와 한계
43-61일반 PMBus 장치에서는 `pmbus.c`가 지원 명령을 자동 감지합니다. 하지만 고려할 변수가 너무 많아 완전한 감지는 불가능합니다.
다중 페이지 장치에서 어떤 명령이 페이지별이고 어떤 명령이 모든 페이지에 복제되는지 자동으로 판별하기는 거의 불가능합니다.
모든 명령을 감지할 수 없다면 장치별 드라이버가 적합합니다. 장치별 데이터 구조로 각 칩의 기능을 코어에 명시할 수 있습니다.
하한 임계, 최소, 최대, 임계 속성과 관련 경보에 해당하는 모든 limit 명령은 항상 자동 감지합니다. 가능한 조합이 너무 많아 수동 구성 인터페이스로 제공하기 어렵기 때문입니다.
자동으로 찾는 항목과 장치별 정보가 필요한 항목을 구분합니다.
자동 감지와 정적 장치 정보를 결합합니다.
PMBus device capabilities auto-detection
========================================
For generic PMBus devices, code in pmbus.c attempts to auto-detect all supported
PMBus commands. Auto-detection is somewhat limited, since there are simply too
many variables to consider. For example, it is almost impossible to autodetect
which PMBus commands are paged and which commands are replicated across all
pages (see the PMBus specification for details on multi-page PMBus devices).
For this reason, it often makes sense to provide a device specific driver if not
all commands can be auto-detected. The data structures in this driver can be
used to inform the core driver about functionality supported by individual
chips.
Some commands are always auto-detected. This applies to all limit commands
(lcrit, min, max, and crit attributes) as well as associated alarm attributes.
Limits and alarm attributes are auto-detected because there are simply too many
possible combinations to provide a manual configuration interface.
표준·가상 명령과 오류 계약
62-105코어와 장치별 PMBus 코드 사이의 내부 API는 `drivers/hwmon/pmbus/pmbus.h`에 정의됩니다. 이 헤더는 내부 API와 함께 표준 PMBus 명령과 가상 PMBus 명령을 정의합니다.
표준 명령 값은 PMBus 규격이 정한 `0x00`부터 `0xff`입니다.
여러 제조사가 구현한 유용한 비표준 기능을 지원하기 위해 가상 명령을 제공합니다. 값은 `0x100`부터 시작하므로 최대 `0xff`인 표준 명령과 명확히 구분됩니다. 가상 명령 지원은 반드시 장치별 코드에서 구현해야 합니다.
가상 명령 이름은 `PMBUS_VIRT_xxx`이고 `PMBUS_VIRT_BASE`에서 시작하며 모두 워드 크기입니다. READ 유형은 읽기 전용이어서 쓰기를 무시하거나 오류를 반환합니다. RESET 유형은 읽기·쓰기가 가능하고 읽으면 감지용 0, 아무 값이나 쓰면 관련 이력을 초기화합니다.
장치별 드라이버는 지원하는 가상 명령에 음수가 아닌 값을, 지원하지 않으면 `-ENODATA` 또는 다른 Linux 오류를 반환합니다. `-ENODATA` 이외 오류가 더 효율적으로 처리되어 권장됩니다.
가상 레지스터 읽기·쓰기에 오류가 나면 코어는 중단합니다. 코어는 가상 명령을 실제 칩으로 직접 보내지 않습니다.
값 범위와 읽기·쓰기 계약입니다.
명령 값을 기준으로 장치별 코드에서 끝내야 합니다.
PMBus internal API
==================
The API between core and device specific PMBus code is defined in
drivers/hwmon/pmbus/pmbus.h. In addition to the internal API, pmbus.h defines
standard PMBus commands and virtual PMBus commands.
Standard PMBus commands
-----------------------
Standard PMBus commands (commands values 0x00 to 0xff) are defined in the PMBUs
specification.
Virtual PMBus commands
----------------------
Virtual PMBus commands are provided to enable support for non-standard
functionality which has been implemented by several chip vendors and is thus
desirable to support.
Virtual PMBus commands start with command value 0x100 and can thus easily be
distinguished from standard PMBus commands (which can not have values larger
than 0xff). Support for virtual PMBus commands is device specific and thus has
to be implemented in device specific code.
Virtual commands are named PMBUS_VIRT_xxx and start with PMBUS_VIRT_BASE. All
virtual commands are word sized.
There are currently two types of virtual commands.
- READ commands are read-only; writes are either ignored or return an error.
- RESET commands are read/write. Reading reset registers returns zero
(used for detection), writing any value causes the associated history to be
reset.
Virtual commands have to be handled in device specific driver code. Chip driver
code returns non-negative values if a virtual command is supported, or a
negative error code if not. The chip driver may return -ENODATA or any other
Linux error code in this case, though an error code other than -ENODATA is
handled more efficiently and thus preferred. Either case, the calling PMBus
core code will abort if the chip driver returns an error code when reading
or writing virtual registers (in other words, the PMBus core code will never
send a virtual command to a chip).
pmbus_driver_info와 PEC
106-132`struct pmbus_driver_info`는 장치별 드라이버가 PMBus 코어에 정보를 전달하는 주된 수단입니다.
Direct Data Format을 지원하는 장치는 레지스터 값을 정규화된 데이터로 변환하는 계수를 제공합니다. 이 계수는 보통 칩 데이터시트에 있습니다.
미지원 명령에 나쁘게 반응하는 칩을 보호하거나 감지·초기화 속도를 높이기 위해 지원 기능을 정적으로 제공할 수 있습니다. 함수 진입점을 이용해 일반 명령 실행을 재정의하거나 확장하고, 비표준 명령을 표준 명령에 매핑하거나 표준 반환값에 장치 정보를 더할 수 있습니다.
많은 PMBus 장치는 SMBus PEC(Packet Error Checking)를 지원합니다. I2C 어댑터와 PMBus 칩이 모두 지원하면 기본으로 활성화됩니다.
PEC가 지원되면 코어는 I2C 장치에 `pec` 속성을 추가하며, 이 속성으로 PMBus 칩과의 통신에서 PEC 사용 여부를 제어할 수 있습니다.
장치별 정보 전달과 전송 오류 검사를 정리합니다.
정적 기능과 콜백을 코어 초기화에 반영합니다.
PMBus driver information
------------------------
PMBus driver information, defined in struct pmbus_driver_info, is the main means
for device specific drivers to pass information to the core PMBus driver.
Specifically, it provides the following information.
- For devices supporting its data in Direct Data Format, it provides coefficients
for converting register values into normalized data. This data is usually
provided by chip manufacturers in device datasheets.
- Supported chip functionality can be provided to the core driver. This may be
necessary for chips which react badly if non-supported commands are executed,
and/or to speed up device detection and initialization.
- Several function entry points are provided to support overriding and/or
augmenting generic command execution. This functionality can be used to map
non-standard PMBus commands to standard commands, or to augment standard
command return values with device specific information.
PEC Support
===========
Many PMBus devices support SMBus PEC (Packet Error Checking). If supported
by both the I2C adapter and by the PMBus chip, it is by default enabled.
If PEC is supported, the PMBus core driver adds an attribute named 'pec' to
the I2C device. This attribute can be used to control PEC support in the
communication with the PMBus chip.
칩 드라이버 콜백과 폴백 규칙
133-203칩 드라이버 함수는 성공한 읽기에서 명령 반환값, 성공한 쓰기에서 0을 반환합니다. `-ENODATA`는 제조사 전용 명령은 없지만 표준 명령이 있을 수 있음을 뜻합니다. 그 밖의 음수는 이 칩에 명령 자체가 없으므로 표준 명령도 시도하지 말라는 뜻입니다.
가상 명령은 예외로 반드시 장치별 코드가 처리해야 합니다. 코어 실행 순서는 칩 접근 함수가 있으면 먼저 호출하고, 결과가 `-ENODATA`가 아니면 즉시 반환합니다. `-ENODATA`이면서 가상 명령이면 `-EINVAL`을 반환하고, 표준 명령일 때만 일반 접근으로 폴백합니다.
선택적 `read_byte_data(client, page, reg)`는 지정 페이지·레지스터의 바이트를 읽습니다. page `-1`은 현재 페이지를 뜻합니다.
선택적 `read_word_data(client, page, phase, reg)`는 페이지·위상·레지스터의 워드를 읽습니다. 다중 위상을 지원하지 않으면 phase를 무시하고, 지원하면 `0xff`가 모든 위상을 뜻합니다.
`write_word_data(client, page, reg, word)`는 지정 페이지 레지스터에 워드를 씁니다. `write_byte(client, page, value)`는 바이트 명령을 쓰며 page `-1`은 현재 페이지입니다.
`identify(client, info)`는 지원 PMBus 기능을 판별합니다. 여러 칩을 지원하고 기능이 미리 정해지지 않은 드라이버에만 필요하며 현재는 일반 `pmbus.c` 드라이버만 사용합니다.
각 함수의 페이지·위상·반환 계약입니다.
장치별 처리 결과로 일반 접근 여부를 결정합니다.
API functions
=============
Functions provided by chip driver
---------------------------------
All functions return the command return value (read) or zero (write) if
successful. A return value of -ENODATA indicates that there is no manufacturer
specific command, but that a standard PMBus command may exist. Any other
negative return value indicates that the commands does not exist for this
chip, and that no attempt should be made to read or write the standard
command.
As mentioned above, an exception to this rule applies to virtual commands,
which *must* be handled in driver specific code. See "Virtual PMBus Commands"
above for more details.
Command execution in the core PMBus driver code is as follows::
if (chip_access_function) {
status = chip_access_function();
if (status != -ENODATA)
return status;
}
if (command >= PMBUS_VIRT_BASE) /* For word commands/registers only */
return -EINVAL;
return generic_access();
Chip drivers may provide pointers to the following functions in struct
pmbus_driver_info. All functions are optional.
::
int (*read_byte_data)(struct i2c_client *client, int page, int reg);
Read byte from page <page>, register <reg>.
<page> may be -1, which means "current page".
::
int (*read_word_data)(struct i2c_client *client, int page, int phase,
int reg);
Read word from page <page>, phase <phase>, register <reg>. If the chip does not
support multiple phases, the phase parameter can be ignored. If the chip
supports multiple phases, a phase value of 0xff indicates all phases.
::
int (*write_word_data)(struct i2c_client *client, int page, int reg,
u16 word);
Write word to page <page>, register <reg>.
::
int (*write_byte)(struct i2c_client *client, int page, u8 value);
Write byte to page <page>, register <reg>.
<page> may be -1, which means "current page".
::
int (*identify)(struct i2c_client *client, struct pmbus_driver_info *info);
Determine supported PMBus functionality. This function is only necessary
if a chip driver supports multiple chips, and the chip functionality is not
pre-determined. It is currently only used by the generic pmbus driver
(pmbus.c).
코어가 내보내는 페이지 안전 API
204-296칩 드라이버는 PMBus 레지스터 읽기·쓰기에 코어가 내보낸 함수를 사용해야 하며 직접 I2C 명령도 사용할 수 있습니다. 직접 I2C를 쓰더라도 코어가 현재 페이지를 캐시하므로 페이지 레지스터를 직접 바꾸면 안 됩니다. 새 페이지는 반드시 `pmbus_set_page()`로 선택해야 합니다.
`pmbus_set_page(client, page, phase)`는 후속 명령용 페이지와 위상을 선택합니다. 다중 위상이 없으면 phase를 무시하고, 있으면 `0xff`가 모든 위상을 선택합니다.
`pmbus_read_word_data()`는 페이지와 위상을 먼저 고른 뒤 워드를 읽고, `pmbus_write_word_data()`는 페이지를 먼저 고른 뒤 워드를 씁니다. 각각 SMBus 워드 함수와 유사합니다.
`pmbus_read_byte_data()`와 `pmbus_write_byte()`도 페이지를 먼저 선택하는 바이트 접근 함수이며 page `-1`은 현재 페이지입니다.
`pmbus_clear_faults()`는 모든 칩 페이지에 Clear Fault 명령을 실행하고 장치별 `write_byte`가 있으면 호출합니다. 따라서 `write_byte` 콜백 내부에서 이 함수를 호출하면 안 됩니다.
`pmbus_check_byte_register()`와 `pmbus_check_word_register()`는 레지스터 존재 여부를 bool로 반환합니다. 상태를 얻기 위해 장치별 `write_byte`를 호출할 수 있으므로 역시 그 콜백 내부에서 호출하면 안 됩니다.
`pmbus_do_probe(client, info)`는 일반 probe와 비슷하지만 `pmbus_driver_info` 포인터를 추가로 받고 지원되면 identify를 호출합니다. 장치 probe 함수에서만 호출해야 합니다.
`pmbus_get_driver_info(client)`는 `pmbus_do_probe()`에 전달했던 `pmbus_driver_info` 포인터를 반환합니다.
페이지 캐시와 재귀 호출 금지 조건을 강조합니다.
코어 캐시와 실제 칩 페이지를 항상 일치시킵니다.
Functions exported by core driver
---------------------------------
Chip drivers are expected to use the following functions to read or write
PMBus registers. Chip drivers may also use direct I2C commands. If direct I2C
commands are used, the chip driver code must not directly modify the current
page, since the selected page is cached in the core driver and the core driver
will assume that it is selected. Using pmbus_set_page() to select a new page
is mandatory.
::
int pmbus_set_page(struct i2c_client *client, u8 page, u8 phase);
Set PMBus page register to <page> and <phase> for subsequent commands.
If the chip does not support multiple phases, the phase parameter is
ignored. Otherwise, a phase value of 0xff selects all phases.
::
int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 phase,
u8 reg);
Read word data from <page>, <phase>, <reg>. Similar to
i2c_smbus_read_word_data(), but selects page and phase first. If the chip does
not support multiple phases, the phase parameter is ignored. Otherwise, a phase
value of 0xff selects all phases.
::
int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg,
u16 word);
Write word data to <page>, <reg>. Similar to i2c_smbus_write_word_data(), but
selects page first.
::
int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
Read byte data from <page>, <reg>. Similar to i2c_smbus_read_byte_data(), but
selects page first. <page> may be -1, which means "current page".
::
int pmbus_write_byte(struct i2c_client *client, int page, u8 value);
Write byte data to <page>, <reg>. Similar to i2c_smbus_write_byte(), but
selects page first. <page> may be -1, which means "current page".
::
void pmbus_clear_faults(struct i2c_client *client);
Execute PMBus "Clear Fault" command on all chip pages.
This function calls the device specific write_byte function if defined.
Therefore, it must _not_ be called from that function.
::
bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
Check if byte register exists. Return true if the register exists, false
otherwise.
This function calls the device specific write_byte function if defined to
obtain the chip status. Therefore, it must _not_ be called from that function.
::
bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
Check if word register exists. Return true if the register exists, false
otherwise.
This function calls the device specific write_byte function if defined to
obtain the chip status. Therefore, it must _not_ be called from that function.
::
int pmbus_do_probe(struct i2c_client *client, struct pmbus_driver_info *info);
Execute probe function. Similar to standard probe function for other drivers,
with the pointer to struct pmbus_driver_info as additional argument. Calls
identify function if supported. Must only be called from device probe
function.
::
const struct pmbus_driver_info
*pmbus_get_driver_info(struct i2c_client *client);
Return pointer to struct pmbus_driver_info as passed to pmbus_do_probe().
플랫폼 데이터와 장치별 플래그
297-390PMBus 플랫폼 데이터는 `include/linux/pmbus.h`의 `struct pmbus_platform_data`에 정의됩니다. `flags`와 레귤레이터 수·초기화 데이터가 있으며 원문은 현재 사용하는 비트를 열거합니다.
`PMBUS_SKIP_STATUS_CHECK`는 레지스터 감지 중 통신·명령 오류를 위한 상태 레지스터 확인을 생략합니다. 미지원 레지스터에서도 유효해 보이는 데이터를 반환하는 칩은 상태 확인이 필수지만, `STATUS_CML`을 지원하지 않거나 이유 없이 통신 오류를 내는 칩은 확인을 꺼야 합니다.
데이터 없는 단일 바이트 쓰기인 `i2c_smbus_write_byte()`를 지원하지 않는 I2C 컨트롤러는 상태 레지스터를 지울 수 없으므로 반드시 `PMBUS_SKIP_STATUS_CHECK`를 설정해야 합니다.
`PMBUS_WRITE_PROTECTED`는 표준 `WRITE_PROTECT` 명령으로 판별되지 않는 쓰기 보호 칩에 사용합니다. `PMBUS_NO_CAPABILITY`는 `CAPABILITY` 읽기가 유효하지 않아 코어가 그 값을 동작 판정에 사용하지 않게 합니다.
`PMBUS_READ_STATUS_AFTER_FAILED_CHECK`는 실패한 레지스터 검사마다 `STATUS`를 읽습니다. 미지원 레지스터 접근 뒤 정의되지 않은 상태가 되는 칩을 알려진 상태로 되돌리며, STATUS 읽기 자체가 실패해도 복구 효과를 낼 수 있습니다.
`PMBUS_NO_WRITE_PROTECT`는 `WRITE_PROTECT` 레지스터가 무효 데이터를 반환하는 칩에서 그 명령을 판정에 사용하지 않게 합니다.
`PMBUS_USE_COEFFICIENTS_CMD`는 Direct 모드 계수를 `COEFFICIENTS` 레지스터로 초기화합니다.
`PMBUS_OP_PROTECTED`는 표준 `WRITE_PROTECT`로 판별되지 않는 `OPERATION` 명령 보호를, `PMBUS_VOUT_PROTECTED`는 같은 조건의 `VOUT_COMMAND` 보호를 나타냅니다.
비트와 적용 조건을 빠짐없이 정리합니다.
칩과 I2C 컨트롤러의 비표준 반응을 코어에 알립니다.
PMBus driver platform data
==========================
PMBus platform data is defined in include/linux/pmbus.h. Platform data
currently provides a flags field with four bits used::
#define PMBUS_SKIP_STATUS_CHECK BIT(0)
#define PMBUS_WRITE_PROTECTED BIT(1)
#define PMBUS_NO_CAPABILITY BIT(2)
#define PMBUS_READ_STATUS_AFTER_FAILED_CHECK BIT(3)
#define PMBUS_NO_WRITE_PROTECT BIT(4)
#define PMBUS_USE_COEFFICIENTS_CMD BIT(5)
#define PMBUS_OP_PROTECTED BIT(6)
#define PMBUS_VOUT_PROTECTED BIT(7)
struct pmbus_platform_data {
u32 flags; /* Device specific flags */
/* regulator support */
int num_regulators;
struct regulator_init_data *reg_init_data;
};
Flags
-----
PMBUS_SKIP_STATUS_CHECK
During register detection, skip checking the status register for
communication or command errors.
Some PMBus chips respond with valid data when trying to read an unsupported
register. For such chips, checking the status register is mandatory when
trying to determine if a chip register exists or not.
Other PMBus chips don't support the STATUS_CML register, or report
communication errors for no explicable reason. For such chips, checking the
status register must be disabled.
Some i2c controllers do not support single-byte commands (write commands with
no data, i2c_smbus_write_byte()). With such controllers, clearing the status
register is impossible, and the PMBUS_SKIP_STATUS_CHECK flag must be set.
PMBUS_WRITE_PROTECTED
Set if the chip is write protected and write protection is not determined
by the standard WRITE_PROTECT command.
PMBUS_NO_CAPABILITY
Some PMBus chips don't respond with valid data when reading the CAPABILITY
register. For such chips, this flag should be set so that the PMBus core
driver doesn't use CAPABILITY to determine its behavior.
PMBUS_READ_STATUS_AFTER_FAILED_CHECK
Read the STATUS register after each failed register check.
Some PMBus chips end up in an undefined state when trying to read an
unsupported register. For such chips, it is necessary to reset the
chip pmbus controller to a known state after a failed register check.
This can be done by reading a known register. By setting this flag the
driver will try to read the STATUS register after each failed
register check. This read may fail, but it will put the chip into a
known state.
PMBUS_NO_WRITE_PROTECT
Some PMBus chips respond with invalid data when reading the WRITE_PROTECT
register. For such chips, this flag should be set so that the PMBus core
driver doesn't use the WRITE_PROTECT command to determine its behavior.
PMBUS_USE_COEFFICIENTS_CMD
When this flag is set the PMBus core driver will use the COEFFICIENTS
register to initialize the coefficients for the direct mode format.
PMBUS_OP_PROTECTED
Set if the chip OPERATION command is protected and protection is not
determined by the standard WRITE_PROTECT command.
PMBUS_VOUT_PROTECTED
Set if the chip VOUT_COMMAND command is protected and protection is not
determined by the standard WRITE_PROTECT command.
pmbus_core.wp 강제 쓰기 보호
391-410PMBus 장치는 여러 쓰기 보호 구성으로 시작할 수 있습니다. 특정 보호 수준이 필요하면 모듈 매개변수 `pmbus_core.wp`를 사용할 수 있습니다.
실제로 보호를 바꿀 수 있는지는 칩에 따라 달라서 실행 중 보호 상태가 요청과 다를 수 있습니다.
값 0은 쓰기 보호를 제거합니다. 값 1은 `WRITE_PROTECT`, `OPERATION`, `PAGE`, `ON_OFF_CONFIG`, `VOUT_COMMAND`를 제외한 모든 쓰기를 막습니다.
값 2는 `WRITE_PROTECT`, `OPERATION`, `PAGE`를 제외한 쓰기를 막고, 값 3은 `WRITE_PROTECT` 이외의 모든 쓰기를 막습니다.
수준 3 보호에는 PAGE 레지스터도 포함되어야 합니다. PMBus 규격을 엄격히 따르는 다중 페이지 칩에서는 활성 페이지 변경을 막아 문제가 될 수 있습니다.
허용되는 명령과 다중 페이지 위험입니다.
요청 수준과 실제 칩 상태의 차이를 확인합니다.
Module parameter
----------------
pmbus_core.wp: PMBus write protect forced mode
PMBus may come up with a variety of write protection configuration.
'pmbus_core.wp' may be used if a particular write protection is necessary.
The ability to actually alter the protection may also depend on the chip
so the actual runtime write protection configuration may differ from
the requested one. pmbus_core currently support the following value:
* 0: write protection removed.
* 1: Disable all writes except to the WRITE_PROTECT, OPERATION,
PAGE, ON_OFF_CONFIG and VOUT_COMMAND commands.
* 2: Disable all writes except to the WRITE_PROTECT, OPERATION and
PAGE commands.
* 3: Disable all writes except to the WRITE_PROTECT command. Note that
protection should include the PAGE register. This may be problematic
for multi-page chips, if the chips strictly follows the PMBus
specification, preventing the chip from changing the active page.
요약·해설
pmbus-core.rst:1-410미지원 명령 반응이 제각각인 PMBus 장치를 코어·일반·장치별 계층으로 처리하고 페이지 캐시와 오류 폴백, 8개 플래그를 정의합니다.
원문 분량과 핵심 장치 구성을 정리합니다.
장치 인식부터 측정·제어까지의 핵심 순서입니다.