From: Hrushikesh Salunke <[email protected]> Add PCIe boot documentation for J784S4-EVM including boot mode switch settings, hardware setup requirements, endpoint configuration details and step-by-step boot procedure.
Signed-off-by: Hrushikesh Salunke <[email protected]> [[email protected]: simplified and documented the pcie_boot_util program] Co-developed-by: Siddharth Vadapalli <[email protected]> Signed-off-by: Siddharth Vadapalli <[email protected]> --- doc/board/ti/j784s4_evm.rst | 305 ++++++++++++++++++++++++++++++++++++ 1 file changed, 305 insertions(+) diff --git a/doc/board/ti/j784s4_evm.rst b/doc/board/ti/j784s4_evm.rst index d858dc7cdbb..fb767bedbf6 100644 --- a/doc/board/ti/j784s4_evm.rst +++ b/doc/board/ti/j784s4_evm.rst @@ -299,6 +299,10 @@ http://www.ti.com/lit/zip/spruj52 under the `Boot Mode Pins` section. - 00000000 - 01110000 + * - PCIe + - 10001000 + - 01010000 + For SW7 and SW11, the switch state in the "ON" position = 1. Boot Mode Pins for AM69-SK @@ -330,6 +334,307 @@ section. For SW2, the switch state in the "ON" position = 1. +PCIe Boot +--------- + +The J784S4 SoC supports booting over PCIe, allowing the device to function +as a PCIe endpoint and receive boot loader images from a PCIe Root Complex. +The PCIe1 instance of PCIe is configured by Boot ROM for Endpoint Mode of +operation. Hence, the PCIe Connector on the EVM corresponding to PCIe1 +should be utilized for PCIe Boot. + +Hardware Setup +^^^^^^^^^^^^^^ + +To boot the J784S4 EVM via PCIe, the following hardware setup is required: + +1. Configure the boot mode switches on J784S4-EVM for PCIe boot: + + .. code-block:: text + + SW7: 01010000 + SW11: 10001000 + +2. Connect the J784S4-EVM (endpoint) to a PCIe Root Complex (e.g., x86 host) + using a PCIe cable. Both boards should be powered off before making the + connection. + +Endpoint Configuration +^^^^^^^^^^^^^^^^^^^^^^ + +The following configuration options are enabled by default in +``j784s4_evm_r5_defconfig`` and ``j784s4_evm_a72_defconfig``: + +- ``CONFIG_SPL_PCI_DFU_BAR_SIZE``: Size of the PCIe BAR for DFU/boot image download +- ``CONFIG_SPL_PCI_DFU_VENDOR_ID``: PCIe vendor ID advertised by the endpoint +- ``CONFIG_SPL_PCI_DFU_DEVICE_ID``: PCIe device ID advertised by the endpoint +- ``CONFIG_SPL_PCI_DFU_MAGIC_WORD``: Magic word written by Root Complex to signal image transfer completion +- ``CONFIG_SPL_PCI_DFU_BOOT_PHASE``: Current boot phase indicator for Root Complex + +By default, PCIe Root Complex mode is enabled in the device tree. For PCIe Boot, +build the Bootloaders with the following content added to k3-j784s4-evm-u-boot.dtsi: + +.. code-block:: devicetree + + &serdes0 { + /delete-property/ serdes0_usb_link; + }; + + &serdes_refclk { + bootph-all; + }; + + &serdes0_pcie1_link { + bootph-all; + }; + + &serdes_ln_ctrl { + bootph-all; + }; + + &pcie1_ctrl { + bootph-all; + }; + + &pcie1_rc { + status = "disabled"; + }; + + &cbass_main { + pcie1_ep: pcie-ep@2910000 { + compatible = "ti,j784s4-pcie-ep"; + reg = <0x00 0x02910000 0x00 0x1000>, + <0x00 0x02917000 0x00 0x400>, + <0x00 0x0d800000 0x00 0x00800000>, + <0x00 0x18000000 0x00 0x08000000>; + reg-names = "intd_cfg", "user_cfg", "reg", "mem"; + interrupt-names = "link_state"; + interrupts = <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>; + ti,syscon-pcie-ctrl = <&pcie1_ctrl 0x0>; + max-link-speed = <3>; + num-lanes = <2>; + power-domains = <&k3_pds 333 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 333 0>; + clock-names = "fck"; + max-functions = /bits/ 8 <6>; + max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; + dma-coherent; + phys = <&serdes0_pcie1_link>; + phy-names = "pcie-phy"; + bootph-all; + }; + }; + +PCIe Boot Procedure +^^^^^^^^^^^^^^^^^^^ + +The following steps describe the process of booting J784S4-EVM over PCIe: + +1. Compile the sample host program (provided after this section): + + .. prompt:: bash + + gcc -o pcie_boot_util pcie_boot_util.c + +2. Power on the J784S4-EVM (endpoint) after configuring boot mode switches + for PCIe Boot. + +3. Copy the compiled sample host program (pcie_boot_util) and the bootloader + images to the Root Complex. Check PCIe enumeration on Root Complex to ensure + that the J784S4 EVM shows up as the PCIe Endpoint: + + .. prompt:: bash + + lspci + + The endpoint will appear as a RAM device or with multiple functions: + + .. code-block:: text + + 0000:00:00.0 PCI bridge: Texas Instruments Device b012 + 0000:01:00.0 RAM memory: Texas Instruments Device b012 + 0000:01:00.1 Non-VGA unclassified device: Texas Instruments Device 0100 + 0000:01:00.2 Non-VGA unclassified device: Texas Instruments Device 0100 + +4. Copy ``tiboot3.bin`` to the endpoint. Use ``lspci -vv`` to identify the BAR + address: + + .. prompt:: bash + + sudo ./pcie_boot_util 0x4007100000 tiboot3.bin + + The sample program automatically writes the image start address to + ``0x41CF3FE0`` and the magic word ``0xB17CEAD9`` to ``0x41CF3FE4``. + +5. After ``tiboot3.bin`` is processed, the PCIe link will go down briefly. + Remove the PCIe device and rescan the bus: + + .. prompt:: bash + + echo 1 > /sys/bus/pci/devices/0000\:01\:00.0/remove + echo 1 > /sys/bus/pci/devices/0000\:00\:00.0/rescan + lspci + + The enumeration will change to something similar: + + .. code-block:: text + + 0000:00:00.0 PCI bridge: Texas Instruments Device b012 + 0000:01:00.0 RAM memory: Texas Instruments Device b010 (rev dc) + + .. note:: + + When the Root-Complex enumerates the PCIe Endpoint after a 'remove-rescan' sequence, + it is possible that the 'BAR' appears 'disabled'. If so, writing to the BAR via the + 'pcie_boot_util' to transfer the bootloader image will have no effect. In such cases, + run 'setpci -s 0000:01:00.0 COMMAND=0x02' on the Root-Complex after enumeration + (with appropriate DOMAIN:BUS:DEVICE.FUNCTION corresponding to the Endpoint) to enable + the BAR. + +6. Copy ``tispl.bin`` to the new BAR address (use ``lspci -vv`` to find): + + .. prompt:: bash + + sudo ./pcie_boot_util 0x4000400000 tispl.bin + +7. After ``tispl.bin`` is processed, the PCIe link will go down again. Remove + and rescan the PCIe device: + + .. prompt:: bash + + echo 1 > /sys/bus/pci/devices/0000\:01\:00.0/remove + echo 1 > /sys/bus/pci/devices/0000\:00\:00.0/rescan + +8. Copy ``u-boot.img``: + + .. prompt:: bash + + sudo ./pcie_boot_util 0x4000400000 u-boot.img + +9. After ``u-boot.img`` is successfully loaded, the boot process is complete + and endpoint should boot till U-Boot prompt. + +.. note:: + + During the boot process, "PCIe LINK DOWN" messages might appear in kernel + logs. This is expected as the endpoint resets and re-initializes the PCIe + link after processing each boot stage. + +Sample Host Program +^^^^^^^^^^^^^^^^^^^ + +The following C program can be used on the Root Complex to copy bootloader images +to the J784S4 endpoint: + +.. code-block:: c + + #include <stdio.h> + #include <stdlib.h> + #include <fcntl.h> + #include <sys/mman.h> + #include <unistd.h> + #include <string.h> + + #define MAP_SIZE 0x400000 + + /* + * bootloader_file: Path to the bootloader image (tiboot3.bin, tispl.bin and u-boot.img) + * bootloader_mem: Memory allocated in RAM for reading the bootloader image file + * bar_address: Address of BAR to which bootloader image will be written + * bar_map_base: Mapping of the BAR Base Address for the program + * load_address: Address in BAR region where bootloader is being transferred + * transfer_completion_offset: Offset in BAR region to write to notify completion of transfer + * fd_mem: File descriptor for opening /dev/mem + * fptr: File pointer for bootloader image in filesystem + * magic_word: Magic word to notify completion of tiboot3.bin transfer to Boot ROM + * use_magic_word: Flag to indicate if Magic Word has to be written + * file_size: Size of bootloader image + * i: Iterator used during bootloader image transfer + */ + int main(int argc, char *argv[]) + { + off_t bar_address, load_address, transfer_completion_offset; + unsigned char *bootloader_mem; + const char *bootloader_file; + int fd_mem, i, use_magic_word; + unsigned int magic_word; + void *bar_map_base; + long file_size; + FILE * fptr; + + if (argc != 3) { + printf("Usage: %s <bar_address> <bootloader_file>\n", argv[0]); + return 0; + } + + bar_address = strtoul(argv[1], NULL, 16); + bootloader_file = argv[2]; + + printf("Bootloader File: %s\n", bootloader_file); + printf("BAR Address: 0x%lx\n", bar_address); + + if(!strcmp(bootloader_file,"tiboot3.bin")) { + transfer_completion_offset = 0xF3FE0; + load_address = 0x41C00000; + magic_word = 0xB17CEAD9; + use_magic_word = 1; + } else { + transfer_completion_offset = MAP_SIZE - 0x4; + load_address = 0xDEADBEEF; + use_magic_word = 0; + } + + fd_mem = open("/dev/mem", O_RDWR | O_SYNC); + if(fd_mem == -1) { + printf("failed to open /dev/mem\n"); + return -1; + } + + bar_map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd_mem, bar_address); + if(bar_map_base == (void *)-1) { + printf("failed to map BAR\n"); + return -1; + } + + fptr = fopen(bootloader_file, "rb"); + if (!fptr) { + printf("failed to read bootloader file\n"); + return -1; + } + + fseek(fptr, 0, SEEK_END); + file_size = ftell(fptr); + rewind(fptr); + + bootloader_mem = (unsigned char *)malloc(sizeof(char) * file_size); + if(!bootloader_mem) { + printf("failed to allocate local memory for bootloader file\n"); + return -1; + } + + if (fread(bootloader_mem, 1, file_size, fptr) != file_size) { + printf("failed to read bootloader file into local memory\n"); + return -1; + } + + for(i = 0; i < file_size; i++) { + *((char *)(bar_map_base) + i) = bootloader_mem[i]; + } + + *(unsigned int *)(bar_map_base + transfer_completion_offset) = (unsigned int)(load_address); + + if(use_magic_word) { + *(unsigned int *)(bar_map_base + transfer_completion_offset + 4) = magic_word; + printf("Magic word written for Boot ROM\n"); + } + + printf("Transferred %s to Endpoint\n", bootloader_file); + return 0; + } + +This program copies the boot image to the PCIe endpoint's memory region and +writes the necessary control words to signal image transfer completion. + Debugging U-Boot ---------------- -- 2.51.1

