Skip to content

Commit c4273c5

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 c4273c5

File tree

4 files changed

+286
-0
lines changed

4 files changed

+286
-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: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
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+
.. ifconfig:: CONFIG_part_variant in ('AM64X')
119+
120+
3. Copy ``tiboot3.bin`` to Region 1. After the root complex has
121+
finished copying the image, it must write the PCIe boot data
122+
address to ``0x701BCFE0``.
123+
124+
For example, if the root complex loads the image at offset
125+
``0x1000``, then it should write ``0x70001000`` (Internal RAM
126+
memory base + offset) to ``0x701BCFE0``. This notifies the ROM
127+
that the image is ready to be authenticated and processed.
128+
129+
4. Once ``tiboot3.bin`` is transferred, rescan the PCIe bus on the
130+
root complex to enumerate the PCIe endpoint device, in order to
131+
transfer the next stage bootloader. The enumeration may now look
132+
like the following:
133+
134+
::
135+
136+
0000:01:00.0 RAM memory: Texas Instruments Device b010
137+
Subsystem: Device 7003:beef
138+
Flags: bus master, fast devsel, latency 0, IRQ 644
139+
Memory at 12000000 (32-bit, prefetchable) [size=4M]
140+
Capabilities: [80] Power Management version 3
141+
Capabilities: [90] MSI: Enable+ Count=1/1 Maskable+ 64bit+
142+
Capabilities: [b0] MSI-X: Enable- Count=1 Masked-
143+
Capabilities: [c0] Express Endpoint, IntMsgNum 0
144+
Capabilities: [100] Advanced Error Reporting
145+
146+
5. At this stage, only one memory region will be visible. Copy
147+
``tispl.bin`` to this region. After the copy, the root complex
148+
must write a 4-byte magic word (defined in the defconfig) at the
149+
end of the memory region. This indicates to the endpoint that the
150+
bootloader image has been copied.
151+
152+
6. Repeat steps 4 and 5 to transfer ``u-boot.img`` using the same
153+
procedure.
154+
155+
Sample Host Program for Image Transfer
156+
--------------------------------------
157+
158+
The following sample C program can be used on the root complex to
159+
copy bootloader images (such as ``tiboot3.bin``, ``tispl.bin``, and
160+
``u-boot.img``) to the PCIe endpoint device by writing them to the
161+
appropriate memory regions using ``/dev/mem``.
162+
163+
.. code-block:: c
164+
165+
#include <sys/mman.h>
166+
#include <sys/stat.h>
167+
#include <fcntl.h>
168+
#include <unistd.h>
169+
#include <stdio.h>
170+
#include <stdlib.h>
171+
#include <string.h>
172+
173+
int main(int argc, char *argv[])
174+
{
175+
char *bootfilename = NULL;
176+
off_t bar1_address = 0;
177+
int fd;
178+
void *map_base;
179+
long image_size, map_size;
180+
char *buffer;
181+
unsigned int *buffer_32;
182+
int i;
183+
FILE * fptr;
184+
off_t load_addr, load_addr_offset, start_addr_offset;
185+
186+
if (argc != 3) {
187+
printf("Usage: %s <bar_address> <binary_file>\n", argv[0]);
188+
return 0;
189+
}
190+
191+
bar1_address = strtoul(argv[1], NULL, 16);
192+
bootfilename = argv[2];
193+
194+
printf("bootfilename: %s\n", bootfilename);
195+
printf("bar1_address: 0x%lx\n", bar1_address);
196+
197+
if(!strcmp(bootfilename,"tiboot3.bin"))
198+
{
199+
load_addr = 0x70000000;
200+
load_addr_offset = 0x1000;
201+
start_addr_offset = 0x1bcfe0;
202+
}
203+
else
204+
{
205+
load_addr = 0xdeadbeef;
206+
load_addr_offset = 0x00;
207+
start_addr_offset = 0x3ffffc;
208+
}
209+
210+
printf("load_addr: 0x%lx\n", load_addr);
211+
printf("load_addr_offset: 0x%lx\n", load_addr_offset);
212+
printf("start_addr_offset: 0x%lx\n", start_addr_offset);
213+
214+
printf("try to open /dev/mem.\n");
215+
fd = open("/dev/mem", O_RDWR | O_SYNC);
216+
if (fd < 0) {
217+
printf("open /dev/mem failed.\n");
218+
return 0;
219+
}
220+
printf("/dev/mem opened.\n");
221+
(void)fflush(stdout);
222+
223+
fptr = fopen(bootfilename, "rb");
224+
if (!fptr) {
225+
printf("open %s failed.\n", bootfilename);
226+
return 0;
227+
}
228+
printf("%s opened.\n", bootfilename);
229+
230+
(void)fseek(fptr, 0L, SEEK_END);
231+
image_size = ftell(fptr);
232+
printf("image_size: %ld\n", image_size);
233+
fseek(fptr, 0, SEEK_SET);
234+
235+
printf("%s: image_size: %ld\n", __func__, image_size);
236+
237+
map_size = 0x400000;
238+
239+
printf("%s: map_size: %ld\n", __func__, map_size);
240+
241+
map_base = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, bar1_address);
242+
if (map_base == MAP_FAILED) {
243+
printf("mmap failed.\n");
244+
return 0;
245+
}
246+
printf("map_base: 0x%lx\n", (unsigned long)map_base);
247+
(void)fflush(stdout);
248+
249+
buffer = malloc(image_size);
250+
if (!buffer) {
251+
printf("malloc failed.\n");
252+
return 0;
253+
}
254+
255+
buffer_32 = (unsigned int *)buffer;
256+
fread(buffer, (size_t)image_size, 1, fptr);
257+
printf("Read image of %ld bytes\n", image_size);
258+
259+
printf("Writing image to memory\n");
260+
for(i = 0; i < (int)image_size; i+=4)
261+
{
262+
*(unsigned int *)( map_base + load_addr_offset + i) = buffer_32[i/4];
263+
}
264+
printf("done.\n");
265+
fflush(stdout);
266+
267+
sleep(1);
268+
269+
*(unsigned int *)(map_base + start_addr_offset) = (unsigned int)(load_addr_offset + load_addr);
270+
return 0;
271+
}
272+
273+
Usage Example
274+
^^^^^^^^^^^^^
275+
276+
To copy a bootloader file (e.g., ``tiboot3.bin``) to the PCIe device,
277+
run:
278+
279+
.. code-block:: bash
280+
281+
sudo ./pcie_boot_copy 0x68200000 tiboot3.bin
282+
283+
Replace ``0x68200000`` with the appropriate BAR region address as
284+
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)