diff options
97 files changed, 3757 insertions, 236 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 228d8af433d..d724b646734 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -343,6 +343,7 @@ F: drivers/rtc/armada38x.c F: drivers/spi/kirkwood_spi.c F: drivers/spi/mvebu_a3700_spi.c F: drivers/pci/pcie_dw_mvebu.c +F: drivers/pci/pcie-xilinx-nwl.c F: drivers/watchdog/armada-37xx-wdt.c F: drivers/watchdog/orion_wdt.c F: include/configs/mv-common.h @@ -755,6 +756,7 @@ F: drivers/spi/zynq_qspi.c F: drivers/spi/zynq_spi.c F: drivers/timer/cadence-ttc.c F: drivers/video/seps525.c +F: drivers/video/zynqmp/ F: drivers/watchdog/cdns_wdt.c F: include/zynqmppl.h F: include/zynqmp_firmware.h diff --git a/arch/Kconfig.nxp b/arch/Kconfig.nxp index 6e1c44b7ea8..e75226bc434 100644 --- a/arch/Kconfig.nxp +++ b/arch/Kconfig.nxp @@ -90,7 +90,7 @@ config SPL_UBOOT_KEY_HASH default "" help Set the key hash for U-Boot here if public/private key pair used to - sign U-boot are different from the SRK hash put in the fuse. Example + sign U-Boot are different from the SRK hash put in the fuse. Example of a key hash is 41066b564c6ffcef40ccbc1e0a5d0d519604000c785d97bbefd25e4d288d1c8b. Otherwise leave this empty. diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h index 6adc0ed42ba..c818b8bdaec 100644 --- a/arch/arc/include/asm/io.h +++ b/arch/arc/include/asm/io.h @@ -80,7 +80,7 @@ static inline void sync(void) /* * We add memory barriers for __raw_readX / __raw_writeX accessors same way as - * it is done for readX and writeX accessors as lots of U-boot driver uses + * it is done for readX and writeX accessors as lots of U-Boot driver uses * __raw_readX / __raw_writeX instead of proper accessor with barrier. */ #define __raw_writeb(v, c) ({ __iowmb(); __arch_putb(v, c); }) diff --git a/arch/arm/cpu/armv7/Kconfig b/arch/arm/cpu/armv7/Kconfig index e33e53636a0..ccc2f208677 100644 --- a/arch/arm/cpu/armv7/Kconfig +++ b/arch/arm/cpu/armv7/Kconfig @@ -110,7 +110,7 @@ config ARMV7_LPAE config ARMV7_SET_CORTEX_SMPEN bool help - Enable the ARM Cortex ACTLR.SMP enable bit in U-boot. + Enable the ARM Cortex ACTLR.SMP enable bit in U-Boot. config SPL_ARMV7_SET_CORTEX_SMPEN bool diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig index 7d5cf1594da..9f0fb369f77 100644 --- a/arch/arm/cpu/armv8/Kconfig +++ b/arch/arm/cpu/armv8/Kconfig @@ -145,7 +145,7 @@ config ARMV8_PSCI bool "Enable PSCI support" if EXPERT help PSCI is Power State Coordination Interface defined by ARM. - The PSCI in U-boot provides a general framework and each platform + The PSCI in U-Boot provides a general framework and each platform can implement their own specific PSCI functions. Say Y here to enable PSCI support on ARMv8 platform. diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3 b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3 index 6f3fe7ca6e0..1ddf9473a30 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3 +++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3 @@ -125,7 +125,7 @@ mcinitcmd: This environment variable is defined to initiate MC and DPL deploymen from the location where it is stored(NOR, NAND, SD, SATA, USB)during u-boot booting.If this variable is not defined then MC_BOOT_ENV_VAR will be null and MC will not be booted and DPL will not be applied - during U-boot booting.However the MC, DPC and DPL can be applied from + during U-Boot booting.However the MC, DPC and DPL can be applied from console independently. The variable needs to be set from the console once and then on rebooting the parameters set in the variable will automatically be diff --git a/arch/arm/dts/fsl-ls1028a.dtsi b/arch/arm/dts/fsl-ls1028a.dtsi index 06b36cc6586..dde0c4091f1 100644 --- a/arch/arm/dts/fsl-ls1028a.dtsi +++ b/arch/arm/dts/fsl-ls1028a.dtsi @@ -51,7 +51,7 @@ idle-states { /* - * PSCI node is not added default, U-boot will add missing + * PSCI node is not added default, U-Boot will add missing * parts if it determines to use PSCI. */ entry-method = "psci"; diff --git a/arch/arm/dts/meson-g12-common-u-boot.dtsi b/arch/arm/dts/meson-g12-common-u-boot.dtsi index efa6a0570bd..8070b62af5b 100644 --- a/arch/arm/dts/meson-g12-common-u-boot.dtsi +++ b/arch/arm/dts/meson-g12-common-u-boot.dtsi @@ -5,7 +5,7 @@ */ / { - /* Keep HW order from U-boot */ + /* Keep HW order from U-Boot */ aliases { /delete-property/ mmc0; /delete-property/ mmc1; diff --git a/arch/arm/dts/meson-gx-u-boot.dtsi b/arch/arm/dts/meson-gx-u-boot.dtsi index 9f123ab0421..9e0620f395e 100644 --- a/arch/arm/dts/meson-gx-u-boot.dtsi +++ b/arch/arm/dts/meson-gx-u-boot.dtsi @@ -5,7 +5,7 @@ */ / { - /* Keep HW order from U-boot */ + /* Keep HW order from U-Boot */ aliases { /delete-property/ mmc0; /delete-property/ mmc1; diff --git a/arch/arm/dts/rk3328-evb-u-boot.dtsi b/arch/arm/dts/rk3328-evb-u-boot.dtsi index 4bfa0c2330b..95e497970ee 100644 --- a/arch/arm/dts/rk3328-evb-u-boot.dtsi +++ b/arch/arm/dts/rk3328-evb-u-boot.dtsi @@ -41,7 +41,7 @@ }; &gmac2phy { - /* Integrated PHY unsupported by U-boot */ + /* Integrated PHY unsupported by U-Boot */ status = "broken"; }; diff --git a/arch/arm/dts/rk3328.dtsi b/arch/arm/dts/rk3328.dtsi index 27e45d5886a..e8d8f00be8a 100644 --- a/arch/arm/dts/rk3328.dtsi +++ b/arch/arm/dts/rk3328.dtsi @@ -984,7 +984,7 @@ }; /* - * U-boot Specific Change + * U-Boot Specific Change * * The OTG controller must come after the USB host pair for it * to work. This is likely due to lack of support for the USB diff --git a/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch2.h b/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch2.h index 1b02d484d98..c18c51ed2c7 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch2.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch2.h @@ -22,7 +22,7 @@ * * -PCIe * -there is a range of stream IDs set aside for PCI in this - * file. U-boot will scan the PCI bus and for each device discovered: + * file. U-Boot will scan the PCI bus and for each device discovered: * -allocate a streamID * -set a PEXn LUT table entry mapping 'requester ID' to 'stream ID' * -set a msi-map entry in the PEXn controller node in the diff --git a/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h b/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h index b36b6d3889f..140849d4e1f 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h @@ -23,7 +23,7 @@ * * -PCIe * -there is a range of stream IDs set aside for PCI in this - * file. U-boot will scan the PCI bus and for each device discovered: + * file. U-Boot will scan the PCI bus and for each device discovered: * -allocate a streamID * -set a PEXn LUT table entry mapping 'requester ID' to 'stream ID' * -set a msi-map entry in the PEXn controller node in the diff --git a/arch/arm/mach-versal-net/include/mach/hardware.h b/arch/arm/mach-versal-net/include/mach/hardware.h index c5e4e22040e..3f04104961d 100644 --- a/arch/arm/mach-versal-net/include/mach/hardware.h +++ b/arch/arm/mach-versal-net/include/mach/hardware.h @@ -27,7 +27,13 @@ struct iou_scntrs_regs { u32 base_frequency_id_register; /* 0x20 */ }; +struct crp_regs { + u32 reserved0[128]; + u32 boot_mode_usr; /* 0x200 */ +}; + #define VERSAL_NET_CRL_APB_BASEADDR 0xEB5E0000 +#define VERSAL_NET_CRP_BASEADDR 0xF1260000 #define VERSAL_NET_IOU_SCNTR_SECURE 0xEC920000 #define CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT BIT(25) @@ -36,6 +42,7 @@ struct iou_scntrs_regs { #define IOU_SCNTRS_CONTROL_EN 1 #define crlapb_base ((struct crlapb_regs *)VERSAL_NET_CRL_APB_BASEADDR) +#define crp_base ((struct crp_regs *)VERSAL_NET_CRP_BASEADDR) #define iou_scntr_secure ((struct iou_scntrs_regs *)VERSAL_NET_IOU_SCNTR_SECURE) #define PMC_TAP 0xF11A0000 @@ -44,11 +51,26 @@ struct iou_scntrs_regs { #define PMC_TAP_VERSION (PMC_TAP + 0x4) # define PMC_VERSION_MASK GENMASK(7, 0) # define PS_VERSION_MASK GENMASK(15, 8) +# define PS_VERSION_PRODUCTION 0x20 # define RTL_VERSION_MASK GENMASK(23, 16) # define PLATFORM_MASK GENMASK(27, 24) # define PLATFORM_VERSION_MASK GENMASK(31, 28) #define PMC_TAP_USERCODE (PMC_TAP + 0x8) +/* Bootmode setting values */ +#define BOOT_MODES_MASK 0x0000000F +#define QSPI_MODE_24BIT 0x00000001 +#define QSPI_MODE_32BIT 0x00000002 +#define SD_MODE 0x00000003 /* sd 0 */ +#define SD_MODE1 0x00000005 /* sd 1 */ +#define EMMC_MODE 0x00000006 +#define USB_MODE 0x00000007 +#define OSPI_MODE 0x00000008 +#define SD1_LSHFT_MODE 0x0000000E /* SD1 Level shifter */ +#define JTAG_MODE 0x00000000 +#define BOOT_MODE_USE_ALT 0x100 +#define BOOT_MODE_ALT_SHIFT 12 + enum versal_net_platform { VERSAL_NET_SILICON = 0, VERSAL_NET_SPP = 1, diff --git a/arch/arm/mach-versal/include/mach/sys_proto.h b/arch/arm/mach-versal/include/mach/sys_proto.h index 3f01508ecb5..433f9ba07c7 100644 --- a/arch/arm/mach-versal/include/mach/sys_proto.h +++ b/arch/arm/mach-versal/include/mach/sys_proto.h @@ -10,6 +10,7 @@ enum { TCM_SPLIT, }; +void initialize_tcm(bool mode); void tcm_init(u8 mode); void mem_map_fill(void); diff --git a/arch/arm/mach-versal/mp.c b/arch/arm/mach-versal/mp.c index 9b0518d6a2c..5b850f3f89f 100644 --- a/arch/arm/mach-versal/mp.c +++ b/arch/arm/mach-versal/mp.c @@ -23,7 +23,7 @@ #define VERSAL_CRL_RST_CPU_R5_RESET_PGE_MASK 0x10 #define VERSAL_CRLAPB_CPU_R5_CTRL_CLKACT_MASK 0x1000000 -void set_r5_halt_mode(u8 halt, u8 mode) +static void set_r5_halt_mode(u8 halt, u8 mode) { u32 tmp; @@ -44,7 +44,7 @@ void set_r5_halt_mode(u8 halt, u8 mode) } } -void set_r5_tcm_mode(u8 mode) +static void set_r5_tcm_mode(u8 mode) { u32 tmp; @@ -62,7 +62,7 @@ void set_r5_tcm_mode(u8 mode) writel(tmp, &rpu_base->rpu_glbl_ctrl); } -void release_r5_reset(u8 mode) +static void release_r5_reset(u8 mode) { u32 tmp; @@ -77,7 +77,7 @@ void release_r5_reset(u8 mode) writel(tmp, &crlapb_base->rst_cpu_r5); } -void enable_clock_r5(void) +static void enable_clock_r5(void) { u32 tmp; diff --git a/arch/arm/mach-zynqmp/handoff.c b/arch/arm/mach-zynqmp/handoff.c index b9e0c6c536b..511b241462f 100644 --- a/arch/arm/mach-zynqmp/handoff.c +++ b/arch/arm/mach-zynqmp/handoff.c @@ -9,6 +9,7 @@ #include <asm/io.h> #include <asm/arch/hardware.h> #include <asm/arch/sys_proto.h> +#include <spl.h> /* * atfhandoffparams diff --git a/arch/arm/mach-zynqmp/mp.c b/arch/arm/mach-zynqmp/mp.c index 7a12f4b2b6c..b06c867e57f 100644 --- a/arch/arm/mach-zynqmp/mp.c +++ b/arch/arm/mach-zynqmp/mp.c @@ -326,6 +326,10 @@ int cpu_release(u32 nr, int argc, char *const argv[]) flush_dcache_all(); if (!strncmp(argv[1], "lockstep", 8)) { + if (nr != ZYNQMP_CORE_RPU0) { + printf("Lockstep mode should run on ZYNQMP_CORE_RPU0\n"); + return 1; + } printf("R5 lockstep mode\n"); set_r5_reset(nr, LOCK); set_r5_tcm_mode(LOCK); diff --git a/board/bosch/acc/acc.c b/board/bosch/acc/acc.c index 732d823826b..7c49b206c15 100644 --- a/board/bosch/acc/acc.c +++ b/board/bosch/acc/acc.c @@ -542,7 +542,7 @@ int board_mmc_init(struct bd_info *bis) gpio_direction_input(USDHC2_CD_GPIO); /* * According to the board_mmc_init() the following map is done: - * (U-boot device node) (Physical Port) + * (U-Boot device node) (Physical Port) * mmc0 USDHC2 * mmc1 USDHC4 */ diff --git a/board/bosch/shc/README b/board/bosch/shc/README index 2f206e0d551..74704cdc115 100644 --- a/board/bosch/shc/README +++ b/board/bosch/shc/README @@ -68,7 +68,7 @@ Netboot - see also doc/SPL/README.am335x-network - set the jumper into netboot mode -- compile the U-boot sources with: +- compile the U-Boot sources with: make am335x_shc_netboot_defconfig make all - copy the images into your tftp boot directory diff --git a/board/compulab/cl-som-imx7/cl-som-imx7.c b/board/compulab/cl-som-imx7/cl-som-imx7.c index 1b08a2c5abf..af19a658b54 100644 --- a/board/compulab/cl-som-imx7/cl-som-imx7.c +++ b/board/compulab/cl-som-imx7/cl-som-imx7.c @@ -86,7 +86,7 @@ int board_mmc_init(struct bd_info *bis) int i, ret; /* * According to the board_mmc_init() the following map is done: - * (U-boot device node) (Physical Port) + * (U-Boot device node) (Physical Port) * mmc0 USDHC1 * mmc2 USDHC3 (eMMC) */ diff --git a/board/hisilicon/poplar/README b/board/hisilicon/poplar/README index 99ed6ce295e..77dcc3ba115 100644 --- a/board/hisilicon/poplar/README +++ b/board/hisilicon/poplar/README @@ -30,7 +30,7 @@ CONNECTORS One connector for Smart Card One connector for TSI Note of warning: ================ -U-boot has a *strong* dependency with the l-loader and the arm trusted firmware +U-Boot has a *strong* dependency with the l-loader and the arm trusted firmware repositories. The boot sequence is: diff --git a/board/isee/igep003x/board.c b/board/isee/igep003x/board.c index 5462a3dea22..7dbb0800892 100644 --- a/board/isee/igep003x/board.c +++ b/board/isee/igep003x/board.c @@ -37,7 +37,7 @@ DECLARE_GLOBAL_DATA_PTR; /* GPIO0_27 and GPIO0_26 are used to read board revision from IGEP003x boards * and control IGEP0034 green and red LEDs. - * U-boot configures these pins as input pullup to detect board revision: + * U-Boot configures these pins as input pullup to detect board revision: * IGEP0034-LITE = 0b00 * IGEP0034 (FULL) = 0b01 * IGEP0033 = 0b1X diff --git a/board/isee/igep00x0/igep00x0.c b/board/isee/igep00x0/igep00x0.c index f1599306e61..0f0a9c592fc 100644 --- a/board/isee/igep00x0/igep00x0.c +++ b/board/isee/igep00x0/igep00x0.c @@ -47,7 +47,7 @@ U_BOOT_DRVINFO(igep_uart) = { * IGEP00x0 boards. First of all, it is necessary to reset USB transceiver from * IGEP0030 in order to read GPIO_IGEP00X0_BOARD_DETECTION correctly, because * this functionality is shared by USB HOST. - * Once USB reset is applied, U-boot configures these pins as input pullup to + * Once USB reset is applied, U-Boot configures these pins as input pullup to * detect board and revision: * IGEP0020-RF = 0b00 * IGEP0020-RC = 0b01 diff --git a/board/keymile/Kconfig b/board/keymile/Kconfig index bf899d005c4..c6576aa6523 100644 --- a/board/keymile/Kconfig +++ b/board/keymile/Kconfig @@ -123,7 +123,7 @@ config SYS_IVM_EEPROM_PAGE_LEN Page size of inventory in EEPROM. config PG_WCOM_UBOOT_UPDATE_SUPPORTED - bool "Enable U-boot Field Fail-Safe Update Functionality" + bool "Enable U-Boot Field Fail-Safe Update Functionality" select EVENT default n help @@ -132,7 +132,7 @@ config PG_WCOM_UBOOT_UPDATE_SUPPORTED from parallel NOR flash. config PG_WCOM_UBOOT_BOOTPACKAGE - bool "U-boot Is Part Of Factory Boot-Package Image" + bool "U-Boot Is Part Of Factory Boot-Package Image" default n help Indicates that u-boot will be a part of the factory programmed @@ -140,7 +140,7 @@ config PG_WCOM_UBOOT_BOOTPACKAGE Has to be set for original u-boot programmed at factory. config PG_WCOM_UBOOT_UPDATE_TEXT_BASE - hex "Text Base For U-boot Programmed Outside Factory" + hex "Text Base For U-Boot Programmed Outside Factory" default 0xFFFFFFFF help Text base of an updated u-boot that is not factory programmed but @@ -148,7 +148,7 @@ config PG_WCOM_UBOOT_UPDATE_TEXT_BASE Has to be set for original u-boot programmed at factory. config PG_WCOM_UBOOT_UPDATE - bool "U-boot Is Part Of Factory Boot-Package Image" + bool "U-Boot Is Part Of Factory Boot-Package Image" default n help Indicates that u-boot will be a part of the embedded software and diff --git a/board/keymile/README b/board/keymile/README index 4e5cfb142a3..99f27e576aa 100644 --- a/board/keymile/README +++ b/board/keymile/README @@ -1,4 +1,4 @@ -Field Fail-Save U-boot Update +Field Fail-Save U-Boot Update ----------------------------- Field Fail-Save u-boot update is a feature that allows save u-boot update of FOX and XMC products that are rolled out in the field. diff --git a/board/kontron/sl-mx6ul/spl.c b/board/kontron/sl-mx6ul/spl.c index bae0e70a657..a9d370bc854 100644 --- a/board/kontron/sl-mx6ul/spl.c +++ b/board/kontron/sl-mx6ul/spl.c @@ -101,7 +101,7 @@ int board_mmc_init(struct bd_info *bis) /* * According to the board_mmc_init() the following map is done: - * (U-boot device node) (Physical Port) + * (U-Boot device node) (Physical Port) * mmc0 USDHC1 * mmc1 USDHC2 */ diff --git a/board/phytec/pcm058/README b/board/phytec/pcm058/README index 687366bffbd..4b6984cd54f 100644 --- a/board/phytec/pcm058/README +++ b/board/phytec/pcm058/README @@ -37,12 +37,12 @@ not supported. Flashing U-Boot onto an SD card ------------------------------- -After a successful build, the generated SPL and U-boot binaries can be copied +After a successful build, the generated SPL and U-Boot binaries can be copied to an SD card. Adjust the SD card device as necessary: $ sudo dd if=u-boot-with-spl.imx of=/dev/mmcblk0 bs=1k seek=1 -This is equivalent to separately copying the SPL and U-boot using: +This is equivalent to separately copying the SPL and U-Boot using: $ sudo dd if=SPL of=/dev/mmcblk0 bs=1k seek=1 $ sudo dd if=u-boot-dtb.img of=/dev/mmcblk0 bs=1k seek=197 @@ -50,11 +50,11 @@ $ sudo dd if=u-boot-dtb.img of=/dev/mmcblk0 bs=1k seek=197 The default bootscripts expect a kernel fit-image file named "fitImage" in the first partition and Linux ext4 rootfs in the second partition. -Flashing U-boot to the SPI Flash, for booting Linux from NAND +Flashing U-Boot to the SPI Flash, for booting Linux from NAND ------------------------------------------------------------- -The SD card created above can also be used to install the SPL and U-boot into -the SPI flash. Boot U-boot from the SD card as above, and stop at the autoboot. +The SD card created above can also be used to install the SPL and U-Boot into +the SPI flash. Boot U-Boot from the SD card as above, and stop at the autoboot. Then, clear the SPI flash: @@ -64,13 +64,13 @@ Then, clear the SPI flash: Load the equivalent of u-boot-with-spl.imx from the raw MMC into memory and copy to the SPI. The SPL is expected at an offset of 0x400, and its size is maximum 392*512-byte blocks in size, therefore 0x188 blocks, totaling 0x31000 -bytes. Assume U-boot should fit into 640KiB, therefore 0x500 512-byte blocks, +bytes. Assume U-Boot should fit into 640KiB, therefore 0x500 512-byte blocks, totalling 0xA0000 bytes. Adding these together: => mmc read ${loadaddr} 0x2 0x688 => sf write ${loadaddr} 0x400 0xD1000 -The SPL is located at offset 0x400, and U-boot at 0x31400 in SPI flash, as to +The SPL is located at offset 0x400, and U-Boot at 0x31400 in SPI flash, as to match the SD Card layout. This would allow, instead of reading from the SD Card above, with networking and TFTP correctly configured, the equivalent of: @@ -84,7 +84,7 @@ image) and "root" (which contains a ubifs root filesystem). The "bootm_size" variable in the environment -------------------------------------------- -By default, U-boot relocates the device tree towards the upper end of the RAM, +By default, U-Boot relocates the device tree towards the upper end of the RAM, which kernels using CONFIG_HIGHMEM=y may not be able to access during early -boot. With the bootm_size variable set to 0x30000000, U-boot relocates the +boot. With the bootm_size variable set to 0x30000000, U-Boot relocates the device tree to below this address instead. diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c index 4308c7e440a..6cbc89ae787 100644 --- a/board/synopsys/hsdk/hsdk.c +++ b/board/synopsys/hsdk/hsdk.c @@ -583,7 +583,7 @@ enum hsdk_axi_masters { * * Please read ARC HS Development IC Specification, section 17.2 for more * information about apertures configuration. - * NOTE: we intentionally modify default settings in U-boot. Default settings + * NOTE: we intentionally modify default settings in U-Boot. Default settings * are specified in "Table 111 CREG Address Decoder register reset values". */ @@ -942,7 +942,7 @@ static int do_hsdk_go(struct cmd_tbl *cmdtp, int flag, int argc, int ret; if (board_mismatch()) { - printf("ERR: U-boot is not configured for this board!\n"); + printf("ERR: U-Boot is not configured for this board!\n"); return CMD_RET_FAILURE; } @@ -983,10 +983,10 @@ U_BOOT_CMD( /* * We may simply use static variable here to store init status, but we also want - * to avoid the situation when we reload U-boot via MDB after previous + * to avoid the situation when we reload U-Boot via MDB after previous * init is done but HW reset (board reset) isn't done. So let's store the * init status in any unused register (i.e CREG_CPU_0_ENTRY) so status will - * survive after U-boot is reloaded via MDB. + * survive after U-Boot is reloaded via MDB. */ #define INIT_MARKER_REGISTER ((void __iomem *)CREG_CPU_0_ENTRY) /* must be equal to INIT_MARKER_REGISTER reset value */ @@ -1008,7 +1008,7 @@ static int do_hsdk_init(struct cmd_tbl *cmdtp, int flag, int argc, int ret; if (board_mismatch()) { - printf("ERR: U-boot is not configured for this board!\n"); + printf("ERR: U-Boot is not configured for this board!\n"); return CMD_RET_FAILURE; } @@ -1258,11 +1258,11 @@ int checkboard(void) printf("Board: Synopsys %s\n", board_name(get_board_type_runtime())); if (board_mismatch()) - printf("WARN: U-boot is configured NOT for this board but for %s!\n", + printf("WARN: U-Boot is configured NOT for this board but for %s!\n", board_name(get_board_type_config())); reg = readl(CREG_AXI_M_HS_CORE_BOOT) & CREG_CORE_BOOT_IMAGE; - printf("U-boot autostart: %s\n", reg ? "enabled" : "disabled"); + printf("U-Boot autostart: %s\n", reg ? "enabled" : "disabled"); return 0; }; diff --git a/board/xilinx/common/board.h b/board/xilinx/common/board.h index 69e642429b8..922c9d557af 100644 --- a/board/xilinx/common/board.h +++ b/board/xilinx/common/board.h @@ -11,4 +11,11 @@ int board_late_init_xilinx(void); int xilinx_read_eeprom(void); +char *board_name_decode(void); + +bool board_detection(void); + +char *soc_name_decode(void); + +bool soc_detection(void); #endif /* BOARD_XILINX_COMMON_BOARD_H */ diff --git a/board/xilinx/versal-net/Kconfig b/board/xilinx/versal-net/Kconfig index 8f94d2bb399..2484429d3cb 100644 --- a/board/xilinx/versal-net/Kconfig +++ b/board/xilinx/versal-net/Kconfig @@ -6,4 +6,12 @@ if ARCH_VERSAL_NET +config CMD_VERSAL_NET + bool "Enable Versal NET specific commands" + default y + depends on ZYNQMP_FIRMWARE + help + Select this to enable Versal NET specific commands. + Commands like versalnet loadpdi are enabled by this. + endif diff --git a/board/xilinx/versal-net/Makefile b/board/xilinx/versal-net/Makefile index 2008d4e231c..f9ff07c11c6 100644 --- a/board/xilinx/versal-net/Makefile +++ b/board/xilinx/versal-net/Makefile @@ -7,3 +7,4 @@ # obj-y := board.o +obj-$(CONFIG_CMD_VERSAL_NET) += cmds.o diff --git a/board/xilinx/versal-net/board.c b/board/xilinx/versal-net/board.c index 6724c7290f8..a68b608b82c 100644 --- a/board/xilinx/versal-net/board.c +++ b/board/xilinx/versal-net/board.c @@ -10,6 +10,7 @@ #include <cpu_func.h> #include <fdtdec.h> #include <init.h> +#include <env_internal.h> #include <log.h> #include <malloc.h> #include <time.h> @@ -74,32 +75,45 @@ char *soc_name_decode(void) bool soc_detection(void) { - u32 version; + u32 version, ps_version; version = readl(PMC_TAP_VERSION); platform_id = FIELD_GET(PLATFORM_MASK, version); + ps_version = FIELD_GET(PS_VERSION_MASK, version); debug("idcode %x, version %x, usercode %x\n", readl(PMC_TAP_IDCODE), version, readl(PMC_TAP_USERCODE)); - debug("pmc_ver %lx, ps version %lx, rtl version %lx\n", + debug("pmc_ver %lx, ps version %x, rtl version %lx\n", FIELD_GET(PMC_VERSION_MASK, version), - FIELD_GET(PS_VERSION_MASK, version), + ps_version, FIELD_GET(RTL_VERSION_MASK, version)); platform_version = FIELD_GET(PLATFORM_VERSION_MASK, version); if (platform_id == VERSAL_NET_SPP || platform_id == VERSAL_NET_EMU) { - /* - * 9 is diff for - * 0 means 0.9 version - * 1 means 1.0 version - * 2 means 1.1 version - * etc, - */ - platform_version += 9; + if (ps_version == PS_VERSION_PRODUCTION) { + /* + * ES1 version ends at 1.9 version where there was +9 + * used because of IPP/SPP conversion. Production + * version have platform_version started from 0 again + * that's why adding +20 to continue with the same line. + * It means the last ES1 version ends at 1.9 version and + * new PRODUCTION line starts at 2.0. + */ + platform_version += 20; + } else { + /* + * 9 is diff for + * 0 means 0.9 version + * 1 means 1.0 version + * 2 means 1.1 version + * etc, + */ + platform_version += 9; + } } debug("Platform id: %d version: %d.%d\n", platform_id, @@ -165,8 +179,32 @@ int board_early_init_r(void) return 0; } +static u8 versal_net_get_bootmode(void) +{ + u8 bootmode; + u32 reg = 0; + + reg = readl(&crp_base->boot_mode_usr); + + if (reg >> BOOT_MODE_ALT_SHIFT) + reg >>= BOOT_MODE_ALT_SHIFT; + + bootmode = reg & BOOT_MODES_MASK; + + return bootmode; +} + int board_late_init(void) { + u8 bootmode; + struct udevice *dev; + int bootseq = -1; + int bootseq_len = 0; + int env_targets_len = 0; + const char *mode; + char *new_targets; + char *env_targets; + if (!(gd->flags & GD_FLG_ENV_DEFAULT)) { debug("Saved variables - Skipping\n"); return 0; @@ -175,6 +213,95 @@ int board_late_init(void) if (!IS_ENABLED(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)) return 0; + bootmode = versal_net_get_bootmode(); + + puts("Bootmode: "); + switch (bootmode) { + case USB_MODE: + puts("USB_MODE\n"); + mode = "usb_dfu0 usb_dfu1"; + break; + case JTAG_MODE: + puts("JTAG_MODE\n"); + mode = "jtag pxe dhcp"; + break; + case QSPI_MODE_24BIT: + puts("QSPI_MODE_24\n"); + mode = "xspi0"; + break; + case QSPI_MODE_32BIT: + puts("QSPI_MODE_32\n"); + mode = "xspi0"; + break; + case OSPI_MODE: + puts("OSPI_MODE\n"); + mode = "xspi0"; + break; + case EMMC_MODE: + puts("EMMC_MODE\n"); + mode = "mmc"; + bootseq = dev_seq(dev); + break; + case SD_MODE: + puts("SD_MODE\n"); + if (uclass_get_device_by_name(UCLASS_MMC, + "mmc@f1040000", &dev)) { + puts("Boot from SD0 but without SD0 enabled!\n"); + return -1; + } + debug("mmc0 device found at %p, seq %d\n", dev, dev_seq(dev)); + + mode = "mmc"; + bootseq = dev_seq(dev); + break; + case SD1_LSHFT_MODE: + puts("LVL_SHFT_"); + fallthrough; + case SD_MODE1: + puts("SD_MODE1\n"); + if (uclass_get_device_by_name(UCLASS_MMC, + "mmc@f1050000", &dev)) { + puts("Boot from SD1 but without SD1 enabled!\n"); + return -1; + } + debug("mmc1 device found at %p, seq %d\n", dev, dev_seq(dev)); + + mode = "mmc"; + bootseq = dev_seq(dev); + break; + default: + mode = ""; + printf("Invalid Boot Mode:0x%x\n", bootmode); + break; + } + + if (bootseq >= 0) { + bootseq_len = snprintf(NULL, 0, "%i", bootseq); + debug("Bootseq len: %x\n", bootseq_len); + } + + /* + * One terminating char + one byte for space between mode + * and default boot_targets + */ + env_targets = env_get("boot_targets"); + if (env_targets) + env_targets_len = strlen(env_targets); + + new_targets = calloc(1, strlen(mode) + env_targets_len + 2 + + bootseq_len); + if (!new_targets) + return -ENOMEM; + + if (bootseq >= 0) + sprintf(new_targets, "%s%x %s", mode, bootseq, + env_targets ? env_targets : ""); + else + sprintf(new_targets, "%s %s", mode, + env_targets ? env_targets : ""); + + env_set("boot_targets", new_targets); + return board_late_init_xilinx(); } diff --git a/board/xilinx/versal-net/cmds.c b/board/xilinx/versal-net/cmds.c new file mode 100644 index 00000000000..b18a71fe52c --- /dev/null +++ b/board/xilinx/versal-net/cmds.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023, Advanced Micro Devices, Inc. + * + * Michal Simek <michal.simek@amd.com> + */ + +#include <cpu_func.h> +#include <command.h> +#include <common.h> +#include <log.h> +#include <memalign.h> +#include <versalpl.h> +#include <zynqmp_firmware.h> + +/** + * do_versalnet_load_pdi - Handle the "versalnet load pdi" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Processes the Versal NET load pdi command + * + * Return: return 0 on success, Error value if command fails. + * CMD_RET_USAGE incase of incorrect/missing parameters. + */ +static int do_versalnet_load_pdi(struct cmd_tbl *cmdtp, int flag, int argc, + char * const argv[]) +{ + u32 buf_lo, buf_hi; + u32 ret_payload[PAYLOAD_ARG_CNT]; + ulong addr, *pdi_buf; + size_t len; + int ret; + + if (argc != cmdtp->maxargs) { + debug("pdi_load: incorrect parameters passed\n"); + return CMD_RET_USAGE; + } + + addr = simple_strtol(argv[1], NULL, 16); + if (!addr) { + debug("pdi_load: zero pdi_data address\n"); + return CMD_RET_USAGE; + } + + len = hextoul(argv[2], NULL); + if (!len) { + debug("pdi_load: zero size\n"); + return CMD_RET_USAGE; + } + + pdi_buf = (ulong *)ALIGN((ulong)addr, ARCH_DMA_MINALIGN); + if ((ulong)addr != (ulong)pdi_buf) { + memcpy((void *)pdi_buf, (void *)addr, len); + debug("Pdi addr:0x%lx aligned to 0x%lx\n", + addr, (ulong)pdi_buf); + } + + flush_dcache_range((ulong)pdi_buf, (ulong)pdi_buf + len); + + buf_lo = lower_32_bits((ulong)pdi_buf); + buf_hi = upper_32_bits((ulong)pdi_buf); + + ret = xilinx_pm_request(VERSAL_PM_LOAD_PDI, VERSAL_PM_PDI_TYPE, buf_lo, + buf_hi, 0, ret_payload); + if (ret) + printf("PDI load failed with err: 0x%08x\n", ret); + + return cmd_process_error(cmdtp, ret); +} + +static char versalnet_help_text[] = + "loadpdi addr len - Load pdi image\n" + "load pdi image at ddr address 'addr' with pdi image size 'len'\n" +; + +U_BOOT_CMD_WITH_SUBCMDS(versalnet, "Versal NET sub-system", versalnet_help_text, + U_BOOT_SUBCMD_MKENT(loadpdi, 3, 1, + do_versalnet_load_pdi)); diff --git a/board/xilinx/zynqmp/cmds.c b/board/xilinx/zynqmp/cmds.c index e20030ecda7..dd1ad66f90c 100644 --- a/board/xilinx/zynqmp/cmds.c +++ b/board/xilinx/zynqmp/cmds.c @@ -187,6 +187,11 @@ static int do_zynqmp_tcm_init(struct cmd_tbl *cmdtp, int flag, int argc, if (argc != cmdtp->maxargs) return CMD_RET_USAGE; + if (strcmp(argv[2], "lockstep") && strcmp(argv[2], "split")) { + printf("mode param should be lockstep or split\n"); + return CMD_RET_FAILURE; + } + mode = hextoul(argv[2], NULL); if (mode != TCM_LOCK && mode != TCM_SPLIT) { printf("Mode should be either 0(lock)/1(split)\n"); @@ -211,15 +216,24 @@ static int do_zynqmp_pmufw(struct cmd_tbl *cmdtp, int flag, int argc, if (!strncmp(argv[2], "node", 4)) { u32 id; + int ret; if (!strncmp(argv[3], "close", 5)) return zynqmp_pmufw_config_close(); id = dectoul(argv[3], NULL); + if (!id) { + printf("Incorrect ID passed\n"); + return CMD_RET_USAGE; + } printf("Enable permission for node ID %d\n", id); - return zynqmp_pmufw_node(id); + ret = zynqmp_pmufw_node(id); + if (ret == -ENODEV) + ret = 0; + + return ret; } addr = hextoul(argv[2], NULL); @@ -390,17 +404,17 @@ static int do_zynqmp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct cmd_tbl *c; + int ret = CMD_RET_USAGE; if (argc < 2) return CMD_RET_USAGE; c = find_cmd_tbl(argv[1], &cmd_zynqmp_sub[0], ARRAY_SIZE(cmd_zynqmp_sub)); - if (c) - return c->cmd(c, flag, argc, argv); - else - return CMD_RET_USAGE; + ret = c->cmd(c, flag, argc, argv); + + return cmd_process_error(c, ret); } /***************************************************/ @@ -429,7 +443,7 @@ static char zynqmp_help_text[] = " lock(0)/split(1)\n" #endif "zynqmp pmufw address size - load PMU FW configuration object\n" - "zynqmp pmufw node <id> - load PMU FW configuration object\n" + "zynqmp pmufw node <id> - load PMU FW configuration object, <id> in dec\n" "zynqmp pmufw node close - disable config object loading\n" " node: keyword, id: NODE_ID in decimal format\n" "zynqmp rsa srcaddr srclen mod exp rsaop -\n" diff --git a/boot/boot_fit.c b/boot/boot_fit.c index 4a493b36847..9d394126563 100644 --- a/boot/boot_fit.c +++ b/boot/boot_fit.c @@ -67,7 +67,7 @@ void *locate_dtb_in_fit(const void *fit) header = (struct legacy_img_hdr *)fit; if (image_get_magic(header) != FDT_MAGIC) { - debug("No FIT image appended to U-boot\n"); + debug("No FIT image appended to U-Boot\n"); return NULL; } diff --git a/cmd/ufs.c b/cmd/ufs.c index d4a1e66c1bd..143e946370f 100644 --- a/cmd/ufs.c +++ b/cmd/ufs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /** - * ufs.c - UFS specific U-boot commands + * ufs.c - UFS specific U-Boot commands * * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com * diff --git a/common/spl/spl.c b/common/spl/spl.c index 801c4b507ca..d74acec10b5 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -321,7 +321,7 @@ static int spl_load_fit_image(struct spl_image_info *spl_image, spl_image->fdt_addr = (void *)dt_data; if (spl_image->os == IH_OS_U_BOOT) { - /* HACK: U-boot expects FDT at a specific address */ + /* HACK: U-Boot expects FDT at a specific address */ fdt_hack = spl_image->load_addr + spl_image->size; fdt_hack = (fdt_hack + 3) & ~3; debug("Relocating FDT to %p\n", spl_image->fdt_addr); diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index a0722167044..a665091b00f 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -250,7 +250,7 @@ static int mmc_load_image_raw_os(struct spl_image_info *spl_image, return ret; if (spl_image->os != IH_OS_LINUX && spl_image->os != IH_OS_TEE) { - puts("Expected image is not found. Trying to start U-boot\n"); + puts("Expected image is not found. Trying to start U-Boot\n"); return -ENOENT; } diff --git a/doc/README.pcap b/doc/README.pcap index 8e30b93c663..10318ef0a9e 100644 --- a/doc/README.pcap +++ b/doc/README.pcap @@ -1,6 +1,6 @@ PCAP: -U-boot supports live Ethernet packet capture in PCAP(2.4) format. +U-Boot supports live Ethernet packet capture in PCAP(2.4) format. This is enabled by CONFIG_CMD_PCAP. The capture is stored on physical memory, and should be copied to diff --git a/doc/README.s5p4418 b/doc/README.s5p4418 index ac724d08a04..8ec7b05fd26 100644 --- a/doc/README.s5p4418 +++ b/doc/README.s5p4418 @@ -38,7 +38,7 @@ The source code for (the used?) LUbuntu 16.04 can be found at [5]. Links ===== -[1] FriendlyArm U-boot v2016.01: +[1] FriendlyArm U-Boot v2016.01: https://github.com/friendlyarm/u-boot/tree/nanopi2-v2016.01 diff --git a/doc/SPL/README.spl-secure-boot b/doc/SPL/README.spl-secure-boot index f2f8d788837..982fbec654d 100644 --- a/doc/SPL/README.spl-secure-boot +++ b/doc/SPL/README.spl-secure-boot @@ -12,7 +12,7 @@ Methodology The SPL image is responsible for loading the next stage boot loader, which is the main u-boot image. For secure boot process on these platforms ROM verifies -SPL image, so to continue chain of trust SPL image verifies U-boot image using +SPL image, so to continue chain of trust SPL image verifies U-Boot image using spl_validate_uboot(). This function uses QorIQ Trust Architecture header -(appended to U-boot image) to validate the U-boot binary just before passing +(appended to U-Boot image) to validate the U-Boot binary just before passing control to it. diff --git a/doc/board/amlogic/p201.rst b/doc/board/amlogic/p201.rst index 28aae98d990..13b732fc7e4 100644 --- a/doc/board/amlogic/p201.rst +++ b/doc/board/amlogic/p201.rst @@ -56,7 +56,7 @@ image but sources have been shared by Linux development contractor, Baylibre: $ make $ export FIPDIR=$PWD/fip -Go back to mainline U-boot source tree then : +Go back to mainline U-Boot source tree then : .. code-block:: bash diff --git a/doc/board/amlogic/p212.rst b/doc/board/amlogic/p212.rst index c1b73e83b17..a872f32f0f4 100644 --- a/doc/board/amlogic/p212.rst +++ b/doc/board/amlogic/p212.rst @@ -50,7 +50,7 @@ the git tree published by the board vendor: $ make $ export FIPDIR=$PWD/fip -Go back to mainline U-boot source tree then : +Go back to mainline U-Boot source tree then : .. code-block:: bash diff --git a/doc/board/amlogic/s400.rst b/doc/board/amlogic/s400.rst index 59dda823755..205e7c38fa3 100644 --- a/doc/board/amlogic/s400.rst +++ b/doc/board/amlogic/s400.rst @@ -56,7 +56,7 @@ image but sources have been shared by Linux development contractor, Baylibre: $ make $ export FIPDIR=$PWD/fip -Go back to mainline U-boot source tree then : +Go back to mainline U-Boot source tree then : .. code-block:: bash diff --git a/doc/board/emulation/qemu-arm.rst b/doc/board/emulation/qemu-arm.rst index 16f66388eb1..b42d924cc66 100644 --- a/doc/board/emulation/qemu-arm.rst +++ b/doc/board/emulation/qemu-arm.rst @@ -54,7 +54,7 @@ Note that for some odd reason qemu-system-aarch64 needs to be explicitly told to use a 64-bit CPU or it will boot in 32-bit mode. The -nographic argument ensures that output appears on the terminal. Use Ctrl-A X to quit. -Additional persistent U-boot environment support can be added as follows: +Additional persistent U-Boot environment support can be added as follows: - Create envstore.img using qemu-img:: diff --git a/doc/board/nxp/ls1046ardb.rst b/doc/board/nxp/ls1046ardb.rst index 35465d00612..49b4842b306 100644 --- a/doc/board/nxp/ls1046ardb.rst +++ b/doc/board/nxp/ls1046ardb.rst @@ -150,7 +150,7 @@ Then, launch openocd like:: openocd -f u-boot.tcl -You should see the U-boot SPL banner followed by the banner for U-Boot proper +You should see the U-Boot SPL banner followed by the banner for U-Boot proper in the output of openocd. The CMSIS-DAP adapter is slow, so this can take a long time. If you don't see it, something has gone wrong. After a while, you should see the prompt. You can load an image using semihosting by running:: diff --git a/doc/board/nxp/mx6sabresd.rst b/doc/board/nxp/mx6sabresd.rst index fe15ba7b798..c9869f4a73a 100644 --- a/doc/board/nxp/mx6sabresd.rst +++ b/doc/board/nxp/mx6sabresd.rst @@ -53,7 +53,7 @@ This will generate the SPL and u-boot-dtb.img binaries. - Boot first from SD card as shown in the previous section -In U-boot change the eMMC partition config:: +In U-Boot change the eMMC partition config:: => mmc partconf 2 1 0 0 diff --git a/doc/board/rockchip/rockchip.rst b/doc/board/rockchip/rockchip.rst index 99376fb54c9..4c555e1c9c1 100644 --- a/doc/board/rockchip/rockchip.rst +++ b/doc/board/rockchip/rockchip.rst @@ -333,12 +333,12 @@ Note: Unlike later SoC models the rk3066 BootROM doesn't have SDMMC support. If all other boot options fail then it enters into a BootROM mode on the USB OTG port. -This method loads TPL/SPL on NAND with U-boot and kernel on SD card. +This method loads TPL/SPL on NAND with U-Boot and kernel on SD card. SD Card ^^^^^^^ -U-boot expects a GPT partition map and a boot directory structure with files on the SD card. +U-Boot expects a GPT partition map and a boot directory structure with files on the SD card. .. code-block:: none @@ -363,7 +363,7 @@ Boot partition: zImage rk3066a-mk808.dtb -To write a U-boot image to the SD card (assumed to be /dev/sda): +To write a U-Boot image to the SD card (assumed to be /dev/sda): .. code-block:: bash diff --git a/doc/board/sifive/unmatched.rst b/doc/board/sifive/unmatched.rst index de2aab59bb1..c515949066f 100644 --- a/doc/board/sifive/unmatched.rst +++ b/doc/board/sifive/unmatched.rst @@ -558,7 +558,7 @@ for partitions one through three respectively. --new=3:10280:10535 --change-name=3:env --typecode=3:3DE21764-95BD-54BD-A5C3-4ABE786F38A8 \ /dev/mtdblock0 -Write U-boot SPL and U-boot to their partitions. +Write U-Boot SPL and U-Boot to their partitions. .. code-block:: none diff --git a/doc/board/st/stm32mp1.rst b/doc/board/st/stm32mp1.rst index c0b1daa0418..63b44776ffc 100644 --- a/doc/board/st/stm32mp1.rst +++ b/doc/board/st/stm32mp1.rst @@ -345,7 +345,7 @@ Build Procedure - BL33=u-boot-nodtb.bin - BL33_CFG=u-boot.dtb - You can also update a existing FIP after U-boot compilation with fiptool, + You can also update a existing FIP after U-Boot compilation with fiptool, a tool provided by TF-A_:: # fiptool update --nt-fw u-boot-nodtb.bin --hw-config u-boot.dtb fip-stm32mp157c-ev1.bin diff --git a/doc/board/xen/xenguest_arm64.rst b/doc/board/xen/xenguest_arm64.rst index 1327f88f990..e9bdaf7ffb2 100644 --- a/doc/board/xen/xenguest_arm64.rst +++ b/doc/board/xen/xenguest_arm64.rst @@ -6,7 +6,7 @@ Xen guest ARM64 board This board specification ------------------------ -This board is to be run as a virtual Xen [1] guest with U-boot as its primary +This board is to be run as a virtual Xen [1] guest with U-Boot as its primary bootloader. Xen is a type 1 hypervisor that allows multiple operating systems to run simultaneously on a single physical server. Xen is capable of running virtual machines in both full virtualization and para-virtualization (PV) @@ -16,7 +16,7 @@ Paravirtualized drivers are a special type of device drivers that are used in a guest system in the Xen domain and perform I/O operations using a special interface provided by the virtualization system and the host system. -Xen support for U-boot is implemented by introducing a new Xen guest ARM64 +Xen support for U-Boot is implemented by introducing a new Xen guest ARM64 board and porting essential drivers from MiniOS [3] as well as some of the work previously done by NXP [4]: @@ -39,7 +39,7 @@ previously done by NXP [4]: Board limitations ----------------- -1. U-boot runs without MMU enabled at the early stages. +1. U-Boot runs without MMU enabled at the early stages. According to Xen on ARM ABI (xen/include/public/arch-arm.h): all memory which is shared with other entities in the system (including the hypervisor and other guests) must reside in memory which is mapped as Normal Inner @@ -54,14 +54,14 @@ Board limitations 2. No serial console until MMU is up. Because data cache maintenance is required until the MMU setup the early/debug serial console is not implemented. Therefore, we do not have - usual prints like U-boot’s banner etc. until the serial driver is + usual prints like U-Boot’s banner etc. until the serial driver is initialized. 3. Single RAM bank supported. If a Xen guest is given much memory it is possible that Xen allocates two memory banks for it. The first one is allocated under 4GB address space and in some cases may represent the whole guest’s memory. It is assumed that - U-boot most likely won’t require high memory bank for its work andlaunching + U-Boot most likely won’t require high memory bank for its work andlaunching OS, so it is enough to take the first one. diff --git a/doc/develop/driver-model/bind.rst b/doc/develop/driver-model/bind.rst index b19661b5fe2..0d0d40734c9 100644 --- a/doc/develop/driver-model/bind.rst +++ b/doc/develop/driver-model/bind.rst @@ -7,7 +7,7 @@ Binding/unbinding a driver This document aims to describe the bind and unbind commands. For debugging purpose, it should be useful to bind or unbind a driver from -the U-boot command line. +the U-Boot command line. The unbind command calls the remove device driver callback and unbind the device from its driver. diff --git a/doc/develop/driver-model/fs_firmware_loader.rst b/doc/develop/driver-model/fs_firmware_loader.rst index b0823700a90..149b8b436ec 100644 --- a/doc/develop/driver-model/fs_firmware_loader.rst +++ b/doc/develop/driver-model/fs_firmware_loader.rst @@ -92,9 +92,9 @@ For example of getting DT phandle from /chosen and creating instance: if (ret) return ret; -Firmware loader driver is also designed to support U-boot environment +Firmware loader driver is also designed to support U-Boot environment variables, so all these data from FDT can be overwritten -through the U-boot environment variable during run time. +through the U-Boot environment variable during run time. For examples: @@ -110,7 +110,7 @@ fw_ubi_volume: When above environment variables are set, environment values would be used instead of data from FDT. The benefit of this design allows user to change storage attribute data -at run time through U-boot console and saving the setting as default +at run time through U-Boot console and saving the setting as default environment values in the storage for the next power cycle, so no compilation is required for both driver and FDT. diff --git a/doc/develop/uefi/uefi.rst b/doc/develop/uefi/uefi.rst index ffd13cebe98..6626ceec52b 100644 --- a/doc/develop/uefi/uefi.rst +++ b/doc/develop/uefi/uefi.rst @@ -357,7 +357,7 @@ bit in OsIndications variable with => setenv -e -nv -bs -rt -v OsIndications =0x0000000000000004 -Since U-boot doesn't currently support SetVariable at runtime, its value +Since U-Boot doesn't currently support SetVariable at runtime, its value won't be taken over across the reboot. If this is the case, you can skip this feature check with the Kconfig option (CONFIG_EFI_IGNORE_OSINDICATIONS) set. diff --git a/doc/usage/cmd/source.rst b/doc/usage/cmd/source.rst index 61a45059096..a5c5204a28b 100644 --- a/doc/usage/cmd/source.rst +++ b/doc/usage/cmd/source.rst @@ -161,7 +161,7 @@ The boot scripts (boot.scr) is created with: mkimage -T script -n 'Test script' -d boot.txt boot.scr -The script can be execute in U-boot like this: +The script can be execute in U-Boot like this: .. code-block:: diff --git a/doc/usage/dfu.rst b/doc/usage/dfu.rst index ed47ff561e3..68cacbbef66 100644 --- a/doc/usage/dfu.rst +++ b/doc/usage/dfu.rst @@ -9,7 +9,7 @@ Overview The Device Firmware Upgrade (DFU) allows to download and upload firmware to/from U-Boot connected over USB. -U-boot follows the Universal Serial Bus Device Class Specification for +U-Boot follows the Universal Serial Bus Device Class Specification for Device Firmware Upgrade Version 1.1 the USB forum (DFU v1.1 in www.usb.org). U-Boot implements this DFU capability (CONFIG_DFU) with the command dfu diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 184d426d0b3..017f25f7a5a 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -184,7 +184,7 @@ struct clk *clk_hw_register_mux_table(struct device *dev, const char *name, if (!mux) return ERR_PTR(-ENOMEM); - /* U-boot specific assignments */ + /* U-Boot specific assignments */ mux->parent_names = parent_names; mux->num_parents = num_parents; diff --git a/drivers/clk/clk_zynqmp.c b/drivers/clk/clk_zynqmp.c index 45c679a627b..be0ee50e0e4 100644 --- a/drivers/clk/clk_zynqmp.c +++ b/drivers/clk/clk_zynqmp.c @@ -691,6 +691,7 @@ static ulong zynqmp_clk_get_rate(struct clk *clk) case topsw_lsbus: case sata_ref ... gpu_pp1_ref: two_divs = true; + fallthrough; case cpu_r5: case dbg_fpd: case ams_ref: diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index dc8e3ad2b9d..ab4c4f1a690 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -23,10 +23,10 @@ #define XST_PM_NO_ACCESS 2002L #define XST_PM_ALREADY_CONFIGURED 2009L -struct zynqmp_power { +static struct zynqmp_power { struct mbox_chan tx_chan; struct mbox_chan rx_chan; -} zynqmp_power = {}; +} zynqmp_power __section(".data"); #define NODE_ID_LOCATION 5 @@ -63,29 +63,32 @@ static unsigned int xpm_configobject_close[] = { int zynqmp_pmufw_config_close(void) { - zynqmp_pmufw_load_config_object(xpm_configobject_close, - sizeof(xpm_configobject_close)); - return 0; + return zynqmp_pmufw_load_config_object(xpm_configobject_close, + sizeof(xpm_configobject_close)); } int zynqmp_pmufw_node(u32 id) { - static bool skip_config; - int ret; + static bool check = true; + static bool permission = true; + + if (check) { + check = false; + + if (zynqmp_pmufw_node(NODE_OCM_BANK_0) == -EACCES) { + printf("PMUFW: No permission to change config object\n"); + permission = false; + } + } - if (skip_config) + if (!permission) return 0; /* Record power domain id */ xpm_configobject[NODE_ID_LOCATION] = id; - ret = zynqmp_pmufw_load_config_object(xpm_configobject, - sizeof(xpm_configobject)); - - if (ret == XST_PM_NO_ACCESS && id == NODE_OCM_BANK_0) - skip_config = true; - - return 0; + return zynqmp_pmufw_load_config_object(xpm_configobject, + sizeof(xpm_configobject)); } static int do_pm_probe(void) @@ -235,8 +238,7 @@ int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id) * * @cfg_obj: Pointer to the configuration object * @size: Size of @cfg_obj in bytes - * Return: 0 on success otherwise negative errno. If the config object - * is not loadable returns positive errno XST_PM_NO_ACCESS(2002) + * Return: 0 on success otherwise negative errno. */ int zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size) { @@ -251,10 +253,6 @@ int zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size) err = xilinx_pm_request(PM_SET_CONFIGURATION, (u32)(u64)cfg_obj, 0, 0, 0, ret_payload); if (err == XST_PM_NO_ACCESS) { - if (((u32 *)cfg_obj)[NODE_ID_LOCATION] == NODE_OCM_BANK_0) { - printf("PMUFW: No permission to change config object\n"); - return err; - } return -EACCES; } @@ -298,9 +296,6 @@ static int zynqmp_power_probe(struct udevice *dev) ret >> ZYNQMP_PM_VERSION_MAJOR_SHIFT, ret & ZYNQMP_PM_VERSION_MINOR_MASK); - if (IS_ENABLED(CONFIG_ARCH_ZYNQMP)) - zynqmp_pmufw_node(NODE_OCM_BANK_0); - return 0; }; @@ -320,7 +315,8 @@ U_BOOT_DRIVER(zynqmp_power) = { int __maybe_unused xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 *ret_payload) { - debug("%s at EL%d, API ID: 0x%0x\n", __func__, current_el(), api_id); + debug("%s at EL%d, API ID: 0x%0x, 0x%0x, 0x%0x, 0x%0x, 0x%0x\n", + __func__, current_el(), api_id, arg0, arg1, arg2, arg3); if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) { #if defined(CONFIG_ZYNQMP_IPI) @@ -398,7 +394,7 @@ static int zynqmp_firmware_bind(struct udevice *dev) } } - return dm_scan_fdt_dev(dev); + return 0; } U_BOOT_DRIVER(zynqmp_firmware) = { diff --git a/drivers/gpio/gpio-fxl6408.c b/drivers/gpio/gpio-fxl6408.c index 902da050fbf..ca7aa14eeb2 100644 --- a/drivers/gpio/gpio-fxl6408.c +++ b/drivers/gpio/gpio-fxl6408.c @@ -27,7 +27,7 @@ * https://patchwork.kernel.org/patch/9148419/ * - the Toradex version by Max Krummenacher <max.krummenacher@toradex.com>: * http://git.toradex.com/cgit/linux-toradex.git/tree/drivers/gpio/gpio-fxl6408.c?h=toradex_5.4-2.3.x-imx - * - the U-boot PCA953x driver by Peng Fan <van.freenix@gmail.com>: + * - the U-Boot PCA953x driver by Peng Fan <van.freenix@gmail.com>: * drivers/gpio/pca953x_gpio.c * * TODO: diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index e44868aaec5..e779251ce34 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -873,7 +873,7 @@ static int arasan_sdhci_set_tapdelay(struct sdhci_host *host) if (ret) return ret; } else if (IS_ENABLED(CONFIG_ARCH_VERSAL_NET) && - device_is_compatible(dev, "xlnx,versal-net-5.1-emmc")) { + device_is_compatible(dev, "xlnx,versal-net-emmc")) { if (mmc->clock >= MIN_PHY_CLK_HZ) if (iclk_phase == VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLY_CHAIN) iclk_phase = VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLL; @@ -948,7 +948,7 @@ static void arasan_dt_parse_clk_phases(struct udevice *dev) } if (IS_ENABLED(CONFIG_ARCH_VERSAL_NET) && - device_is_compatible(dev, "xlnx,versal-net-5.1-emmc")) { + device_is_compatible(dev, "xlnx,versal-net-emmc")) { for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) { clk_data->clk_phase_in[i] = versal_net_emmc_iclk_phases[i]; clk_data->clk_phase_out[i] = versal_net_emmc_oclk_phases[i]; @@ -1102,7 +1102,7 @@ static int arasan_sdhci_probe(struct udevice *dev) } } #endif - if (device_is_compatible(dev, "xlnx,versal-net-5.1-emmc")) + if (device_is_compatible(dev, "xlnx,versal-net-emmc")) priv->internal_phy_reg = true; ret = clk_get_by_index(dev, 0, &clk); @@ -1136,7 +1136,7 @@ static int arasan_sdhci_probe(struct udevice *dev) host->quirks |= SDHCI_QUIRK_NO_1_8_V; if (CONFIG_IS_ENABLED(ARCH_VERSAL_NET) && - device_is_compatible(dev, "xlnx,versal-net-5.1-emmc")) + device_is_compatible(dev, "xlnx,versal-net-emmc")) host->quirks |= SDHCI_QUIRK_CAPS_BIT63_FOR_HS400; plat->cfg.f_max = CONFIG_ZYNQ_SDHCI_MAX_FREQ; @@ -1219,7 +1219,7 @@ static int arasan_sdhci_bind(struct udevice *dev) static const struct udevice_id arasan_sdhci_ids[] = { { .compatible = "arasan,sdhci-8.9a" }, - { .compatible = "xlnx,versal-net-5.1-emmc" }, + { .compatible = "xlnx,versal-net-emmc" }, { } }; diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index d115fcf841f..d624589a892 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -553,7 +553,7 @@ config NAND_ZYNQ_USE_BOOTLOADER1_TIMINGS bool "Enable use of 1st stage bootloader timing for NAND" depends on NAND_ZYNQ help - This flag prevent U-boot reconfigure NAND flash controller and reuse + This flag prevent U-Boot reconfigure NAND flash controller and reuse the NAND timing from 1st stage bootloader. config NAND_OCTEONTX @@ -732,10 +732,10 @@ config SYS_NAND_BAD_BLOCK_POS default 5 if HAS_NAND_SMALL_BADBLOCK_POS config SYS_NAND_U_BOOT_LOCATIONS - bool "Define U-boot binaries locations in NAND" + bool "Define U-Boot binaries locations in NAND" help Enable CONFIG_SYS_NAND_U_BOOT_OFFS though Kconfig. - This option should not be enabled when compiling U-boot for boards + This option should not be enabled when compiling U-Boot for boards defining CONFIG_SYS_NAND_U_BOOT_OFFS in their include/configs/<board>.h file. diff --git a/drivers/mtd/nand/raw/fsl_ifc_spl.c b/drivers/mtd/nand/raw/fsl_ifc_spl.c index 60a865b5667..c67065eaf8c 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_spl.c +++ b/drivers/mtd/nand/raw/fsl_ifc_spl.c @@ -275,8 +275,8 @@ void nand_boot(void) #ifdef CONFIG_CHAIN_OF_TRUST /* - * U-Boot header is appended at end of U-boot image, so - * calculate U-boot header address using U-boot header size. + * U-Boot header is appended at end of U-Boot image, so + * calculate U-Boot header address using U-Boot header size. */ #define FSL_U_BOOT_HDR_ADDR \ ((CFG_SYS_NAND_U_BOOT_START + \ diff --git a/drivers/net/pfe_eth/pfe_hw.c b/drivers/net/pfe_eth/pfe_hw.c index 4db6f3158c3..9f2f92d116d 100644 --- a/drivers/net/pfe_eth/pfe_hw.c +++ b/drivers/net/pfe_eth/pfe_hw.c @@ -814,7 +814,7 @@ static inline void class_set_config(struct class_cfg *cfg) writel(0x1, CLASS_AXI_CTRL); /*Make Util AXI transactions non-bufferable */ - /*Util is disabled in U-boot, do it from here */ + /*Util is disabled in U-Boot, do it from here */ writel(0x1, UTIL_AXI_CTRL); } diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index ef328d26525..60d98d14640 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -374,4 +374,11 @@ config PCIE_UNIPHIER Say Y here if you want to enable PCIe controller support on UniPhier SoCs. +config PCIE_XILINX_NWL + bool "Xilinx NWL PCIe controller" + depends on ARCH_ZYNQMP + help + Say 'Y' here if you want support for Xilinx / AMD NWL PCIe + controller as Root Port. + endif diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 49506e7ba59..11f60c6991d 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -49,3 +49,4 @@ obj-$(CONFIG_PCI_OCTEONTX) += pci_octeontx.o obj-$(CONFIG_PCIE_OCTEON) += pcie_octeon.o obj-$(CONFIG_PCIE_DW_SIFIVE) += pcie_dw_sifive.o obj-$(CONFIG_PCIE_UNIPHIER) += pcie_uniphier.o +obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o diff --git a/drivers/pci/pcie-xilinx-nwl.c b/drivers/pci/pcie-xilinx-nwl.c new file mode 100644 index 00000000000..7ef2bdf57b5 --- /dev/null +++ b/drivers/pci/pcie-xilinx-nwl.c @@ -0,0 +1,352 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PCIe host bridge driver for Xilinx / AMD ZynqMP NWL PCIe Bridge + * + * Based on the Linux driver which is: + * (C) Copyright 2014 - 2015, Xilinx, Inc. + * + * Author: Stefan Roese <sr@denx.de> + */ + +#include <clk.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <dm/devres.h> +#include <mapmem.h> +#include <pci.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/ioport.h> + +/* Bridge core config registers */ +#define BRCFG_PCIE_RX0 0x00000000 +#define BRCFG_PCIE_RX1 0x00000004 +#define BRCFG_INTERRUPT 0x00000010 +#define BRCFG_PCIE_RX_MSG_FILTER 0x00000020 + +/* Egress - Bridge translation registers */ +#define E_BREG_CAPABILITIES 0x00000200 +#define E_BREG_CONTROL 0x00000208 +#define E_BREG_BASE_LO 0x00000210 +#define E_BREG_BASE_HI 0x00000214 +#define E_ECAM_CAPABILITIES 0x00000220 +#define E_ECAM_CONTROL 0x00000228 +#define E_ECAM_BASE_LO 0x00000230 +#define E_ECAM_BASE_HI 0x00000234 + +#define I_ISUB_CONTROL 0x000003E8 +#define SET_ISUB_CONTROL BIT(0) +/* Rxed msg fifo - Interrupt status registers */ +#define MSGF_MISC_STATUS 0x00000400 +#define MSGF_MISC_MASK 0x00000404 +#define MSGF_LEG_STATUS 0x00000420 +#define MSGF_LEG_MASK 0x00000424 +#define MSGF_MSI_STATUS_LO 0x00000440 +#define MSGF_MSI_STATUS_HI 0x00000444 +#define MSGF_MSI_MASK_LO 0x00000448 +#define MSGF_MSI_MASK_HI 0x0000044C + +/* Msg filter mask bits */ +#define CFG_ENABLE_PM_MSG_FWD BIT(1) +#define CFG_ENABLE_INT_MSG_FWD BIT(2) +#define CFG_ENABLE_ERR_MSG_FWD BIT(3) +#define CFG_ENABLE_MSG_FILTER_MASK (CFG_ENABLE_PM_MSG_FWD | \ + CFG_ENABLE_INT_MSG_FWD | \ + CFG_ENABLE_ERR_MSG_FWD) + +/* Misc interrupt status mask bits */ +#define MSGF_MISC_SR_RXMSG_AVAIL BIT(0) +#define MSGF_MISC_SR_RXMSG_OVER BIT(1) +#define MSGF_MISC_SR_SLAVE_ERR BIT(4) +#define MSGF_MISC_SR_MASTER_ERR BIT(5) +#define MSGF_MISC_SR_I_ADDR_ERR BIT(6) +#define MSGF_MISC_SR_E_ADDR_ERR BIT(7) +#define MSGF_MISC_SR_FATAL_AER BIT(16) +#define MSGF_MISC_SR_NON_FATAL_AER BIT(17) +#define MSGF_MISC_SR_CORR_AER BIT(18) +#define MSGF_MISC_SR_UR_DETECT BIT(20) +#define MSGF_MISC_SR_NON_FATAL_DEV BIT(22) +#define MSGF_MISC_SR_FATAL_DEV BIT(23) +#define MSGF_MISC_SR_LINK_DOWN BIT(24) +#define MSGF_MSIC_SR_LINK_AUTO_BWIDTH BIT(25) +#define MSGF_MSIC_SR_LINK_BWIDTH BIT(26) + +#define MSGF_MISC_SR_MASKALL (MSGF_MISC_SR_RXMSG_AVAIL | \ + MSGF_MISC_SR_RXMSG_OVER | \ + MSGF_MISC_SR_SLAVE_ERR | \ + MSGF_MISC_SR_MASTER_ERR | \ + MSGF_MISC_SR_I_ADDR_ERR | \ + MSGF_MISC_SR_E_ADDR_ERR | \ + MSGF_MISC_SR_FATAL_AER | \ + MSGF_MISC_SR_NON_FATAL_AER | \ + MSGF_MISC_SR_CORR_AER | \ + MSGF_MISC_SR_UR_DETECT | \ + MSGF_MISC_SR_NON_FATAL_DEV | \ + MSGF_MISC_SR_FATAL_DEV | \ + MSGF_MISC_SR_LINK_DOWN | \ + MSGF_MSIC_SR_LINK_AUTO_BWIDTH | \ + MSGF_MSIC_SR_LINK_BWIDTH) + +/* Legacy interrupt status mask bits */ +#define MSGF_LEG_SR_INTA BIT(0) +#define MSGF_LEG_SR_INTB BIT(1) +#define MSGF_LEG_SR_INTC BIT(2) +#define MSGF_LEG_SR_INTD BIT(3) +#define MSGF_LEG_SR_MASKALL (MSGF_LEG_SR_INTA | MSGF_LEG_SR_INTB | \ + MSGF_LEG_SR_INTC | MSGF_LEG_SR_INTD) + +/* MSI interrupt status mask bits */ +#define MSGF_MSI_SR_LO_MASK GENMASK(31, 0) +#define MSGF_MSI_SR_HI_MASK GENMASK(31, 0) + +/* Bridge config interrupt mask */ +#define BRCFG_INTERRUPT_MASK BIT(0) +#define BREG_PRESENT BIT(0) +#define BREG_ENABLE BIT(0) +#define BREG_ENABLE_FORCE BIT(1) + +/* E_ECAM status mask bits */ +#define E_ECAM_PRESENT BIT(0) +#define E_ECAM_CR_ENABLE BIT(0) +#define E_ECAM_SIZE_LOC GENMASK(20, 16) +#define E_ECAM_SIZE_SHIFT 16 +#define NWL_ECAM_VALUE_DEFAULT 12 + +#define CFG_DMA_REG_BAR GENMASK(2, 0) +#define CFG_PCIE_CACHE GENMASK(7, 0) + +/* Readin the PS_LINKUP */ +#define PS_LINKUP_OFFSET 0x00000238 +#define PCIE_PHY_LINKUP_BIT BIT(0) +#define PHY_RDY_LINKUP_BIT BIT(1) + +/* Parameters for the waiting for link up routine */ +#define LINK_WAIT_MAX_RETRIES 10 +#define LINK_WAIT_USLEEP_MIN 90000 +#define LINK_WAIT_USLEEP_MAX 100000 + +struct nwl_pcie { + struct udevice *dev; + void __iomem *breg_base; + void __iomem *pcireg_base; + void __iomem *ecam_base; + phys_addr_t phys_breg_base; /* Physical Bridge Register Base */ + phys_addr_t phys_ecam_base; /* Physical Configuration Base */ + u32 ecam_value; +}; + +static int nwl_pcie_config_address(const struct udevice *bus, + pci_dev_t bdf, uint offset, + void **paddress) +{ + struct nwl_pcie *pcie = dev_get_priv(bus); + void *addr; + + addr = pcie->ecam_base; + addr += PCIE_ECAM_OFFSET(PCI_BUS(bdf) - dev_seq(bus), + PCI_DEV(bdf), PCI_FUNC(bdf), offset); + *paddress = addr; + + return 0; +} + +static int nwl_pcie_read_config(const struct udevice *bus, pci_dev_t bdf, + uint offset, ulong *valuep, + enum pci_size_t size) +{ + return pci_generic_mmap_read_config(bus, nwl_pcie_config_address, + bdf, offset, valuep, size); +} + +static int nwl_pcie_write_config(struct udevice *bus, pci_dev_t bdf, + uint offset, ulong value, + enum pci_size_t size) +{ + return pci_generic_mmap_write_config(bus, nwl_pcie_config_address, + bdf, offset, value, size); +} + +static const struct dm_pci_ops nwl_pcie_ops = { + .read_config = nwl_pcie_read_config, + .write_config = nwl_pcie_write_config, +}; + +static inline u32 nwl_bridge_readl(struct nwl_pcie *pcie, u32 off) +{ + return readl(pcie->breg_base + off); +} + +static inline void nwl_bridge_writel(struct nwl_pcie *pcie, u32 val, u32 off) +{ + writel(val, pcie->breg_base + off); +} + +static bool nwl_pcie_link_up(struct nwl_pcie *pcie) +{ + if (readl(pcie->pcireg_base + PS_LINKUP_OFFSET) & PCIE_PHY_LINKUP_BIT) + return true; + return false; +} + +static bool nwl_phy_link_up(struct nwl_pcie *pcie) +{ + if (readl(pcie->pcireg_base + PS_LINKUP_OFFSET) & PHY_RDY_LINKUP_BIT) + return true; + return false; +} + +static int nwl_wait_for_link(struct nwl_pcie *pcie) +{ + struct udevice *dev = pcie->dev; + int retries; + + /* check if the link is up or not */ + for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) { + if (nwl_phy_link_up(pcie)) + return 0; + udelay(LINK_WAIT_USLEEP_MIN); + } + + dev_warn(dev, "PHY link never came up\n"); + return -ETIMEDOUT; +} + +static int nwl_pcie_bridge_init(struct nwl_pcie *pcie) +{ + struct udevice *dev = pcie->dev; + u32 breg_val, ecam_val; + int err; + + breg_val = nwl_bridge_readl(pcie, E_BREG_CAPABILITIES) & BREG_PRESENT; + if (!breg_val) { + dev_err(dev, "BREG is not present\n"); + return breg_val; + } + + /* Write bridge_off to breg base */ + nwl_bridge_writel(pcie, lower_32_bits(pcie->phys_breg_base), + E_BREG_BASE_LO); + nwl_bridge_writel(pcie, upper_32_bits(pcie->phys_breg_base), + E_BREG_BASE_HI); + + /* Enable BREG */ + nwl_bridge_writel(pcie, ~BREG_ENABLE_FORCE & BREG_ENABLE, + E_BREG_CONTROL); + + /* Disable DMA channel registers */ + nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, BRCFG_PCIE_RX0) | + CFG_DMA_REG_BAR, BRCFG_PCIE_RX0); + + /* Enable Ingress subtractive decode translation */ + nwl_bridge_writel(pcie, SET_ISUB_CONTROL, I_ISUB_CONTROL); + + /* Enable msg filtering details */ + nwl_bridge_writel(pcie, CFG_ENABLE_MSG_FILTER_MASK, + BRCFG_PCIE_RX_MSG_FILTER); + + err = nwl_wait_for_link(pcie); + if (err) + return err; + + ecam_val = nwl_bridge_readl(pcie, E_ECAM_CAPABILITIES) & E_ECAM_PRESENT; + if (!ecam_val) { + dev_err(dev, "ECAM is not present\n"); + return ecam_val; + } + + /* Enable ECAM */ + nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, E_ECAM_CONTROL) | + E_ECAM_CR_ENABLE, E_ECAM_CONTROL); + + nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, E_ECAM_CONTROL) | + (pcie->ecam_value << E_ECAM_SIZE_SHIFT), + E_ECAM_CONTROL); + + nwl_bridge_writel(pcie, lower_32_bits(pcie->phys_ecam_base), + E_ECAM_BASE_LO); + nwl_bridge_writel(pcie, upper_32_bits(pcie->phys_ecam_base), + E_ECAM_BASE_HI); + + if (nwl_pcie_link_up(pcie)) + dev_info(dev, "Link is UP\n"); + else + dev_info(dev, "Link is DOWN\n"); + + /* Disable all misc interrupts */ + nwl_bridge_writel(pcie, (u32)~MSGF_MISC_SR_MASKALL, MSGF_MISC_MASK); + + /* Clear pending misc interrupts */ + nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, MSGF_MISC_STATUS) & + MSGF_MISC_SR_MASKALL, MSGF_MISC_STATUS); + + /* Disable all legacy interrupts */ + nwl_bridge_writel(pcie, (u32)~MSGF_LEG_SR_MASKALL, MSGF_LEG_MASK); + + /* Clear pending legacy interrupts */ + nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, MSGF_LEG_STATUS) & + MSGF_LEG_SR_MASKALL, MSGF_LEG_STATUS); + + return 0; +} + +static int nwl_pcie_parse_dt(struct nwl_pcie *pcie) +{ + struct udevice *dev = pcie->dev; + struct resource res; + int ret; + + ret = dev_read_resource_byname(dev, "breg", &res); + if (ret) + return ret; + pcie->breg_base = devm_ioremap(dev, res.start, resource_size(&res)); + if (IS_ERR(pcie->breg_base)) + return PTR_ERR(pcie->breg_base); + pcie->phys_breg_base = res.start; + + ret = dev_read_resource_byname(dev, "cfg", &res); + if (ret) + return ret; + pcie->ecam_base = devm_ioremap(dev, res.start, resource_size(&res)); + if (IS_ERR(pcie->ecam_base)) + return PTR_ERR(pcie->ecam_base); + pcie->phys_ecam_base = res.start; + + return 0; +} + +static int nwl_pcie_probe(struct udevice *dev) +{ + struct nwl_pcie *pcie = dev_get_priv(dev); + int err; + + pcie->dev = dev; + pcie->ecam_value = NWL_ECAM_VALUE_DEFAULT; + + err = nwl_pcie_parse_dt(pcie); + if (err) { + dev_err(dev, "Parsing DT failed\n"); + return err; + } + + err = nwl_pcie_bridge_init(pcie); + if (err) { + dev_err(dev, "HW Initialization failed\n"); + return err; + } + + return 0; +} + +static const struct udevice_id nwl_pcie_of_match[] = { + { .compatible = "xlnx,nwl-pcie-2.11", }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(nwl_pcie) = { + .name = "nwl-pcie", + .id = UCLASS_PCI, + .of_match = nwl_pcie_of_match, + .probe = nwl_pcie_probe, + .priv_auto = sizeof(struct nwl_pcie), + .ops = &nwl_pcie_ops, +}; diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c index e063b51c6dd..a7e0099045f 100644 --- a/drivers/phy/marvell/comphy_cp110.c +++ b/drivers/phy/marvell/comphy_cp110.c @@ -25,7 +25,7 @@ DECLARE_GLOBAL_DATA_PTR; #define MV_SIP_COMPHY_PLL_LOCK 0x82000003 #define MV_SIP_COMPHY_XFI_TRAIN 0x82000004 -/* Used to distinguish between different possible callers (U-boot/Linux) */ +/* Used to distinguish between different possible callers (U-Boot/Linux) */ #define COMPHY_CALLER_UBOOT (0x1 << 21) #define COMPHY_FW_MODE_FORMAT(mode) ((mode) << 12) diff --git a/drivers/power/domain/zynqmp-power-domain.c b/drivers/power/domain/zynqmp-power-domain.c index adbbb5fdd93..5ee9e020fb3 100644 --- a/drivers/power/domain/zynqmp-power-domain.c +++ b/drivers/power/domain/zynqmp-power-domain.c @@ -23,12 +23,17 @@ static int zynqmp_pm_request_node(const u32 node, const u32 capabilities, static int zynqmp_power_domain_request(struct power_domain *power_domain) { + int ret = 0; + dev_dbg(power_domain->dev, "Request for id: %ld\n", power_domain->id); - if (IS_ENABLED(CONFIG_ARCH_ZYNQMP)) - return zynqmp_pmufw_node(power_domain->id); + if (IS_ENABLED(CONFIG_ARCH_ZYNQMP)) { + ret = zynqmp_pmufw_node(power_domain->id); + if (ret == -ENODEV) + ret = 0; + } - return 0; + return ret; } static int zynqmp_power_domain_free(struct power_domain *power_domain) diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index 7b64532e50b..572cef1694c 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -9,7 +9,7 @@ * Author: Robert Marko <robert.marko@sartura.hr> * Author: Luka Kovacic <luka.kovacic@sartura.hr> * - * Based on stock U-boot and Linux drivers + * Based on stock U-Boot and Linux drivers */ #include <asm/gpio.h> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 1e2f4e6de4a..49762950719 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -740,14 +740,7 @@ config VIDEO_SEPS525 Enable support for the Syncoam PM-OLED display driver (RGB 160x128). Currently driver is supporting only SPI interface. -config VIDEO_ZYNQMP_DPSUB - bool "Enable video support for ZynqMP Display Port" - depends on ZYNQMP_POWER_DOMAIN - help - Enable support for Xilinx ZynqMP Display Port. Currently this file - is used as placeholder for driver. The main reason is to record - compatible string and calling power domain driver. - +source "drivers/video/zynqmp/Kconfig" source "drivers/video/nexell/Kconfig" config CONSOLE_SCROLL_LINES diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 9a53cd14187..f99d7e3c3d9 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -73,7 +73,7 @@ obj-$(CONFIG_VIDEO_SANDBOX_SDL) += sandbox_sdl.o obj-$(CONFIG_VIDEO_SIMPLE) += simplefb.o obj-$(CONFIG_VIDEO_VESA) += vesa.o obj-$(CONFIG_VIDEO_SEPS525) += seps525.o -obj-$(CONFIG_VIDEO_ZYNQMP_DPSUB) += zynqmp_dpsub.o +obj-$(CONFIG_VIDEO_ZYNQMP_DPSUB) += zynqmp/ obj-y += bridge/ obj-y += sunxi/ diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index 8396bdfb11e..1b66a8061a7 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -220,14 +220,20 @@ u32 video_index_to_colour(struct video_priv *priv, unsigned int idx) break; case VIDEO_BPP32: if (CONFIG_IS_ENABLED(VIDEO_BPP32)) { - if (priv->format == VIDEO_X2R10G10B10) + switch (priv->format) { + case VIDEO_X2R10G10B10: return (colours[idx].r << 22) | (colours[idx].g << 12) | (colours[idx].b << 2); - else + case VIDEO_RGBA8888: + return (colours[idx].r << 24) | + (colours[idx].g << 16) | + (colours[idx].b << 8) | 0xff; + default: return (colours[idx].r << 16) | (colours[idx].g << 8) | (colours[idx].b << 0); + } } break; default: diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c index 47e52c4f69c..45f003c8251 100644 --- a/drivers/video/video_bmp.c +++ b/drivers/video/video_bmp.c @@ -43,6 +43,18 @@ static u32 get_bmp_col_x2r10g10b10(struct bmp_color_table_entry *cte) } /** + * get_bmp_col_rgba8888() - Convert a colour-table entry into a rgba8888 pixel value + * + * Return: value to write to the rgba8888 frame buffer for this palette entry + */ +static u32 get_bmp_col_rgba8888(struct bmp_color_table_entry *cte) +{ + return ((cte->red) | + (cte->green << 8U) | + (cte->blue << 16U) | 0xff << 24U); +} + +/** * write_pix8() - Write a pixel from a BMP image into the framebuffer * * This handles frame buffers with 8, 16, 24 or 32 bits per pixel @@ -71,6 +83,8 @@ static void write_pix8(u8 *fb, uint bpix, enum video_format eformat, *fb++ = cte->blue; } else if (eformat == VIDEO_X2R10G10B10) { *(u32 *)fb = get_bmp_col_x2r10g10b10(cte); + } else if (eformat == VIDEO_RGBA8888) { + *(u32 *)fb = get_bmp_col_rgba8888(cte); } else { *fb++ = cte->blue; *fb++ = cte->green; @@ -382,6 +396,17 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, *fb++ = (pix >> 8) & 0xff; *fb++ = (pix >> 16) & 0xff; *fb++ = pix >> 24; + } else if (eformat == VIDEO_RGBA8888) { + u32 pix; + + pix = *bmap++ << 8U; /* blue */ + pix |= *bmap++ << 16U; /* green */ + pix |= *bmap++ << 24U; /* red */ + + *fb++ = (pix >> 24) & 0xff; + *fb++ = (pix >> 16) & 0xff; + *fb++ = (pix >> 8) & 0xff; + *fb++ = 0xff; } else { *fb++ = *bmap++; *fb++ = *bmap++; @@ -409,6 +434,17 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, *fb++ = (pix >> 8) & 0xff; *fb++ = (pix >> 16) & 0xff; *fb++ = pix >> 24; + } else if (eformat == VIDEO_RGBA8888) { + u32 pix; + + pix = *bmap++ << 8U; /* blue */ + pix |= *bmap++ << 16U; /* green */ + pix |= *bmap++ << 24U; /* red */ + bmap++; + *fb++ = (pix >> 24) & 0xff; + *fb++ = (pix >> 16) & 0xff; + *fb++ = (pix >> 8) & 0xff; + *fb++ = 0xff; /* opacity */ } else { *fb++ = *bmap++; *fb++ = *bmap++; diff --git a/drivers/video/zynqmp/Kconfig b/drivers/video/zynqmp/Kconfig new file mode 100644 index 00000000000..b35cd1fb342 --- /dev/null +++ b/drivers/video/zynqmp/Kconfig @@ -0,0 +1,8 @@ + +config VIDEO_ZYNQMP_DPSUB + bool "Enable video support for ZynqMP Display Port" + depends on ZYNQMP_POWER_DOMAIN + help + Enable support for Xilinx ZynqMP Display Port. Currently this file + is used as placeholder for driver. The main reason is to record + compatible string and calling power domain driver. diff --git a/drivers/video/zynqmp/Makefile b/drivers/video/zynqmp/Makefile new file mode 100644 index 00000000000..cc057f53560 --- /dev/null +++ b/drivers/video/zynqmp/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2023, Advanced Micro Devices, Inc. + +obj-y += zynqmp_dpsub.o diff --git a/drivers/video/zynqmp/zynqmp_dpsub.c b/drivers/video/zynqmp/zynqmp_dpsub.c new file mode 100644 index 00000000000..def4dcf6261 --- /dev/null +++ b/drivers/video/zynqmp/zynqmp_dpsub.c @@ -0,0 +1,2225 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 - 2022, Xilinx Inc. + * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc. + * + * Xilinx displayport(DP) Tx Subsytem driver + */ + +#include <common.h> +#include <clk.h> +#include <cpu_func.h> +#include <dm.h> +#include <errno.h> +#include <generic-phy.h> +#include <stdlib.h> +#include <video.h> +#include <wait_bit.h> +#include <dm/device_compat.h> +#include <asm/io.h> +#include <linux/delay.h> +#include <linux/ioport.h> +#include <dm/device_compat.h> +#include <asm/global_data.h> + +#include "zynqmp_dpsub.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* Maximum supported resolution */ +#define WIDTH 1024 +#define HEIGHT 768 + +static struct dp_dma dp_dma; +static struct dp_dma_descriptor cur_desc __aligned(256); + +static void dma_init_video_descriptor(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + struct dp_dma_frame_buffer *frame_buffer = &dp_sub->frame_buffer; + + cur_desc.control = DPDMA_DESC_PREAMBLE | DPDMA_DESC_IGNR_DONE | + DPDMA_DESC_LAST_FRAME; + cur_desc.dscr_id = 0; + cur_desc.xfer_size = frame_buffer->size; + cur_desc.line_size_stride = ((frame_buffer->stride >> 4) << + DPDMA_DESCRIPTOR_LINE_SIZE_STRIDE_SHIFT) | + (frame_buffer->line_size); + cur_desc.addr_ext = (((u32)(frame_buffer->address >> + DPDMA_DESCRIPTOR_SRC_ADDR_WIDTH) << + DPDMA_DESCRIPTOR_ADDR_EXT_SRC_ADDR_EXT_SHIFT) | + (upper_32_bits((u64)&cur_desc))); + cur_desc.next_desr = lower_32_bits((u64)&cur_desc); + cur_desc.src_addr = lower_32_bits((u64)gd->fb_base); +} + +static void dma_set_descriptor_address(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + + flush_dcache_range((u64)&cur_desc, + ALIGN(((u64)&cur_desc + sizeof(cur_desc)), + CONFIG_SYS_CACHELINE_SIZE)); + writel(upper_32_bits((u64)&cur_desc), dp_sub->dp_dma->base_addr + + DPDMA_CH3_DSCR_STRT_ADDRE); + writel(lower_32_bits((u64)&cur_desc), dp_sub->dp_dma->base_addr + + DPDMA_CH3_DSCR_STRT_ADDR); +} + +static void dma_setup_channel(struct udevice *dev) +{ + dma_init_video_descriptor(dev); + dma_set_descriptor_address(dev); +} + +static void dma_set_channel_state(struct udevice *dev) +{ + u32 mask = 0, regval = 0; + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + + mask = DPDMA_CH_CNTL_EN_MASK | DPDMA_CH_CNTL_PAUSE_MASK; + regval = DPDMA_CH_CNTL_EN_MASK; + + clrsetbits_le32(dp_sub->dp_dma->base_addr + DPDMA_CH3_CNTL, + mask, regval); +} + +static void dma_trigger(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 trigger; + + trigger = DPDMA_GBL_TRG_CH3_MASK; + dp_sub->dp_dma->gfx.trigger_status = DPDMA_TRIGGER_DONE; + writel(trigger, dp_sub->dp_dma->base_addr + DPDMA_GBL); +} + +static void dma_vsync_intr_handler(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + + dma_setup_channel(dev); + dma_set_channel_state(dev); + dma_trigger(dev); + + /* Clear VSync Interrupt */ + writel(DPDMA_ISR_VSYNC_INT_MASK, dp_sub->dp_dma->base_addr + DPDMA_ISR); +} + +/** + * wait_phy_ready() - Wait for the DisplayPort PHY to come out of reset + * @dev: The DP device + * + * Return: 0 if wait succeeded, -ve if error occurred + */ +static int wait_phy_ready(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 timeout = 100, phy_status; + u8 phy_ready_mask = DP_PHY_STATUS_RESET_LANE_0_DONE_MASK | + DP_PHY_STATUS_GT_PLL_LOCK_MASK; + + /* Wait until the PHY is ready. */ + do { + udelay(20); + phy_status = readl(dp_sub->base_addr + DP_PHY_STATUS); + phy_status &= phy_ready_mask; + /* Protect against an infinite loop. */ + if (!timeout--) + return -ETIMEDOUT; + } while (phy_status != phy_ready_mask); + + return 0; +} + +static int init_dp_tx(struct udevice *dev) +{ + u32 status, phyval, regval, rate; + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + + phyval = readl(dp_sub->base_addr + DP_PHY_CONFIG); + writel(DP_SOFT_RESET_EN, dp_sub->base_addr + DP_SOFT_RESET); + status = readl(dp_sub->base_addr + DP_SOFT_RESET); + writel(DP_DISABLE, dp_sub->base_addr + DP_ENABLE); + + regval = (readl(dp_sub->base_addr + DP_AUX_CLK_DIVIDER) & + ~DP_AUX_CLK_DIVIDER_VAL_MASK) | + (60 << 8) | + (dp_sub->clock / 1000000); + writel(regval, dp_sub->base_addr + DP_AUX_CLK_DIVIDER); + + writel(DP_PHY_CLOCK_SELECT_540GBPS, dp_sub->base_addr + DP_PHY_CLOCK_SELECT); + + regval = phyval & ~DP_PHY_CONFIG_GT_ALL_RESET_MASK; + writel(regval, dp_sub->base_addr + DP_PHY_CONFIG); + status = wait_phy_ready(dev); + if (status) + return -EINVAL; + + writel(DP_ENABLE, dp_sub->base_addr + DP_ENABLE); + + rate = ~DP_INTR_HPD_PULSE_DETECTED_MASK & ~DP_INTR_HPD_EVENT_MASK + & ~DP_INTR_HPD_IRQ_MASK; + writel(rate, dp_sub->base_addr + DP_INTR_MASK); + return 0; +} + +static int set_nonlive_gfx_format(struct udevice *dev, enum av_buf_video_format format) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + struct av_buf_vid_attribute *ptr = (struct av_buf_vid_attribute *)avbuf_supported_formats; + + while (1) { + dev_dbg(dev, "Format %d\n", ptr->video_format); + + if (!ptr->video_format) + return -EINVAL; + + if (ptr->video_format == format) { + dp_sub->non_live_graphics = ptr; + break; + } + ptr++; + } + dev_dbg(dev, "Video format found. BPP %d\n", dp_sub->non_live_graphics->bpp); + return 0; +} + +/* DP dma setup */ +static void set_qos(struct udevice *dev, u8 qos) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u8 index; + u32 regval = 0, mask; + + regval = (((u32)qos << DPDMA_CH_CNTL_QOS_DATA_RD_SHIFT) | + ((u32)qos << DPDMA_CH_CNTL_QOS_DSCR_RD_SHIFT) | + ((u32)qos << DPDMA_CH_CNTL_QOS_DSCR_WR_SHIFT)); + + mask = DPDMA_CH_CNTL_QOS_DATA_RD_MASK | + DPDMA_CH_CNTL_QOS_DSCR_RD_MASK | + DPDMA_CH_CNTL_QOS_DSCR_WR_MASK; + for (index = 0; index <= DPDMA_AUDIO_CHANNEL1; index++) { + clrsetbits_le32(dp_sub->dp_dma->base_addr + + DPDMA_CH0_CNTL + + (DPDMA_CH_OFFSET * (u32)index), + mask, regval); + } +} + +static void enable_gfx_buffers(struct udevice *dev, u8 enable) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 regval = 0; + + regval = (0xF << AVBUF_CHBUF3_BURST_LEN_SHIFT) | + AVBUF_CHBUF3_FLUSH_MASK; + writel(regval, dp_sub->base_addr + AVBUF_CHBUF3); + if (enable) { + regval = (0xF << AVBUF_CHBUF3_BURST_LEN_SHIFT) | + AVBUF_CHBUF0_EN_MASK; + writel(regval, dp_sub->base_addr + AVBUF_CHBUF3); + } +} + +static void avbuf_video_select(struct udevice *dev, enum av_buf_video_stream vid_stream, + enum av_buf_gfx_stream gfx_stream) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + + dp_sub->av_mode.video_src = vid_stream; + dp_sub->av_mode.gfx_src = gfx_stream; + + clrsetbits_le32(dp_sub->base_addr + + AVBUF_BUF_OUTPUT_AUD_VID_SELECT, + AVBUF_BUF_OUTPUT_AUD_VID_SELECT_VID_STREAM2_SEL_MASK | + AVBUF_BUF_OUTPUT_AUD_VID_SELECT_VID_STREAM1_SEL_MASK, + vid_stream | gfx_stream); +} + +static void config_gfx_pipeline(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u16 *csc_matrix, *offset_matrix; + u32 regval = 0, index = 0, *scaling_factors = NULL; + u16 rgb_coeffs[] = { 0x1000, 0x0000, 0x0000, + 0x0000, 0x1000, 0x0000, + 0x0000, 0x0000, 0x1000 }; + u16 rgb_offset[] = { 0x0000, 0x0000, 0x0000 }; + struct av_buf_vid_attribute *video = dp_sub->non_live_graphics; + + scaling_factors = video->sf; + + clrsetbits_le32(dp_sub->base_addr + AVBUF_BUF_FORMAT, + AVBUF_BUF_FORMAT_NL_GRAPHX_FORMAT_MASK, + (video->value) << AVBUF_BUF_FORMAT_NL_GRAPHX_FORMAT_SHIFT); + + for (index = 0; index < 3; index++) { + writel(scaling_factors[index], dp_sub->base_addr + + AVBUF_BUF_GRAPHICS_COMP0_SCALE_FACTOR + (index * 4)); + } + regval = (video->is_rgb << AVBUF_V_BLEND_LAYER0_CONTROL_RGB_MODE_SHIFT) | + video->sampling_en; + writel(regval, dp_sub->base_addr + AVBUF_V_BLEND_LAYER1_CONTROL); + + if (video->is_rgb) { + csc_matrix = rgb_coeffs; + offset_matrix = rgb_offset; + } + /* Program Colorspace conversion coefficients */ + for (index = 9; index < 12; index++) { + writel(offset_matrix[index - 9], dp_sub->base_addr + + AVBUF_V_BLEND_IN2CSC_COEFF0 + (index * 4)); + } + + /* Program Colorspace conversion matrix */ + for (index = 0; index < 9; index++) { + writel(csc_matrix[index], dp_sub->base_addr + + AVBUF_V_BLEND_IN2CSC_COEFF0 + (index * 4)); + } +} + +static void set_blender_alpha(struct udevice *dev, u8 alpha, u8 enable) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 regval; + + regval = enable; + regval |= alpha << AVBUF_V_BLEND_SET_GLOBAL_ALPHA_REG_VALUE_SHIFT; + writel(regval, dp_sub->base_addr + + AVBUF_V_BLEND_SET_GLOBAL_ALPHA_REG); +} + +static void config_output_video(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 regval = 0, index; + u16 rgb_coeffs[] = { 0x1000, 0x0000, 0x0000, + 0x0000, 0x1000, 0x0000, + 0x0000, 0x0000, 0x1000 }; + u16 rgb_offset[] = { 0x0000, 0x0000, 0x0000 }; + u16 *matrix_coeff = rgb_coeffs, *matrix_offset = rgb_offset; + + struct av_buf_vid_attribute *output_video = dp_sub->non_live_graphics; + + regval |= output_video->sampling_en << + AVBUF_V_BLEND_OUTPUT_VID_FORMAT_EN_DOWNSAMPLE_SHIFT; + regval |= output_video->value; + writel(regval, dp_sub->base_addr + AVBUF_V_BLEND_OUTPUT_VID_FORMAT); + + for (index = 0; index < 9; index++) { + writel(matrix_coeff[index], dp_sub->base_addr + + AVBUF_V_BLEND_RGB2YCBCR_COEFF0 + (index * 4)); + } + + for (index = 0; index < 3; index++) { + writel((matrix_offset[index] << + AVBUF_V_BLEND_LUMA_IN1CSC_OFFSET_POST_OFFSET_SHIFT), + dp_sub->base_addr + + AVBUF_V_BLEND_LUMA_OUTCSC_OFFSET + + (index * 4)); + } + + set_blender_alpha(dev, 0, 0); +} + +static void config_msa_sync_clk_mode(struct udevice *dev, u8 enable) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + struct main_stream_attributes *msa_config; + + msa_config = &dp_sub->msa_config; + msa_config->synchronous_clock_mode = enable; + + if (enable == 1) { + msa_config->misc0 |= (1 << + DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_SHIFT); + } else { + msa_config->misc0 &= ~(1 << + DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_SHIFT); + } +} + +static void av_buf_soft_reset(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + + writel(AVBUF_BUF_SRST_REG_VID_RST_MASK, + dp_sub->base_addr + AVBUF_BUF_SRST_REG); + writel(0, dp_sub->base_addr + AVBUF_BUF_SRST_REG); +} + +static void set_video_clk_source(struct udevice *dev, u8 video_clk, u8 audio_clk) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 regval = 0; + + if (dp_sub->av_mode.video_src != AVBUF_VIDSTREAM1_LIVE && + dp_sub->av_mode.gfx_src != AVBUF_VIDSTREAM2_LIVE_GFX) { + regval = 1 << AVBUF_BUF_AUD_VID_CLK_SOURCE_VID_TIMING_SRC_SHIFT; + } else if (dp_sub->av_mode.video_src == AVBUF_VIDSTREAM1_LIVE || + dp_sub->av_mode.gfx_src == AVBUF_VIDSTREAM2_LIVE_GFX) { + video_clk = AVBUF_PL_CLK; + } + + regval |= (video_clk << AVBUF_BUF_AUD_VID_CLK_SOURCE_VID_CLK_SRC_SHIFT) | + (audio_clk << AVBUF_BUF_AUD_VID_CLK_SOURCE_AUD_CLK_SRC_SHIFT); + writel(regval, dp_sub->base_addr + AVBUF_BUF_AUD_VID_CLK_SOURCE); + + av_buf_soft_reset(dev); +} + +static int init_dpdma_subsys(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + + dp_sub->dp_dma->base_addr = DPDMA_BASE_ADDRESS; + dp_sub->dp_dma->gfx.channel.cur = NULL; + dp_sub->dp_dma->gfx.trigger_status = DPDMA_TRIGGER_DONE; + + set_qos(dev, 11); + return 0; +} + +/** + * is_dp_connected() - Check if there is a connected RX device + * @dev: The DP device + * + * + * Return: true if a connected RX device was detected, false otherwise + */ +static bool is_dp_connected(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 status; + u8 retries = 0; + + do { + status = readl(dp_sub->base_addr + + DP_INTERRUPT_SIG_STATE) + & DP_INTERRUPT_SIG_STATE_HPD_STATE_MASK; + + if (retries > DP_IS_CONNECTED_MAX_TIMEOUT_COUNT) + return 0; + + retries++; + udelay(1000); + } while (status == 0); + + return 1; +} + +/** + * aux_wait_ready() - Wait until another request is no longer in progress + * @dev: The DP device + * + * Return: 0 if wait succeeded, -ve if error occurred + */ +static int aux_wait_ready(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 status, timeout = 100; + + do { + status = readl(dp_sub->base_addr + + DP_INTERRUPT_SIG_STATE); + if (!timeout--) + return -ETIMEDOUT; + + udelay(20); + } while (status & DP_REPLY_STATUS_REPLY_IN_PROGRESS_MASK); + + return 0; +} + +/** + * aux_wait_reply() - Wait for reply on AUX channel + * @dev: The DP device + * + * Wait for a reply indicating that the most recent AUX request + * has been received by the RX device. + * + * Return: 0 if wait succeeded, -ve if error occurred + */ +static int aux_wait_reply(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 timeout = DP_AUX_MAX_WAIT, status; + + while (timeout > 0) { + status = readl(dp_sub->base_addr + DP_REPLY_STATUS); + if (status & DP_REPLY_STATUS_REPLY_ERROR_MASK) + return -ETIMEDOUT; + + if ((status & DP_REPLY_STATUS_REPLY_RECEIVED_MASK) && + !(status & DP_REPLY_STATUS_REQUEST_IN_PROGRESS_MASK) && + !(status & DP_REPLY_STATUS_REPLY_IN_PROGRESS_MASK)) { + return 0; + } + timeout--; + udelay(20); + } + return -ETIMEDOUT; +} + +/** + * aux_request_send() - Send request on the AUX channel + * @dev: The DP device + * @request: The request to send + * + * Submit the supplied AUX request to the RX device over the AUX + * channel by writing the command, the destination address, (the write buffer + * for write commands), and the data size to the DisplayPort TX core. + * + * This is the lower-level sending routine, which is called by aux_request(). + * + * Return: 0 if request was sent successfully, -ve on error + */ +static int aux_request_send(struct udevice *dev, struct aux_transaction *request) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 timeout_count = 0, status; + u8 index; + + do { + status = readl(dp_sub->base_addr + + DP_REPLY_STATUS); + + udelay(20); + timeout_count++; + if (timeout_count >= DP_AUX_MAX_TIMEOUT_COUNT) + return -ETIMEDOUT; + + } while ((status & DP_REPLY_STATUS_REQUEST_IN_PROGRESS_MASK) || + (status & DP_REPLY_STATUS_REPLY_IN_PROGRESS_MASK)); + /* Set the address for the request. */ + writel(request->address, dp_sub->base_addr + DP_AUX_ADDRESS); + + if (request->cmd_code == DP_AUX_CMD_WRITE || + request->cmd_code == DP_AUX_CMD_I2C_WRITE || + request->cmd_code == DP_AUX_CMD_I2C_WRITE_MOT) { + /* Feed write data into the DisplayPort TX core's write FIFO. */ + for (index = 0; index < request->num_bytes; index++) { + writel(request->data[index], + dp_sub->base_addr + + DP_AUX_WRITE_FIFO); + } + } + + status = ((request->cmd_code << DP_AUX_CMD_SHIFT) | + ((request->num_bytes - 1) & + DP_AUX_CMD_NBYTES_TRANSFER_MASK)); + + /* Submit the command and the data size. */ + writel(((request->cmd_code << DP_AUX_CMD_SHIFT) | + ((request->num_bytes - 1) & DP_AUX_CMD_NBYTES_TRANSFER_MASK)), + dp_sub->base_addr + DP_AUX_CMD); + + /* Check for a reply from the RX device to the submitted request. */ + status = aux_wait_reply(dev); + if (status) + /* Waiting for a reply timed out. */ + return -ETIMEDOUT; + + /* Analyze the reply. */ + status = readl(dp_sub->base_addr + DP_AUX_REPLY_CODE); + if (status == DP_AUX_REPLY_CODE_DEFER || + status == DP_AUX_REPLY_CODE_I2C_DEFER) { + /* The request was deferred. */ + return -EAGAIN; + } else if (status == DP_AUX_REPLY_CODE_NACK || + status == DP_AUX_REPLY_CODE_I2C_NACK) { + /* The request was not acknowledged. */ + return -EIO; + } + + /* The request was acknowledged. */ + if (request->cmd_code == DP_AUX_CMD_READ || + request->cmd_code == DP_AUX_CMD_I2C_READ || + request->cmd_code == DP_AUX_CMD_I2C_READ_MOT) { + /* Wait until all data has been received. */ + timeout_count = 0; + do { + status = readl(dp_sub->base_addr + + DP_REPLY_DATA_COUNT); + udelay(100); + timeout_count++; + if (timeout_count >= DP_AUX_MAX_TIMEOUT_COUNT) + return -ETIMEDOUT; + } while (status != request->num_bytes); + + /* Obtain the read data from the reply FIFO. */ + for (index = 0; index < request->num_bytes; index++) { + request->data[index] = readl(dp_sub->base_addr + + DP_AUX_REPLY_DATA); + } + } + return 0; +} + +/** + * aux_request() - Submit request on the AUX channel + * @dev: The DP device + * @request: The request to submit + * + * Submit the supplied AUX request to the RX device over the AUX + * channel. If waiting for a reply times out, or if the DisplayPort TX core + * indicates that the request was deferred, the request is sent again (up to a + * maximum specified by DP_AUX_MAX_DEFER_COUNT|DP_AUX_MAX_TIMEOUT_COUNT). + * + * Return: 0 if request was submitted successfully, -ve on error + */ +static int aux_request(struct udevice *dev, struct aux_transaction *request) +{ + u32 status, defer_count = 0, timeout_count = 0; + + do { + status = aux_wait_ready(dev); + if (status) { + /* The RX device isn't ready yet. */ + timeout_count++; + continue; + } + /* Send the request. */ + status = aux_request_send(dev, request); + if (status == -EAGAIN) { + /* The request was deferred. */ + defer_count++; + } else if (status == -ETIMEDOUT) { + /* Waiting for a reply timed out. */ + timeout_count++; + } else { + return status; + } + + udelay(100); + } while ((defer_count < DP_AUX_MAX_DEFER_COUNT) && + (timeout_count < DP_AUX_MAX_TIMEOUT_COUNT)); + + /* The request was not successfully received by the RX device. */ + return -ETIMEDOUT; +} + +/** + * aux_common() - Common (read/write) AUX communication transmission + * @dev: The DP device + * @cmd_type: Command code of the transaction + * @address: The DPCD address of the transaction + * @num_bytes: Number of bytes in the payload data + * @data: The payload data of the AUX command + * + * Common sequence of submitting an AUX command for AUX read, AUX write, + * I2C-over-AUX read, and I2C-over-AUX write transactions. If required, the + * reads and writes are split into multiple requests, each acting on a maximum + * of 16 bytes. + * + * Return: 0 if OK, -ve on error + */ +static int aux_common(struct udevice *dev, u32 cmd_type, u32 address, + u32 num_bytes, u8 *data) +{ + u32 status, bytes_left; + struct aux_transaction request; + + if (!is_dp_connected(dev)) + return -ENODEV; + + /* + * Set the start address for AUX transactions. For I2C transactions, + * this is the address of the I2C bus. + */ + request.address = address; + bytes_left = num_bytes; + while (bytes_left > 0) { + request.cmd_code = cmd_type; + + if (cmd_type == DP_AUX_CMD_READ || + cmd_type == DP_AUX_CMD_WRITE) { + /* Increment address for normal AUX transactions. */ + request.address = address + (num_bytes - bytes_left); + } + + /* Increment the pointer to the supplied data buffer. */ + request.data = &data[num_bytes - bytes_left]; + + if (bytes_left > 16) + request.num_bytes = 16; + else + request.num_bytes = bytes_left; + + bytes_left -= request.num_bytes; + + if (cmd_type == DP_AUX_CMD_I2C_READ && bytes_left > 0) { + /* + * Middle of a transaction I2C read request. Override + * the command code that was set to CmdType. + */ + request.cmd_code = DP_AUX_CMD_I2C_READ_MOT; + } else if (cmd_type == DP_AUX_CMD_I2C_WRITE && bytes_left > 0) { + /* + * Middle of a transaction I2C write request. Override + * the command code that was set to CmdType. + */ + request.cmd_code = DP_AUX_CMD_I2C_WRITE_MOT; + } + + status = aux_request(dev, &request); + if (status) + return status; + } + return 0; +} + +/** + * aux_write() - Issue AUX write request + * @dev: The DP device + * @dpcd_address: The DPCD address to write to + * @bytes_to_write: Number of bytes to write + * @write_data: Buffer containig data to be written + * + * Issue a write request over the AUX channel that will write to + * the RX device's DisplayPort Configuration data (DPCD) address space. The + * write message will be divided into multiple transactions which write a + * maximum of 16 bytes each. + * + * Return: 0 if write operation was successful, -ve on error + */ +static int aux_write(struct udevice *dev, u32 dpcd_address, u32 bytes_to_write, + void *write_data) +{ + return aux_common(dev, DP_AUX_CMD_WRITE, dpcd_address, + bytes_to_write, (u8 *)write_data); +} + +/** + * aux_read() - Issue AUX read request + * @dev: The DP device + * @dpcd_address: The DPCD address to read from + * @bytes_to_read: Number of bytes to read + * @read_data: Buffer to receive the read data + * + * Issue a read request over the AUX channel that will read from the RX + * device's DisplayPort Configuration data (DPCD) address space. The read + * message will be divided into multiple transactions which read a maximum of + * 16 bytes each. + * + * Return: 0 if read operation was successful, -ve on error + */ +static int aux_read(struct udevice *dev, u32 dpcd_address, u32 bytes_to_read, void *read_data) +{ + return aux_common(dev, DP_AUX_CMD_READ, dpcd_address, + bytes_to_read, (u8 *)read_data); +} + +static int dp_tx_wakeup(struct udevice *dev) +{ + u32 status; + u8 aux_data; + + aux_data = 0x1; + status = aux_write(dev, DP_DPCD_SET_POWER_DP_PWR_VOLTAGE, 1, &aux_data); + if (status) + debug("! 1st power wake-up - AUX write failed.\n"); + status = aux_write(dev, DP_DPCD_SET_POWER_DP_PWR_VOLTAGE, 1, &aux_data); + if (status) + debug("! 2nd power wake-up - AUX write failed.\n"); + + return status; +} + +/** + * enable_main_link() - Switch on main link for a device + * @dev: The DP device + */ +static void enable_main_link(struct udevice *dev, u8 enable) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + + /* Reset the scrambler. */ + writel(1, dp_sub->base_addr + DP_FORCE_SCRAMBLER_RESET); + /* Enable the main stream. */ + writel(enable, dp_sub->base_addr + DP_ENABLE_MAIN_STREAM); +} + +/** + * get_rx_capabilities() - Check if capabilities of RX device are valid for TX + * device + * @dev: The DP device + * + * Return: 0 if the capabilities of the RX device are valid for the TX device, + * -ve if not, of an error occurred during capability determination + */ +static int get_rx_capabilities(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u8 rx_max_link_rate, rx_max_lane_count, *dpcd = NULL; + u32 status; + struct link_config *link_config = NULL; + + dpcd = dp_sub->dpcd_rx_caps; + link_config = &dp_sub->link_config; + + status = aux_read(dev, DP_DPCD_RECEIVER_CAP_FIELD_START, 16, dpcd); + if (status) + return status; + + rx_max_link_rate = dpcd[DP_DPCD_MAX_LINK_RATE]; + rx_max_lane_count = dpcd[DP_DPCD_MAX_LANE_COUNT] & DP_DPCD_MAX_LANE_COUNT_MASK; + link_config->max_link_rate = (rx_max_link_rate > DP_0_LINK_RATE) ? + DP_0_LINK_RATE : rx_max_link_rate; + link_config->max_lane_count = (rx_max_lane_count > DP_0_LANE_COUNT) ? + DP_0_LANE_COUNT : rx_max_lane_count; + link_config->support_enhanced_framing_mode = dpcd[DP_DPCD_MAX_LANE_COUNT] & + DP_DPCD_ENHANCED_FRAME_SUPPORT_MASK; + link_config->support_downspread_control = dpcd[DP_DPCD_MAX_DOWNSPREAD] & + DP_DPCD_MAX_DOWNSPREAD_MASK; + + return 0; +} + +/** + * set_enhanced_frame_mode() - Enable/Disable enhanced frame mode + * @dev: The DP device + * @enable: Flag to determine whether to enable (1) or disable (0) the enhanced + * frame mode + * + * Enable or disable the enhanced framing symbol sequence for + * both the DisplayPort TX core and the RX device. + * + * Return: 0 if enabling/disabling the enhanced frame mode was successful, -ve + * on error + */ +static int set_enhanced_frame_mode(struct udevice *dev, u8 enable) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 status; + u8 regval; + + dp_sub->link_config.enhanced_framing_mode = enable; + /* Write enhanced frame mode enable to the DisplayPort TX core. */ + writel(dp_sub->link_config.enhanced_framing_mode, + dp_sub->base_addr + DP_ENHANCED_FRAME_EN); + + /* Preserve the current RX device settings. */ + status = aux_read(dev, DP_DPCD_LANE_COUNT_SET, 0x1, ®val); + if (status) + return status; + + if (dp_sub->link_config.enhanced_framing_mode) + regval |= DP_DPCD_ENHANCED_FRAME_EN_MASK; + else + regval &= ~DP_DPCD_ENHANCED_FRAME_EN_MASK; + + /* Write enhanced frame mode enable to the RX device. */ + return aux_write(dev, DP_DPCD_LANE_COUNT_SET, 0x1, ®val); +} + +/** + * set_lane_count() - Set the lane count + * @dev: The DP device + * @lane_count: Lane count to set + * + * Set the number of lanes to be used by the main link for both + * the DisplayPort TX core and the RX device. + * + * Return: 0 if setting the lane count was successful, -ve on error + */ +static int set_lane_count(struct udevice *dev, u8 lane_count) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 status; + u8 regval; + + dp_sub->link_config.lane_count = lane_count; + /* Write the new lane count to the DisplayPort TX core. */ + writel(dp_sub->link_config.lane_count, + dp_sub->base_addr + DP_LANE_COUNT_SET); + + /* Preserve the current RX device settings. */ + status = aux_read(dev, DP_DPCD_LANE_COUNT_SET, 0x1, ®val); + if (status) + return status; + + regval &= ~DP_DPCD_LANE_COUNT_SET_MASK; + regval |= dp_sub->link_config.lane_count; + + /* Write the new lane count to the RX device. */ + return aux_write(dev, DP_DPCD_LANE_COUNT_SET, 0x1, ®val); +} + +/** + * set_clk_speed() - Set DP phy clock speed + * @dev: The DP device + * @speed: The clock frquency to set (one of PHY_CLOCK_SELECT_*) + * + * Set the clock frequency for the DisplayPort PHY corresponding to a desired + * data rate. + * + * Return: 0 if setting the DP phy clock speed was successful, -ve on error + */ +static int set_clk_speed(struct udevice *dev, u32 speed) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 regval; + + /* Disable the DisplayPort TX core first. */ + regval = readl(dp_sub->base_addr + DP_ENABLE); + writel(0, dp_sub->base_addr + DP_ENABLE); + + /* Change speed of the feedback clock. */ + writel(speed, dp_sub->base_addr + DP_PHY_CLOCK_SELECT); + + /* Re-enable the DisplayPort TX core if it was previously enabled. */ + if (regval) + writel(regval, dp_sub->base_addr + DP_ENABLE); + + /* Wait until the PHY is ready. */ + return wait_phy_ready(dev); +} + +/** + * set_link_rate() - Set the link rate + * @dev: The DP device + * @link_rate: The link rate to set (one of LINK_BW_SET_*) + * + * Set the data rate to be used by the main link for both the DisplayPort TX + * core and the RX device. + * + * Return: 0 if setting the link rate was successful, -ve on error + */ +static int set_link_rate(struct udevice *dev, u8 link_rate) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 status; + + /* Write a corresponding clock frequency to the DisplayPort TX core. */ + switch (link_rate) { + case DP_LINK_BW_SET_162GBPS: + status = set_clk_speed(dev, DP_PHY_CLOCK_SELECT_162GBPS); + break; + case DP_LINK_BW_SET_270GBPS: + status = set_clk_speed(dev, DP_PHY_CLOCK_SELECT_270GBPS); + break; + case DP_LINK_BW_SET_540GBPS: + status = set_clk_speed(dev, DP_PHY_CLOCK_SELECT_540GBPS); + break; + default: + status = -EINVAL; + break; + } + if (status) + return status; + + dp_sub->link_config.link_rate = link_rate; + /* Write new link rate to the DisplayPort TX core. */ + writel(dp_sub->link_config.link_rate, + dp_sub->base_addr + + DP_LINK_BW_SET); + + /* Write new link rate to the RX device. */ + return aux_write(dev, DP_DPCD_LINK_BW_SET, 0x1, + &dp_sub->link_config.link_rate); +} + +static int set_downspread(struct udevice *dev, u8 enable) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 status; + u8 regval; + + dp_sub->link_config.support_downspread_control = enable; + /* Write downspread enable to the DisplayPort TX core. */ + writel(dp_sub->link_config.support_downspread_control, + dp_sub->base_addr + DP_DOWNSPREAD_CTRL); + + /* Preserve the current RX device settings. */ + status = aux_read(dev, DP_DPCD_DOWNSPREAD_CTRL, 0x1, ®val); + if (status) + return status; + + if (dp_sub->link_config.support_downspread_control) + regval |= DP_DPCD_SPREAD_AMP_MASK; + else + regval &= ~DP_DPCD_SPREAD_AMP_MASK; + + /* Write downspread enable to the RX device. */ + return aux_write(dev, DP_DPCD_DOWNSPREAD_CTRL, 0x1, ®val); +} + +static void set_serdes_vswing_preemp(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u8 index; + u8 vs_level_rx = dp_sub->link_config.vs_level; + u8 pe_level_rx = dp_sub->link_config.pe_level; + + for (index = 0; index < dp_sub->link_config.lane_count; index++) { + /* Write new voltage swing levels to the TX registers. */ + writel(vs[pe_level_rx][vs_level_rx], (ulong)SERDES_BASEADDR + + SERDES_L0_TX_MARGININGF + index * SERDES_LANE_OFFSET); + /* Write new pre-emphasis levels to the TX registers. */ + writel(pe[pe_level_rx][vs_level_rx], (ulong)SERDES_BASEADDR + + SERDES_L0_TX_DEEMPHASIS + index * SERDES_LANE_OFFSET); + } +} + +/** + * set_vswing_preemp() - Build AUX data to set voltage swing and pre-emphasis + * @dev: The DP device + * @aux_data: Buffer to receive the built AUX data + * + * Build AUX data to set current voltage swing and pre-emphasis level settings; + * the necessary data is taken from the link_config structure. + */ +static void set_vswing_preemp(struct udevice *dev, u8 *aux_data) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u8 data = 0; + u8 vs_level_rx = dp_sub->link_config.vs_level; + u8 pe_level_rx = dp_sub->link_config.pe_level; + + if (vs_level_rx >= DP_MAXIMUM_VS_LEVEL) + data |= DP_DPCD_TRAINING_LANEX_SET_MAX_VS_MASK; + + /* The maximum pre-emphasis level has been reached. */ + if (pe_level_rx >= DP_MAXIMUM_PE_LEVEL) + data |= DP_DPCD_TRAINING_LANEX_SET_MAX_PE_MASK; + + /* Set up the data buffer for writing to the RX device. */ + data |= (pe_level_rx << DP_DPCD_TRAINING_LANEX_SET_PE_SHIFT) | + vs_level_rx; + memset(aux_data, data, 4); + + set_serdes_vswing_preemp(dev); +} + +static int set_training_pattern(struct udevice *dev, u32 pattern) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u8 aux_data[5]; + + writel(pattern, dp_sub->base_addr + TRAINING_PATTERN_SET); + + aux_data[0] = pattern; + switch (pattern) { + case TRAINING_PATTERN_SET_OFF: + writel(0, dp_sub->base_addr + SCRAMBLING_DISABLE); + dp_sub->link_config.scrambler_en = 1; + break; + case TRAINING_PATTERN_SET_TP1: + case TRAINING_PATTERN_SET_TP2: + case TRAINING_PATTERN_SET_TP3: + aux_data[0] |= DP_DPCD_TP_SET_SCRAMB_DIS_MASK; + writel(1, dp_sub->base_addr + SCRAMBLING_DISABLE); + dp_sub->link_config.scrambler_en = 0; + break; + default: + break; + } + /* + * Make the adjustments to both the DisplayPort TX core and the RX + * device. + */ + set_vswing_preemp(dev, &aux_data[1]); + /* + * Write the voltage swing and pre-emphasis levels for each lane to the + * RX device. + */ + if (pattern == TRAINING_PATTERN_SET_OFF) + return aux_write(dev, DP_DPCD_TP_SET, 1, aux_data); + else + return aux_write(dev, DP_DPCD_TP_SET, 5, aux_data); +} + +static int get_lane_status_adj_reqs(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 status; + u8 aux_data[8]; + + status = aux_read(dev, DP_DPCD_SINK_COUNT, 8, aux_data); + if (status) + return status; + + /* Save XDPPSU_DPCD_SINK_COUNT contents. */ + dp_sub->sink_count = + ((aux_data[0] & DP_DPCD_SINK_COUNT_HIGH_MASK) >> + DP_DPCD_SINK_COUNT_HIGH_LOW_SHIFT) | + (aux_data[0] & DP_DPCD_SINK_COUNT_LOW_MASK); + memcpy(dp_sub->lane_status_ajd_reqs, &aux_data[2], 6); + return 0; +} + +/** + * check_clock_recovery() - Check clock recovery success + * @dev: The LogiCore DP TX device in question + * @lane_count: The number of lanes for which to check clock recovery success + * + * Check if the RX device's DisplayPort Configuration data (DPCD) indicates + * that the clock recovery sequence during link training was successful - the + * RX device's link clock and data recovery unit has realized and maintained + * the frequency lock for all lanes currently in use. + * + * Return: 0 if clock recovery was successful on all lanes in question, -ve if + * not + */ +static int check_clock_recovery(struct udevice *dev, u8 lane_count) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u8 *lane_status = dp_sub->lane_status_ajd_reqs; + + switch (lane_count) { + case DP_LANE_COUNT_SET_2: + if (!(lane_status[0] & DP_DPCD_STATUS_LANE_1_CR_DONE_MASK)) + return -EINVAL; + case DP_LANE_COUNT_SET_1: + if (!(lane_status[0] & DP_DPCD_STATUS_LANE_0_CR_DONE_MASK)) + return -EINVAL; + default: + /* All (LaneCount) lanes have achieved clock recovery. */ + break; + } + return 0; +} + +/** + * adj_vswing_preemp() - Adjust voltage swing and pre-emphasis + * @dev: The DP device + * + * Set new voltage swing and pre-emphasis levels using the + * adjustment requests obtained from the RX device. + * + * Return: 0 if voltage swing and pre-emphasis could be adjusted successfully, + * -ve on error + */ +static int adj_vswing_preemp(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u8 index, vs_level_adj_req[4], pe_level_adj_req[4]; + u8 aux_data[4]; + u8 *adj_reqs = &dp_sub->lane_status_ajd_reqs[4]; + + /* + * Analyze the adjustment requests for changes in voltage swing and + * pre-emphasis levels. + */ + vs_level_adj_req[0] = adj_reqs[0] & DP_DPCD_ADJ_REQ_LANE_0_2_VS_MASK; + vs_level_adj_req[1] = (adj_reqs[0] & DP_DPCD_ADJ_REQ_LANE_1_3_VS_MASK) >> + DP_DPCD_ADJ_REQ_LANE_1_3_VS_SHIFT; + pe_level_adj_req[0] = (adj_reqs[0] & DP_DPCD_ADJ_REQ_LANE_0_2_PE_MASK) >> + DP_DPCD_ADJ_REQ_LANE_0_2_PE_SHIFT; + pe_level_adj_req[1] = (adj_reqs[0] & DP_DPCD_ADJ_REQ_LANE_1_3_PE_MASK) >> + DP_DPCD_ADJ_REQ_LANE_1_3_PE_SHIFT; + + /* + * Change the drive settings to match the adjustment requests. Use the + * greatest level requested. + */ + dp_sub->link_config.vs_level = 0; + dp_sub->link_config.pe_level = 0; + for (index = 0; index < dp_sub->link_config.lane_count; index++) { + if (vs_level_adj_req[index] > dp_sub->link_config.vs_level) + dp_sub->link_config.vs_level = vs_level_adj_req[index]; + + if (pe_level_adj_req[index] > dp_sub->link_config.pe_level) + dp_sub->link_config.pe_level = pe_level_adj_req[index]; + } + + if (dp_sub->link_config.pe_level > DP_MAXIMUM_PE_LEVEL) + dp_sub->link_config.pe_level = DP_MAXIMUM_PE_LEVEL; + + if (dp_sub->link_config.vs_level > DP_MAXIMUM_VS_LEVEL) + dp_sub->link_config.vs_level = DP_MAXIMUM_VS_LEVEL; + + if (dp_sub->link_config.pe_level > + (4 - dp_sub->link_config.vs_level)) { + dp_sub->link_config.pe_level = + 4 - dp_sub->link_config.vs_level; + } + /* + * Make the adjustments to both the DisplayPort TX core and the RX + * device. + */ + set_vswing_preemp(dev, aux_data); + /* + * Write the voltage swing and pre-emphasis levels for each lane to the + * RX device. + */ + return aux_write(dev, DP_DPCD_TRAINING_LANE0_SET, 2, aux_data); +} + +/** + * get_training_delay() - Get training delay + * @dev: The DP device + * @training_state: The training state for which the required training delay + * should be queried + * + * Determine what the RX device's required training delay is for + * link training. + * + * Return: The training delay in us + */ +static u32 get_training_delay(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u8 *dpcd = dp_sub->dpcd_rx_caps; + + if (dpcd[DP_DPCD_TRAIN_AUX_RD_INTERVAL]) + return 400 * dpcd[DP_DPCD_TRAIN_AUX_RD_INTERVAL] * 10; + + return 400; +} + +/** + * training_state_clock_recovery() - Run clock recovery part of link training + * @dev: The DP device + * + * Run the clock recovery sequence as part of link training. The + * sequence is as follows: + * + * 0) Start signaling at the minimum voltage swing, pre-emphasis, and + * post- cursor levels. + * 1) Transmit training pattern 1 over the main link with symbol + * scrambling disabled. + * 2) The clock recovery loop. If clock recovery is unsuccessful after + * MaxIterations loop iterations, return. + * 2a) Wait for at least the period of time specified in the RX device's + * DisplayPort Configuration data (DPCD) register, + * TRAINING_AUX_RD_INTERVAL. + * 2b) Check if all lanes have achieved clock recovery lock. If so, + * return. + * 2c) Check if the same voltage swing level has been used 5 consecutive + * times or if the maximum level has been reached. If so, return. + * 2d) Adjust the voltage swing, pre-emphasis, and post-cursor levels as + * requested by the RX device. + * 2e) Loop back to 2a. + * + * For a more detailed description of the clock recovery sequence, see section + * 3.5.1.2.1 of the DisplayPort 1.2a specification document. + * + * Return: The next state machine state to advance to + */ +static enum link_training_states training_state_clock_recovery(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 status, delay_us; + u8 prev_vs_level = 0, same_vs_level_count = 0; + struct link_config *link_config = &dp_sub->link_config; + + delay_us = get_training_delay(dev); + /* Start CRLock. */ + /* Start from minimal voltage swing and pre-emphasis levels. */ + dp_sub->link_config.vs_level = 0; + dp_sub->link_config.pe_level = 0; + /* Transmit training pattern 1. */ + status = set_training_pattern(dev, TRAINING_PATTERN_SET_TP1); + if (status) + return TS_FAILURE; + + while (1) { + /* Wait delay specified in TRAINING_AUX_RD_INTERVAL. */ + udelay(delay_us); + /* Get lane and adjustment requests. */ + status = get_lane_status_adj_reqs(dev); + if (status) + /* The AUX read failed. */ + return TS_FAILURE; + + /* + * Check if all lanes have realized and maintained the frequency + * lock and get adjustment requests. + */ + status = check_clock_recovery(dev, dp_sub->link_config.lane_count); + if (status == 0) + return TS_CHANNEL_EQUALIZATION; + /* + * Check if the same voltage swing for each lane has been used 5 + * consecutive times. + */ + if (prev_vs_level == link_config->vs_level) { + same_vs_level_count++; + } else { + same_vs_level_count = 0; + prev_vs_level = link_config->vs_level; + } + if (same_vs_level_count >= 5) + break; + + /* Only try maximum voltage swing once. */ + if (link_config->vs_level == DP_MAXIMUM_VS_LEVEL) + break; + + /* Adjust the drive settings as requested by the RX device. */ + status = adj_vswing_preemp(dev); + if (status) + /* The AUX write failed. */ + return TS_FAILURE; + } + return TS_ADJUST_LINK_RATE; +} + +/** + * check_channel_equalization() - Check channel equalization success + * @dev: The DP device + * @lane_count: The number of lanes for which to check channel equalization + * success + * + * Check if the RX device's DisplayPort Configuration data (DPCD) indicates + * that the channel equalization sequence during link training was successful - + * the RX device has achieved channel equalization, symbol lock, and interlane + * alignment for all lanes currently in use. + * + * Return: 0 if channel equalization was successful on all lanes in question, + * -ve if not + */ +static int check_channel_equalization(struct udevice *dev, u8 lane_count) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u8 *lane_status = dp_sub->lane_status_ajd_reqs; + + /* Check that all LANEx_CHANNEL_EQ_DONE bits are set. */ + switch (lane_count) { + case DP_LANE_COUNT_SET_2: + if (!(lane_status[0] & DP_DPCD_STATUS_LANE_1_CE_DONE_MASK)) + return -EINVAL; + case DP_LANE_COUNT_SET_1: + if (!(lane_status[0] & DP_DPCD_STATUS_LANE_0_CE_DONE_MASK)) + return -EINVAL; + default: + /* All (LaneCount) lanes have achieved channel equalization. */ + break; + } + + /* Check that all LANEx_SYMBOL_LOCKED bits are set. */ + switch (lane_count) { + case DP_LANE_COUNT_SET_2: + if (!(lane_status[0] & DP_DPCD_STATUS_LANE_1_SL_DONE_MASK)) + return -EINVAL; + case DP_LANE_COUNT_SET_1: + if (!(lane_status[0] & DP_DPCD_STATUS_LANE_0_SL_DONE_MASK)) + return -EINVAL; + default: + /* All (LaneCount) lanes have achieved symbol lock. */ + break; + } + + /* Check that interlane alignment is done. */ + if (!(lane_status[2] & DP_DPCD_LANE_ALIGN_STATUS_UPDATED_IA_DONE_MASK)) + return -EINVAL; + return 0; +} + +/** + * training_state_channel_equalization() - Run channel equalization part of + * link training + * @dev: The DP device + * + * Run the channel equalization sequence as part of link + * training. The sequence is as follows: + * + * 0) Start signaling with the same drive settings used at the end of the + * clock recovery sequence. + * 1) Transmit training pattern 2 (or 3) over the main link with symbol + * scrambling disabled. + * 2) The channel equalization loop. If channel equalization is + * unsuccessful after 5 loop iterations, return. + * 2a) Wait for at least the period of time specified in the RX device's + * DisplayPort Configuration data (DPCD) register, + * TRAINING_AUX_RD_INTERVAL. + * 2b) Check if all lanes have achieved channel equalization, symbol lock, + * and interlane alignment. If so, return. + * 2c) Check if the same voltage swing level has been used 5 consecutive + * times or if the maximum level has been reached. If so, return. + * 2d) Adjust the voltage swing, pre-emphasis, and post-cursor levels as + * requested by the RX device. + * 2e) Loop back to 2a. + * + * For a more detailed description of the channel equalization sequence, see + * section 3.5.1.2.2 of the DisplayPort 1.2a specification document. + * + * Return: The next state machine state to advance to + */ +static enum link_training_states training_state_channel_equalization(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 status, delay_us = 400, iteration_count = 0; + + /* Write the current drive settings. */ + /* Transmit training pattern 2/3. */ + if (dp_sub->dpcd_rx_caps[DP_DPCD_MAX_LANE_COUNT] & + DP_DPCD_TPS3_SUPPORT_MASK) + status = set_training_pattern(dev, TRAINING_PATTERN_SET_TP3); + else + status = set_training_pattern(dev, TRAINING_PATTERN_SET_TP2); + + if (status) + return TS_FAILURE; + + while (iteration_count < 5) { + /* Wait delay specified in TRAINING_AUX_RD_INTERVAL. */ + udelay(delay_us); + + /* Get lane and adjustment requests. */ + status = get_lane_status_adj_reqs(dev); + if (status) + /* The AUX read failed. */ + return TS_FAILURE; + + /* Adjust the drive settings as requested by the RX device. */ + status = adj_vswing_preemp(dev); + if (status) + /* The AUX write failed. */ + return TS_FAILURE; + + /* Check that all lanes still have their clocks locked. */ + status = check_clock_recovery(dev, dp_sub->link_config.lane_count); + if (status) + break; + /* + * Check that all lanes have accomplished channel + * equalization, symbol lock, and interlane alignment. + */ + status = check_channel_equalization(dev, dp_sub->link_config.lane_count); + if (status == 0) + return TS_SUCCESS; + iteration_count++; + } + + /* + * Tried 5 times with no success. Try a reduced bitrate first, then + * reduce the number of lanes. + */ + return TS_ADJUST_LINK_RATE; +} + +static int check_lane_align(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u8 *lane_status = dp_sub->lane_status_ajd_reqs; + + if (!(lane_status[2] & DP_DPCD_LANE_ALIGN_STATUS_UPDATED_IA_DONE_MASK)) + return -EINVAL; + return 0; +} + +/** + * check_link_status() - Check status of link + * @dev: The DP device + * @lane_count: The lane count to use for the check + * + * Check if the receiver's DisplayPort Configuration data (DPCD) indicates the + * receiver has achieved and maintained clock recovery, channel equalization, + * symbol lock, and interlane alignment for all lanes currently in use. + * + * Return: 0 if the link status is OK, -ve if a error occurred during checking + */ +static int check_link_status(struct udevice *dev, u8 lane_count) +{ + u32 status; + + status = get_lane_status_adj_reqs(dev); + if (status) + /* The AUX read failed. */ + return status; + + /* Check if the link needs training. */ + if ((check_clock_recovery(dev, lane_count) == 0) && + (check_channel_equalization(dev, lane_count) == 0) && + (check_lane_align(dev) == 0)) { + return 0; + } + return -EINVAL; +} + +/** + * run_training() - Run link training + * @dev: The DP device + * + * Run the link training process. It is implemented as a state machine, with + * each state returning the next state. First, the clock recovery sequence will + * be run; if successful, the channel equalization sequence will run. If either + * the clock recovery or channel equalization sequence failed, the link rate or + * the number of lanes used will be reduced and training will be re-attempted. + * If training fails at the minimal data rate, 1.62 Gbps with a single lane, + * training will no longer re-attempt and fail. + * + * There are undocumented timeout constraints in the link training process. In + * DP v1.2a spec, Chapter 3.5.1.2.2 a 10ms limit for the complete training + * process is mentioned. Which individual timeouts are derived and implemented + * by sink manufacturers is unknown. So each step should be as short as + * possible and link training should start as soon as possible after HPD. + * + * Return: 0 if the training sequence ran successfully, -ve if a error occurred + * or the training failed + */ +static int run_training(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 status; + enum link_training_states training_state = TS_CLOCK_RECOVERY; + + while (1) { + switch (training_state) { + case TS_CLOCK_RECOVERY: + training_state = training_state_clock_recovery(dev); + break; + case TS_CHANNEL_EQUALIZATION: + training_state = training_state_channel_equalization(dev); + break; + default: + break; + } + + if (training_state == TS_SUCCESS) + break; + else if (training_state == TS_FAILURE) + return -EINVAL; + + if (training_state == TS_ADJUST_LANE_COUNT || + training_state == TS_ADJUST_LINK_RATE) { + status = set_training_pattern(dev, TRAINING_PATTERN_SET_OFF); + if (status) + return -EINVAL; + } + } + + /* Final status check. */ + return check_link_status(dev, dp_sub->link_config.lane_count); +} + +void reset_dp_phy(struct udevice *dev, u32 reset) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 phyval, regval; + + writel(0, dp_sub->base_addr + DP_ENABLE); + phyval = readl(dp_sub->base_addr + DP_PHY_CONFIG); + regval = phyval | reset; + writel(regval, dp_sub->base_addr + DP_PHY_CONFIG); + /* Remove the reset. */ + writel(phyval, dp_sub->base_addr + DP_PHY_CONFIG); + /* Wait for the PHY to be ready. */ + wait_phy_ready(dev); + + writel(1, dp_sub->base_addr + DP_ENABLE); +} + +/** + * establish_link() - Establish a link + * @dev: The DP device + * + * Check if the link needs training and run the training sequence if training + * is required. + * + * Return: 0 if the link was established successfully, -ve on error + */ +static int establish_link(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 status, re_enable_main_link; + + reset_dp_phy(dev, DP_PHY_CONFIG_TX_PHY_8B10BEN_MASK | + DP_PHY_CONFIG_PHY_RESET_MASK); + + re_enable_main_link = readl(dp_sub->base_addr + DP_ENABLE_MAIN_STREAM); + if (re_enable_main_link) + enable_main_link(dev, 0); + + status = run_training(dev); + if (status) + return status; + + status = set_training_pattern(dev, TRAINING_PATTERN_SET_OFF); + if (status) + return status; + + if (re_enable_main_link) + enable_main_link(dev, 1); + + return check_link_status(dev, dp_sub->link_config.lane_count); +} + +static int dp_hpd_train(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + struct link_config *link_config = &dp_sub->link_config; + u32 status; + + status = get_rx_capabilities(dev); + if (status) { + debug("! Error getting RX caps.\n"); + return status; + } + + status = set_enhanced_frame_mode(dev, link_config->support_enhanced_framing_mode ? 1 : 0); + if (status) { + debug("! EFM set failed.\n"); + return status; + } + + status = set_lane_count(dev, (dp_sub->use_max_lane_count) ? + link_config->max_lane_count : dp_sub->lane_count); + if (status) { + debug("! Lane count set failed.\n"); + return status; + } + + status = set_link_rate(dev, (dp_sub->use_max_link_rate) ? + link_config->max_link_rate : dp_sub->link_rate); + if (status) { + debug("! Link rate set failed.\n"); + return status; + } + + status = set_downspread(dev, link_config->support_downspread_control); + if (status) { + debug("! Setting downspread failed.\n"); + return status; + } + + debug("Lane count =%d\n", dp_sub->link_config.lane_count); + debug("Link rate =%d\n", dp_sub->link_config.link_rate); + + debug("Starting Training...\n"); + status = establish_link(dev); + if (status == 0) + debug("! Training succeeded.\n"); + else + debug("! Training failed.\n"); + + return status; +} + +static void display_gfx_frame_buffer(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + + if (!dp_sub->dp_dma->gfx.channel.cur) + dp_sub->dp_dma->gfx.trigger_status = DPDMA_TRIGGER_EN; +} + +static void set_color_encode(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + struct main_stream_attributes *msa_config = &dp_sub->msa_config; + + msa_config->y_cb_cr_colorimetry = 0; + msa_config->dynamic_range = 0; + msa_config->component_format = 0; + msa_config->misc0 = 0; + msa_config->misc1 = 0; + msa_config->component_format = DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_RGB; +} + +static void config_msa_recalculate(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + u32 video_bw, link_bw, words_per_line; + u8 bits_per_pixel; + struct main_stream_attributes *msa_config; + struct link_config *link_config; + + msa_config = &dp_sub->msa_config; + link_config = &dp_sub->link_config; + + msa_config->user_pixel_width = 1; + + /* Compute the rest of the MSA values. */ + msa_config->n_vid = 27 * 1000 * link_config->link_rate; + msa_config->h_start = msa_config->vid_timing_mode.video_timing.h_sync_width + + msa_config->vid_timing_mode.video_timing.h_back_porch; + msa_config->v_start = msa_config->vid_timing_mode.video_timing.f0_pv_sync_width + + msa_config->vid_timing_mode.video_timing.f0_pv_back_porch; + + /* Miscellaneous attributes. */ + if (msa_config->bits_per_color == 6) + msa_config->misc0 = DP_MAIN_STREAM_MISC0_BDC_6BPC; + else if (msa_config->bits_per_color == 8) + msa_config->misc0 = DP_MAIN_STREAM_MISC0_BDC_8BPC; + else if (msa_config->bits_per_color == 10) + msa_config->misc0 = DP_MAIN_STREAM_MISC0_BDC_10BPC; + else if (msa_config->bits_per_color == 12) + msa_config->misc0 = DP_MAIN_STREAM_MISC0_BDC_12BPC; + else if (msa_config->bits_per_color == 16) + msa_config->misc0 = DP_MAIN_STREAM_MISC0_BDC_16BPC; + + msa_config->misc0 <<= DP_MAIN_STREAM_MISC0_BDC_SHIFT; + + /* Need to set this. */ + msa_config->misc0 |= msa_config->component_format << + DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_SHIFT; + + msa_config->misc0 |= msa_config->dynamic_range << + DP_MAIN_STREAM_MISC0_DYNAMIC_RANGE_SHIFT; + + msa_config->misc0 |= msa_config->y_cb_cr_colorimetry << + DP_MAIN_STREAM_MISC0_YCBCR_COLORIMETRY_SHIFT; + + msa_config->misc0 |= msa_config->synchronous_clock_mode; + /* + * Determine the number of bits per pixel for the specified color + * component format. + */ + if (msa_config->misc1 == DP_MAIN_STREAM_MISC1_Y_ONLY_EN_MASK) + bits_per_pixel = msa_config->bits_per_color; + else if (msa_config->component_format == + DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_YCBCR422) + /* YCbCr422 color component format. */ + bits_per_pixel = msa_config->bits_per_color * 2; + else + /* RGB or YCbCr 4:4:4 color component format. */ + bits_per_pixel = msa_config->bits_per_color * 3; + + /* Calculate the data per lane. */ + words_per_line = msa_config->vid_timing_mode.video_timing.h_active * bits_per_pixel; + if (words_per_line % 16) + words_per_line += 16; + + words_per_line /= 16; + msa_config->data_per_lane = words_per_line - link_config->lane_count; + if (words_per_line % link_config->lane_count) + msa_config->data_per_lane += (words_per_line % link_config->lane_count); + + /* Allocate a fixed size for single-stream transport (SST) operation. */ + msa_config->transfer_unit_size = 64; + + /* + * Calculate the average number of bytes per transfer unit. + * Note: Both the integer and the fractional part is stored in + * AvgBytesPerTU. + */ + video_bw = ((msa_config->pixel_clock_hz / 1000) * bits_per_pixel) / 8; + link_bw = (link_config->lane_count * link_config->link_rate * 27); + msa_config->avg_bytes_per_tu = ((10 * + (video_bw * msa_config->transfer_unit_size) + / link_bw) + 5) / 10; + /* + * The number of initial wait cycles at the start of a new line by the + * framing logic. This allows enough data to be buffered in the input + * FIFO before video is sent. + */ + if ((msa_config->avg_bytes_per_tu / 1000) <= 4) + msa_config->init_wait = 64; + else + msa_config->init_wait = msa_config->transfer_unit_size - + (msa_config->avg_bytes_per_tu / 1000); +} + +static void set_msa_bpc(struct udevice *dev, u8 bits_per_color) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + + dp_sub->msa_config.bits_per_color = bits_per_color; + /* Calculate the rest of the MSA values. */ + config_msa_recalculate(dev); +} + +const struct video_timing_mode *get_video_mode_data(enum video_mode vm_id) +{ + if (vm_id < VIDC_VM_NUM_SUPPORTED) + return &vidc_video_timing_modes[vm_id]; + + return NULL; +} + +static u64 get_pixelclk_by_vmid(enum video_mode vm_id) +{ + const struct video_timing_mode *vm; + u64 clk_hz; + + vm = get_video_mode_data(vm_id); + /* For progressive mode, use only frame 0 vertical total. */ + clk_hz = vm->video_timing.f0_pv_total; + /* Multiply the number of pixels by the frame rate. */ + clk_hz *= vm->frame_rate; + + /* + * Multiply the vertical total by the horizontal total for number of + * pixels. + */ + clk_hz *= vm->video_timing.h_total; + + return clk_hz; +} + +/** + * config_msa_video_mode() - Enable video output + * @dev: The DP device + * @msa: The MSA values to set for the device + * + * Return: 0 if the video was enabled successfully, -ve on error + */ +static void config_msa_video_mode(struct udevice *dev, enum video_mode videomode) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + struct main_stream_attributes *msa_config; + + msa_config = &dp_sub->msa_config; + + /* Configure the MSA values from the display monitor DMT table. */ + msa_config->vid_timing_mode.vid_mode = vidc_video_timing_modes[videomode].vid_mode; + msa_config->vid_timing_mode.frame_rate = vidc_video_timing_modes[videomode].frame_rate; + msa_config->vid_timing_mode.video_timing.h_active = + vidc_video_timing_modes[videomode].video_timing.h_active; + msa_config->vid_timing_mode.video_timing.h_front_porch = + vidc_video_timing_modes[videomode].video_timing.h_front_porch; + msa_config->vid_timing_mode.video_timing.h_sync_width = + vidc_video_timing_modes[videomode].video_timing.h_sync_width; + msa_config->vid_timing_mode.video_timing.h_back_porch = + vidc_video_timing_modes[videomode].video_timing.h_back_porch; + msa_config->vid_timing_mode.video_timing.h_total = + vidc_video_timing_modes[videomode].video_timing.h_total; + msa_config->vid_timing_mode.video_timing.h_sync_polarity = + vidc_video_timing_modes[videomode].video_timing.h_sync_polarity; + msa_config->vid_timing_mode.video_timing.v_active = + vidc_video_timing_modes[videomode].video_timing.v_active; + msa_config->vid_timing_mode.video_timing.f0_pv_front_porch = + vidc_video_timing_modes[videomode].video_timing.f0_pv_front_porch; + msa_config->vid_timing_mode.video_timing.f0_pv_sync_width = + vidc_video_timing_modes[videomode].video_timing.f0_pv_sync_width; + msa_config->vid_timing_mode.video_timing.f0_pv_back_porch = + vidc_video_timing_modes[videomode].video_timing.f0_pv_back_porch; + msa_config->vid_timing_mode.video_timing.f0_pv_total = + vidc_video_timing_modes[videomode].video_timing.f0_pv_total; + msa_config->vid_timing_mode.video_timing.f1_v_front_porch = + vidc_video_timing_modes[videomode].video_timing.f1_v_front_porch; + msa_config->vid_timing_mode.video_timing.f1_v_sync_width = + vidc_video_timing_modes[videomode].video_timing.f1_v_sync_width; + msa_config->vid_timing_mode.video_timing.f1_v_back_porch = + vidc_video_timing_modes[videomode].video_timing.f1_v_back_porch; + msa_config->vid_timing_mode.video_timing.f1_v_total = + vidc_video_timing_modes[videomode].video_timing.f1_v_total; + msa_config->vid_timing_mode.video_timing.v_sync_polarity = + vidc_video_timing_modes[videomode].video_timing.v_sync_polarity; + msa_config->pixel_clock_hz = get_pixelclk_by_vmid(msa_config->vid_timing_mode.vid_mode); + + /* Calculate the rest of the MSA values. */ + config_msa_recalculate(dev); +} + +static void set_pixel_clock(u64 freq_hz) +{ + u64 ext_divider, vco, vco_int_frac; + u32 pll_assigned, frac_int_fb_div, fraction, regpll = 0; + u8 pll; + + pll_assigned = readl(CLK_FPD_BASEADDR + VIDEO_REF_CTRL) & VIDEO_REF_CTRL_SRCSEL_MASK; + if (pll_assigned) + pll = VPLL; + + ext_divider = PLL_OUT_FREQ / freq_hz; + vco = freq_hz * ext_divider * 2; + vco_int_frac = (vco * INPUT_FREQ_PRECISION * SHIFT_DECIMAL) / + AVBUF_INPUT_REF_CLK; + frac_int_fb_div = vco_int_frac >> PRECISION; + fraction = vco_int_frac & AVBUF_DECIMAL; + + regpll |= ENABLE_BIT << PLL_CTRL_BYPASS_SHIFT; + regpll |= frac_int_fb_div << PLL_CTRL_FBDIV_SHIFT; + regpll |= (1 << PLL_CTRL_DIV2_SHIFT); + regpll |= (PSS_REF_CLK << PLL_CTRL_PRE_SRC_SHIFT); + writel(regpll, CLK_FPD_BASEADDR + VPLL_CTRL); + + regpll = 0; + regpll |= VPLL_CFG_CP << PLL_CFG_CP_SHIFT; + regpll |= VPLL_CFG_RES << PLL_CFG_RES_SHIFT; + regpll |= VPLL_CFG_LFHF << PLL_CFG_LFHF_SHIFT; + regpll |= VPLL_CFG_LOCK_DLY << PLL_CFG_LOCK_DLY_SHIFT; + regpll |= VPLL_CFG_LOCK_CNT << PLL_CFG_LOCK_CNT_SHIFT; + writel(regpll, CLK_FPD_BASEADDR + VPLL_CFG); + + regpll = (1U << PLL_FRAC_CFG_ENABLED_SHIFT) | + (fraction << PLL_FRAC_CFG_DATA_SHIFT); + writel(regpll, CLK_FPD_BASEADDR + VPLL_FRAC_CFG); + + clrsetbits_le32(CLK_FPD_BASEADDR + VPLL_CTRL, + PLL_CTRL_RESET_MASK, + (ENABLE_BIT << PLL_CTRL_RESET_SHIFT)); + + /* Deassert reset to the PLL. */ + clrsetbits_le32(CLK_FPD_BASEADDR + VPLL_CTRL, + PLL_CTRL_RESET_MASK, + (DISABLE_BIT << PLL_CTRL_RESET_SHIFT)); + + while (!(readl(CLK_FPD_BASEADDR + PLL_STATUS) & + (1 << PLL_STATUS_VPLL_LOCK))) + ; + + /* Deassert Bypass. */ + clrsetbits_le32(CLK_FPD_BASEADDR + VPLL_CTRL, + PLL_CTRL_BYPASS_MASK, + (DISABLE_BIT << PLL_CTRL_BYPASS_SHIFT)); + udelay(1); + + clrsetbits_le32(CLK_FPD_BASEADDR + VIDEO_REF_CTRL, + VIDEO_REF_CTRL_CLKACT_MASK, + (DISABLE_BIT << VIDEO_REF_CTRL_CLKACT_SHIFT)); + + clrsetbits_le32(CLK_FPD_BASEADDR + VIDEO_REF_CTRL, + VIDEO_REF_CTRL_DIVISOR1_MASK, + (ENABLE_BIT << VIDEO_REF_CTRL_DIVISOR1_SHIFT)); + + clrsetbits_le32(CLK_FPD_BASEADDR + VIDEO_REF_CTRL, + VIDEO_REF_CTRL_DIVISOR0_MASK, + (ext_divider << VIDEO_REF_CTRL_DIVISOR0_SHIFT)); + + clrsetbits_le32(CLK_FPD_BASEADDR + VIDEO_REF_CTRL, + VIDEO_REF_CTRL_CLKACT_MASK, + (ENABLE_BIT << VIDEO_REF_CTRL_CLKACT_SHIFT)); +} + +/** + * set_msa_values() - Set MSA values + * @dev: The DP device + * + * Set the main stream attributes registers of the DisplayPort TX + * core with the values specified in the main stream attributes configuration + * structure. + */ +static void set_msa_values(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + struct main_stream_attributes *msa_config; + + msa_config = &dp_sub->msa_config; + + /* + * Set the main stream attributes to the associated DisplayPort TX core + * registers. + */ + writel(msa_config->vid_timing_mode.video_timing.h_total, + dp_sub->base_addr + DP_MAIN_STREAM_HTOTAL); + writel(msa_config->vid_timing_mode.video_timing.f0_pv_total, + dp_sub->base_addr + DP_MAIN_STREAM_VTOTAL); + writel(msa_config->vid_timing_mode.video_timing.h_sync_polarity | + (msa_config->vid_timing_mode.video_timing.v_sync_polarity + << DP_MAIN_STREAM_POLARITY_VSYNC_POL_SHIFT), + dp_sub->base_addr + DP_MAIN_STREAM_POLARITY); + writel(msa_config->vid_timing_mode.video_timing.h_sync_width, + dp_sub->base_addr + DP_MAIN_STREAM_HSWIDTH); + writel(msa_config->vid_timing_mode.video_timing.f0_pv_sync_width, + dp_sub->base_addr + DP_MAIN_STREAM_VSWIDTH); + writel(msa_config->vid_timing_mode.video_timing.h_active, + dp_sub->base_addr + DP_MAIN_STREAM_HRES); + writel(msa_config->vid_timing_mode.video_timing.v_active, + dp_sub->base_addr + DP_MAIN_STREAM_VRES); + writel(msa_config->h_start, dp_sub->base_addr + DP_MAIN_STREAM_HSTART); + writel(msa_config->v_start, dp_sub->base_addr + DP_MAIN_STREAM_VSTART); + writel(msa_config->misc0, dp_sub->base_addr + DP_MAIN_STREAM_MISC0); + writel(msa_config->misc1, dp_sub->base_addr + DP_MAIN_STREAM_MISC1); + writel(msa_config->pixel_clock_hz / 1000, dp_sub->base_addr + DP_M_VID); + writel(msa_config->n_vid, dp_sub->base_addr + DP_N_VID); + writel(msa_config->user_pixel_width, dp_sub->base_addr + DP_USER_PIXEL_WIDTH); + writel(msa_config->data_per_lane, dp_sub->base_addr + DP_USER_DATA_COUNT_PER_LANE); + /* + * Set the transfer unit values to the associated DisplayPort TX core + * registers. + */ + writel(msa_config->transfer_unit_size, dp_sub->base_addr + DP_TU_SIZE); + writel(msa_config->avg_bytes_per_tu / 1000, + dp_sub->base_addr + DP_MIN_BYTES_PER_TU); + writel((msa_config->avg_bytes_per_tu % 1000) * 1000, + dp_sub->base_addr + DP_FRAC_BYTES_PER_TU); + writel(msa_config->init_wait, dp_sub->base_addr + DP_INIT_WAIT); +} + +static void setup_video_stream(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + struct main_stream_attributes *msa_config = &dp_sub->msa_config; + + set_color_encode(dev); + set_msa_bpc(dev, dp_sub->bpc); + config_msa_video_mode(dev, dp_sub->video_mode); + + /* Set pixel clock. */ + dp_sub->pix_clk = msa_config->pixel_clock_hz; + set_pixel_clock(dp_sub->pix_clk); + + /* Reset the transmitter. */ + writel(1, dp_sub->base_addr + DP_SOFT_RESET); + udelay(10); + writel(0, dp_sub->base_addr + DP_SOFT_RESET); + + set_msa_values(dev); + + /* Issuing a soft-reset (AV_BUF_SRST_REG). */ + writel(3, dp_sub->base_addr + AVBUF_BUF_SRST_REG); // Assert reset. + udelay(10); + writel(0, dp_sub->base_addr + AVBUF_BUF_SRST_REG); // De-ssert reset. + + enable_main_link(dev, 1); + + debug("DONE!\n"); +} + +static int dp_tx_start_link_training(struct udevice *dev) +{ + u32 status; + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + + enable_main_link(dev, 0); + + if (!is_dp_connected(dev)) { + debug("! Disconnected.\n"); + return -ENODEV; + } + + status = dp_tx_wakeup(dev); + if (status) { + debug("! Wakeup failed.\n"); + return -EIO; + } + + do { + mdelay(100); + status = dp_hpd_train(dev); + if (status == -EINVAL) { + debug("Lost connection\n\r"); + return -EIO; + } else if (status) { + continue; + } + display_gfx_frame_buffer(dev); + setup_video_stream(dev); + status = check_link_status(dev, dp_sub->link_config.lane_count); + if (status == -EINVAL) + return -EIO; + } while (status != 0); + + return 0; +} + +static void init_run_config(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + + dp_sub->dp_dma = &dp_dma; + dp_sub->video_mode = VIDC_VM_1024x768_60_P; + dp_sub->bpc = VIDC_BPC_8; + dp_sub->color_encode = DP_CENC_RGB; + dp_sub->use_max_cfg_caps = 1; + dp_sub->lane_count = LANE_COUNT_1; + dp_sub->link_rate = LINK_RATE_540GBPS; + dp_sub->en_sync_clk_mode = 0; + dp_sub->use_max_lane_count = 1; + dp_sub->use_max_link_rate = 1; +} + +static int dpdma_setup(struct udevice *dev) +{ + int status; + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + + writel(DPDMA_ISR_VSYNC_INT_MASK, dp_sub->dp_dma->base_addr + DPDMA_IEN); + status = wait_for_bit_le32((u32 *)dp_sub->dp_dma->base_addr + DPDMA_ISR, + DPDMA_ISR_VSYNC_INT_MASK, false, 1000, false); + if (status) { + debug("%s: INTR TIMEDOUT\n", __func__); + return status; + } + debug("INTR dma_vsync_intr_handler called...\n"); + dma_vsync_intr_handler(dev); + + return 0; +} + +static int zynqmp_dpsub_init(struct udevice *dev) +{ + int status; + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + + /* Initialize the dpdma configuration */ + status = init_dpdma_subsys(dev); + if (status) + return -EINVAL; + + config_msa_sync_clk_mode(dev, dp_sub->en_sync_clk_mode); + set_video_clk_source(dev, AVBUF_PS_CLK, AVBUF_PS_CLK); + + return 0; +} + +static int dp_tx_run(struct udevice *dev) +{ + u32 interrupt_signal_state, interrupt_status, hpd_state, hpd_event; + u32 hpd_pulse_detected, hpd_duration, status; + int attempts = 0; + struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev); + + /* Continuously poll for HPD events. */ + while (attempts < 5) { + /* Read interrupt registers. */ + interrupt_signal_state = readl(dp_sub->base_addr + DP_INTERRUPT_SIG_STATE); + interrupt_status = readl(dp_sub->base_addr + DP_INTR_STATUS); + /* Check for HPD events. */ + hpd_state = interrupt_signal_state & DP_INTERRUPT_SIG_STATE_HPD_STATE_MASK; + hpd_event = interrupt_status & DP_INTR_HPD_EVENT_MASK; + hpd_pulse_detected = interrupt_status & DP_INTR_HPD_PULSE_DETECTED_MASK; + if (hpd_pulse_detected) + hpd_duration = readl(dp_sub->base_addr + DP_HPD_DURATION); + else + attempts++; + + /* HPD event handling. */ + if (hpd_state && hpd_event) { + debug("+===> HPD connection event detected.\n"); + /* Initiate link training. */ + status = dp_tx_start_link_training(dev); + if (status) { + debug("Link training failed\n"); + return status; + } + return 0; + } else if (hpd_state && hpd_pulse_detected && (hpd_duration >= 250)) { + debug("===> HPD pulse detected.\n"); + /* Re-train if needed. */ + status = dp_tx_start_link_training(dev); + if (status) { + debug("HPD pulse detection failed\n"); + return status; + } + return 0; + } else if (!hpd_state && hpd_event) { + debug("+===> HPD disconnection event detected.\n\n"); + /* Disable main link. */ + enable_main_link(dev, 0); + break; + } + } + return -EINVAL; +} + +static int zynqmp_dpsub_probe(struct udevice *dev) +{ + struct video_priv *uc_priv = dev_get_uclass_priv(dev); + struct zynqmp_dpsub_priv *priv = dev_get_priv(dev); + struct clk clk; + int ret; + int mode = RGBA8888; + + ret = clk_get_by_name(dev, "dp_apb_clk", &clk); + if (ret < 0) { + dev_err(dev, "failed to get clock\n"); + return ret; + } + + priv->clock = clk_get_rate(&clk); + if (IS_ERR_VALUE(priv->clock)) { + dev_err(dev, "failed to get rate\n"); + return priv->clock; + } + + ret = clk_enable(&clk); + if (ret) { + dev_err(dev, "failed to enable clock\n"); + return ret; + } + + dev_dbg(dev, "Base addr 0x%x, clock %d\n", (u32)priv->base_addr, + priv->clock); + + /* Initialize the DisplayPort TX core. */ + ret = init_dp_tx(dev); + if (ret) + return -EINVAL; + + /* Initialize the runtime configuration */ + init_run_config(dev); + /* Set the format graphics frame for Video Pipeline */ + ret = set_nonlive_gfx_format(dev, mode); + if (ret) + return ret; + + uc_priv->bpix = ffs(priv->non_live_graphics->bpp) - 1; + dev_dbg(dev, "BPP in bits %d, bpix %d\n", + priv->non_live_graphics->bpp, uc_priv->bpix); + + uc_priv->fb = (void *)gd->fb_base; + uc_priv->xsize = vidc_video_timing_modes[priv->video_mode].video_timing.h_active; + uc_priv->ysize = vidc_video_timing_modes[priv->video_mode].video_timing.v_active; + /* Calculated by core but need it for my own setup */ + uc_priv->line_length = uc_priv->xsize * VNBYTES(uc_priv->bpix); + /* Will be calculated again in video_post_probe() but I need that value now */ + uc_priv->fb_size = uc_priv->line_length * uc_priv->ysize; + + switch (mode) { + case RGBA8888: + uc_priv->format = VIDEO_RGBA8888; + break; + default: + debug("Unsupported mode\n"); + return -EINVAL; + } + + video_set_flush_dcache(dev, true); + debug("Video: WIDTH[%d]xHEIGHT[%d]xBPP[%d/%d] -- line length %d\n", uc_priv->xsize, + uc_priv->ysize, uc_priv->bpix, VNBYTES(uc_priv->bpix), uc_priv->line_length); + + enable_gfx_buffers(dev, 1); + avbuf_video_select(dev, AVBUF_VIDSTREAM1_NONE, AVBUF_VIDSTREAM2_NONLIVE_GFX); + config_gfx_pipeline(dev); + config_output_video(dev); + + ret = zynqmp_dpsub_init(dev); + if (ret) + return ret; + + /* Populate the FrameBuffer structure with the frame attributes */ + priv->frame_buffer.stride = uc_priv->line_length; + priv->frame_buffer.line_size = priv->frame_buffer.stride; + priv->frame_buffer.size = priv->frame_buffer.line_size * uc_priv->ysize; + + ret = dp_tx_run(dev); + if (ret) + return ret; + + return dpdma_setup(dev); +} + +static int zynqmp_dpsub_bind(struct udevice *dev) +{ + struct video_uc_plat *plat = dev_get_uclass_plat(dev); + + /* This is maximum size to allocate - it depends on BPP setting */ + plat->size = WIDTH * HEIGHT * 4; + /* plat->align is not defined that's why 1MB alignment is used */ + + /* + * plat->base can be used for allocating own location for FB + * if not defined then it is allocated by u-boot itself + */ + + return 0; +} + +static int zynqmp_dpsub_of_to_plat(struct udevice *dev) +{ + struct zynqmp_dpsub_priv *priv = dev_get_priv(dev); + struct resource res; + int ret; + + ret = dev_read_resource_byname(dev, "dp", &res); + if (ret) + return ret; + + priv->base_addr = res.start; + + return 0; +} + +static const struct udevice_id zynqmp_dpsub_ids[] = { + { .compatible = "xlnx,zynqmp-dpsub-1.7" }, + { } +}; + +U_BOOT_DRIVER(zynqmp_dpsub_video) = { + .name = "zynqmp_dpsub_video", + .id = UCLASS_VIDEO, + .of_match = zynqmp_dpsub_ids, + .plat_auto = sizeof(struct video_uc_plat), + .bind = zynqmp_dpsub_bind, + .probe = zynqmp_dpsub_probe, + .priv_auto = sizeof(struct zynqmp_dpsub_priv), + .of_to_plat = zynqmp_dpsub_of_to_plat, +}; diff --git a/drivers/video/zynqmp/zynqmp_dpsub.h b/drivers/video/zynqmp/zynqmp_dpsub.h new file mode 100644 index 00000000000..7d2737e31aa --- /dev/null +++ b/drivers/video/zynqmp/zynqmp_dpsub.h @@ -0,0 +1,680 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023, Advanced Micro Devices, Inc. + * + */ + +#ifndef _VIDEO_ZYNQMP_DPSUB_H +#define _VIDEO_ZYNQMP_DPSUB_H + +enum video_mode { + VIDC_VM_640x480_60_P = 0, + VIDC_VM_1024x768_60_P = 1, +}; + +enum { + LANE_COUNT_1 = 1, + LANE_COUNT_2 = 2, +}; + +enum { + LINK_RATE_162GBPS = 0x06, + LINK_RATE_270GBPS = 0x0A, + LINK_RATE_540GBPS = 0x14, +}; + +enum video_color_depth { + VIDC_BPC_6 = 6, + VIDC_BPC_8 = 8, + VIDC_BPC_10 = 10, + VIDC_BPC_12 = 12, + VIDC_BPC_14 = 14, + VIDC_BPC_16 = 16, + VIDC_BPC_NUM_SUPPORTED = 6, + VIDC_BPC_UNKNOWN +}; + +enum video_color_encoding { + DP_CENC_RGB = 0, + DP_CENC_YONLY, +}; + +enum dp_dma_channel_type { + VIDEO_CHAN, + GRAPHICS_CHAN, +}; + +enum dp_dma_channel_state { + DPDMA_DISABLE, + DPDMA_ENABLE, + DPDMA_IDLE, + DPDMA_PAUSE +}; + +enum link_training_states { + TS_CLOCK_RECOVERY, + TS_CHANNEL_EQUALIZATION, + TS_ADJUST_LINK_RATE, + TS_ADJUST_LANE_COUNT, + TS_FAILURE, + TS_SUCCESS +}; + +enum video_frame_rate { + VIDC_FR_60HZ = 60, + VIDC_FR_NUM_SUPPORTED = 2, + VIDC_FR_UNKNOWN +}; + +enum av_buf_video_modes { + INTERLEAVED, + SEMIPLANAR +}; + +enum av_buf_video_format { + RGBA8888 = 1, +}; + +enum av_buf_video_stream { + AVBUF_VIDSTREAM1_LIVE, + AVBUF_VIDSTREAM1_NONLIVE, + AVBUF_VIDSTREAM1_TPG, + AVBUF_VIDSTREAM1_NONE, +}; + +enum av_buf_gfx_stream { + AVBUF_VIDSTREAM2_DISABLEGFX = 0x0, + AVBUF_VIDSTREAM2_NONLIVE_GFX = 0x4, + AVBUF_VIDSTREAM2_LIVE_GFX = 0x8, + AVBUF_VIDSTREAM2_NONE = 0xC0, +}; + +/** + * struct aux_transaction - Description of an AUX channel transaction + * @cmd_code: Command code of the transaction + * @num_bytes: The number of bytes in the transaction's payload data + * @address: The DPCD address of the transaction + * @data: Payload data of the AUX channel transaction + */ +struct aux_transaction { + u16 cmd_code; + u8 num_bytes; + u32 address; + u8 *data; +}; + +/** + * struct link_config - Description of link configuration + * @lane_count: Currently selected lane count for this link + * @link_rate: Currently selected link rate for this link + * @scrambler_en: Flag to determine whether the scrambler is + * enabled for this link + * @enhanced_framing_mode: Flag to determine whether enhanced framing + * mode is active for this link + * @max_lane_count: Maximum lane count for this link + * @max_link_rate: Maximum link rate for this link + * @support_enhanced_framing_mode: Flag to indicate whether the link supports + * enhanced framing mode + * @vs_level: Voltage swing for each lane + * @pe_level: Pre-emphasis/cursor level for each lane + * @pattern: The current pattern currently in use over the main link + */ +struct link_config { + u8 lane_count; + u8 link_rate; + u8 scrambler_en; + u8 enhanced_framing_mode; + u8 max_lane_count; + u8 max_link_rate; + u8 support_enhanced_framing_mode; + u8 support_downspread_control; + u8 vs_level; + u8 pe_level; + u8 pattern; +}; + +struct video_timing { + u16 h_active; + u16 h_front_porch; + u16 h_sync_width; + u16 h_back_porch; + u16 h_total; + bool h_sync_polarity; + u16 v_active; + u16 f0_pv_front_porch; + u16 f0_pv_sync_width; + u16 f0_pv_back_porch; + u16 f0_pv_total; + u16 f1_v_front_porch; + u16 f1_v_sync_width; + u16 f1_v_back_porch; + u16 f1_v_total; + bool v_sync_polarity; +}; + +struct video_timing_mode { + enum video_mode vid_mode; + char name[21]; + enum video_frame_rate frame_rate; + struct video_timing video_timing; +}; + +/* + * struct main_stream_attributes - Main Stream Attributes (MSA) + * @pixel_clock_hz: The pixel clock of the stream (in Hz) + * @h_start: Horizontal blank start (in pixels) + * @v_start: Vertical blank start (in lines). + * @misc0: Miscellaneous stream attributes 0 + * @misc1: Miscellaneous stream attributes 1 + * @n_vid N value for the video stream + * @user_pixel_width: The width of the user data input port. + * @data_per_plane: Used to translate the number of pixels per + * line to the native internal 16-bit datapath. + * @avg_bytes_per_tu: Average number of bytes per transfer unit, + * scaled up by a factor of 1000. + * @transfer_unit_size: Size of the transfer unit in the + * framing logic. + * @init_wait: Number of initial wait cycles at the start + * of a new line by the framing logic. + * @bits_per_color: Number of bits per color component. + * @component_format: The component format currently in + * use by the video stream. + * @dynamic_range: The dynamic range currently in use + * by the video stream. + * @y_cb_cr_colorimetry: The YCbCr colorimetry currently in + * use by the video stream. + * @synchronous_clock_mode: Synchronous clock mode is currently + * in use by the video stream. + */ +struct main_stream_attributes { + struct video_timing_mode vid_timing_mode; + u32 pixel_clock_hz; + u32 h_start; + u32 v_start; + u32 misc0; + u32 misc1; + u32 n_vid; + u32 user_pixel_width; + u32 data_per_lane; + u32 avg_bytes_per_tu; + u32 transfer_unit_size; + u32 init_wait; + u32 bits_per_color; + u8 component_format; + u8 dynamic_range; + u8 y_cb_cr_colorimetry; + u8 synchronous_clock_mode; +}; + +struct av_buf_vid_attribute { + enum av_buf_video_format video_format; + u8 value; + enum av_buf_video_modes mode; + u32 sf[3]; + u8 sampling_en; + u8 is_rgb; + u8 swap; + u8 bpp; +}; + +struct av_buf_mode { + enum av_buf_video_stream video_src; + enum av_buf_gfx_stream gfx_src; + u8 video_clk; +}; + +struct dp_dma_descriptor { + u32 control; + u32 dscr_id; + u32 xfer_size; + u32 line_size_stride; + u32 lsb_timestamp; + u32 msb_timestamp; + u32 addr_ext; + u32 next_desr; + u32 src_addr; + u32 addr_ext_23; + u32 addr_ext_45; + u32 src_addr2; + u32 src_addr3; + u32 src_addr4; + u32 src_addr5; + u32 crc; +}; + +struct dp_dma_channel { + struct dp_dma_descriptor *cur; +}; + +struct dp_dma_frame_buffer { + u64 address; + u32 size; + u32 stride; + u32 line_size; +}; + +struct dp_dma_gfx_channel { + struct dp_dma_channel channel; + u8 trigger_status; + u8 av_buf_en; + struct dp_dma_frame_buffer *frame_buffer; +}; + +struct dp_dma { + phys_addr_t base_addr; + struct dp_dma_gfx_channel gfx; +}; + +/** + * struct zynqmp_dpsub_priv - Private structure + * @dev: Device uclass for video_ops + */ +struct zynqmp_dpsub_priv { + phys_addr_t base_addr; + u32 clock; + struct av_buf_vid_attribute *non_live_graphics; + struct av_buf_mode av_mode; + struct dp_dma_frame_buffer frame_buffer; + + struct link_config link_config; + struct main_stream_attributes msa_config; + struct dp_dma *dp_dma; + enum video_mode video_mode; + enum video_color_depth bpc; + enum video_color_encoding color_encode; + u32 pix_clk; + u8 dpcd_rx_caps[16]; + u8 lane_status_ajd_reqs[6]; + u8 sink_count; + u8 use_max_lane_count; + u8 use_max_link_rate; + u8 lane_count; + u8 link_rate; + u8 use_max_cfg_caps; + u8 en_sync_clk_mode; +}; + +/**************************** Variable Definitions ****************************/ +#define TRAINING_PATTERN_SET 0x000C +#define TRAINING_PATTERN_SET_OFF 0x0 +#define SCRAMBLING_DISABLE 0x0014 +#define TRAINING_PATTERN_SET_TP1 0x1 +#define TRAINING_PATTERN_SET_TP2 0x2 +#define TRAINING_PATTERN_SET_TP3 0x3 + +#define AVBUF_BUF_4BIT_SF 0x11111 +#define AVBUF_BUF_5BIT_SF 0x10842 +#define AVBUF_BUF_6BIT_SF 0x10410 +#define AVBUF_BUF_8BIT_SF 0x10101 +#define AVBUF_BUF_10BIT_SF 0x10040 +#define AVBUF_BUF_12BIT_SF 0x10000 +#define AVBUF_BUF_6BPC 0x000 +#define AVBUF_BUF_8BPC 0x001 +#define AVBUF_BUF_10BPC 0x010 +#define AVBUF_BUF_12BPC 0x011 +#define AVBUF_CHBUF3 0x0000B01C +#define AVBUF_CHBUF3_BURST_LEN_SHIFT 2 +#define AVBUF_CHBUF3_FLUSH_MASK 0x00000002 +#define AVBUF_CHBUF0_EN_MASK 0x00000001 +#define AVBUF_BUF_OUTPUT_AUD_VID_SELECT 0x0000B070 +#define AVBUF_BUF_OUTPUT_AUD_VID_SELECT_VID_STREAM2_SEL_MASK 0x0000000C +#define AVBUF_BUF_OUTPUT_AUD_VID_SELECT_VID_STREAM1_SEL_MASK 0x00000003 +#define AVBUF_BUF_OUTPUT_AUD_VID_SELECT 0x0000B070 +#define AVBUF_BUF_GRAPHICS_COMP0_SCALE_FACTOR 0x0000B200 +#define AVBUF_V_BLEND_LAYER1_CONTROL 0x0000A01C +#define AVBUF_V_BLEND_IN2CSC_COEFF0 0x0000A080 +#define AVBUF_BUF_FORMAT 0x0000B000 +#define AVBUF_BUF_FORMAT_NL_VID_FORMAT_MASK 0x0000001F +#define AVBUF_BUF_FORMAT_NL_GRAPHX_FORMAT_MASK 0x00000F00 +#define AVBUF_BUF_FORMAT_NL_GRAPHX_FORMAT_SHIFT 8 +#define AVBUF_V_BLEND_LAYER0_CONTROL_RGB_MODE_SHIFT 1 +#define AVBUF_V_BLEND_OUTPUT_VID_FORMAT_EN_DOWNSAMPLE_SHIFT 4 +#define AVBUF_V_BLEND_OUTPUT_VID_FORMAT 0x0000A014 +#define AVBUF_V_BLEND_RGB2YCBCR_COEFF0 0x0000A020 +#define AVBUF_V_BLEND_LUMA_OUTCSC_OFFSET 0x0000A074 +#define AVBUF_V_BLEND_LUMA_IN1CSC_OFFSET_POST_OFFSET_SHIFT 16 +#define AVBUF_V_BLEND_SET_GLOBAL_ALPHA_REG_VALUE_SHIFT 1 +#define AVBUF_V_BLEND_SET_GLOBAL_ALPHA_REG 0x0000A00C +#define DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_SHIFT 1 +#define DP_MAIN_STREAM_MISC0_DYNAMIC_RANGE_SHIFT 3 +#define DP_MAIN_STREAM_MISC0_YCBCR_COLORIMETRY_SHIFT 4 +#define DP_MAIN_STREAM_MISC1_Y_ONLY_EN_MASK 0x00000080 +#define DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_YCBCR422 0x1 +#define AVBUF_PL_CLK 0x0 +#define AVBUF_PS_CLK 0x1 +#define AVBUF_BUF_AUD_VID_CLK_SOURCE_VID_TIMING_SRC_SHIFT 2 +#define AVBUF_BUF_AUD_VID_CLK_SOURCE_VID_CLK_SRC_SHIFT 0 +#define AVBUF_BUF_AUD_VID_CLK_SOURCE_AUD_CLK_SRC_SHIFT 1 +#define AVBUF_BUF_AUD_VID_CLK_SOURCE 0x0000B120 +#define AVBUF_BUF_SRST_REG 0x0000B124 +#define AVBUF_BUF_SRST_REG_VID_RST_MASK 0x00000002 +#define AVBUF_CLK_FPD_BASEADDR 0xFD1A0000 +#define AVBUF_CLK_LPD_BASEADDR 0xFF5E0000 +#define AVBUF_LPD_CTRL_OFFSET 16 +#define AVBUF_FPD_CTRL_OFFSET 12 +#define AVBUF_EXTERNAL_DIVIDER 2 +#define AVBUF_VIDEO_REF_CTRL 0x00000070 +#define AVBUF_VIDEO_REF_CTRL_SRCSEL_MASK 0x00000007 +#define AVBUF_VPLL_SRC_SEL 0 +#define AVBUF_DPLL_SRC_SEL 2 +#define AVBUF_RPLL_TO_FPD_SRC_SEL 3 +#define AVBUF_INPUT_REF_CLK 3333333333 +#define AVBUF_PLL_OUT_FREQ 1450000000 +#define AVBUF_INPUT_FREQ_PRECISION 100 +#define AVBUF_PRECISION 16 +#define AVBUF_SHIFT_DECIMAL BIT(16) +#define AVBUF_DECIMAL (AVBUF_SHIFT_DECIMAL - 1) +#define AVBUF_ENABLE_BIT 1 +#define AVBUF_DISABLE_BIT 0 +#define AVBUF_PLL_CTRL_BYPASS_SHIFT 3 +#define AVBUF_PLL_CTRL_FBDIV_SHIFT 8 +#define AVBUF_PLL_CTRL_DIV2_SHIFT 16 +#define AVBUF_PLL_CTRL_PRE_SRC_SHIFT 20 +#define AVBUF_PLL_CTRL 0x00000020 +#define AVBUF_PLL_CFG_CP_SHIFT 5 +#define AVBUF_PLL_CFG_RES_SHIFT 0 +#define AVBUF_PLL_CFG_LFHF_SHIFT 10 +#define AVBUF_PLL_CFG_LOCK_DLY_SHIFT 25 +#define AVBUF_PLL_CFG_LOCK_CNT_SHIFT 13 +#define AVBUF_PLL_FRAC_CFG 0x00000028 +#define AVBUF_PLL_FRAC_CFG_ENABLED_SHIFT 31 +#define AVBUF_PLL_FRAC_CFG_DATA_SHIFT 0 +#define AVBUF_PLL_CTRL_RESET_MASK 0x00000001 +#define AVBUF_PLL_CTRL_RESET_SHIFT 0 +#define AVBUF_PLL_STATUS 0x00000044 +#define AVBUF_REG_OFFSET 4 +#define AVBUF_PLL_CTRL_BYPASS_MASK 0x00000008 +#define AVBUF_PLL_CTRL_BYPASS_SHIFT 3 +#define AVBUF_DOMAIN_SWITCH_CTRL 0x00000044 +#define AVBUF_DOMAIN_SWITCH_DIVISOR0_MASK 0x00003F00 +#define AVBUF_DOMAIN_SWITCH_DIVISOR0_SHIFT 8 +#define AVBUF_PLL_CFG 0x00000024 +#define AVBUF_BUF_AUD_VID_CLK_SOURCE_VID_CLK_SRC_SHIFT 0 +#define AVBUF_VIDEO_REF_CTRL_CLKACT_MASK 0x01000000 +#define AVBUF_VIDEO_REF_CTRL_CLKACT_SHIFT 24 +#define AVBUF_VIDEO_REF_CTRL_DIVISOR1_MASK 0x003F0000 +#define AVBUF_VIDEO_REF_CTRL_DIVISOR1_SHIFT 16 +#define AVBUF_VIDEO_REF_CTRL_DIVISOR0_MASK 0x00003F00 +#define AVBUF_VIDEO_REF_CTRL_DIVISOR0_SHIFT 8 +#define AVBUF_VIDEO_REF_CTRL_CLKACT_MASK 0x01000000 +#define AVBUF_VIDEO_REF_CTRL_CLKACT_SHIFT 24 + +#define DP_INTERRUPT_SIG_STATE 0x0130 +#define DP_INTR_STATUS 0x03A0 +#define DP_INTERRUPT_SIG_STATE_HPD_STATE_MASK 0x00000001 +#define DP_INTR_HPD_EVENT_MASK 0x00000002 +#define DP_INTR_HPD_PULSE_DETECTED_MASK 0x00000010 +#define DP_HPD_DURATION 0x0150 +#define DP_FORCE_SCRAMBLER_RESET 0x00C0 +#define DP_ENABLE_MAIN_STREAM 0x0084 +#define DP_IS_CONNECTED_MAX_TIMEOUT_COUNT 50 +#define DP_0_LINK_RATE 20 +#define DP_0_LANE_COUNT 1 +#define DP_ENHANCED_FRAME_EN 0x0008 +#define DP_LANE_COUNT_SET 0x0004 +#define DP_LINK_BW_SET_162GBPS 0x06 +#define DP_LINK_BW_SET_270GBPS 0x0A +#define DP_LINK_BW_SET_540GBPS 0x14 +#define DP_LINK_BW_SET 0x0000 +#define DP_DOWNSPREAD_CTRL 0x0018 +#define DP_SCRAMBLING_DISABLE 0x0014 +#define DP_AUX_CMD_READ 0x9 +#define DP_AUX_CMD_WRITE 0x8 +#define DP_AUX_CMD_I2C_READ 0x1 +#define DP_AUX_CMD_I2C_READ_MOT 0x5 +#define DP_AUX_CMD_I2C_WRITE 0x0 +#define DP_AUX_CMD_I2C_WRITE_MOT 0x4 +#define DP_REPLY_STATUS_REPLY_IN_PROGRESS_MASK 0x00000002 +#define DP_REPLY_STATUS_REQUEST_IN_PROGRESS_MASK 0x00000004 +#define DP_REPLY_STATUS 0x014C +#define DP_AUX_MAX_TIMEOUT_COUNT 50 +#define DP_AUX_MAX_DEFER_COUNT 50 +#define DP_AUX_ADDRESS 0x0108 +#define DP_AUX_WRITE_FIFO 0x0104 +#define DP_AUX_CMD 0x0100 +#define DP_AUX_CMD_SHIFT 8 +#define DP_AUX_CMD_NBYTES_TRANSFER_MASK 0x0000000F +#define DP_AUX_REPLY_CODE 0x0138 +#define DP_AUX_REPLY_CODE_DEFER 0x2 +#define DP_AUX_REPLY_CODE_I2C_DEFER 0x8 +#define DP_AUX_REPLY_CODE_NACK 0x1 +#define DP_AUX_REPLY_CODE_I2C_NACK 0x4 +#define DP_REPLY_DATA_COUNT 0x0148 +#define DP_AUX_REPLY_DATA 0x0134 +#define DP_LANE_COUNT_SET_1 0x01 +#define DP_LANE_COUNT_SET_2 0x02 +#define DP_MAXIMUM_PE_LEVEL 2 +#define DP_MAXIMUM_VS_LEVEL 3 +#define DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_RGB 0x0 +#define DP_MAIN_STREAM_MISC0_BDC_6BPC 0x0 +#define DP_MAIN_STREAM_MISC0_BDC_8BPC 0x1 +#define DP_MAIN_STREAM_MISC0_BDC_10BPC 0x2 +#define DP_MAIN_STREAM_MISC0_BDC_12BPC 0x3 +#define DP_MAIN_STREAM_MISC0_BDC_16BPC 0x4 +#define DP_MAIN_STREAM_MISC0_BDC_SHIFT 5 +#define DP_PHY_CONFIG_TX_PHY_8B10BEN_MASK 0x0010000 +#define DP_PHY_CONFIG_PHY_RESET_MASK 0x0000001 +#define DP_ENABLE_MAIN_STREAM 0x0084 +#define DP_SOFT_RESET 0x001C +#define DP_MAIN_STREAM_HTOTAL 0x0180 +#define DP_MAIN_STREAM_VTOTAL 0x0184 +#define DP_MAIN_STREAM_POLARITY 0x0188 +#define DP_MAIN_STREAM_POLARITY_VSYNC_POL_SHIFT 1 +#define DP_MAIN_STREAM_HSWIDTH 0x018C +#define DP_MAIN_STREAM_VSWIDTH 0x0190 +#define DP_MAIN_STREAM_HRES 0x0194 +#define DP_MAIN_STREAM_VRES 0x0198 +#define DP_MAIN_STREAM_HSTART 0x019C +#define DP_MAIN_STREAM_VSTART 0x01A0 +#define DP_MAIN_STREAM_MISC0 0x01A4 +#define DP_MAIN_STREAM_MISC1 0x01A8 +#define DP_M_VID 0x01AC +#define DP_N_VID 0x01B4 +#define DP_USER_PIXEL_WIDTH 0x01B8 +#define DP_USER_DATA_COUNT_PER_LANE 0x01BC +#define DP_TU_SIZE 0x01B0 +#define DP_MIN_BYTES_PER_TU 0x01C4 +#define DP_FRAC_BYTES_PER_TU 0x01C8 +#define DP_INIT_WAIT 0x01CC +#define DP_PHY_CLOCK_SELECT_162GBPS 0x1 +#define DP_PHY_CLOCK_SELECT_270GBPS 0x3 +#define DP_PHY_CLOCK_SELECT_540GBPS 0x5 +#define DP_PHY_STATUS 0x0280 +#define DP_PHY_STATUS_ALL_LANES_READY_MASK 0x00000013 +#define DP_PHY_STATUS_GT_PLL_LOCK_MASK 0x00000010 +#define DP_PHY_STATUS_RESET_LANE_0_DONE_MASK 0x00000001 +#define DP_INTR_HPD_IRQ_MASK 0x00000001 +#define DP_INTR_MASK 0x03A4 +#define DP_DP_ENABLE 0x1 +#define DP_PHY_CONFIG_GT_ALL_RESET_MASK 0x0000003 +#define DP_PHY_CLOCK_SELECT 0x0234 +#define DP_AUX_CLK_DIVIDER_VAL_MASK 0x000000FF +#define DP_AUX_CLK_DIVIDER 0x010C +#define DP_DISABLE 0x0 +#define DP_ENABLE 0x0080 +#define DP_SOFT_RESET_EN 0x1 +#define DP_PHY_CONFIG 0x0200 +#define DP_REPLY_STATUS_REPLY_RECEIVED_MASK 0x00000001 +#define DP_REPLY_STATUS_REPLY_IN_PROGRESS_MASK 0x00000002 +#define DP_REPLY_STATUS_REPLY_ERROR_MASK 0x00000008 +#define DP_AUX_MAX_WAIT 20000 + +#define DP_DPCD_SINK_COUNT 0x00200 +#define DP_DPCD_TP_SET_SCRAMB_DIS_MASK 0x20 +#define DP_DPCD_STATUS_LANE_1_CR_DONE_MASK 0x10 +#define DP_DPCD_STATUS_LANE_0_CR_DONE_MASK 0x01 +#define DP_DPCD_STATUS_LANE_1_CE_DONE_MASK 0x20 +#define DP_DPCD_STATUS_LANE_0_CE_DONE_MASK 0x02 +#define DP_DPCD_STATUS_LANE_1_SL_DONE_MASK 0x40 +#define DP_DPCD_STATUS_LANE_0_SL_DONE_MASK 0x04 +#define DP_DPCD_LANE_ALIGN_STATUS_UPDATED_IA_DONE_MASK 0x01 +#define DP_DPCD_ADJ_REQ_LANE_0_2_VS_MASK 0x03 +#define DP_DPCD_ADJ_REQ_LANE_1_3_VS_MASK 0x30 +#define DP_DPCD_ADJ_REQ_LANE_1_3_VS_SHIFT 4 +#define DP_DPCD_ADJ_REQ_LANE_0_2_PE_MASK 0x0C +#define DP_DPCD_ADJ_REQ_LANE_0_2_PE_SHIFT 2 +#define DP_DPCD_ADJ_REQ_LANE_1_3_PE_MASK 0xC0 +#define DP_DPCD_ADJ_REQ_LANE_1_3_PE_SHIFT 6 +#define DP_DPCD_TRAINING_LANE0_SET 0x00103 +#define DP_DPCD_TRAINING_LANEX_SET_MAX_VS_MASK 0x04 +#define DP_DPCD_TRAINING_LANEX_SET_MAX_PE_MASK 0x20 +#define DP_DPCD_TRAINING_LANEX_SET_PE_SHIFT 3 +#define DP_DPCD_SET_POWER_DP_PWR_VOLTAGE 0x00600 +#define DP_DPCD_RECEIVER_CAP_FIELD_START 0x00000 +#define DP_DPCD_MAX_LINK_RATE 0x00001 +#define DP_DPCD_MAX_LANE_COUNT 0x00002 +#define DP_DPCD_MAX_LANE_COUNT_MASK 0x1F +#define DP_DPCD_ENHANCED_FRAME_SUPPORT_MASK 0x80 +#define DP_DPCD_MAX_DOWNSPREAD 0x00003 +#define DP_DPCD_MAX_DOWNSPREAD_MASK 0x01 +#define DP_DPCD_LANE_COUNT_SET 0x00101 +#define DP_DPCD_ENHANCED_FRAME_EN_MASK 0x80 +#define DP_DPCD_LINK_BW_SET 0x00100 +#define DP_DPCD_DOWNSPREAD_CTRL 0x00107 +#define DP_DPCD_SPREAD_AMP_MASK 0x10 +#define DP_DPCD_LANE_COUNT_SET_MASK 0x1F +#define DP_DPCD_TPS3_SUPPORT_MASK 0x40 +#define DP_DPCD_TRAIN_AUX_RD_INTERVAL 0x0000E +#define DP_DPCD_SINK_COUNT_HIGH_MASK 0x80 +#define DP_DPCD_SINK_COUNT_HIGH_LOW_SHIFT 1 +#define DP_DPCD_SINK_COUNT_LOW_MASK 0x3F +#define DP_DPCD_TP_SET 0x00102 + +#define SERDES_BASEADDR 0xFD400000 +#define SERDES_L0_TX_MARGININGF 0x0CC0 +#define SERDES_L0_TX_DEEMPHASIS 0x0048 +#define SERDES_LANE_OFFSET 0x4000 + +#define DPDMA_TRIGGER_EN 1U +#define DPDMA_RETRIGGER_EN 2U +#define DPDMA_DESC_PREAMBLE 0xA5U +#define DPDMA_DESC_IGNR_DONE 0x400U +#define DPDMA_DESC_LAST_FRAME 0x200000U +#define DPDMA_DESCRIPTOR_LINE_SIZE_STRIDE_SHIFT 18 +#define DPDMA_DESCRIPTOR_SRC_ADDR_WIDTH 32U +#define DPDMA_DESCRIPTOR_ADDR_EXT_SRC_ADDR_EXT_SHIFT 16U +#define DPDMA_CH0_DSCR_STRT_ADDR 0X0204U +#define DPDMA_CH_OFFSET 0x100U +#define DPDMA_CH0_CNTL 0x0218U +#define DPDMA_CH3_CNTL 0x0518U +#define DPDMA_CH0_DSCR_STRT_ADDRE 0x0200U +#define DPDMA_CH3_DSCR_STRT_ADDR 0x0504 +#define DPDMA_CH3_DSCR_STRT_ADDRE 0x0500 +#define DPDMA_CH_CNTL_EN_MASK 0x1U +#define DPDMA_CH_CNTL_PAUSE_MASK 0x2U +#define DPDMA_GBL 0x0104U +#define DPDMA_GBL_TRG_CH3_MASK 0x8 +#define DPDMA_TRIGGER_DONE 0U +#define DPDMA_CH_CNTL_EN_MASK 0x1U +#define DPDMA_CH_CNTL_PAUSE_MASK 0x2U +#define DPDMA_CH_CNTL_QOS_DATA_RD_SHIFT 10U +#define DPDMA_CH_CNTL_QOS_DATA_RD_MASK 0x3C00U +#define DPDMA_CH_CNTL_QOS_DSCR_RD_SHIFT 6U +#define DPDMA_CH_CNTL_QOS_DSCR_RD_MASK 0x03C0U +#define DPDMA_CH_CNTL_QOS_DSCR_WR_SHIFT 2U +#define DPDMA_CH_CNTL_QOS_DSCR_WR_MASK 0x3CU +#define DPDMA_CH_OFFSET 0x100U +#define DPDMA_WAIT_TIMEOUT 10000U +#define DPDMA_AUDIO_ALIGNMENT 128U +#define DPDMA_VIDEO_CHANNEL0 0U +#define DPDMA_VIDEO_CHANNEL1 1U +#define DPDMA_VIDEO_CHANNEL2 2U +#define DPDMA_GRAPHICS_CHANNEL 3U +#define DPDMA_AUDIO_CHANNEL0 4U +#define DPDMA_AUDIO_CHANNEL1 5U +#define DPDMA_DESC_PREAMBLE 0xA5U +#define DPDMA_DESC_IGNR_DONE 0x400U +#define DPDMA_DESC_UPDATE 0x200U +#define DPDMA_DESC_COMP_INTR 0x100U +#define DPDMA_DESC_LAST_FRAME 0x200000U +#define DPDMA_DESC_DONE_SHIFT 31U +#define DPDMA_QOS_MIN 4U +#define DPDMA_QOS_MAX 11U +#define DPDMA_BASE_ADDRESS 0xFD4C0000 +#define DPDMA_ISR 0x0004U +#define DPDMA_IEN 0x000CU +#define DPDMA_ISR_VSYNC_INT_MASK 0x08000000 + +#define CLK_FPD_BASEADDR 0xFD1A0000 +#define VIDEO_REF_CTRL 0x00000070 +#define VIDEO_REF_CTRL_SRCSEL_MASK 0x00000007 +#define PLL_OUT_FREQ 1450000000 +#define INPUT_FREQ_PRECISION 100 +#define PRECISION 16 +#define SHIFT_DECIMAL BIT(16) +#define ENABLE_BIT 1 +#define DISABLE_BIT 0 +#define PLL_CTRL_BYPASS_SHIFT 3 +#define PLL_CTRL_FBDIV_SHIFT 8 +#define PLL_CTRL_DIV2_SHIFT 16 +#define PLL_CTRL_PRE_SRC_SHIFT 20 +#define PLL_CTRL 0x00000020 +#define VPLL_CTRL 0x00000038 +#define PLL_CFG 0x00000024 +#define VPLL 2 +#define VPLL_CFG 0x0000003C +#define VPLL_CFG_CP 4 +#define VPLL_CFG_RES 6 +#define VPLL_CFG_LFHF 3 +#define VPLL_CFG_LOCK_DLY 63 +#define VPLL_CFG_LOCK_CNT 600 +#define PLL_STATUS_VPLL_LOCK 2 +#define PLL_CFG_CP_SHIFT 5 +#define PLL_CFG_RES_SHIFT 0 +#define PLL_CFG_LFHF_SHIFT 10 +#define PLL_CFG_LOCK_DLY_SHIFT 25 +#define PLL_CFG_LOCK_CNT_SHIFT 13 +#define PLL_FRAC_CFG 0x00000028 +#define VPLL_FRAC_CFG 0x00000040 +#define PLL_FRAC_CFG_ENABLED_SHIFT 31 +#define PLL_FRAC_CFG_DATA_SHIFT 0 +#define PLL_CTRL_RESET_MASK 0x00000001 +#define PLL_CTRL_RESET_SHIFT 0 +#define PLL_STATUS 0x00000044 +#define REG_OFFSET 4 +#define PLL_CTRL_BYPASS_MASK 0x00000008 +#define PLL_CTRL_BYPASS_SHIFT 3 +#define DOMAIN_SWITCH_CTRL 0x00000044 +#define DOMAIN_SWITCH_DIVISOR0_MASK 0x00003F00 +#define DOMAIN_SWITCH_DIVISOR0_SHIFT 8 +#define VIDEO_REF_CTRL_CLKACT_MASK 0x01000000 +#define VIDEO_REF_CTRL_CLKACT_SHIFT 24 +#define VIDEO_REF_CTRL_DIVISOR1_MASK 0x003F0000 +#define VIDEO_REF_CTRL_DIVISOR1_SHIFT 16 +#define VIDEO_REF_CTRL_DIVISOR0_MASK 0x00003F00 +#define VIDEO_REF_CTRL_DIVISOR0_SHIFT 8 +#define PSS_REF_CLK 0 +#define FPD_CTRL_OFFSET 12 +#define VIDC_VM_NUM_SUPPORTED 2 + +static const u32 vs[4][4] = { + { 0x2a, 0x27, 0x24, 0x20 }, + { 0x27, 0x23, 0x20, 0xff }, + { 0x24, 0x20, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff }, +}; + +static const u32 pe[4][4] = { + { 0x02, 0x02, 0x02, 0x02 }, + { 0x01, 0x01, 0x01, 0xff }, + { 0x00, 0x00, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff }, +}; + +const struct video_timing_mode vidc_video_timing_modes[VIDC_VM_NUM_SUPPORTED] = { + { VIDC_VM_640x480_60_P, "640x480@60Hz", VIDC_FR_60HZ, + {640, 16, 96, 48, 800, 0, + 480, 10, 2, 33, 525, 0, 0, 0, 0, 0} }, + { VIDC_VM_1024x768_60_P, "1024x768@60Hz", VIDC_FR_60HZ, + {1024, 24, 136, 160, 1344, 0, + 768, 3, 6, 29, 806, 0, 0, 0, 0, 0} }, +}; + +const struct av_buf_vid_attribute avbuf_supported_formats[] = { + /* Non-Live Graphics formats */ + { RGBA8888, 0, INTERLEAVED, + {AVBUF_BUF_8BIT_SF, AVBUF_BUF_8BIT_SF, AVBUF_BUF_8BIT_SF}, + 0, 1, 0, 32}, +}; + +#endif diff --git a/drivers/video/zynqmp_dpsub.c b/drivers/video/zynqmp_dpsub.c deleted file mode 100644 index 4ead663cd59..00000000000 --- a/drivers/video/zynqmp_dpsub.c +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2021 Xilinx Inc. - */ - -#include <common.h> -#include <cpu_func.h> -#include <dm.h> -#include <errno.h> -#include <video.h> -#include <dm/device_compat.h> - -#define WIDTH 640 -#define HEIGHT 480 - -/** - * struct zynqmp_dpsub_priv - Private structure - * @dev: Device uclass for video_ops - */ -struct zynqmp_dpsub_priv { - struct udevice *dev; -}; - -static int zynqmp_dpsub_probe(struct udevice *dev) -{ - struct video_priv *uc_priv = dev_get_uclass_priv(dev); - struct zynqmp_dpsub_priv *priv = dev_get_priv(dev); - - uc_priv->bpix = VIDEO_BPP16; - uc_priv->xsize = WIDTH; - uc_priv->ysize = HEIGHT; - uc_priv->rot = 0; - - priv->dev = dev; - - /* Only placeholder for power domain driver */ - return 0; -} - -static int zynqmp_dpsub_bind(struct udevice *dev) -{ - struct video_uc_plat *plat = dev_get_uclass_plat(dev); - - plat->size = WIDTH * HEIGHT * 16; - - return 0; -} - -static const struct video_ops zynqmp_dpsub_ops = { -}; - -static const struct udevice_id zynqmp_dpsub_ids[] = { - { .compatible = "xlnx,zynqmp-dpsub-1.7" }, - { } -}; - -U_BOOT_DRIVER(zynqmp_dpsub_video) = { - .name = "zynqmp_dpsub_video", - .id = UCLASS_VIDEO, - .of_match = zynqmp_dpsub_ids, - .ops = &zynqmp_dpsub_ops, - .plat_auto = sizeof(struct video_uc_plat), - .bind = zynqmp_dpsub_bind, - .probe = zynqmp_dpsub_probe, - .priv_auto = sizeof(struct zynqmp_dpsub_priv), -}; diff --git a/dts/Kconfig b/dts/Kconfig index 3b7489f0f87..9152f5885e9 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -171,7 +171,7 @@ config OF_LIST default DEFAULT_DEVICE_TREE help This option specifies a list of device tree files to use for DT - control. These will be packaged into a FIT. At run-time, U-boot + control. These will be packaged into a FIT. At run-time, U-Boot or SPL will select the correct DT to use by examining the hardware (e.g. reading a board ID value). This is a list of device tree files (without the directory or .dtb suffix) @@ -254,7 +254,7 @@ config DTB_RESELECT config MULTI_DTB_FIT bool "Support embedding several DTBs in a FIT image for u-boot" help - This option provides hooks to allow U-boot to parse an + This option provides hooks to allow U-Boot to parse an appended FIT image and enable board specific code to then select the correct DTB to be used. Use this if you need to support multiple DTBs but don't use the SPL. diff --git a/fs/btrfs/compat.h b/fs/btrfs/compat.h index 9cf8a10c76c..02173dea5f4 100644 --- a/fs/btrfs/compat.h +++ b/fs/btrfs/compat.h @@ -46,7 +46,7 @@ /* * Read data from device specified by @desc and @part * - * U-boot equivalent of pread(). + * U-Boot equivalent of pread(). * * Return the bytes of data read. * Return <0 for error. diff --git a/fs/btrfs/extent-io.h b/fs/btrfs/extent-io.h index 6b0c87da969..5c5c579d1ea 100644 --- a/fs/btrfs/extent-io.h +++ b/fs/btrfs/extent-io.h @@ -8,7 +8,7 @@ * Use pointer to provide better alignment. * - Remove max_cache_size related interfaces * Includes free_extent_buffer_nocache() - * As we don't cache eb in U-boot. + * As we don't cache eb in U-Boot. * - Include headers * * Write related functions are kept as we still need to modify dummy extent diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h index 011f0034c50..995427db63c 100644 --- a/include/configs/xilinx_zynqmp.h +++ b/include/configs/xilinx_zynqmp.h @@ -60,6 +60,9 @@ "scriptaddr=0x20000000\0" \ "ramdisk_addr_r=0x02100000\0" \ "script_size_f=0x80000\0" \ + "stdin=serial\0" \ + "stdout=serial,vidconsole\0" \ + "stderr=serial,vidconsole\0" \ #if defined(CONFIG_MMC_SDHCI_ZYNQ) # define BOOT_TARGET_DEVICES_MMC(func) func(MMC, mmc, 0) func(MMC, mmc, 1) diff --git a/include/fsl_validate.h b/include/fsl_validate.h index fbcbd424967..66a5883f1f7 100644 --- a/include/fsl_validate.h +++ b/include/fsl_validate.h @@ -275,9 +275,9 @@ int fsl_check_boot_mode_secure(void); int fsl_setenv_chain_of_trust(void); /* - * This function is used to validate the main U-boot binary from + * This function is used to validate the main U-Boot binary from * SPL just before passing control to it using QorIQ Trust - * Architecture header (appended to U-boot image). + * Architecture header (appended to U-Boot image). */ void spl_validate_uboot(uint32_t hdr_addr, uintptr_t img_addr); diff --git a/include/video.h b/include/video.h index 29c4f51efb0..03434a81234 100644 --- a/include/video.h +++ b/include/video.h @@ -64,6 +64,7 @@ enum video_log2_bpp { enum video_format { VIDEO_UNKNOWN, + VIDEO_RGBA8888, VIDEO_X8B8G8R8, VIDEO_X8R8G8B8, VIDEO_X2R10G10B10, diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h index f7a4a39d350..1192d5902dc 100644 --- a/include/zynqmp_firmware.h +++ b/include/zynqmp_firmware.h @@ -35,7 +35,7 @@ enum pm_api_id { PM_FPGA_LOAD = 22, PM_FPGA_GET_STATUS = 23, PM_GET_CHIPID = 24, - /* ID 25 is been used by U-boot to process secure boot images */ + /* ID 25 is been used by U-Boot to process secure boot images */ /* Secure library generic API functions */ PM_SECURE_SHA = 26, PM_SECURE_RSA = 27, diff --git a/test/py/tests/test_android/test_avb.py b/test/py/tests/test_android/test_avb.py index bc5c5b55821..238b48c90fa 100644 --- a/test/py/tests/test_android/test_avb.py +++ b/test/py/tests/test_android/test_avb.py @@ -5,7 +5,7 @@ # Android Verified Boot 2.0 Test """ -This tests Android Verified Boot 2.0 support in U-boot: +This tests Android Verified Boot 2.0 support in U-Boot: For additional details about how to build proper vbmeta partition check doc/android/avb2.rst diff --git a/test/py/tests/test_cat/conftest.py b/test/py/tests/test_cat/conftest.py index 058fe523521..fc396f50d32 100644 --- a/test/py/tests/test_cat/conftest.py +++ b/test/py/tests/test_cat/conftest.py @@ -13,7 +13,7 @@ def cat_data(u_boot_config): """Set up a file system to be used in cat tests Args: - u_boot_config -- U-boot configuration. + u_boot_config -- U-Boot configuration. """ mnt_point = u_boot_config.persistent_data_dir + '/test_cat' image_path = u_boot_config.persistent_data_dir + '/cat.img' diff --git a/test/py/tests/test_efi_bootmgr/conftest.py b/test/py/tests/test_efi_bootmgr/conftest.py index eabafa54298..0eca025058e 100644 --- a/test/py/tests/test_efi_bootmgr/conftest.py +++ b/test/py/tests/test_efi_bootmgr/conftest.py @@ -12,7 +12,7 @@ def efi_bootmgr_data(u_boot_config): """Set up a file system to be used in UEFI bootmanager tests. Args: - u_boot_config -- U-boot configuration. + u_boot_config -- U-Boot configuration. Return: A path to disk image to be used for testing diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py index d0e20df01e3..054be1ee971 100644 --- a/test/py/tests/test_efi_capsule/conftest.py +++ b/test/py/tests/test_efi_capsule/conftest.py @@ -17,7 +17,7 @@ def efi_capsule_data(request, u_boot_config): for testing. request -- Pytest request object. - u_boot_config -- U-boot configuration. + u_boot_config -- U-Boot configuration. """ mnt_point = u_boot_config.persistent_data_dir + '/test_efi_capsule' data_dir = mnt_point + CAPSULE_DATA_DIR diff --git a/test/py/tests/test_efi_secboot/conftest.py b/test/py/tests/test_efi_secboot/conftest.py index 30ff7029438..ff7ac7c8101 100644 --- a/test/py/tests/test_efi_secboot/conftest.py +++ b/test/py/tests/test_efi_secboot/conftest.py @@ -14,7 +14,7 @@ def efi_boot_env(request, u_boot_config): Args: request: Pytest request object. - u_boot_config: U-boot configuration. + u_boot_config: U-Boot configuration. Return: A path to disk image to be used for testing @@ -139,7 +139,7 @@ def efi_boot_env_intca(request, u_boot_config): Args: request: Pytest request object. - u_boot_config: U-boot configuration. + u_boot_config: U-Boot configuration. Return: A path to disk image to be used for testing diff --git a/test/py/tests/test_eficonfig/conftest.py b/test/py/tests/test_eficonfig/conftest.py index f289df03626..0a82fbefd75 100644 --- a/test/py/tests/test_eficonfig/conftest.py +++ b/test/py/tests/test_eficonfig/conftest.py @@ -14,7 +14,7 @@ def efi_eficonfig_data(u_boot_config): tests Args: - u_boot_config -- U-boot configuration. + u_boot_config -- U-Boot configuration. Return: A path to disk image to be used for testing diff --git a/test/py/tests/test_fs/conftest.py b/test/py/tests/test_fs/conftest.py index 9329ec6f1b2..0d87d180c7b 100644 --- a/test/py/tests/test_fs/conftest.py +++ b/test/py/tests/test_fs/conftest.py @@ -97,7 +97,7 @@ def pytest_generate_tests(metafunc): # Helper functions # def fstype_to_ubname(fs_type): - """Convert a file system type to an U-boot specific string + """Convert a file system type to an U-Boot specific string A generated string can be used as part of file system related commands or a config name in u-boot. Currently fat16 and fat32 are handled @@ -217,7 +217,7 @@ def fs_obj_basic(request, u_boot_config): Args: request: Pytest request object. - u_boot_config: U-boot configuration. + u_boot_config: U-Boot configuration. Return: A fixture for basic fs test, i.e. a triplet of file system type, @@ -339,7 +339,7 @@ def fs_obj_ext(request, u_boot_config): Args: request: Pytest request object. - u_boot_config: U-boot configuration. + u_boot_config: U-Boot configuration. Return: A fixture for extended fs test, i.e. a triplet of file system type, @@ -440,7 +440,7 @@ def fs_obj_mkdir(request, u_boot_config): Args: request: Pytest request object. - u_boot_config: U-boot configuration. + u_boot_config: U-Boot configuration. Return: A fixture for mkdir test, i.e. a duplet of file system type and @@ -471,7 +471,7 @@ def fs_obj_unlink(request, u_boot_config): Args: request: Pytest request object. - u_boot_config: U-boot configuration. + u_boot_config: U-Boot configuration. Return: A fixture for unlink test, i.e. a duplet of file system type and @@ -551,7 +551,7 @@ def fs_obj_symlink(request, u_boot_config): Args: request: Pytest request object. - u_boot_config: U-boot configuration. + u_boot_config: U-Boot configuration. Return: A fixture for basic fs test, i.e. a triplet of file system type, diff --git a/test/py/tests/test_scp03.py b/test/py/tests/test_scp03.py index 1f689252ddf..1a104b365f7 100644 --- a/test/py/tests/test_scp03.py +++ b/test/py/tests/test_scp03.py @@ -5,7 +5,7 @@ # SCP03 command test """ -This tests SCP03 command in U-boot. +This tests SCP03 command in U-Boot. For additional details check doc/usage/scp03.rst """ diff --git a/test/py/tests/test_xxd/conftest.py b/test/py/tests/test_xxd/conftest.py index 59285aadf40..f35b8f11136 100644 --- a/test/py/tests/test_xxd/conftest.py +++ b/test/py/tests/test_xxd/conftest.py @@ -13,7 +13,7 @@ def xxd_data(u_boot_config): """Set up a file system to be used in xxd tests Args: - u_boot_config -- U-boot configuration. + u_boot_config -- U-Boot configuration. """ mnt_point = u_boot_config.persistent_data_dir + '/test_xxd' image_path = u_boot_config.persistent_data_dir + '/xxd.img' diff --git a/tools/relocate-rela.c b/tools/relocate-rela.c index fe8cd6bda98..f230ec5676c 100644 --- a/tools/relocate-rela.c +++ b/tools/relocate-rela.c @@ -521,7 +521,7 @@ static int rela_elf32(char **argv, FILE *f) uint32_t pos = rela_start + sizeof(Elf32_Rela) * i; uint32_t addr, pos_dyn; - debug("\nPossition:\t%d/0x%x\n", i, pos); + debug("\nPosition:\t%d/0x%x\n", i, pos); if (fseek(f, pos, SEEK_SET) < 0) { fprintf(stderr, "%s: %s: seek to %" PRIx32 |