← Documents Documentation/misc-devices/spear-pcie-gadget.rst GitHub 원문 ↗

Linux 6.18.37 · Misc devices

SPEAr PCIe Gadget Driver

SPEAr13xx dual-mode PCIe controller를 configfs로 endpoint device로 만들고 BAR0·INTA·MSI를 설정하는 절차입니다.

Source pathDocumentation/misc-devices/spear-pcie-gadget.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

spear-pcie-gadget.rst:1-170

Configfs node로 identity와 BAR0 mapping을 먼저 programming한 뒤 interrupt mode를 선택하고 link를 올립니다. Host enumeration은 gadget의 link가 UP인 뒤 시작해야 합니다.

1MB RAM endpoint 구성
vendor_id·device_idbar0_size=0x100000bar0_address=0x2100000read-back 확인int_typelink=UP

BAR size를 address보다 먼저 설정하고 실제 적용 값을 다시 읽어 alignment 변경을 확인합니다.

MSI 전송
no_of_msi=4int_type=MSIlink=UP 대기no_of_msi=4 확인send_msi=2

MSI vector 수를 먼저 요청한 뒤 mode와 link를 설정합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 ========================
4 Spear PCIe Gadget Driver
5 ========================
6
7 Author
8 ======
9 Pratyush Anand (pratyush.anand@gmail.com)
10
11 Location
12 ========
13 driver/misc/spear13xx_pcie_gadget.c
14
15 Supported Chip:
16 ===============
17 SPEAr1300
18 SPEAr1310
19
20 Menuconfig option:
21 ==================
22 Device Drivers
23 Misc devices
24 PCIe gadget support for SPEAr13XX platform
25
26 purpose
27 =======
28 This driver has several nodes which can be read/written by configfs interface.
29 Its main purpose is to configure selected dual mode PCIe controller as device
30 and then program its various registers to configure it as a particular device
31 type. This driver can be used to show spear's PCIe device capability.
32
33 Description of different nodes:
34 ===============================
35
36 read behavior of nodes:
37 -----------------------
38
39 =============== ==============================================================
40 link gives ltssm status.
41 int_type type of supported interrupt
42 no_of_msi zero if MSI is not enabled by host. A positive value is the
43 number of MSI vector granted.
44 vendor_id returns programmed vendor id (hex)
45 device_id returns programmed device id(hex)
46 bar0_size: returns size of bar0 in hex.
47 bar0_address returns address of bar0 mapped area in hex.
48 bar0_rw_offset returns offset of bar0 for which bar0_data will return value.
49 bar0_data returns data at bar0_rw_offset.
50 =============== ==============================================================
51
52 write behavior of nodes:
53 ------------------------
54
55 =============== ================================================================
56 link write UP to enable ltsmm DOWN to disable
57 int_type write interrupt type to be configured and (int_type could be
58 INTA, MSI or NO_INT). Select MSI only when you have programmed
59 no_of_msi node.
60 no_of_msi number of MSI vector needed.
61 inta write 1 to assert INTA and 0 to de-assert.
62 send_msi write MSI vector to be sent.
63 vendor_id write vendor id(hex) to be programmed.
64 device_id write device id(hex) to be programmed.
65 bar0_size write size of bar0 in hex. default bar0 size is 1000 (hex)
66 bytes.
67 bar0_address write address of bar0 mapped area in hex. (default mapping of
68 bar0 is SYSRAM1(E0800000). Always program bar size before bar
69 address. Kernel might modify bar size and address for alignment,
70 so read back bar size and address after writing to cross check.
71 bar0_rw_offset write offset of bar0 for which bar0_data will write value.
72 bar0_data write data to be written at bar0_rw_offset.
73 =============== ================================================================
74
75 Node programming example
76 ========================
77
78 Program all PCIe registers in such a way that when this device is connected
79 to the PCIe host, then host sees this device as 1MB RAM.
80
81 ::
82
83 #mount -t configfs none /Config
84
85 For nth PCIe Device Controller::
86
87 # cd /config/pcie_gadget.n/
88
89 Now you have all the nodes in this directory.
90 program vendor id as 0x104a::
91
92 # echo 104A >> vendor_id
93
94 program device id as 0xCD80::
95
96 # echo CD80 >> device_id
97
98 program BAR0 size as 1MB::
99
100 # echo 100000 >> bar0_size
101
102 check for programmed bar0 size::
103
104 # cat bar0_size
105
106 Program BAR0 Address as DDR (0x2100000). This is the physical address of
107 memory, which is to be made visible to PCIe host. Similarly any other peripheral
108 can also be made visible to PCIe host. E.g., if you program base address of UART
109 as BAR0 address then when this device will be connected to a host, it will be
110 visible as UART.
111
112 ::
113
114 # echo 2100000 >> bar0_address
115
116 program interrupt type : INTA::
117
118 # echo INTA >> int_type
119
120 go for link up now::
121
122 # echo UP >> link
123
124 It will have to be insured that, once link up is done on gadget, then only host
125 is initialized and start to search PCIe devices on its port.
126
127 ::
128
129 /*wait till link is up*/
130 # cat link
131
132 Wait till it returns UP.
133
134 To assert INTA::
135
136 # echo 1 >> inta
137
138 To de-assert INTA::
139
140 # echo 0 >> inta
141
142 if MSI is to be used as interrupt, program no of msi vector needed (say4)::
143
144 # echo 4 >> no_of_msi
145
146 select MSI as interrupt type::
147
148 # echo MSI >> int_type
149
150 go for link up now::
151
152 # echo UP >> link
153
154 wait till link is up::
155
156 # cat link
157
158 An application can repetitively read this node till link is found UP. It can
159 sleep between two read.
160
161 wait till msi is enabled::
162
163 # cat no_of_msi
164
165 Should return 4 (number of requested MSI vector)
166
167 to send msi vector 2::
168
169 # echo 2 >> send_msi
170 # cd -
171

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

저자·source·지원 chip

1-25

SPEAr PCIe Gadget driver의 저자는 Pratyush Anand <pratyush.anand@gmail.com>입니다. 원문에 표시된 source 위치는 `driver/misc/spear13xx_pcie_gadget.c`이며 SPEAr1300과 SPEAr1310을 지원합니다.

Menuconfig에서는 `Device Drivers` → `Misc devices` → `PCIe gadget support for SPEAr13XX platform` 경로로 선택합니다.

.. SPDX-License-Identifier: GPL-2.0

========================
Spear PCIe Gadget Driver
========================

Author
======
Pratyush Anand (pratyush.anand@gmail.com)

Location
========
driver/misc/spear13xx_pcie_gadget.c

Supported Chip:
===============
SPEAr1300
SPEAr1310

Menuconfig option:
==================
Device Drivers
        Misc devices
                PCIe gadget support for SPEAr13XX platform

Driver 목적

26-32

이 driver는 configfs interface로 읽고 쓸 수 있는 여러 node를 제공합니다. 선택한 dual-mode PCIe controller를 device mode로 구성한 뒤 여러 register를 programming해 특정 device type으로 만드는 것이 주 목적입니다. 이를 통해 SPEAr의 PCIe device capability를 보여줄 수 있습니다.

purpose
=======
This driver has several nodes which can be read/written by configfs interface.
Its main purpose is to configure selected dual mode PCIe controller as device
and then program its various registers to configure it as a particular device
type. This driver can be used to show spear's PCIe device capability.

Node 읽기 동작

33-50
Node읽기 결과
`link`LTSSM status
`int_type`지원하는 interrupt type
`no_of_msi`Host가 MSI를 enable하지 않았으면 0, enable했다면 grant된 MSI vector 수
`vendor_id`Programming된 vendor ID, hex
`device_id`Programming된 device ID, hex
`bar0_size`BAR0 size, hex
`bar0_address`BAR0 mapping 영역의 address, hex
`bar0_rw_offset``bar0_data`가 읽을 BAR0 offset
`bar0_data``bar0_rw_offset` 위치의 data
Description of different nodes:
===============================

read behavior of nodes:
-----------------------

=============== ==============================================================
link                 gives ltssm status.
int_type         type of supported interrupt
no_of_msi         zero if MSI is not enabled by host. A positive value is the
                number of MSI vector granted.
vendor_id        returns programmed vendor id (hex)
device_id        returns programmed device id(hex)
bar0_size:        returns size of bar0 in hex.
bar0_address        returns address of bar0 mapped area in hex.
bar0_rw_offset        returns offset of bar0 for which bar0_data will return value.
bar0_data        returns data at bar0_rw_offset.
=============== ==============================================================

Node 쓰기 동작

51-73
Node쓰기 동작
`link``UP`은 LTSSM enable, `DOWN`은 disable
`int_type``INTA`, `MSI`, `NO_INT` 중 하나를 설정하며 MSI는 `no_of_msi`를 먼저 programming한 경우에만 선택
`no_of_msi`필요한 MSI vector 수
`inta`1은 INTA assert, 0은 de-assert
`send_msi`전송할 MSI vector
`vendor_id`Programming할 vendor ID, hex
`device_id`Programming할 device ID, hex
`bar0_size`BAR0 size, hex. 기본값은 0x1000 byte
`bar0_address`BAR0 mapping 물리 주소, hex. 기본은 SYSRAM1(0xE0800000)이며 size를 먼저 써야 함
`bar0_rw_offset``bar0_data`가 쓸 BAR0 offset
`bar0_data``bar0_rw_offset`에 쓸 data

Kernel이 alignment를 위해 BAR size와 address를 변경할 수 있으므로 `bar0_address`를 쓴 뒤 size와 address를 다시 읽어 확인해야 합니다.


write behavior of nodes:
------------------------

=============== ================================================================
link                 write UP to enable ltsmm DOWN to disable
int_type        write interrupt type to be configured and (int_type could be
                INTA, MSI or NO_INT). Select MSI only when you have programmed
                no_of_msi node.
no_of_msi        number of MSI vector needed.
inta                write 1 to assert INTA and 0 to de-assert.
send_msi        write MSI vector to be sent.
vendor_id        write vendor id(hex) to be programmed.
device_id        write device id(hex) to be programmed.
bar0_size        write size of bar0 in hex. default bar0 size is 1000 (hex)
                bytes.
bar0_address        write        address of bar0 mapped area in hex. (default mapping of
                bar0 is SYSRAM1(E0800000). Always program bar size before bar
                address. Kernel might modify bar size and address for alignment,
                so read back bar size and address after writing to cross check.
bar0_rw_offset        write offset of bar0 for which        bar0_data will write value.
bar0_data        write data to be written at bar0_rw_offset.
=============== ================================================================

1MB RAM endpoint 구성

74-110

예제는 PCIe host가 gadget을 1MB RAM으로 보도록 register를 programming합니다. 먼저 configfs를 `/Config`에 mount하고 n번째 controller의 `/config/pcie_gadget.n/`으로 이동합니다.

# mount -t configfs none /Config
# cd /config/pcie_gadget.n/
# echo 104A >> vendor_id
# echo CD80 >> device_id
# echo 100000 >> bar0_size
# cat bar0_size

BAR0 address에는 host에 보이게 할 memory의 physical address를 씁니다. 예제는 DDR `0x2100000`을 사용합니다. 다른 peripheral의 base address도 노출할 수 있으며, UART base를 쓰면 host에서 UART로 보입니다.

# echo 2100000 >> bar0_address

Node programming example
========================

Program all PCIe registers in such a way that when this device is connected
to the PCIe host, then host sees this device as 1MB RAM.

::

    #mount -t configfs none /Config

For nth PCIe Device Controller::

    # cd /config/pcie_gadget.n/

Now you have all the nodes in this directory.
program vendor id as 0x104a::

    # echo 104A >> vendor_id

program device id as 0xCD80::

    # echo CD80 >> device_id

program BAR0 size as 1MB::

    # echo 100000 >> bar0_size

check for programmed bar0 size::

    # cat bar0_size

Program BAR0 Address as DDR (0x2100000). This is the physical address of
memory, which is to be made visible to PCIe host. Similarly any other peripheral
can also be made visible to PCIe host. E.g., if you program base address of UART
as BAR0 address then when this device will be connected to a host, it will be
visible as UART.

INTA 설정과 link-up

111-140

INTA를 사용하려면 `int_type`에 `INTA`를 쓰고 `link`에 `UP`을 씁니다. Gadget link-up이 끝난 뒤에만 host를 initialize하고 해당 port의 PCIe device 검색을 시작해야 합니다.

# echo INTA >> int_type
# echo UP >> link
# cat link

`link`가 `UP`을 반환할 때까지 기다립니다. INTA를 assert하려면 `inta`에 1을, de-assert하려면 0을 씁니다.

# echo 1 >> inta
# echo 0 >> inta

::

    # echo 2100000 >> bar0_address

program interrupt type : INTA::

    # echo INTA >> int_type

go for link up now::

    # echo UP >> link

It will have to be insured that, once link up is done on gadget, then only host
is initialized and start to search PCIe devices on its port.

::

    /*wait till link is up*/
    # cat link

Wait till it returns UP.

To assert INTA::

    # echo 1 >> inta

To de-assert INTA::

    # echo 0 >> inta

MSI 설정과 전송

141-170

MSI를 사용하려면 필요한 vector 수를 먼저 `no_of_msi`에 씁니다. 예제는 4개를 요청한 뒤 `int_type`을 `MSI`로 설정하고 link를 올립니다.

# echo 4 >> no_of_msi
# echo MSI >> int_type
# echo UP >> link
# cat link

Application은 `link`가 `UP`이 될 때까지 반복해 읽되 각 read 사이에서 sleep할 수 있습니다. 그 다음 `no_of_msi`가 요청한 vector 수 4를 반환할 때까지 기다립니다. MSI vector 2를 보내려면 `send_msi`에 2를 씁니다.

# cat no_of_msi
# echo 2 >> send_msi
# cd -

if MSI is to be used as interrupt, program no of msi vector needed (say4)::

    # echo 4 >> no_of_msi

select MSI as interrupt type::

    # echo MSI >> int_type

go for link up now::

    # echo UP >> link

wait till link is up::

    # cat link

An application can repetitively read this node till link is found UP. It can
sleep between two read.

wait till msi is enabled::

    # cat no_of_msi

Should return 4 (number of requested MSI vector)

to send msi vector 2::

    # echo 2 >> send_msi
    # cd -