diff options
145 files changed, 4066 insertions, 956 deletions
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 9c136513bb9..15520c4dafd 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -92,7 +92,7 @@ stages: set -e python3 -m venv /tmp/venvhtml . /tmp/venvhtml/bin/activate - pip install -r doc/sphinx/requirements.txt pytest + pip install -r doc/sphinx/requirements.txt -r test/py/requirements.txt make htmldocs KDOC_WERROR=1 make infodocs diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7aadd5d8b73..49f3c588cfc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -164,7 +164,7 @@ docs: script: - python3 -m venv /tmp/venvhtml - . /tmp/venvhtml/bin/activate - - pip install -r doc/sphinx/requirements.txt pytest + - pip install -r doc/sphinx/requirements.txt -r test/py/requirements.txt - make htmldocs KDOC_WERROR=1 - make infodocs diff --git a/.readthedocs.yml b/.readthedocs.yml index 16418f286dc..9b6d251b738 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -22,3 +22,4 @@ formats: [] python: install: - requirements: doc/sphinx/requirements.txt + - requirements: test/py/requirements.txt @@ -3,7 +3,7 @@ VERSION = 2025 PATCHLEVEL = 07 SUBLEVEL = -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc3 NAME = # *DOCUMENTATION* @@ -482,18 +482,6 @@ The following options need to be configured: for your device - CONFIG_USBD_PRODUCTID 0xFFFF -- ULPI Layer Support: - The ULPI (UTMI Low Pin (count) Interface) PHYs are supported via - the generic ULPI layer. The generic layer accesses the ULPI PHY - via the platform viewport, so you need both the genric layer and - the viewport enabled. Currently only Chipidea/ARC based - viewport is supported. - To enable the ULPI layer support, define CONFIG_USB_ULPI and - CONFIG_USB_ULPI_VIEWPORT in your board configuration file. - If your ULPI phy needs a different reference clock than the - standard 24 MHz then you have to define CFG_ULPI_REF_CLK to - the appropriate value in Hz. - - MMC Support: CONFIG_SH_MMCIF Support for Renesas on-chip MMCIF controller diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index fedfdb21457..79f60eb3f34 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1416,7 +1416,7 @@ config TARGET_TOTAL_COMPUTE select DM_SERIAL select DM_GPIO select MMC - imply OF_HAS_PRIOR_STAGE + imply OF_HAS_PRIOR_STAGE if !BLOBLIST imply MISC_INIT_R config TARGET_LS2080A_EMU diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 32b698a7f41..976dbda48c3 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -918,8 +918,7 @@ dtb-$(CONFIG_ARCH_IMX8M) += \ imx8mq-librem5-r4.dtb dtb-$(CONFIG_ARCH_IMX9) += \ - imx93-var-som-symphony.dtb \ - imx93-phyboard-segin.dtb + imx93-var-som-symphony.dtb dtb-$(CONFIG_ARCH_IMXRT) += imxrt1020-evk.dtb \ imxrt1170-evk.dtb \ diff --git a/arch/arm/dts/imx6ulz-bsh-smm-m2-u-boot.dtsi b/arch/arm/dts/imx6ulz-bsh-smm-m2-u-boot.dtsi index 7730bb60dd0..faf596255f1 100644 --- a/arch/arm/dts/imx6ulz-bsh-smm-m2-u-boot.dtsi +++ b/arch/arm/dts/imx6ulz-bsh-smm-m2-u-boot.dtsi @@ -5,8 +5,12 @@ * Author: Michael Trimarchi <michael@amarulasolutions.com> */ -&{/soc} { - bootph-all; +/ { + wdt-reboot { + compatible = "wdt-reboot"; + wdt = <&wdog1>; + bootph-pre-ram; + }; }; &aips2 { diff --git a/arch/arm/dts/imx93-phyboard-segin.dts b/arch/arm/dts/imx93-phyboard-segin.dts deleted file mode 100644 index 85fb188b057..00000000000 --- a/arch/arm/dts/imx93-phyboard-segin.dts +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Copyright (C) 2023 PHYTEC Messtechnik GmbH - * Author: Wadim Egorov <w.egorov@phytec.de>, Christoph Stoidner <c.stoidner@phytec.de> - * Copyright (C) 2024 Mathieu Othacehe <m.othacehe@gmail.com> - * - * Product homepage: - * phyBOARD-Segin carrier board is reused for the i.MX93 design. - * https://www.phytec.eu/en/produkte/single-board-computer/phyboard-segin-imx6ul/ - */ -/dts-v1/; - -#include "imx93-phycore-som.dtsi" - -/{ - model = "PHYTEC phyBOARD-Segin-i.MX93"; - compatible = "phytec,imx93-phyboard-segin", "phytec,imx93-phycore-som", - "fsl,imx93"; - - chosen { - stdout-path = &lpuart1; - }; - - reg_usdhc2_vmmc: regulator-usdhc2 { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "VCC_SD"; - }; -}; - -/* Console */ -&lpuart1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart1>; - status = "okay"; -}; - -/* eMMC */ -&usdhc1 { - no-1-8-v; -}; - -/* SD-Card */ -&usdhc2 { - pinctrl-names = "default", "state_100mhz", "state_200mhz"; - pinctrl-0 = <&pinctrl_usdhc2_default>, <&pinctrl_usdhc2_cd>; - pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_cd>; - pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_cd>; - bus-width = <4>; - cd-gpios = <&gpio3 0 GPIO_ACTIVE_LOW>; - no-mmc; - no-sdio; - vmmc-supply = <®_usdhc2_vmmc>; - status = "okay"; -}; - -&iomuxc { - pinctrl_uart1: uart1grp { - fsl,pins = < - MX93_PAD_UART1_RXD__LPUART1_RX 0x31e - MX93_PAD_UART1_TXD__LPUART1_TX 0x30e - >; - }; - - pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp { - fsl,pins = < - MX93_PAD_SD2_RESET_B__GPIO3_IO07 0x31e - >; - }; - - pinctrl_usdhc2_cd: usdhc2cdgrp { - fsl,pins = < - MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e - >; - }; - - pinctrl_usdhc2_default: usdhc2grp { - fsl,pins = < - MX93_PAD_SD2_CLK__USDHC2_CLK 0x179e - MX93_PAD_SD2_CMD__USDHC2_CMD 0x139e - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x138e - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x138e - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x138e - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x139e - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e - >; - }; - - pinctrl_usdhc2_100mhz: usdhc2grp { - fsl,pins = < - MX93_PAD_SD2_CLK__USDHC2_CLK 0x179e - MX93_PAD_SD2_CMD__USDHC2_CMD 0x139e - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x138e - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x138e - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x139e - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x139e - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e - >; - }; - - pinctrl_usdhc2_200mhz: usdhc2grp { - fsl,pins = < - MX93_PAD_SD2_CLK__USDHC2_CLK 0x178e - MX93_PAD_SD2_CMD__USDHC2_CMD 0x139e - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x139e - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x139e - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x139e - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x139e - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e - >; - }; -}; diff --git a/arch/arm/dts/imx93-phycore-som.dtsi b/arch/arm/dts/imx93-phycore-som.dtsi deleted file mode 100644 index 88c2657b50e..00000000000 --- a/arch/arm/dts/imx93-phycore-som.dtsi +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Copyright (C) 2023 PHYTEC Messtechnik GmbH - * Author: Wadim Egorov <w.egorov@phytec.de>, Christoph Stoidner <c.stoidner@phytec.de> - * Copyright (C) 2024 Mathieu Othacehe <m.othacehe@gmail.com> - * - * Product homepage: - * https://www.phytec.eu/en/produkte/system-on-modules/phycore-imx-91-93/ - */ - -#include <dt-bindings/leds/common.h> - -#include "imx93.dtsi" - -/{ - model = "PHYTEC phyCORE-i.MX93"; - compatible = "phytec,imx93-phycore-som", "fsl,imx93"; - - reserved-memory { - ranges; - #address-cells = <2>; - #size-cells = <2>; - - linux,cma { - compatible = "shared-dma-pool"; - reusable; - alloc-ranges = <0 0x80000000 0 0x40000000>; - size = <0 0x10000000>; - linux,cma-default; - }; - }; - - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_leds>; - - led-0 { - color = <LED_COLOR_ID_GREEN>; - function = LED_FUNCTION_HEARTBEAT; - gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "heartbeat"; - }; - }; -}; - -/* Ethernet */ -&fec { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_fec>; - phy-mode = "rmii"; - phy-handle = <ðphy1>; - fsl,magic-packet; - assigned-clocks = <&clk IMX93_CLK_ENET_TIMER1>, - <&clk IMX93_CLK_ENET_REF>, - <&clk IMX93_CLK_ENET_REF_PHY>; - assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>, - <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>, - <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>; - assigned-clock-rates = <100000000>, <50000000>, <50000000>; - status = "okay"; - - mdio: mdio { - clock-frequency = <5000000>; - #address-cells = <1>; - #size-cells = <0>; - - ethphy1: ethernet-phy@1 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <1>; - }; - }; -}; - -/* eMMC */ -&usdhc1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usdhc1>; - bus-width = <8>; - non-removable; - status = "okay"; -}; - -/* Watchdog */ -&wdog3 { - status = "okay"; -}; - -&iomuxc { - pinctrl_fec: fecgrp { - fsl,pins = < - MX93_PAD_ENET2_MDC__ENET1_MDC 0x50e - MX93_PAD_ENET2_MDIO__ENET1_MDIO 0x502 - MX93_PAD_ENET2_RD0__ENET1_RGMII_RD0 0x57e - MX93_PAD_ENET2_RD1__ENET1_RGMII_RD1 0x57e - MX93_PAD_ENET2_RXC__ENET1_RX_ER 0x5fe - MX93_PAD_ENET2_RX_CTL__ENET1_RGMII_RX_CTL 0x57e - MX93_PAD_ENET2_TD0__ENET1_RGMII_TD0 0x50e - MX93_PAD_ENET2_TD1__ENET1_RGMII_TD1 0x50e - MX93_PAD_ENET2_TX_CTL__ENET1_RGMII_TX_CTL 0x50e - MX93_PAD_ENET2_TD2__ENET1_TX_CLK 0x4000050e - >; - }; - - pinctrl_leds: ledsgrp { - fsl,pins = < - MX93_PAD_I2C1_SDA__GPIO1_IO01 0x31e - >; - }; - - pinctrl_usdhc1: usdhc1grp { - fsl,pins = < - MX93_PAD_SD1_CLK__USDHC1_CLK 0x179e - MX93_PAD_SD1_CMD__USDHC1_CMD 0x1386 - MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x138e - MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x1386 - MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x138e - MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x1386 - MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x1386 - MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x1386 - MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x1386 - MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x1386 - MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x179e - >; - }; -}; diff --git a/arch/arm/dts/imxrt1170-evk.dts b/arch/arm/dts/imxrt1170-evk.dts index 0d8e7016860..354352477c7 100644 --- a/arch/arm/dts/imxrt1170-evk.dts +++ b/arch/arm/dts/imxrt1170-evk.dts @@ -234,6 +234,34 @@ (IMX_PAD_SION | 8) /* SEMC_DQS */ >; }; + + pinctrl_flexspi1: flexspi1grp { + fsl,pins = < + IOMUXC_GPIO_SD_B2_05_FLEXSPI1_A_DQS 0xa + IOMUXC_GPIO_SD_B2_06_FLEXSPI1_A_SS0_B 0xa + IOMUXC_GPIO_SD_B2_07_FLEXSPI1_A_SCLK 0xa + IOMUXC_GPIO_SD_B2_08_FLEXSPI1_A_DATA00 0xa + IOMUXC_GPIO_SD_B2_09_FLEXSPI1_A_DATA01 0xa + IOMUXC_GPIO_SD_B2_10_FLEXSPI1_A_DATA02 0xa + IOMUXC_GPIO_SD_B2_11_FLEXSPI1_A_DATA03 0xa + >; + }; + }; +}; + +&flexspi1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexspi1>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <250000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; }; }; diff --git a/arch/arm/dts/imxrt1170.dtsi b/arch/arm/dts/imxrt1170.dtsi index 2de775f043f..08665eaf06a 100644 --- a/arch/arm/dts/imxrt1170.dtsi +++ b/arch/arm/dts/imxrt1170.dtsi @@ -246,6 +246,19 @@ #interrupt-cells = <2>; }; + flexspi1: spi@400cc000 { + compatible = "nxp,imxrt1170-fspi"; + reg = <0x400cc000 0x800>, <0x30000000 0x10000000>; + reg-names = "fspi_base", "fspi_mmap"; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <130>; + clocks = <&clks IMXRT1170_CLK_DUMMY>, + <&clks IMXRT1170_CLK_FLEXSPI1>; + clock-names = "fspi_en", "fspi"; + status = "disabled"; + }; + gpt1: gpt1@400ec000 { compatible = "fsl,imxrt-gpt"; reg = <0x400ec000 0x4000>; diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 567e8e9e81a..3cdb71a2528 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -38,7 +38,7 @@ DECLARE_GLOBAL_DATA_PTR; -#if defined(CONFIG_IMX_HAB) +#if IS_ENABLED(CONFIG_IMX_HAB) struct imx_fuse const imx_sec_config_fuse = { .bank = 1, .word = 3, @@ -52,7 +52,7 @@ struct imx_fuse const imx_field_return_fuse = { int timer_init(void) { -#ifdef CONFIG_XPL_BUILD +#if IS_ENABLED(CONFIG_XPL_BUILD) struct sctr_regs *sctr = (struct sctr_regs *)SYSCNT_CTRL_BASE_ADDR; unsigned long freq = readl(&sctr->cntfid0); @@ -110,7 +110,7 @@ void set_wdog_reset(struct wdog_regs *wdog) setbits_le16(&wdog->wcr, WDOG_WDT_MASK | WDOG_WDZST_MASK); } -#ifdef CONFIG_ARMV8_PSCI +#if IS_ENABLED(CONFIG_ARMV8_PSCI) #define PTE_MAP_NS PTE_BLOCK_NS #else #define PTE_MAP_NS 0 @@ -700,11 +700,11 @@ int arch_cpu_init(void) return 0; } -#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP) +#if IS_ENABLED(CONFIG_IMX8MN) || IS_ENABLED(CONFIG_IMX8MP) struct rom_api *g_rom_api = (struct rom_api *)0x980; #endif -#if defined(CONFIG_IMX8M) +#if IS_ENABLED(CONFIG_IMX8M) #include <spl.h> int imx8m_detect_secondary_image_boot(void) { @@ -790,8 +790,8 @@ int boot_mode_getprisec(void) } #endif -#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP) -#ifdef SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION +#if IS_ENABLED(CONFIG_IMX8MN) || IS_ENABLED(CONFIG_IMX8MP) +#if IS_ENABLED(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION) #define IMG_CNTN_SET1_OFFSET GENMASK(22, 19) unsigned long arch_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, unsigned long raw_sect) @@ -826,7 +826,7 @@ unsigned long arch_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, return raw_sect; } -#endif /* SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION */ +#endif /* CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION */ #endif bool is_usb_boot(void) @@ -834,7 +834,7 @@ bool is_usb_boot(void) return get_boot_device() == USB_BOOT; } -#ifdef CONFIG_OF_SYSTEM_SETUP +#if IS_ENABLED(CONFIG_OF_SYSTEM_SETUP) bool check_fdt_new_path(void *blob) { const char *soc_path = "/soc@0"; @@ -880,7 +880,7 @@ add_status: return 0; } -#ifdef CONFIG_IMX8MQ +#if IS_ENABLED(CONFIG_IMX8MQ) bool check_dcss_fused(void) { struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; @@ -1026,7 +1026,7 @@ int disable_vpu_nodes(void *blob) return -EPERM; } -#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE +#if IS_ENABLED(CONFIG_IMX8MN_LOW_DRIVE_MODE) static int low_drive_gpu_freq(void *blob) { static const char *nodes_path_8mn[] = { @@ -1311,7 +1311,7 @@ int ft_system_setup(void *blob, struct bd_info *bd) "/cpus/cpu@3", }; -#ifdef CONFIG_IMX8MQ +#if IS_ENABLED(CONFIG_IMX8MQ) int i = 0; int rc; int nodeoff; @@ -1387,7 +1387,7 @@ usb_modify_speed: if (is_imx8md()) disable_cpu_nodes(blob, nodes_path, 2, 4); -#elif defined(CONFIG_IMX8MM) +#elif IS_ENABLED(CONFIG_IMX8MM) if (is_imx8mml() || is_imx8mmdl() || is_imx8mmsl()) disable_vpu_nodes(blob); @@ -1396,10 +1396,10 @@ usb_modify_speed: else if (is_imx8mms() || is_imx8mmsl()) disable_cpu_nodes(blob, nodes_path, 3, 4); -#elif defined(CONFIG_IMX8MN) +#elif IS_ENABLED(CONFIG_IMX8MN) if (is_imx8mnl() || is_imx8mndl() || is_imx8mnsl()) disable_gpu_nodes(blob); -#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE +#if IS_ENABLED(CONFIG_IMX8MN_LOW_DRIVE_MODE) else { int ldm_gpu = low_drive_gpu_freq(blob); @@ -1415,7 +1415,7 @@ usb_modify_speed: else if (is_imx8mns() || is_imx8mnsl() || is_imx8mnus()) disable_cpu_nodes(blob, nodes_path, 3, 4); -#elif defined(CONFIG_IMX8MP) +#elif IS_ENABLED(CONFIG_IMX8MP) if (is_imx8mpul()) { /* Disable GPU */ disable_gpu_nodes(blob); @@ -1471,7 +1471,7 @@ void reset_cpu(void) } #endif -#if defined(CONFIG_ARCH_MISC_INIT) +#if IS_ENABLED(CONFIG_ARCH_MISC_INIT) int arch_misc_init(void) { if (IS_ENABLED(CONFIG_FSL_CAAM)) { @@ -1487,8 +1487,8 @@ int arch_misc_init(void) } #endif -#if defined(CONFIG_XPL_BUILD) -#if defined(CONFIG_IMX8MQ) || defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN) +#if IS_ENABLED(CONFIG_XPL_BUILD) +#if IS_ENABLED(CONFIG_IMX8MQ) || IS_ENABLED(CONFIG_IMX8MM) || IS_ENABLED(CONFIG_IMX8MN) bool serror_need_skip = true; void do_error(struct pt_regs *pt_regs) @@ -1523,7 +1523,7 @@ void do_error(struct pt_regs *pt_regs) #endif #endif -#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP) +#if IS_ENABLED(CONFIG_IMX8MN) || IS_ENABLED(CONFIG_IMX8MP) enum env_location arch_env_get_location(enum env_operation op, int prio) { enum boot_device dev = get_boot_device(); @@ -1571,7 +1571,7 @@ enum env_location arch_env_get_location(enum env_operation op, int prio) #endif -#ifdef CONFIG_IMX_BOOTAUX +#if IS_ENABLED(CONFIG_IMX_BOOTAUX) const struct rproc_att hostmap[] = { /* aux core , host core, size */ { 0x00000000, 0x007e0000, 0x00020000 }, diff --git a/arch/arm/mach-imx/imx9/Kconfig b/arch/arm/mach-imx/imx9/Kconfig index 0fd82dc0811..e6cafdcd813 100644 --- a/arch/arm/mach-imx/imx9/Kconfig +++ b/arch/arm/mach-imx/imx9/Kconfig @@ -73,6 +73,7 @@ config TARGET_PHYCORE_IMX93 bool "phycore_imx93" select IMX93 select IMX9_LPDDR4X + imply OF_UPSTREAM select OF_BOARD_FIXUP select OF_BOARD_SETUP diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c index 3982f4cca18..b7008df8e35 100644 --- a/arch/arm/mach-imx/spl_imx_romapi.c +++ b/arch/arm/mach-imx/spl_imx_romapi.c @@ -35,12 +35,10 @@ ulong __weak spl_romapi_get_uboot_base(u32 image_offset, u32 rom_bt_dev) { u32 sector = 0; - /* - * Some boards use this value even though MMC is not enabled in SPL, for - * example imx8mn_bsh_smm_s2 - */ -#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR +#if IS_ENABLED(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR) sector = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR; +#elif IS_ENABLED(CONFIG_SPL_NAND_RAW_U_BOOT_USE_SECTOR) + sector = CONFIG_SPL_NAND_RAW_U_BOOT_SECTOR; #endif return image_offset + sector * 512 - 0x8000; diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig index 6761a9cb393..f1ccedba5d7 100644 --- a/arch/arm/mach-kirkwood/Kconfig +++ b/arch/arm/mach-kirkwood/Kconfig @@ -50,11 +50,13 @@ config TARGET_DS109 bool "Synology DS109" select KW88F6281 select SHEEVA_88SV131 + select KIRKWOOD_COMMON config TARGET_GURUPLUG bool "GuruPlug Board" select KW88F6281 select SHEEVA_88SV131 + select KIRKWOOD_COMMON config TARGET_SHEEVAPLUG bool "SheevaPlug Board" @@ -86,6 +88,7 @@ config TARGET_DNS325 bool "dns325 Board" select FEROCEON_88FR131 select KW88F6281 + select KIRKWOOD_COMMON config TARGET_ICONNECT bool "iconnect Board" @@ -103,15 +106,18 @@ config TARGET_NET2BIG_V2 bool "LaCie 2Big Network v2 NAS Board" select FEROCEON_88FR131 select KW88F6281 + select KIRKWOOD_COMMON config TARGET_NETSPACE_V2 bool "LaCie netspace_v2 Board" select FEROCEON_88FR131 + select KIRKWOOD_COMMON config TARGET_IB62X0 bool "ib62x0 Board" select FEROCEON_88FR131 select KW88F6281 + select KIRKWOOD_COMMON config TARGET_DOCKSTAR bool "Dockstar Board" @@ -129,6 +135,7 @@ config TARGET_NAS220 bool "BlackArmor NAS220" select FEROCEON_88FR131 select KW88F6192 + select KIRKWOOD_COMMON config TARGET_NSA310S bool "Zyxel NSA310S" @@ -146,11 +153,13 @@ config TARGET_SBx81LIFKW bool "Allied Telesis SBx81GS24/SBx81GT40/SBx81XS6/SBx81XS16" select FEROCEON_88FR131 select KW88F6281 + select KIRKWOOD_COMMON config TARGET_SBx81LIFXCAT bool "Allied Telesis SBx81GP24/SBx81GT24" select FEROCEON_88FR131 select KW88F6281 + select KIRKWOOD_COMMON endchoice diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index b24623590f2..8c6feae5735 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -77,6 +77,14 @@ config SYS_DCACHE_OFF help Do not enable data cache in U-Boot. +config SYS_CACHE_THEAD_CMO + bool "THEAD non-standard cache operations" + depends on !SYS_DCACHE_OFF + default n + help + Support for non-standard cache management operations on SoCs based on + T-Head C906/C910 cores. + config SPL_SYS_DCACHE_OFF bool "Do not enable dcache in SPL" depends on SPL @@ -118,6 +126,7 @@ source "arch/riscv/cpu/generic/Kconfig" source "arch/riscv/cpu/jh7110/Kconfig" source "arch/riscv/cpu/k1/Kconfig" source "arch/riscv/cpu/k230/Kconfig" +source "arch/riscv/cpu/th1520/Kconfig" # architecture-specific options below diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c index 5b31da64cbd..15c4e14599d 100644 --- a/arch/riscv/cpu/cpu.c +++ b/arch/riscv/cpu/cpu.c @@ -18,6 +18,7 @@ #include <asm/hwcap.h> #include <asm/cpufeature.h> #include <asm/cache.h> +#include <asm/global_data.h> #include <dm/uclass-internal.h> #include <linux/bitops.h> #include <linux/log2.h> @@ -746,3 +747,8 @@ __weak int cleanup_before_linux(void) return 0; } + +void arch_setup_gd(gd_t *new_gd) +{ + set_gd(new_gd); +} diff --git a/arch/riscv/cpu/cv1800b/Kconfig b/arch/riscv/cpu/cv1800b/Kconfig index 7225b1210c5..57f724ae043 100644 --- a/arch/riscv/cpu/cv1800b/Kconfig +++ b/arch/riscv/cpu/cv1800b/Kconfig @@ -6,6 +6,7 @@ config SOPHGO_CV1800B bool select ARCH_EARLY_INIT_R select SYS_CACHE_SHIFT_6 + select SYS_CACHE_THEAD_CMO imply CPU imply CPU_RISCV imply RISCV_TIMER diff --git a/arch/riscv/cpu/cv1800b/Makefile b/arch/riscv/cpu/cv1800b/Makefile index 95beb34b51a..da12e0f64e1 100644 --- a/arch/riscv/cpu/cv1800b/Makefile +++ b/arch/riscv/cpu/cv1800b/Makefile @@ -4,4 +4,3 @@ obj-y += dram.o obj-y += cpu.o -obj-y += cache.o diff --git a/arch/riscv/cpu/th1520/Kconfig b/arch/riscv/cpu/th1520/Kconfig new file mode 100644 index 00000000000..4d44191bd22 --- /dev/null +++ b/arch/riscv/cpu/th1520/Kconfig @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> +# Copyright (C) 2025, Yao Zi <ziyao@disroot.org> + +config THEAD_TH1520 + bool + select ARCH_EARLY_INIT_R + select SYS_CACHE_SHIFT_6 + select SUPPORT_SPL + select BINMAN if SPL + select SYS_CACHE_THEAD_CMO + select CLK_THEAD + imply CPU + imply CPU_RISCV + imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE) + imply RISCV_ACLINT if RISCV_MMODE + imply SPL_RISCV_ACLINT if SPL_RISCV_MMODE + imply CMD_CPU + imply SPL_CPU + imply SPL_OPENSBI + imply SPL_LOAD_FIT diff --git a/arch/riscv/cpu/th1520/Makefile b/arch/riscv/cpu/th1520/Makefile new file mode 100644 index 00000000000..5d806c06e2e --- /dev/null +++ b/arch/riscv/cpu/th1520/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2025, Yao Zi <ziyao@disroot.org> + +obj-y += cache.o +obj-y += cpu.o +obj-y += dram.o +obj-y += spl.o diff --git a/arch/riscv/cpu/th1520/cache.c b/arch/riscv/cpu/th1520/cache.c new file mode 100644 index 00000000000..08aa1f789fd --- /dev/null +++ b/arch/riscv/cpu/th1520/cache.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2025 Yao Zi <ziyao@disroot.org> + */ + +#include <asm/io.h> +#include <cpu_func.h> +#include <linux/bitops.h> + +#define CSR_MHCR 0x7c1 +#define CSR_MHCR_IE BIT(0) +#define CSR_MHCR_DE BIT(1) + +void icache_enable(void) +{ + csr_write(CSR_MHCR, csr_read(CSR_MHCR) | CSR_MHCR_IE); +} + +void dcache_enable(void) +{ + csr_write(CSR_MHCR, csr_read(CSR_MHCR) | CSR_MHCR_DE); +} + +int icache_status(void) +{ + return (csr_read(CSR_MHCR) & CSR_MHCR_IE) != 0; +} + +int dcache_status(void) +{ + return (csr_read(CSR_MHCR) & CSR_MHCR_DE) != 0; +} diff --git a/arch/riscv/cpu/th1520/cpu.c b/arch/riscv/cpu/th1520/cpu.c new file mode 100644 index 00000000000..b83f1272c67 --- /dev/null +++ b/arch/riscv/cpu/th1520/cpu.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2025 Yao Zi <ziyao@disroot.org> + * + * TH1520 SoC has a set of undocumented customized PMP registers that are + * configured through MMIO operation. It must be disabled before entering + * the DRAM region, or an exception will be raised. + */ + +#include <asm/io.h> +#include <cpu_func.h> + +#define TH1520_PMP_BASE (void *)0xffdc020000 + +void th1520_invalidate_pmp(void) +{ + /* Invalidate the PMP configuration as in vendor U-Boot code */ + writel(0x0, TH1520_PMP_BASE + 0x0); + + invalidate_icache_all(); +} diff --git a/arch/riscv/cpu/th1520/dram.c b/arch/riscv/cpu/th1520/dram.c new file mode 100644 index 00000000000..91007c0a3d3 --- /dev/null +++ b/arch/riscv/cpu/th1520/dram.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> + */ + +#include <fdtdec.h> +#include <init.h> +#include <asm/global_data.h> +#include <linux/sizes.h> + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + return fdtdec_setup_mem_size_base(); +} + +int dram_init_banksize(void) +{ + return fdtdec_setup_memory_banksize(); +} diff --git a/arch/riscv/cpu/th1520/spl.c b/arch/riscv/cpu/th1520/spl.c new file mode 100644 index 00000000000..362fe895f86 --- /dev/null +++ b/arch/riscv/cpu/th1520/spl.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2025 Yao Zi <ziyao@disroot.org> + */ +#include <asm/arch/iopmp.h> +#include <asm/io.h> +#include <dm.h> +#include <linux/sizes.h> +#include <log.h> +#include <init.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define TH1520_SUBSYS_CLK (void __iomem *)(0xffff011000 + 0x220) +#define TH1520_SUBSYS_CLK_VO_EN BIT(2) +#define TH1520_SUBSYS_CLK_VI_EN BIT(1) +#define TH1520_SUBSYS_CLK_DSP_EN BIT(0) +#define TH1520_SUBSYS_RST (void __iomem *)(0xffff015000 + 0x220) +#define TH1520_SUBSYS_RST_VP_N BIT(3) +#define TH1520_SUBSYS_RST_VO_N BIT(2) +#define TH1520_SUBSYS_RST_VI_N BIT(1) +#define TH1520_SUBSYS_RST_DSP_N BIT(0) + +int spl_dram_init(void) +{ + int ret; + struct udevice *dev; + + ret = fdtdec_setup_mem_size_base(); + if (ret) { + printf("failed to setup memory size and base: %d\n", ret); + return ret; + } + + /* DDR init */ + ret = uclass_get_device(UCLASS_RAM, 0, &dev); + if (ret) { + printf("DRAM init failed: %d\n", ret); + return ret; + } + + return 0; +} + +static void __iomem *th1520_iopmp_regs[] = { + TH1520_IOPMP_EMMC, + TH1520_IOPMP_SDIO0, + TH1520_IOPMP_SDIO1, + TH1520_IOPMP_USB0, + TH1520_IOPMP_AO, + TH1520_IOPMP_AUD, + TH1520_IOPMP_CHIP_DBG, + TH1520_IOPMP_EIP120I, + TH1520_IOPMP_EIP120II, + TH1520_IOPMP_EIP120III, + TH1520_IOPMP_ISP0, + TH1520_IOPMP_ISP1, + TH1520_IOPMP_DW200, + TH1520_IOPMP_VIPRE, + TH1520_IOPMP_VENC, + TH1520_IOPMP_VDEC, + TH1520_IOPMP_G2D, + TH1520_IOPMP_FCE, + TH1520_IOPMP_NPU, + TH1520_IOPMP_DPU0, + TH1520_IOPMP_DPU1, + TH1520_IOPMP_GPU, + TH1520_IOPMP_GMAC1, + TH1520_IOPMP_GMAC2, + TH1520_IOPMP_DMAC, + TH1520_IOPMP_TEE_DMAC, + TH1520_IOPMP_DSP0, + TH1520_IOPMP_DSP1, +}; + +void harts_early_init(void) +{ + int i; + + /* + * Set IOPMPs to the default attribute, allowing the application + * processor to access various peripherals. Subsystem clocks should be + * enabled and resets should be deasserted ahead of time, or the HART + * will hang when configuring corresponding IOPMP entries. + */ + setbits_le32(TH1520_SUBSYS_CLK, TH1520_SUBSYS_CLK_VO_EN | + TH1520_SUBSYS_CLK_VI_EN | + TH1520_SUBSYS_CLK_DSP_EN); + setbits_le32(TH1520_SUBSYS_RST, TH1520_SUBSYS_RST_VP_N | + TH1520_SUBSYS_RST_VO_N | + TH1520_SUBSYS_RST_VI_N | + TH1520_SUBSYS_RST_DSP_N); + + for (i = 0; i < ARRAY_SIZE(th1520_iopmp_regs); i++) + writel(TH1520_IOPMP_DEFAULT_ATTR, th1520_iopmp_regs[i]); +} diff --git a/arch/riscv/dts/binman.dtsi b/arch/riscv/dts/binman.dtsi index 5aeeeddb59f..c5b0464d6a7 100644 --- a/arch/riscv/dts/binman.dtsi +++ b/arch/riscv/dts/binman.dtsi @@ -5,6 +5,12 @@ #include <config.h> +#ifdef CONFIG_64BIT +#define ARCH "riscv64" +#else +#define ARCH "riscv" + +#endif / { binman: binman { multiple-images; @@ -31,12 +37,11 @@ description = "U-Boot"; type = "standalone"; os = "U-Boot"; - arch = "riscv"; + arch = ARCH; compression = "none"; load = /bits/ 64 <CONFIG_TEXT_BASE>; uboot_blob: u-boot-nodtb { - filename = "u-boot-nodtb.bin"; }; }; #else @@ -44,7 +49,7 @@ description = "Linux"; type = "standalone"; os = "Linux"; - arch = "riscv"; + arch = ARCH; compression = "none"; load = /bits/ 64 <CONFIG_TEXT_BASE>; @@ -57,7 +62,7 @@ tee { description = "OP-TEE"; type = "tee"; - arch = "riscv"; + arch = ARCH; compression = "none"; os = "tee"; load = /bits/ 64 <CONFIG_SPL_OPTEE_LOAD_ADDR>; @@ -71,7 +76,7 @@ description = "OpenSBI fw_dynamic Firmware"; type = "firmware"; os = "opensbi"; - arch = "riscv"; + arch = ARCH; compression = "none"; load = /bits/ 64 <CONFIG_SPL_OPENSBI_LOAD_ADDR>; entry = /bits/ 64 <CONFIG_SPL_OPENSBI_LOAD_ADDR>; diff --git a/arch/riscv/dts/jh7110-common-u-boot.dtsi b/arch/riscv/dts/jh7110-common-u-boot.dtsi index 6d85b2d91a7..049b0a7ce28 100644 --- a/arch/riscv/dts/jh7110-common-u-boot.dtsi +++ b/arch/riscv/dts/jh7110-common-u-boot.dtsi @@ -27,7 +27,6 @@ bootph-pre-ram; reg-offset = <0>; current-speed = <115200>; - clock-frequency = <24000000>; }; &mmc0 { diff --git a/arch/riscv/dts/jh7110-u-boot.dtsi b/arch/riscv/dts/jh7110-u-boot.dtsi index a9e318c4a31..f8d13277d24 100644 --- a/arch/riscv/dts/jh7110-u-boot.dtsi +++ b/arch/riscv/dts/jh7110-u-boot.dtsi @@ -6,46 +6,6 @@ #include <dt-bindings/reset/starfive,jh7110-crg.h> / { - cpus: cpus { - bootph-pre-ram; - - S7_0: cpu@0 { - bootph-pre-ram; - status = "okay"; - cpu0_intc: interrupt-controller { - bootph-pre-ram; - }; - }; - - U74_1: cpu@1 { - bootph-pre-ram; - cpu1_intc: interrupt-controller { - bootph-pre-ram; - }; - }; - - U74_2: cpu@2 { - bootph-pre-ram; - cpu2_intc: interrupt-controller { - bootph-pre-ram; - }; - }; - - U74_3: cpu@3 { - bootph-pre-ram; - cpu3_intc: interrupt-controller { - bootph-pre-ram; - }; - }; - - U74_4: cpu@4 { - bootph-pre-ram; - cpu4_intc: interrupt-controller { - bootph-pre-ram; - }; - }; - }; - timer { compatible = "riscv,timer"; interrupts-extended = <&cpu0_intc 5>, @@ -58,10 +18,6 @@ soc { bootph-pre-ram; - clint: timer@2000000 { - bootph-pre-ram; - }; - dmc: dmc@15700000 { bootph-pre-ram; compatible = "starfive,jh7110-dmc"; @@ -78,6 +34,34 @@ }; }; +&clint { + bootph-pre-ram; +}; + +&cpu0_intc { + bootph-pre-ram; +}; + +&cpu1_intc { + bootph-pre-ram; +}; + +&cpu2_intc { + bootph-pre-ram; +}; + +&cpu3_intc { + bootph-pre-ram; +}; + +&cpu4_intc { + bootph-pre-ram; +}; + +&cpus { + bootph-pre-ram; +}; + &osc { bootph-pre-ram; }; @@ -107,6 +91,7 @@ }; &syscrg { + assigned-clock-rates = <0>; /* cpufreq not implemented, use defaults */ bootph-pre-ram; }; diff --git a/arch/riscv/dts/th1520-lichee-module-4a.dtsi b/arch/riscv/dts/th1520-lichee-module-4a.dtsi index 86a81bdcf77..9b255f8243c 100644 --- a/arch/riscv/dts/th1520-lichee-module-4a.dtsi +++ b/arch/riscv/dts/th1520-lichee-module-4a.dtsi @@ -14,6 +14,7 @@ memory@0 { device_type = "memory"; reg = <0x0 0x00000000 0x2 0x00000000>; + bootph-pre-ram; }; }; @@ -25,14 +26,6 @@ clock-frequency = <32768>; }; -&apb_clk { - clock-frequency = <62500000>; -}; - -&uart_sclk { - clock-frequency = <100000000>; -}; - &emmc { bus-width = <8>; max-frequency = <198000000>; diff --git a/arch/riscv/dts/th1520-lichee-pi-4a.dts b/arch/riscv/dts/th1520-lichee-pi-4a.dts index a1248b2ee3a..49af88b7adf 100644 --- a/arch/riscv/dts/th1520-lichee-pi-4a.dts +++ b/arch/riscv/dts/th1520-lichee-pi-4a.dts @@ -4,6 +4,7 @@ */ #include "th1520-lichee-module-4a.dtsi" +#include "thead-th1520-binman.dtsi" / { model = "Sipeed Lichee Pi 4A"; diff --git a/arch/riscv/dts/th1520.dtsi b/arch/riscv/dts/th1520.dtsi index cbe3481fadd..28107a9f354 100644 --- a/arch/riscv/dts/th1520.dtsi +++ b/arch/riscv/dts/th1520.dtsi @@ -4,6 +4,7 @@ * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org> */ +#include <dt-bindings/clock/thead,th1520-clk-ap.h> #include <dt-bindings/interrupt-controller/irq.h> / { @@ -14,6 +15,7 @@ cpus: cpus { #address-cells = <1>; #size-cells = <0>; + bootph-pre-ram; timebase-frequency = <3000000>; c910_0: cpu@0 { @@ -21,6 +23,7 @@ device_type = "cpu"; riscv,isa = "rv64imafdc"; reg = <0>; + bootph-pre-ram; i-cache-block-size = <64>; i-cache-size = <65536>; i-cache-sets = <512>; @@ -42,6 +45,7 @@ device_type = "cpu"; riscv,isa = "rv64imafdc"; reg = <1>; + bootph-pre-ram; i-cache-block-size = <64>; i-cache-size = <65536>; i-cache-sets = <512>; @@ -63,6 +67,7 @@ device_type = "cpu"; riscv,isa = "rv64imafdc"; reg = <2>; + bootph-pre-ram; i-cache-block-size = <64>; i-cache-size = <65536>; i-cache-sets = <512>; @@ -84,6 +89,7 @@ device_type = "cpu"; riscv,isa = "rv64imafdc"; reg = <3>; + bootph-pre-ram; i-cache-block-size = <64>; i-cache-size = <65536>; i-cache-sets = <512>; @@ -122,25 +128,6 @@ #clock-cells = <0>; }; - apb_clk: apb-clk-clock { - compatible = "fixed-clock"; - clock-output-names = "apb_clk"; - #clock-cells = <0>; - }; - - uart_sclk: uart-sclk-clock { - compatible = "fixed-clock"; - clock-output-names = "uart_sclk"; - #clock-cells = <0>; - }; - - sdhci_clk: sdhci-clock { - compatible = "fixed-clock"; - clock-frequency = <198000000>; - clock-output-names = "sdhci_clk"; - #clock-cells = <0>; - }; - soc { compatible = "simple-bus"; interrupt-parent = <&plic>; @@ -173,8 +160,10 @@ uart0: serial@ffe7014000 { compatible = "snps,dw-apb-uart"; reg = <0xff 0xe7014000 0x0 0x100>; + bootph-pre-ram; interrupts = <36 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&uart_sclk>; + clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART0_PCLK>; + clock-names = "buadclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; @@ -184,7 +173,7 @@ compatible = "thead,th1520-dwcmshc"; reg = <0xff 0xe7080000 0x0 0x10000>; interrupts = <62 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&sdhci_clk>; + clocks = <&clk CLK_EMMC_SDIO>; clock-names = "core"; status = "disabled"; }; @@ -193,7 +182,7 @@ compatible = "thead,th1520-dwcmshc"; reg = <0xff 0xe7090000 0x0 0x10000>; interrupts = <64 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&sdhci_clk>; + clocks = <&clk CLK_EMMC_SDIO>; clock-names = "core"; status = "disabled"; }; @@ -202,7 +191,7 @@ compatible = "thead,th1520-dwcmshc"; reg = <0xff 0xe70a0000 0x0 0x10000>; interrupts = <71 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&sdhci_clk>; + clocks = <&clk CLK_EMMC_SDIO>; clock-names = "core"; status = "disabled"; }; @@ -211,7 +200,8 @@ compatible = "snps,dw-apb-uart"; reg = <0xff 0xe7f00000 0x0 0x100>; interrupts = <37 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&uart_sclk>; + clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART1_PCLK>; + clock-names = "buadclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; @@ -221,7 +211,8 @@ compatible = "snps,dw-apb-uart"; reg = <0xff 0xe7f04000 0x0 0x100>; interrupts = <39 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&uart_sclk>; + clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART3_PCLK>; + clock-names = "buadclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; @@ -230,6 +221,8 @@ gpio2: gpio@ffe7f34000 { compatible = "snps,dw-apb-gpio"; reg = <0xff 0xe7f34000 0x0 0x1000>; + clocks = <&clk CLK_GPIO2>; + clock-names = "bus"; #address-cells = <1>; #size-cells = <0>; @@ -248,6 +241,8 @@ gpio3: gpio@ffe7f38000 { compatible = "snps,dw-apb-gpio"; reg = <0xff 0xe7f38000 0x0 0x1000>; + clocks = <&clk CLK_GPIO3>; + clock-names = "bus"; #address-cells = <1>; #size-cells = <0>; @@ -266,6 +261,8 @@ gpio0: gpio@ffec005000 { compatible = "snps,dw-apb-gpio"; reg = <0xff 0xec005000 0x0 0x1000>; + clocks = <&clk CLK_GPIO0>; + clock-names = "bus"; #address-cells = <1>; #size-cells = <0>; @@ -284,6 +281,8 @@ gpio1: gpio@ffec006000 { compatible = "snps,dw-apb-gpio"; reg = <0xff 0xec006000 0x0 0x1000>; + clocks = <&clk CLK_GPIO1>; + clock-names = "bus"; #address-cells = <1>; #size-cells = <0>; @@ -303,16 +302,24 @@ compatible = "snps,dw-apb-uart"; reg = <0xff 0xec010000 0x0 0x4000>; interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&uart_sclk>; + clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART2_PCLK>; + clock-names = "buadclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; }; + clk: clock-controller@ffef010000 { + compatible = "thead,th1520-clk-ap"; + reg = <0xff 0xef010000 0x0 0x1000>; + clocks = <&osc>; + #clock-cells = <1>; + }; + timer0: timer@ffefc32000 { compatible = "snps,dw-apb-timer"; reg = <0xff 0xefc32000 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <16 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; @@ -321,7 +328,7 @@ timer1: timer@ffefc32014 { compatible = "snps,dw-apb-timer"; reg = <0xff 0xefc32014 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; @@ -330,7 +337,7 @@ timer2: timer@ffefc32028 { compatible = "snps,dw-apb-timer"; reg = <0xff 0xefc32028 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <18 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; @@ -339,7 +346,7 @@ timer3: timer@ffefc3203c { compatible = "snps,dw-apb-timer"; reg = <0xff 0xefc3203c 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <19 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; @@ -349,7 +356,8 @@ compatible = "snps,dw-apb-uart"; reg = <0xff 0xf7f08000 0x0 0x4000>; interrupts = <40 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&uart_sclk>; + clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART4_PCLK>; + clock-names = "buadclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; @@ -359,16 +367,27 @@ compatible = "snps,dw-apb-uart"; reg = <0xff 0xf7f0c000 0x0 0x4000>; interrupts = <41 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&uart_sclk>; + clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART5_PCLK>; + clock-names = "buadclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; }; + ddrc: ddrc@fffd000000 { + compatible = "thead,th1520-ddrc"; + reg = <0xff 0xfd000000 0x0 0x1000000>, + <0xff 0xfe000000 0x0 0x1000000>, + <0xff 0xff000000 0x0 0x4000>, + <0xff 0xff005000 0x0 0x1000>; + reg-names = "phy-0", "phy-1", "ctrl", "sys"; + bootph-pre-ram; + }; + timer4: timer@ffffc33000 { compatible = "snps,dw-apb-timer"; reg = <0xff 0xffc33000 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; @@ -377,7 +396,7 @@ timer5: timer@ffffc33014 { compatible = "snps,dw-apb-timer"; reg = <0xff 0xffc33014 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; @@ -386,7 +405,7 @@ timer6: timer@ffffc33028 { compatible = "snps,dw-apb-timer"; reg = <0xff 0xffc33028 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <22 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; @@ -395,7 +414,7 @@ timer7: timer@ffffc3303c { compatible = "snps,dw-apb-timer"; reg = <0xff 0xffc3303c 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <23 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; diff --git a/arch/riscv/dts/thead-th1520-binman.dtsi b/arch/riscv/dts/thead-th1520-binman.dtsi new file mode 100644 index 00000000000..f060639e1c6 --- /dev/null +++ b/arch/riscv/dts/thead-th1520-binman.dtsi @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2025 Yao Zi <ziyao@disroot.org> + */ + +#include <config.h> + +/ { + binman: binman { + }; +}; + +&binman { + filename = "u-boot-with-spl.bin"; + + u-boot-spl { + }; + + ddr-fw { + filename = "th1520-ddr-firmware.bin"; + type = "blob-ext"; + }; + + fit { + offset = <CONFIG_SPL_PAD_TO>; + + description = "Configuration to load M-mode U-Boot"; + + #address-cells = <2>; + fit,fdt-list = "of-list"; + + images { + uboot { + description = "U-Boot"; + type = "standalone"; + os = "U-boot"; + arch = "riscv"; + compression = "none"; + load = /bits/ 64 <CONFIG_TEXT_BASE>; + + uboot_blob: u-boot { + }; + }; + }; + + configurations { + default = "conf-th1520-lichee-pi-4a"; + + conf-th1520-lichee-pi-4a { + description = "th1520-lichee-pi-4a"; + loadables = "uboot"; + }; + }; + }; +}; diff --git a/arch/riscv/include/asm/arch-th1520/cpu.h b/arch/riscv/include/asm/arch-th1520/cpu.h new file mode 100644 index 00000000000..837f0b8d06b --- /dev/null +++ b/arch/riscv/include/asm/arch-th1520/cpu.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2025 Yao Zi <ziyao@disroot.org> + */ + +#ifndef _ASM_TH1520_CPU_H_ +#define _ASM_TH1520_CPU_H_ +void th1520_invalidate_pmp(void); +#endif /* _ASM_TH1520_CPU_H_ */ diff --git a/arch/riscv/include/asm/arch-th1520/iopmp.h b/arch/riscv/include/asm/arch-th1520/iopmp.h new file mode 100644 index 00000000000..3dc766b5bff --- /dev/null +++ b/arch/riscv/include/asm/arch-th1520/iopmp.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2025 Yao Zi <ziyao@disroot.org> + */ +#ifndef _ASM_ARCH_TH1520_IOPMP_H_ +#define _ASM_ARCH_TH1520_IOPMP_H_ + +#define TH1520_IOPMP_EMMC (void *)0xfffc0280c0 +#define TH1520_IOPMP_SDIO0 (void *)0xfffc0290c0 +#define TH1520_IOPMP_SDIO1 (void *)0xfffc02a0c0 +#define TH1520_IOPMP_USB0 (void *)0xfffc02e0c0 +#define TH1520_IOPMP_AO (void *)0xffffc210c0 +#define TH1520_IOPMP_AUD (void *)0xffffc220c0 +#define TH1520_IOPMP_CHIP_DBG (void *)0xffffc370c0 +#define TH1520_IOPMP_EIP120I (void *)0xffff2200c0 +#define TH1520_IOPMP_EIP120II (void *)0xffff2300c0 +#define TH1520_IOPMP_EIP120III (void *)0xffff2400c0 +#define TH1520_IOPMP_ISP0 (void *)0xfff40800c0 +#define TH1520_IOPMP_ISP1 (void *)0xfff40810c0 +#define TH1520_IOPMP_DW200 (void *)0xfff40820c0 +#define TH1520_IOPMP_VIPRE (void *)0xfff40830c0 +#define TH1520_IOPMP_VENC (void *)0xfffcc600c0 +#define TH1520_IOPMP_VDEC (void *)0xfffcc610c0 +#define TH1520_IOPMP_G2D (void *)0xfffcc620c0 +#define TH1520_IOPMP_FCE (void *)0xfffcc630c0 +#define TH1520_IOPMP_NPU (void *)0xffff01c0c0 +#define TH1520_IOPMP_DPU0 (void *)0xffff5200c0 +#define TH1520_IOPMP_DPU1 (void *)0xffff5210c0 +#define TH1520_IOPMP_GPU (void *)0xffff5220c0 +#define TH1520_IOPMP_GMAC1 (void *)0xfffc0010c0 +#define TH1520_IOPMP_GMAC2 (void *)0xfffc0020c0 +#define TH1520_IOPMP_DMAC (void *)0xffffc200c0 +#define TH1520_IOPMP_TEE_DMAC (void *)0xffff2500c0 +#define TH1520_IOPMP_DSP0 (void *)0xffff0580c0 +#define TH1520_IOPMP_DSP1 (void *)0xffff0590c0 +#define TH1520_IOPMP_AUDIO (void *)0xffffc220c0 +#define TH1520_IOPMP_AUDIO0 (void *)0xffcb02e0c0 +#define TH1520_IOPMP_AUDIO1 (void *)0xffcb02f0c0 + +#define TH1520_IOPMP_DEFAULT_ATTR 0xffffffff + +#endif // _ASM_ARCH_TH1520_IOPMP_H_ diff --git a/arch/riscv/include/asm/arch-th1520/spl.h b/arch/riscv/include/asm/arch-th1520/spl.h new file mode 100644 index 00000000000..59aed8cad62 --- /dev/null +++ b/arch/riscv/include/asm/arch-th1520/spl.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2025 Yao Zi <ziyao@disroot.org> + */ +#ifndef _ASM_ARCH_TH1520_SPL_H_ +#define _ASM_ARCH_TH1520_SPL_H_ + +void spl_dram_init(void); + +#endif // _ASM_ARCH_TH1520_SPL_H_ diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h index d356752a56a..47b5e2cfc8f 100644 --- a/arch/riscv/include/asm/global_data.h +++ b/arch/riscv/include/asm/global_data.h @@ -14,6 +14,7 @@ #include <asm/smp.h> #include <asm/u-boot.h> #include <compiler.h> +#include <config.h> /* Architecture-specific global data */ struct arch_global_data { @@ -47,8 +48,26 @@ struct arch_global_data { #include <asm-generic/global_data.h> +#if defined(__clang__) || CONFIG_IS_ENABLED(LTO) + +#define DECLARE_GLOBAL_DATA_PTR +#define gd get_gd() + +static inline gd_t *get_gd(void) +{ + gd_t *gd_ptr; + + __asm__ volatile ("mv %0, gp\n" : "=r" (gd_ptr)); + + return gd_ptr; +} + +#else + #define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("gp") +#endif + static inline void set_gd(volatile gd_t *gd_ptr) { #ifdef CONFIG_64BIT diff --git a/arch/riscv/include/asm/insn-def.h b/arch/riscv/include/asm/insn-def.h index 19a10cad84c..1869342b167 100644 --- a/arch/riscv/include/asm/insn-def.h +++ b/arch/riscv/include/asm/insn-def.h @@ -5,8 +5,8 @@ * Ported from linux insn-def.h. */ -#ifndef _ASM_RISCV_BARRIER_H -#define _ASM_RISCV_BARRIER_H +#ifndef _ASM_RISCV_INSN_DEF_H +#define _ASM_RISCV_INSN_DEF_H #define INSN_I_SIMM12_SHIFT 20 #define INSN_I_RS1_SHIFT 15 @@ -36,4 +36,4 @@ __INSN_I(RV_##opcode, RV_##func3, RV_##rd, \ RV_##rs1, RV_##simm12) -#endif /* _ASM_RISCV_BARRIER_H */ +#endif /* _ASM_RISCV_INSN_DEF_H */ diff --git a/arch/riscv/include/asm/u-boot.h b/arch/riscv/include/asm/u-boot.h index d5e1d5f3231..a90cc4c21cf 100644 --- a/arch/riscv/include/asm/u-boot.h +++ b/arch/riscv/include/asm/u-boot.h @@ -23,6 +23,10 @@ #include <asm/u-boot-riscv.h> /* For image.h:image_check_target_arch() */ +#ifdef CONFIG_64BIT +#define IH_ARCH_DEFAULT IH_ARCH_RISCV64 +#else #define IH_ARCH_DEFAULT IH_ARCH_RISCV +#endif #endif /* _U_BOOT_H_ */ diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile index 189b35c24d3..db8d235c699 100644 --- a/arch/riscv/lib/Makefile +++ b/arch/riscv/lib/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_CMD_BOOTI) += bootm.o image.o obj-$(CONFIG_CMD_GO) += boot.o obj-y += cache.o obj-$(CONFIG_SIFIVE_CACHE) += sifive_cache.o +obj-$(CONFIG_SYS_CACHE_THEAD_CMO) += thead_cmo.o ifeq ($(CONFIG_$(PHASE_)RISCV_MMODE),y) obj-$(CONFIG_$(PHASE_)RISCV_ACLINT) += aclint_ipi.o obj-$(CONFIG_ANDES_PLICSW) += andes_plicsw.o diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c index 9544907ab1e..c98c5e76633 100644 --- a/arch/riscv/lib/bootm.c +++ b/arch/riscv/lib/bootm.c @@ -90,6 +90,10 @@ static void boot_jump_linux(struct bootm_headers *images, int flag) announce_and_cleanup(fake); if (!fake) { + if (images->os.arch != IH_ARCH_DEFAULT) { + printf("Image arch not compatible with host arch.\n"); + hang(); + } if (CONFIG_IS_ENABLED(OF_LIBFDT) && images->ft_len) { #ifdef CONFIG_SMP ret = smp_call_function(images->ep, diff --git a/arch/riscv/cpu/cv1800b/cache.c b/arch/riscv/lib/thead_cmo.c index b8051e29e02..b8051e29e02 100644 --- a/arch/riscv/cpu/cv1800b/cache.c +++ b/arch/riscv/lib/thead_cmo.c diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index ec52992209f..d7f183f95dc 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -126,6 +126,8 @@ int write_tables(void) use_high = true; if (!gd->arch.table_start_high) gd->arch.table_start_high = rom_addr; + if (table->tag == BLOBLISTT_SMBIOS_TABLES) + gd_set_smbios_start(rom_addr); } rom_table_end = table->write(rom_addr); if (!rom_table_end) { diff --git a/board/Synology/ds109/ds109.c b/board/Synology/ds109/ds109.c index 4f397578182..f3a914cc515 100644 --- a/board/Synology/ds109/ds109.c +++ b/board/Synology/ds109/ds109.c @@ -97,24 +97,6 @@ int board_init(void) return 0; } -/* Synology reset uses UART */ -#include <ns16550.h> -#define SOFTWARE_SHUTDOWN 0x31 -#define SOFTWARE_REBOOT 0x43 -#define CFG_SYS_NS16550_COM2 KW_UART1_BASE -void reset_misc(void) -{ - int b_d; - printf("Synology reset..."); - udelay(50000); - - b_d = ns16550_calc_divisor((struct ns16550 *)CFG_SYS_NS16550_COM2, - CFG_SYS_NS16550_CLK, 9600); - ns16550_init((struct ns16550 *)CFG_SYS_NS16550_COM2, b_d); - ns16550_putc((struct ns16550 *)CFG_SYS_NS16550_COM2, - SOFTWARE_REBOOT); -} - #ifdef CONFIG_RESET_PHY_R /* Configure and enable MV88E1116 PHY */ void reset_phy(void) diff --git a/board/armltd/total_compute/Makefile b/board/armltd/total_compute/Makefile index f1ef5a0c39a..615c7876353 100644 --- a/board/armltd/total_compute/Makefile +++ b/board/armltd/total_compute/Makefile @@ -4,4 +4,4 @@ # Usama Arif <usama.arif@arm.com> obj-y := total_compute.o -obj-y += lowlevel_init.o +obj-$(CONFIG_OF_HAS_PRIOR_STAGE) += lowlevel_init.o diff --git a/board/armltd/total_compute/total_compute.c b/board/armltd/total_compute/total_compute.c index 75ba3c33d56..75bc6b0631f 100644 --- a/board/armltd/total_compute/total_compute.c +++ b/board/armltd/total_compute/total_compute.c @@ -31,6 +31,7 @@ static struct mm_region total_compute_mem_map[TC_MEM_MAP_MAX] = { struct mm_region *mem_map = total_compute_mem_map; +#ifdef CONFIG_OF_HAS_PRIOR_STAGE /* * Push the variable into the .data section so that it * does not get cleared later. @@ -45,14 +46,16 @@ int board_fdt_blob_setup(void **fdtp) *fdtp = (void *)fw_dtb_pointer; return 0; } +#endif int misc_init_r(void) { size_t base; +#ifdef CONFIG_OF_HAS_PRIOR_STAGE if (!env_get("fdt_addr_r")) env_set_hex("fdt_addr_r", fw_dtb_pointer); - +#endif if (!env_get("kernel_addr_r")) { /* * The kernel has to be 2M aligned and the first 64K at the diff --git a/board/armltd/total_compute/total_compute.env b/board/armltd/total_compute/total_compute.env index 7924632678e..84d5a10b107 100644 --- a/board/armltd/total_compute/total_compute.env +++ b/board/armltd/total_compute/total_compute.env @@ -11,6 +11,12 @@ bootcmd= blk_dev=mmc; fi; echo block device is ${blk_dev}; + if test -n "${fdt_addr_r}"; then + echo "Custom FDT at ${fdt_addr_r}"; + else; + setenv fdt_addr_r ${fdtcontroladdr}; + echo "FDT address is now set to ${fdt_addr_r}"; + fi; if part number ${blk_dev} 0 vbmeta is_avb; then echo '${blk_dev} with vbmeta partition detected.'; echo 'Starting Android Verified boot...'; diff --git a/board/bsh/imx6ulz_smm_m2/Makefile b/board/bsh/imx6ulz_smm_m2/Makefile index 59870419bdd..4f4d67f659d 100644 --- a/board/bsh/imx6ulz_smm_m2/Makefile +++ b/board/bsh/imx6ulz_smm_m2/Makefile @@ -2,5 +2,4 @@ # (C) Copyright 2021 Amarula Solutions B.V. obj-y := imx6ulz_smm_m2.o -obj-$(CONFIG_XPL_BUILD) += spl.o - +obj-$(CONFIG_XPL_BUILD) += spl.o ddr3l_timing_512m.o ddr3l_timing_256m.o ddr3l_timing_128m.o diff --git a/board/bsh/imx6ulz_smm_m2/ddr3l_timing_128m.c b/board/bsh/imx6ulz_smm_m2/ddr3l_timing_128m.c new file mode 100644 index 00000000000..66c3483adbf --- /dev/null +++ b/board/bsh/imx6ulz_smm_m2/ddr3l_timing_128m.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include "spl_mtypes.h" + +static const struct dram_cfg_param ddr_ddrc_cfg_128mb[] = { + /* IOMUX */ + + /* DDR IO Type: */ + {0x020e04b4, 0x000C0000}, /* IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE */ + {0x020e04ac, 0x00000000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRPKE */ + + /* Clock: */ + {0x020e027c, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_0 */ + + /* Address: */ + {0x020e0250, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS */ + {0x020e024c, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS */ + {0x020e0490, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_ADDDS */ + + /* Control: */ + {0x020e0288, 0x000C0028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_RESET */ + {0x020e0270, 0x00000000}, /* + * IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2 - DSE can be configured + * using Group Control Register IOMUXC_SW_PAD_CTL_GRP_CTLDS + */ + + {0x020e0260, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT0 */ + {0x020e0264, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT1 */ + {0x020e04a0, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_CTLDS */ + + /* Data Strobes: */ + {0x020e0494, 0x00020000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL */ + {0x020e0280, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0 */ + {0x020e0284, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1 */ + + /* Data: */ + {0x020e04b0, 0x00020000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRMODE */ + {0x020e0498, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_B0DS */ + {0x020e04a4, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_B1DS */ + + {0x020e0244, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0 */ + {0x020e0248, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 */ + + /* + * ============================================================================= + * DDR Controller Registers + * ============================================================================= + * Manufacturer:ISSI + * Device Part Number:IS43TR16640BL-125JBLI + * Clock Freq.: 400MHz + * Density per CS in Gb: 1 + * Chip Selects used:1 + * Number of Banks:8 + * Row address: 13 + * Column address: 10 + * Data bus width16 + * ============================================================================= + */ + {0x021b001c, 0x00008000}, /* + * MMDC0_MDSCR, set the Configuration request bit + * during MMDC set up + */ + + /* + * ============================================================================= + * Calibration setup. + * ============================================================================= + */ + {0x021b0800, 0xA1390003}, /* + * DDR_PHY_P0_MPZQHWCTRL, enable both one-time & periodic + * HW ZQ calibration. + */ + + /* + * For target board, may need to run write leveling calibration to fine tune + * these settings. + */ + {0x021b080c, 0x00000000}, + + /* Read DQS Gating calibration */ + {0x021b083c, 0x41480148}, /* MPDGCTRL0 PHY0 */ + + /* Read calibration */ + {0x021b0848, 0x40403A3E}, /* MPRDDLCTL PHY0 */ + + /* Write calibration */ + {0x021b0850, 0x4040362E}, /* MPWRDLCTL PHY0 */ + + /* + * Read data bit delay: 3 is the recommended default value, although out of reset + * value is 0. + */ + {0x021b081c, 0x33333333}, /* MMDC_MPRDDQBY0DL */ + {0x021b0820, 0x33333333}, /* MMDC_MPRDDQBY1DL */ + + /* Write data bit delay: */ + {0x021b082c, 0xF3333333}, /* MMDC_MPWRDQBY0DL */ + {0x021b0830, 0xF3333333}, /* MMDC_MPWRDQBY1DL */ + + /* DQS&CLK Duty Cycle */ + {0x021b08c0, 0x00944009}, /* [MMDC_MPDCCR] MMDC Duty Cycle Control Register */ + + /* Complete calibration by forced measurement: */ + {0x021b08b8, 0x00000800}, /* DDR_PHY_P0_MPMUR0, frc_msr */ + + /* + * ============================================================================= + * Calibration setup end + * ============================================================================= + */ + + /* MMDC init: */ + {0x021b0004, 0x0002002D}, /* MMDC0_MDPDC */ + {0x021b0008, 0x1B333030}, /* MMDC0_MDOTC */ + {0x021b000c, 0x2B2F52F3}, /* MMDC0_MDCFG0 */ + {0x021b0010, 0xB66D0B63}, /* MMDC0_MDCFG1 */ + {0x021b0014, 0x01FF00DB}, /* MMDC0_MDCFG2 */ + + /* + * MDMISC: RALAT kept to the high level of 5. + * MDMISC: consider reducing RALAT if your 528MHz board design allow that. + * Lower RALAT benefits: + * a. better operation at low frequency, for LPDDR2 freq < 100MHz, change RALAT to 3 + * b. Small performance improvement + */ + {0x021b0018, 0x00211740}, /* MMDC0_MDMISC */ + {0x021b001c, 0x00008000}, /* + * MMDC0_MDSCR, set the Configuration request bit during + * MMDC set up + */ + {0x021b002c, 0x000026D2}, /* MMDC0_MDRWD */ + {0x021b0030, 0x002F1023}, /* MMDC0_MDOR */ + {0x021b0040, 0x00000043}, /* Chan0 CS0_END */ + {0x021b0000, 0x82180000}, /* MMDC0_MDCTL */ + + {0x021b0890, 0x00400000}, /* MPPDCMPR2 */ + + /* Mode register writes */ + {0x021b001c, 0x02808032}, /* MMDC0_MDSCR, MR2 write, CS0 */ + {0x021b001c, 0x00008033}, /* MMDC0_MDSCR, MR3 write, CS0 */ + {0x021b001c, 0x00048031}, /* MMDC0_MDSCR, MR1 write, CS0 */ + {0x021b001c, 0x15208030}, /* MMDC0_MDSCR, MR0write, CS0 */ + {0x021b001c, 0x04008040}, /* + * MMDC0_MDSCR, ZQ calibration command sent to device + * on CS0 + */ + + {0x021b0020, 0x00007800}, /* MMDC0_MDREF */ + + {0x021b0818, 0x00000227}, /* DDR_PHY_P0_MPODTCTRL */ + + {0x021b0004, 0x0002552D}, /* MMDC0_MDPDC now SDCTL power down enabled */ + + {0x021b0404, 0x00011006}, /* + * MMDC0_MAPSR ADOPT power down enabled, + * MMDC will enter automatically to self-refresh + * while the number of idle cycle reached. + */ + + {0x021b001c, 0x00000000}, /* + * MMDC0_MDSCR, clear this register (especially the + * configuration bit as initialization is complete) + */ +}; + +struct dram_timing_info bsh_dram_timing_128mb = { + .ddrc_cfg = ddr_ddrc_cfg_128mb, + .ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_128mb), +}; diff --git a/board/bsh/imx6ulz_smm_m2/ddr3l_timing_256m.c b/board/bsh/imx6ulz_smm_m2/ddr3l_timing_256m.c new file mode 100644 index 00000000000..0fe5b90a673 --- /dev/null +++ b/board/bsh/imx6ulz_smm_m2/ddr3l_timing_256m.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include "spl_mtypes.h" + +static const struct dram_cfg_param ddr_ddrc_cfg_256mb[] = { + /* IOMUX */ + + /* DDR IO Type: */ + {0x020e04b4, 0x000C0000}, /* IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE */ + {0x020e04ac, 0x00000000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRPKE */ + + /* Clock: */ + {0x020e027c, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_0 */ + + /* Address: */ + {0x020e0250, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS */ + {0x020e024c, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS */ + {0x020e0490, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_ADDDS */ + + /* Control: */ + {0x020e0288, 0x000C0028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_RESET */ + {0x020e0270, 0x00000000}, /* + * IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2 - DSE can be configured + * using Group Control Register: IOMUXC_SW_PAD_CTL_GRP_CTLDS + */ + + {0x020e0260, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT0 */ + {0x020e0264, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT1 */ + {0x020e04a0, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_CTLDS */ + + /* Data Strobes: */ + {0x020e0494, 0x00020000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL */ + {0x020e0280, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0 */ + {0x020e0284, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1 */ + + /* Data: */ + {0x020e04b0, 0x00020000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRMODE */ + {0x020e0498, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_B0DS */ + {0x020e04a4, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_B1DS */ + + {0x020e0244, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0 */ + {0x020e0248, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 */ + + /* + * ============================================================================= + * DDR Controller Registers + * ============================================================================= + * Manufacturer:ISSI + * Device Part Number:IS43TR16640BL-125JBLI + * Clock Freq.: 400MHz + * Density per CS in Gb: 2 + * Chip Selects used:1 + * Number of Banks:8 + * Row address: 14 + * Column address: 10 + * Data bus width16 + * ============================================================================= + */ + {0x021b001c, 0x00008000}, /* + * MMDC0_MDSCR, set the Configuration request bit during + * MMDC set up + */ + + /* + * ============================================================================= + * Calibration setup. + * ============================================================================= + */ + {0x021b0800, 0xA1390003}, /* + * DDR_PHY_P0_MPZQHWCTRL, enable both one-time & periodic + * HW ZQ calibration + */ + + /* + * For target board, may need to run write leveling calibration to fine tune these settings + */ + {0x021b080c, 0x00050005}, + + /* Read DQS Gating calibration */ + {0x021b083c, 0x01480144}, /* MPDGCTRL0 PHY0 */ + + /* Read calibration */ + {0x021b0848, 0x4040363A}, /* MPRDDLCTL PHY0 */ + + /* Write calibration */ + {0x021b0850, 0x40402E2C}, /* MPWRDLCTL PHY0 */ + + /* + * Read data bit delay: 3 is the reccommended default value, although out of reset value + * is 0 + */ + {0x021b081c, 0x33333333}, /* MMDC_MPRDDQBY0DL */ + {0x021b0820, 0x33333333}, /* MMDC_MPRDDQBY1DL */ + + /* Write data bit delay: */ + {0x021b082c, 0xF3333333}, /* MMDC_MPWRDQBY0DL */ + {0x021b0830, 0xF3333333}, /* MMDC_MPWRDQBY1DL */ + + /* DQS&CLK Duty Cycle */ + {0x021b08c0, 0x00944009}, /* [MMDC_MPDCCR] MMDC Duty Cycle Control Register */ + + /* Complete calibration by forced measurement: */ + {0x021b08b8, 0x00000800}, /* DDR_PHY_P0_MPMUR0, frc_msr */ + + /* + * ============================================================================= + * Calibration setup end + * ============================================================================= + */ + + /* MMDC init: */ + {0x021b0004, 0x0002002D}, /* MMDC0_MDPDC */ + {0x021b0008, 0x1B333030}, /* MMDC0_MDOTC */ + {0x021b000c, 0x3F435333}, /* MMDC0_MDCFG0 */ + {0x021b0010, 0xB68E0B63}, /* MMDC0_MDCFG1 */ + {0x021b0014, 0x01FF00DB}, /* MMDC0_MDCFG2 */ + + /* + * MDMISC: RALAT kept to the high level of 5. + * MDMISC: consider reducing RALAT if your 528MHz board design allow that. + * Lower RALAT benefits: + * a. better operation at low frequency, for LPDDR2 freq < 100MHz, change RALAT to 3 + * b. Small performence improvment + */ + {0x021b0018, 0x00211740}, /* MMDC0_MDMISC */ + {0x021b001c, 0x00008000}, /* + * MMDC0_MDSCR, set the Configuration request bit during + * MMDC set up + */ + {0x021b002c, 0x000026D2}, /* MMDC0_MDRWD */ + {0x021b0030, 0x00431023}, /* MMDC0_MDOR */ + {0x021b0040, 0x00000047}, /* Chan0 CS0_END */ + {0x021b0000, 0x83180000}, /* MMDC0_MDCTL */ + + {0x021b0890, 0x00400000}, /* MPPDCMPR2 */ + + /* Mode register writes */ + {0x021b001c, 0x02808032}, /* MMDC0_MDSCR, MR2 write, CS0 */ + {0x021b001c, 0x00008033}, /* MMDC0_MDSCR, MR3 write, CS0 */ + {0x021b001c, 0x00048031}, /* MMDC0_MDSCR, MR1 write, CS0 */ + {0x021b001c, 0x15208030}, /* MMDC0_MDSCR, MR0write, CS0 */ + {0x021b001c, 0x04008040}, /* + * MMDC0_MDSCR, ZQ calibration command sent to device + * on CS0 + */ + + {0x021b0020, 0x00007800}, /* MMDC0_MDREF */ + + {0x021b0818, 0x00000227}, /* DDR_PHY_P0_MPODTCTRL */ + + {0x021b0004, 0x0002552D}, /* MMDC0_MDPDC now SDCTL power down enabled */ + + {0x021b0404, 0x00011006}, /* + * MMDC0_MAPSR ADOPT power down enabled, MMDC will enter + * automatically to self-refresh while the number of idle + * cycle reached + */ + + {0x021b001c, 0x00000000}, /* + * MMDC0_MDSCR, clear this register (especially the + * configuration bit as initialization is complete) + */ +}; + +struct dram_timing_info bsh_dram_timing_256mb = { + .ddrc_cfg = ddr_ddrc_cfg_256mb, + .ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_256mb), +}; diff --git a/board/bsh/imx6ulz_smm_m2/ddr3l_timing_512m.c b/board/bsh/imx6ulz_smm_m2/ddr3l_timing_512m.c new file mode 100644 index 00000000000..f5989382f5a --- /dev/null +++ b/board/bsh/imx6ulz_smm_m2/ddr3l_timing_512m.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include "spl_mtypes.h" + +static const struct dram_cfg_param ddr_ddrc_cfg_512mb[] = { + /* + * ============================================================================= + * IOMUX + * ============================================================================= + */ + + /* DDR IO Type: */ + {0x020e04b4, 0x000C0000}, /* IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE */ + {0x020e04ac, 0x00000000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRPKE */ + + /* Clock: */ + {0x020e027c, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_0 */ + + /* Address: */ + {0x020e0250, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS */ + {0x020e024c, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS */ + {0x020e0490, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_ADDDS */ + + /* Control: */ + {0x020e0288, 0x000C0028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_RESET */ + {0x020e0270, 0x00000000}, /* + * IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2 - DSE can be configured using + * Group Control Register: IOMUXC_SW_PAD_CTL_GRP_CTLDS + */ + {0x020e0260, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT0 */ + {0x020e0264, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT1 */ + {0x020e04a0, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_CTLDS */ + + /* Data Strobes: */ + {0x020e0494, 0x00020000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL */ + {0x020e0280, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0 */ + {0x020e0284, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1 */ + + /* Data: */ + {0x020e04b0, 0x00020000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRMODE */ + {0x020e0498, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_B0DS */ + {0x020e04a4, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_B1DS */ + + {0x020e0244, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0 */ + {0x020e0248, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 */ + + /* + * ============================================================================= + * DDR Controller Registers + * ============================================================================= + * Manufacturer:ISSI + * Device Part Number:IS43TR16640BL-125JBLI + * Clock Freq.: 400MHz + * Density per CS in Gb: 2 + * Chip Selects used:1 + * Number of Banks:8 + * Row address: 14 + * Column address: 10 + * Data bus width16 + * ============================================================================= + */ + {0x021b001c, 0x00008000}, /* + * MMDC0_MDSCR, set the Configuration request bit during + * MMDC set up + */ + + /* + * ============================================================================= + * Calibration setup. + * ============================================================================= + */ + {0x021b0800, 0xA1390003}, /* + * DDR_PHY_P0_MPZQHWCTRL, enable both one-time & periodic + * HW ZQ calibration + */ + + /* + * For target board may need to run write leveling calibration to fine tune these settings + */ + {0x021b080c, 0x00000000}, + + /* Read DQS Gating calibration */ + {0x021b083c, 0x01440140}, /* MPDGCTRL0 PHY0 */ + + /* Read calibration */ + {0x021b0848, 0x40403A3E}, /* MPRDDLCTL PHY0 */ + + /* Write calibration */ + {0x021b0850, 0x4040322A}, /* MPWRDLCTL PHY0 */ + + /* + * Read data bit delay: 3 is the reccommended default value, although out of reset value + * is 0 + */ + {0x021b081c, 0x33333333}, /* MMDC_MPRDDQBY0DL */ + {0x021b0820, 0x33333333}, /* MMDC_MPRDDQBY1DL */ + + /* Write data bit delay: */ + {0x021b082c, 0xF3333333}, /* MMDC_MPWRDQBY0DL */ + {0x021b0830, 0xF3333333}, /* MMDC_MPWRDQBY1DL */ + + /* DQS&CLK Duty Cycle */ + {0x021b08c0, 0x00944009}, /* [MMDC_MPDCCR] MMDC Duty Cycle Control Register */ + + /* Complete calibration by forced measurement: */ + {0x021b08b8, 0x00000800}, /* DDR_PHY_P0_MPMUR0, frc_msr */ + + /* + * ============================================================================= + * Calibration setup end + * ============================================================================= + */ + + /* MMDC init: */ + {0x021b0004, 0x0002002D}, /* MMDC0_MDPDC */ + {0x021b0008, 0x1B333030}, /* MMDC0_MDOTC */ + {0x021b000c, 0x3F435333}, /* MMDC0_MDCFG0 */ + {0x021b0010, 0xB68E0B63}, /* MMDC0_MDCFG1 */ + {0x021b0014, 0x01FF00DB}, /* MMDC0_MDCFG2 */ + + /* + * MDMISC: RALAT kept to the high level of 5. + * MDMISC: consider reducing RALAT if your 528MHz board design allow that. + * Lower RALAT benefits: + * a. better operation at low frequency, for LPDDR2 freq < 100MHz, change RALAT to 3 + * b. Small performence improvment + */ + {0x021b0018, 0x00211740}, /* MMDC0_MDMISC */ + {0x021b001c, 0x00008000}, /* + * MMDC0_MDSCR set the Configuration request bit during + * MMDC set up + */ + {0x021b002c, 0x000026D2}, /* MMDC0_MDRWD */ + {0x021b0030, 0x00431023}, /* MMDC0_MDOR */ + {0x021b0040, 0x0000004F}, /* Chan0 CS0_END */ + {0x021b0000, 0x84180000}, /* MMDC0_MDCTL */ + + {0x021b0890, 0x00400000}, /* MPPDCMPR2 */ + + /* Mode register writes */ + {0x021b001c, 0x02808032}, /* MMDC0_MDSCR, MR2 write, CS0 */ + {0x021b001c, 0x00008033}, /* MMDC0_MDSCR, MR3 write, CS0 */ + {0x021b001c, 0x00048031}, /* MMDC0_MDSCR, MR1 write, CS0 */ + {0x021b001c, 0x15208030}, /* MMDC0_MDSCR, MR0write, CS0 */ + {0x021b001c, 0x04008040}, /* MMDC0_MDSCR, ZQ calibration command sent to device on CS0 */ + + {0x021b0020, 0x00007800}, /* MMDC0_MDREF */ + + {0x021b0818, 0x00000227}, /* DDR_PHY_P0_MPODTCTRL */ + + {0x021b0004, 0x0002552D}, /* MMDC0_MDPDC now SDCTL power down enabled */ + + {0x021b0404, 0x00011006}, /* + * MMDC0_MAPSR ADOPT power down enabled, MMDC will enter + * automatically to self-refresh while the number of idle + * cycle reached + */ + + {0x021b001c, 0x00000000}, /* + * MMDC0_MDSCR, clear this register (especially the configuration + * bit as initialization is complete) + */ +}; + +struct dram_timing_info bsh_dram_timing_512mb = { + .ddrc_cfg = ddr_ddrc_cfg_512mb, + .ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_512mb), +}; diff --git a/board/bsh/imx6ulz_smm_m2/spl.c b/board/bsh/imx6ulz_smm_m2/spl.c index 724841b5745..c330e4d6d39 100644 --- a/board/bsh/imx6ulz_smm_m2/spl.c +++ b/board/bsh/imx6ulz_smm_m2/spl.c @@ -13,10 +13,13 @@ #include <asm/gpio.h> #include <asm/mach-imx/iomux-v3.h> #include <asm/mach-imx/boot_mode.h> +#include <linux/delay.h> #include <linux/libfdt.h> #include <spl.h> #include <asm/arch/mx6-ddr.h> +#include "spl_mtypes.h" + #define UART_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) @@ -31,69 +34,48 @@ static void setup_iomux_uart(void) imx_iomux_v3_setup_multiple_pads(uart4_pads, ARRAY_SIZE(uart4_pads)); } -static struct mx6ul_iomux_grp_regs mx6_grp_ioregs = { - .grp_addds = 0x00000028, - .grp_ddrmode_ctl = 0x00020000, - .grp_b0ds = 0x00000028, - .grp_ctlds = 0x00000028, - .grp_b1ds = 0x00000028, - .grp_ddrpke = 0x00000000, - .grp_ddrmode = 0x00020000, - .grp_ddr_type = 0x000c0000, -}; +static void ddr_cfg_write(const struct dram_timing_info *dram_timing_info) +{ + int i; + const struct dram_cfg_param *ddrc_cfg = dram_timing_info->ddrc_cfg; + const int ddrc_cfg_num = dram_timing_info->ddrc_cfg_num; + struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR; -static struct mx6ul_iomux_ddr_regs mx6_ddr_ioregs = { - .dram_dqm0 = 0x00000028, - .dram_dqm1 = 0x00000028, - .dram_ras = 0x00000028, - .dram_cas = 0x00000028, - .dram_odt0 = 0x00000028, - .dram_odt1 = 0x00000028, - .dram_sdba2 = 0x00000000, - .dram_sdclk_0 = 0x00000028, - .dram_sdqs0 = 0x00000028, - .dram_sdqs1 = 0x00000028, - .dram_reset = 0x000c0028, -}; + clrbits_le32(&mmdc0->mdctl, 1 << 31); /* clear SDE_0 */ + clrbits_le32(&mmdc0->mdctl, 1 << 30); /* clear SDE_1 */ -static struct mx6_mmdc_calibration mx6_mmcd_calib = { - .p0_mpwldectrl0 = 0x00000000, - .p0_mpwldectrl1 = 0x00100010, - .p0_mpdgctrl0 = 0x414c014c, - .p0_mpdgctrl1 = 0x00000000, - .p0_mprddlctl = 0x40403a42, - .p0_mpwrdlctl = 0x4040342e, -}; + for (i = 0; i < ddrc_cfg_num; i++) { + debug("Writing 0x%x to register 0x%x\n", ddrc_cfg->val, + ddrc_cfg->reg); + writel(ddrc_cfg->val, ddrc_cfg->reg); + ddrc_cfg++; + } +} -static struct mx6_ddr_sysinfo ddr_sysinfo = { - .dsize = 0, - .cs1_mirror = 0, - .cs_density = 32, - .ncs = 1, - .bi_on = 1, - .rtt_nom = 1, - .rtt_wr = 0, - .ralat = 5, - .walat = 1, - .mif3_mode = 3, - .rst_to_cke = 0x23, /* 33 cycles (JEDEC value for DDR3) - total of 500 us */ - .sde_to_rst = 0x10, /* 14 cycles (JEDEC value for DDR3) - total of 200 us */ - .refsel = 1, - .refr = 3, -}; +static void spl_dram_init(void) +{ + /* Configure memory to maximum supported size for detection */ + ddr_cfg_write(&bsh_dram_timing_512mb); -static struct mx6_ddr3_cfg mem_ddr = { - .mem_speed = 1333, - .density = 2, - .width = 16, - .banks = 8, - .rowaddr = 13, - .coladdr = 10, - .pagesz = 2, - .trcd = 1350, - .trcmin = 4950, - .trasmin = 3600, -}; + /* Detect memory physically present */ + gd->ram_size = get_ram_size((void *)CFG_SYS_SDRAM_BASE, SZ_512M); + + /* Reconfigure memory for actual detected size */ + switch (gd->ram_size) { + case SZ_512M: + /* Already configured, nothing to do */ + break; + case SZ_256M: + udelay(1); + ddr_cfg_write(&bsh_dram_timing_256mb); + break; + case SZ_128M: + default: + udelay(1); + ddr_cfg_write(&bsh_dram_timing_128mb); + break; + } +} static void ccgr_init(void) { @@ -108,20 +90,17 @@ static void ccgr_init(void) writel(0xFFFFFFFF, &ccm->CCGR6); } -static void imx6ul_spl_dram_cfg(void) -{ - mx6ul_dram_iocfg(mem_ddr.width, &mx6_ddr_ioregs, &mx6_grp_ioregs); - mx6_dram_cfg(&ddr_sysinfo, &mx6_mmcd_calib, &mem_ddr); -} - void board_init_f(ulong dummy) { ccgr_init(); + + /* DDR initialization */ + spl_dram_init(); + arch_cpu_init(); timer_init(); setup_iomux_uart(); preloader_console_init(); - imx6ul_spl_dram_cfg(); } void reset_cpu(void) diff --git a/board/bsh/imx6ulz_smm_m2/spl_mtypes.h b/board/bsh/imx6ulz_smm_m2/spl_mtypes.h new file mode 100644 index 00000000000..8da59881c83 --- /dev/null +++ b/board/bsh/imx6ulz_smm_m2/spl_mtypes.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2025 BSH Hausgeraete GmbH + * + * Written by: Simon Holesch <simon.holesch@bshg.com> + */ + +#ifndef SPL_MTYPES_H +#define SPL_MTYPES_H + +#include <spl.h> + +struct dram_cfg_param { + unsigned int reg; + unsigned int val; +}; + +struct dram_timing_info { + const struct dram_cfg_param *ddrc_cfg; + unsigned int ddrc_cfg_num; +}; + +extern struct dram_timing_info bsh_dram_timing_128mb; +extern struct dram_timing_info bsh_dram_timing_256mb; +extern struct dram_timing_info bsh_dram_timing_512mb; + +#endif /* SPL_MTYPES_H */ diff --git a/board/bsh/imx8mn_smm_s2/spl.c b/board/bsh/imx8mn_smm_s2/spl.c index 5a77d28cb7e..d36ddd24c63 100644 --- a/board/bsh/imx8mn_smm_s2/spl.c +++ b/board/bsh/imx8mn_smm_s2/spl.c @@ -43,8 +43,6 @@ void spl_board_init(void) int board_early_init_f(void) { - init_uart_clk(3); - if (IS_ENABLED(CONFIG_NAND_MXS)) { init_nand_clk(); } diff --git a/board/emulation/qemu-x86/Kconfig b/board/emulation/qemu-x86/Kconfig index b2a4e0891a4..c1564fba7cd 100644 --- a/board/emulation/qemu-x86/Kconfig +++ b/board/emulation/qemu-x86/Kconfig @@ -23,5 +23,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply VIRTIO_PCI imply VIRTIO_NET imply VIRTIO_BLK + imply CMD_SMBIOS endif diff --git a/board/freescale/imx8mn_evk/spl.c b/board/freescale/imx8mn_evk/spl.c index 231b9289eea..f96f5c45789 100644 --- a/board/freescale/imx8mn_evk/spl.c +++ b/board/freescale/imx8mn_evk/spl.c @@ -115,8 +115,6 @@ void board_init_f(ulong dummy) arch_cpu_init(); - init_uart_clk(1); - timer_init(); /* Clear the BSS. */ diff --git a/board/phytec/phycore_imx93/MAINTAINERS b/board/phytec/phycore_imx93/MAINTAINERS index 718f89a084a..7393061707d 100644 --- a/board/phytec/phycore_imx93/MAINTAINERS +++ b/board/phytec/phycore_imx93/MAINTAINERS @@ -3,8 +3,6 @@ M: Mathieu Othacehe <m.othacehe@gmail.com> R: Christoph Stoidner <c.stoidner@phytec.de> W: https://www.phytec.eu/en/produkte/system-on-modules/phycore-imx-91-93/ S: Maintained -F: arch/arm/dts/imx93-phyboard-segin.dts -F: arch/arm/dts/imx93-phycore-som.dtsi F: arch/arm/dts/imx93-phyboard-segin-u-boot.dtsi F: board/phytec/phycore_imx93/ F: board/phytec/common/imx93_som_detection.c diff --git a/board/thead/th1520_lpi4a/Kconfig b/board/thead/th1520_lpi4a/Kconfig index 622246127c1..f139d5ff2bb 100644 --- a/board/thead/th1520_lpi4a/Kconfig +++ b/board/thead/th1520_lpi4a/Kconfig @@ -11,7 +11,7 @@ config SYS_VENDOR default "thead" config SYS_CPU - default "generic" + default "th1520" config SYS_CONFIG_NAME default "th1520_lpi4a" @@ -22,7 +22,7 @@ config TEXT_BASE default 0x01c00000 if RISCV_SMODE config SPL_TEXT_BASE - default 0x08000000 + default 0xffe0000000 config SPL_OPENSBI_LOAD_ADDR default 0x80000000 @@ -30,6 +30,7 @@ config SPL_OPENSBI_LOAD_ADDR config BOARD_SPECIFIC_OPTIONS def_bool y select ARCH_EARLY_INIT_R + select THEAD_TH1520 imply CPU imply CPU_RISCV imply RISCV_TIMER if RISCV_SMODE diff --git a/board/thead/th1520_lpi4a/Makefile b/board/thead/th1520_lpi4a/Makefile index 9671b3bbb0b..a7ddfc48d40 100644 --- a/board/thead/th1520_lpi4a/Makefile +++ b/board/thead/th1520_lpi4a/Makefile @@ -3,3 +3,4 @@ # Copyright (c) 2023, Yixun Lan <dlan@gentoo.org> obj-y += board.o +obj-$(CONFIG_XPL_BUILD) += spl.o diff --git a/board/thead/th1520_lpi4a/spl.c b/board/thead/th1520_lpi4a/spl.c new file mode 100644 index 00000000000..25dfa387c36 --- /dev/null +++ b/board/thead/th1520_lpi4a/spl.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2025, Yao Zi <ziyao@disroot.org> + */ + +#include <asm/io.h> +#include <asm/spl.h> +#include <asm/arch/cpu.h> +#include <asm/arch/spl.h> +#include <cpu_func.h> +#include <dm.h> +#include <hang.h> +#include <spl.h> + +u32 spl_boot_device(void) +{ + /* + * We don't bother to load proper U-Boot from an external device as + * it fits in the integrated SRAM nicely. + */ + return BOOT_DEVICE_RAM; +} + +void board_init_f(ulong dummy) +{ + int ret = spl_early_init(); + struct udevice *dev; + + if (ret) + panic("spl_early_init() failed %d\n", ret); + + preloader_console_init(); + + /* + * Manually bind CPU ahead of time to make sure in-core timers are + * available in SPL. + */ + ret = uclass_get_device(UCLASS_CPU, 0, &dev); + if (ret) + panic("failed to bind CPU: %d\n", ret); + + spl_dram_init(); + + icache_enable(); + dcache_enable(); + + th1520_invalidate_pmp(); +} diff --git a/boot/image.c b/boot/image.c index 139c5bd035a..45299a7dc33 100644 --- a/boot/image.c +++ b/boot/image.c @@ -92,7 +92,8 @@ static const table_entry_t uimage_arch[] = { { IH_ARCH_ARC, "arc", "ARC", }, { IH_ARCH_X86_64, "x86_64", "AMD x86_64", }, { IH_ARCH_XTENSA, "xtensa", "Xtensa", }, - { IH_ARCH_RISCV, "riscv", "RISC-V", }, + { IH_ARCH_RISCV, "riscv", "RISC-V 32 Bit",}, + { IH_ARCH_RISCV64, "riscv64", "RISC-V 64 Bit",}, { -1, "", "", }, }; diff --git a/cmd/bootefi.c b/cmd/bootefi.c index cea6d356ee6..8e8752127ed 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -9,6 +9,7 @@ #include <command.h> #include <efi.h> +#include <efi_device_path.h> #include <efi_loader.h> #include <exports.h> #include <log.h> diff --git a/cmd/booti.c b/cmd/booti.c index 1a57fe91397..ced2c1047ab 100644 --- a/cmd/booti.c +++ b/cmd/booti.c @@ -130,8 +130,11 @@ int do_booti(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) bootm_disable_interrupts(); images.os.os = IH_OS_LINUX; - if (IS_ENABLED(CONFIG_RISCV_SMODE)) - images.os.arch = IH_ARCH_RISCV; + if (IS_ENABLED(CONFIG_RISCV)) + if (IS_ENABLED(CONFIG_64BIT)) + images.os.arch = IH_ARCH_RISCV64; + else + images.os.arch = IH_ARCH_RISCV; else if (IS_ENABLED(CONFIG_ARM64)) images.os.arch = IH_ARCH_ARM64; diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c index 629bf1b82c7..6e14d34a6bd 100644 --- a/cmd/eficonfig.c +++ b/cmd/eficonfig.c @@ -8,6 +8,7 @@ #include <ansi.h> #include <cli.h> #include <charset.h> +#include <efi_device_path.h> #include <efi_loader.h> #include <efi_load_initrd.h> #include <efi_config.h> @@ -514,7 +515,7 @@ struct efi_device_path *eficonfig_create_device_path(struct efi_device_path *dp_ struct efi_device_path_file_path *fp; fp_size = sizeof(struct efi_device_path) + u16_strsize(current_path); - buf = calloc(1, fp_size + sizeof(END)); + buf = calloc(1, fp_size + sizeof(EFI_DP_END)); if (!buf) return NULL; @@ -526,7 +527,7 @@ struct efi_device_path *eficonfig_create_device_path(struct efi_device_path *dp_ p = buf; p += fp_size; - *((struct efi_device_path *)p) = END; + *((struct efi_device_path *)p) = EFI_DP_END; dp = efi_dp_shorten(dp_volume); if (!dp) diff --git a/cmd/efidebug.c b/cmd/efidebug.c index 2461425e291..109496d9e95 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -8,6 +8,7 @@ #include <charset.h> #include <command.h> #include <dm/device.h> +#include <efi_device_path.h> #include <efi_dt_fixup.h> #include <efi_load_initrd.h> #include <efi_loader.h> @@ -812,7 +813,7 @@ static int efi_boot_add_uri(int argc, char *const argv[], u16 *var_name16, lo->label = label; uridp_len = sizeof(struct efi_device_path) + strlen(argv[3]) + 1; - uridp = efi_alloc(uridp_len + sizeof(END)); + uridp = efi_alloc(uridp_len + sizeof(EFI_DP_END)); if (!uridp) { log_err("Out of memory\n"); return CMD_RET_FAILURE; @@ -822,10 +823,10 @@ static int efi_boot_add_uri(int argc, char *const argv[], u16 *var_name16, uridp->dp.length = uridp_len; strcpy(uridp->uri, argv[3]); pos = (char *)uridp + uridp_len; - memcpy(pos, &END, sizeof(END)); + memcpy(pos, &EFI_DP_END, sizeof(EFI_DP_END)); *file_path = &uridp->dp; - *fp_size += uridp_len + sizeof(END); + *fp_size += uridp_len + sizeof(EFI_DP_END); return CMD_RET_SUCCESS; } diff --git a/cmd/tlv_eeprom.c b/cmd/tlv_eeprom.c index 0aec7521770..d7c229e5441 100644 --- a/cmd/tlv_eeprom.c +++ b/cmd/tlv_eeprom.c @@ -476,6 +476,7 @@ int do_tlv_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) printf("EEPROM data loaded from device to memory.\n"); has_been_read = 1; + return 0; } // Subsequent commands require that the EEPROM has already been read. diff --git a/common/board_r.c b/common/board_r.c index 65ff5fb595c..980bd3813af 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -814,7 +814,9 @@ void board_init_r(gd_t *new_gd, ulong dest_addr) if (CONFIG_IS_ENABLED(X86_64) && !IS_ENABLED(CONFIG_EFI_APP)) arch_setup_gd(new_gd); -#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64) +#if defined(CONFIG_RISCV) + set_gd(new_gd); +#elif !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64) gd = new_gd; #endif gd->flags &= ~GD_FLG_LOG_READY; diff --git a/common/cyclic.c b/common/cyclic.c index b695f092f52..ec952a01ee1 100644 --- a/common/cyclic.c +++ b/common/cyclic.c @@ -28,9 +28,23 @@ struct hlist_head *cyclic_get_list(void) return (struct hlist_head *)&gd->cyclic_list; } +static bool cyclic_is_registered(const struct cyclic_info *cyclic) +{ + const struct cyclic_info *c; + + hlist_for_each_entry(c, cyclic_get_list(), list) { + if (c == cyclic) + return true; + } + + return false; +} + void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, uint64_t delay_us, const char *name) { + cyclic_unregister(cyclic); + memset(cyclic, 0, sizeof(*cyclic)); /* Store values in struct */ @@ -43,6 +57,9 @@ void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, void cyclic_unregister(struct cyclic_info *cyclic) { + if (!cyclic_is_registered(cyclic)) + return; + hlist_del(&cyclic->list); } diff --git a/common/init/board_init.c b/common/init/board_init.c index a06ec1caa2c..2a6f39f51ad 100644 --- a/common/init/board_init.c +++ b/common/init/board_init.c @@ -13,8 +13,11 @@ DECLARE_GLOBAL_DATA_PTR; -/* Unfortunately x86 or ARM can't compile this code as gd cannot be assigned */ -#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) +/* + * Unfortunately x86, ARM and RISC-V can't compile this code as gd is defined + * as macro and cannot be assigned. + */ +#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_RISCV) __weak void arch_setup_gd(struct global_data *gd_ptr) { gd = gd_ptr; diff --git a/common/spl/Kconfig b/common/spl/Kconfig index a84a0f83924..be87b3e63fd 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -974,6 +974,21 @@ config SPL_NAND_SUPPORT This enables the drivers in drivers/mtd/nand/raw as part of an SPL build. +config SPL_NAND_RAW_U_BOOT_USE_SECTOR + bool "NAND raw mode: by sector" + depends on SPL_NAND_SUPPORT + select SPL_LOAD_BLOCK + help + Use sector number for specifying U-Boot location on NAND in + raw mode. + +config SPL_NAND_RAW_U_BOOT_SECTOR + hex "Address on the NAND to load U-Boot from" + depends on SPL_NAND_RAW_U_BOOT_USE_SECTOR + help + Address on the NAND to load U-Boot from, when the NAND is being used + in raw mode. Units: NAND disk sectors (1 sector = 512 bytes). + config SPL_NAND_RAW_ONLY bool "Support to boot only raw u-boot.bin images" depends on SPL_NAND_SUPPORT diff --git a/configs/ds109_defconfig b/configs/ds109_defconfig index ef805eca562..1dafef3529b 100644 --- a/configs/ds109_defconfig +++ b/configs/ds109_defconfig @@ -54,8 +54,6 @@ CONFIG_MVGBE=y CONFIG_MII=y CONFIG_DM_RTC=y CONFIG_RTC_MV=y -CONFIG_SYS_NS16550_SERIAL=y -CONFIG_SYS_NS16550_REG_SIZE=-4 CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_KIRKWOOD_SPI=y diff --git a/configs/imx6ulz_smm_m2_defconfig b/configs/imx6ulz_smm_m2_defconfig index 15a3ec5c627..436bfb78cc2 100644 --- a/configs/imx6ulz_smm_m2_defconfig +++ b/configs/imx6ulz_smm_m2_defconfig @@ -64,6 +64,8 @@ CONFIG_DM_PMIC=y CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_FIXED=y CONFIG_MXC_UART=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_WATCHDOG=y CONFIG_IMX_THERMAL=y CONFIG_USB=y CONFIG_SPL_USB_HOST=y @@ -75,3 +77,4 @@ CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5 CONFIG_CI_UDC=y CONFIG_SDP_LOADADDR=0x877fffc0 CONFIG_SPL_USB_SDP_SUPPORT=y +CONFIG_IMX_WATCHDOG=y diff --git a/configs/imx8mn_bsh_smm_s2_defconfig b/configs/imx8mn_bsh_smm_s2_defconfig index 9ffcd3b221c..206d216394d 100644 --- a/configs/imx8mn_bsh_smm_s2_defconfig +++ b/configs/imx8mn_bsh_smm_s2_defconfig @@ -15,7 +15,6 @@ CONFIG_SYS_MONITOR_LEN=524288 CONFIG_SPL_SERIAL=y CONFIG_SPL_DRIVERS_MISC=y CONFIG_SPL_STACK=0x980000 -CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000 CONFIG_SPL_TEXT_BASE=0x912000 CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x950000 @@ -47,6 +46,8 @@ CONFIG_SPL_DMA=y CONFIG_SPL_I2C=y CONFIG_SPL_MTD=y CONFIG_SPL_NAND_SUPPORT=y +CONFIG_SPL_NAND_RAW_U_BOOT_USE_SECTOR=y +CONFIG_SPL_NAND_RAW_U_BOOT_SECTOR=0x300 CONFIG_SPL_NAND_BASE=y CONFIG_SPL_NAND_IDENT=y CONFIG_SPL_POWER=y diff --git a/configs/imx8mn_bsh_smm_s2pro_defconfig b/configs/imx8mn_bsh_smm_s2pro_defconfig index d2010d13b8c..ef486f51eee 100644 --- a/configs/imx8mn_bsh_smm_s2pro_defconfig +++ b/configs/imx8mn_bsh_smm_s2pro_defconfig @@ -16,7 +16,6 @@ CONFIG_SPL_MMC=y CONFIG_SPL_SERIAL=y CONFIG_SPL_DRIVERS_MISC=y CONFIG_SPL_STACK=0x980000 -CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000 CONFIG_SPL_TEXT_BASE=0x912000 CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x950000 diff --git a/configs/imx93-phycore_defconfig b/configs/imx93-phycore_defconfig index 7187fd70833..66a431244b0 100644 --- a/configs/imx93-phycore_defconfig +++ b/configs/imx93-phycore_defconfig @@ -12,7 +12,7 @@ CONFIG_ENV_SIZE=0x10000 CONFIG_ENV_OFFSET=0x700000 CONFIG_IMX_CONFIG="arch/arm/mach-imx/imx9/imximage.cfg" CONFIG_DM_GPIO=y -CONFIG_DEFAULT_DEVICE_TREE="imx93-phyboard-segin" +CONFIG_DEFAULT_DEVICE_TREE="freescale/imx93-phyboard-segin" CONFIG_AHAB_BOOT=y CONFIG_TARGET_PHYCORE_IMX93=y CONFIG_OF_LIBFDT_OVERLAY=y diff --git a/configs/imx95_19x19_evk_defconfig b/configs/imx95_19x19_evk_defconfig index a40d93db0df..32aee1fa90a 100644 --- a/configs/imx95_19x19_evk_defconfig +++ b/configs/imx95_19x19_evk_defconfig @@ -41,6 +41,7 @@ CONFIG_SYS_PBSIZE=2074 CONFIG_ARCH_MISC_INIT=y CONFIG_BOARD_EARLY_INIT_F=y CONFIG_BOARD_LATE_INIT=y +CONFIG_PCI_INIT_R=y CONFIG_SPL_MAX_SIZE=0x20000 CONFIG_SPL_BOARD_INIT=y CONFIG_SPL_LOAD_IMX_CONTAINER=y diff --git a/configs/imxrt1170-evk_defconfig b/configs/imxrt1170-evk_defconfig index 32107fa9d52..a57c35bf686 100644 --- a/configs/imxrt1170-evk_defconfig +++ b/configs/imxrt1170-evk_defconfig @@ -37,6 +37,8 @@ CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x100 # CONFIG_BOOTM_PLAN9 is not set # CONFIG_BOOTM_RTEMS is not set # CONFIG_BOOTM_VXWORKS is not set +CONFIG_CMD_MTD=y +CONFIG_CMD_SPI=y # CONFIG_CMD_MII is not set # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_ISO_PARTITION is not set @@ -58,6 +60,15 @@ CONFIG_CLK_IMXRT1170=y CONFIG_MXC_GPIO=y # CONFIG_INPUT is not set CONFIG_FSL_USDHC=y +CONFIG_MTD=y +CONFIG_DM_MTD=y +CONFIG_MTD_BLOCK=y +CONFIG_CFI_FLASH=y +CONFIG_FLASH_CFI_MTD=y +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH_SOFT_RESET=y +CONFIG_SPI_FLASH_ISSI=y +CONFIG_SPI_FLASH_MTD=y CONFIG_PINCTRL=y CONFIG_SPL_PINCTRL=y CONFIG_PINCTRL_IMXRT=y @@ -65,6 +76,10 @@ CONFIG_RAM=y CONFIG_SPL_RAM=y CONFIG_IMXRT_SDRAM=y CONFIG_FSL_LPUART=y +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_SPI_DIRMAP=y +CONFIG_NXP_FSPI=y CONFIG_TIMER=y CONFIG_SPL_TIMER=y CONFIG_IMX_GPT_TIMER=y diff --git a/configs/mvebu_espressobin_ultra-88f3720_defconfig b/configs/mvebu_espressobin_ultra-88f3720_defconfig index 1cbeee8fcb7..fb8efbdf0b9 100644 --- a/configs/mvebu_espressobin_ultra-88f3720_defconfig +++ b/configs/mvebu_espressobin_ultra-88f3720_defconfig @@ -97,3 +97,5 @@ CONFIG_USB_EHCI_HCD=y # CONFIG_WATCHDOG_AUTOSTART is not set CONFIG_WDT=y CONFIG_WDT_ARMADA_37XX=y +CONFIG_DM_RNG=y +CONFIG_RNG_TURRIS_RWTM=y diff --git a/configs/th1520_lpi4a_defconfig b/configs/th1520_lpi4a_defconfig index d13c97463a8..b19dc009fde 100644 --- a/configs/th1520_lpi4a_defconfig +++ b/configs/th1520_lpi4a_defconfig @@ -90,3 +90,21 @@ CONFIG_ZLIB_UNCOMPRESS=y CONFIG_BZIP2=y CONFIG_ZSTD=y CONFIG_LIB_RATIONAL=y +CONFIG_SPL=y +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SPL_LOAD_FIT_ADDRESS=0xffe0040000 +CONFIG_SPL_HAVE_INIT_STACK=y +CONFIG_SPL_STACK=0xffe0170000 +CONFIG_SPL_BSS_START_ADDR=0xffe0160000 +CONFIG_SPL_BSS_MAX_SIZE=0x10000 +CONFIG_SPL_MAX_SIZE=0x40000 +CONFIG_SPL_RAM_DEVICE=y +CONFIG_RAM=y +CONFIG_SPL_RAM=y +CONFIG_SPL_THEAD_TH1520_DDR=y +CONFIG_SPL_GPIO=y +CONFIG_SPL_MMC_y +CONFIG_SPL_SYS_MALLOC=y +CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y +CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x10000000 +CONFIG_SPL_SYS_MALLOC_SIZE=0x400000 diff --git a/configs/total_compute_defconfig b/configs/total_compute_defconfig index 70bec3ba3a0..e66c011efb1 100644 --- a/configs/total_compute_defconfig +++ b/configs/total_compute_defconfig @@ -55,3 +55,6 @@ CONFIG_SYS_FLASH_CFI=y CONFIG_SYS_MAX_FLASH_SECT=256 # CONFIG_RANDOM_UUID is not set CONFIG_LIBAVB=y +CONFIG_BLOBLIST=y +CONFIG_BLOBLIST_PASSAGE_MANDATORY=y +CONFIG_BLOBLIST_SIZE_RELOC=0x10000 diff --git a/doc/README.omap-ulpi-viewport b/doc/README.omap-ulpi-viewport deleted file mode 100644 index a5240b9e295..00000000000 --- a/doc/README.omap-ulpi-viewport +++ /dev/null @@ -1,27 +0,0 @@ -Reference code ""drivers/usb/ulpi/omap-ulpi-viewport.c" - -Contains the ulpi read write api's to perform -any ulpi phy port access on omap platform. - -On omap ehci reg map contains INSNREG05_ULPI -register which offers the ulpi phy access so -any ulpi phy commands should be passsed using this -register. - -omap-ulpi-viewport.c is a low level function -implementation of "drivers/usb/ulpi/ulpi.c" - -To enable and use omap-ulpi-viewport.c -we require CONFIG_USB_ULPI_VIEWPORT_OMAP and -CONFIG_USB_ULPI be enabled in config file. - -Any ulpi ops request can be done with ulpi.c -and soc specific binding and usage is done with -omap-ulpi-viewport implementation. - -Ex: scenario: -omap-ehci driver code requests for ulpi phy reset if -ehci is used in phy mode, which will call ulpi phy reset -the ulpi phy reset does ulpi_read/write from viewport -implementation which will do ulpi reset using the -INSNREG05_ULPI register. diff --git a/doc/api/efi.rst b/doc/api/efi.rst index 43d6f936fb0..a98298f93dc 100644 --- a/doc/api/efi.rst +++ b/doc/api/efi.rst @@ -178,6 +178,12 @@ Driver binding protocol .. kernel-doc:: include/efi_driver.h :internal: +Device paths +------------ + +.. kernel-doc:: include/efi_device_path.h + :internal: + Unit testing ------------ diff --git a/doc/board/thead/lpi4a.rst b/doc/board/thead/lpi4a.rst index e395c6ae12c..7e4c4ea81ee 100644 --- a/doc/board/thead/lpi4a.rst +++ b/doc/board/thead/lpi4a.rst @@ -32,6 +32,8 @@ Mainline support The support for following drivers are already enabled: 1. ns16550 UART Driver. +2. eMMC and SD card + Building ~~~~~~~~ @@ -43,15 +45,32 @@ Building export CROSS_COMPILE=<riscv64 toolchain prefix> -The U-Boot is capable of running in M-Mode, so we can directly build it. +3. Build DDR firmware + +DDR driver requires a firmware to function, to build it: + +.. code-block:: bash + + git clone --depth 1 https://github.com/ziyao233/th1520-firmware + cd th1520-firmware + lua5.4 ddr-generate.lua src/<CONFIGURATION_NAME>.lua th1520-ddr-firmware.bin + +4. Build U-Boot images + +The U-Boot is capable of running in M-Mode, so we can directly build it without +OpenSBI. The DDR firmware should be copied to U-Boot source directory before +building. .. code-block:: console cd <U-Boot-dir> + cp <path-to-ddr-firmware> th1520-ddr-firmware.bin make th1520_lpi4a_defconfig make -This will generate u-boot-dtb.bin +This will generate u-boot-dtb.bin and u-boot-with-spl.bin. The former contains +only proper U-Boot and is for chainloading; the later contains also SPL and +DDR firmware and is ready for booting by BROM directly. Booting ~~~~~~~ @@ -61,7 +80,7 @@ and chain load the mainline u-boot image either via tftp or emmc storage, then bootup from it. Sample boot log from Lichee PI 4A board via tftp -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: none @@ -127,3 +146,36 @@ Sample boot log from Lichee PI 4A board via tftp Err: serial@ffe7014000 Model: Sipeed Lichee Pi 4A LPI4A=> + +SPL support is still in an early stage and not all of the functionalities are +available when booting from mainline SPL. When using mainline SPL, +u-boot-with-spl.bin should be loaded to SRAM through fastboot. + +Sample boot log from Lichee PI 4A board via fastboot and mainline SPL +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + brom_ver 8 + [APP][E] protocol_connect failed, exit. + Starting download of 636588 bytes + + downloading of 636588 bytes finished + + U-Boot SPL 2025.04-rc2-00049-geaa9fc99d4cd-dirty (Apr 26 2025 - 13:31:41 +0000) + Trying to boot from RAM + + + U-Boot 2025.04-rc2-00049-geaa9fc99d4cd-dirty (Apr 26 2025 - 13:31:41 +0000) + + CPU: thead,c910 + Model: Sipeed Lichee Pi 4A + DRAM: 8 GiB + Core: 30 devices, 9 uclasses, devicetree: separate + MMC: mmc@ffe7080000: 0, mmc@ffe7090000: 1 + Loading Environment from <NULL>... OK + In: serial@ffe7014000 + Out: serial@ffe7014000 + Err: serial@ffe7014000 + Model: Sipeed Lichee Pi 4A + LPI4A=> diff --git a/doc/develop/cyclic.rst b/doc/develop/cyclic.rst index 6f1da6f0d9b..a99b17052f5 100644 --- a/doc/develop/cyclic.rst +++ b/doc/develop/cyclic.rst @@ -54,3 +54,16 @@ responsible for calling all registered cyclic functions, into the common schedule() function. This guarantees that cyclic_run() is executed very often, which is necessary for the cyclic functions to get scheduled and executed at their configured periods. + +Idempotence +----------- + +Both the cyclic_register() and cyclic_unregister() functions are safe +to call on any struct cyclic_info, regardless of whether that instance +is already registered or not. + +More specifically, calling cyclic_unregister() with a cyclic_info +which is not currently registered is a no-op, while calling +cyclic_register() with a cyclic_info which is currently registered +results in it being automatically unregistered, and then registered +with the new callback function and timeout parameters. diff --git a/doc/develop/pytest/index.rst b/doc/develop/pytest/index.rst index 0a7c1b21a24..dce8a96370f 100644 --- a/doc/develop/pytest/index.rst +++ b/doc/develop/pytest/index.rst @@ -16,12 +16,6 @@ Individual tests .. toctree:: :maxdepth: 1 + :glob: - test_000_version - test_bind - test_bootmenu - test_bootstage - test_button - test_efi_loader - test_net - test_net_boot + test_* diff --git a/doc/develop/pytest/usage.rst b/doc/develop/pytest/usage.rst index 49d269d66a7..779b2dbe24b 100644 --- a/doc/develop/pytest/usage.rst +++ b/doc/develop/pytest/usage.rst @@ -522,3 +522,27 @@ of the `ubman.config` object, for example Build configuration values (from `.config`) may be accessed via the dictionary `ubman.config.buildconfig`, with keys equal to the Kconfig variable names. + +A required configuration setting can be defined via a buildconfigspec() +annotation. The name of the configuration option is specified in lower case. The +following annotation for a test requires CONFIG_EFI_LOADER=y: + +.. code-block:: python + + @pytest.mark.buildconfigspec('efi_loader') + +Sometimes multiple configuration option supply the same functionality. If +multiple arguments are passed to buildconfigspec(), only one of the +configuration options needs to be set. The following annotation requires that +either of CONFIG_NET or CONFIG_NET_LWIP is set: + +.. code-block:: python + + @pytest.mark.buildconfigspec('net', 'net lwip') + +The notbuildconfigspec() annotation can be used to require a configuration +option not to be set. The following annotation requires CONFIG_RISCV=n: + +.. code-block:: python + + @pytest.mark.notbuildconfigspec('riscv') diff --git a/doc/develop/release_cycle.rst b/doc/develop/release_cycle.rst index b68b462257d..36bb9055e6a 100644 --- a/doc/develop/release_cycle.rst +++ b/doc/develop/release_cycle.rst @@ -75,7 +75,7 @@ For the next scheduled release, release candidates were made on:: * U-Boot |next_ver|-rc2 was released on Mon 12 May 2025. -.. * U-Boot |next_ver|-rc3 was released on Mon 26 May 2025. +* U-Boot |next_ver|-rc3 was released on Mon 26 May 2025. .. * U-Boot |next_ver|-rc4 was released on Mon 09 June 2025. diff --git a/doc/usage/cmd/wget.rst b/doc/usage/cmd/wget.rst index cc82e495a29..44033aaff39 100644 --- a/doc/usage/cmd/wget.rst +++ b/doc/usage/cmd/wget.rst @@ -141,9 +141,9 @@ https://cacerts.digicert.com/DigiCertTLSRSA4096RootG5.crt. Bytes transferred = 1864 (748 hex) # Another server not signed against Digicert will fail => wget https://www.google.com/ - Certificate verification failed HTTP client error 4 + Certificate verification failed # Disable authentication to allow the command to proceed anyways => wget cacert none => wget https://www.google.com/ diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 18bd640a68b..19aa2ffa539 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -271,6 +271,7 @@ source "drivers/clk/starfive/Kconfig" source "drivers/clk/stm32/Kconfig" source "drivers/clk/tegra/Kconfig" source "drivers/clk/ti/Kconfig" +source "drivers/clk/thead/Kconfig" source "drivers/clk/uniphier/Kconfig" endmenu diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 8411205ee04..5f0c0d8a5c2 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -20,6 +20,7 @@ obj-y += imx/ obj-$(CONFIG_CLK_JH7110) += starfive/ obj-y += tegra/ obj-y += ti/ +obj-$(CONFIG_CLK_THEAD) += thead/ obj-$(CONFIG_$(PHASE_)CLK_INTEL) += intel/ obj-$(CONFIG_ARCH_ASPEED) += aspeed/ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ diff --git a/drivers/clk/imx/clk-imxrt1170.c b/drivers/clk/imx/clk-imxrt1170.c index 3f55d0d0127..bfd5dd6c464 100644 --- a/drivers/clk/imx/clk-imxrt1170.c +++ b/drivers/clk/imx/clk-imxrt1170.c @@ -105,6 +105,8 @@ static const char * const usdhc1_sels[] = {"rcosc48M_div2", "osc", "rcosc400M", "pll2_pfd2", "pll2_pfd0", "pll1_div5", "pll_arm"}; static const char * const semc_sels[] = {"rcosc48M_div2", "osc", "rcosc400M", "rcosc16M", "pll1_div5", "pll2_sys", "pll2_pfd2", "pll3_pfd0"}; +static const char * const flexspi1_sels[] = {"rcosc48M_div2", "osc", "rcosc400M", "rcosc16M", +"pll3_pdf0", "pll2_clk", "pll2_pfd2", "pll3_clk"}; static int imxrt1170_clk_probe(struct udevice *dev) { @@ -163,6 +165,13 @@ static int imxrt1170_clk_probe(struct udevice *dev) imx_clk_divider(dev, "lpuart1", "lpuart1_sel", base + (25 * 0x80), 0, 8)); + clk_dm(IMXRT1170_CLK_FLEXSPI1_SEL, + imx_clk_mux(dev, "flexspi1_sel", base + (20 * 0x80), 8, 3, + flexspi1_sels, ARRAY_SIZE(flexspi1_sels))); + clk_dm(IMXRT1170_CLK_FLEXSPI1, + imx_clk_divider(dev, "flexspi1", "flexspi1_sel", + base + (20 * 0x80), 0, 8)); + clk_dm(IMXRT1170_CLK_USDHC1_SEL, imx_clk_mux(dev, "usdhc1_sel", base + (58 * 0x80), 8, 3, usdhc1_sels, ARRAY_SIZE(usdhc1_sels))); diff --git a/drivers/clk/thead/Kconfig b/drivers/clk/thead/Kconfig new file mode 100644 index 00000000000..e815286b085 --- /dev/null +++ b/drivers/clk/thead/Kconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (c) 2025, Yao Zi <ziyao@disroot.org> + +config CLK_THEAD + bool "Clock support for T-Head SoCs" + depends on CLK + +if CLK_THEAD + +config CLK_THEAD_TH1520_AP + bool "T-Head TH1520 AP clock support" + select CLK_CCF + default THEAD_TH1520 + help + This enables support clock driver for T-Head TH1520 Application + processor. + +endif diff --git a/drivers/clk/thead/Makefile b/drivers/clk/thead/Makefile new file mode 100644 index 00000000000..8cc05ed7914 --- /dev/null +++ b/drivers/clk/thead/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (C) 2025 Yao Zi <ziyao@disroot.org> + +obj-$(CONFIG_CLK_THEAD_TH1520_AP) += clk-th1520-ap.o diff --git a/drivers/clk/thead/clk-th1520-ap.c b/drivers/clk/thead/clk-th1520-ap.c new file mode 100644 index 00000000000..b80ad05b8ad --- /dev/null +++ b/drivers/clk/thead/clk-th1520-ap.c @@ -0,0 +1,1031 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org> + * Copyright (C) 2023 Vivo Communication Technology Co. Ltd. + * Copyright (C) 2025 Yao Zi <ziyao@disroot.org> + * Authors: Yangtao Li <frank.li@vivo.com> + */ + +#include <asm/io.h> +#include <dm.h> +#include <linux/bitfield.h> +#include <linux/clk-provider.h> + +#include <dt-bindings/clock/thead,th1520-clk-ap.h> + +#define TH1520_PLL_POSTDIV2 GENMASK(26, 24) +#define TH1520_PLL_POSTDIV1 GENMASK(22, 20) +#define TH1520_PLL_FBDIV GENMASK(19, 8) +#define TH1520_PLL_REFDIV GENMASK(5, 0) +#define TH1520_PLL_BYPASS BIT(30) +#define TH1520_PLL_DSMPD BIT(24) +#define TH1520_PLL_FRAC GENMASK(23, 0) +#define TH1520_PLL_FRAC_BITS 24 + +static const char ccu_osc_name_to_be_filled[] = "TO BE FILLED"; + +struct ccu_internal { + u8 shift; + u8 width; +}; + +struct ccu_div_internal { + u8 shift; + u8 width; +}; + +struct ccu_common { + void __iomem *reg; + const char *name; + struct clk clk; + int clkid; + u16 cfg0; + u16 cfg1; +}; + +struct ccu_mux { + struct ccu_common common; + struct ccu_internal mux; + const char **parents; + size_t num_parents; +}; + +struct ccu_gate { + struct ccu_common common; + const char *parent; + u32 enable; +}; + +struct ccu_div { + struct ccu_div_internal div; + struct ccu_common common; + struct ccu_internal mux; + const char **parents; + size_t num_parents; + u32 enable; +}; + +struct ccu_pll { + struct ccu_common common; +}; + +#define TH_CCU_ARG(_shift, _width) \ + { \ + .shift = _shift, \ + .width = _width, \ + } + +#define TH_CCU_DIV_FLAGS(_shift, _width, _flags) \ + { \ + .shift = _shift, \ + .width = _width, \ + } + +#define CCU_GATE(_clkid, _struct, _name, _parent, _reg, _gate, _flags) \ + struct ccu_gate _struct = { \ + .parent = _parent, \ + .enable = _gate, \ + .common = { \ + .clkid = _clkid, \ + .cfg0 = _reg, \ + .name = _name, \ + } \ + } + +static inline struct ccu_common *clk_to_ccu_common(struct clk *clk) +{ + return container_of(clk, struct ccu_common, clk); +} + +static inline struct ccu_mux *clk_to_ccu_mux(struct clk *clk) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + + return container_of(common, struct ccu_mux, common); +} + +static inline struct ccu_pll *clk_to_ccu_pll(struct clk *clk) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + + return container_of(common, struct ccu_pll, common); +} + +static inline struct ccu_div *clk_to_ccu_div(struct clk *clk) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + + return container_of(common, struct ccu_div, common); +} + +static inline struct ccu_gate *clk_to_ccu_gate(struct clk *clk) +{ + struct ccu_common *common = clk_to_ccu_common(clk); + + return container_of(common, struct ccu_gate, common); +} + +static int ccu_set_parent_helper(struct ccu_common *common, + struct ccu_internal *mux, + u8 index) +{ + clrsetbits_le32(common->reg + common->cfg0, + GENMASK(mux->width - 1, 0) << mux->shift, + index << mux->shift); + + return 0; +} + +static void ccu_disable_helper(struct ccu_common *common, u32 gate) +{ + if (!gate) + return; + + clrsetbits_le32(common->reg + common->cfg0, + gate, ~gate); +} + +static int ccu_enable_helper(struct ccu_common *common, u32 gate) +{ + u32 val; + + if (!gate) + return 0; + + clrsetbits_le32(common->reg + common->cfg0, gate, gate); + val = readl(common->reg + common->cfg0); + + return 0; +} + +static int ccu_get_parent_index_helper(const char * const *parents, + int num_parents, struct clk *parent) +{ + const char *parent_name = parent->dev->name; + unsigned int index; + + for (index = 0; index < num_parents; index++) { + if (!strcmp(parents[index], parent_name)) + return index; + } + + return -ENOENT; +} + +static unsigned long ccu_div_get_rate(struct clk *clk) +{ + struct ccu_div *cd = clk_to_ccu_div(clk); + unsigned long rate; + unsigned int val; + + val = readl(cd->common.reg + cd->common.cfg0); + val = val >> cd->div.shift; + val &= GENMASK(cd->div.width - 1, 0); + rate = divider_recalc_rate(clk, clk_get_parent_rate(clk), val, NULL, + 0, cd->div.width); + + return rate; +} + +static int ccu_div_get_parent(struct ccu_div *cd) +{ + u32 val = readl(cd->common.reg + cd->common.cfg0); + + return (val >> cd->mux.shift) & GENMASK(cd->mux.width - 1, 0); +} + +static int ccu_div_set_parent(struct clk *clk, struct clk *parent) +{ + struct ccu_div *cd = clk_to_ccu_div(clk); + u8 id; + + id = ccu_get_parent_index_helper(cd->parents, cd->num_parents, parent); + if (id < 0) + return id; + + return ccu_set_parent_helper(&cd->common, &cd->mux, id); +} + +static int ccu_div_disable(struct clk *clk) +{ + struct ccu_div *cd = clk_to_ccu_div(clk); + + ccu_disable_helper(&cd->common, cd->enable); + + return 0; +} + +static int ccu_div_enable(struct clk *clk) +{ + struct ccu_div *cd = clk_to_ccu_div(clk); + + return ccu_enable_helper(&cd->common, cd->enable); +} + +static const struct clk_ops ccu_div_ops = { + .disable = ccu_div_disable, + .enable = ccu_div_enable, + .set_parent = ccu_div_set_parent, + .get_rate = ccu_div_get_rate, +}; + +U_BOOT_DRIVER(th1520_clk_div) = { + .name = "th1520_clk_div", + .id = UCLASS_CLK, + .ops = &ccu_div_ops, +}; + +static unsigned long th1520_pll_vco_recalc_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct ccu_pll *pll = clk_to_ccu_pll(clk); + unsigned long div, mul, frac; + unsigned int cfg0, cfg1; + u64 rate = parent_rate; + + cfg0 = readl(pll->common.reg + pll->common.cfg0); + cfg1 = readl(pll->common.reg + pll->common.cfg1); + + mul = FIELD_GET(TH1520_PLL_FBDIV, cfg0); + div = FIELD_GET(TH1520_PLL_REFDIV, cfg0); + if (!(cfg1 & TH1520_PLL_DSMPD)) { + mul <<= TH1520_PLL_FRAC_BITS; + frac = FIELD_GET(TH1520_PLL_FRAC, cfg1); + mul += frac; + div <<= TH1520_PLL_FRAC_BITS; + } + + rate = parent_rate * mul; + rate = rate / div; + + return rate; +} + +static unsigned long th1520_pll_postdiv_recalc_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct ccu_pll *pll = clk_to_ccu_pll(clk); + unsigned long div, rate = parent_rate; + unsigned int cfg0, cfg1; + + cfg0 = readl(pll->common.reg + pll->common.cfg0); + cfg1 = readl(pll->common.reg + pll->common.cfg1); + + if (cfg1 & TH1520_PLL_BYPASS) + return rate; + + div = FIELD_GET(TH1520_PLL_POSTDIV1, cfg0) * + FIELD_GET(TH1520_PLL_POSTDIV2, cfg0); + + rate = rate / div; + + return rate; +} + +static unsigned long ccu_pll_get_rate(struct clk *clk) +{ + unsigned long rate = clk_get_parent_rate(clk); + + rate = th1520_pll_vco_recalc_rate(clk, rate); + rate = th1520_pll_postdiv_recalc_rate(clk, rate); + + return rate; +} + +static const struct clk_ops clk_pll_ops = { + .get_rate = ccu_pll_get_rate, +}; + +U_BOOT_DRIVER(th1520_clk_pll) = { + .name = "th1520_clk_pll", + .id = UCLASS_CLK, + .ops = &clk_pll_ops, +}; + +static struct ccu_pll cpu_pll0_clk = { + .common = { + .clkid = CLK_CPU_PLL0, + .cfg0 = 0x000, + .cfg1 = 0x004, + .name = "cpu-pll0", + }, +}; + +static struct ccu_pll cpu_pll1_clk = { + .common = { + .clkid = CLK_CPU_PLL1, + .cfg0 = 0x010, + .cfg1 = 0x014, + .name = "cpu-pll1", + }, +}; + +static struct ccu_pll gmac_pll_clk = { + .common = { + .clkid = CLK_GMAC_PLL, + .cfg0 = 0x020, + .cfg1 = 0x024, + .name = "gmac-pll", + }, +}; + +static const char *gmac_pll_clk_parent[] = { + "gmac-pll", +}; + +static struct ccu_pll video_pll_clk = { + .common = { + .clkid = CLK_VIDEO_PLL, + .cfg0 = 0x030, + .cfg1 = 0x034, + .name = "video-pll", + }, +}; + +static const char *video_pll_clk_parent[] = { + "video-pll", +}; + +static struct ccu_pll dpu0_pll_clk = { + .common = { + .clkid = CLK_DPU0_PLL, + .cfg0 = 0x040, + .cfg1 = 0x044, + .name = "dpu0-pll", + }, +}; + +static const char *dpu0_pll_clk_parent[] = { + "dpu0-pll", +}; + +static struct ccu_pll dpu1_pll_clk = { + .common = { + .clkid = CLK_DPU1_PLL, + .cfg0 = 0x050, + .cfg1 = 0x054, + .name = "dpu1-pll", + }, +}; + +static const char *dpu1_pll_clk_parent[] = { + "dpu1-pll", +}; + +static struct ccu_pll tee_pll_clk = { + .common = { + .clkid = CLK_TEE_PLL, + .cfg0 = 0x060, + .cfg1 = 0x064, + .name = "tee-pll", + }, +}; + +static const char *c910_i0_parents[] = { + "cpu-pll0", ccu_osc_name_to_be_filled, +}; + +static struct ccu_mux c910_i0_clk = { + .parents = c910_i0_parents, + .num_parents = ARRAY_SIZE(c910_i0_parents), + .mux = TH_CCU_ARG(1, 1), + .common = { + .clkid = CLK_C910_I0, + .cfg0 = 0x100, + .name = "c910-i0", + } +}; + +static const char *c910_parents[] = { + "c910-i0", "cpu-pll1", +}; + +static struct ccu_mux c910_clk = { + .parents = c910_parents, + .num_parents = ARRAY_SIZE(c910_parents), + .mux = TH_CCU_ARG(0, 1), + .common = { + .clkid = CLK_C910, + .cfg0 = 0x100, + .name = "c910", + } +}; + +static const char *ahb2_cpusys_parents[] = { + "gmac-pll", ccu_osc_name_to_be_filled, +}; + +static struct ccu_div ahb2_cpusys_hclk = { + .parents = ahb2_cpusys_parents, + .num_parents = ARRAY_SIZE(ahb2_cpusys_parents), + .div = TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED), + .mux = TH_CCU_ARG(5, 1), + .common = { + .clkid = CLK_AHB2_CPUSYS_HCLK, + .cfg0 = 0x120, + .name = "ahb2-cpusys-hclk", + }, +}; + +static const char *ahb2_cpusys_hclk_parents[] = { + "ahb2-cpusys-hclk", +}; + +static struct ccu_div apb3_cpusys_pclk = { + .parents = ahb2_cpusys_hclk_parents, + .num_parents = ARRAY_SIZE(ahb2_cpusys_hclk_parents), + .div = TH_CCU_ARG(0, 3), + .common = { + .clkid = CLK_APB3_CPUSYS_PCLK, + .cfg0 = 0x130, + .name = "apb3-cpusys-pclk", + }, +}; + +static struct ccu_div axi4_cpusys2_aclk = { + .parents = gmac_pll_clk_parent, + .num_parents = ARRAY_SIZE(gmac_pll_clk_parent), + .div = TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED), + .common = { + .clkid = CLK_AXI4_CPUSYS2_ACLK, + .cfg0 = 0x134, + .name = "axi4-cpusys2-aclk", + }, +}; + +static const char *axi_parents[] = { + "video-pll", ccu_osc_name_to_be_filled, +}; + +static struct ccu_div axi_aclk = { + .parents = axi_parents, + .num_parents = ARRAY_SIZE(axi_parents), + .div = TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED), + .mux = TH_CCU_ARG(5, 1), + .common = { + .clkid = CLK_AXI_ACLK, + .cfg0 = 0x138, + .name = "axi-aclk", + }, +}; + +static const char *perisys_ahb_hclk_parents[] = { + "gmac-pll", ccu_osc_name_to_be_filled, +}; + +static struct ccu_div perisys_ahb_hclk = { + .parents = perisys_ahb_hclk_parents, + .num_parents = ARRAY_SIZE(perisys_ahb_hclk_parents), + .enable = BIT(6), + .div = TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED), + .mux = TH_CCU_ARG(5, 1), + .common = { + .clkid = CLK_PERI_AHB_HCLK, + .cfg0 = 0x140, + .name = "perisys-ahb-hclk", + }, +}; + +static const char *perisys_ahb_hclk_parent[] = { + "perisys-ahb-hclk", +}; + +static struct ccu_div perisys_apb_pclk = { + .parents = perisys_ahb_hclk_parent, + .num_parents = ARRAY_SIZE(perisys_ahb_hclk_parent), + .div = TH_CCU_ARG(0, 3), + .common = { + .clkid = CLK_PERI_APB_PCLK, + .cfg0 = 0x150, + .name = "perisys-apb-pclk", + }, +}; + +static struct ccu_div peri2sys_apb_pclk = { + .parents = gmac_pll_clk_parent, + .num_parents = ARRAY_SIZE(gmac_pll_clk_parent), + .div = TH_CCU_DIV_FLAGS(4, 3, CLK_DIVIDER_ONE_BASED), + .common = { + .clkid = CLK_PERI2APB_PCLK, + .cfg0 = 0x150, + .name = "peri2sys-apb-pclk", + }, +}; + +static const char *apb_parents[] = { + "gmac-pll", ccu_osc_name_to_be_filled, +}; + +static struct ccu_div apb_pclk = { + .parents = apb_parents, + .num_parents = ARRAY_SIZE(apb_parents), + .enable = BIT(5), + .div = TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED), + .mux = TH_CCU_ARG(7, 1), + .common = { + .clkid = CLK_APB_PCLK, + .cfg0 = 0x1c4, + .name = "apb-pclk", + }, +}; + +static const char *npu_parents[] = { + "gmac-pll", "video-pll", +}; + +static struct ccu_div npu_clk = { + .parents = npu_parents, + .num_parents = ARRAY_SIZE(npu_parents), + .enable = BIT(4), + .div = TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED), + .mux = TH_CCU_ARG(6, 1), + .common = { + .clkid = CLK_NPU, + .cfg0 = 0x1c8, + .name = "npu", + }, +}; + +static struct ccu_div vi_clk = { + .parents = video_pll_clk_parent, + .num_parents = ARRAY_SIZE(video_pll_clk_parent), + .div = TH_CCU_DIV_FLAGS(16, 4, CLK_DIVIDER_ONE_BASED), + .common = { + .clkid = CLK_VI, + .cfg0 = 0x1d0, + .name = "vi", + }, +}; + +static struct ccu_div vi_ahb_clk = { + .parents = video_pll_clk_parent, + .num_parents = ARRAY_SIZE(video_pll_clk_parent), + .div = TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED), + .common = { + .clkid = CLK_VI_AHB, + .cfg0 = 0x1d0, + .name = "vi-ahb", + }, +}; + +static struct ccu_div vo_axi_clk = { + .parents = video_pll_clk_parent, + .num_parents = ARRAY_SIZE(video_pll_clk_parent), + .enable = BIT(5), + .div = TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED), + .common = { + .clkid = CLK_VO_AXI, + .cfg0 = 0x1dc, + .name = "vo-axi", + }, +}; + +static struct ccu_div vp_apb_clk = { + .parents = gmac_pll_clk_parent, + .num_parents = ARRAY_SIZE(gmac_pll_clk_parent), + .div = TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED), + .common = { + .clkid = CLK_VP_APB, + .cfg0 = 0x1e0, + .name = "vp-apb", + }, +}; + +static struct ccu_div vp_axi_clk = { + .parents = video_pll_clk_parent, + .num_parents = ARRAY_SIZE(video_pll_clk_parent), + .enable = BIT(15), + .div = TH_CCU_DIV_FLAGS(8, 4, CLK_DIVIDER_ONE_BASED), + .common = { + .clkid = CLK_VP_AXI, + .cfg0 = 0x1e0, + .name = "vp-axi", + }, +}; + +static struct ccu_div venc_clk = { + .parents = gmac_pll_clk_parent, + .num_parents = ARRAY_SIZE(gmac_pll_clk_parent), + .enable = BIT(5), + .div = TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED), + .common = { + .clkid = CLK_VENC, + .cfg0 = 0x1e4, + .name = "venc", + }, +}; + +static struct ccu_div dpu0_clk = { + .parents = dpu0_pll_clk_parent, + .num_parents = ARRAY_SIZE(dpu0_pll_clk_parent), + .div = TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED), + .common = { + .clkid = CLK_DPU0, + .cfg0 = 0x1e8, + .name = "dpu0", + }, +}; + +static struct ccu_div dpu1_clk = { + .parents = dpu1_pll_clk_parent, + .num_parents = ARRAY_SIZE(dpu1_pll_clk_parent), + .div = TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED), + .common = { + .clkid = CLK_DPU1, + .cfg0 = 0x1ec, + .name = "dpu1", + }, +}; + +static CCU_GATE(CLK_BROM, brom_clk, "brom", "ahb2-cpusys-hclk", 0x100, BIT(4), 0); +static CCU_GATE(CLK_BMU, bmu_clk, "bmu", "axi4-cpusys2-aclk", 0x100, BIT(5), 0); +static CCU_GATE(CLK_AON2CPU_A2X, aon2cpu_a2x_clk, "aon2cpu-a2x", "axi4-cpusys2-aclk", + 0x134, BIT(8), 0); +static CCU_GATE(CLK_X2X_CPUSYS, x2x_cpusys_clk, "x2x-cpusys", "axi4-cpusys2-aclk", + 0x134, BIT(7), 0); +static CCU_GATE(CLK_CPU2AON_X2H, cpu2aon_x2h_clk, "cpu2aon-x2h", "axi-aclk", 0x138, BIT(8), 0); +static CCU_GATE(CLK_CPU2PERI_X2H, cpu2peri_x2h_clk, "cpu2peri-x2h", "axi4-cpusys2-aclk", + 0x140, BIT(9), CLK_IGNORE_UNUSED); +static CCU_GATE(CLK_PERISYS_APB1_HCLK, perisys_apb1_hclk, "perisys-apb1-hclk", "perisys-ahb-hclk", + 0x150, BIT(9), 0); +static CCU_GATE(CLK_PERISYS_APB2_HCLK, perisys_apb2_hclk, "perisys-apb2-hclk", "perisys-ahb-hclk", + 0x150, BIT(10), CLK_IGNORE_UNUSED); +static CCU_GATE(CLK_PERISYS_APB3_HCLK, perisys_apb3_hclk, "perisys-apb3-hclk", "perisys-ahb-hclk", + 0x150, BIT(11), CLK_IGNORE_UNUSED); +static CCU_GATE(CLK_PERISYS_APB4_HCLK, perisys_apb4_hclk, "perisys-apb4-hclk", "perisys-ahb-hclk", + 0x150, BIT(12), 0); +static CCU_GATE(CLK_NPU_AXI, npu_axi_clk, "npu-axi", "axi-aclk", 0x1c8, BIT(5), 0); +static CCU_GATE(CLK_CPU2VP, cpu2vp_clk, "cpu2vp", "axi-aclk", 0x1e0, BIT(13), 0); +static CCU_GATE(CLK_EMMC_SDIO, emmc_sdio_clk, "emmc-sdio", "emmc-sdio-ref", 0x204, BIT(30), 0); +static CCU_GATE(CLK_GMAC1, gmac1_clk, "gmac1", "gmac-pll", 0x204, BIT(26), 0); +static CCU_GATE(CLK_PADCTRL1, padctrl1_clk, "padctrl1", "perisys-apb-pclk", 0x204, BIT(24), 0); +static CCU_GATE(CLK_DSMART, dsmart_clk, "dsmart", "perisys-apb-pclk", 0x204, BIT(23), 0); +static CCU_GATE(CLK_PADCTRL0, padctrl0_clk, "padctrl0", "perisys-apb-pclk", 0x204, BIT(22), 0); +static CCU_GATE(CLK_GMAC_AXI, gmac_axi_clk, "gmac-axi", "axi4-cpusys2-aclk", 0x204, BIT(21), 0); +static CCU_GATE(CLK_GPIO3, gpio3_clk, "gpio3-clk", "peri2sys-apb-pclk", 0x204, BIT(20), 0); +static CCU_GATE(CLK_GMAC0, gmac0_clk, "gmac0", "gmac-pll", 0x204, BIT(19), 0); +static CCU_GATE(CLK_PWM, pwm_clk, "pwm", "perisys-apb-pclk", 0x204, BIT(18), 0); +static CCU_GATE(CLK_QSPI0, qspi0_clk, "qspi0", "video-pll", 0x204, BIT(17), 0); +static CCU_GATE(CLK_QSPI1, qspi1_clk, "qspi1", "video-pll", 0x204, BIT(16), 0); +static CCU_GATE(CLK_SPI, spi_clk, "spi", "video-pll", 0x204, BIT(15), 0); +static CCU_GATE(CLK_UART0_PCLK, uart0_pclk, "uart0-pclk", "perisys-apb-pclk", 0x204, BIT(14), 0); +static CCU_GATE(CLK_UART1_PCLK, uart1_pclk, "uart1-pclk", "perisys-apb-pclk", 0x204, BIT(13), 0); +static CCU_GATE(CLK_UART2_PCLK, uart2_pclk, "uart2-pclk", "perisys-apb-pclk", 0x204, BIT(12), 0); +static CCU_GATE(CLK_UART3_PCLK, uart3_pclk, "uart3-pclk", "perisys-apb-pclk", 0x204, BIT(11), 0); +static CCU_GATE(CLK_UART4_PCLK, uart4_pclk, "uart4-pclk", "perisys-apb-pclk", 0x204, BIT(10), 0); +static CCU_GATE(CLK_UART5_PCLK, uart5_pclk, "uart5-pclk", "perisys-apb-pclk", 0x204, BIT(9), 0); +static CCU_GATE(CLK_GPIO0, gpio0_clk, "gpio0-clk", "perisys-apb-pclk", 0x204, BIT(8), 0); +static CCU_GATE(CLK_GPIO1, gpio1_clk, "gpio1-clk", "perisys-apb-pclk", 0x204, BIT(7), 0); +static CCU_GATE(CLK_GPIO2, gpio2_clk, "gpio2-clk", "peri2sys-apb-pclk", 0x204, BIT(6), 0); +static CCU_GATE(CLK_I2C0, i2c0_clk, "i2c0", "perisys-apb-pclk", 0x204, BIT(5), 0); +static CCU_GATE(CLK_I2C1, i2c1_clk, "i2c1", "perisys-apb-pclk", 0x204, BIT(4), 0); +static CCU_GATE(CLK_I2C2, i2c2_clk, "i2c2", "perisys-apb-pclk", 0x204, BIT(3), 0); +static CCU_GATE(CLK_I2C3, i2c3_clk, "i2c3", "perisys-apb-pclk", 0x204, BIT(2), 0); +static CCU_GATE(CLK_I2C4, i2c4_clk, "i2c4", "perisys-apb-pclk", 0x204, BIT(1), 0); +static CCU_GATE(CLK_I2C5, i2c5_clk, "i2c5", "perisys-apb-pclk", 0x204, BIT(0), 0); +static CCU_GATE(CLK_SPINLOCK, spinlock_clk, "spinlock", "ahb2-cpusys-hclk", 0x208, BIT(10), 0); +static CCU_GATE(CLK_DMA, dma_clk, "dma", "axi4-cpusys2-aclk", 0x208, BIT(8), 0); +static CCU_GATE(CLK_MBOX0, mbox0_clk, "mbox0", "apb3-cpusys-pclk", 0x208, BIT(7), 0); +static CCU_GATE(CLK_MBOX1, mbox1_clk, "mbox1", "apb3-cpusys-pclk", 0x208, BIT(6), 0); +static CCU_GATE(CLK_MBOX2, mbox2_clk, "mbox2", "apb3-cpusys-pclk", 0x208, BIT(5), 0); +static CCU_GATE(CLK_MBOX3, mbox3_clk, "mbox3", "apb3-cpusys-pclk", 0x208, BIT(4), 0); +static CCU_GATE(CLK_WDT0, wdt0_clk, "wdt0", "apb3-cpusys-pclk", 0x208, BIT(3), 0); +static CCU_GATE(CLK_WDT1, wdt1_clk, "wdt1", "apb3-cpusys-pclk", 0x208, BIT(2), 0); +static CCU_GATE(CLK_TIMER0, timer0_clk, "timer0", "apb3-cpusys-pclk", 0x208, BIT(1), 0); +static CCU_GATE(CLK_TIMER1, timer1_clk, "timer1", "apb3-cpusys-pclk", 0x208, BIT(0), 0); +static CCU_GATE(CLK_SRAM0, sram0_clk, "sram0", "axi-aclk", 0x20c, BIT(4), 0); +static CCU_GATE(CLK_SRAM1, sram1_clk, "sram1", "axi-aclk", 0x20c, BIT(3), 0); +static CCU_GATE(CLK_SRAM2, sram2_clk, "sram2", "axi-aclk", 0x20c, BIT(2), 0); +static CCU_GATE(CLK_SRAM3, sram3_clk, "sram3", "axi-aclk", 0x20c, BIT(1), 0); + +static const char *uart_sclk_parents[] = { + "gmac-pll-clk-100m", ccu_osc_name_to_be_filled, +}; + +static struct ccu_mux uart_sclk = { + .parents = uart_sclk_parents, + .num_parents = ARRAY_SIZE(uart_sclk_parents), + .mux = TH_CCU_ARG(0, 1), + .common = { + .clkid = CLK_UART_SCLK, + .cfg0 = 0x210, + .name = "uart-sclk", + } +}; + +static struct ccu_common *th1520_pll_clks[] = { + &cpu_pll0_clk.common, + &cpu_pll1_clk.common, + &gmac_pll_clk.common, + &video_pll_clk.common, + &dpu0_pll_clk.common, + &dpu1_pll_clk.common, + &tee_pll_clk.common, +}; + +static struct ccu_common *th1520_div_clks[] = { + &ahb2_cpusys_hclk.common, + &apb3_cpusys_pclk.common, + &axi4_cpusys2_aclk.common, + &perisys_ahb_hclk.common, + &perisys_apb_pclk.common, + &axi_aclk.common, + &peri2sys_apb_pclk.common, + &apb_pclk.common, + &npu_clk.common, + &vi_clk.common, + &vi_ahb_clk.common, + &vo_axi_clk.common, + &vp_apb_clk.common, + &vp_axi_clk.common, + &venc_clk.common, + &dpu0_clk.common, + &dpu1_clk.common, +}; + +static struct ccu_common *th1520_mux_clks[] = { + &c910_i0_clk.common, + &c910_clk.common, + &uart_sclk.common, +}; + +static struct ccu_common *th1520_gate_clks[] = { + &emmc_sdio_clk.common, + &aon2cpu_a2x_clk.common, + &x2x_cpusys_clk.common, + &brom_clk.common, + &bmu_clk.common, + &cpu2aon_x2h_clk.common, + &cpu2peri_x2h_clk.common, + &cpu2vp_clk.common, + &perisys_apb1_hclk.common, + &perisys_apb2_hclk.common, + &perisys_apb3_hclk.common, + &perisys_apb4_hclk.common, + &npu_axi_clk.common, + &gmac1_clk.common, + &padctrl1_clk.common, + &dsmart_clk.common, + &padctrl0_clk.common, + &gmac_axi_clk.common, + &gpio3_clk.common, + &gmac0_clk.common, + &pwm_clk.common, + &qspi0_clk.common, + &qspi1_clk.common, + &spi_clk.common, + &uart0_pclk.common, + &uart1_pclk.common, + &uart2_pclk.common, + &uart3_pclk.common, + &uart4_pclk.common, + &uart5_pclk.common, + &gpio0_clk.common, + &gpio1_clk.common, + &gpio2_clk.common, + &i2c0_clk.common, + &i2c1_clk.common, + &i2c2_clk.common, + &i2c3_clk.common, + &i2c4_clk.common, + &i2c5_clk.common, + &spinlock_clk.common, + &dma_clk.common, + &mbox0_clk.common, + &mbox1_clk.common, + &mbox2_clk.common, + &mbox3_clk.common, + &wdt0_clk.common, + &wdt1_clk.common, + &timer0_clk.common, + &timer1_clk.common, + &sram0_clk.common, + &sram1_clk.common, + &sram2_clk.common, + &sram3_clk.common, +}; + +static void th1520_clk_fill_osc_name(const char **names, size_t name_num, + const char *osc_name) +{ + size_t i; + + for (i = 0; i < name_num; i++) { + if (names[i] == ccu_osc_name_to_be_filled) + names[i] = osc_name; + } +} + +static int th1520_clk_probe(struct udevice *dev) +{ + struct clk *clk, osc_clk; + const char *osc_name; + void __iomem *base; + fdt_addr_t addr; + int ret, i; + + addr = dev_read_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + base = (void __iomem *)addr; + + ret = clk_get_by_index(dev, 0, &osc_clk); + if (ret) { + pr_err("failed to get osc clock: %d\n", ret); + return ret; + } + + osc_name = clk_hw_get_name(&osc_clk); + + for (i = 0; i < ARRAY_SIZE(th1520_pll_clks); i++) { + struct ccu_common *common = th1520_pll_clks[i]; + + common->reg = base; + + ret = clk_register(&common->clk, "th1520_clk_pll", + common->name, osc_name); + if (ret) { + pr_err("failed to register PLL %s: %d\n", + common->name, ret); + return ret; + } + + common->clk.id = common->clkid; + } + + for (i = 0; i < ARRAY_SIZE(th1520_div_clks); i++) { + struct ccu_div *cd = container_of(th1520_div_clks[i], + struct ccu_div, common); + const char *current_parent; + + cd->common.reg = base; + th1520_clk_fill_osc_name(cd->parents, cd->num_parents, + osc_name); + + if (cd->num_parents > 1) + current_parent = cd->parents[ccu_div_get_parent(cd)]; + else + current_parent = cd->parents[0]; + + ret = clk_register(&cd->common.clk, "th1520_clk_div", + cd->common.name, + current_parent); + + if (ret) { + pr_err("failed to register div clock %s: %d\n", + cd->common.name, ret); + return ret; + } + + cd->common.clk.id = cd->common.clkid; + } + + clk = clk_register_fixed_factor(dev, "gmac-pll-clk-100m", "gmac-pll", + 0, 1, 10); + if (IS_ERR(clk)) { + pr_err("failed to register gmac-pll-clk-100m: %d\n", + (int)PTR_ERR(clk)); + return PTR_ERR(clk); + } + clk->id = CLK_PLL_GMAC_100M; + + clk = clk_register_fixed_factor(dev, "emmc-sdio-ref", "video-pll", + 0, 1, 4); + if (IS_ERR(clk)) { + pr_err("failed to register emmc-sdio-ref: %d\n", + (int)PTR_ERR(clk)); + return PTR_ERR(clk); + } + + for (i = 0; i < ARRAY_SIZE(th1520_mux_clks); i++) { + struct ccu_mux *cm = container_of(th1520_mux_clks[i], + struct ccu_mux, common); + + th1520_clk_fill_osc_name(cm->parents, cm->num_parents, + osc_name); + + clk = clk_register_mux(dev, cm->common.name, + cm->parents, cm->num_parents, + 0, + base + cm->common.cfg0, + cm->mux.shift, cm->mux.width, + 0); + if (IS_ERR(clk)) { + pr_err("failed to register mux clock %s: %d\n", + cm->common.name, (int)PTR_ERR(clk)); + return PTR_ERR(clk); + } + + clk->id = cm->common.clkid; + } + + for (i = 0; i < ARRAY_SIZE(th1520_gate_clks); i++) { + struct ccu_gate *cg = container_of(th1520_gate_clks[i], + struct ccu_gate, common); + + th1520_clk_fill_osc_name(&cg->parent, 1, osc_name); + + clk = clk_register_gate(dev, cg->common.name, + cg->parent, + 0, + base + cg->common.cfg0, + ffs(cg->enable) - 1, 0, NULL); + if (IS_ERR(clk)) { + pr_err("failed to register gate clock %s: %d\n", + cg->common.name, (int)PTR_ERR(clk)); + return PTR_ERR(clk); + } + + clk->id = cg->common.clkid; + } + + return 0; +} + +static const struct udevice_id th1520_clk_match[] = { + { + .compatible = "thead,th1520-clk-ap", + }, + { /* sentinel */ }, +}; + +static int th1520_clk_enable(struct clk *clk) +{ + struct clk *c; + int ret; + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + return clk_enable(c); +} + +static int th1520_clk_disable(struct clk *clk) +{ + struct clk *c; + int ret; + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + return clk_disable(c); +} + +static ulong th1520_clk_get_rate(struct clk *clk) +{ + struct clk *c; + int ret; + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + return clk_get_rate(c); +} + +static ulong th1520_clk_set_rate(struct clk *clk, ulong rate) +{ + struct clk *c; + int ret; + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + return clk_set_rate(c, rate); +} + +static int th1520_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk *c, *p; + int ret; + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + ret = clk_get_by_id(parent->id, &p); + if (ret) + return ret; + + return clk_set_parent(c, p); +} + +static const struct clk_ops th1520_clk_ops = { + .enable = th1520_clk_enable, + .disable = th1520_clk_disable, + .get_rate = th1520_clk_get_rate, + .set_rate = th1520_clk_set_rate, + .set_parent = th1520_clk_set_parent, +}; + +U_BOOT_DRIVER(th1520_clk) = { + .name = "th1520-clk", + .id = UCLASS_CLK, + .of_match = th1520_clk_match, + .probe = th1520_clk_probe, + .ops = &th1520_clk_ops, +}; diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c index 8f7a821ebf3..1d95d2bff27 100644 --- a/drivers/crypto/fsl/jr.c +++ b/drivers/crypto/fsl/jr.c @@ -217,13 +217,6 @@ static int jr_enqueue(uint32_t *desc_addr, jr->head = (head + 1) & (jr->size - 1); - /* Invalidate output ring */ - start = (unsigned long)jr->output_ring & - ~(ARCH_DMA_MINALIGN - 1); - end = ALIGN((unsigned long)jr->output_ring + jr->op_size, - ARCH_DMA_MINALIGN); - invalidate_dcache_range(start, end); - sec_out32(®s->irja, 1); return 0; @@ -243,6 +236,7 @@ static int jr_dequeue(int sec_idx, struct caam_regs *caam) #else uint32_t *addr; #endif + unsigned long start, end; while (sec_in32(®s->orsf) && CIRC_CNT(jr->head, jr->tail, jr->size)) { @@ -250,6 +244,11 @@ static int jr_dequeue(int sec_idx, struct caam_regs *caam) found = 0; caam_dma_addr_t op_desc; + + /* Invalidate output ring */ + start = (unsigned long)jr->output_ring & ~(ARCH_DMA_MINALIGN - 1); + end = ALIGN((unsigned long)jr->output_ring + jr->op_size, ARCH_DMA_MINALIGN); + invalidate_dcache_range(start, end); #ifdef CONFIG_CAAM_64BIT /* Read the 64 bit Descriptor address from Output Ring. * The 32 bit hign and low part of the address will @@ -283,8 +282,13 @@ static int jr_dequeue(int sec_idx, struct caam_regs *caam) } /* Error condition if match not found */ - if (!found) + if (!found) { + int slots_full = sec_in32(®s->orsf); + + jr->tail = (jr->tail + slots_full) & (jr->size - 1); + sec_out32(®s->orjr, slots_full); return -1; + } jr->info[idx].op_done = 1; callback = (void *)jr->info[idx].callback; @@ -296,14 +300,14 @@ static int jr_dequeue(int sec_idx, struct caam_regs *caam) */ if (idx == tail) do { + jr->info[tail].op_done = 0; tail = (tail + 1) & (jr->size - 1); } while (jr->info[tail].op_done); jr->tail = tail; - jr->read_idx = (jr->read_idx + 1) & (jr->size - 1); + sec_out32(®s->orjr, 1); - jr->info[idx].op_done = 0; callback(status, arg); } @@ -378,7 +382,6 @@ static int jr_sw_cleanup(uint8_t sec_idx, struct caam_regs *caam) jr->head = 0; jr->tail = 0; - jr->read_idx = 0; jr->write_idx = 0; memset(jr->info, 0, sizeof(jr->info)); memset(jr->input_ring, 0, jr->size * sizeof(caam_dma_addr_t)); diff --git a/drivers/crypto/fsl/jr.h b/drivers/crypto/fsl/jr.h index b136cd8d05a..8d5ca03e501 100644 --- a/drivers/crypto/fsl/jr.h +++ b/drivers/crypto/fsl/jr.h @@ -83,10 +83,6 @@ struct jobring { * in-order job completion */ int tail; - /* Read index of the output ring. It may not match with tail in case - * of out of order completetion - */ - int read_idx; /* Write index to input ring. Would be always equal to head */ int write_idx; /* Size of the rings. */ diff --git a/drivers/mmc/cv1800b_sdhci.c b/drivers/mmc/cv1800b_sdhci.c index 4e75051c317..377e6a887df 100644 --- a/drivers/mmc/cv1800b_sdhci.c +++ b/drivers/mmc/cv1800b_sdhci.c @@ -31,6 +31,7 @@ static void cv1800b_sdhci_reset(struct sdhci_host *host, u8 mask) udelay(10); } +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) static int cv1800b_execute_tuning(struct mmc *mmc, u8 opcode) { struct sdhci_host *host = dev_get_priv(mmc->dev); @@ -61,9 +62,12 @@ static int cv1800b_execute_tuning(struct mmc *mmc, u8 opcode) return 0; } +#endif const struct sdhci_ops cv1800b_sdhci_sd_ops = { +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) .platform_execute_tuning = cv1800b_execute_tuning, +#endif }; static int cv1800b_sdhci_bind(struct udevice *dev) diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c index 52fa820f518..97cccda4519 100644 --- a/drivers/net/fsl_enetc.c +++ b/drivers/net/fsl_enetc.c @@ -473,13 +473,15 @@ static int enetc_init_sxgmii(struct udevice *dev) /* Apply protocol specific configuration to MAC, serdes as needed */ static void enetc_start_pcs(struct udevice *dev) { + struct enetc_data *data = (struct enetc_data *)dev_get_driver_data(dev); struct enetc_priv *priv = dev_get_priv(dev); /* register internal MDIO for debug purposes */ if (enetc_read_pcapr_mdio(dev)) { priv->imdio.read = enetc_mdio_read; priv->imdio.write = enetc_mdio_write; - priv->imdio.priv = priv->port_regs + ENETC_PM_IMDIO_BASE; + priv->imdio.priv = priv->port_regs + data->reg_offset_mac + + ENETC_PM_IMDIO_BASE; strlcpy(priv->imdio.name, dev->name, MDIO_NAME_LEN); if (!miiphy_get_dev_by_name(priv->imdio.name)) mdio_register(&priv->imdio); diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig index 2a40b0c9f81..39d03e8d3d3 100644 --- a/drivers/ram/Kconfig +++ b/drivers/ram/Kconfig @@ -135,3 +135,4 @@ source "drivers/ram/sifive/Kconfig" source "drivers/ram/stm32mp1/Kconfig" source "drivers/ram/starfive/Kconfig" source "drivers/ram/sunxi/Kconfig" +source "drivers/ram/thead/Kconfig" diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile index f92e86eaa3f..82afd5fcbcc 100644 --- a/drivers/ram/Makefile +++ b/drivers/ram/Makefile @@ -30,3 +30,7 @@ obj-$(CONFIG_ARCH_OCTEON) += octeon/ obj-$(CONFIG_ARCH_RENESAS) += renesas/ obj-$(CONFIG_CADENCE_DDR_CTRL) += cadence/ + +ifdef CONFIG_XPL_BUILD +obj-$(CONFIG_SPL_THEAD_TH1520_DDR) += thead/ +endif diff --git a/drivers/ram/thead/Kconfig b/drivers/ram/thead/Kconfig new file mode 100644 index 00000000000..7b05abb6986 --- /dev/null +++ b/drivers/ram/thead/Kconfig @@ -0,0 +1,5 @@ +config SPL_THEAD_TH1520_DDR + bool "T-Head TH1520 DDR driver in SPL" + depends on SPL_RAM && THEAD_TH1520 + help + This enables DDR support for T-Head TH1520 platforms. diff --git a/drivers/ram/thead/Makefile b/drivers/ram/thead/Makefile new file mode 100644 index 00000000000..ad4d053cfc2 --- /dev/null +++ b/drivers/ram/thead/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_SPL_THEAD_TH1520_DDR) += th1520_ddr.o diff --git a/drivers/ram/thead/th1520_ddr.c b/drivers/ram/thead/th1520_ddr.c new file mode 100644 index 00000000000..bb4736b0236 --- /dev/null +++ b/drivers/ram/thead/th1520_ddr.c @@ -0,0 +1,787 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * Copyright (C) 2025 Yao Zi <ziyao@disroot.org> + */ + +#include <binman.h> +#include <binman_sym.h> +#include <dm.h> +#include <init.h> +#include <linux/bitfield.h> +#include <linux/iopoll.h> +#include <ram.h> + +DECLARE_GLOBAL_DATA_PTR; + +#pragma pack(push, 1) + +struct th1520_ddr_fw { + u64 magic; + u8 type, ranknum, bitwidth, freq; + u8 reserved[8]; + + u32 cfgnum; + union th1520_ddr_cfg { + u32 opaddr; + + struct th1520_ddr_phy { + u32 opaddr; + u16 data; + } phy; + + struct th1520_ddr_range { + u32 opaddr; + u32 num; + u16 data[]; + } range; + } cfgs[]; +}; + +#pragma pack(pop) + +/* Firmware constants */ +#define TH1520_DDR_MAGIC 0x4452444445415448 + +#define TH1520_DDR_TYPE_LPDDR4 0 +#define TH1520_DDR_TYPE_LPDDR4X 1 + +#define TH1520_DDR_FREQ_2133 0 +#define TH1520_DDR_FREQ_3200 1 +#define TH1520_DDR_FREQ_3733 2 +#define TH1520_DDR_FREQ_4266 3 + +#define TH1520_DDR_CFG_OP GENMASK(31, 24) +#define TH1520_DDR_CFG_ADDR GENMASK(23, 0) + +#define TH1520_DDR_CFG_PHY0 0 +#define TH1520_DDR_CFG_PHY1 1 +#define TH1520_DDR_CFG_PHY 2 +#define TH1520_DDR_CFG_RANGE 3 +#define TH1520_DDR_CFG_WAITFW0 4 +#define TH1520_DDR_CFG_WAITFW1 5 + +/* Driver constants */ +#define TH1520_SYS_PLL_TIMEOUT_US 30 +#define TH1520_CTRL_INIT_TIMEOUT_US 1000000 +#define TH1520_PHY_MSG_TIMEOUT_US 1000000 + +/* System configuration registers */ +#define TH1520_SYS_DDR_CFG0 0x00 +#define TH1520_SYS_DDR_CFG0_APB_RSTN BIT(4) +#define TH1520_SYS_DDR_CFG0_CTRL_RSTN BIT(5) +#define TH1520_SYS_DDR_CFG0_PHY_PWROK_RSTN BIT(6) +#define TH1520_SYS_DDR_CFG0_PHY_CORE_RSTN BIT(7) +#define TH1520_SYS_DDR_CFG0_APB_PORT_RSTN(n) BIT(n + 4 + 4) +#define TH1520_SYS_DDR_CFG1 0x04 +#define TH1520_SYS_PLL_CFG0 0x08 +#define TH1520_SYS_PLL_CFG0_POSTDIV2 GENMASK(26, 24) +#define TH1520_SYS_PLL_CFG0_POSTDIV1 GENMASK(22, 20) +#define TH1520_SYS_PLL_CFG0_FBDIV GENMASK(19, 8) +#define TH1520_SYS_PLL_CFG0_REFDIV GENMASK(5, 0) +#define TH1520_SYS_PLL_CFG1 0x0c +#define TH1520_SYS_PLL_CFG1_RST BIT(30) +#define TH1520_SYS_PLL_CFG1_FOUTPOSTDIVPD BIT(27) +#define TH1520_SYS_PLL_CFG1_FOUT4PHASEPD BIT(25) +#define Th1520_SYS_PLL_CFG1_DACPD BIT(24) +#define TH1520_SYS_PLL_CFG2 0x10 +#define TH1520_SYS_PLL_CFG3 0x14 +#define TH1520_SYS_PLL_STS 0x18 +#define TH1520_SYS_PLL_STS_EN BIT(16) +#define TH1520_SYS_PLL_STS_LOCKED BIT(0) + +/* DDR Controller Registers */ +#define TH1520_CTRL_MSTR 0x0000 +#define TH1520_CTRL_STAT 0x0004 +#define TH1520_CTRL_MRCTRL0 0x0010 +#define TH1520_CTRL_MRCTRL1 0x0014 +#define TH1520_CTRL_MRSTAT 0x0018 +#define TH1520_CTRL_DERATEEN 0x0020 +#define TH1520_CTRL_DERATEINT 0x0024 +#define TH1520_CTRL_DERATECTL 0x002c +#define TH1520_CTRL_PWRCTL 0x0030 +#define TH1520_CTRL_PWRTMG 0x0034 +#define TH1520_CTRL_HWLPCTL 0x0038 +#define TH1520_CTRL_RFSHCTL0 0x0050 +#define TH1520_CTRL_RFSHCTL1 0x0054 +#define TH1520_CTRL_RFSHCTL3 0x0060 +#define TH1520_CTRL_RFSHTMG 0x0064 +#define TH1520_CTRL_RFSHTMG1 0x0068 +#define TH1520_CTRL_CRCPARCTL0 0x00c0 +#define TH1520_CTRL_CRCPARSTAT 0x00cc +#define TH1520_CTRL_INIT0 0x00d0 +#define TH1520_CTRL_INIT1 0x00d4 +#define TH1520_CTRL_INIT2 0x00d8 +#define TH1520_CTRL_INIT3 0x00dc +#define TH1520_CTRL_INIT4 0x00e0 +#define TH1520_CTRL_INIT5 0x00e4 +#define TH1520_CTRL_INIT6 0x00e8 +#define TH1520_CTRL_INIT7 0x00ec +#define TH1520_CTRL_DIMMCTL 0x00f0 +#define TH1520_CTRL_RANKCTL 0x00f4 +#define TH1520_CTRL_RANKCTL1 0x00f8 +#define TH1520_CTRL_DRAMTMG0 0x0100 +#define TH1520_CTRL_DRAMTMG1 0x0104 +#define TH1520_CTRL_DRAMTMG2 0x0108 +#define TH1520_CTRL_DRAMTMG3 0x010c +#define TH1520_CTRL_DRAMTMG4 0x0110 +#define TH1520_CTRL_DRAMTMG5 0x0114 +#define TH1520_CTRL_DRAMTMG6 0x0118 +#define TH1520_CTRL_DRAMTMG7 0x011c +#define TH1520_CTRL_DRAMTMG8 0x0120 +#define TH1520_CTRL_DRAMTMG12 0x0130 +#define TH1520_CTRL_DRAMTMG13 0x0134 +#define TH1520_CTRL_DRAMTMG14 0x0138 +#define TH1520_CTRL_DRAMTMG17 0x0144 +#define TH1520_CTRL_ZQCTL0 0x0180 +#define TH1520_CTRL_ZQCTL1 0x0184 +#define TH1520_CTRL_ZQCTL2 0x0188 +#define TH1520_CTRL_ZQSTAT 0x018c +#define TH1520_CTRL_DFITMG0 0x0190 +#define TH1520_CTRL_DFITMG1 0x0194 +#define TH1520_CTRL_DFILPCFG0 0x0198 +#define TH1520_CTRL_DFIUPD0 0x01a0 +#define TH1520_CTRL_DFIUPD1 0x01a4 +#define TH1520_CTRL_DFIUPD2 0x01a8 +#define TH1520_CTRL_DFIMISC 0x01b0 +#define TH1520_CTRL_DFITMG2 0x01b4 +#define TH1520_CTRL_DFISTAT 0x01bc +#define TH1520_CTRL_DBICTL 0x01c0 +#define TH1520_CTRL_DFIPHYMSTR 0x01c4 +#define TH1520_CTRL_ADDRMAP0 0x0200 +#define TH1520_CTRL_ADDRMAP1 0x0204 +#define TH1520_CTRL_ADDRMAP2 0x0208 +#define TH1520_CTRL_ADDRMAP3 0x020c +#define TH1520_CTRL_ADDRMAP4 0x0210 +#define TH1520_CTRL_ADDRMAP5 0x0214 +#define TH1520_CTRL_ADDRMAP6 0x0218 +#define TH1520_CTRL_ADDRMAP7 0x021c +#define TH1520_CTRL_ADDRMAP8 0x0220 +#define TH1520_CTRL_ADDRMAP9 0x0224 +#define TH1520_CTRL_ADDRMAP10 0x0228 +#define TH1520_CTRL_ADDRMAP11 0x022c +#define TH1520_CTRL_ODTCFG 0x0240 +#define TH1520_CTRL_ODTMAP 0x0244 +#define TH1520_CTRL_SCHED 0x0250 +#define TH1520_CTRL_SCHED1 0x0254 +#define TH1520_CTRL_PERFHPR1 0x025c +#define TH1520_CTRL_PERFLPR1 0x0264 +#define TH1520_CTRL_PERFWR1 0x026c +#define TH1520_CTRL_SCHED3 0x0270 +#define TH1520_CTRL_SCHED4 0x0274 +#define TH1520_CTRL_DBG0 0x0300 +#define TH1520_CTRL_DBG1 0x0304 +#define TH1520_CTRL_DBGCAM 0x0308 +#define TH1520_CTRL_DBGCMD 0x030c +#define TH1520_CTRL_DBGSTAT 0x0310 +#define TH1520_CTRL_SWCTL 0x0320 +#define TH1520_CTRL_SWSTAT 0x0324 +#define TH1520_CTRL_SWCTLSTATIC 0x0328 +#define TH1520_CTRL_POISONCFG 0x036c +#define TH1520_CTRL_POISONSTAT 0x0370 +#define TH1520_CTRL_DERATESTAT 0x03f0 +#define TH1520_CTRL_PSTAT 0x03fc +#define TH1520_CTRL_PCCFG 0x0400 +#define TH1520_CTRL_PCFGR_0 0x0404 +#define TH1520_CTRL_PCFGW_0 0x0408 +#define TH1520_CTRL_PCTRL_0 0x0490 +#define TH1520_CTRL_PCFGQOS0_0 0x0494 +#define TH1520_CTRL_PCFGQOS1_0 0x0498 +#define TH1520_CTRL_PCFGWQOS0_0 0x049c +#define TH1520_CTRL_PCFGWQOS1_0 0x04a0 +#define TH1520_CTRL_PCFGR_1 0x04b4 +#define TH1520_CTRL_PCFGW_1 0x04b8 +#define TH1520_CTRL_PCTRL_1 0x0540 +#define TH1520_CTRL_PCFGQOS0_1 0x0544 +#define TH1520_CTRL_PCFGQOS1_1 0x0548 +#define TH1520_CTRL_PCFGWQOS0_1 0x054c +#define TH1520_CTRL_PCFGWQOS1_1 0x0550 +#define TH1520_CTRL_PCFGR_2 0x0564 +#define TH1520_CTRL_PCFGW_2 0x0568 +#define TH1520_CTRL_PCTRL_2 0x05f0 +#define TH1520_CTRL_PCFGQOS0_2 0x05f4 +#define TH1520_CTRL_PCFGQOS1_2 0x05f8 +#define TH1520_CTRL_PCFGWQOS0_2 0x05fc +#define TH1520_CTRL_PCFGWQOS1_2 0x0600 +#define TH1520_CTRL_PCFGR_3 0x0614 +#define TH1520_CTRL_PCFGW_3 0x0618 +#define TH1520_CTRL_PCTRL_3 0x06a0 +#define TH1520_CTRL_PCFGQOS0_3 0x06a4 +#define TH1520_CTRL_PCFGQOS1_3 0x06a8 +#define TH1520_CTRL_PCFGWQOS0_3 0x06ac +#define TH1520_CTRL_PCFGWQOS1_3 0x06b0 +#define TH1520_CTRL_PCFGR_4 0x06c4 +#define TH1520_CTRL_PCFGW_4 0x06c8 +#define TH1520_CTRL_PCTRL_4 0x0750 +#define TH1520_CTRL_PCFGQOS0_4 0x0754 +#define TH1520_CTRL_PCFGQOS1_4 0x0758 +#define TH1520_CTRL_PCFGWQOS0_4 0x075c +#define TH1520_CTRL_PCFGWQOS1_4 0x0760 +#define TH1520_CTRL_UMCTL2_VER_NUMBER 0x0ff0 +#define TH1520_CTRL_UMCTL2_VER_TYPE 0x0ff4 +#define TH1520_CTRL_DCH1_STAT 0x1b04 +#define TH1520_CTRL_DCH1_MRCTRL0 0x1b10 +#define TH1520_CTRL_DCH1_MRCTRL1 0x1b14 +#define TH1520_CTRL_DCH1_MRSTAT 0x1b18 +#define TH1520_CTRL_DCH1_DERATECTL 0x1b2c +#define TH1520_CTRL_DCH1_PWRCTL 0x1b30 +#define TH1520_CTRL_DCH1_HWLPCTL 0x1b38 +#define TH1520_CTRL_DCH1_CRCPARCTL0 0x1bc0 +#define TH1520_CTRL_DCH1_ZQCTL2 0x1c88 +#define TH1520_CTRL_DCH1_DFISTAT 0x1cbc +#define TH1520_CTRL_DCH1_ODTMAP 0x1d44 +#define TH1520_CTRL_DCH1_DBG1 0x1e04 +#define TH1520_CTRL_DCH1_DBGCMD 0x1e0c +#define TH1520_CTRL_DCH1_DBGCAM 0x1e08 + +/* PHY configuration registers */ +#define TH1520_DDR_PHY_REG(regid) ((regid) * 2) + +/* UctShadowRegs */ +#define TH1520_PHY_MSG_STATUS TH1520_DDR_PHY_REG(0xd0004) +#define TH1520_PHY_MSG_STATUS_EMPTY BIT(0) +/* DctWriteProt */ +#define TH1520_PHY_MSG_ACK TH1520_DDR_PHY_REG(0xd0031) +#define TH1520_PHY_MSG_ACK_EN BIT(0) +/* UctWriteOnlyShadow */ +#define TH1520_PHY_MSG_ID TH1520_DDR_PHY_REG(0xd0032) +#define TH1520_PHY_MSG_ID_COMPLETION 0x7 +#define TH1520_PHY_MSG_ID_ERROR 0xff +/* UctDatWriteOnlyShadow */ +#define TH1520_PHY_MSG_DATA TH1520_DDR_PHY_REG(0xd0034) + +struct th1520_ddr_priv { + void __iomem *phy0; + void __iomem *phy1; + void __iomem *ctrl; + void __iomem *sys; +}; + +binman_sym_declare(ulong, ddr_fw, image_pos); + +static int th1520_ddr_pll_config(void __iomem *sysreg, unsigned int frequency) +{ + u32 tmp; + int ret; + + tmp = TH1520_SYS_PLL_CFG1_RST | + TH1520_SYS_PLL_CFG1_FOUTPOSTDIVPD | + TH1520_SYS_PLL_CFG1_FOUT4PHASEPD | + Th1520_SYS_PLL_CFG1_DACPD; + writel(tmp, sysreg + TH1520_SYS_PLL_CFG1); + + switch (frequency) { + case TH1520_DDR_FREQ_3733: + writel(FIELD_PREP(TH1520_SYS_PLL_CFG0_REFDIV, 1) | + FIELD_PREP(TH1520_SYS_PLL_CFG0_FBDIV, 77) | + FIELD_PREP(TH1520_SYS_PLL_CFG0_POSTDIV1, 2) | + FIELD_PREP(TH1520_SYS_PLL_CFG0_POSTDIV2, 1), + sysreg + TH1520_SYS_PLL_CFG0); + break; + default: + return -EINVAL; + } + + udelay(2); + tmp &= ~TH1520_SYS_PLL_CFG1_RST; + writel(tmp, sysreg + TH1520_SYS_PLL_CFG1); + + ret = readl_poll_timeout(sysreg + TH1520_SYS_PLL_STS, tmp, + tmp & TH1520_SYS_PLL_STS_LOCKED, + TH1520_SYS_PLL_TIMEOUT_US); + + writel(TH1520_SYS_PLL_STS_EN, sysreg + TH1520_SYS_PLL_STS); + + return ret; +} + +static int th1520_ddr_ctrl_init(void __iomem *ctrlreg, struct th1520_ddr_fw *fw) +{ + int ret; + u32 tmp; + + writel(0x00000001, ctrlreg + TH1520_CTRL_DBG1); + writel(0x00000001, ctrlreg + TH1520_CTRL_PWRCTL); + + ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_STAT, tmp, + tmp == 0x00000000, + TH1520_CTRL_INIT_TIMEOUT_US); + if (ret) + return ret; + + if (fw->ranknum == 2) + writel(0x03080020, ctrlreg + TH1520_CTRL_MSTR); + else + return -EINVAL; + + writel(0x00003030, ctrlreg + TH1520_CTRL_MRCTRL0); + writel(0x0002d90f, ctrlreg + TH1520_CTRL_MRCTRL1); + + switch (fw->freq) { + case TH1520_DDR_FREQ_3733: + writel(0x000013f3, ctrlreg + TH1520_CTRL_DERATEEN); + writel(0x40000000, ctrlreg + TH1520_CTRL_DERATEINT); + writel(0x00000001, ctrlreg + TH1520_CTRL_DERATECTL); + writel(0x00000020, ctrlreg + TH1520_CTRL_PWRCTL); + writel(0x0040ae04, ctrlreg + TH1520_CTRL_PWRTMG); + writel(0x00430000, ctrlreg + TH1520_CTRL_HWLPCTL); + writel(0x00210004, ctrlreg + TH1520_CTRL_RFSHCTL0); + writel(0x000d0021, ctrlreg + TH1520_CTRL_RFSHCTL1); + writel(0x00000001, ctrlreg + TH1520_CTRL_RFSHCTL3); + writel(0x81c00084, ctrlreg + TH1520_CTRL_RFSHTMG); + writel(0x00540000, ctrlreg + TH1520_CTRL_RFSHTMG1); + writel(0x00000000, ctrlreg + TH1520_CTRL_CRCPARCTL0); + writel(0xc0020002, ctrlreg + TH1520_CTRL_INIT0); + writel(0x00010002, ctrlreg + TH1520_CTRL_INIT1); + writel(0x00001f00, ctrlreg + TH1520_CTRL_INIT2); + writel(0x00640036, ctrlreg + TH1520_CTRL_INIT3); + writel(0x00f20008, ctrlreg + TH1520_CTRL_INIT4); + writel(0x0004000b, ctrlreg + TH1520_CTRL_INIT5); + writel(0x00440012, ctrlreg + TH1520_CTRL_INIT6); + writel(0x0004001a, ctrlreg + TH1520_CTRL_INIT7); + writel(0x00000000, ctrlreg + TH1520_CTRL_DIMMCTL); + writel(0x0000ab9f, ctrlreg + TH1520_CTRL_RANKCTL); + writel(0x00000017, ctrlreg + TH1520_CTRL_RANKCTL1); + writel(0x1f263f28, ctrlreg + TH1520_CTRL_DRAMTMG0); + writel(0x00080839, ctrlreg + TH1520_CTRL_DRAMTMG1); + writel(0x08121d17, ctrlreg + TH1520_CTRL_DRAMTMG2); + writel(0x00d0e000, ctrlreg + TH1520_CTRL_DRAMTMG3); + writel(0x11040a12, ctrlreg + TH1520_CTRL_DRAMTMG4); + writel(0x02050e0e, ctrlreg + TH1520_CTRL_DRAMTMG5); + writel(0x01010008, ctrlreg + TH1520_CTRL_DRAMTMG6); + writel(0x00000502, ctrlreg + TH1520_CTRL_DRAMTMG7); + writel(0x00000101, ctrlreg + TH1520_CTRL_DRAMTMG8); + writel(0x00020000, ctrlreg + TH1520_CTRL_DRAMTMG12); + writel(0x0d100002, ctrlreg + TH1520_CTRL_DRAMTMG13); + writel(0x0000010c, ctrlreg + TH1520_CTRL_DRAMTMG14); + writel(0x03a50021, ctrlreg + TH1520_CTRL_ZQCTL0); + writel(0x02f00800, ctrlreg + TH1520_CTRL_ZQCTL1); + writel(0x00000000, ctrlreg + TH1520_CTRL_ZQCTL2); + writel(0x059f820c, ctrlreg + TH1520_CTRL_DFITMG0); + writel(0x000c0303, ctrlreg + TH1520_CTRL_DFITMG1); + writel(0x0351a101, ctrlreg + TH1520_CTRL_DFILPCFG0); + writel(0x00000011, ctrlreg + TH1520_CTRL_DFIMISC); + writel(0x00001f0c, ctrlreg + TH1520_CTRL_DFITMG2); + writel(0x00000007, ctrlreg + TH1520_CTRL_DBICTL); + writel(0x14000001, ctrlreg + TH1520_CTRL_DFIPHYMSTR); + writel(0x06090b40, ctrlreg + TH1520_CTRL_ODTCFG); + break; + default: + return -EINVAL; + } + + writel(0x00400018, ctrlreg + TH1520_CTRL_DFIUPD0); + writel(0x00280032, ctrlreg + TH1520_CTRL_DFIUPD1); + writel(0x00000000, ctrlreg + TH1520_CTRL_DFIUPD2); + writel(0x00000000, ctrlreg + TH1520_CTRL_ODTMAP); + writel(0x1f829b1c, ctrlreg + TH1520_CTRL_SCHED); + writel(0x4400b00f, ctrlreg + TH1520_CTRL_SCHED1); + writel(0x0f000001, ctrlreg + TH1520_CTRL_PERFHPR1); + writel(0x0f00007f, ctrlreg + TH1520_CTRL_PERFLPR1); + writel(0x0f00007f, ctrlreg + TH1520_CTRL_PERFWR1); + writel(0x00000208, ctrlreg + TH1520_CTRL_SCHED3); + writel(0x08400810, ctrlreg + TH1520_CTRL_SCHED4); + writel(0x00000000, ctrlreg + TH1520_CTRL_DBG0); + writel(0x00000000, ctrlreg + TH1520_CTRL_DBG1); + writel(0x00000000, ctrlreg + TH1520_CTRL_DBGCMD); + writel(0x00000001, ctrlreg + TH1520_CTRL_SWCTL); + writel(0x00000000, ctrlreg + TH1520_CTRL_SWCTLSTATIC); + writel(0x00000001, ctrlreg + TH1520_CTRL_POISONCFG); + writel(0x00000001, ctrlreg + TH1520_CTRL_PCTRL_0); + writel(0x00000001, ctrlreg + TH1520_CTRL_PCTRL_1); + writel(0x00000001, ctrlreg + TH1520_CTRL_PCTRL_2); + writel(0x00000001, ctrlreg + TH1520_CTRL_PCTRL_3); + writel(0x00000001, ctrlreg + TH1520_CTRL_PCTRL_4); + writel(0x00003030, ctrlreg + TH1520_CTRL_DCH1_MRCTRL0); + writel(0x0002d90f, ctrlreg + TH1520_CTRL_DCH1_MRCTRL1); + writel(0x00000001, ctrlreg + TH1520_CTRL_DCH1_DERATECTL); + writel(0x00000020, ctrlreg + TH1520_CTRL_DCH1_PWRCTL); + writel(0x00430002, ctrlreg + TH1520_CTRL_DCH1_HWLPCTL); + writel(0x00000000, ctrlreg + TH1520_CTRL_DCH1_CRCPARCTL0); + writel(0x00000000, ctrlreg + TH1520_CTRL_DCH1_ZQCTL2); + writel(0x00000000, ctrlreg + TH1520_CTRL_DCH1_ODTMAP); + writel(0x00000000, ctrlreg + TH1520_CTRL_DCH1_DBG1); + writel(0x00000000, ctrlreg + TH1520_CTRL_DCH1_DBGCMD); + + ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_RFSHCTL3, tmp, + tmp == 0x00000001, + TH1520_CTRL_INIT_TIMEOUT_US); + if (ret) + return ret; + + writel(0x00000010, ctrlreg + TH1520_CTRL_PCCFG); + writel(0x0000500f, ctrlreg + TH1520_CTRL_PCFGR_0); + writel(0x0000500f, ctrlreg + TH1520_CTRL_PCFGW_0); + writel(0x00005020, ctrlreg + TH1520_CTRL_PCFGR_1); + writel(0x0000501f, ctrlreg + TH1520_CTRL_PCFGW_1); + writel(0x0000501f, ctrlreg + TH1520_CTRL_PCFGR_2); + writel(0x0000503f, ctrlreg + TH1520_CTRL_PCFGW_2); + writel(0x000051ff, ctrlreg + TH1520_CTRL_PCFGR_3); + writel(0x000051ff, ctrlreg + TH1520_CTRL_PCFGW_3); + writel(0x0000503f, ctrlreg + TH1520_CTRL_PCFGR_4); + writel(0x0000503f, ctrlreg + TH1520_CTRL_PCFGW_4); + + ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_PWRCTL, tmp, + tmp == 0x00000020, + TH1520_CTRL_INIT_TIMEOUT_US); + if (ret) + return ret; + + writel(0x00000020, ctrlreg + TH1520_CTRL_PWRCTL); + + ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_DCH1_PWRCTL, tmp, + tmp == 0x00000020, + TH1520_CTRL_INIT_TIMEOUT_US); + if (ret) + return ret; + + writel(0x00000020, ctrlreg + TH1520_CTRL_DCH1_PWRCTL); + writel(0x00000000, ctrlreg + TH1520_CTRL_DBG1); + + ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_PWRCTL, tmp, + tmp == 0x00000020, + TH1520_CTRL_INIT_TIMEOUT_US); + if (ret) + return ret; + + writel(0x00000020, ctrlreg + TH1520_CTRL_PWRCTL); + + ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_PWRCTL, tmp, + tmp == 0x00000020, + TH1520_CTRL_INIT_TIMEOUT_US); + if (ret) + return ret; + + writel(0x00000020, ctrlreg + TH1520_CTRL_PWRCTL); + writel(0x00000000, ctrlreg + TH1520_CTRL_DCH1_DBG1); + + ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_DCH1_PWRCTL, tmp, + tmp == 0x00000020, + TH1520_CTRL_INIT_TIMEOUT_US); + if (ret) + return ret; + + writel(0x00000020, ctrlreg + TH1520_CTRL_DCH1_PWRCTL); + + ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_DCH1_PWRCTL, tmp, + tmp == 0x00000020, + TH1520_CTRL_INIT_TIMEOUT_US); + if (ret) + return ret; + + writel(0x00000020, ctrlreg + TH1520_CTRL_DCH1_PWRCTL); + writel(0x14000001, ctrlreg + TH1520_CTRL_DFIPHYMSTR); + writel(0x00000000, ctrlreg + TH1520_CTRL_SWCTL); + writel(0x00000010, ctrlreg + TH1520_CTRL_DFIMISC); + writel(0x00000010, ctrlreg + TH1520_CTRL_DFIMISC); + writel(0x00000002, ctrlreg + TH1520_CTRL_DBG1); + writel(0x00000002, ctrlreg + TH1520_CTRL_DCH1_DBG1); + + switch (fw->bitwidth) { + case 64: + writel(0x00040018, ctrlreg + TH1520_CTRL_ADDRMAP0); + writel(0x00090909, ctrlreg + TH1520_CTRL_ADDRMAP1); + writel(0x00000000, ctrlreg + TH1520_CTRL_ADDRMAP2); + writel(0x01010101, ctrlreg + TH1520_CTRL_ADDRMAP3); + writel(0x00001f1f, ctrlreg + TH1520_CTRL_ADDRMAP4); + writel(0x080f0808, ctrlreg + TH1520_CTRL_ADDRMAP5); + writel(0x08080808, ctrlreg + TH1520_CTRL_ADDRMAP6); + writel(0x00000f0f, ctrlreg + TH1520_CTRL_ADDRMAP7); + writel(0x08080808, ctrlreg + TH1520_CTRL_ADDRMAP9); + writel(0x08080808, ctrlreg + TH1520_CTRL_ADDRMAP10); + writel(0x00000008, ctrlreg + TH1520_CTRL_ADDRMAP11); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int th1520_ddr_read_msg(void __iomem *phyreg, u16 *id, u16 *data) +{ + u32 tmp; + int ret; + + ret = readw_poll_timeout(phyreg + TH1520_PHY_MSG_STATUS, tmp, + !(tmp & TH1520_PHY_MSG_STATUS_EMPTY), + TH1520_PHY_MSG_TIMEOUT_US); + if (ret) + return ret; + + *id = readw(phyreg + TH1520_PHY_MSG_ID); + *data = readw(phyreg + TH1520_PHY_MSG_DATA); + + writew(0, phyreg + TH1520_PHY_MSG_ACK); + + ret = readw_poll_timeout(phyreg + TH1520_PHY_MSG_STATUS, tmp, + tmp & TH1520_PHY_MSG_STATUS_EMPTY, + TH1520_PHY_MSG_TIMEOUT_US); + if (ret) + return ret; + + writew(TH1520_PHY_MSG_ACK_EN, phyreg + TH1520_PHY_MSG_ACK); + + return 0; +} + +static int th1520_phy_wait_pmu_completion(void __iomem *phyreg) +{ + u16 id, data; + int ret; + + do { + ret = th1520_ddr_read_msg(phyreg, &id, &data); + + if (ret) + return ret; + } while (id != TH1520_PHY_MSG_ID_COMPLETION && + id != TH1520_PHY_MSG_ID_ERROR && + !ret); + + return id == TH1520_PHY_MSG_ID_COMPLETION ? ret : -EIO; +} + +static int lpddr4_load_firmware(struct th1520_ddr_priv *priv, + struct th1520_ddr_fw *fw) +{ + union th1520_ddr_cfg *cfg; + size_t i, j; + int ret; + + for (cfg = fw->cfgs, i = 0; i < fw->cfgnum; i++) { + u32 addr = FIELD_GET(TH1520_DDR_CFG_ADDR, cfg->opaddr) * 2; + u32 op = FIELD_GET(TH1520_DDR_CFG_OP, cfg->opaddr); + + switch (op) { + case TH1520_DDR_CFG_PHY0: + writew(cfg->phy.data, priv->phy0 + addr); + break; + case TH1520_DDR_CFG_PHY1: + writew(cfg->phy.data, priv->phy1 + addr); + break; + case TH1520_DDR_CFG_PHY: + writew(cfg->phy.data, priv->phy0 + addr); + writew(cfg->phy.data, priv->phy1 + addr); + break; + case TH1520_DDR_CFG_RANGE: + for (j = 0; j < cfg->range.num; j++) { + writew(cfg->range.data[j], + priv->phy0 + addr + j * 2); + writew(cfg->range.data[j], + priv->phy1 + addr + j * 2); + } + break; + case TH1520_DDR_CFG_WAITFW0: + ret = th1520_phy_wait_pmu_completion(priv->phy0); + + if (ret) { + pr_err("phy 0 training failed: %d\n", ret); + return ret; + } + + break; + case TH1520_DDR_CFG_WAITFW1: + ret = th1520_phy_wait_pmu_completion(priv->phy1); + + if (ret) { + pr_err("phy 1 training failed: %d\n", ret); + return ret; + } + + break; + default: + pr_err("Unknown DRAM configuration %d\n", op); + + return -EOPNOTSUPP; + } + + if (op == TH1520_DDR_CFG_RANGE) + cfg = (void *)cfg + sizeof(cfg->range) + + cfg->range.num * sizeof(u16); + else + cfg = (union th1520_ddr_cfg *)(&cfg->phy + 1); + } + + return 0; +} + +static int th1520_ddr_ctrl_enable(void __iomem *ctrlreg, + struct th1520_ddr_fw *fw) +{ + u32 tmp; + int ret; + + writel(0x00000030, ctrlreg + TH1520_CTRL_DFIMISC); + + ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_DFISTAT, tmp, + tmp == 0x00000001, + TH1520_CTRL_INIT_TIMEOUT_US); + if (ret) + return ret; + + ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_DCH1_DFISTAT, tmp, + tmp == 0x00000001, + TH1520_CTRL_INIT_TIMEOUT_US); + if (ret) + return ret; + + writel(0x00000010, ctrlreg + TH1520_CTRL_DFIMISC); + writel(0x00000011, ctrlreg + TH1520_CTRL_DFIMISC); + writel(0x0000000a, ctrlreg + TH1520_CTRL_PWRCTL); + writel(0x0000000a, ctrlreg + TH1520_CTRL_DCH1_PWRCTL); + writel(0x00000001, ctrlreg + TH1520_CTRL_SWCTL); + + ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_SWSTAT, tmp, + tmp == 0x00000001, + TH1520_CTRL_INIT_TIMEOUT_US); + if (ret) + return ret; + + ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_STAT, tmp, + tmp == 0x00000001, + TH1520_CTRL_INIT_TIMEOUT_US); + if (ret) + return ret; + + ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_DCH1_STAT, tmp, + tmp == 0x00000001, + TH1520_CTRL_INIT_TIMEOUT_US); + if (ret) + return ret; + + writel(0x14000001, ctrlreg + TH1520_CTRL_DFIPHYMSTR); + writel(0x00000000, ctrlreg + TH1520_CTRL_SWCTL); + writel(0x00020002, ctrlreg + TH1520_CTRL_INIT0); + writel(0x00000001, ctrlreg + TH1520_CTRL_SWCTL); + + ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_SWSTAT, tmp, + tmp == 0x00000001, + TH1520_CTRL_INIT_TIMEOUT_US); + + if (ret) + return ret; + + writel(0x00000000, ctrlreg + TH1520_CTRL_DBG1); + writel(0x00000000, ctrlreg + TH1520_CTRL_DCH1_DBG1); + + return 0; +} + +static void th1520_ddr_enable_self_refresh(void __iomem *ctrlreg, + void __iomem *sysreg) +{ + writel(0x00000000, ctrlreg + TH1520_CTRL_RFSHCTL3); + + writel(0x000a0000, sysreg + TH1520_SYS_DDR_CFG1); + + writel(0x00000000, ctrlreg + TH1520_CTRL_SWCTL); + writel(0x00000001, ctrlreg + TH1520_CTRL_SWCTLSTATIC); + writel(0x0040ae04, ctrlreg + TH1520_CTRL_PWRTMG); + writel(0x00430003, ctrlreg + TH1520_CTRL_HWLPCTL); + writel(0x00430003, ctrlreg + TH1520_CTRL_DCH1_HWLPCTL); + writel(0x00000001, ctrlreg + TH1520_CTRL_SWCTL); + writel(0x00000000, ctrlreg + TH1520_CTRL_SWCTLSTATIC); + writel(0x0000000b, ctrlreg + TH1520_CTRL_PWRCTL); + writel(0x0000000b, ctrlreg + TH1520_CTRL_DCH1_PWRCTL); +} + +static int th1520_ddr_init(struct th1520_ddr_priv *priv) +{ + struct th1520_ddr_fw *fw = (void *)binman_sym(ulong, ddr_fw, image_pos); + u32 reset; + int ret; + + ret = th1520_ddr_pll_config(priv->sys, fw->freq); + if (ret) { + pr_err("failed to configure PLL: %d\n", ret); + return ret; + } + + reset = TH1520_SYS_DDR_CFG0_PHY_PWROK_RSTN; + writel(reset, priv->sys + TH1520_SYS_DDR_CFG0); + reset |= TH1520_SYS_DDR_CFG0_PHY_CORE_RSTN; + writel(reset, priv->sys + TH1520_SYS_DDR_CFG0); + reset |= TH1520_SYS_DDR_CFG0_APB_RSTN; + writel(reset, priv->sys + TH1520_SYS_DDR_CFG0); + + ret = th1520_ddr_ctrl_init(priv->ctrl, fw); + if (ret) { + pr_err("failed to initialize DDR controller: %d\n", ret); + return ret; + } + + reset |= TH1520_SYS_DDR_CFG0_APB_PORT_RSTN(0) | + TH1520_SYS_DDR_CFG0_APB_PORT_RSTN(1) | + TH1520_SYS_DDR_CFG0_APB_PORT_RSTN(2) | + TH1520_SYS_DDR_CFG0_APB_PORT_RSTN(3) | + TH1520_SYS_DDR_CFG0_APB_PORT_RSTN(4) | + TH1520_SYS_DDR_CFG0_CTRL_RSTN; + writel(reset, priv->sys + TH1520_SYS_DDR_CFG0); + + lpddr4_load_firmware(priv, fw); + + ret = th1520_ddr_ctrl_enable(priv->ctrl, fw); + if (ret) { + pr_err("failed to enable DDR controller: %d\n", ret); + return ret; + } + + th1520_ddr_enable_self_refresh(priv->ctrl, priv->sys); + + return 0; +} + +static int th1520_ddr_probe(struct udevice *dev) +{ + struct th1520_ddr_priv *priv = dev_get_priv(dev); + fdt_addr_t addr; + + addr = dev_read_addr_name(dev, "phy-0"); + priv->phy0 = (void __iomem *)addr; + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + addr = dev_read_addr_name(dev, "phy-1"); + priv->phy1 = (void __iomem *)addr; + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + addr = dev_read_addr_name(dev, "ctrl"); + priv->ctrl = (void __iomem *)addr; + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + addr = dev_read_addr_name(dev, "sys"); + priv->sys = (void __iomem *)addr; + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + return th1520_ddr_init(priv); +} + +static int th1520_ddr_get_info(struct udevice *dev, struct ram_info *info) +{ + info->base = gd->ram_base; + info->size = gd->ram_size; + + return 0; +} + +static struct ram_ops th1520_ddr_ops = { + .get_info = th1520_ddr_get_info, +}; + +static const struct udevice_id th1520_ddr_ids[] = { + { .compatible = "thead,th1520-ddrc" }, + { } +}; + +U_BOOT_DRIVER(th1520_ddr) = { + .name = "th1520_ddr", + .id = UCLASS_RAM, + .ops = &th1520_ddr_ops, + .of_match = th1520_ddr_ids, + .probe = th1520_ddr_probe, + .priv_auto = sizeof(struct th1520_ddr_priv), +}; diff --git a/drivers/spi/nxp_fspi.c b/drivers/spi/nxp_fspi.c index 7489c896f9d..6d97b8eefc9 100644 --- a/drivers/spi/nxp_fspi.c +++ b/drivers/spi/nxp_fspi.c @@ -52,13 +52,6 @@ #include <linux/bug.h> #include <linux/err.h> -/* - * The driver only uses one single LUT entry, that is updated on - * each call of exec_op(). Index 0 is preset at boot with a basic - * read operation, so let's use the last entry (31). - */ -#define SEQID_LUT 31 - /* Registers used by the driver */ #define FSPI_MCR0 0x00 #define FSPI_MCR0_AHB_TIMEOUT(x) ((x) << 24) @@ -242,9 +235,6 @@ #define FSPI_TFDR 0x180 #define FSPI_LUT_BASE 0x200 -#define FSPI_LUT_OFFSET (SEQID_LUT * 4 * 4) -#define FSPI_LUT_REG(idx) \ - (FSPI_LUT_BASE + FSPI_LUT_OFFSET + (idx) * 4) /* register map end */ @@ -316,6 +306,7 @@ struct nxp_fspi_devtype_data { unsigned int txfifo; unsigned int ahb_buf_size; unsigned int quirks; + unsigned int lut_num; bool little_endian; }; @@ -324,6 +315,7 @@ static struct nxp_fspi_devtype_data lx2160a_data = { .txfifo = SZ_1K, /* (128 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ .quirks = 0, + .lut_num = 32, .little_endian = true, /* little-endian */ }; @@ -332,9 +324,19 @@ static struct nxp_fspi_devtype_data imx8mm_data = { .txfifo = SZ_1K, /* (128 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ .quirks = 0, + .lut_num = 32, .little_endian = true, /* little-endian */ }; +static struct nxp_fspi_devtype_data imxrt1170_data = { + .rxfifo = SZ_256, + .txfifo = SZ_256, + .ahb_buf_size = SZ_4K, + .quirks = 0, + .lut_num = 16, + .little_endian = true, +}; + struct nxp_fspi { struct udevice *dev; void __iomem *iobase; @@ -486,6 +488,8 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f, void __iomem *base = f->iobase; u32 lutval[4] = {}; int lutidx = 1, i; + u32 lut_offset = (f->devtype_data->lut_num - 1) * 4 * 4; + u32 target_lut_reg; /* cmd */ lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth), @@ -530,8 +534,10 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f, fspi_writel(f, FSPI_LCKER_UNLOCK, f->iobase + FSPI_LCKCR); /* fill LUT */ - for (i = 0; i < ARRAY_SIZE(lutval); i++) - fspi_writel(f, lutval[i], base + FSPI_LUT_REG(i)); + for (i = 0; i < ARRAY_SIZE(lutval); i++) { + target_lut_reg = FSPI_LUT_BASE + lut_offset + i * 4; + fspi_writel(f, lutval[i], base + target_lut_reg); + } dev_dbg(f->dev, "CMD[%x] lutval[0:%x \t 1:%x \t 2:%x \t 3:%x], size: 0x%08x\n", op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3], op->data.nbytes); @@ -731,7 +737,7 @@ static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op) void __iomem *base = f->iobase; int seqnum = 0; int err = 0; - u32 reg; + u32 reg, seqid_lut; reg = fspi_readl(f, base + FSPI_IPRXFCR); /* invalid RXFIFO first */ @@ -745,8 +751,9 @@ static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op) * the LUT at each exec_op() call. And also specify the DATA * length, since it's has not been specified in the LUT. */ + seqid_lut = f->devtype_data->lut_num - 1; fspi_writel(f, op->data.nbytes | - (SEQID_LUT << FSPI_IPCR1_SEQID_SHIFT) | + (seqid_lut << FSPI_IPCR1_SEQID_SHIFT) | (seqnum << FSPI_IPCR1_SEQNUM_SHIFT), base + FSPI_IPCR1); @@ -862,7 +869,7 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f) { void __iomem *base = f->iobase; int ret, i; - u32 reg; + u32 reg, seqid_lut; #if CONFIG_IS_ENABLED(CLK) /* the default frequency, we will change it later if necessary. */ @@ -933,11 +940,17 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f) fspi_writel(f, reg, base + FSPI_FLSHB1CR1); fspi_writel(f, reg, base + FSPI_FLSHB2CR1); + /* + * The driver only uses one single LUT entry, that is updated on + * each call of exec_op(). Index 0 is preset at boot with a basic + * read operation, so let's use the last entry. + */ + seqid_lut = f->devtype_data->lut_num - 1; /* AHB Read - Set lut sequence ID for all CS. */ - fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA1CR2); - fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA2CR2); - fspi_writel(f, SEQID_LUT, base + FSPI_FLSHB1CR2); - fspi_writel(f, SEQID_LUT, base + FSPI_FLSHB2CR2); + fspi_writel(f, seqid_lut, base + FSPI_FLSHA1CR2); + fspi_writel(f, seqid_lut, base + FSPI_FLSHA2CR2); + fspi_writel(f, seqid_lut, base + FSPI_FLSHB1CR2); + fspi_writel(f, seqid_lut, base + FSPI_FLSHB2CR2); return 0; } @@ -1035,7 +1048,8 @@ static int nxp_fspi_of_to_plat(struct udevice *bus) } #endif - dev_dbg(bus, "iobase=<0x%llx>, ahb_addr=<0x%llx>\n", iobase, ahb_addr); + dev_dbg(bus, "iobase=<0x%llx>, ahb_addr=<0x%llx>\n", + (long long)iobase, (long long)ahb_addr); return 0; } @@ -1057,6 +1071,7 @@ static const struct udevice_id nxp_fspi_ids[] = { { .compatible = "nxp,lx2160a-fspi", .data = (ulong)&lx2160a_data, }, { .compatible = "nxp,imx8mm-fspi", .data = (ulong)&imx8mm_data, }, { .compatible = "nxp,imx8mp-fspi", .data = (ulong)&imx8mm_data, }, + { .compatible = "nxp,imxrt1170-fspi", .data = (ulong)&imxrt1170_data, }, { } }; diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index a35b8c2f646..847fa1f82c3 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -23,6 +23,7 @@ #include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/err.h> +#include <linux/iopoll.h> #include <linux/ioport.h> #include <dm.h> #include <generic-phy.h> @@ -587,7 +588,6 @@ static void dwc3_set_incr_burst_type(struct dwc3 *dwc) */ static int dwc3_core_init(struct dwc3 *dwc) { - unsigned long timeout; u32 hwparams4 = dwc->hwparams.hwparams4; u32 reg; int ret; @@ -610,15 +610,11 @@ static int dwc3_core_init(struct dwc3 *dwc) } /* issue device SoftReset too */ - timeout = 5000; dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); - while (timeout--) { - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - if (!(reg & DWC3_DCTL_CSFTRST)) - break; - }; - - if (!timeout) { + ret = read_poll_timeout(dwc3_readl, reg, + !(reg & DWC3_DCTL_CSFTRST), + 1, 5000, dwc->regs, DWC3_DCTL); + if (ret) { dev_err(dwc->dev, "Reset Timed Out\n"); ret = -ETIMEDOUT; goto err0; diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 3dc79770eeb..5c9e8fc9d15 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -262,7 +262,7 @@ endif config USB_EHCI_MSM bool "Support for Qualcomm on-chip EHCI USB controller" depends on DM_USB - select USB_ULPI_VIEWPORT + select USB_ULPI select MSM8916_USB_PHY ---help--- Enables support for the on-chip EHCI controller on Qualcomm @@ -279,7 +279,10 @@ config USB_EHCI_TEGRA depends on ARCH_TEGRA select USB_EHCI_IS_TDI ---help--- - Enable support for Tegra on-chip EHCI USB controller + Enable support for Tegra on-chip EHCI USB controller. If you enable + ULPI and your PHY needs a different reference clock than the standard + 24 MHz then you have to define CFG_ULPI_REF_CLK to the appropriate + value in Hz. config USB_EHCI_ZYNQ bool "Support for Xilinx Zynq on-chip EHCI USB controller" diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 7c73eb66b60..89b87886da1 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -25,13 +25,6 @@ #define HOSTPC1_DEVLC 0x84 #define HOSTPC1_PSPD(x) (((x) >> 25) & 0x3) -#ifdef CONFIG_USB_ULPI - #ifndef CONFIG_USB_ULPI_VIEWPORT - #error "To use CONFIG_USB_ULPI on Tegra Boards you have to also \ - define CONFIG_USB_ULPI_VIEWPORT" - #endif -#endif - /* Parameters we need for USB */ enum { PARAM_DIVN, /* PLL FEEDBACK DIVIDer */ diff --git a/drivers/usb/ulpi/Kconfig b/drivers/usb/ulpi/Kconfig index 001564d40c6..d969360f7eb 100644 --- a/drivers/usb/ulpi/Kconfig +++ b/drivers/usb/ulpi/Kconfig @@ -1,8 +1,18 @@ comment "ULPI drivers" +config USB_ULPI + bool "ULPI support" + depends on USB_HOST + help + Select to commnicate with USB PHY via ULPI interface. + The ULPI (UTMI Low Pin (count) Interface) is a wrapper on UTMI+ core + that is used as PHY Transreceiver for USB controllers. + + This driver uses ULPI viewports that are specific for each SoC. + choice prompt "ULPI Viewport type" - optional + depends on USB_ULPI help Select ULPI viewport (SoC-side interface to ULPI) implementation appropriate for the device if you want to communicate with @@ -10,23 +20,9 @@ choice config USB_ULPI_VIEWPORT bool "Generic ULPI Viewport" + depends on USB_ULPI help Support generic ULPI Viewport implementation that is used on some Tegra and Snapdragon devices. -config USB_ULPI_VIEWPORT_OMAP - bool "OMAP ULPI Viewport" - help - Support ULPI Viewport implementation that is used on OMAP devices. - endchoice - -config USB_ULPI - bool "ULPI support" - depends on (USB_ULPI_VIEWPORT || USB_ULPI_VIEWPORT_OMAP) - help - Select to commnicate with USB PHY via ULPI interface. - ULPI is wrapper on UTMI+ core that is used as - PHY Transreceiver for USB controllers. - - This driver uses ULPI viewports that are specific for each SoC. diff --git a/drivers/usb/ulpi/Makefile b/drivers/usb/ulpi/Makefile index f05b7743531..5565948bc12 100644 --- a/drivers/usb/ulpi/Makefile +++ b/drivers/usb/ulpi/Makefile @@ -4,4 +4,3 @@ obj-$(CONFIG_USB_ULPI) += ulpi.o obj-$(CONFIG_USB_ULPI_VIEWPORT) += ulpi-viewport.o -obj-$(CONFIG_USB_ULPI_VIEWPORT_OMAP) += omap-ulpi-viewport.o diff --git a/drivers/usb/ulpi/omap-ulpi-viewport.c b/drivers/usb/ulpi/omap-ulpi-viewport.c deleted file mode 100644 index 6f0c3eb154e..00000000000 --- a/drivers/usb/ulpi/omap-ulpi-viewport.c +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * OMAP ulpi viewport support - * Based on drivers/usb/ulpi/ulpi-viewport.c - * - * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com - * Author: Govindraj R <govindraj.raja@ti.com> - */ - -#include <log.h> -#include <asm/io.h> -#include <linux/delay.h> -#include <usb/ulpi.h> - -#define OMAP_ULPI_WR_OPSEL (2 << 22) -#define OMAP_ULPI_RD_OPSEL (3 << 22) -#define OMAP_ULPI_START (1 << 31) - -/* - * Wait for having ulpi in done state - */ -static int ulpi_wait(struct ulpi_viewport *ulpi_vp, u32 mask) -{ - int timeout = CFG_USB_ULPI_TIMEOUT; - - while (--timeout) { - if (!(readl(ulpi_vp->viewport_addr) & mask)) - return 0; - - udelay(1); - } - - return ULPI_ERROR; -} - -/* - * Issue a ULPI read/write request - */ -static int ulpi_request(struct ulpi_viewport *ulpi_vp, u32 value) -{ - int err; - - writel(value, ulpi_vp->viewport_addr); - - err = ulpi_wait(ulpi_vp, OMAP_ULPI_START); - if (err) - debug("ULPI request timed out\n"); - - return err; -} - -int ulpi_write(struct ulpi_viewport *ulpi_vp, u8 *reg, u32 value) -{ - u32 val = OMAP_ULPI_START | (((ulpi_vp->port_num + 1) & 0xf) << 24) | - OMAP_ULPI_WR_OPSEL | ((u32)reg << 16) | (value & 0xff); - - return ulpi_request(ulpi_vp, val); -} - -u32 ulpi_read(struct ulpi_viewport *ulpi_vp, u8 *reg) -{ - int err; - u32 val = OMAP_ULPI_START | (((ulpi_vp->port_num + 1) & 0xf) << 24) | - OMAP_ULPI_RD_OPSEL | ((u32)reg << 16); - - err = ulpi_request(ulpi_vp, val); - if (err) - return err; - - return readl(ulpi_vp->viewport_addr) & 0xff; -} diff --git a/env/Kconfig b/env/Kconfig index 9f5ec44601e..d7a7e81144b 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -389,7 +389,7 @@ config ENV_IS_IN_SPI_FLASH config ENV_IS_IN_MTD bool "Environment is in MTD flash" - depends on !CHAIN_OF_TRUST && (SPI_FLASH || DM_SPI_FLASH) + depends on !CHAIN_OF_TRUST && MTD default y if ARCH_AIROHA help Define this if you have a MTD Flash memory device which you diff --git a/env/mtd.c b/env/mtd.c index 721faebd8f2..d7ec30e183a 100644 --- a/env/mtd.c +++ b/env/mtd.c @@ -32,7 +32,7 @@ static int setup_mtd_device(struct mtd_info **mtd_env) static int env_mtd_save(void) { - char *saved_buf, *write_buf, *tmp; + char *saved_buf = NULL, *write_buf, *tmp; struct erase_info ei = { }; struct mtd_info *mtd_env; u32 sect_size, sect_num; @@ -105,7 +105,7 @@ static int env_mtd_save(void) } offset = CONFIG_ENV_OFFSET; - remaining = sect_size; + remaining = write_size; tmp = write_buf; puts("Writing to MTD..."); diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig index 1a913d2b6d2..8ddaebebd48 100644 --- a/fs/ext4/Kconfig +++ b/fs/ext4/Kconfig @@ -1,5 +1,6 @@ config FS_EXT4 bool "Enable ext4 filesystem support" + select CRC16 help This provides support for reading images from the ext4 filesystem. ext4 is a widely used general-purpose filesystem for Linux. diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c index bd058a09614..51944b61bd0 100644 --- a/fs/ext4/ext4fs.c +++ b/fs/ext4/ext4fs.c @@ -102,7 +102,7 @@ int ext4fs_read_file(struct ext2fs_node *node, loff_t pos, blockcnt = lldiv(((len + pos) + blocksize - 1), blocksize); for (i = lldiv(pos, blocksize); i < blockcnt; i++) { - long int blknr; + lbaint_t blknr; int blockoff = pos - (blocksize * i); int blockend = blocksize; int skipfirst = 0; diff --git a/fs/fs_internal.c b/fs/fs_internal.c index ab4847ac257..ff27c564efc 100644 --- a/fs/fs_internal.c +++ b/fs/fs_internal.c @@ -28,7 +28,7 @@ int fs_devread(struct blk_desc *blk, struct disk_partition *partition, /* Check partition boundaries */ if ((sector + ((byte_offset + byte_len - 1) >> log2blksz)) >= partition->size) { - log_debug("read outside partition " LBAFU "\n", sector); + log_err("** Read outside partition " LBAFU "\n", sector); return 0; } diff --git a/include/configs/imx6ulz_smm_m2.h b/include/configs/imx6ulz_smm_m2.h index 44a3fc02e8a..87aede218d1 100644 --- a/include/configs/imx6ulz_smm_m2.h +++ b/include/configs/imx6ulz_smm_m2.h @@ -60,10 +60,8 @@ BOOTENV /* Physical Memory Map */ -#define PHYS_SDRAM MMDC0_ARB_BASE_ADDR -#define PHYS_SDRAM_SIZE SZ_128M - -#define CFG_SYS_SDRAM_BASE PHYS_SDRAM +#define PHYS_SDRAM MMDC0_ARB_BASE_ADDR +#define CFG_SYS_SDRAM_BASE PHYS_SDRAM #define CFG_SYS_INIT_RAM_ADDR IRAM_BASE_ADDR #define CFG_SYS_INIT_RAM_SIZE IRAM_SIZE diff --git a/include/configs/starfive-visionfive2.h b/include/configs/starfive-visionfive2.h index 049b0a06301..e7001b26abf 100644 --- a/include/configs/starfive-visionfive2.h +++ b/include/configs/starfive-visionfive2.h @@ -39,4 +39,6 @@ "partitions=" PARTS_DEFAULT "\0" \ "fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" +#define CFG_SYS_NS16550_CLK 24000000 + #endif /* _STARFIVE_VISIONFIVE2_H */ diff --git a/include/configs/th1520_lpi4a.h b/include/configs/th1520_lpi4a.h index 87496a52c4c..7a9b70a3678 100644 --- a/include/configs/th1520_lpi4a.h +++ b/include/configs/th1520_lpi4a.h @@ -9,6 +9,7 @@ #include <linux/sizes.h> +#define CFG_SYS_NS16550_CLK 100000000 #define CFG_SYS_SDRAM_BASE 0x00000000 #define UART_BASE 0xffe7014000 diff --git a/include/dt-bindings/clock/imxrt1170-clock.h b/include/dt-bindings/clock/imxrt1170-clock.h index 8ab8018a15e..d3d21cf310d 100644 --- a/include/dt-bindings/clock/imxrt1170-clock.h +++ b/include/dt-bindings/clock/imxrt1170-clock.h @@ -43,6 +43,8 @@ #define IMXRT1170_CLK_GPT1 33 #define IMXRT1170_CLK_SEMC_SEL 34 #define IMXRT1170_CLK_SEMC 35 -#define IMXRT1170_CLK_END 36 +#define IMXRT1170_CLK_FLEXSPI1_SEL 36 +#define IMXRT1170_CLK_FLEXSPI1 37 +#define IMXRT1170_CLK_END 38 #endif /* __DT_BINDINGS_CLOCK_IMXRT1170_H */ diff --git a/include/efi_device_path.h b/include/efi_device_path.h new file mode 100644 index 00000000000..aae85228f68 --- /dev/null +++ b/include/efi_device_path.h @@ -0,0 +1,421 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * EFI device path functions + * + * (C) Copyright 2017 Rob Clark + */ + +#ifndef EFI_DEVICE_PATH_H +#define EFI_DEVICE_PATH_H + +#include <efi.h> + +struct blk_desc; +struct efi_load_option; +struct udevice; + +/* + * EFI_DP_END - Template end node for EFI device paths. + * + * Represents the terminating node of an EFI device path. + * It has a type of DEVICE_PATH_TYPE_END and sub_type DEVICE_PATH_SUB_TYPE_END + */ +extern const struct efi_device_path EFI_DP_END; + +/** + * efi_dp_next() - Iterate to next block in device-path + * + * Advance to the next node in an EFI device path. + * + * @dp: Pointer to the current device path node. + * Return: Pointer to the next device path node, or NULL if at the end + * or if input is NULL. + */ +struct efi_device_path *efi_dp_next(const struct efi_device_path *dp); + +/** + * efi_dp_match() - Compare two device-paths + * + * Compare two device paths node by node. The comparison stops when an End + * node is reached in the shorter of the two paths. This is useful, for example, + * to compare a device-path representing a device with one representing a file + * on that device, or a device with a parent device. + * + * @a: Pointer to the first device path. + * @b: Pointer to the second device path. + * Return: An integer less than, equal to, or greater than zero if the first + * differing node in 'a' is found, respectively, to be less than, + * to match, or be greater than the corresponding node in 'b'. Returns 0 + * if they match up to the end of the shorter path. Compares length first, + * then content. + */ +int efi_dp_match(const struct efi_device_path *a, + const struct efi_device_path *b); + +/** + * efi_dp_shorten() - shorten device-path + * + * When creating a short-boot option we want to use a device-path that is + * independent of the location where the block device is plugged in. + * + * UsbWwi() nodes contain a serial number, hard drive paths a partition + * UUID. Both should be unique. + * + * See UEFI spec, section 3.1.2 for "short-form device path". + * + * @dp: original device-path + * Return: shortened device-path or NULL + */ +struct efi_device_path *efi_dp_shorten(struct efi_device_path *dp); + +/** + * efi_dp_find_obj() - find handle by device path + * + * If @rem is provided, the handle with the longest partial match is returned. + * + * @dp: device path to search + * @guid: GUID of protocol that must be installed on path or NULL + * @rem: pointer to receive remaining device path + * Return: matching handle + */ +efi_handle_t efi_dp_find_obj(struct efi_device_path *dp, const efi_guid_t *guid, + struct efi_device_path **rem); + +/** + * efi_dp_last_node() - Determine the last device path node before the end node + * + * Iterate through the device path to find the very last node before + * the terminating EFI_DP_END node. + * + * @dp: Pointer to the device path. + * Return: Pointer to the last actual data node before the end node if it exists + * otherwise NULL (e.g., if dp is NULL or only an EFI_DP_END node). + */ +const struct efi_device_path *efi_dp_last_node(const struct efi_device_path *dp); + +/** + * efi_dp_instance_size() - Get size of the first device path instance + * + * Calculate the total length of all nodes in the first instance of a + * (potentially multi-instance) device path. The size of the instance-specific + * end node (if any) or the final device path. The end node is not included. + * + * @dp: Pointer to the device path. + * Return: Size in bytes of the first instance, or 0 if dp is NULL or an + * EFI_DP_END node + */ +efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp); + +/** + * efi_dp_size() - Get size of multi-instance device path excluding end node + * + * Calculate the total size of the entire device path structure, traversing + * through all instances, up to but not including the final + * END_ENTIRE_DEVICE_PATH node. + * + * @dp: Pointer to the device path. + * Return: Total size in bytes of all nodes in the device path (excluding the + * final EFI_DP_END node), or 0 if dp is NULL. + */ +efi_uintn_t efi_dp_size(const struct efi_device_path *dp); + +/** + * efi_dp_dup() - Copy multi-instance device path + * + * Duplicate the given device path, including its end node(s). + * The caller is responsible for freeing the allocated memory (e.g., + * using efi_free()). + * + * @dp: Pointer to the device path to duplicate. + * Return: Pointer to the newly allocated and copied device path, or NULL on + * allocation failure or if dp is NULL. + */ +struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp); + +/** + * efi_dp_concat() - Concatenate two device paths and terminate the result + * + * @dp1: First device path + * @dp2: Second device path + * @split_end_node: + * - 0 to concatenate (dp1 is assumed not to have an end node or it's ignored, + * dp2 is appended, then one EFI_DP_END node) + * - 1 to concatenate with end node added as separator (dp1, END_THIS_INSTANCE, + * dp2, END_ENTIRE) + * + * Size of dp1 excluding last end node to concatenate with end node as + * separator in case dp1 contains an end node (dp1 (partial), END_THIS_INSTANCE, + * dp2, END_ENTIRE) + * + * Return: + * concatenated device path or NULL. Caller must free the returned value. + */ +struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1, + const struct efi_device_path *dp2, + size_t split_end_node); + +/** + * efi_dp_append_node() - Append a single node to a device path + * + * Create a new device path by appending a given node to an existing + * device path. + * If the original device path @dp is NULL, a new path is created + * with the given @node followed by an EFI_DP_END node. + * If the @node is NULL and @dp is not NULL, the original path @dp is + * duplicated. + * If both @dp and @node are NULL, a path with only an EFI_DP_END node is + * returned. + * The caller must free the returned path (e.g., using efi_free()). + * + * @dp: Original device path (can be NULL). + * @node: Node to append (can be NULL). + * Return: New device path with the node appended, or NULL on allocation + * failure. + */ +struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, + const struct efi_device_path *node); + +/** + * efi_dp_create_device_node() - Create a new device path node + * + * Allocate and initialise the header of a new EFI device path node with the + * given type, sub-type, and length. The content of the node beyond the basic + * efi_device_path header is zeroed by efi_alloc. + * + * @type: Device path type. + * @sub_type: Device path sub-type. + * @length: Length of the node (must be >= sizeof(struct efi_device_path)). + * Return: Pointer to the new device path node, or NULL on allocation failure + * or if length is invalid. + */ +struct efi_device_path *efi_dp_create_device_node(const u8 type, + const u8 sub_type, + const u16 length); + +/** + * efi_dp_append_instance() - Append a device path instance to another + * + * Concatenate two device paths, treating the second path (@dpi) as a new + * instance appended to the first path (@dp). An END_THIS_INSTANCE node is + * inserted between @dp and @dpi if @dp is not NULL. + * If @dp is NULL, @dpi is duplicated (and terminated appropriately). + * @dpi must not be NULL. + * The caller is responsible for freeing the returned path (e.g., using + * efi_free()). + * + * @dp: The base device path. If NULL, @dpi is duplicated. + * @dpi: The device path instance to append. Must not be NULL. + * Return: A new device path with @dpi appended as a new instance, or NULL on + * error (e.g. allocation failure, @dpi is NULL). + */ +struct efi_device_path * +efi_dp_append_instance(const struct efi_device_path *dp, + const struct efi_device_path *dpi); + +/** + * efi_dp_get_next_instance() - Extract the next dp instance + * + * Given a pointer to a pointer to a device path (@dp), this function extracts + * the first instance from the path. It allocates a new path for this extracted + * instance (including its instance-specific EFI_DP_END node). The input pointer + * (*@dp) is then updated to point to the start of the next instance in the + * original path, or set to NULL if no more instances remain. + * The caller is responsible for freeing the returned instance path (e.g., + * using efi_free()). + * + * @dp: On input, a pointer to a pointer to the multi-instance device path. + * On output, *@dp is updated to point to the start of the next instance, + * or NULL if no more instances. + * @size: Optional pointer to an efi_uintn_t variable that will receive the size + * of the extracted instance path (including its EFI_DP_END node). + * Return: Pointer to a newly allocated device path for the extracted instance, + * or NULL if no instance could be extracted or an error occurred (e.g., + * allocation failure). + */ +struct efi_device_path *efi_dp_get_next_instance(struct efi_device_path **dp, + efi_uintn_t *size); + +/** + * efi_dp_is_multi_instance() - Check if a device path is multi-instance + * + * Traverse the device path to its end. It is considered multi-instance if an + * END_THIS_INSTANCE_DEVICE_PATH node (type DEVICE_PATH_TYPE_END, sub-type + * DEVICE_PATH_SUB_TYPE_INSTANCE_END) is encountered before the final + * END_ENTIRE_DEVICE_PATH node. + * + * @dp: The device path to check. + * Return: True if the device path contains multiple instances, false otherwise + * (including if @dp is NULL). + */ +bool efi_dp_is_multi_instance(const struct efi_device_path *dp); + +/** + * efi_dp_from_part() - Construct a dp from a partition on a block device + * + * Create a full device path for a specified partition on a given block device. + * If the partition number @part is 0, the path is for the block device itself. + * The caller is responsible for freeing the allocated memory (e.g., using + * efi_free()). + * + * @desc: Pointer to the block device descriptor. + * @part: Partition number (0 for the whole device, >0 for a specific + * partition). + * Return: Pointer to the newly created device path, or NULL on allocation + * failure or if the device/partition is not found or invalid. + */ +struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part); + +/** + * efi_dp_part_node() - Create a device node for a block device partition + * + * Creates a single device path node representing a specific partition + * (e.g., HardDrivePath or CDROMPath, depending on desc->part_type). + * It does not create the full path from the root, only the partition-specific + * node. The caller is responsible for freeing the allocated memory (e.g., + * using efi_free()). + * + * @desc: Pointer to the block device descriptor. + * @part: Partition number (must be > 0 and correspond to a valid partition on + * the device). + * Return: Pointer to the new device path node for the partition, or NULL on + * allocation * failure or error in getting partition information. + */ +struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part); + +/** + * efi_dp_from_file() - append file path node to device path. + * + * @dp: device path or NULL + * @path: file path or NULL + * Return: device path or NULL in case of an error + */ +struct efi_device_path *efi_dp_from_file(const struct efi_device_path *dp, + const char *path); + +/** + * efi_dp_from_uart() - Create a device path for a UART device. + * + * Construct a device path representing the system's default UART, + * typically based on the U-Boot device model root and a UART messaging node. + * The caller is responsible for freeing the allocated memory (e.g., using + * efi_free()). + * + * Return: Pointer to the new UART device path, or NULL on allocation failure. + */ +struct efi_device_path *efi_dp_from_uart(void); + +/** + * efi_dp_from_eth() - Create a device path for an Ethernet device + * + * Construct a device path representing the given device. The caller is + * responsible for freeing the allocated memory (e.g. using efi_free()) + * + * @dev: UCLASS_ETH device to process + * + * Return: Pointer to the new Ethernet device path, or NULL on allocation + * failure + */ +struct efi_device_path *efi_dp_from_eth(struct udevice *dev); + +/** + * efi_dp_from_mem() - Construct a device-path for a memory-mapped region + * + * Create an EFI device path representing a specific memory region, defined + * by its type, start address, and size. + * The caller is responsible for freeing the allocated memory (e.g., + * using efi_free()). + * + * @memory_type: EFI memory type (e.g., EFI_RESERVED_MEMORY_TYPE). + * @start_address: Starting address of the memory region. + * @size: Size of the memory region in bytes. + * Return: Pointer to the new memory device path, or NULL on allocation failure + */ +struct efi_device_path *efi_dp_from_mem(u32 memory_type, u64 start_address, + size_t size); + +/** + * efi_dp_split_file_path() - split of relative file path from device path + * + * Given a device path indicating a file on a device, separate the device + * path in two: the device path of the actual device and the file path + * relative to this device. + * + * @full_path: device path including device and file path + * @device_path: path of the device + * @file_path: relative path of the file or NULL if there is none + * Return: status code + */ +efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path, + struct efi_device_path **device_path, + struct efi_device_path **file_path); + +/** + * efi_dp_from_name() - convert U-Boot device and file path to device path + * + * @dev: U-Boot device, e.g. 'mmc' + * @devnr: U-Boot device number, e.g. 1 for 'mmc:1' + * @path: file path relative to U-Boot device, may be NULL + * @device: pointer to receive device path of the device + * @file: pointer to receive device path for the file + * Return: status code + */ +efi_status_t efi_dp_from_name(const char *dev, const char *devnr, + const char *path, struct efi_device_path **device, + struct efi_device_path **file); + +/** + * efi_dp_check_length() - check length of a device path + * + * @dp: pointer to device path + * @maxlen: maximum length of the device path + * Return: + * * length of the device path if it is less or equal @maxlen + * * -1 if the device path is longer then @maxlen + * * -1 if a device path node has a length of less than 4 + * * -EINVAL if maxlen exceeds SSIZE_MAX + */ +ssize_t efi_dp_check_length(const struct efi_device_path *dp, + const size_t maxlen); + +/** + * efi_dp_from_lo() - get device-path from load option + * + * The load options in U-Boot may contain multiple concatenated device-paths. + * The first device-path indicates the EFI binary to execute. Subsequent + * device-paths start with a VenMedia node where the GUID identifies the + * function (initrd or fdt). + * + * @lo: EFI load option containing a valid device path + * @guid: GUID identifying device-path or NULL for the EFI binary + * + * Return: + * device path excluding the matched VenMedia node or NULL. + * Caller must free the returned value. + */ +struct efi_device_path *efi_dp_from_lo(struct efi_load_option *lo, + const efi_guid_t *guid); + +/** + * search_gpt_dp_node() - search gpt device path node + * + * @device_path: device path + * + * Return: pointer to the gpt device path node + */ +struct efi_device_path *search_gpt_dp_node(struct efi_device_path *device_path); + +/** + * efi_dp_from_http() - set device path from http + * + * Set the device path to an IPv4 path as provided by efi_dp_from_ipv4 + * concatenated with a device path of subtype DEVICE_PATH_SUB_TYPE_MSG_URI, + * and an EFI_DP_END node. + * + * @server: URI of remote server + * @dev: net udevice + * Return: pointer to HTTP device path, NULL on error + */ +struct efi_device_path *efi_dp_from_http(const char *server, + struct udevice *dev); + +#endif /* EFI_DEVICE_PATH_H */ diff --git a/include/efi_loader.h b/include/efi_loader.h index 84e8cfe320e..b3beda5de7b 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -9,6 +9,7 @@ #define _EFI_LOADER_H 1 #include <blk.h> +#include <efi_device_path.h> #include <event.h> #include <log.h> #include <part_efi.h> @@ -588,8 +589,27 @@ efi_status_t efi_bootmgr_delete_boot_option(u16 boot_index); efi_status_t efi_bootmgr_run(void *fdt); /* search the boot option index in BootOrder */ bool efi_search_bootorder(u16 *bootorder, efi_uintn_t num, u32 target, u32 *index); -/* Set up console modes */ + +/** + * efi_setup_console_size() - update the mode table. + * + * By default the only mode available is 80x25. If the console has at least 50 + * lines, enable mode 80x50. If we can query the console size and it is neither + * 80x25 nor 80x50, set it as an additional mode. + */ void efi_setup_console_size(void); + +/** + * efi_console_set_ansi() - Set whether ANSI escape-characters should be emitted + * + * These characters mess up tests which use ut_assert_nextline(). Call this + * function to tell efi_loader not to emit these characters when starting up the + * terminal + * + * @allow_ansi: Allow emitting ANSI escape-characters + */ +void efi_console_set_ansi(bool allow_ansi); + /* Set up load options from environment variable */ efi_status_t efi_env_set_load_options(efi_handle_t handle, const char *env_var, u16 **load_options); @@ -916,66 +936,10 @@ extern void *efi_bounce_buffer; #define EFI_LOADER_BOUNCE_BUFFER_SIZE (64 * 1024 * 1024) #endif -/* shorten device path */ -struct efi_device_path *efi_dp_shorten(struct efi_device_path *dp); -struct efi_device_path *efi_dp_next(const struct efi_device_path *dp); -int efi_dp_match(const struct efi_device_path *a, - const struct efi_device_path *b); -efi_handle_t efi_dp_find_obj(struct efi_device_path *dp, - const efi_guid_t *guid, - struct efi_device_path **rem); -/* get size of the first device path instance excluding end node */ -efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp); -/* size of multi-instance device path excluding end node */ -efi_uintn_t efi_dp_size(const struct efi_device_path *dp); -struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp); -struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, - const struct efi_device_path *node); -/* Create a device path node of given type, sub-type, length */ -struct efi_device_path *efi_dp_create_device_node(const u8 type, - const u8 sub_type, - const u16 length); -/* Append device path instance */ -struct efi_device_path *efi_dp_append_instance( - const struct efi_device_path *dp, - const struct efi_device_path *dpi); -/* Get next device path instance */ -struct efi_device_path *efi_dp_get_next_instance(struct efi_device_path **dp, - efi_uintn_t *size); -/* Check if a device path contains muliple instances */ -bool efi_dp_is_multi_instance(const struct efi_device_path *dp); - -struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part); -/* Create a device node for a block device partition. */ -struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part); -struct efi_device_path *efi_dp_from_file(const struct efi_device_path *dp, - const char *path); -struct efi_device_path *efi_dp_from_eth(struct udevice *dev); -struct efi_device_path *efi_dp_from_http(const char *server, struct udevice *dev); -struct efi_device_path *efi_dp_from_mem(uint32_t mem_type, - uint64_t start_address, - size_t size); -/* Determine the last device path node that is not the end node. */ -const struct efi_device_path *efi_dp_last_node( - const struct efi_device_path *dp); -efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path, - struct efi_device_path **device_path, - struct efi_device_path **file_path); -struct efi_device_path *efi_dp_from_uart(void); -efi_status_t efi_dp_from_name(const char *dev, const char *devnr, - const char *path, - struct efi_device_path **device, - struct efi_device_path **file); -ssize_t efi_dp_check_length(const struct efi_device_path *dp, - const size_t maxlen); - #define EFI_DP_TYPE(_dp, _type, _subtype) \ (((_dp)->type == DEVICE_PATH_TYPE_##_type) && \ ((_dp)->sub_type == DEVICE_PATH_SUB_TYPE_##_subtype)) -/* template END node: */ -extern const struct efi_device_path END; - /* Indicate supported runtime services */ efi_status_t efi_init_runtime_supported(void); diff --git a/include/image.h b/include/image.h index c1db8383459..4620782c069 100644 --- a/include/image.h +++ b/include/image.h @@ -138,7 +138,8 @@ enum { IH_ARCH_ARC, /* Synopsys DesignWare ARC */ IH_ARCH_X86_64, /* AMD x86_64, Intel and Via */ IH_ARCH_XTENSA, /* Xtensa */ - IH_ARCH_RISCV, /* RISC-V */ + IH_ARCH_RISCV, /* RISC-V 32 bit*/ + IH_ARCH_RISCV64, /* RISC-V 64 bit*/ IH_ARCH_COUNT, }; diff --git a/include/net-common.h b/include/net-common.h index e536968a92b..7853612b237 100644 --- a/include/net-common.h +++ b/include/net-common.h @@ -570,6 +570,7 @@ enum wget_http_method { * Filled by client. * @hdr_cont_len: content length according to headers. Filled by wget * @headers: buffer for headers. Filled by wget. + * @silent: do not print anything to the console. Filled by client. */ struct wget_http_info { enum wget_http_method method; @@ -580,6 +581,7 @@ struct wget_http_info { bool check_buffer_size; u32 hdr_cont_len; char *headers; + bool silent; }; extern struct wget_http_info default_wget_info; diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c index 495be53cb77..7392c60f0f9 100644 --- a/lib/efi_driver/efi_uclass.c +++ b/lib/efi_driver/efi_uclass.c @@ -20,6 +20,7 @@ #define LOG_CATEGORY LOGC_EFI #include <dm.h> +#include <efi_device_path.h> #include <efi_driver.h> #include <log.h> #include <malloc.h> diff --git a/lib/efi_loader/efi_bootbin.c b/lib/efi_loader/efi_bootbin.c index 94ba7c5589b..b394f0d60ce 100644 --- a/lib/efi_loader/efi_bootbin.c +++ b/lib/efi_loader/efi_bootbin.c @@ -10,6 +10,7 @@ #include <charset.h> #include <dm.h> #include <efi.h> +#include <efi_device_path.h> #include <efi_loader.h> #include <env.h> #include <image.h> diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index c0df5cb9acd..1a3461f5a9d 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -12,6 +12,7 @@ #include <charset.h> #include <dm.h> #include <efi.h> +#include <efi_device_path.h> #include <log.h> #include <malloc.h> #include <net.h> @@ -479,6 +480,13 @@ static efi_status_t try_load_from_uri_path(struct efi_device_path_uri *uridp, if (!ctx) return EFI_OUT_OF_RESOURCES; + s = env_get("ipaddr"); + if (!s && dhcp_run(0, NULL, false)) { + log_err("Error: Can't find a valid IP address\n"); + ret = EFI_DEVICE_ERROR; + goto err; + } + s = env_get("loadaddr"); if (!s) { log_err("Error: loadaddr is not set\n"); @@ -527,7 +535,7 @@ static efi_status_t try_load_from_uri_path(struct efi_device_path_uri *uridp, * will be freed in return_to_efibootmgr event callback. */ loaded_dp = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, - (uintptr_t)image_addr, image_size); + image_addr, image_size); ret = efi_install_multiple_protocol_interfaces( &mem_handle, &efi_guid_device_path, loaded_dp, NULL); if (ret != EFI_SUCCESS) @@ -855,7 +863,8 @@ efi_bootmgr_enumerate_boot_options(struct eficonfig_media_boot_option *opt, lo.label = dev_name; lo.attributes = LOAD_OPTION_ACTIVE; lo.file_path = device_path; - lo.file_path_length = efi_dp_size(device_path) + sizeof(END); + lo.file_path_length = efi_dp_size(device_path) + + sizeof(EFI_DP_END); /* * Set the dedicated guid to optional_data, it is used to identify * the boot option that automatically generated by the bootmenu. diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index dbebb37dc04..24b0e52a2a2 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -11,6 +11,7 @@ #include <div64.h> #include <dm/device.h> #include <dm/root.h> +#include <efi_device_path.h> #include <efi_loader.h> #include <irq_func.h> #include <log.h> diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index 1aa52ac7bb6..f19e78ae9d1 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -8,6 +8,7 @@ #define LOG_CATEGORY LOGC_EFI +#include <efi_device_path.h> #include <efi_loader.h> #include <efi_variable.h> #include <env.h> diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 9d9f786a6db..953f6831466 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -9,6 +9,7 @@ #include <ansi.h> #include <charset.h> +#include <efi_device_path.h> #include <malloc.h> #include <time.h> #include <dm/device.h> @@ -30,6 +31,17 @@ struct cout_mode { __maybe_unused static struct efi_object uart_obj; +/* + * suppress emission of ANSI escape-characters for use by unit tests. Leave it + * as 0 for the default behaviour + */ +static bool no_ansi; + +void efi_console_set_ansi(bool allow_ansi) +{ + no_ansi = !allow_ansi; +} + static struct cout_mode efi_cout_modes[] = { /* EFI Mode 0 is 80x25 and always present */ { @@ -348,13 +360,6 @@ static int __maybe_unused query_vidconsole(int *rows, int *cols) return 0; } -/** - * efi_setup_console_size() - update the mode table. - * - * By default the only mode available is 80x25. If the console has at least 50 - * lines, enable mode 80x50. If we can query the console size and it is neither - * 80x25 nor 80x50, set it as an additional mode. - */ void efi_setup_console_size(void) { int rows = 25, cols = 80; @@ -362,8 +367,12 @@ void efi_setup_console_size(void) if (IS_ENABLED(CONFIG_VIDEO)) ret = query_vidconsole(&rows, &cols); - if (ret) - ret = query_console_serial(&rows, &cols); + if (ret) { + if (no_ansi) + ret = 0; + else + ret = query_console_serial(&rows, &cols); + } if (ret) return; diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index c9bf2726fe2..7316a76f462 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -10,6 +10,7 @@ #include <blk.h> #include <dm.h> #include <dm/root.h> +#include <efi_device_path.h> #include <log.h> #include <net.h> #include <usb.h> @@ -21,11 +22,11 @@ #include <asm-generic/unaligned.h> #include <linux/compat.h> /* U16_MAX */ -/* template END node: */ -const struct efi_device_path END = { +/* template EFI_DP_END node: */ +const struct efi_device_path EFI_DP_END = { .type = DEVICE_PATH_TYPE_END, .sub_type = DEVICE_PATH_SUB_TYPE_END, - .length = sizeof(END), + .length = sizeof(EFI_DP_END), }; #if defined(CONFIG_MMC) @@ -46,10 +47,6 @@ static bool is_sd(struct blk_desc *desc) } #endif -/* - * Iterate to next block in device-path, terminating (returning NULL) - * at /End* node. - */ struct efi_device_path *efi_dp_next(const struct efi_device_path *dp) { if (dp == NULL) @@ -62,12 +59,6 @@ struct efi_device_path *efi_dp_next(const struct efi_device_path *dp) return (struct efi_device_path *)dp; } -/* - * Compare two device-paths, stopping when the shorter of the two hits - * an End* node. This is useful to, for example, compare a device-path - * representing a device with one representing a file on the device, or - * a device with a parent device. - */ int efi_dp_match(const struct efi_device_path *a, const struct efi_device_path *b) { @@ -90,20 +81,6 @@ int efi_dp_match(const struct efi_device_path *a, } } -/** - * efi_dp_shorten() - shorten device-path - * - * When creating a short boot option we want to use a device-path that is - * independent of the location where the block device is plugged in. - * - * UsbWwi() nodes contain a serial number, hard drive paths a partition - * UUID. Both should be unique. - * - * See UEFI spec, section 3.1.2 for "short-form device path". - * - * @dp: original device-path - * Return: shortened device-path or NULL - */ struct efi_device_path *efi_dp_shorten(struct efi_device_path *dp) { while (dp) { @@ -180,16 +157,6 @@ static efi_handle_t find_handle(struct efi_device_path *dp, return best_handle; } -/** - * efi_dp_find_obj() - find handle by device path - * - * If @rem is provided, the handle with the longest partial match is returned. - * - * @dp: device path to search - * @guid: GUID of protocol that must be installed on path or NULL - * @rem: pointer to receive remaining device path - * Return: matching handle - */ efi_handle_t efi_dp_find_obj(struct efi_device_path *dp, const efi_guid_t *guid, struct efi_device_path **rem) @@ -204,13 +171,6 @@ efi_handle_t efi_dp_find_obj(struct efi_device_path *dp, return handle; } -/* - * Determine the last device path node that is not the end node. - * - * @dp device path - * Return: last node before the end node if it exists - * otherwise NULL - */ const struct efi_device_path *efi_dp_last_node(const struct efi_device_path *dp) { struct efi_device_path *ret; @@ -224,7 +184,6 @@ const struct efi_device_path *efi_dp_last_node(const struct efi_device_path *dp) return ret; } -/* get size of the first device path instance excluding end node */ efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp) { efi_uintn_t sz = 0; @@ -239,7 +198,6 @@ efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp) return sz; } -/* get size of multi-instance device path excluding end node */ efi_uintn_t efi_dp_size(const struct efi_device_path *dp) { const struct efi_device_path *p = dp; @@ -253,11 +211,10 @@ efi_uintn_t efi_dp_size(const struct efi_device_path *dp) return (void *)p - (void *)dp; } -/* copy multi-instance device path */ struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp) { struct efi_device_path *ndp; - size_t sz = efi_dp_size(dp) + sizeof(END); + size_t sz = efi_dp_size(dp) + sizeof(EFI_DP_END); if (!dp) return NULL; @@ -270,21 +227,6 @@ struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp) return ndp; } -/** - * efi_dp_concat() - Concatenate two device paths and add and terminate them - * with an end node. - * - * @dp1: First device path - * @dp2: Second device path - * @split_end_node: - * * 0 to concatenate - * * 1 to concatenate with end node added as separator - * * size of dp1 excluding last end node to concatenate with end node as - * separator in case dp1 contains an end node - * - * Return: - * concatenated device path or NULL. Caller must free the returned value - */ struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1, const struct efi_device_path *dp2, @@ -295,7 +237,7 @@ efi_device_path *efi_dp_concat(const struct efi_device_path *dp1, if (!dp1 && !dp2) { /* return an end node */ - ret = efi_dp_dup(&END); + ret = efi_dp_dup(&EFI_DP_END); } else if (!dp1) { ret = efi_dp_dup(dp2); } else if (!dp2) { @@ -312,9 +254,9 @@ efi_device_path *efi_dp_concat(const struct efi_device_path *dp1, sz1 = split_end_node; if (split_end_node) - end_size = 2 * sizeof(END); + end_size = 2 * sizeof(EFI_DP_END); else - end_size = sizeof(END); + end_size = sizeof(EFI_DP_END); p = efi_alloc(sz1 + sz2 + end_size); if (!p) return NULL; @@ -323,14 +265,14 @@ efi_device_path *efi_dp_concat(const struct efi_device_path *dp1, p += sz1; if (split_end_node) { - memcpy(p, &END, sizeof(END)); - p += sizeof(END); + memcpy(p, &EFI_DP_END, sizeof(EFI_DP_END)); + p += sizeof(EFI_DP_END); } /* the end node of the second device path has to be retained */ memcpy(p, dp2, sz2); p += sz2; - memcpy(p, &END, sizeof(END)); + memcpy(p, &EFI_DP_END, sizeof(EFI_DP_END)); } return ret; @@ -342,26 +284,26 @@ struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, struct efi_device_path *ret; if (!node && !dp) { - ret = efi_dp_dup(&END); + ret = efi_dp_dup(&EFI_DP_END); } else if (!node) { ret = efi_dp_dup(dp); } else if (!dp) { size_t sz = node->length; - void *p = efi_alloc(sz + sizeof(END)); + void *p = efi_alloc(sz + sizeof(EFI_DP_END)); if (!p) return NULL; memcpy(p, node, sz); - memcpy(p + sz, &END, sizeof(END)); + memcpy(p + sz, &EFI_DP_END, sizeof(EFI_DP_END)); ret = p; } else { /* both dp and node are non-null */ size_t sz = efi_dp_size(dp); - void *p = efi_alloc(sz + node->length + sizeof(END)); + void *p = efi_alloc(sz + node->length + sizeof(EFI_DP_END)); if (!p) return NULL; memcpy(p, dp, sz); memcpy(p + sz, node, node->length); - memcpy(p + sz + node->length, &END, sizeof(END)); + memcpy(p + sz + node->length, &EFI_DP_END, sizeof(EFI_DP_END)); ret = p; } @@ -399,17 +341,17 @@ struct efi_device_path *efi_dp_append_instance( return efi_dp_dup(dpi); sz = efi_dp_size(dp); szi = efi_dp_instance_size(dpi); - p = efi_alloc(sz + szi + 2 * sizeof(END)); + p = efi_alloc(sz + szi + 2 * sizeof(EFI_DP_END)); if (!p) return NULL; ret = p; - memcpy(p, dp, sz + sizeof(END)); + memcpy(p, dp, sz + sizeof(EFI_DP_END)); p = (void *)p + sz; p->sub_type = DEVICE_PATH_SUB_TYPE_INSTANCE_END; - p = (void *)p + sizeof(END); + p = (void *)p + sizeof(EFI_DP_END); memcpy(p, dpi, szi); p = (void *)p + szi; - memcpy(p, &END, sizeof(END)); + memcpy(p, &EFI_DP_END, sizeof(EFI_DP_END)); return ret; } @@ -424,17 +366,17 @@ struct efi_device_path *efi_dp_get_next_instance(struct efi_device_path **dp, if (!dp || !*dp) return NULL; sz = efi_dp_instance_size(*dp); - p = efi_alloc(sz + sizeof(END)); + p = efi_alloc(sz + sizeof(EFI_DP_END)); if (!p) return NULL; - memcpy(p, *dp, sz + sizeof(END)); + memcpy(p, *dp, sz + sizeof(EFI_DP_END)); *dp = (void *)*dp + sz; if ((*dp)->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END) - *dp = (void *)*dp + sizeof(END); + *dp = (void *)*dp + sizeof(EFI_DP_END); else *dp = NULL; if (size) - *size = sz + sizeof(END); + *size = sz + sizeof(EFI_DP_END); return p; } @@ -449,9 +391,6 @@ bool efi_dp_is_multi_instance(const struct efi_device_path *dp) return p->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END; } -/* size of device-path not including END node for device and all parents - * up to the root device. - */ __maybe_unused static unsigned int dp_size(struct udevice *dev) { if (!dev || !dev->driver) @@ -820,29 +759,21 @@ static void *dp_part_fill(void *buf, struct blk_desc *desc, int part) return dp_part_node(buf, desc, part); } -/* Construct a device-path from a partition on a block device: */ struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part) { void *buf, *start; - start = buf = efi_alloc(dp_part_size(desc, part) + sizeof(END)); - if (!buf) + start = efi_alloc(dp_part_size(desc, part) + sizeof(EFI_DP_END)); + if (!start) return NULL; - buf = dp_part_fill(buf, desc, part); + buf = dp_part_fill(start, desc, part); - *((struct efi_device_path *)buf) = END; + *((struct efi_device_path *)buf) = EFI_DP_END; return start; } -/* - * Create a device node for a block device partition. - * - * @buf buffer to which the device path is written - * @desc block device descriptor - * @part partition number, 0 identifies a block device - */ struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part) { efi_uintn_t dpsize; @@ -892,13 +823,6 @@ static void path_to_uefi(void *uefi, const char *src) *pos = 0; } -/** - * efi_dp_from_file() - append file path node to device path. - * - * @dp: device path or NULL - * @path: file path or NULL - * Return: device path or NULL in case of an error - */ struct efi_device_path *efi_dp_from_file(const struct efi_device_path *dp, const char *path) { @@ -912,7 +836,7 @@ struct efi_device_path *efi_dp_from_file(const struct efi_device_path *dp, if (fpsize > U16_MAX) return NULL; - buf = efi_alloc(dpsize + fpsize + sizeof(END)); + buf = efi_alloc(dpsize + fpsize + sizeof(EFI_DP_END)); if (!buf) return NULL; @@ -929,7 +853,7 @@ struct efi_device_path *efi_dp_from_file(const struct efi_device_path *dp, pos += fpsize; } - memcpy(pos, &END, sizeof(END)); + memcpy(pos, &EFI_DP_END, sizeof(EFI_DP_END)); return buf; } @@ -938,7 +862,7 @@ struct efi_device_path *efi_dp_from_uart(void) { void *buf, *pos; struct efi_device_path_uart *uart; - size_t dpsize = dp_size(dm_root()) + sizeof(*uart) + sizeof(END); + size_t dpsize = dp_size(dm_root()) + sizeof(*uart) + sizeof(EFI_DP_END); buf = efi_alloc(dpsize); if (!buf) @@ -949,7 +873,7 @@ struct efi_device_path *efi_dp_from_uart(void) uart->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_UART; uart->dp.length = sizeof(*uart); pos += sizeof(*uart); - memcpy(pos, &END, sizeof(END)); + memcpy(pos, &EFI_DP_END, sizeof(EFI_DP_END)); return buf; } @@ -963,13 +887,13 @@ struct efi_device_path __maybe_unused *efi_dp_from_eth(struct udevice *dev) dpsize += dp_size(dev); - start = buf = efi_alloc(dpsize + sizeof(END)); - if (!buf) + start = efi_alloc(dpsize + sizeof(EFI_DP_END)); + if (!start) return NULL; - buf = dp_fill(buf, dev); + buf = dp_fill(start, dev); - *((struct efi_device_path *)buf) = END; + *((struct efi_device_path *)buf) = EFI_DP_END; return start; } @@ -979,7 +903,7 @@ struct efi_device_path __maybe_unused *efi_dp_from_eth(struct udevice *dev) * * Set the device path to an ethernet device path as provided by * efi_dp_from_eth() concatenated with a device path of subtype - * DEVICE_PATH_SUB_TYPE_MSG_IPV4, and an END node. + * DEVICE_PATH_SUB_TYPE_MSG_IPV4, and an EFI_DP_END node. * * @ip: IPv4 local address * @mask: network mask @@ -1010,7 +934,7 @@ static struct efi_device_path *efi_dp_from_ipv4(struct efi_ipv4_address *ip, if (srv) memcpy(&dp.ipv4dp.remote_ip_address, srv, sizeof(*srv)); pos = &dp.end; - memcpy(pos, &END, sizeof(END)); + memcpy(pos, &EFI_DP_END, sizeof(EFI_DP_END)); dp1 = efi_dp_from_eth(dev); if (!dp1) @@ -1023,17 +947,6 @@ static struct efi_device_path *efi_dp_from_ipv4(struct efi_ipv4_address *ip, return dp2; } -/** - * efi_dp_from_http() - set device path from http - * - * Set the device path to an IPv4 path as provided by efi_dp_from_ipv4 - * concatenated with a device path of subtype DEVICE_PATH_SUB_TYPE_MSG_URI, - * and an END node. - * - * @server: URI of remote server - * @dev: net udevice - * Return: pointer to HTTP device path, NULL on error - */ struct efi_device_path *efi_dp_from_http(const char *server, struct udevice *dev) { struct efi_device_path *dp1, *dp2; @@ -1066,7 +979,7 @@ struct efi_device_path *efi_dp_from_http(const char *server, struct udevice *dev } uridp_len = sizeof(struct efi_device_path) + strlen(tmp) + 1; - uridp = efi_alloc(uridp_len + sizeof(END)); + uridp = efi_alloc(uridp_len + sizeof(EFI_DP_END)); if (!uridp) { log_err("Out of memory\n"); return NULL; @@ -1078,7 +991,7 @@ struct efi_device_path *efi_dp_from_http(const char *server, struct udevice *dev memcpy(uridp->uri, tmp, strlen(tmp) + 1); pos = (char *)uridp + uridp_len; - memcpy(pos, &END, sizeof(END)); + memcpy(pos, &EFI_DP_END, sizeof(EFI_DP_END)); dp2 = efi_dp_concat(dp1, (const struct efi_device_path *)uridp, 0); @@ -1096,11 +1009,11 @@ struct efi_device_path *efi_dp_from_mem(uint32_t memory_type, struct efi_device_path_memory *mdp; void *buf, *start; - start = buf = efi_alloc(sizeof(*mdp) + sizeof(END)); - if (!buf) + start = efi_alloc(sizeof(*mdp) + sizeof(EFI_DP_END)); + if (!start) return NULL; - mdp = buf; + mdp = start; mdp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; mdp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MEMORY; mdp->dp.length = sizeof(*mdp); @@ -1109,7 +1022,7 @@ struct efi_device_path *efi_dp_from_mem(uint32_t memory_type, mdp->end_address = start_address + size; buf = &mdp[1]; - *((struct efi_device_path *)buf) = END; + *((struct efi_device_path *)buf) = EFI_DP_END; return start; } diff --git a/lib/efi_loader/efi_device_path_utilities.c b/lib/efi_loader/efi_device_path_utilities.c index 552c5bb1f05..87d52df5066 100644 --- a/lib/efi_loader/efi_device_path_utilities.c +++ b/lib/efi_loader/efi_device_path_utilities.c @@ -7,6 +7,7 @@ #define LOG_CATEGORY LOGC_EFI +#include <efi_device_path.h> #include <efi_loader.h> const efi_guid_t efi_guid_device_path_utilities_protocol = @@ -31,7 +32,7 @@ static efi_uintn_t EFIAPI get_device_path_size( efi_uintn_t sz = 0; EFI_ENTRY("%pD", device_path); - /* size includes the END node: */ + /* size includes the EFI_DP_END node: */ if (device_path) sz = efi_dp_size(device_path) + sizeof(struct efi_device_path); return EFI_EXIT(sz); diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 5452640354e..47b583cc5e1 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -11,6 +11,7 @@ #include <dm.h> #include <dm/device-internal.h> #include <dm/tag.h> +#include <efi_device_path.h> #include <event.h> #include <efi_driver.h> #include <efi_loader.h> diff --git a/lib/efi_loader/efi_fdt.c b/lib/efi_loader/efi_fdt.c index 1ba6641d821..bfaa9cfc207 100644 --- a/lib/efi_loader/efi_fdt.c +++ b/lib/efi_loader/efi_fdt.c @@ -8,6 +8,7 @@ #define LOG_CATEGORY LOGC_EFI +#include <efi_device_path.h> #include <efi_loader.h> #include <env.h> #include <errno.h> diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index 19fb5d03fec..44b806aadc4 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -7,6 +7,7 @@ #include <blkmap.h> #include <bootm.h> +#include <efi_device_path.h> #include <env.h> #include <image.h> #include <log.h> @@ -199,7 +200,7 @@ efi_status_t efi_load_option_dp_join(struct efi_device_path **dp, efi_free_pool(tmp_dp); if (!*dp) return EFI_OUT_OF_RESOURCES; - *dp_size += efi_dp_size(initrd_dp) + sizeof(END); + *dp_size += efi_dp_size(initrd_dp) + sizeof(EFI_DP_END); } if (fdt_dp) { @@ -209,10 +210,10 @@ efi_status_t efi_load_option_dp_join(struct efi_device_path **dp, efi_free_pool(tmp_dp); if (!*dp) return EFI_OUT_OF_RESOURCES; - *dp_size += efi_dp_size(fdt_dp) + sizeof(END); + *dp_size += efi_dp_size(fdt_dp) + sizeof(EFI_DP_END); } - *dp_size += sizeof(END); + *dp_size += sizeof(EFI_DP_END); return EFI_SUCCESS; } diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index b3291b4f1d5..8e708d8d350 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -17,6 +17,7 @@ #define LOG_CATEGORY LOGC_EFI +#include <efi_device_path.h> #include <efi_loader.h> #include <dm.h> #include <linux/sizes.h> @@ -51,7 +52,7 @@ static int next_dp_entry; static struct wget_http_info efi_wget_info = { .set_bootdev = false, .check_buffer_size = true, - + .silent = true, }; #endif diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 210a846ebc8..1832eeb5dce 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -10,6 +10,7 @@ #define LOG_CATEGORY LOGC_EFI #include <dm.h> +#include <efi_device_path.h> #include <efi_loader.h> #include <efi_variable.h> #include <efi_tcg2.h> diff --git a/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c b/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c index ef51a5ac168..7459bfa468f 100644 --- a/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c +++ b/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c @@ -60,6 +60,8 @@ #if LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS +#include "lwip/errno.h" + #include "lwip/altcp.h" #include "lwip/altcp_tls.h" #include "lwip/priv/altcp_priv.h" @@ -299,7 +301,8 @@ altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn, altcp_mbedtls_state_t * LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_handshake failed: %d\n", ret)); /* handshake failed, connection has to be closed */ if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { - printf("Certificate verification failed\n"); + /* provide a cause for why the connection is closed to the called */ + errno = EPERM; } if (conn->err) { conn->err(conn->arg, ERR_CLSD); @@ -844,9 +847,6 @@ altcp_tls_create_config(int is_server, u8_t cert_count, u8_t pkey_count, int hav altcp_mbedtls_free_config(conf); return NULL; } - if (authmode == MBEDTLS_SSL_VERIFY_NONE) { - printf("WARNING: no CA certificates, HTTPS connections not authenticated\n"); - } mbedtls_ssl_conf_authmode(&conf->conf, authmode); mbedtls_ssl_conf_rng(&conf->conf, mbedtls_ctr_drbg_random, &altcp_tls_entropy_rng->ctr_drbg); diff --git a/net/lwip/tftp.c b/net/lwip/tftp.c index 4f9b2049187..fae701bad2e 100644 --- a/net/lwip/tftp.c +++ b/net/lwip/tftp.c @@ -8,6 +8,7 @@ #include <efi_loader.h> #include <image.h> #include <linux/delay.h> +#include <linux/kconfig.h> #include <lwip/apps/tftp_client.h> #include <lwip/timeouts.h> #include <mapmem.h> @@ -15,6 +16,8 @@ #include <time.h> #define PROGRESS_PRINT_STEP_BYTES (10 * 1024) +/* Max time to wait for first data packet from server */ +#define NO_RSP_TIMEOUT_MS 10000 enum done_state { NOT_DONE = 0, @@ -31,6 +34,47 @@ struct tftp_ctx { enum done_state done; }; +/** + * store_block() - copy received data + * + * This function is called by the receive callback to copy a block of data + * into its final location (ctx->daddr). Before doing so, it checks if the copy + * is allowed. + * + * @ctx: the context for the current transfer + * @src: the data received from the TCP stack + * @len: the length of the data + */ +static int store_block(struct tftp_ctx *ctx, void *src, u16_t len) +{ + ulong store_addr = ctx->daddr; + void *ptr; + + if (CONFIG_IS_ENABLED(LMB)) { + if (store_addr + len < store_addr || + lmb_read_check(store_addr, len)) { + puts("\nTFTP error: "); + puts("trying to overwrite reserved memory...\n"); + return -1; + } + } + + ptr = map_sysmem(store_addr, len); + memcpy(ptr, src, len); + unmap_sysmem(ptr); + + ctx->daddr += len; + ctx->size += len; + ctx->block_count++; + if (ctx->block_count % 10 == 0) { + putc('#'); + if (ctx->block_count % (65 * 10) == 0) + puts("\n\t "); + } + + return 0; +} + static void *tftp_open(const char *fname, const char *mode, u8_t is_write) { return NULL; @@ -71,17 +115,9 @@ static int tftp_write(void *handle, struct pbuf *p) struct tftp_ctx *ctx = handle; struct pbuf *q; - for (q = p; q; q = q->next) { - memcpy((void *)ctx->daddr, q->payload, q->len); - ctx->daddr += q->len; - ctx->size += q->len; - ctx->block_count++; - if (ctx->block_count % 10 == 0) { - putc('#'); - if (ctx->block_count % (65 * 10) == 0) - puts("\n\t "); - } - } + for (q = p; q; q = q->next) + if (store_block(ctx, q->payload, q->len) < 0) + return -1; return 0; } @@ -106,6 +142,17 @@ static const struct tftp_context tftp_context = { tftp_error }; +static void no_response(void *arg) +{ + struct tftp_ctx *ctx = (struct tftp_ctx *)arg; + + if (ctx->size) + return; + + printf("Timeout!\n"); + ctx->done = FAILURE; +} + static int tftp_loop(struct udevice *udev, ulong addr, char *fname, ip_addr_t srvip, uint16_t srvport) { @@ -150,6 +197,7 @@ static int tftp_loop(struct udevice *udev, ulong addr, char *fname, return -1; } + sys_timeout(NO_RSP_TIMEOUT_MS, no_response, &ctx); while (!ctx.done) { net_lwip_rx(udev, netif); sys_check_timeouts(); @@ -159,6 +207,7 @@ static int tftp_loop(struct udevice *udev, ulong addr, char *fname, break; } } + sys_untimeout(no_response, (void *)&ctx); tftp_cleanup(); diff --git a/net/lwip/wget.c b/net/lwip/wget.c index a3b82908877..ea1113e18b1 100644 --- a/net/lwip/wget.c +++ b/net/lwip/wget.c @@ -6,8 +6,10 @@ #include <display_options.h> #include <efi_loader.h> #include <image.h> +#include <linux/kconfig.h> #include <lwip/apps/http_client.h> #include "lwip/altcp_tls.h" +#include <lwip/errno.h> #include <lwip/timeouts.h> #include <rng.h> #include <mapmem.h> @@ -201,11 +203,58 @@ static int parse_legacy_arg(char *arg, char *nurl, size_t rem) return 0; } +/** + * store_block() - copy received data + * + * This function is called by the receive callback to copy a block of data + * into its final location (ctx->daddr). Before doing so, it checks if the copy + * is allowed. + * + * @ctx: the context for the current transfer + * @src: the data received from the TCP stack + * @len: the length of the data + */ +static int store_block(struct wget_ctx *ctx, void *src, u16_t len) +{ + ulong store_addr = ctx->daddr; + uchar *ptr; + + /* Avoid overflow */ + if (wget_info->buffer_size && wget_info->buffer_size < ctx->size + len) + return -1; + + if (CONFIG_IS_ENABLED(LMB) && wget_info->set_bootdev) { + if (store_addr + len < store_addr || + lmb_read_check(store_addr, len)) { + if (!wget_info->silent) { + printf("\nwget error: "); + printf("trying to overwrite reserved memory\n"); + } + return -1; + } + } + + ptr = map_sysmem(store_addr, len); + memcpy(ptr, src, len); + unmap_sysmem(ptr); + + ctx->daddr += len; + ctx->size += len; + if (ctx->size - ctx->prevsize > PROGRESS_PRINT_STEP_BYTES) { + if (!wget_info->silent) + printf("#"); + ctx->prevsize = ctx->size; + } + + return 0; +} + static err_t httpc_recv_cb(void *arg, struct altcp_pcb *pcb, struct pbuf *pbuf, err_t err) { struct wget_ctx *ctx = arg; struct pbuf *buf; + err_t ret; if (!pbuf) return ERR_BUF; @@ -214,18 +263,17 @@ static err_t httpc_recv_cb(void *arg, struct altcp_pcb *pcb, struct pbuf *pbuf, ctx->start_time = get_timer(0); for (buf = pbuf; buf; buf = buf->next) { - memcpy((void *)ctx->daddr, buf->payload, buf->len); - ctx->daddr += buf->len; - ctx->size += buf->len; - if (ctx->size - ctx->prevsize > PROGRESS_PRINT_STEP_BYTES) { - printf("#"); - ctx->prevsize = ctx->size; + if (store_block(ctx, buf->payload, buf->len) < 0) { + altcp_abort(pcb); + ret = ERR_BUF; + goto out; } } - altcp_recved(pcb, pbuf->tot_len); + ret = ERR_OK; +out: pbuf_free(pbuf); - return ERR_OK; + return ret; } static void httpc_result_cb(void *arg, httpc_result_t httpc_result, @@ -255,11 +303,15 @@ static void httpc_result_cb(void *arg, httpc_result_t httpc_result, elapsed = get_timer(ctx->start_time); if (!elapsed) elapsed = 1; - if (rx_content_len > PROGRESS_PRINT_STEP_BYTES) - printf("\n"); - printf("%u bytes transferred in %lu ms (", rx_content_len, elapsed); - print_size(rx_content_len / elapsed * 1000, "/s)\n"); - printf("Bytes transferred = %lu (%lx hex)\n", ctx->size, ctx->size); + if (!wget_info->silent) { + if (rx_content_len > PROGRESS_PRINT_STEP_BYTES) + printf("\n"); + printf("%u bytes transferred in %lu ms (", rx_content_len, + elapsed); + print_size(rx_content_len / elapsed * 1000, "/s)\n"); + printf("Bytes transferred = %lu (%lx hex)\n", ctx->size, + ctx->size); + } if (wget_info->set_bootdev) efi_set_bootdev("Http", ctx->server_name, ctx->path, map_sysmem(ctx->saved_daddr, 0), rx_content_len); @@ -339,7 +391,8 @@ static int _set_cacert(const void *addr, size_t sz) mbedtls_x509_crt_init(&crt); ret = mbedtls_x509_crt_parse(&crt, cacert, cacert_size); if (ret) { - printf("Could not parse certificates (%d)\n", ret); + if (!wget_info->silent) + printf("Could not parse certificates (%d)\n", ret); free(cacert); cacert = NULL; cacert_size = 0; @@ -372,13 +425,14 @@ static int set_cacert(char * const saddr, char * const ssz) #endif #endif /* CONFIG_WGET_CACERT || CONFIG_WGET_BUILTIN_CACERT */ -static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) +int wget_do_request(ulong dst_addr, char *uri) { #if CONFIG_IS_ENABLED(WGET_HTTPS) altcp_allocator_t tls_allocator; #endif httpc_connection_t conn; httpc_state_t *state; + struct udevice *udev; struct netif *netif; struct wget_ctx ctx; char *path; @@ -394,6 +448,14 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) if (parse_url(uri, ctx.server_name, &ctx.port, &path, &is_https)) return CMD_RET_USAGE; + if (net_lwip_eth_start() < 0) + return CMD_RET_FAILURE; + + if (!wget_info) + wget_info = &default_wget_info; + + udev = eth_get_dev(); + netif = net_lwip_new_netif(udev); if (!netif) return -1; @@ -413,9 +475,10 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) if (cacert_auth_mode == AUTH_REQUIRED) { if (!ca || !ca_sz) { - printf("Error: cacert authentication mode is " - "'required' but no CA certificates " - "given\n"); + if (!wget_info->silent) + printf("Error: cacert authentication " + "mode is 'required' but no CA " + "certificates given\n"); return CMD_RET_FAILURE; } } else if (cacert_auth_mode == AUTH_NONE) { @@ -430,6 +493,10 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) */ } + if (!ca && !wget_info->silent) { + printf("WARNING: no CA certificates, "); + printf("HTTPS connections not authenticated\n"); + } tls_allocator.alloc = &altcp_tls_alloc; tls_allocator.arg = altcp_tls_create_config_client(ca, ca_sz, @@ -454,6 +521,8 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) return CMD_RET_FAILURE; } + errno = 0; + while (!ctx.done) { net_lwip_rx(udev, netif); sys_check_timeouts(); @@ -466,21 +535,10 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) if (ctx.done == SUCCESS) return 0; - return -1; -} - -int wget_do_request(ulong dst_addr, char *uri) -{ - int ret; + if (errno == EPERM && !wget_info->silent) + printf("Certificate verification failed\n"); - ret = net_lwip_eth_start(); - if (ret < 0) - return ret; - - if (!wget_info) - wget_info = &default_wget_info; - - return wget_loop(eth_get_dev(), dst_addr, uri); + return -1; } int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) diff --git a/net/wget.c b/net/wget.c index c73836cbc9d..3c0fff488eb 100644 --- a/net/wget.c +++ b/net/wget.c @@ -59,8 +59,10 @@ static inline int store_block(uchar *src, unsigned int offset, unsigned int len) if (CONFIG_IS_ENABLED(LMB) && wget_info->set_bootdev) { if (store_addr < image_load_addr || lmb_read_check(store_addr, len)) { - printf("\nwget error: "); - printf("trying to overwrite reserved memory...\n"); + if (!wget_info->silent) { + printf("\nwget error: "); + printf("trying to overwrite reserved memory\n"); + } return -1; } } @@ -76,6 +78,9 @@ static void show_block_marker(u32 packets) { int cnt; + if (wget_info->silent) + return; + if (content_length != -1) { if (net_boot_file_size > content_length) content_length = net_boot_file_size; @@ -101,11 +106,15 @@ static void tcp_stream_on_closed(struct tcp_stream *tcp) net_set_state(wget_loop_state); if (wget_loop_state != NETLOOP_SUCCESS) { net_boot_file_size = 0; - printf("\nwget: Transfer Fail, TCP status - %d\n", tcp->status); + if (!wget_info->silent) + printf("\nwget: Transfer Fail, TCP status - %d\n", + tcp->status); return; } - printf("\nPackets received %d, Transfer Successful\n", tcp->rx_packets); + if (!wget_info->silent) + printf("\nPackets received %d, Transfer Successful\n", + tcp->rx_packets); wget_info->file_size = net_boot_file_size; if (wget_info->method == WGET_HTTP_METHOD_GET && wget_info->set_bootdev) { efi_set_bootdev("Http", NULL, image_url, @@ -139,7 +148,8 @@ static void tcp_stream_on_rcv_nxt_update(struct tcp_stream *tcp, u32 rx_bytes) tcp->state == TCP_ESTABLISHED) goto end; - printf("ERROR: misssed HTTP header\n"); + if (!wget_info->silent) + printf("ERROR: misssed HTTP header\n"); tcp_stream_close(tcp); goto end; } @@ -346,7 +356,8 @@ void wget_start(void) tcp_stream_set_on_create_handler(tcp_stream_on_create); tcp = tcp_stream_connect(web_server_ip, server_port); if (!tcp) { - printf("No free tcp streams\n"); + if (!wget_info->silent) + printf("No free tcp streams\n"); net_set_state(NETLOOP_FAIL); return; } diff --git a/test/lib/efi_device_path.c b/test/lib/efi_device_path.c index 5cc001e209e..5a358ddcb93 100644 --- a/test/lib/efi_device_path.c +++ b/test/lib/efi_device_path.c @@ -5,6 +5,7 @@ * Copyright (c) 2020 Heinrich Schuchardt <xypron.glpk@gmx.de> */ +#include <efi_device_path.h> #include <efi_loader.h> #include <test/lib.h> #include <test/test.h> diff --git a/test/py/conftest.py b/test/py/conftest.py index 5aea85647af..6c3ac67979a 100644 --- a/test/py/conftest.py +++ b/test/py/conftest.py @@ -711,9 +711,13 @@ def setup_buildconfigspec(item): """ for options in item.iter_markers('buildconfigspec'): - option = options.args[0] - if not ubconfig.buildconfig.get('config_' + option.lower(), None): - pytest.skip('.config feature "%s" not enabled' % option.lower()) + nomatch = True + for arg in options.args: + if ubconfig.buildconfig.get('config_' + arg.lower(), None): + nomatch = False + if nomatch: + argsString = ', '.join(options.args) + pytest.skip(f'.config features "{argsString}" not enabled') for options in item.iter_markers('notbuildconfigspec'): option = options.args[0] if ubconfig.buildconfig.get('config_' + option.lower(), None): diff --git a/test/py/tests/test_efi_loader.py b/test/py/tests/test_efi_loader.py index 91f151d09cd..dc58c0d4dbd 100644 --- a/test/py/tests/test_efi_loader.py +++ b/test/py/tests/test_efi_loader.py @@ -98,7 +98,7 @@ def test_efi_setup_dhcp(ubman): global net_set_up net_set_up = True -@pytest.mark.buildconfigspec('net') +@pytest.mark.buildconfigspec('net', 'net_lwip') def test_efi_setup_static(ubman): """Set up the network using a static IP configuration. diff --git a/test/py/tests/test_fpga.py b/test/py/tests/test_fpga.py index 74cd42b910e..299a8653f74 100644 --- a/test/py/tests/test_fpga.py +++ b/test/py/tests/test_fpga.py @@ -506,7 +506,7 @@ def test_fpga_loadfs(ubman): @pytest.mark.buildconfigspec('cmd_fpga_load_secure') @pytest.mark.buildconfigspec('cmd_net') @pytest.mark.buildconfigspec('cmd_dhcp') -@pytest.mark.buildconfigspec('net') +@pytest.mark.buildconfigspec('net', 'net_lwip') def test_fpga_secure_bit_auth(ubman): test_net.test_net_dhcp(ubman) @@ -534,7 +534,7 @@ def test_fpga_secure_bit_auth(ubman): @pytest.mark.buildconfigspec('cmd_fpga_load_secure') @pytest.mark.buildconfigspec('cmd_net') @pytest.mark.buildconfigspec('cmd_dhcp') -@pytest.mark.buildconfigspec('net') +@pytest.mark.buildconfigspec('net', 'net_lwip') def test_fpga_secure_bit_img_auth_kup(ubman): test_net.test_net_dhcp(ubman) diff --git a/test/py/tests/test_net.py b/test/py/tests/test_net.py index 27cdd73fd49..6ef02e53389 100644 --- a/test/py/tests/test_net.py +++ b/test/py/tests/test_net.py @@ -201,7 +201,7 @@ def test_net_dhcp6(ubman): global net6_set_up net6_set_up = True -@pytest.mark.buildconfigspec('net') +@pytest.mark.buildconfigspec('net', 'net_lwip') def test_net_setup_static(ubman): """Set up a static IP configuration. |