Skip to content

Commit b936451

Browse files
committed
docs(linux): AM64X: Add the PCIe boot documentation
Add PCIe boot documentation for AM64X. Signed-off-by: Hrushikesh Salunke <[email protected]>
1 parent 4fe1623 commit b936451

File tree

4 files changed

+287
-0
lines changed

4 files changed

+287
-0
lines changed

configs/AM64X/AM64X_linux_toc.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ linux/Foundational_Components/U-Boot/UG-DDRSS
3434
linux/Foundational_Components/U-Boot/UG-NAND
3535
linux/Foundational_Components/U-Boot/UG-Network-K3
3636
linux/Foundational_Components/U-Boot/UG-RemoteProc
37+
linux/Foundational_Components/U-Boot/UG-PCIeBoot
3738
linux/Foundational_Components/U-Boot/Applications
3839
linux/Foundational_Components/U-Boot/Apps-SPL-Debug-OpenOCD
3940
linux/Foundational_Components/U-Boot/Apps-TroubleShooting

source/images/AM64X_PCIe_boot.jpg

121 KB
Loading
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
.. _pcie_boot:
2+
3+
=========================
4+
PCIe Boot Mode
5+
=========================
6+
7+
Overview
8+
--------
9+
10+
PCIe (Peripheral Component Interconnect Express) boot mode allows
11+
|__PART_FAMILY_NAME__| family of devices, configured as a PCIe endpoint, to boot by
12+
receiving bootloader images over PCIe from a host system acting as a
13+
PCIe root complex (RC). In this mode, the root complex is
14+
responsible for discovering the endpoint device and transferring the
15+
required bootloader images for each boot stage.
16+
17+
This document provides a step-by-step guide to configuring and using
18+
PCIe boot mode. PCIe boot is supported on the |__PART_FAMILY_NAME__| SoC family. The
19+
following instructions and switch settings are specific to the |__PART_FAMILY_NAME__| EVM;
20+
for other boards, please consult the corresponding hardware documentation.
21+
22+
Boot Mode Switch Settings
23+
-------------------------
24+
25+
To enable PCIe boot mode, configure the boot mode switches as follows:
26+
27+
.. ifconfig:: CONFIG_part_variant in ('AM64X')
28+
29+
::
30+
31+
SW2 (B0 - B7): 1 1 0 1 0 1 1 0
32+
SW3 (B8 - B15): 0 0 0 0 0 0 0 0
33+
34+
.. note::
35+
36+
DIP switch settings are EVM-specific and may not apply to all board designs.
37+
38+
Board Setup (Connection Example)
39+
--------------------------------
40+
41+
The following is an example of a connection in which the root complex (host) and the
42+
endpoint (|__PART_FAMILY_NAME__| device) are physically connected using a PCIe cable
43+
or connector, as shown in the figure below.
44+
45+
.. image:: /images/AM64X_PCIe_boot.jpg
46+
47+
Both boards should be powered off before making the connection, and the PCIe link
48+
securely established before powering on the devices.
49+
50+
Other hardware configurations are possible. So please adapt the setup steps as
51+
applicable to your board design.
52+
53+
Endpoint Configuration
54+
----------------------
55+
56+
The following configuration options are used to set up the |__PART_FAMILY_NAME__| device
57+
as a PCIe endpoint for PCIe boot. These options must be set in the
58+
board's defconfig in U-BOOT for the corresponding bootloader image.
59+
60+
- ``CONFIG_PCI_DFU_BAR_SIZE``:
61+
Configures the size of the PCIe BAR (Base Address Register) that is
62+
exposed for device firmware update (DFU) and bootloader image download.
63+
64+
- ``CONFIG_PCI_DFU_VENDOR_ID``:
65+
Specifies the PCIe vendor ID to be advertised by the endpoint.
66+
67+
- ``CONFIG_PCI_DFU_DEVICE_ID``:
68+
Specifies the PCIe device ID to be advertised by the endpoint.
69+
70+
- ``CONFIG_PCI_DFU_MAGIC_WORD``:
71+
Magic word written by the root complex at the end of the image transfer to
72+
signal to the endpoint that the bootloader image is ready for processing.
73+
74+
- ``CONFIG_PCI_DFU_BOOT_PHASE``:
75+
Specify the current boot phase when booting via DFU over PCIe.
76+
This value can be read by the root complex to determine the
77+
current boot phase. Value of this config is written to memory
78+
location (BAR_start + PCI_DFU_BAR_SIZE - 70). Max size of this
79+
config is 63 bytes.
80+
81+
.. ifconfig:: CONFIG_part_variant in ('AM64X')
82+
83+
.. note::
84+
85+
All the configs required for PCIe boot are enabled in
86+
``am64x_evm_a53_defconfig`` and ``am64x_evm_r5_defconfig`` by default.
87+
88+
By default, PCIe root complex mode is enabled in the device tree.
89+
To enable endpoint mode, the bootloaders must be built with the
90+
device tree overlay ``k3-am642-evm-pcie0-ep.dtso``.
91+
92+
Ensure these configuration options are set appropriately in the build
93+
environment to enable a successful PCIe boot process.
94+
95+
PCIe Boot Procedure
96+
-------------------
97+
98+
1. After configuring the boot mode switches on the endpoint and
99+
connecting it to the root complex as shown in the figure, power
100+
on the endpoint.
101+
102+
2. On the root complex, rescan the PCIe bus to enumerate the PCIe
103+
endpoint. The endpoint will appear as a RAM device on the root
104+
complex. The enumeration may look similar to the following:
105+
106+
::
107+
108+
01:00.0 RAM memory: Texas Instruments Device b010
109+
Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
110+
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
111+
Latency: 0
112+
Interrupt: pin A routed to IRQ 526
113+
Region 0: Memory at 68100000 (32-bit, non-prefetchable) [size=1M]
114+
Region 1: Memory at 68200000 (32-bit, prefetchable) [size=2M]
115+
Region 2: Memory at 6a000000 (64-bit, prefetchable) [size=32M]
116+
Region 4: Memory at 6c000000 (64-bit, prefetchable) [size=32M]
117+
118+
3. Copy ``tiboot3.bin`` to Region 1.
119+
120+
.. ifconfig:: CONFIG_part_variant in ('AM64X')
121+
122+
After the root complex has finished copying the image,
123+
it must write the PCIe boot data address to ``0x701BCFE0``.
124+
125+
For example, if the root complex loads the image at offset
126+
``0x1000``, then it should write ``0x70001000`` (Internal RAM
127+
memory base + offset) to ``0x701BCFE0``. This notifies the ROM
128+
that the image is ready to be authenticated and processed.
129+
130+
4. Once ``tiboot3.bin`` is transferred, rescan the PCIe bus on the
131+
root complex to enumerate the PCIe endpoint device, in order to
132+
transfer the next stage bootloader. The enumeration may now look
133+
like the following:
134+
135+
::
136+
137+
0000:01:00.0 RAM memory: Texas Instruments Device b010
138+
Subsystem: Device 7003:beef
139+
Flags: bus master, fast devsel, latency 0, IRQ 644
140+
Memory at 12000000 (32-bit, prefetchable) [size=4M]
141+
Capabilities: [80] Power Management version 3
142+
Capabilities: [90] MSI: Enable+ Count=1/1 Maskable+ 64bit+
143+
Capabilities: [b0] MSI-X: Enable- Count=1 Masked-
144+
Capabilities: [c0] Express Endpoint, IntMsgNum 0
145+
Capabilities: [100] Advanced Error Reporting
146+
147+
5. At this stage, only one memory region will be visible. Copy
148+
``tispl.bin`` to this region. After the copy, the root complex
149+
must write a 4-byte magic word (defined in the defconfig) at the
150+
end of the memory region. This indicates to the endpoint that the
151+
bootloader image has been copied.
152+
153+
6. Repeat steps 4 and 5 to transfer ``u-boot.img`` using the same
154+
procedure.
155+
156+
Sample Host Program for Image Transfer
157+
--------------------------------------
158+
159+
The following sample C program can be used on the root complex to
160+
copy bootloader images (such as ``tiboot3.bin``, ``tispl.bin``, and
161+
``u-boot.img``) to the PCIe endpoint device by writing them to the
162+
appropriate memory regions using ``/dev/mem``.
163+
164+
.. code-block:: c
165+
166+
#include <sys/mman.h>
167+
#include <sys/stat.h>
168+
#include <fcntl.h>
169+
#include <unistd.h>
170+
#include <stdio.h>
171+
#include <stdlib.h>
172+
#include <string.h>
173+
174+
int main(int argc, char *argv[])
175+
{
176+
char *bootfilename = NULL;
177+
off_t bar1_address = 0;
178+
int fd;
179+
void *map_base;
180+
long image_size, map_size;
181+
char *buffer;
182+
unsigned int *buffer_32;
183+
int i;
184+
FILE * fptr;
185+
off_t load_addr, load_addr_offset, start_addr_offset;
186+
187+
if (argc != 3) {
188+
printf("Usage: %s <bar_address> <binary_file>\n", argv[0]);
189+
return 0;
190+
}
191+
192+
bar1_address = strtoul(argv[1], NULL, 16);
193+
bootfilename = argv[2];
194+
195+
printf("bootfilename: %s\n", bootfilename);
196+
printf("bar1_address: 0x%lx\n", bar1_address);
197+
198+
if(!strcmp(bootfilename,"tiboot3.bin"))
199+
{
200+
load_addr = 0x70000000;
201+
load_addr_offset = 0x1000;
202+
start_addr_offset = 0x1bcfe0;
203+
}
204+
else
205+
{
206+
load_addr = 0xdeadbeef;
207+
load_addr_offset = 0x00;
208+
start_addr_offset = 0x3ffffc;
209+
}
210+
211+
printf("load_addr: 0x%lx\n", load_addr);
212+
printf("load_addr_offset: 0x%lx\n", load_addr_offset);
213+
printf("start_addr_offset: 0x%lx\n", start_addr_offset);
214+
215+
printf("try to open /dev/mem.\n");
216+
fd = open("/dev/mem", O_RDWR | O_SYNC);
217+
if (fd < 0) {
218+
printf("open /dev/mem failed.\n");
219+
return 0;
220+
}
221+
printf("/dev/mem opened.\n");
222+
(void)fflush(stdout);
223+
224+
fptr = fopen(bootfilename, "rb");
225+
if (!fptr) {
226+
printf("open %s failed.\n", bootfilename);
227+
return 0;
228+
}
229+
printf("%s opened.\n", bootfilename);
230+
231+
(void)fseek(fptr, 0L, SEEK_END);
232+
image_size = ftell(fptr);
233+
printf("image_size: %ld\n", image_size);
234+
fseek(fptr, 0, SEEK_SET);
235+
236+
printf("%s: image_size: %ld\n", __func__, image_size);
237+
238+
map_size = 0x400000;
239+
240+
printf("%s: map_size: %ld\n", __func__, map_size);
241+
242+
map_base = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, bar1_address);
243+
if (map_base == MAP_FAILED) {
244+
printf("mmap failed.\n");
245+
return 0;
246+
}
247+
printf("map_base: 0x%lx\n", (unsigned long)map_base);
248+
(void)fflush(stdout);
249+
250+
buffer = malloc(image_size);
251+
if (!buffer) {
252+
printf("malloc failed.\n");
253+
return 0;
254+
}
255+
256+
buffer_32 = (unsigned int *)buffer;
257+
fread(buffer, (size_t)image_size, 1, fptr);
258+
printf("Read image of %ld bytes\n", image_size);
259+
260+
printf("Writing image to memory\n");
261+
for(i = 0; i < (int)image_size; i+=4)
262+
{
263+
*(unsigned int *)( map_base + load_addr_offset + i) = buffer_32[i/4];
264+
}
265+
printf("done.\n");
266+
fflush(stdout);
267+
268+
sleep(1);
269+
270+
*(unsigned int *)(map_base + start_addr_offset) = (unsigned int)(load_addr_offset + load_addr);
271+
return 0;
272+
}
273+
274+
Usage Example
275+
^^^^^^^^^^^^^
276+
277+
To copy a bootloader file (e.g., ``tiboot3.bin``) to the PCIe device,
278+
run:
279+
280+
.. code-block:: bash
281+
282+
sudo ./pcie_boot_copy 0x68200000 tiboot3.bin
283+
284+
Replace ``0x68200000`` with the appropriate BAR region address as
285+
enumerated on the root complex, and specify the correct binary file.

source/linux/Foundational_Components/U-Boot/Users-Guide.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ User's Guide
1212
UG-DFU
1313
UG-Network
1414
UG-Network-K3
15+
UG-PCIeBoot
1516
UG-NAND
1617
UG-Memory-K3
1718
UG-Memory-OMAP

0 commit comments

Comments
 (0)