요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
* Marvell MBus
Required properties:
- compatible: Should be set to one of the following:
marvell,armada370-mbus
marvell,armadaxp-mbus
marvell,armada375-mbus
marvell,armada380-mbus
marvell,kirkwood-mbus
marvell,dove-mbus
marvell,orion5x-88f5281-mbus
marvell,orion5x-88f5182-mbus
marvell,orion5x-88f5181-mbus
marvell,orion5x-88f6183-mbus
marvell,mv78xx0-mbus
- address-cells: Must be '2'. The first cell for the MBus ID encoding,
the second cell for the address offset within the window.
- size-cells: Must be '1'.
- ranges: Must be set up to provide a proper translation for each child.
See the examples below.
- controller: Contains a single phandle referring to the MBus controller
node. This allows to specify the node that contains the
registers that control the MBus, which is typically contained
within the internal register window (see below).
Optional properties:
- pcie-mem-aperture: This optional property contains the aperture for
the memory region of the PCIe driver.
If it's defined, it must encode the base address and
size for the address decoding windows allocated for
the PCIe memory region.
- pcie-io-aperture: Just as explained for the above property, this
optional property contains the aperture for the
I/O region of the PCIe driver.
* Marvell MBus controller
Required properties:
- compatible: Should be set to "marvell,mbus-controller".
- reg: Device's register space.
Two or three entries are expected (see the examples below):
the first one controls the devices decoding window,
the second one controls the SDRAM decoding window and
the third controls the MBus bridge (only with the
marvell,armada370-mbus and marvell,armadaxp-mbus
compatible strings)
Example:
soc {
compatible = "marvell,armada370-mbus", "simple-bus";
#address-cells = <2>;
#size-cells = <1>;
controller = <&mbusc>;
pcie-mem-aperture = <0xe0000000 0x8000000>;
pcie-io-aperture = <0xe8000000 0x100000>;
internal-regs {
compatible = "simple-bus";
mbusc: mbus-controller@20000 {
compatible = "marvell,mbus-controller";
reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
};
/* more children ...*/
};
};
** MBus address decoding window specification
The MBus children address space is comprised of two cells: the first one for
the window ID and the second one for the offset within the window.
In order to allow to describe valid and non-valid window entries, the
following encoding is used:
0xSIAA0000 0x00oooooo
Where:
S = 0x0 for a MBus valid window
S = 0xf for a non-valid window (see below)
If S = 0x0, then:
I = 4-bit window target ID
AA = windpw attribute
If S = 0xf, then:
I = don't care
AA = 1 for internal register
Following the above encoding, for each ranges entry for a MBus valid window
(S = 0x0), an address decoding window is allocated. On the other side,
entries for translation that do not correspond to valid windows (S = 0xf)
are skipped.
soc {
compatible = "marvell,armada370-mbus", "simple-bus";
#address-cells = <2>;
#size-cells = <1>;
controller = <&mbusc>;
ranges = <0xf0010000 0 0 0xd0000000 0x100000
0x01e00000 0 0 0xfff00000 0x100000>;
bootrom {
compatible = "marvell,bootrom";
reg = <0x01e00000 0 0x100000>;
};
/* other children */
...
internal-regs {
compatible = "simple-bus";
ranges = <0 0xf0010000 0 0x100000>;
mbusc: mbus-controller@20000 {
compatible = "marvell,mbus-controller";
reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
};
/* more children ...*/
};
};
In the shown example, the translation entry in the 'ranges' property is what
makes the MBus driver create a static decoding window for the corresponding
given child device. Note that the binding does not require child nodes to be
present. Of course, child nodes are needed to probe the devices.
Since each window is identified by its target ID and attribute ID there's
a special macro that can be use to simplify the translation entries:
#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
Using this macro, the above example would be:
soc {
compatible = "marvell,armada370-mbus", "simple-bus";
#address-cells = <2>;
#size-cells = <1>;
controller = <&mbusc>;
ranges = < MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000
MBUS_ID(0x01, 0xe0) 0 0 0xfff00000 0x100000>;
bootrom {
compatible = "marvell,bootrom";
reg = <MBUS_ID(0x01, 0xe0) 0 0x100000>;
};
/* other children */
...
internal-regs {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
mbusc: mbus-controller@20000 {
compatible = "marvell,mbus-controller";
reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
};
/* other children */
...
};
};
** About the window base address
Remember the MBus controller allows a great deal of flexibility for choosing
the decoding window base address. When planning the device tree layout it's
possible to choose any address as the base address, provided of course there's
a region large enough available, and with the required alignment.
Yet in other words: there's nothing preventing us from setting a base address
of 0xf0000000, or 0xd0000000 for the NOR device shown above, if such region is
unused.
** Window allocation policy
The mbus-node ranges property defines a set of mbus windows that are expected
to be set by the operating system and that are guaranteed to be free of overlaps
with one another or with the system memory ranges.
Each entry in the property refers to exactly one window. If the operating system
chooses to use a different set of mbus windows, it must ensure that any address
translations performed from downstream devices are adapted accordingly.
The operating system may insert additional mbus windows that do not conflict
with the ones listed in the ranges, e.g. for mapping PCIe devices.
As a special case, the internal register window must be set up by the boot
loader at the address listed in the ranges property, since access to that region
is needed to set up the other windows.
** Example
See the example below, where a more complete device tree is shown:
soc {
compatible = "marvell,armadaxp-mbus", "simple-bus";
controller = <&mbusc>;
ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000 /* internal-regs */
MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x8000000>;
bootrom {
compatible = "marvell,bootrom";
reg = <MBUS_ID(0x01, 0x1d) 0 0x100000>;
};
devbus-bootcs {
ranges = <0 MBUS_ID(0x01, 0x2f) 0 0x8000000>;
/* NOR */
nor {
compatible = "cfi-flash";
reg = <0 0x8000000>;
bank-width = <2>;
};
};
pcie-controller {
compatible = "marvell,armada-xp-pcie";
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
ranges =
<0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000 /* Port 0.0 registers */
0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000 /* Port 2.0 registers */
0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000 /* Port 0.1 registers */
0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000 /* Port 0.2 registers */
0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000 /* Port 0.3 registers */
0x82000800 0 0xe0000000 MBUS_ID(0x04, 0xe8) 0xe0000000 0 0x08000000 /* Port 0.0 MEM */
0x81000800 0 0 MBUS_ID(0x04, 0xe0) 0xe8000000 0 0x00100000 /* Port 0.0 IO */>;
pcie@1,0 {
/* Port 0, Lane 0 */
};
};
internal-regs {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
mbusc: mbus-controller@20000 {
reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
};
interrupt-controller@20000 {
reg = <0x20a00 0x2d0>, <0x21070 0x58>;
};
};
};
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Marvell MBus 필수 및 선택 속성
1-43Marvell MBus
필수 `compatible`은 `marvell,armada370-mbus`, `marvell,armadaxp-mbus`, `marvell,armada375-mbus`, `marvell,armada380-mbus`, `marvell,kirkwood-mbus`, `marvell,dove-mbus` 중 하나일 수 있습니다.
또한 `marvell,orion5x-88f5281-mbus`, `marvell,orion5x-88f5182-mbus`, `marvell,orion5x-88f5181-mbus`, `marvell,orion5x-88f6183-mbus`, `marvell,mv78xx0-mbus` 중 하나일 수 있습니다.
`#address-cells`는 2여야 합니다. 첫 번째 cell은 MBus ID encoding, 두 번째 cell은 window 안의 address offset입니다. `#size-cells`는 1이어야 합니다.
`ranges`는 각 child에 올바른 주소 변환을 제공하도록 구성해야 합니다. `controller`에는 MBus controller 노드를 가리키는 하나의 phandle을 넣습니다. 이 노드는 MBus 제어 레지스터를 포함하며 일반적으로 아래에서 설명하는 internal register window 안에 있습니다.
선택적 `pcie-mem-aperture`는 PCIe driver의 memory region aperture를 담습니다. 정의하는 경우 PCIe memory 영역에 할당되는 address decoding window의 base address와 size를 encoding해야 합니다.
선택적 `pcie-io-aperture`는 같은 방식으로 PCIe driver I/O region의 aperture를 담습니다.
두 cell child 주소와 ranges가 MBus decoding window를 만드는 관계입니다.
MBus controller와 레지스터 영역
44-79Marvell MBus controller
필수 `compatible`은 `marvell,mbus-controller`입니다. `reg`에는 장치 레지스터 공간을 지정하며 두 개 또는 세 개의 entry가 필요합니다.
첫 번째 entry는 device decoding window, 두 번째는 SDRAM decoding window를 제어합니다. 세 번째는 MBus bridge를 제어하며 `marvell,armada370-mbus`와 `marvell,armadaxp-mbus`에서만 사용합니다.
레지스터 영역의 순서와 역할입니다.
다음 예제는 MBus SoC 노드, PCIe memory/I/O aperture와 internal register window 안의 controller를 보여 줍니다.
soc {
compatible = "marvell,armada370-mbus", "simple-bus";
#address-cells = <2>;
#size-cells = <1>;
controller = <&mbusc>;
pcie-mem-aperture = <0xe0000000 0x8000000>;
pcie-io-aperture = <0xe8000000 0x100000>;
internal-regs {
compatible = "simple-bus";
mbusc: mbus-controller@20000 {
compatible = "marvell,mbus-controller";
reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
};
/* more children ...*/
};
};
MBus address decoding window encoding
80-108MBus child 주소 공간은 window ID와 window 내부 offset을 나타내는 두 cell로 구성됩니다. 유효한 window와 유효하지 않은 window entry를 모두 기술하기 위해 다음 encoding을 사용합니다.
0xSIAA0000 0x00oooooo
Where:
S = 0x0 for a MBus valid window
S = 0xf for a non-valid window (see below)
If S = 0x0, then:
I = 4-bit window target ID
AA = windpw attribute
If S = 0xf, then:
I = don't care
AA = 1 for internal register
`S = 0x0`이면 유효한 MBus window이며 `I`는 4-bit window target ID, `AA`는 window attribute입니다. `S = 0xf`이면 유효하지 않은 window이며 `I`는 무관하고 `AA = 1`은 internal register를 나타냅니다.
따라서 `ranges`의 유효한 MBus window entry마다 address decoding window가 하나씩 할당됩니다. 유효한 window에 해당하지 않는 `S = 0xf` 변환 entry는 건너뜁니다.
`0xSIAA0000 0x00oooooo`의 bit field 의미를 구조화해 표시합니다.
ranges와 정적 decoding window 예
109-143다음 예제의 `ranges` 변환 entry는 MBus driver가 해당 child device를 위한 정적 decoding window를 만들도록 합니다. 바인딩 자체는 child node를 요구하지 않지만 장치를 probe하려면 child node가 필요합니다.
soc {
compatible = "marvell,armada370-mbus", "simple-bus";
#address-cells = <2>;
#size-cells = <1>;
controller = <&mbusc>;
ranges = <0xf0010000 0 0 0xd0000000 0x100000
0x01e00000 0 0 0xfff00000 0x100000>;
bootrom {
compatible = "marvell,bootrom";
reg = <0x01e00000 0 0x100000>;
};
/* other children */
...
internal-regs {
compatible = "simple-bus";
ranges = <0 0xf0010000 0 0x100000>;
mbusc: mbus-controller@20000 {
compatible = "marvell,mbus-controller";
reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
};
/* more children ...*/
};
};
첫 번째 entry의 `S = 0xf` internal register 변환은 decoding window 할당에서 건너뛰고, `bootrom`에 해당하는 유효 entry는 정적 window를 만듭니다.
MBUS_ID macro를 사용한 변환
144-184각 window는 target ID와 attribute ID로 식별되므로 변환 entry를 단순화하는 특별한 macro를 사용할 수 있습니다.
#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
이 macro를 사용하면 앞의 raw ID encoding 예제를 다음과 같이 표현할 수 있습니다.
soc {
compatible = "marvell,armada370-mbus", "simple-bus";
#address-cells = <2>;
#size-cells = <1>;
controller = <&mbusc>;
ranges = < MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000
MBUS_ID(0x01, 0xe0) 0 0 0xfff00000 0x100000>;
bootrom {
compatible = "marvell,bootrom";
reg = <MBUS_ID(0x01, 0xe0) 0 0x100000>;
};
/* other children */
...
internal-regs {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
mbusc: mbus-controller@20000 {
compatible = "marvell,mbus-controller";
reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
};
/* other children */
...
};
};
Window base address와 할당 정책
185-211MBus controller는 decoding window base address 선택에 큰 유연성을 제공합니다. 충분히 큰 빈 영역이 있고 필요한 alignment를 만족한다면 Device Tree를 구성할 때 어떤 주소든 base address로 선택할 수 있습니다.
따라서 해당 영역이 사용되지 않는다면 앞의 NOR 장치 base address를 `0xf0000000`이나 `0xd0000000`으로 설정하는 것을 막는 제약은 없습니다.
MBus 노드의 `ranges` 속성은 운영체제가 설정할 MBus window 집합을 정의합니다. 이 window들은 서로 겹치지 않고 system memory range와도 겹치지 않음이 보장되어야 합니다.
각 entry는 정확히 하나의 window를 나타냅니다. 운영체제가 다른 MBus window 집합을 사용한다면 downstream device가 수행하는 모든 주소 변환도 그에 맞게 조정해야 합니다.
운영체제는 PCIe 장치 매핑처럼 `ranges`에 나열된 window와 충돌하지 않는 추가 MBus window를 넣을 수 있습니다.
특별한 경우로 internal register window는 다른 window를 설정할 때 접근해야 하므로 boot loader가 `ranges`에 지정된 주소에 미리 설정해야 합니다.
Boot loader와 운영체제가 decoding window를 준비하는 순서입니다.
Armada XP MBus 전체 예
212-276다음의 더 완전한 예제는 internal register, boot ROM, NOR flash 및 PCIe controller의 register/MEM/I/O 범위를 하나의 Armada XP MBus 주소 체계에 연결합니다.
soc {
compatible = "marvell,armadaxp-mbus", "simple-bus";
controller = <&mbusc>;
ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000 /* internal-regs */
MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x8000000>;
bootrom {
compatible = "marvell,bootrom";
reg = <MBUS_ID(0x01, 0x1d) 0 0x100000>;
};
devbus-bootcs {
ranges = <0 MBUS_ID(0x01, 0x2f) 0 0x8000000>;
/* NOR */
nor {
compatible = "cfi-flash";
reg = <0 0x8000000>;
bank-width = <2>;
};
};
pcie-controller {
compatible = "marvell,armada-xp-pcie";
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
ranges =
<0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000 /* Port 0.0 registers */
0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000 /* Port 2.0 registers */
0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000 /* Port 0.1 registers */
0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000 /* Port 0.2 registers */
0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000 /* Port 0.3 registers */
0x82000800 0 0xe0000000 MBUS_ID(0x04, 0xe8) 0xe0000000 0 0x08000000 /* Port 0.0 MEM */
0x81000800 0 0 MBUS_ID(0x04, 0xe0) 0xe8000000 0 0x00100000 /* Port 0.0 IO */>;
pcie@1,0 {
/* Port 0, Lane 0 */
};
};
internal-regs {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
mbusc: mbus-controller@20000 {
reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
};
interrupt-controller@20000 {
reg = <0x20a00 0x2d0>, <0x21070 0x58>;
};
};
};
완전한 예제의 주요 child와 각 MBus window 용도를 요약합니다.
요약과 해설
mvebu-mbus.txt:1-276MBus ID encoding, ranges 변환, window base와 할당 정책 및 Boot ROM/NOR/PCIe 통합 예제를 설명합니다.