diff options
101 files changed, 2511 insertions, 461 deletions
@@ -3,7 +3,7 @@ VERSION = 2025 PATCHLEVEL = 04 SUBLEVEL = -EXTRAVERSION = -rc4 +EXTRAVERSION = -rc5 NAME = # *DOCUMENTATION* diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index cf08fe63f1e..32b80da9869 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1117,6 +1117,8 @@ config ARCH_SNAPDRAGON select OF_BOARD select SAVE_PREV_BL_FDT_ADDR select LINUX_KERNEL_IMAGE_HEADER if !ENABLE_ARM_SOC_BOOT0_HOOK + select SYSRESET + select SYSRESET_PSCI imply OF_UPSTREAM imply CMD_DM diff --git a/arch/arm/dts/ipq9574-rdp433-u-boot.dtsi b/arch/arm/dts/ipq9574-rdp433-u-boot.dtsi new file mode 100644 index 00000000000..390e2338d65 --- /dev/null +++ b/arch/arm/dts/ipq9574-rdp433-u-boot.dtsi @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/ { + /* Will be removed when SMEM parsing is updated */ + memory@40000000 { + device_type = "memory"; + reg = <0x0 0x40000000 0x0 0x40000000>, + <0x0 0x4a500000 0x0 0x00100000>; + }; +}; + +&sdhc_1 { + sdhci-caps-mask = <0x0 0x04000000>; + sdhci-caps = <0x0 0x04000000>; /* SDHCI_CAN_VDD_180 */ + + /* + * This reset is needed to clear out the settings done by + * previous boot loader. Without this the SDHCI_RESET_ALL + * reset done sdhci_init() times out. + */ + resets = <&gcc GCC_SDCC_BCR>; +}; diff --git a/arch/arm/dts/r8a779g0-u-boot.dtsi b/arch/arm/dts/r8a779g0-u-boot.dtsi index 10051c9dbfe..cc9d99b0f34 100644 --- a/arch/arm/dts/r8a779g0-u-boot.dtsi +++ b/arch/arm/dts/r8a779g0-u-boot.dtsi @@ -147,6 +147,10 @@ bootph-all; }; +&otp { + bootph-all; +}; + &pfc { bootph-all; }; diff --git a/arch/arm/lib/crt0_aarch64_efi.S b/arch/arm/lib/crt0_aarch64_efi.S index e21b54fdbcb..003d5f83041 100644 --- a/arch/arm/lib/crt0_aarch64_efi.S +++ b/arch/arm/lib/crt0_aarch64_efi.S @@ -144,6 +144,7 @@ section_table: IMAGE_SCN_CNT_INITIALIZED_DATA) .align 12 + .globl _start _start: stp x29, x30, [sp, #-32]! mov x29, sp diff --git a/arch/arm/lib/crt0_arm_efi.S b/arch/arm/lib/crt0_arm_efi.S index 91b0fe12c51..1e7de5c3343 100644 --- a/arch/arm/lib/crt0_arm_efi.S +++ b/arch/arm/lib/crt0_arm_efi.S @@ -143,6 +143,7 @@ section_table: IMAGE_SCN_CNT_INITIALIZED_DATA) .align 12 + .globl _start _start: stmfd sp!, {r0-r2, lr} diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c index 2ef936aab75..deae4d32378 100644 --- a/arch/arm/mach-snapdragon/board.c +++ b/arch/arm/mach-snapdragon/board.c @@ -88,7 +88,29 @@ int dram_init_banksize(void) return 0; } -static void qcom_parse_memory(const void *fdt) +/** + * The generic memory parsing code in U-Boot lacks a few things that we + * need on Qualcomm: + * + * 1. It sets gd->ram_size and gd->ram_base to represent a single memory block + * 2. setup_dest_addr() later relocates U-Boot to ram_base + ram_size, the end + * of that first memory block. + * + * This results in all memory beyond U-Boot being unusable in Linux when booting + * with EFI. + * + * Since the ranges in the memory node may be out of order, the only way for us + * to correctly determine the relocation address for U-Boot is to parse all + * memory regions and find the highest valid address. + * + * We can't use fdtdec_setup_memory_banksize() since it stores the result in + * gd->bd, which is not yet allocated. + * + * @fdt: FDT blob to parse /memory node from + * + * Return: 0 on success or -ENODATA if /memory node is missing or incomplete + */ +static int qcom_parse_memory(const void *fdt) { int offset; const fdt64_t *memory; @@ -97,16 +119,12 @@ static void qcom_parse_memory(const void *fdt) int i, j, banks; offset = fdt_path_offset(fdt, "/memory"); - if (offset < 0) { - log_err("No memory node found in device tree!\n"); - return; - } + if (offset < 0) + return -ENODATA; memory = fdt_getprop(fdt, offset, "reg", &memsize); - if (!memory) { - log_err("No memory configuration was provided by the previous bootloader!\n"); - return; - } + if (!memory) + return -ENODATA; banks = min(memsize / (2 * sizeof(u64)), (ulong)CONFIG_NR_DRAM_BANKS); @@ -119,7 +137,6 @@ static void qcom_parse_memory(const void *fdt) for (i = 0, j = 0; i < banks * 2; i += 2, j++) { prevbl_ddr_banks[j].start = get_unaligned_be64(&memory[i]); prevbl_ddr_banks[j].size = get_unaligned_be64(&memory[i + 1]); - /* SM8650 boards sometimes have empty regions! */ if (!prevbl_ddr_banks[j].size) { j--; continue; @@ -127,13 +144,16 @@ static void qcom_parse_memory(const void *fdt) ram_end = max(ram_end, prevbl_ddr_banks[j].start + prevbl_ddr_banks[j].size); } + if (!banks || !prevbl_ddr_banks[0].size) + return -ENODATA; + /* Sort our RAM banks -_- */ qsort(prevbl_ddr_banks, banks, sizeof(prevbl_ddr_banks[0]), ddr_bank_cmp); gd->ram_base = prevbl_ddr_banks[0].start; gd->ram_size = ram_end - gd->ram_base; - debug("ram_base = %#011lx, ram_size = %#011llx, ram_end = %#011llx\n", - gd->ram_base, gd->ram_size, ram_end); + + return 0; } static void show_psci_version(void) @@ -142,24 +162,56 @@ static void show_psci_version(void) arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res); + /* Some older SoCs like MSM8916 don't always support PSCI */ + if ((int)res.a0 == PSCI_RET_NOT_SUPPORTED) + return; + debug("PSCI: v%ld.%ld\n", PSCI_VERSION_MAJOR(res.a0), PSCI_VERSION_MINOR(res.a0)); } +/** + * Most MSM8916 devices in the wild shipped without PSCI support, but the + * upstream DTs pretend that PSCI exists. If that situation is detected here, + * the /psci node is deleted. This is done very early to ensure the PSCI + * firmware driver doesn't bind (which then binds a sysreset driver that won't + * work). + */ +static void qcom_psci_fixup(void *fdt) +{ + int offset, ret; + struct arm_smccc_res res; + + arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res); + + if ((int)res.a0 != PSCI_RET_NOT_SUPPORTED) + return; + + offset = fdt_path_offset(fdt, "/psci"); + if (offset < 0) + return; + + debug("Found /psci DT node on device with no PSCI. Deleting.\n"); + ret = fdt_del_node(fdt, offset); + if (ret) + log_err("Failed to delete /psci node: %d\n", ret); +} + /* We support booting U-Boot with an internal DT when running as a first-stage bootloader * or for supporting quirky devices where it's easier to leave the downstream DT in place * to improve ABL compatibility. Otherwise, we use the DT provided by ABL. */ int board_fdt_blob_setup(void **fdtp) { - struct fdt_header *fdt; + struct fdt_header *external_fdt, *internal_fdt; bool internal_valid, external_valid; - int ret = 0; + int ret = -ENODATA; - fdt = (struct fdt_header *)get_prev_bl_fdt_addr(); - external_valid = fdt && !fdt_check_header(fdt); - internal_valid = !fdt_check_header(*fdtp); + internal_fdt = (struct fdt_header *)*fdtp; + external_fdt = (struct fdt_header *)get_prev_bl_fdt_addr(); + external_valid = external_fdt && !fdt_check_header(external_fdt); + internal_valid = !fdt_check_header(internal_fdt); /* * There is no point returning an error here, U-Boot can't do anything useful in this situation. @@ -167,31 +219,42 @@ int board_fdt_blob_setup(void **fdtp) */ if (!internal_valid && !external_valid) panic("Internal FDT is invalid and no external FDT was provided! (fdt=%#llx)\n", - (phys_addr_t)fdt); + (phys_addr_t)external_fdt); + + /* Prefer memory information from internal DT if it's present */ + if (internal_valid) + ret = qcom_parse_memory(internal_fdt); + + if (ret < 0 && external_valid) { + /* No internal FDT or it lacks a proper /memory node. + * The previous bootloader handed us something, let's try that. + */ + if (internal_valid) + debug("No memory info in internal FDT, falling back to external\n"); + + ret = qcom_parse_memory(external_fdt); + } + + if (ret < 0) + panic("No valid memory ranges found!\n"); + + debug("ram_base = %#011lx, ram_size = %#011llx\n", + gd->ram_base, gd->ram_size); if (internal_valid) { debug("Using built in FDT\n"); ret = -EEXIST; } else { debug("Using external FDT\n"); - /* So we can use it before returning */ - *fdtp = fdt; + *fdtp = external_fdt; + ret = 0; } - /* - * Parse the /memory node while we're here, - * this makes it easy to do other things early. - */ - qcom_parse_memory(*fdtp); + qcom_psci_fixup(*fdtp); return ret; } -void reset_cpu(void) -{ - psci_system_reset(); -} - /* * Some Qualcomm boards require GPIO configuration when switching USB modes. * Support setting this configuration via pinctrl state. diff --git a/arch/riscv/cpu/k1/Kconfig b/arch/riscv/cpu/k1/Kconfig index d9cd8dce964..14201df80f2 100644 --- a/arch/riscv/cpu/k1/Kconfig +++ b/arch/riscv/cpu/k1/Kconfig @@ -13,6 +13,7 @@ config SPACEMIT_K1 imply RISCV_ACLINT if RISCV_MMODE imply SPL_RISCV_ACLINT if SPL_RISCV_MMODE imply CMD_CPU + imply DM_RESET imply SPL_CPU imply SPL_OPENSBI imply SPL_LOAD_FIT diff --git a/arch/riscv/dts/binman.dtsi b/arch/riscv/dts/binman.dtsi index 0405faca574..ceb916b74a7 100644 --- a/arch/riscv/dts/binman.dtsi +++ b/arch/riscv/dts/binman.dtsi @@ -82,8 +82,9 @@ }; }; -#ifndef CONFIG_OF_BOARD +#if !defined(CONFIG_OF_BOARD) || defined(CONFIG_MULTI_DTB_FIT) @fdt-SEQ { + fit,operation = "gen-fdt-nodes"; description = "NAME"; type = "flat_dt"; compression = "none"; @@ -92,9 +93,12 @@ }; configurations { + +#ifndef CONFIG_MULTI_DTB_FIT default = "conf-1"; +#endif -#ifndef CONFIG_OF_BOARD +#if !defined(CONFIG_OF_BOARD) || defined(CONFIG_MULTI_DTB_FIT) @conf-SEQ { #else conf-1 { @@ -115,7 +119,7 @@ #endif #endif /* CONFIG_OPTEE */ -#ifndef CONFIG_OF_BOARD +#if !defined(CONFIG_OF_BOARD) || defined(CONFIG_MULTI_DTB_FIT) fdt = "fdt-SEQ"; #endif }; diff --git a/arch/riscv/dts/cv18xx.dtsi b/arch/riscv/dts/cv18xx.dtsi index 8a7386b76e6..6fac247e7ac 100644 --- a/arch/riscv/dts/cv18xx.dtsi +++ b/arch/riscv/dts/cv18xx.dtsi @@ -46,20 +46,6 @@ #clock-cells = <0>; }; - eth_csrclk: eth-csrclk { - compatible = "fixed-clock"; - clock-frequency = <250000000>; - clock-output-names = "eth_csrclk"; - #clock-cells = <0x0>; - }; - - eth_ptpclk: eth-ptpclk { - compatible = "fixed-clock"; - clock-frequency = <50000000>; - clock-output-names = "eth_ptpclk"; - #clock-cells = <0x0>; - }; - soc { compatible = "simple-bus"; interrupt-parent = <&plic>; diff --git a/arch/riscv/dts/k1.dtsi b/arch/riscv/dts/k1.dtsi index 514be453dba..7c0f1b928e2 100644 --- a/arch/riscv/dts/k1.dtsi +++ b/arch/riscv/dts/k1.dtsi @@ -327,7 +327,7 @@ ranges; uart0: serial@d4017000 { - compatible = "spacemit,k1-uart", "snps,dw-apb-uart"; + compatible = "spacemit,k1-uart", "intel,xscale-uart"; reg = <0x0 0xd4017000 0x0 0x100>; interrupts = <42>; clock-frequency = <14857000>; @@ -337,7 +337,7 @@ }; uart2: serial@d4017100 { - compatible = "spacemit,k1-uart", "snps,dw-apb-uart"; + compatible = "spacemit,k1-uart", "intel,xscale-uart"; reg = <0x0 0xd4017100 0x0 0x100>; interrupts = <44>; clock-frequency = <14857000>; @@ -347,7 +347,7 @@ }; uart3: serial@d4017200 { - compatible = "spacemit,k1-uart", "snps,dw-apb-uart"; + compatible = "spacemit,k1-uart", "intel,xscale-uart"; reg = <0x0 0xd4017200 0x0 0x100>; interrupts = <45>; clock-frequency = <14857000>; @@ -357,7 +357,7 @@ }; uart4: serial@d4017300 { - compatible = "spacemit,k1-uart", "snps,dw-apb-uart"; + compatible = "spacemit,k1-uart", "intel,xscale-uart"; reg = <0x0 0xd4017300 0x0 0x100>; interrupts = <46>; clock-frequency = <14857000>; @@ -367,7 +367,7 @@ }; uart5: serial@d4017400 { - compatible = "spacemit,k1-uart", "snps,dw-apb-uart"; + compatible = "spacemit,k1-uart", "intel,xscale-uart"; reg = <0x0 0xd4017400 0x0 0x100>; interrupts = <47>; clock-frequency = <14857000>; @@ -377,7 +377,7 @@ }; uart6: serial@d4017500 { - compatible = "spacemit,k1-uart", "snps,dw-apb-uart"; + compatible = "spacemit,k1-uart", "intel,xscale-uart"; reg = <0x0 0xd4017500 0x0 0x100>; interrupts = <48>; clock-frequency = <14857000>; @@ -387,7 +387,7 @@ }; uart7: serial@d4017600 { - compatible = "spacemit,k1-uart", "snps,dw-apb-uart"; + compatible = "spacemit,k1-uart", "intel,xscale-uart"; reg = <0x0 0xd4017600 0x0 0x100>; interrupts = <49>; clock-frequency = <14857000>; @@ -397,7 +397,7 @@ }; uart8: serial@d4017700 { - compatible = "spacemit,k1-uart", "snps,dw-apb-uart"; + compatible = "spacemit,k1-uart", "intel,xscale-uart"; reg = <0x0 0xd4017700 0x0 0x100>; interrupts = <50>; clock-frequency = <14857000>; @@ -407,7 +407,7 @@ }; uart9: serial@d4017800 { - compatible = "spacemit,k1-uart", "snps,dw-apb-uart"; + compatible = "spacemit,k1-uart", "intel,xscale-uart"; reg = <0x0 0xd4017800 0x0 0x100>; interrupts = <51>; clock-frequency = <14857000>; @@ -447,7 +447,7 @@ }; sec_uart1: serial@f0612000 { - compatible = "spacemit,k1-uart", "snps,dw-apb-uart"; + compatible = "spacemit,k1-uart", "intel,xscale-uart"; reg = <0x0 0xf0612000 0x0 0x100>; interrupts = <43>; clock-frequency = <14857000>; @@ -455,5 +455,20 @@ reg-io-width = <4>; status = "reserved"; /* for TEE usage */ }; + + reset: reset-controller@d4050000 { + compatible = "spacemit,k1-reset"; + reg = <0x0 0xd4050000 0x0 0x209c>, + <0x0 0xd4282800 0x0 0x400>, + <0x0 0xd4015000 0x0 0x1000>, + <0x0 0xd4090000 0x0 0x1000>, + <0x0 0xd4282c00 0x0 0x400>, + <0x0 0xd8440000 0x0 0x98>, + <0x0 0xc0000000 0x0 0x4280>, + <0x0 0xf0610000 0x0 0x20>; + reg-names = "mpmu", "apmu", "apbc", "apbs", "ciu", "dciu", "ddrc", "apbc2"; + #reset-cells = <1>; + status = "disabled"; + }; }; };
\ No newline at end of file diff --git a/arch/riscv/dts/starfive-visionfive2-binman.dtsi b/arch/riscv/dts/starfive-visionfive2-binman.dtsi index 4cce001e80d..05787bdb92d 100644 --- a/arch/riscv/dts/starfive-visionfive2-binman.dtsi +++ b/arch/riscv/dts/starfive-visionfive2-binman.dtsi @@ -13,82 +13,6 @@ }; &binman { - itb { - fit { - images { - fdt-jh7110-milkv-mars { - description = "jh7110-milkv-mars"; - load = <0x40400000>; - compression = "none"; - - blob-ext { - filename = "dts/upstream/src/riscv/starfive/jh7110-milkv-mars.dtb"; - }; - }; - - fdt-jh7110-pine64-star64 { - description = "jh7110-pine64-star64"; - load = <0x40400000>; - compression = "none"; - - blob-ext { - filename = "dts/upstream/src/riscv/starfive/jh7110-pine64-star64.dtb"; - }; - }; - - fdt-jh7110-starfive-visionfive-2-v1.2a { - description = "jh7110-starfive-visionfive-2-v1.2a"; - load = <0x40400000>; - compression = "none"; - - blob-ext { - filename = "dts/upstream/src/riscv/starfive/jh7110-starfive-visionfive-2-v1.2a.dtb"; - }; - }; - - fdt-jh7110-starfive-visionfive-2-v1.3b { - description = "jh7110-starfive-visionfive-2-v1.3b"; - load = <0x40400000>; - compression = "none"; - - blob-ext { - filename = "dts/upstream/src/riscv/starfive/jh7110-starfive-visionfive-2-v1.3b.dtb"; - }; - }; - }; - - configurations { - conf-jh7110-milkv-mars { - description = "jh7110-milkv-mars"; - firmware = "opensbi"; - loadables = "uboot"; - fdt = "fdt-jh7110-milkv-mars"; - }; - - conf-jh7110-pine64-star64 { - description = "jh7110-pine64-star64"; - firmware = "opensbi"; - loadables = "uboot"; - fdt = "fdt-jh7110-pine64-star64"; - }; - - conf-jh7110-starfive-visionfive-2-v1.2a { - description = "jh7110-starfive-visionfive-2-v1.2a"; - firmware = "opensbi"; - loadables = "uboot"; - fdt = "fdt-jh7110-starfive-visionfive-2-v1.2a"; - }; - - conf-jh7110-starfive-visionfive-2-v1.3b { - description = "jh7110-starfive-visionfive-2-v1.3b"; - firmware = "opensbi"; - loadables = "uboot"; - fdt = "fdt-jh7110-starfive-visionfive-2-v1.3b"; - }; - }; - }; - }; - spl-img { filename = "spl/u-boot-spl.bin.normal.out"; diff --git a/arch/riscv/lib/crt0_riscv_efi.S b/arch/riscv/lib/crt0_riscv_efi.S index 9eacbe4a859..f170e4b26d6 100644 --- a/arch/riscv/lib/crt0_riscv_efi.S +++ b/arch/riscv/lib/crt0_riscv_efi.S @@ -179,6 +179,7 @@ section_table: IMAGE_SCN_CNT_INITIALIZED_DATA) .align 12 + .globl _start _start: addi sp, sp, -(SIZE_LONG * 3) SAVE_LONG(a0, 0) diff --git a/board/emulation/qemu-riscv/Kconfig b/board/emulation/qemu-riscv/Kconfig index 012ac14a123..134dbfd7151 100644 --- a/board/emulation/qemu-riscv/Kconfig +++ b/board/emulation/qemu-riscv/Kconfig @@ -62,6 +62,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply VIDEO_SIMPLE imply PCIE_ECAM_GENERIC imply DM_RNG + imply RNG_RISCV_ZKR imply DM_RTC imply RTC_GOLDFISH imply SCSI diff --git a/board/renesas/common/Makefile b/board/renesas/common/Makefile index 347be5cc93c..5e51b691178 100644 --- a/board/renesas/common/Makefile +++ b/board/renesas/common/Makefile @@ -1,6 +1,4 @@ # -# board/renesas/whitehawk/Makefile -# # Copyright (C) 2024 Marek Vasut <marek.vasut+renesas@mailbox.org> # # SPDX-License-Identifier: GPL-2.0+ diff --git a/board/renesas/common/gen4-common.c b/board/renesas/common/gen4-common.c index 52a0639073b..f7d129be4c8 100644 --- a/board/renesas/common/gen4-common.c +++ b/board/renesas/common/gen4-common.c @@ -7,11 +7,13 @@ #include <asm/arch/renesas.h> #include <asm/arch/sys_proto.h> +#include <asm/armv8/mmu.h> #include <asm/global_data.h> #include <asm/io.h> #include <asm/mach-types.h> #include <asm/processor.h> #include <asm/system.h> +#include <image.h> #include <linux/errno.h> #define RST_BASE 0xE6160000 /* Domain0 */ @@ -88,3 +90,127 @@ int ft_board_setup(void *blob, struct bd_info *bd) { return 0; } + +/* R-Car Gen4 TFA BL31 handoff structure and handling. */ +struct param_header { + u8 type; + u8 version; + u16 size; + u32 attr; +}; + +struct tfa_image_info { + struct param_header h; + uintptr_t image_base; + u32 image_size; + u32 image_max_size; +}; + +struct aapcs64_params { + u64 arg0; + u64 arg1; + u64 arg2; + u64 arg3; + u64 arg4; + u64 arg5; + u64 arg6; + u64 arg7; +}; + +struct entry_point_info { + struct param_header h; + uintptr_t pc; + u32 spsr; + struct aapcs64_params args; +}; + +struct bl2_to_bl31_params_mem { + struct tfa_image_info bl32_image_info; + struct tfa_image_info bl33_image_info; + struct entry_point_info bl33_ep_info; + struct entry_point_info bl32_ep_info; +}; + +/* Default jump address, return to U-Boot */ +#define BL33_BASE 0x44100000 +/* Custom parameters address passed to TFA by ICUMXA loader */ +#define PARAMS_BASE 0x46422200 + +/* Usually such a structure is produced by ICUMXA and passed in at 0x46422200 */ +static const struct bl2_to_bl31_params_mem blinfo_template = { + .bl33_ep_info.h.type = 1, /* PARAM_EP */ + .bl33_ep_info.h.version = 2, /* Version 2 */ + .bl33_ep_info.h.size = sizeof(struct entry_point_info), + .bl33_ep_info.h.attr = 0x81, /* Executable | Non-Secure */ + .bl33_ep_info.spsr = 0x2c9, /* Mode=EL2, SP=ELX, Exceptions=OFF */ + .bl33_ep_info.pc = BL33_BASE, + + .bl33_image_info.h.type = 1, /* PARAM_EP */ + .bl33_image_info.h.version = 2, /* Version 2 */ + .bl33_image_info.h.size = sizeof(struct image_info), + .bl33_image_info.h.attr = 0, + .bl33_image_info.image_base = BL33_BASE, +}; + +static bool tfa_bl31_image_loaded; +static ulong tfa_bl31_image_addr; + +static void tfa_bl31_image_process(ulong image, size_t size) +{ + /* Custom parameters address passed to TFA by ICUMXA loader */ + struct bl2_to_bl31_params_mem *blinfo = (struct bl2_to_bl31_params_mem *)PARAMS_BASE; + + /* Not in EL3, do nothing. */ + if (current_el() != 3) + return; + + /* Clear a page and copy template */ + memset((void *)PARAMS_BASE, 0, PAGE_SIZE); + memcpy(blinfo, &blinfo_template, sizeof(*blinfo)); + tfa_bl31_image_addr = image; + tfa_bl31_image_loaded = true; +} + +U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_TFA_BL31, tfa_bl31_image_process); + +void armv8_switch_to_el2_prep(u64 args, u64 mach_nr, u64 fdt_addr, + u64 arg4, u64 entry_point, u64 es_flag) +{ + typedef void __noreturn (*image_entry_noargs_t)(void); + image_entry_noargs_t image_entry = + (image_entry_noargs_t)(void *)tfa_bl31_image_addr; + struct bl2_to_bl31_params_mem *blinfo = + (struct bl2_to_bl31_params_mem *)PARAMS_BASE; + + /* Not in EL3, do nothing. */ + if (current_el() != 3) + return; + + /* + * Destination address in arch/arm/cpu/armv8/transition.S + * right past the first bl in armv8_switch_to_el2() to let + * the rest of U-Boot pre-Linux code run. The code does run + * without stack pointer! + */ + const u64 ep = ((u64)(uintptr_t)&armv8_switch_to_el2) + 4; + + /* If TFA BL31 was not part of the fitImage, do regular boot. */ + if (!tfa_bl31_image_loaded) + return; + + /* + * Set up kernel entry point and parameters: + * x0 is FDT address, x1..x3 must be 0 + */ + blinfo->bl33_ep_info.pc = ep; + blinfo->bl33_ep_info.args.arg0 = args; + blinfo->bl33_ep_info.args.arg1 = mach_nr; + blinfo->bl33_ep_info.args.arg2 = fdt_addr; + blinfo->bl33_ep_info.args.arg3 = arg4; + blinfo->bl33_ep_info.args.arg4 = entry_point; + blinfo->bl33_ep_info.args.arg5 = es_flag; + blinfo->bl33_image_info.image_base = ep; + + /* Jump to TFA BL31 */ + image_entry(); +} diff --git a/board/renesas/common/gen4-spl.c b/board/renesas/common/gen4-spl.c index e46ef0a3075..ebfefab7253 100644 --- a/board/renesas/common/gen4-spl.c +++ b/board/renesas/common/gen4-spl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * R-Car Gen4 Cortex-R52 SPL + * R-Car Gen4 SPL * * Copyright (C) 2024 Marek Vasut <marek.vasut+renesas@mailbox.org> */ diff --git a/board/starfive/visionfive2/spl.c b/board/starfive/visionfive2/spl.c index 1538d6aec73..13a48939c8f 100644 --- a/board/starfive/visionfive2/spl.c +++ b/board/starfive/visionfive2/spl.c @@ -121,6 +121,10 @@ int board_fit_config_name_match(const char *name) product_id = get_product_id_from_eeprom(); + /* Strip off prefix */ + if (strncmp(name, "starfive/", 9)) + return -EINVAL; + name += 9; if (!strncmp(product_id, "VF7110", 6)) { version = get_pcb_revision_from_eeprom(); if ((version == 'b' || version == 'B') && diff --git a/board/toradex/verdin-am62/verdin-am62.c b/board/toradex/verdin-am62/verdin-am62.c index a1c471111a0..7b2eecbf659 100644 --- a/board/toradex/verdin-am62/verdin-am62.c +++ b/board/toradex/verdin-am62/verdin-am62.c @@ -112,13 +112,6 @@ int board_late_init(void) #define CORE_VOLTAGE 0x80000000 #define MCU_CTRL_LFXOSC_32K_BYPASS_VAL BIT(4) -#if IS_ENABLED(CONFIG_XPL_BUILD) -void spl_perform_fixups(struct spl_image_info *spl_image) -{ - fixup_memory_node(spl_image); -} -#endif - #ifdef CONFIG_SPL_BOARD_INIT void spl_board_init(void) { diff --git a/cmd/version.c b/cmd/version.c index 53db1a0b6bd..62406608eb0 100644 --- a/cmd/version.c +++ b/cmd/version.c @@ -6,6 +6,7 @@ #include <command.h> #include <display_options.h> +#include <version.h> #include <version_string.h> #include <linux/compiler.h> #ifdef CONFIG_SYS_COREBOOT diff --git a/configs/bananapi-f3_defconfig b/configs/bananapi-f3_defconfig index 0f12db3db84..7483f128bae 100644 --- a/configs/bananapi-f3_defconfig +++ b/configs/bananapi-f3_defconfig @@ -18,3 +18,4 @@ CONFIG_HUSH_PARSER=y CONFIG_ENV_OVERWRITE=y CONFIG_SYS_NS16550=y CONFIG_SYS_NS16550_MEM32=y +CONFIG_RESET_SPACEMIT_K1=y diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig index 661a484f7bf..ba4d38d100e 100644 --- a/configs/qcom_defconfig +++ b/configs/qcom_defconfig @@ -97,6 +97,7 @@ CONFIG_PINCTRL_QCOM_APQ8016=y CONFIG_PINCTRL_QCOM_APQ8096=y CONFIG_PINCTRL_QCOM_QCM2290=y CONFIG_PINCTRL_QCOM_QCS404=y +CONFIG_PINCTRL_QCOM_SC7280=y CONFIG_PINCTRL_QCOM_SDM845=y CONFIG_PINCTRL_QCOM_SM6115=y CONFIG_PINCTRL_QCOM_SM8150=y @@ -120,6 +121,7 @@ CONFIG_QCOM_RPMH=y CONFIG_SPMI_MSM=y CONFIG_SYSINFO=y CONFIG_SYSINFO_SMBIOS=y +CONFIG_SYSRESET_QCOM_PSHOLD=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y diff --git a/configs/qcom_ipq9574_mmc_defconfig b/configs/qcom_ipq9574_mmc_defconfig new file mode 100644 index 00000000000..9bc1e1c70b7 --- /dev/null +++ b/configs/qcom_ipq9574_mmc_defconfig @@ -0,0 +1,83 @@ +CONFIG_ARM=y +CONFIG_SKIP_LOWLEVEL_INIT=y +CONFIG_POSITION_INDEPENDENT=y +CONFIG_SYS_INIT_SP_BSS_OFFSET=1572864 +CONFIG_ARCH_SNAPDRAGON=y +CONFIG_NR_DRAM_BANKS=24 +CONFIG_DEFAULT_DEVICE_TREE="qcom/ipq9574-rdp433" +CONFIG_SYS_LOAD_ADDR=0x50000000 +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +# CONFIG_EFI_LOADER is not set +# CONFIG_EFI_BINARY_EXEC is not set +# CONFIG_EFI_VARIABLE_FILE_STORE is not set +# CONFIG_PXE_UTILS is not set +# CONFIG_BOOTSTD is not set +# CONFIG_BOOTMETH_VBE is not set +CONFIG_BOOTDELAY=2 +CONFIG_OF_BOARD_SETUP=y +CONFIG_USE_PREBOOT=y +CONFIG_SYS_CBSIZE=512 +CONFIG_LOG_MAX_LEVEL=9 +CONFIG_LOG_DEFAULT_LEVEL=4 +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_CMD_MMC=y +CONFIG_CMD_USB=y +CONFIG_CMD_PART=y +CONFIG_OF_LIVE=y +CONFIG_USE_DEFAULT_ENV_FILE=y +CONFIG_DEFAULT_ENV_FILE="board/qualcomm/default.env" +CONFIG_CLK=y +CONFIG_CLK_QCOM_IPQ9574=y +CONFIG_DFU_MMC=y +CONFIG_DFU_SCSI=y +CONFIG_SYS_DFU_DATA_BUF_SIZE=0x200000 +CONFIG_MSM_GPIO=y +CONFIG_PINCTRL=y +CONFIG_PINCONF=y +CONFIG_PINCTRL_QCOM_IPQ9574=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_ADMA=y +CONFIG_MMC_SDHCI_MSM=y +CONFIG_DM_MDIO=y +CONFIG_DM_ETH_PHY=y +CONFIG_DWC_ETH_QOS=y +CONFIG_DWC_ETH_QOS_QCOM=y +CONFIG_RGMII=y +CONFIG_PHY=y +CONFIG_PHY_QCOM_QMP_UFS=y +CONFIG_PHY_QCOM_QUSB2=y +CONFIG_SCSI=y +CONFIG_MSM_SERIAL=y +CONFIG_MSM_GENI_SERIAL=y +CONFIG_SOC_QCOM=y +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_ANNOUNCE=y +CONFIG_DEBUG_UART_BASE=0x78b1000 +CONFIG_DEBUG_UART_MSM=y +CONFIG_DEBUG_UART_CLOCK=1843200 +CONFIG_TEXT_BASE=0x4A240000 +CONFIG_REMAKE_ELF=y +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_BOOTSTD_FULL=y +CONFIG_SYS_CBSIZE=1024 +CONFIG_SYS_PBSIZE=1024 +CONFIG_OF_LIVE=y +CONFIG_MSM_SERIAL=y +CONFIG_DM_EVENT=y +CONFIG_ENV_IS_IN_MMC=y +CONFIG_ENV_SIZE=0x40000 +CONFIG_ENV_OFFSET=0 +CONFIG_PARTITIONS=y +CONFIG_PARTITION_UUIDS=y +CONFIG_MTD=y +CONFIG_MTD_PARTS=y +CONFIG_HUSH_PARSER=y +CONFIG_PARTITIONS=y +CONFIG_EFI_PARTITION=y +# CONFIG_I2C is not set +# CONFIG_INPUT is not set +# CONFIG_SCSI is not set +# CONFIG_SPMI is not set diff --git a/configs/r8a779g0_whitehawk_defconfig b/configs/r8a779g0_whitehawk_defconfig index b49a81dcd49..8dcf8e35ee0 100644 --- a/configs/r8a779g0_whitehawk_defconfig +++ b/configs/r8a779g0_whitehawk_defconfig @@ -3,6 +3,8 @@ CONFIG_ARM=y CONFIG_ARCH_RENESAS=y CONFIG_RCAR_GEN4=y +CONFIG_ARM_SMCCC=y +CONFIG_ARMV8_PSCI=y CONFIG_ENV_SIZE=0x20000 CONFIG_ENV_OFFSET=0xFFFE0000 CONFIG_DEFAULT_DEVICE_TREE="renesas/r8a779g0-white-hawk" diff --git a/configs/renesas_rzg2l_smarc_defconfig b/configs/renesas_rzg2l_smarc_defconfig index 7a1224b3f07..b1d970b6b7e 100644 --- a/configs/renesas_rzg2l_smarc_defconfig +++ b/configs/renesas_rzg2l_smarc_defconfig @@ -26,6 +26,7 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_PART=y +CONFIG_CMD_USB=y CONFIG_CMD_PMIC=y CONFIG_CMD_EXT2=y CONFIG_CMD_EXT4=y @@ -54,5 +55,12 @@ CONFIG_PMIC_RAA215300=y CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_FIXED=y CONFIG_DM_REGULATOR_GPIO=y +CONFIG_RESET_RZG2L_USBPHY_CTRL=y CONFIG_SYSRESET=y CONFIG_SYSRESET_RAA215300=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_GENERIC=y +CONFIG_USB_STORAGE=y diff --git a/configs/sifive_unmatched_defconfig b/configs/sifive_unmatched_defconfig index 88a75c03259..f70e3db4441 100644 --- a/configs/sifive_unmatched_defconfig +++ b/configs/sifive_unmatched_defconfig @@ -27,7 +27,7 @@ CONFIG_FIT=y CONFIG_SPL_LOAD_FIT_ADDRESS=0x84000000 CONFIG_BOOTSTD_DEFAULTS=y CONFIG_USE_PREBOOT=y -CONFIG_PREBOOT="setenv fdt_addr ${fdtcontroladdr};fdt addr ${fdtcontroladdr};" +CONFIG_PREBOOT="setenv fdt_addr ${fdtcontroladdr};fdt addr ${fdtcontroladdr};nvme scan" CONFIG_DEFAULT_FDT_FILE="sifive/hifive-unmatched-a00.dtb" CONFIG_SYS_CBSIZE=256 CONFIG_SYS_PBSIZE=276 diff --git a/doc/README.bitbangMII b/doc/README.bitbangMII deleted file mode 100644 index 05ab20376f3..00000000000 --- a/doc/README.bitbangMII +++ /dev/null @@ -1,39 +0,0 @@ -This patch rewrites the miiphybb ( Bit-banged MII bus driver ) in order to -support an arbitrary number of mii buses. This feature is useful when your -board uses different mii buses for different phys and all (or a part) of these -buses are implemented via bit-banging mode. - -The driver requires that the following macros should be defined into the board -configuration file: - -CONFIG_BITBANGMII - Enable the miiphybb driver - -The board code needs to fill the bb_miiphy_buses[] array with a record for -each required bus and declare the bb_miiphy_buses_num variable with the -number of mii buses. The record (struct bb_miiphy_bus) has the following -fields/callbacks (see miiphy.h for details): - -char name[] - The symbolic name that must be equal to the MII bus - registered name -int (*init)() - Initialization function called at startup time (just - before the Ethernet initialization) -int (*mdio_active)() - Activate the MDIO pin as output -int (*mdio_tristate)() - Activate the MDIO pin as input/tristate pin -int (*set_mdio)() - Write the MDIO pin -int (*get_mdio)() - Read the MDIO pin -int (*set_mdc)() - Write the MDC pin -int (*delay)() - Delay function -void *priv - Private data used by board specific code - -The board code will look like: - -struct bb_miiphy_bus bb_miiphy_buses[] = { - { .name = "miibus#1", .init = b1_init, .mdio_active = b1_mdio_active, ... }, - { .name = "miibus#2", .init = b2_init, .mdio_active = b2_mdio_active, ... }, - ... -}; -int bb_miiphy_buses_num = sizeof(bb_miiphy_buses) / - sizeof(bb_miiphy_buses[0]); - -2009 Industrie Dial Face S.p.A. - Luigi 'Comio' Mantellini <luigi.mantellini@idf-hit.com> diff --git a/doc/board/qualcomm/index.rst b/doc/board/qualcomm/index.rst index 8c7969987a9..66bc922033a 100644 --- a/doc/board/qualcomm/index.rst +++ b/doc/board/qualcomm/index.rst @@ -10,3 +10,4 @@ Qualcomm rb3gen2 board debugging + rdp diff --git a/doc/board/qualcomm/rdp.rst b/doc/board/qualcomm/rdp.rst new file mode 100644 index 00000000000..fd14f1d9829 --- /dev/null +++ b/doc/board/qualcomm/rdp.rst @@ -0,0 +1,55 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. sectionauthor:: Varadarajan Narayanan <quic_varada@quicinc.com> + +Qualcomm Reference Design Platform (RDP) +======================================== + +Qualcomm RDPs are development boards based on the Qualcomm IPQ series of +SoCs. These SoCs are used as the application processors in WiFi router +platforms. RDPs come in multiple variants with differences in storage +medium (NOR, NAND, MMC), no. of USB and PCIe ports, n/w ports etc. + +.. _Qualcomm's product page: https://www.qualcomm.com/products/internet-of-things/networking/wi-fi-networks/networking-pro-series/qualcomm-networking-pro-820-platform + +Installation +------------ +First, setup ``CROSS_COMPILE`` for aarch64. Then, build U-Boot for ``IPQ9574``:: + + $ export CROSS_COMPILE=<aarch64 toolchain prefix> + $ make qcom_ipq9574_mmc_defconfig + $ make -j8 + +This will build ``u-boot.elf`` in the configured output directory. + +Although the RDPs do not have secure boot set up by default, the firmware still +expects firmware ELF images to be "signed". The signature does not provide any +security in this case, but it provides the firmware with some required metadata. + +To "sign" ``u-boot.elf`` you can use e.g. `qtestsign`_:: + + $ qtestsign -v6 aboot -o u-boot.mbn u-boot.elf + +Then install the resulting ``u-boot.mbn`` to the ``0:APPSBL`` partition +on your device with:: + + IPQ9574# tftpboot path/to/u-boot.mbn + IPQ9574# mmc part (note down the start & end block no.s of '0:APPSBL' partition) + IPQ9574# mmc erase <start blk no> <count> + IPQ9574# mmc write $fileaddr <blk no> <count> + +U-Boot should be running after a reboot (``reset``). + +.. WARNING + Boards with newer software versions would automatically go the emergency + download (EDL) mode if U-Boot is not functioning as expected. If its a + runtime failure at Uboot, the system will get reset (due to watchdog) + and XBL will try to boot from next bank and if Bank B also doesn't have + a functional image and is not booting fine, then the system will enter + EDL. A tool like bkerler's `edl`_ can be used for flashing with the + firehose loader binary appropriate for the board. + + Note that the support added is very basic. Restoring the original U-Boot + on boards with older version of the software requires a debugger. + +.. _qtestsign: https://github.com/msm8916-mainline/qtestsign +.. _edl: https://github.com/bkerler/edl diff --git a/doc/develop/bitbangmii.rst b/doc/develop/bitbangmii.rst new file mode 100644 index 00000000000..35a4a0cb7f9 --- /dev/null +++ b/doc/develop/bitbangmii.rst @@ -0,0 +1,75 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later +.. Luigi 'Comio' Mantellini <luigi.mantellini@idf-hit.com>, Industrie Dial Face S.p.A., 2009 + +Bit-banged MII bus support +========================== + +The miiphybb ( Bit-banged MII bus driver ) supports an arbitrary number of +MII buses. This feature is useful when a driver uses different MII buses for +different PHYs and all (or a part) of these buses are implemented via +bit-banging mode. + +The driver requires that the following macro is defined in the board +configuration file: + +* CONFIG_BITBANGMII - Enable the miiphybb driver + +The driver code needs to allocate a regular MDIO device using mdio_alloc() +and assign .read and .write accessors which wrap bb_miiphy_read() and +bb_miiphy_write() functions respectively. The bb_miiphy_read() and +bb_miiphy_write() functions take a pointer to a callback structure, +struct bb_miiphy_bus_ops. The struct bb_miiphy_bus_ops has the following +fields/callbacks (see miiphy.h for details): + +.. code-block:: c + + int (*mdio_active)() // Activate the MDIO pin as output + int (*mdio_tristate)() // Activate the MDIO pin as input/tristate pin + int (*set_mdio)() // Write the MDIO pin + int (*get_mdio)() // Read the MDIO pin + int (*set_mdc)() // Write the MDC pin + int (*delay)() // Delay function + +The driver code will look like: + +.. code-block:: c + + static const struct bb_miiphy_bus_ops ravb_bb_miiphy_bus_ops = { + .mdio_active = ravb_bb_mdio_active, + .mdio_tristate = ravb_bb_mdio_tristate, + .set_mdio = ravb_bb_set_mdio, + .get_mdio = ravb_bb_get_mdio, + .set_mdc = ravb_bb_set_mdc, + .delay = ravb_bb_delay, + }; + + static int ravb_bb_miiphy_read(struct mii_dev *miidev, int addr, + int devad, int reg) + { + return bb_miiphy_read(miidev, &ravb_bb_miiphy_bus_ops, + addr, devad, reg); + } + + static int ravb_bb_miiphy_write(struct mii_dev *miidev, int addr, + int devad, int reg, u16 value) + { + return bb_miiphy_write(miidev, &ravb_bb_miiphy_bus_ops, + addr, devad, reg, value); + } + + static int ravb_probe(struct udevice *dev) + { + struct mii_dev *mdiodev; + ... + mdiodev = mdio_alloc(); + if (!mdiodev) + return -ENOMEM; + + mdiodev->read = ravb_bb_miiphy_read; + mdiodev->write = ravb_bb_miiphy_write; + mdiodev->priv = eth; + snprintf(mdiodev->name, sizeof(mdiodev->name), dev->name); + + ret = mdio_register(mdiodev); + ... + } diff --git a/doc/develop/index.rst b/doc/develop/index.rst index d9f2a838207..c907f8c9c2c 100644 --- a/doc/develop/index.rst +++ b/doc/develop/index.rst @@ -9,6 +9,7 @@ General .. toctree:: :maxdepth: 1 + bitbangmii board_best_practices codingstyle designprinciples diff --git a/doc/develop/release_cycle.rst b/doc/develop/release_cycle.rst index dc5bb340ff2..e736dc0616e 100644 --- a/doc/develop/release_cycle.rst +++ b/doc/develop/release_cycle.rst @@ -76,7 +76,7 @@ For the next scheduled release, release candidates were made on:: * U-Boot v2025.04-rc4 was released on Mon 10 March 2025. -.. * U-Boot v2025.04-rc5 was released on Mon 24 March 2025. +* U-Boot v2025.04-rc5 was released on Mon 24 March 2025. Please note that the following dates are planned only and may be deviated from as needed. diff --git a/drivers/clk/clk-stub.c b/drivers/clk/clk-stub.c index 5fbbb07b7f7..343fa5cd3fe 100644 --- a/drivers/clk/clk-stub.c +++ b/drivers/clk/clk-stub.c @@ -50,6 +50,7 @@ static struct clk_ops stub_clk_ops = { static const struct udevice_id stub_clk_ids[] = { { .compatible = "qcom,rpmcc" }, + { .compatible = "qcom,sc7280-rpmh-clk" }, { .compatible = "qcom,sm8150-rpmh-clk" }, { .compatible = "qcom,sm8250-rpmh-clk" }, { .compatible = "qcom,sm8550-rpmh-clk" }, diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index cb867acc48c..3ea01f3c969 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -31,6 +31,14 @@ config CLK_QCOM_IPQ4019 on the Snapdragon IPQ4019 SoC. This driver supports the clocks and resets exposed by the GCC hardware block. +config CLK_QCOM_IPQ9574 + bool "Qualcomm IPQ9574 GCC" + select CLK_QCOM + help + Say Y here to enable support for the Global Clock Controller + on the Snapdragon IPQ9574 SoC. This driver supports the clocks + and resets exposed by the GCC hardware block. + config CLK_QCOM_QCM2290 bool "Qualcomm QCM2290 GCC" select CLK_QCOM diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 1bc0f15005b..e13fc8c1071 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_CLK_QCOM_SDM845) += clock-sdm845.o obj-$(CONFIG_CLK_QCOM_APQ8016) += clock-apq8016.o obj-$(CONFIG_CLK_QCOM_APQ8096) += clock-apq8096.o obj-$(CONFIG_CLK_QCOM_IPQ4019) += clock-ipq4019.o +obj-$(CONFIG_CLK_QCOM_IPQ9574) += clock-ipq9574.o obj-$(CONFIG_CLK_QCOM_QCM2290) += clock-qcm2290.o obj-$(CONFIG_CLK_QCOM_QCS404) += clock-qcs404.o obj-$(CONFIG_CLK_QCOM_SA8775P) += clock-sa8775p.o diff --git a/drivers/clk/qcom/clock-apq8016.c b/drivers/clk/qcom/clock-apq8016.c index b5def55dbc2..6a53f900a9e 100644 --- a/drivers/clk/qcom/clock-apq8016.c +++ b/drivers/clk/qcom/clock-apq8016.c @@ -54,8 +54,9 @@ static struct vote_clk gcc_blsp1_ahb_clk = { }; static const struct gate_clk apq8016_clks[] = { - GATE_CLK(GCC_USB_HS_AHB_CLK, 0x41008, 0x00000001), - GATE_CLK(GCC_USB_HS_SYSTEM_CLK, 0x41004, 0x00000001), + GATE_CLK(GCC_PRNG_AHB_CLK, 0x45004, BIT(8)), + GATE_CLK(GCC_USB_HS_AHB_CLK, 0x41008, BIT(0)), + GATE_CLK(GCC_USB_HS_SYSTEM_CLK, 0x41004, BIT(0)), }; /* SDHCI */ @@ -139,15 +140,14 @@ static int apq8016_clk_enable(struct clk *clk) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); - if (priv->data->num_clks < clk->id) { + if (priv->data->num_clks < clk->id || !apq8016_clks[clk->id].reg) { log_warning("%s: unknown clk id %lu\n", __func__, clk->id); return 0; } - debug("%s: clk %s\n", __func__, apq8016_clks[clk->id].name); - qcom_gate_clk_en(priv, clk->id); + debug("%s: enabling clock %s\n", __func__, apq8016_clks[clk->id].name); - return 0; + return qcom_gate_clk_en(priv, clk->id); } static struct msm_clk_data apq8016_clk_data = { diff --git a/drivers/clk/qcom/clock-ipq9574.c b/drivers/clk/qcom/clock-ipq9574.c new file mode 100644 index 00000000000..b0af4036059 --- /dev/null +++ b/drivers/clk/qcom/clock-ipq9574.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Clock drivers for Qualcomm ipq9574 + * + * (C) Copyright 2025 Linaro Ltd. + */ + +#include <linux/types.h> +#include <clk-uclass.h> +#include <dm.h> +#include <linux/delay.h> +#include <asm/io.h> +#include <linux/bug.h> +#include <linux/bitops.h> +#include <dt-bindings/clock/qcom,ipq9574-gcc.h> +#include <dt-bindings/reset/qcom,ipq9574-gcc.h> + +#include "clock-qcom.h" + +#define GCC_BLSP1_AHB_CBCR 0x1004 +#define GCC_BLSP1_UART3_APPS_CMD_RCGR 0x402C +#define GCC_BLSP1_UART3_APPS_CBCR 0x4054 + +#define GCC_SDCC1_APPS_CBCR 0x3302C +#define GCC_SDCC1_AHB_CBCR 0x33034 +#define GCC_SDCC1_APPS_CMD_RCGR 0x33004 +#define GCC_SDCC1_ICE_CORE_CBCR 0x33030 + +static ulong ipq9574_set_rate(struct clk *clk, ulong rate) +{ + struct msm_clk_priv *priv = dev_get_priv(clk->dev); + + switch (clk->id) { + case GCC_BLSP1_UART3_APPS_CLK: + clk_rcg_set_rate_mnd(priv->base, GCC_BLSP1_UART3_APPS_CMD_RCGR, + 0, 144, 15625, CFG_CLK_SRC_GPLL0, 16); + return rate; + case GCC_SDCC1_APPS_CLK: + clk_rcg_set_rate_mnd(priv->base, GCC_SDCC1_APPS_CMD_RCGR, + 11, 0, 0, CFG_CLK_SRC_GPLL2, 16); + return rate; + default: + return -EINVAL; + } +} + +static const struct gate_clk ipq9574_clks[] = { + GATE_CLK(GCC_BLSP1_UART3_APPS_CLK, 0x4054, 0x00000001), + GATE_CLK(GCC_BLSP1_AHB_CLK, 0x1004, 0x00000001), + GATE_CLK(GCC_SDCC1_AHB_CLK, 0x33034, 0x00000001), + GATE_CLK(GCC_SDCC1_APPS_CLK, 0x3302C, 0x00000001), + GATE_CLK(GCC_SDCC1_ICE_CORE_CLK, 0x33030, 0x00000001), +}; + +static int ipq9574_enable(struct clk *clk) +{ + struct msm_clk_priv *priv = dev_get_priv(clk->dev); + + debug("%s: clk %s\n", __func__, ipq9574_clks[clk->id].name); + + if (!ipq9574_clks[clk->id].reg) + return -EINVAL; + + qcom_gate_clk_en(priv, clk->id); + + return 0; +} + +static const struct qcom_reset_map ipq9574_gcc_resets[] = { + [GCC_SDCC_BCR] = { 0x33000 }, +}; + +static struct msm_clk_data ipq9574_gcc_data = { + .resets = ipq9574_gcc_resets, + .num_resets = ARRAY_SIZE(ipq9574_gcc_resets), + .enable = ipq9574_enable, + .set_rate = ipq9574_set_rate, +}; + +static const struct udevice_id gcc_ipq9574_of_match[] = { + { + .compatible = "qcom,ipq9574-gcc", + .data = (ulong)&ipq9574_gcc_data, + }, + { } +}; + +U_BOOT_DRIVER(gcc_ipq9574) = { + .name = "gcc_ipq9574", + .id = UCLASS_NOP, + .of_match = gcc_ipq9574_of_match, + .bind = qcom_cc_bind, + .flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF, +}; diff --git a/drivers/clk/qcom/clock-qcm2290.c b/drivers/clk/qcom/clock-qcm2290.c index c78705cb8cf..1326b770c3e 100644 --- a/drivers/clk/qcom/clock-qcm2290.c +++ b/drivers/clk/qcom/clock-qcm2290.c @@ -134,9 +134,7 @@ static int qcm2290_enable(struct clk *clk) break; } - qcom_gate_clk_en(priv, clk->id); - - return 0; + return qcom_gate_clk_en(priv, clk->id); } static const struct qcom_reset_map qcm2290_gcc_resets[] = { diff --git a/drivers/clk/qcom/clock-qcom.h b/drivers/clk/qcom/clock-qcom.h index ff336dea39c..f43edea2525 100644 --- a/drivers/clk/qcom/clock-qcom.h +++ b/drivers/clk/qcom/clock-qcom.h @@ -7,10 +7,12 @@ #include <asm/io.h> #include <linux/bitfield.h> +#include <errno.h> #define CFG_CLK_SRC_CXO (0 << 8) #define CFG_CLK_SRC_GPLL0 (1 << 8) #define CFG_CLK_SRC_GPLL0_AUX2 (2 << 8) +#define CFG_CLK_SRC_GPLL2 (2 << 8) #define CFG_CLK_SRC_GPLL9 (2 << 8) #define CFG_CLK_SRC_GPLL0_ODD (3 << 8) #define CFG_CLK_SRC_GPLL6 (4 << 8) @@ -105,14 +107,19 @@ void clk_rcg_set_rate(phys_addr_t base, uint32_t cmd_rcgr, int div, int source); void clk_phy_mux_enable(phys_addr_t base, uint32_t cmd_rcgr, bool enabled); -static inline void qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id) +static inline int qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id) { u32 val; - if (id >= priv->data->num_clks || priv->data->clks[id].reg == 0) - return; + if (id >= priv->data->num_clks || priv->data->clks[id].reg == 0) { + log_err("gcc@%#08llx: unknown clock ID %lu!\n", + priv->base, id); + return -ENOENT; + } val = readl(priv->base + priv->data->clks[id].reg); writel(val | priv->data->clks[id].en_val, priv->base + priv->data->clks[id].reg); + + return 0; } #endif diff --git a/drivers/clk/qcom/clock-sa8775p.c b/drivers/clk/qcom/clock-sa8775p.c index e31f24ed4f0..527cecf5c82 100644 --- a/drivers/clk/qcom/clock-sa8775p.c +++ b/drivers/clk/qcom/clock-sa8775p.c @@ -73,9 +73,7 @@ static int sa8775p_enable(struct clk *clk) break; } - qcom_gate_clk_en(priv, clk->id); - - return 0; + return qcom_gate_clk_en(priv, clk->id); } static const struct qcom_reset_map sa8775p_gcc_resets[] = { diff --git a/drivers/clk/qcom/clock-sc7280.c b/drivers/clk/qcom/clock-sc7280.c index 5d343f12051..8691f08109b 100644 --- a/drivers/clk/qcom/clock-sc7280.c +++ b/drivers/clk/qcom/clock-sc7280.c @@ -16,29 +16,64 @@ #include "clock-qcom.h" -#define USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR 0xf038 #define USB30_PRIM_MASTER_CLK_CMD_RCGR 0xf020 +#define USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR 0xf038 +#define USB30_SEC_MASTER_CLK_CMD_RCGR 0x9e020 +#define USB30_SEC_MOCK_UTMI_CLK_CMD_RCGR 0x9e038 +#define PCIE_1_AUX_CLK_CMD_RCGR 0x8d058 +#define PCIE1_PHY_RCHNG_CMD_RCGR 0x8d03c +#define PCIE_1_PIPE_CLK_PHY_MUX 0x8d054 + +static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = { + F(66666667, CFG_CLK_SRC_GPLL0_EVEN, 4.5, 0, 0), + F(133333333, CFG_CLK_SRC_GPLL0, 4.5, 0, 0), + F(200000000, CFG_CLK_SRC_GPLL0_ODD, 1, 0, 0), + F(240000000, CFG_CLK_SRC_GPLL0, 2.5, 0, 0), + { } +}; + +static const struct freq_tbl ftbl_gcc_usb30_sec_master_clk_src[] = { + F(60000000, CFG_CLK_SRC_GPLL0_EVEN, 5, 0, 0), + F(120000000, CFG_CLK_SRC_GPLL0_EVEN, 2.5, 0, 0), + { } +}; static ulong sc7280_set_rate(struct clk *clk, ulong rate) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); + const struct freq_tbl *freq; if (clk->id < priv->data->num_clks) debug("%s: %s, requested rate=%ld\n", __func__, priv->data->clks[clk->id].name, rate); switch (clk->id) { - case GCC_USB30_PRIM_MOCK_UTMI_CLK: - WARN(rate != 19200000, "Unexpected rate for USB30_PRIM_MOCK_UTMI_CLK: %lu\n", rate); - clk_rcg_set_rate(priv->base, USB30_PRIM_MASTER_CLK_CMD_RCGR, 0, CFG_CLK_SRC_CXO); - return rate; case GCC_USB30_PRIM_MASTER_CLK: - WARN(rate != 200000000, "Unexpected rate for USB30_PRIM_MASTER_CLK: %lu\n", rate); + freq = qcom_find_freq(ftbl_gcc_usb30_prim_master_clk_src, rate); clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MASTER_CLK_CMD_RCGR, - 1, 0, 0, CFG_CLK_SRC_GPLL0_ODD, 8); - clk_rcg_set_rate(priv->base, 0xf064, 0, 0); - return rate; + freq->pre_div, freq->m, freq->n, freq->src, 8); + return freq->freq; + case GCC_USB30_PRIM_MOCK_UTMI_CLK: + clk_rcg_set_rate(priv->base, USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR, 1, 0); + return 19200000; + case GCC_USB3_PRIM_PHY_AUX_CLK_SRC: + clk_rcg_set_rate(priv->base, USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR, 1, 0); + return 19200000; + case GCC_USB30_SEC_MASTER_CLK: + freq = qcom_find_freq(ftbl_gcc_usb30_sec_master_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, USB30_SEC_MASTER_CLK_CMD_RCGR, + freq->pre_div, freq->m, freq->n, freq->src, 8); + return freq->freq; + case GCC_USB30_SEC_MOCK_UTMI_CLK: + clk_rcg_set_rate(priv->base, USB30_SEC_MOCK_UTMI_CLK_CMD_RCGR, 1, 0); + return 19200000; + case GCC_USB3_SEC_PHY_AUX_CLK_SRC: + clk_rcg_set_rate(priv->base, USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR, 1, 0); + return 19200000; + case GCC_PCIE1_PHY_RCHNG_CLK: + clk_rcg_set_rate(priv->base, PCIE1_PHY_RCHNG_CMD_RCGR, 5, CFG_CLK_SRC_GPLL0_EVEN); + return 100000000; default: - return 0; + return rate; } } @@ -50,13 +85,35 @@ static const struct gate_clk sc7280_clks[] = { GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0xf01c, 1), GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0xf054, 1), GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0xf058, 1), + GATE_CLK(GCC_CFG_NOC_USB3_SEC_AXI_CLK, 0x9e07c, 1), + GATE_CLK(GCC_USB30_SEC_MASTER_CLK, 0x9e010, 1), + GATE_CLK(GCC_AGGRE_USB3_SEC_AXI_CLK, 0x9e080, 1), + GATE_CLK(GCC_USB30_SEC_SLEEP_CLK, 0x9e018, 1), + GATE_CLK(GCC_USB30_SEC_MOCK_UTMI_CLK, 0x9e01c, 1), + GATE_CLK(GCC_USB3_SEC_PHY_AUX_CLK, 0x9e054, 1), + GATE_CLK(GCC_USB3_SEC_PHY_COM_AUX_CLK, 0x9e058, 1), + GATE_CLK(GCC_PCIE_CLKREF_EN, 0x8c004, 1), + GATE_CLK(GCC_PCIE_1_PIPE_CLK, 0x52000, BIT(30)), + GATE_CLK(GCC_PCIE_1_AUX_CLK, 0x52000, BIT(29)), + GATE_CLK(GCC_PCIE_1_CFG_AHB_CLK, 0x52000, BIT(28)), + GATE_CLK(GCC_PCIE_1_MSTR_AXI_CLK, 0x52000, BIT(27)), + GATE_CLK(GCC_PCIE_1_SLV_AXI_CLK, 0x52000, BIT(26)), + GATE_CLK(GCC_PCIE_1_SLV_Q2A_AXI_CLK, 0x52000, BIT(25)), + GATE_CLK(GCC_PCIE1_PHY_RCHNG_CLK, 0x52000, BIT(23)), + GATE_CLK(GCC_DDRSS_PCIE_SF_CLK, 0x52000, BIT(19)), + GATE_CLK(GCC_AGGRE_NOC_PCIE_TBU_CLK, 0x52000, BIT(18)), + GATE_CLK(GCC_AGGRE_NOC_PCIE_1_AXI_CLK, 0x52000, BIT(11)), + GATE_CLK(GCC_AGGRE_NOC_PCIE_CENTER_SF_AXI_CLK, 0x52008, BIT(28)), + GATE_CLK(GCC_QUPV3_WRAP0_S0_CLK, 0x52008, BIT(10)), + GATE_CLK(GCC_QUPV3_WRAP0_S1_CLK, 0x52008, BIT(11)), + GATE_CLK(GCC_QUPV3_WRAP0_S3_CLK, 0x52008, BIT(13)), }; static int sc7280_enable(struct clk *clk) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); - if (priv->data->num_clks < clk->id) { + if (priv->data->num_clks <= clk->id) { debug("%s: unknown clk id %lu\n", __func__, clk->id); return 0; } @@ -71,11 +128,32 @@ static int sc7280_enable(struct clk *clk) qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_AUX_CLK); qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_COM_AUX_CLK); break; + case GCC_AGGRE_USB3_SEC_AXI_CLK: + qcom_gate_clk_en(priv, GCC_USB30_SEC_MASTER_CLK); + fallthrough; + case GCC_USB30_SEC_MASTER_CLK: + qcom_gate_clk_en(priv, GCC_USB3_SEC_PHY_AUX_CLK); + qcom_gate_clk_en(priv, GCC_USB3_SEC_PHY_COM_AUX_CLK); + break; + case GCC_PCIE_1_PIPE_CLK: + clk_phy_mux_enable(priv->base, PCIE_1_PIPE_CLK_PHY_MUX, true); + break; + case GCC_PCIE_1_AUX_CLK: + clk_rcg_set_rate_mnd(priv->base, PCIE_1_AUX_CLK_CMD_RCGR, 1, 0, 0, + CFG_CLK_SRC_CXO, 16); + break; + case GCC_QUPV3_WRAP0_S0_CLK: + clk_rcg_set_rate_mnd(priv->base, 0x17010, 1, 0, 0, CFG_CLK_SRC_CXO, 16); + break; + case GCC_QUPV3_WRAP0_S1_CLK: + clk_rcg_set_rate_mnd(priv->base, 0x17140, 1, 0, 0, CFG_CLK_SRC_CXO, 16); + break; + case GCC_QUPV3_WRAP0_S3_CLK: + clk_rcg_set_rate_mnd(priv->base, 0x173a0, 1, 0, 0, CFG_CLK_SRC_CXO, 16); + break; } - qcom_gate_clk_en(priv, clk->id); - - return 0; + return qcom_gate_clk_en(priv, clk->id); } static const struct qcom_reset_map sc7280_gcc_resets[] = { @@ -100,6 +178,20 @@ static const struct qcom_reset_map sc7280_gcc_resets[] = { static const struct qcom_power_map sc7280_gdscs[] = { [GCC_UFS_PHY_GDSC] = { 0x77004 }, [GCC_USB30_PRIM_GDSC] = { 0xf004 }, + [GCC_USB30_SEC_GDSC] = { 0x9e004 }, + [GCC_PCIE_1_GDSC] = { 0x8d004 }, +}; + +static const phys_addr_t sc7280_rcg_addrs[] = { + 0x10f020, // USB30_PRIM_MASTER_CLK_CMD_RCGR + 0x10f038, // USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR + 0x18d058, // PCIE_1_AUX_CLK_CMD_RCGR +}; + +static const char *const sc7280_rcg_names[] = { + "USB30_PRIM_MASTER_CLK_SRC", + "USB30_PRIM_MOCK_UTMI_CLK_SRC", + "GCC_PCIE_1_AUX_CLK_SRC", }; static struct msm_clk_data qcs404_gcc_data = { @@ -113,6 +205,10 @@ static struct msm_clk_data qcs404_gcc_data = { .enable = sc7280_enable, .set_rate = sc7280_set_rate, + + .dbg_rcg_addrs = sc7280_rcg_addrs, + .num_rcgs = ARRAY_SIZE(sc7280_rcg_addrs), + .dbg_rcg_names = sc7280_rcg_names, }; static const struct udevice_id gcc_sc7280_of_match[] = { diff --git a/drivers/clk/qcom/clock-sdm845.c b/drivers/clk/qcom/clock-sdm845.c index adffb0cb240..6a0bf16ba2d 100644 --- a/drivers/clk/qcom/clock-sdm845.c +++ b/drivers/clk/qcom/clock-sdm845.c @@ -162,9 +162,7 @@ static int sdm845_clk_enable(struct clk *clk) break; } - qcom_gate_clk_en(priv, clk->id); - - return 0; + return qcom_gate_clk_en(priv, clk->id); } static const struct qcom_reset_map sdm845_gcc_resets[] = { diff --git a/drivers/clk/qcom/clock-sm6115.c b/drivers/clk/qcom/clock-sm6115.c index 9057dfe0bb1..17c2e561758 100644 --- a/drivers/clk/qcom/clock-sm6115.c +++ b/drivers/clk/qcom/clock-sm6115.c @@ -146,9 +146,7 @@ static int sm6115_enable(struct clk *clk) break; } - qcom_gate_clk_en(priv, clk->id); - - return 0; + return qcom_gate_clk_en(priv, clk->id); } static const struct qcom_reset_map sm6115_gcc_resets[] = { diff --git a/drivers/clk/qcom/clock-sm8150.c b/drivers/clk/qcom/clock-sm8150.c index 88f2e678f43..7dd0d56eb43 100644 --- a/drivers/clk/qcom/clock-sm8150.c +++ b/drivers/clk/qcom/clock-sm8150.c @@ -243,9 +243,7 @@ static int sm8150_clk_enable(struct clk *clk) break; }; - qcom_gate_clk_en(priv, clk->id); - - return 0; + return qcom_gate_clk_en(priv, clk->id); } static const struct qcom_reset_map sm8150_gcc_resets[] = { diff --git a/drivers/clk/qcom/clock-sm8250.c b/drivers/clk/qcom/clock-sm8250.c index e322a923a5c..26396847d85 100644 --- a/drivers/clk/qcom/clock-sm8250.c +++ b/drivers/clk/qcom/clock-sm8250.c @@ -195,9 +195,7 @@ static int sm8250_enable(struct clk *clk) break; } - qcom_gate_clk_en(priv, clk->id); - - return 0; + return qcom_gate_clk_en(priv, clk->id); } static const struct qcom_reset_map sm8250_gcc_resets[] = { diff --git a/drivers/clk/qcom/clock-sm8550.c b/drivers/clk/qcom/clock-sm8550.c index 62b5a409e8e..7c06489b9c4 100644 --- a/drivers/clk/qcom/clock-sm8550.c +++ b/drivers/clk/qcom/clock-sm8550.c @@ -220,9 +220,7 @@ static int sm8550_enable(struct clk *clk) break; } - qcom_gate_clk_en(priv, clk->id); - - return 0; + return qcom_gate_clk_en(priv, clk->id); } static const struct qcom_reset_map sm8550_gcc_resets[] = { diff --git a/drivers/clk/qcom/clock-sm8650.c b/drivers/clk/qcom/clock-sm8650.c index 9baaecb571f..364454644a6 100644 --- a/drivers/clk/qcom/clock-sm8650.c +++ b/drivers/clk/qcom/clock-sm8650.c @@ -217,9 +217,7 @@ static int sm8650_enable(struct clk *clk) break; } - qcom_gate_clk_en(priv, clk->id); - - return 0; + return qcom_gate_clk_en(priv, clk->id); } static const struct qcom_reset_map sm8650_gcc_resets[] = { diff --git a/drivers/clk/qcom/clock-x1e80100.c b/drivers/clk/qcom/clock-x1e80100.c index bd9c6ed1c8a..542d6248d65 100644 --- a/drivers/clk/qcom/clock-x1e80100.c +++ b/drivers/clk/qcom/clock-x1e80100.c @@ -174,9 +174,7 @@ static int x1e80100_enable(struct clk *clk) break; } - qcom_gate_clk_en(priv, clk->id); - - return 0; + return qcom_gate_clk_en(priv, clk->id); } static const struct qcom_reset_map x1e80100_gcc_resets[] = { diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c index 27bb7052fca..ac77fb06bf7 100644 --- a/drivers/mmc/msm_sdhci.c +++ b/drivers/mmc/msm_sdhci.c @@ -10,6 +10,7 @@ #include <clk.h> #include <dm.h> #include <malloc.h> +#include <reset.h> #include <sdhci.h> #include <wait_bit.h> #include <asm/global_data.h> @@ -153,9 +154,18 @@ static int msm_sdc_probe(struct udevice *dev) const struct msm_sdhc_variant_info *var_info; struct sdhci_host *host = &prv->host; u32 core_version, core_minor, core_major; + struct reset_ctl bcr_rst; u32 caps; int ret; + ret = reset_get_by_index(dev, 0, &bcr_rst); + if (!ret) { + reset_assert(&bcr_rst); + udelay(200); + reset_deassert(&bcr_rst); + udelay(200); + } + host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B; host->max_clk = 0; diff --git a/drivers/net/phy/micrel_ksz90x1.c b/drivers/net/phy/micrel_ksz90x1.c index c48ae6e88f3..ee8eae1efd9 100644 --- a/drivers/net/phy/micrel_ksz90x1.c +++ b/drivers/net/phy/micrel_ksz90x1.c @@ -389,10 +389,126 @@ U_BOOT_PHY_DRIVER(ksz9031) = { #define KSZ9131RN_DLL_ENABLE_DELAY 0 #define KSZ9131RN_DLL_DISABLE_DELAY BIT(12) +#define KSZ9131RN_COMMON_CTRL 0 +#define KSZ9131RN_COMMON_CTRL_INDIVIDUAL_LED_MODE BIT(4) + +#define KSZ9131RN_LED_ERRATA_REG 0x1e +#define KSZ9131RN_LED_ERRATA_BIT BIT(9) + +#define KSZ9131RN_CONTROL_PAD_SKEW 4 +#define KSZ9131RN_RX_DATA_PAD_SKEW 5 +#define KSZ9131RN_TX_DATA_PAD_SKEW 6 +#define KSZ9131RN_CLK_PAD_SKEW 8 + +#define KSZ9131RN_SKEW_5BIT_MAX 2400 +#define KSZ9131RN_SKEW_4BIT_MAX 800 +#define KSZ9131RN_OFFSET 700 +#define KSZ9131RN_STEP 100 + +static int ksz9131_of_load_skew_values(struct phy_device *phydev, + ofnode of_node, + u16 reg, size_t field_sz, + const char *field[], u8 numfields) +{ + int val[4] = {-(1 + KSZ9131RN_OFFSET), -(2 + KSZ9131RN_OFFSET), + -(3 + KSZ9131RN_OFFSET), -(4 + KSZ9131RN_OFFSET)}; + int skewval, skewmax = 0; + int matches = 0; + u16 maxval; + u16 newval; + u16 mask; + int i; + + /* psec properties in dts should mean x pico seconds */ + if (field_sz == 5) + skewmax = KSZ9131RN_SKEW_5BIT_MAX; + else + skewmax = KSZ9131RN_SKEW_4BIT_MAX; + + for (i = 0; i < numfields; i++) + if (!ofnode_read_s32(of_node, field[i], &skewval)) { + if (skewval < -KSZ9131RN_OFFSET) + skewval = -KSZ9131RN_OFFSET; + else if (skewval > skewmax) + skewval = skewmax; + + val[i] = skewval + KSZ9131RN_OFFSET; + matches++; + } + + if (!matches) + return 0; + + if (matches < numfields) + newval = phy_read_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG, reg); + else + newval = 0; + + maxval = (field_sz == 4) ? 0xf : 0x1f; + for (i = 0; i < numfields; i++) + if (val[i] != -(i + 1 + KSZ9131RN_OFFSET)) { + mask = 0xffff; + mask ^= maxval << (field_sz * i); + newval = (newval & mask) | + (((val[i] / KSZ9131RN_STEP) & maxval) + << (field_sz * i)); + } + + return phy_write_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG, reg, newval); +} + +static int ksz9131_of_load_all_skew_values(struct phy_device *phydev) +{ + const char *control_skews[2] = { "txen-skew-psec", "rxdv-skew-psec" }; + const char *clk_skews[2] = { "rxc-skew-psec", "txc-skew-psec" }; + const char *rx_data_skews[4] = { + "rxd0-skew-psec", "rxd1-skew-psec", + "rxd2-skew-psec", "rxd3-skew-psec" + }; + const char *tx_data_skews[4] = { + "txd0-skew-psec", "txd1-skew-psec", + "txd2-skew-psec", "txd3-skew-psec" + }; + struct ofnode_phandle_args phandle_args; + int ret; + + /* + * Silently ignore failure here as the device tree is not required to + * contain a phy node. + */ + if (dev_read_phandle_with_args(phydev->dev, "phy-handle", NULL, 0, 0, + &phandle_args)) + return 0; + + if (!ofnode_valid(phandle_args.node)) + return 0; + + ret = ksz9131_of_load_skew_values(phydev, phandle_args.node, + KSZ9131RN_CLK_PAD_SKEW, 5, + clk_skews, 2); + if (ret < 0) + return ret; + + ret = ksz9131_of_load_skew_values(phydev, phandle_args.node, + KSZ9131RN_CONTROL_PAD_SKEW, 4, + control_skews, 2); + if (ret < 0) + return ret; + + ret = ksz9131_of_load_skew_values(phydev, phandle_args.node, + KSZ9131RN_RX_DATA_PAD_SKEW, 4, + rx_data_skews, 4); + if (ret < 0) + return ret; + + return ksz9131_of_load_skew_values(phydev, phandle_args.node, + KSZ9131RN_TX_DATA_PAD_SKEW, 4, + tx_data_skews, 4); +} + static int ksz9131_config_rgmii_delay(struct phy_device *phydev) { - struct phy_driver *drv = phydev->drv; - u16 rxcdll_val, txcdll_val, val; + u16 rxcdll_val, txcdll_val; int ret; switch (phydev->interface) { @@ -416,24 +532,37 @@ static int ksz9131_config_rgmii_delay(struct phy_device *phydev) return 0; } - val = drv->readext(phydev, 0, KSZ9131RN_MMD_COMMON_CTRL_REG, - KSZ9131RN_RXC_DLL_CTRL); - val &= ~KSZ9131RN_DLL_CTRL_BYPASS; - val |= rxcdll_val; - ret = drv->writeext(phydev, 0, KSZ9131RN_MMD_COMMON_CTRL_REG, - KSZ9131RN_RXC_DLL_CTRL, val); - if (ret) + ret = phy_modify_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG, + KSZ9131RN_RXC_DLL_CTRL, KSZ9131RN_DLL_CTRL_BYPASS, + rxcdll_val); + if (ret < 0) return ret; - val = drv->readext(phydev, 0, KSZ9131RN_MMD_COMMON_CTRL_REG, - KSZ9131RN_TXC_DLL_CTRL); + return phy_modify_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG, + KSZ9131RN_TXC_DLL_CTRL, KSZ9131RN_DLL_CTRL_BYPASS, + txcdll_val); +} + +/* Silicon Errata DS80000693B + * + * When LEDs are configured in Individual Mode, LED1 is ON in a no-link + * condition. Workaround is to set register 0x1e, bit 9, this way LED1 behaves + * according to the datasheet (off if there is no link). + */ +static int ksz9131_led_errata(struct phy_device *phydev) +{ + int reg; - val &= ~KSZ9131RN_DLL_CTRL_BYPASS; - val |= txcdll_val; - ret = drv->writeext(phydev, 0, KSZ9131RN_MMD_COMMON_CTRL_REG, - KSZ9131RN_TXC_DLL_CTRL, val); + reg = phy_read_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG, + KSZ9131RN_COMMON_CTRL); + if (reg < 0) + return reg; - return ret; + if (!(reg & KSZ9131RN_COMMON_CTRL_INDIVIDUAL_LED_MODE)) + return 0; + + return phy_set_bits(phydev, MDIO_DEVAD_NONE, KSZ9131RN_LED_ERRATA_REG, + KSZ9131RN_LED_ERRATA_BIT); } static int ksz9131_config(struct phy_device *phydev) @@ -446,6 +575,14 @@ static int ksz9131_config(struct phy_device *phydev) return ret; } + ret = ksz9131_of_load_all_skew_values(phydev); + if (ret < 0) + return ret; + + ret = ksz9131_led_errata(phydev); + if (ret < 0) + return ret; + /* add an option to disable the gigabit feature of this PHY */ if (env_get("disable_giga")) { unsigned features; diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c index c39bef17b79..539fd37ee59 100644 --- a/drivers/net/ravb.c +++ b/drivers/net/ravb.c @@ -592,7 +592,7 @@ static int ravb_probe(struct udevice *dev) ret = clk_get_bulk(dev, ð->clks); if (ret < 0) - goto err_mdio_alloc; + goto err_clk_get; mdiodev = mdio_alloc(); if (!mdiodev) { @@ -614,23 +614,25 @@ static int ravb_probe(struct udevice *dev) /* Bring up PHY */ ret = clk_enable_bulk(ð->clks); if (ret) - goto err_mdio_register; + goto err_clk_enable; ret = ravb_reset(dev); if (ret) - goto err_mdio_reset; + goto err_clk_enable; ret = ravb_phy_config(dev); if (ret) - goto err_mdio_reset; + goto err_clk_enable; return 0; -err_mdio_reset: - clk_release_bulk(ð->clks); +err_clk_enable: + mdio_unregister(mdiodev); err_mdio_register: mdio_free(mdiodev); err_mdio_alloc: + clk_release_bulk(ð->clks); +err_clk_get: unmap_physmem(eth->iobase, MAP_NOCACHE); return ret; } diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index f940648fe58..d3fe90d939e 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -163,8 +163,8 @@ config PHY_RCAR_GEN2 config PHY_RCAR_GEN3 tristate "Renesas R-Car Gen3 USB PHY" - depends on PHY && RCAR_GEN3 && CLK && DM_REGULATOR - default y if RCAR_GEN3 + depends on PHY && CLK && DM_REGULATOR && (RCAR_GEN3 || RZG2L) + default y if (RCAR_GEN3 || RZG2L) help Support for the Renesas R-Car Gen3 USB PHY. This driver operates the PHY connected to EHCI USB module and controls USB OTG operation. diff --git a/drivers/phy/phy-rcar-gen3.c b/drivers/phy/phy-rcar-gen3.c index 8c004eaf4c6..d06861c4f79 100644 --- a/drivers/phy/phy-rcar-gen3.c +++ b/drivers/phy/phy-rcar-gen3.c @@ -55,6 +55,7 @@ /* VBCTRL */ #define USB2_VBCTRL_DRVVBUSSEL BIT(8) +#define USB2_VBCTRL_VBOUT BIT(0) /* LINECTRL1 */ #define USB2_LINECTRL1_DPRPD_EN BIT(19) @@ -68,6 +69,13 @@ #define USB2_ADPCTRL_IDPULLUP BIT(5) /* 1 = ID sampling is enabled */ #define USB2_ADPCTRL_DRVVBUS BIT(4) +/* RZ/G2L specific */ +#define USB2_OBINT_IDCHG_EN BIT(0) +#define USB2_LINECTRL1_USB2_IDMON BIT(0) + +/* Device flags */ +#define RCAR_GEN3_PHY_NO_ADPCTRL BIT(0) + struct rcar_gen3_phy { fdt_addr_t regs; struct clk clk; @@ -122,15 +130,50 @@ static int rcar_gen3_phy_phy_power_off(struct phy *phy) return regulator_set_enable(priv->vbus_supply, false); } +static bool rcar_gen3_phy_check_id(struct phy *phy) +{ + const u32 adpdevmask = USB2_ADPCTRL_IDDIG | USB2_ADPCTRL_OTGSESSVLD; + struct rcar_gen3_phy *priv = dev_get_priv(phy->dev); + ulong flags = dev_get_driver_data(phy->dev); + u32 val; + + if (flags & RCAR_GEN3_PHY_NO_ADPCTRL) { + val = readl(priv->regs + USB2_LINECTRL1); + return !!(val & USB2_LINECTRL1_USB2_IDMON); + } + + val = readl(priv->regs + USB2_ADPCTRL); + return (val & adpdevmask) == adpdevmask; +} + +static void rcar_gen3_phy_set_vbus(struct phy *phy, bool enable) +{ + struct rcar_gen3_phy *priv = dev_get_priv(phy->dev); + ulong flags = dev_get_driver_data(phy->dev); + u32 bits = USB2_ADPCTRL_DRVVBUS; + u64 reg = USB2_ADPCTRL; + + if (flags & RCAR_GEN3_PHY_NO_ADPCTRL) { + bits = USB2_VBCTRL_VBOUT; + reg = USB2_VBCTRL; + } + + if (enable) + setbits_le32(priv->regs + reg, bits); + else + clrbits_le32(priv->regs + reg, bits); +} + static int rcar_gen3_phy_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) { - const u32 adpdevmask = USB2_ADPCTRL_IDDIG | USB2_ADPCTRL_OTGSESSVLD; struct rcar_gen3_phy *priv = dev_get_priv(phy->dev); - u32 adpctrl; + ulong flags = dev_get_driver_data(phy->dev); if (mode == PHY_MODE_USB_OTG) { if (submode) { + u32 obint_enable_bits; + /* OTG submode is used as initialization indicator */ writel(USB2_INT_ENABLE_UCOM_INTEN | USB2_INT_ENABLE_USBH_INTB_EN | @@ -138,13 +181,16 @@ static int rcar_gen3_phy_phy_set_mode(struct phy *phy, enum phy_mode mode, priv->regs + USB2_INT_ENABLE); setbits_le32(priv->regs + USB2_VBCTRL, USB2_VBCTRL_DRVVBUSSEL); - writel(USB2_OBINT_SESSVLDCHG | USB2_OBINT_IDDIGCHG, - priv->regs + USB2_OBINTSTA); - setbits_le32(priv->regs + USB2_OBINTEN, - USB2_OBINT_SESSVLDCHG | - USB2_OBINT_IDDIGCHG); - setbits_le32(priv->regs + USB2_ADPCTRL, - USB2_ADPCTRL_IDPULLUP); + if (flags & RCAR_GEN3_PHY_NO_ADPCTRL) { + obint_enable_bits = USB2_OBINT_IDCHG_EN; + } else { + obint_enable_bits = USB2_OBINT_SESSVLDCHG | + USB2_OBINT_IDDIGCHG; + setbits_le32(priv->regs + USB2_ADPCTRL, + USB2_ADPCTRL_IDPULLUP); + } + writel(obint_enable_bits, priv->regs + USB2_OBINTSTA); + setbits_le32(priv->regs + USB2_OBINTEN, obint_enable_bits); clrsetbits_le32(priv->regs + USB2_LINECTRL1, USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD | @@ -154,8 +200,7 @@ static int rcar_gen3_phy_phy_set_mode(struct phy *phy, enum phy_mode mode, USB2_LINECTRL1_DMRPD_EN); } - adpctrl = readl(priv->regs + USB2_ADPCTRL); - if ((adpctrl & adpdevmask) == adpdevmask) + if (rcar_gen3_phy_check_id(phy)) mode = PHY_MODE_USB_DEVICE; else mode = PHY_MODE_USB_HOST; @@ -165,13 +210,13 @@ static int rcar_gen3_phy_phy_set_mode(struct phy *phy, enum phy_mode mode, clrbits_le32(priv->regs + USB2_COMMCTRL, USB2_COMMCTRL_OTG_PERI); setbits_le32(priv->regs + USB2_LINECTRL1, USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD); - setbits_le32(priv->regs + USB2_ADPCTRL, USB2_ADPCTRL_DRVVBUS); + rcar_gen3_phy_set_vbus(phy, true); } else if (mode == PHY_MODE_USB_DEVICE) { setbits_le32(priv->regs + USB2_COMMCTRL, USB2_COMMCTRL_OTG_PERI); clrsetbits_le32(priv->regs + USB2_LINECTRL1, USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD, USB2_LINECTRL1_DM_RPD); - clrbits_le32(priv->regs + USB2_ADPCTRL, USB2_ADPCTRL_DRVVBUS); + rcar_gen3_phy_set_vbus(phy, false); } else { dev_err(phy->dev, "Unknown mode %d\n", mode); return -EINVAL; @@ -226,7 +271,13 @@ static int rcar_gen3_phy_remove(struct udevice *dev) } static const struct udevice_id rcar_gen3_phy_of_match[] = { - { .compatible = "renesas,rcar-gen3-usb2-phy", }, + { + .compatible = "renesas,rcar-gen3-usb2-phy", + }, + { + .compatible = "renesas,rzg2l-usb2-phy", + .data = RCAR_GEN3_PHY_NO_ADPCTRL, + }, { }, }; diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index d3eb6998551..f4a3942ee2f 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -7,84 +7,98 @@ config PINCTRL_QCOM menu "Qualcomm pinctrl drivers" config PINCTRL_QCOM_APQ8016 - bool "Qualcomm APQ8016 GCC" + bool "Qualcomm APQ8016 Pinctrl" select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the MSM8916 / APQ8016 Snapdragon 410 SoC, as well as the associated GPIO driver. config PINCTRL_QCOM_APQ8096 - bool "Qualcomm APQ8096 GCC" + bool "Qualcomm APQ8096 Pinctrl" select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the MSM8996 / APQ8096 Snapdragon 820 SoC, as well as the associated GPIO driver. config PINCTRL_QCOM_IPQ4019 - bool "Qualcomm IPQ4019 GCC" + bool "Qualcomm IPQ4019 Pinctrl" select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the IPQ4019 SoC, as well as the associated GPIO driver. +config PINCTRL_QCOM_IPQ9574 + bool "Qualcomm IPQ9574 Pinctrl" + select PINCTRL_QCOM + help + Say Y here to enable support for pinctrl on the IPQ9574 SoC, + as well as the associated GPIO driver. + config PINCTRL_QCOM_QCM2290 - bool "Qualcomm QCM2290 GCC" + bool "Qualcomm QCM2290 Pinctrl" select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon QCM2290 SoC, as well as the associated GPIO driver. config PINCTRL_QCOM_QCS404 - bool "Qualcomm QCS404 GCC" + bool "Qualcomm QCS404 Pinctrl" select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon QCS404 SoC, as well as the associated GPIO driver. +config PINCTRL_QCOM_SC7280 + bool "Qualcomm SC7280/QCM6490 Pinctrl" + select PINCTRL_QCOM + help + Say Y here to enable support for pinctrl on the Snapdragon SC7280 SoC, + as well as the associated GPIO driver. + config PINCTRL_QCOM_SDM845 - bool "Qualcomm SDM845 GCC" + bool "Qualcomm SDM845 Pinctrl" select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon 845 SoC, as well as the associated GPIO driver. config PINCTRL_QCOM_SM6115 - bool "Qualcomm SM6115 GCC" + bool "Qualcomm SM6115 Pinctrl" select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SM6115 SoC, as well as the associated GPIO driver. config PINCTRL_QCOM_SM8150 - bool "Qualcomm SM8150 GCC" + bool "Qualcomm SM8150 Pinctrl" select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SM8150 SoC, as well as the associated GPIO driver. config PINCTRL_QCOM_SM8250 - bool "Qualcomm SM8250 GCC" + bool "Qualcomm SM8250 Pinctrl" select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SM8250 SoC, as well as the associated GPIO driver. config PINCTRL_QCOM_SM8550 - bool "Qualcomm SM8550 GCC" + bool "Qualcomm SM8550 Pinctrl" select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SM8550 SoC, as well as the associated GPIO driver. config PINCTRL_QCOM_SM8650 - bool "Qualcomm SM8650 GCC" + bool "Qualcomm SM8650 Pinctrl" select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SM8650 SoC, as well as the associated GPIO driver. config PINCTRL_QCOM_X1E80100 - bool "Qualcomm X1E80100 GCC" + bool "Qualcomm X1E80100 Pinctrl" select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon X1E80100 SoC, diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 06d3c95f93a..94cdc6e4a62 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -5,9 +5,11 @@ obj-$(CONFIG_PINCTRL_QCOM) += pinctrl-qcom.o obj-$(CONFIG_PINCTRL_QCOM_APQ8016) += pinctrl-apq8016.o obj-$(CONFIG_PINCTRL_QCOM_IPQ4019) += pinctrl-ipq4019.o +obj-$(CONFIG_PINCTRL_QCOM_IPQ9574) += pinctrl-ipq9574.o obj-$(CONFIG_PINCTRL_QCOM_APQ8096) += pinctrl-apq8096.o obj-$(CONFIG_PINCTRL_QCOM_QCM2290) += pinctrl-qcm2290.o obj-$(CONFIG_PINCTRL_QCOM_QCS404) += pinctrl-qcs404.o +obj-$(CONFIG_PINCTRL_QCOM_SC7280) += pinctrl-sc7280.o obj-$(CONFIG_PINCTRL_QCOM_SDM845) += pinctrl-sdm845.o obj-$(CONFIG_PINCTRL_QCOM_SM6115) += pinctrl-sm6115.o obj-$(CONFIG_PINCTRL_QCOM_SM8150) += pinctrl-sm8150.o diff --git a/drivers/pinctrl/qcom/pinctrl-apq8016.c b/drivers/pinctrl/qcom/pinctrl-apq8016.c index 0c7437822ff..9ae07d43d93 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8016.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8016.c @@ -50,8 +50,8 @@ static const char *apq8016_get_pin_name(struct udevice *dev, } } -static unsigned int apq8016_get_function_mux(__maybe_unused unsigned int pin, - unsigned int selector) +static int apq8016_get_function_mux(__maybe_unused unsigned int pin, + unsigned int selector) { return msm_pinctrl_functions[selector].val; } diff --git a/drivers/pinctrl/qcom/pinctrl-apq8096.c b/drivers/pinctrl/qcom/pinctrl-apq8096.c index 132ece868bf..eaa927c6e22 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8096.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8096.c @@ -43,8 +43,8 @@ static const char *apq8096_get_pin_name(struct udevice *dev, } } -static unsigned int apq8096_get_function_mux(__maybe_unused unsigned int pin, - unsigned int selector) +static int apq8096_get_function_mux(__maybe_unused unsigned int pin, + unsigned int selector) { return msm_pinctrl_functions[selector].val; } diff --git a/drivers/pinctrl/qcom/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c index 3215c677b26..dafcd494df4 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c @@ -311,8 +311,7 @@ static const char *ipq4019_get_pin_name(struct udevice *dev, return pin_name; } -static unsigned int ipq4019_get_function_mux(unsigned int pin, - unsigned int selector) +static int ipq4019_get_function_mux(unsigned int pin, unsigned int selector) { unsigned int i; const msm_pin_function *func = ipq4019_pin_functions + pin; diff --git a/drivers/pinctrl/qcom/pinctrl-ipq9574.c b/drivers/pinctrl/qcom/pinctrl-ipq9574.c new file mode 100644 index 00000000000..ce09072ae3c --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-ipq9574.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * pinctrl driver for Qualcomm ipq9574 + * + * (C) Copyright 2025 Linaro Ltd. + */ + +#include <dm.h> + +#include "pinctrl-qcom.h" + +#define MAX_PIN_NAME_LEN 32 +static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); + +enum ipq9574_functions { + msm_mux_blsp0_spi, + msm_mux_blsp0_uart, + msm_mux_blsp1_i2c, + msm_mux_blsp1_spi, + msm_mux_blsp1_uart, + msm_mux_blsp2_i2c, + msm_mux_blsp2_spi, + msm_mux_blsp2_uart, + msm_mux_blsp3_i2c, + msm_mux_blsp3_spi, + msm_mux_blsp3_uart, + msm_mux_blsp4_i2c, + msm_mux_blsp4_spi, + msm_mux_blsp4_uart, + msm_mux_blsp5_i2c, + msm_mux_blsp5_uart, + msm_mux_gpio, + msm_mux_mdc, + msm_mux_mdio, + msm_mux_pcie0_clk, + msm_mux_pcie0_wake, + msm_mux_pcie1_clk, + msm_mux_pcie1_wake, + msm_mux_pcie2_clk, + msm_mux_pcie2_wake, + msm_mux_pcie3_clk, + msm_mux_pcie3_wake, + msm_mux_qspi_data, + msm_mux_qspi_clk, + msm_mux_qspi_cs, + msm_mux_sdc_data, + msm_mux_sdc_clk, + msm_mux_sdc_cmd, + msm_mux_sdc_rclk, + msm_mux_NA, +}; + +#define MSM_PIN_FUNCTION(fname) \ + [msm_mux_##fname] = {#fname, msm_mux_##fname} + +static const struct pinctrl_function msm_pinctrl_functions[] = { + MSM_PIN_FUNCTION(blsp0_spi), + MSM_PIN_FUNCTION(blsp0_uart), + MSM_PIN_FUNCTION(blsp1_i2c), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp1_uart), + MSM_PIN_FUNCTION(blsp2_i2c), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp2_uart), + MSM_PIN_FUNCTION(blsp3_i2c), + MSM_PIN_FUNCTION(blsp3_spi), + MSM_PIN_FUNCTION(blsp3_uart), + MSM_PIN_FUNCTION(blsp4_i2c), + MSM_PIN_FUNCTION(blsp4_spi), + MSM_PIN_FUNCTION(blsp4_uart), + MSM_PIN_FUNCTION(blsp5_i2c), + MSM_PIN_FUNCTION(blsp5_uart), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(mdc), + MSM_PIN_FUNCTION(mdio), + MSM_PIN_FUNCTION(pcie0_clk), + MSM_PIN_FUNCTION(pcie0_wake), + MSM_PIN_FUNCTION(pcie1_clk), + MSM_PIN_FUNCTION(pcie1_wake), + MSM_PIN_FUNCTION(pcie2_clk), + MSM_PIN_FUNCTION(pcie2_wake), + MSM_PIN_FUNCTION(pcie3_clk), + MSM_PIN_FUNCTION(pcie3_wake), + MSM_PIN_FUNCTION(qspi_data), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(sdc_data), + MSM_PIN_FUNCTION(sdc_clk), + MSM_PIN_FUNCTION(sdc_cmd), + MSM_PIN_FUNCTION(sdc_rclk), +}; + +typedef unsigned int msm_pin_function[10]; + +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ + [id] = { msm_mux_gpio, /* gpio mode */ \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9, \ + } + +static const msm_pin_function ipq9574_pin_functions[] = { + PINGROUP(0, sdc_data, qspi_data, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(1, sdc_data, qspi_data, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(2, sdc_data, qspi_data, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(3, sdc_data, qspi_data, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(4, sdc_cmd, qspi_cs, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(5, sdc_clk, qspi_clk, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(6, sdc_data, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(7, sdc_data, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(8, sdc_data, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(9, sdc_data, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(10, sdc_rclk, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(11, blsp0_spi, blsp0_uart, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(12, blsp0_spi, blsp0_uart, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(13, blsp0_spi, blsp0_uart, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(14, blsp0_spi, blsp0_uart, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(15, blsp3_spi, blsp3_i2c, blsp3_uart, NA, NA, NA, NA, NA, NA), + PINGROUP(16, blsp3_spi, blsp3_i2c, blsp3_uart, NA, NA, NA, NA, NA, NA), + PINGROUP(17, blsp3_spi, blsp3_uart, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(18, blsp3_spi, blsp3_uart, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(19, blsp3_spi, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(20, blsp3_spi, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(21, blsp3_spi, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(22, pcie0_clk, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(23, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(24, pcie0_wake, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(25, pcie1_clk, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(26, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(27, pcie1_wake, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(28, pcie2_clk, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(29, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(30, pcie2_wake, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(31, pcie3_clk, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(32, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(33, pcie3_wake, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(34, blsp2_uart, blsp2_i2c, blsp2_spi, blsp1_uart, NA, NA, NA, NA, NA), + PINGROUP(35, blsp2_uart, blsp2_i2c, blsp2_spi, blsp1_uart, NA, NA, NA, NA, NA), + PINGROUP(36, blsp1_uart, blsp1_i2c, blsp2_spi, NA, NA, NA, NA, NA, NA), + PINGROUP(37, blsp1_uart, blsp1_i2c, blsp2_spi, NA, NA, NA, NA, NA, NA), + PINGROUP(38, mdc, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(39, mdio, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(40, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(41, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(42, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(43, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(44, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(45, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(46, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(47, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(48, blsp5_i2c, blsp5_uart, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(49, blsp5_i2c, blsp5_uart, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(50, blsp4_uart, blsp4_i2c, blsp4_spi, NA, NA, NA, NA, NA, NA), + PINGROUP(51, blsp4_uart, blsp4_i2c, blsp4_spi, NA, NA, NA, NA, NA, NA), + PINGROUP(52, blsp4_uart, blsp4_spi, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(53, blsp4_uart, blsp4_spi, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(54, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(55, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(56, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(57, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(58, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(59, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(60, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(61, blsp1_spi, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(62, blsp1_spi, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(63, blsp1_spi, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(64, blsp1_spi, NA, NA, NA, NA, NA, NA, NA, NA), +}; + +static const char *ipq9574_get_function_name(struct udevice *dev, + unsigned int selector) +{ + return msm_pinctrl_functions[selector].name; +} + +static const char *ipq9574_get_pin_name(struct udevice *dev, + unsigned int selector) +{ + snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector); + return pin_name; +} + +static int ipq9574_get_function_mux(unsigned int pin, unsigned int selector) +{ + unsigned int i; + const msm_pin_function *func = ipq9574_pin_functions + pin; + + for (i = 0; i < 10; i++) + if ((*func)[i] == selector) + return i; + + debug("Can't find requested function for pin:selector %u:%u\n", + pin, selector); + + return -EINVAL; +} + +static const struct msm_pinctrl_data ipq9574_data = { + .pin_data = { + .pin_count = 65, + }, + .functions_count = ARRAY_SIZE(msm_pinctrl_functions), + .get_function_name = ipq9574_get_function_name, + .get_function_mux = ipq9574_get_function_mux, + .get_pin_name = ipq9574_get_pin_name, +}; + +static const struct udevice_id msm_pinctrl_ids[] = { + { .compatible = "qcom,ipq9574-tlmm", .data = (ulong)&ipq9574_data }, + { /* Sentinal */ } +}; + +U_BOOT_DRIVER(pinctrl_ipq9574) = { + .name = "pinctrl_ipq9574", + .id = UCLASS_NOP, + .of_match = msm_pinctrl_ids, + .ops = &msm_pinctrl_ops, + .bind = msm_pinctrl_bind, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/pinctrl/qcom/pinctrl-qcm2290.c b/drivers/pinctrl/qcom/pinctrl-qcm2290.c index af969e177d7..0c2222ce663 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcm2290.c +++ b/drivers/pinctrl/qcom/pinctrl-qcm2290.c @@ -38,7 +38,7 @@ static const char *qcm2290_get_pin_name(struct udevice *dev, unsigned int select return pin_name; } -static unsigned int qcm2290_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector) +static int qcm2290_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector) { return msm_pinctrl_functions[selector].val; } diff --git a/drivers/pinctrl/qcom/pinctrl-qcom.c b/drivers/pinctrl/qcom/pinctrl-qcom.c index 26a3fba194a..24d031947a3 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcom.c +++ b/drivers/pinctrl/qcom/pinctrl-qcom.c @@ -92,7 +92,10 @@ static int msm_pinmux_set(struct udevice *dev, unsigned int pin_selector, unsigned int func_selector) { struct msm_pinctrl_priv *priv = dev_get_priv(dev); - u32 func = priv->data->get_function_mux(pin_selector, func_selector); + int func = priv->data->get_function_mux(pin_selector, func_selector); + + if (func < 0) + return func; /* Always NOP for special pins, assume they're in the correct state */ if (qcom_is_special_pin(&priv->data->pin_data, pin_selector)) diff --git a/drivers/pinctrl/qcom/pinctrl-qcom.h b/drivers/pinctrl/qcom/pinctrl-qcom.h index 49b7bfbc001..cd167e63868 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcom.h +++ b/drivers/pinctrl/qcom/pinctrl-qcom.h @@ -18,8 +18,7 @@ struct msm_pinctrl_data { int functions_count; const char *(*get_function_name)(struct udevice *dev, unsigned int selector); - unsigned int (*get_function_mux)(unsigned int pin, - unsigned int selector); + int (*get_function_mux)(unsigned int pin, unsigned int selector); const char *(*get_pin_name)(struct udevice *dev, unsigned int selector); }; diff --git a/drivers/pinctrl/qcom/pinctrl-qcs404.c b/drivers/pinctrl/qcom/pinctrl-qcs404.c index fb6defaeddf..c272595aa2a 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcs404.c +++ b/drivers/pinctrl/qcom/pinctrl-qcs404.c @@ -93,8 +93,8 @@ static const char *qcs404_get_pin_name(struct udevice *dev, } } -static unsigned int qcs404_get_function_mux(__maybe_unused unsigned int pin, - unsigned int selector) +static int qcs404_get_function_mux(__maybe_unused unsigned int pin, + unsigned int selector) { return msm_pinctrl_functions[selector].val; } diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280.c b/drivers/pinctrl/qcom/pinctrl-sc7280.c new file mode 100644 index 00000000000..fe87947fbbf --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-sc7280.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Qualcomm sc7280 pinctrl + * + * (C) Copyright 2024 Linaro Ltd. + * + */ + +#include <dm.h> + +#include "pinctrl-qcom.h" + +#define WEST 0x00000000 +#define SOUTH 0x00400000 +#define NORTH 0x00800000 + +#define MAX_PIN_NAME_LEN 32 +static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); + +static const struct pinctrl_function msm_pinctrl_functions[] = { + { "qup05", 1 }, + { "gpio", 0 }, + { "pcie1_clkreqn", 3}, +}; +#define SDC_PINGROUP(pg_name, ctl, pull, drv) \ + { \ + .name = pg_name, \ + .ctl_reg = ctl, \ + .io_reg = 0, \ + .pull_bit = pull, \ + .drv_bit = drv, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = -1, \ + } + +#define UFS_RESET(pg_name, offset) \ + { \ + .name = pg_name, \ + .ctl_reg = offset, \ + .io_reg = offset + 0x4, \ + .pull_bit = 3, \ + .drv_bit = 0, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = 0, \ + } + +static const struct msm_special_pin_data sc7280_special_pins_data[] = { + [0] = UFS_RESET("ufs_reset", SOUTH + 0xbe000), + [1] = SDC_PINGROUP("sdc1_rclk", 0xb3004, 0, 6), + [2] = SDC_PINGROUP("sdc1_clk", 0xb3000, 13, 6), + [3] = SDC_PINGROUP("sdc1_cmd", 0xb3000, 11, 3), + [4] = SDC_PINGROUP("sdc1_data", 0xb3000, 9, 0), + [5] = SDC_PINGROUP("sdc2_clk", 0xb4000, 14, 6), + [6] = SDC_PINGROUP("sdc2_cmd", 0xb4000, 11, 3), + [7] = SDC_PINGROUP("sdc2_data", 0xb4000, 9, 0), +}; + +static const char *sc7280_get_function_name(struct udevice *dev, unsigned int selector) +{ + return msm_pinctrl_functions[selector].name; +} + +static const char *sc7280_get_pin_name(struct udevice *dev, unsigned int selector) +{ + if (selector >= 175 && selector <= 182) + snprintf(pin_name, MAX_PIN_NAME_LEN, + sc7280_special_pins_data[selector - 175].name); + else + snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector); + + return pin_name; +} + +static int sc7280_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector) +{ + return msm_pinctrl_functions[selector].val; +} + +static struct msm_pinctrl_data sc7280_data = { + .pin_data = { + .pin_count = 183, + .special_pins_start = 175, + .special_pins_data = sc7280_special_pins_data, + }, + .functions_count = ARRAY_SIZE(msm_pinctrl_functions), + .get_function_name = sc7280_get_function_name, + .get_function_mux = sc7280_get_function_mux, + .get_pin_name = sc7280_get_pin_name, +}; + +static const struct udevice_id msm_pinctrl_ids[] = { + { + .compatible = "qcom,sc7280-pinctrl", + .data = (ulong)&sc7280_data + }, + { /* Sentinel */ } }; + +U_BOOT_DRIVER(pinctrl_sc7280) = { + .name = "pinctrl_sc7280", + .id = UCLASS_NOP, + .of_match = msm_pinctrl_ids, + .ops = &msm_pinctrl_ops, + .bind = msm_pinctrl_bind, +}; diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c index f1a23f51099..3f55fc81c8e 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm845.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c @@ -80,8 +80,8 @@ static const char *sdm845_get_pin_name(struct udevice *dev, return pin_name; } -static unsigned int sdm845_get_function_mux(__maybe_unused unsigned int pin, - unsigned int selector) +static int sdm845_get_function_mux(__maybe_unused unsigned int pin, + unsigned int selector) { return msm_pinctrl_functions[selector].val; } diff --git a/drivers/pinctrl/qcom/pinctrl-sm6115.c b/drivers/pinctrl/qcom/pinctrl-sm6115.c index f07f39f4ac3..7e80ea39a12 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6115.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6115.c @@ -167,7 +167,7 @@ static const char *sm6115_get_pin_name(struct udevice *dev, unsigned int selecto return pin_name; } -static unsigned int sm6115_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector) +static int sm6115_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector) { return msm_pinctrl_functions[selector].val; } diff --git a/drivers/pinctrl/qcom/pinctrl-sm8150.c b/drivers/pinctrl/qcom/pinctrl-sm8150.c index 1fb2ffb9597..fe789e8639b 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8150.c @@ -123,8 +123,8 @@ static const char *sm8150_get_pin_name(struct udevice *dev, return pin_name; } -static unsigned int sm8150_get_function_mux(__maybe_unused unsigned int pin, - unsigned int selector) +static int sm8150_get_function_mux(__maybe_unused unsigned int pin, + unsigned int selector) { return msm_pinctrl_functions[selector].val; } diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250.c b/drivers/pinctrl/qcom/pinctrl-sm8250.c index b21cdc4d24b..d5447651695 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8250.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8250.c @@ -99,7 +99,7 @@ static const char *sm8250_get_pin_name(struct udevice *dev, unsigned int selecto return pin_name; } -static unsigned int sm8250_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector) +static int sm8250_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector) { return msm_pinctrl_functions[selector].val; } diff --git a/drivers/pinctrl/qcom/pinctrl-sm8550.c b/drivers/pinctrl/qcom/pinctrl-sm8550.c index 25b972a6d82..f7fcad0e4aa 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8550.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8550.c @@ -68,8 +68,8 @@ static const char *sm8550_get_pin_name(struct udevice *dev, return pin_name; } -static unsigned int sm8550_get_function_mux(__maybe_unused unsigned int pin, - unsigned int selector) +static int sm8550_get_function_mux(__maybe_unused unsigned int pin, + unsigned int selector) { return msm_pinctrl_functions[selector].val; } diff --git a/drivers/pinctrl/qcom/pinctrl-sm8650.c b/drivers/pinctrl/qcom/pinctrl-sm8650.c index 9146d6abd9a..6b9d56b1058 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8650.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8650.c @@ -69,8 +69,8 @@ static const char *sm8650_get_pin_name(struct udevice *dev, return pin_name; } -static unsigned int sm8650_get_function_mux(__maybe_unused unsigned int pin, - unsigned int selector) +static int sm8650_get_function_mux(__maybe_unused unsigned int pin, + unsigned int selector) { return msm_pinctrl_functions[selector].val; } diff --git a/drivers/pinctrl/qcom/pinctrl-x1e80100.c b/drivers/pinctrl/qcom/pinctrl-x1e80100.c index f39dc426d68..319667bfc16 100644 --- a/drivers/pinctrl/qcom/pinctrl-x1e80100.c +++ b/drivers/pinctrl/qcom/pinctrl-x1e80100.c @@ -72,8 +72,8 @@ static const char *x1e80100_get_pin_name(struct udevice *dev, return pin_name; } -static unsigned int x1e80100_get_function_mux(__maybe_unused unsigned int pin, - unsigned int selector) +static int x1e80100_get_function_mux(__maybe_unused unsigned int pin, + unsigned int selector) { return msm_pinctrl_functions[selector].val; } diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index 958f337c7e7..8f102a92c23 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -478,3 +478,11 @@ config DM_REGULATOR_TPS65219 features for REGULATOR TPS65219 and the family of TPS65219 PMICs. TPS65219 series of PMICs have 3 single phase BUCKs & 4 LDOs. The driver implements get/set api for value and enable. + +config REGULATOR_RZG2L_USBPHY + bool "Enable driver for RZ/G2L USB PHY VBUS supply" + depends on DM_REGULATOR + help + Enable this option to support controlling the VBUS supply in + the USB PHY peripheral of the Renesas RZ/G2L SoC. This option + is required in order to use the USB OTG port. diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile index ca6c89d13b5..4382d4b3ab9 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -42,3 +42,4 @@ obj-$(CONFIG_DM_REGULATOR_TPS65941) += tps65941_regulator.o obj-$(CONFIG_DM_REGULATOR_SCMI) += scmi_regulator.o obj-$(CONFIG_$(XPL_)DM_REGULATOR_ANATOP) += anatop_regulator.o obj-$(CONFIG_DM_REGULATOR_TPS65219) += tps65219_regulator.o +obj-$(CONFIG_REGULATOR_RZG2L_USBPHY) += rzg2l-usbphy-regulator.o diff --git a/drivers/power/regulator/rzg2l-usbphy-regulator.c b/drivers/power/regulator/rzg2l-usbphy-regulator.c new file mode 100644 index 00000000000..451f04c140e --- /dev/null +++ b/drivers/power/regulator/rzg2l-usbphy-regulator.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 Renesas Electronics Corporation + */ + +#include <asm/io.h> +#include <dm.h> +#include <power/regulator.h> +#include <renesas/rzg2l-usbphy.h> + +#define VBENCTL 0x03c +#define VBENCTL_VBUS_SEL BIT(0) + +static int rzg2l_usbphy_regulator_set_enable(struct udevice *dev, bool enable) +{ + struct rzg2l_usbphy_ctrl_priv *priv = dev_get_priv(dev->parent); + + if (enable) + clrbits_le32(priv->regs + VBENCTL, VBENCTL_VBUS_SEL); + else + setbits_le32(priv->regs + VBENCTL, VBENCTL_VBUS_SEL); + + return 0; +} + +static int rzg2l_usbphy_regulator_get_enable(struct udevice *dev) +{ + struct rzg2l_usbphy_ctrl_priv *priv = dev_get_priv(dev->parent); + + return !!readl(priv->regs + VBENCTL) & VBENCTL_VBUS_SEL; +} + +static const struct dm_regulator_ops rzg2l_usbphy_regulator_ops = { + .get_enable = rzg2l_usbphy_regulator_get_enable, + .set_enable = rzg2l_usbphy_regulator_set_enable, +}; + +U_BOOT_DRIVER(rzg2l_usbphy_regulator) = { + .name = "rzg2l_usbphy_regulator", + .id = UCLASS_REGULATOR, + .ops = &rzg2l_usbphy_regulator_ops, +}; diff --git a/drivers/ram/renesas/dbsc5/dbsc5.c b/drivers/ram/renesas/dbsc5/dbsc5.c index d24b7c5c30a..4cbc6aeda43 100644 --- a/drivers/ram/renesas/dbsc5/dbsc5.c +++ b/drivers/ram/renesas/dbsc5/dbsc5.c @@ -59,7 +59,8 @@ int renesas_dbsc5_bind(struct udevice *dev) struct renesas_dbsc5_data r8a779g0_dbsc5_data = { .clock_node = "renesas,r8a779g0-cpg-mssr", - .reset_node = "renesas,r8a779g0-rst" + .reset_node = "renesas,r8a779g0-rst", + .otp_node = "renesas,r8a779g0-otp", }; static const struct udevice_id renesas_dbsc5_ids[] = { diff --git a/drivers/ram/renesas/dbsc5/dbsc5.h b/drivers/ram/renesas/dbsc5/dbsc5.h index c410eb0c5ed..bf22fcb8c11 100644 --- a/drivers/ram/renesas/dbsc5/dbsc5.h +++ b/drivers/ram/renesas/dbsc5/dbsc5.h @@ -23,6 +23,7 @@ struct renesas_dbsc5_data { const char *clock_node; const char *reset_node; + const char *otp_node; }; #endif /* __DRIVERS_RAM_RENESAS_DBSC5_DBSC5_H__ */ diff --git a/drivers/ram/renesas/dbsc5/dram.c b/drivers/ram/renesas/dbsc5/dram.c index 210a68f6496..6f78afb0ab5 100644 --- a/drivers/ram/renesas/dbsc5/dram.c +++ b/drivers/ram/renesas/dbsc5/dram.c @@ -4,6 +4,7 @@ */ #include <asm/io.h> +#include <dbsc5.h> #include <dm.h> #include <errno.h> #include <hang.h> @@ -12,13 +13,6 @@ #include <linux/sizes.h> #include "dbsc5.h" -/* The number of channels V4H has */ -#define DRAM_CH_CNT 4 -/* The number of slices V4H has */ -#define SLICE_CNT 2 -/* The number of chip select V4H has */ -#define CS_CNT 2 - /* Number of array elements in Data Slice */ #define DDR_PHY_SLICE_REGSET_SIZE_V4H 0x100 /* Number of array elements in Data Slice */ @@ -220,6 +214,7 @@ static const u16 jedec_spec2_tRFC_ab[] = { #define PHY_RDLVL_RDDQS_DQ_TE_DLY_OBS DDR_REGDEF(0x00, 0x09, 0x103F) #define PHY_WDQLVL_STATUS_OBS DDR_REGDEF(0x00, 0x20, 0x1043) #define PHY_DATA_DC_CAL_START DDR_REGDEF(0x18, 0x01, 0x104D) +#define PHY_SLV_DLY_CTRL_GATE_DISABLE DDR_REGDEF(0x10, 0x01, 0x104E) #define PHY_REGULATOR_EN_CNT DDR_REGDEF(0x18, 0x06, 0x1050) #define PHY_VREF_INITIAL_START_POINT DDR_REGDEF(0x00, 0x09, 0x1055) #define PHY_VREF_INITIAL_STOP_POINT DDR_REGDEF(0x10, 0x09, 0x1055) @@ -469,7 +464,7 @@ static const u32 DDR_PHY_SLICE_REGSET_V4H[DDR_PHY_SLICE_REGSET_NUM_V4H] = { 0x00000000, 0x00500050, 0x00500050, 0x00500050, 0x00500050, 0x0D000050, 0x10100004, 0x06102010, 0x61619041, 0x07097000, 0x00644180, 0x00803280, - 0x00808001, 0x13010100, 0x02000016, 0x10001003, + 0x00808001, 0x13010101, 0x02000016, 0x10001003, 0x06093E42, 0x0F063D01, 0x011700C8, 0x04100140, 0x00000100, 0x000001D1, 0x05000068, 0x00030402, 0x01400000, 0x80800300, 0x00160010, 0x76543210, @@ -512,8 +507,8 @@ static const u32 DDR_PHY_ADR_G_REGSET_V4H[DDR_PHY_ADR_G_REGSET_NUM_V4H] = { 0x00040101, 0x00000000, 0x00000000, 0x00000064, 0x00000000, 0x00000000, 0x39421B42, 0x00010124, 0x00520052, 0x00000052, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x07030102, + 0x00010001, 0x00000000, 0x00000000, 0x00010001, + 0x00000000, 0x00000000, 0x00010001, 0x07030102, 0x01030307, 0x00000054, 0x00004096, 0x08200820, 0x08200820, 0x08200820, 0x08200820, 0x00000820, 0x004103B8, 0x0000003F, 0x000C0006, 0x00000000, @@ -1294,7 +1289,7 @@ static const struct dbsc5_table_patch dbsc5_table_patch_slice_mbpsdiv_572 = { }; static const struct dbsc5_table_patch dbsc5_table_patch_adr_g_mbpsdiv_572 = { - PHY_PAD_ACS_RX_PCLK_CLK_SEL, 0x03 + PHY_PAD_ACS_RX_PCLK_CLK_SEL, 0x02 }; static const struct dbsc5_table_patch dbsc5_table_patch_adr_g_mbpsdiv_400[] = { @@ -1374,46 +1369,6 @@ static const u32 PI_DARRAY3_1_CSx_Fx[CS_CNT][3] = { #define CLK_DIV(a, diva, b, divb) (((a) * (divb)) / ((b) * (diva))) -struct renesas_dbsc5_board_config { - /* Channels in use */ - u8 bdcfg_phyvalid; - /* Read vref (SoC) training range */ - u32 bdcfg_vref_r; - /* Write vref (MR14, MR15) training range */ - u16 bdcfg_vref_w; - /* CA vref (MR12) training range */ - u16 bdcfg_vref_ca; - /* RFM required check */ - bool bdcfg_rfm_chk; - - /* Board parameter about channels */ - struct { - /* - * 0x00: 4Gb dual channel die / 2Gb single channel die - * 0x01: 6Gb dual channel die / 3Gb single channel die - * 0x02: 8Gb dual channel die / 4Gb single channel die - * 0x03: 12Gb dual channel die / 6Gb single channel die - * 0x04: 16Gb dual channel die / 8Gb single channel die - * 0x05: 24Gb dual channel die / 12Gb single channel die - * 0x06: 32Gb dual channel die / 16Gb single channel die - * 0x07: 24Gb single channel die - * 0x08: 32Gb single channel die - * 0xFF: NO_MEMORY - */ - u8 bdcfg_ddr_density[CS_CNT]; - /* SoC caX([6][5][4][3][2][1][0]) -> MEM caY: */ - u32 bdcfg_ca_swap; - /* SoC dqsX([1][0]) -> MEM dqsY: */ - u8 bdcfg_dqs_swap; - /* SoC dq([7][6][5][4][3][2][1][0]) -> MEM dqY/dm: (8 means DM) */ - u32 bdcfg_dq_swap[SLICE_CNT]; - /* SoC dm -> MEM dqY/dm: (8 means DM) */ - u8 bdcfg_dm_swap[SLICE_CNT]; - /* SoC ckeX([1][0]) -> MEM csY */ - u8 bdcfg_cs_swap; - } ch[4]; -}; - struct renesas_dbsc5_dram_priv { void __iomem *regs; void __iomem *cpg_regs; @@ -1713,14 +1668,17 @@ static void dbsc5_clk_wait_dbpdstat1(struct udevice *dev, u32 status) { struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); void __iomem *regs_dbsc_d = priv->regs + DBSC5_DBSC_D_OFFSET; - u32 i, ch, reg; + u32 i, ch, chk, reg; for (i = 0; i < 2; i++) { do { reg = status; - r_foreach_vch(dev, ch) + chk = 0; + r_foreach_vch(dev, ch) { reg &= readl(regs_dbsc_d + DBSC_DBPDSTAT1(ch)); - } while (reg != status); + chk |= readl(regs_dbsc_d + DBSC_DBPDSTAT0(ch)); + } + } while (reg != status && !(chk & BIT(0))); } } @@ -2192,7 +2150,7 @@ static void dbsc5_ddrtbl_calc(struct renesas_dbsc5_dram_priv *priv) if (js1[i].fx3 * 2 * priv->ddr_mbpsdiv >= priv->ddr_mbps * 3) break; - priv->js1_ind = max(i, JS1_USABLEC_SPEC_HI); + priv->js1_ind = clamp(i, 0, JS1_USABLEC_SPEC_HI); priv->RL = js1[priv->js1_ind].RLset1; priv->WL = js1[priv->js1_ind].WLsetA; @@ -2635,7 +2593,7 @@ static void dbsc5_dbsc_regset(struct udevice *dev) */ dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(11), priv->RL + 4 + priv->js2[JS2_tWCK2DQO_HF] - - js1[priv->js1_ind].ODTLon - priv->js2[JS2_tODTon_min]); + js1[priv->js1_ind].ODTLon - priv->js2[JS2_tODTon_min] + 2); /* DBTR12.TWRRD_S : WL + BL/2 + tWTR_S, TWRRD_L : WL + BL + tWTR_L */ dbsc5_reg_write(regs_dbsc_d + DBSC_DBTR(12), @@ -3491,13 +3449,10 @@ static void dbsc5_manual_write_dca(struct udevice *dev) { struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); const u32 rank = priv->ch_have_this_cs[1] ? 0x2 : 0x1; - u32 slv_dly_center[DRAM_CH_CNT][CS_CNT][SLICE_CNT]; - u32 slv_dly_center_cyc; - u32 slv_dly_center_dly; + u32 phy_slv_dly[DRAM_CH_CNT][CS_CNT][SLICE_CNT]; + u32 phy_slv_dly_avg[DRAM_CH_CNT][SLICE_CNT]; u32 slv_dly_min[DRAM_CH_CNT][SLICE_CNT]; u32 slv_dly_max[DRAM_CH_CNT][SLICE_CNT]; - u32 slv_dly_min_tmp[DRAM_CH_CNT][CS_CNT][SLICE_CNT]; - u32 slv_dly_max_tmp[DRAM_CH_CNT][CS_CNT][SLICE_CNT]; u32 phy_dcc_code_min[DRAM_CH_CNT][SLICE_CNT]; u32 phy_dcc_code_max[DRAM_CH_CNT][SLICE_CNT]; u32 phy_dcc_code_mid; @@ -3521,18 +3476,9 @@ static void dbsc5_manual_write_dca(struct udevice *dev) dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_PER_CS_TRAINING_INDEX, cs); r_foreach_vch(dev, ch) { for (slice = 0; slice < SLICE_CNT; slice++) { - slv_dly_center[ch][cs][slice] = - dbsc5_ddr_getval_slice(dev, ch, slice, PHY_CLK_WRDQS_SLAVE_DELAY); - slv_dly_center_cyc = slv_dly_center[ch][cs][slice] & 0x180; - slv_dly_center_dly = slv_dly_center[ch][cs][slice] & 0x7F; - slv_dly_min_tmp[ch][cs][slice] = - slv_dly_center_cyc | - (slv_dly_center_dly * ratio_min / ratio_min_div); - slv_dly_max_tmp[ch][cs][slice] = slv_dly_center_cyc; - if ((slv_dly_center_dly * ratio_max) > (0x7F * ratio_max_div)) - slv_dly_max_tmp[ch][cs][slice] |= 0x7F; - else - slv_dly_max_tmp[ch][cs][slice] |= slv_dly_center_dly * ratio_max / ratio_max_div; + phy_slv_dly[ch][cs][slice] = + dbsc5_ddr_getval_slice(dev, ch, slice, + PHY_CLK_WRDQS_SLAVE_DELAY); } } } @@ -3540,22 +3486,22 @@ static void dbsc5_manual_write_dca(struct udevice *dev) r_foreach_vch(dev, ch) { for (slice = 0; slice < SLICE_CNT; slice++) { if (rank == 0x2) { - if (slv_dly_max_tmp[ch][0][slice] < slv_dly_max_tmp[ch][1][slice]) - slv_dly_max[ch][slice] = slv_dly_max_tmp[ch][1][slice]; - else - slv_dly_max[ch][slice] = slv_dly_max_tmp[ch][0][slice]; - - if (slv_dly_min_tmp[ch][0][slice] < slv_dly_min_tmp[ch][1][slice]) - slv_dly_min[ch][slice] = slv_dly_min_tmp[ch][0][slice]; - else - slv_dly_min[ch][slice] = slv_dly_min_tmp[ch][1][slice]; + /* Calculate average between ranks */ + phy_slv_dly_avg[ch][slice] = (phy_slv_dly[ch][0][slice] + + phy_slv_dly[ch][1][slice]) / 2; } else { - slv_dly_max[ch][slice] = slv_dly_max_tmp[ch][0][slice]; - slv_dly_min[ch][slice] = slv_dly_min_tmp[ch][0][slice]; + phy_slv_dly_avg[ch][slice] = phy_slv_dly[ch][0][slice]; } + /* Determine the search range */ + slv_dly_min[ch][slice] = (phy_slv_dly_avg[ch][slice] & 0x07F) * ratio_min / ratio_min_div; + slv_dly_max[ch][slice] = (phy_slv_dly_avg[ch][slice] & 0x07F) * ratio_max / ratio_max_div; + if (slv_dly_max[ch][slice] > 0x7F) + slv_dly_max[ch][slice] = 0x7F; } } + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_SLV_DLY_CTRL_GATE_DISABLE, 0x1); + for (i = 0; i <= 0x7F; i++) { r_foreach_vch(dev, ch) { for (slice = 0; slice < SLICE_CNT; slice++) { @@ -3621,13 +3567,16 @@ static void dbsc5_manual_write_dca(struct udevice *dev) for (slice = 0; slice < SLICE_CNT; slice++) { dbsc5_ddr_setval_slice(dev, ch, slice, PHY_CLK_WRDQS_SLAVE_DELAY, - slv_dly_center[ch][cs][slice]); + phy_slv_dly[ch][cs][slice]); dbsc5_ddr_setval_slice(dev, ch, slice, SC_PHY_WCK_CALC, 0x1); dbsc5_ddr_setval(dev, ch, SC_PHY_MANUAL_UPDATE, 0x1); } } } + + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_SLV_DLY_CTRL_GATE_DISABLE, 0x0); + dbsc5_ddr_setval_all_ch_all_slice(dev, PHY_PER_CS_TRAINING_MULTICAST_EN, 0x1); r_foreach_vch(dev, ch) { @@ -4369,16 +4318,20 @@ static int renesas_dbsc5_dram_probe(struct udevice *dev) { #define RST_MODEMR0 0x0 #define RST_MODEMR1 0x4 +#define OTP_MONITOR17 0x1144 struct renesas_dbsc5_data *data = (struct renesas_dbsc5_data *)dev_get_driver_data(dev); ofnode cnode = ofnode_by_compatible(ofnode_null(), data->clock_node); ofnode rnode = ofnode_by_compatible(ofnode_null(), data->reset_node); + ofnode onode = ofnode_by_compatible(ofnode_null(), data->otp_node); struct renesas_dbsc5_dram_priv *priv = dev_get_priv(dev); void __iomem *regs_dbsc_a = priv->regs + DBSC5_DBSC_A_OFFSET; void __iomem *regs_dbsc_d = priv->regs + DBSC5_DBSC_D_OFFSET; phys_addr_t rregs = ofnode_get_addr(rnode); const u32 modemr0 = readl(rregs + RST_MODEMR0); const u32 modemr1 = readl(rregs + RST_MODEMR1); - u32 breg, reg, md, sscg; + phys_addr_t oregs = ofnode_get_addr(onode); + const u32 otpmon17 = readl(oregs + OTP_MONITOR17); + u32 breg, reg, md, sscg, product; u32 ch, cs; /* Get board data */ @@ -4433,29 +4386,41 @@ static int renesas_dbsc5_dram_probe(struct udevice *dev) /* Decode DDR operating frequency from MD[37:36,19,17] pins */ md = ((modemr0 & BIT(19)) >> 18) | ((modemr0 & BIT(17)) >> 17); + product = otpmon17 & 0xff; sscg = (modemr1 >> 4) & 0x03; if (sscg == 2) { printf("MD[37:36] setting 0x%x not supported!", sscg); hang(); } - if (md == 0) { - if (sscg == 0) { - priv->ddr_mbps = 6400; - priv->ddr_mbpsdiv = 1; - } else { - priv->ddr_mbps = 19000; - priv->ddr_mbpsdiv = 3; - } - } else if (md == 1) { - priv->ddr_mbps = 6000; - priv->ddr_mbpsdiv = 1; - } else if (md == 1) { - priv->ddr_mbps = 5500; - priv->ddr_mbpsdiv = 1; - } else if (md == 1) { + if (product == 0x2) { /* V4H-3 */ priv->ddr_mbps = 4800; priv->ddr_mbpsdiv = 1; + } else if (product == 0x1) { /* V4H-5 */ + if (md == 3) + priv->ddr_mbps = 4800; + else + priv->ddr_mbps = 5000; + priv->ddr_mbpsdiv = 1; + } else { /* V4H-7 */ + if (md == 0) { + if (sscg == 0) { + priv->ddr_mbps = 6400; + priv->ddr_mbpsdiv = 1; + } else { + priv->ddr_mbps = 19000; + priv->ddr_mbpsdiv = 3; + } + } else if (md == 1) { + priv->ddr_mbps = 6000; + priv->ddr_mbpsdiv = 1; + } else if (md == 2) { + priv->ddr_mbps = 5500; + priv->ddr_mbpsdiv = 1; + } else if (md == 3) { + priv->ddr_mbps = 4800; + priv->ddr_mbpsdiv = 1; + } } priv->ddr_mul = CLK_DIV(priv->ddr_mbps, priv->ddr_mbpsdiv * 2, diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index fe5c1214f57..b408f19a20b 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -235,4 +235,20 @@ config RESET_AT91 This enables the Reset Controller driver support for Microchip/Atmel SoCs. Mainly used to expose assert/deassert methods to other drivers that require it. + +config RESET_RZG2L_USBPHY_CTRL + bool "Enable support for Renesas RZ/G2L USB 2.0 PHY control" + depends on DM_RESET + select REGULATOR_RZG2L_USBPHY + help + Enable support for controlling USB 2.0 PHY resets on the Renesas + RZ/G2L SoC. This is required for USB 2.0 functionality to work on this + SoC. + +config RESET_SPACEMIT_K1 + bool "Support for SPACEMIT's K1 Reset driver" + depends on DM_RESET + help + Support for SPACEMIT's K1 Reset system. Basic Assert/Deassert + is supported. endmenu diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index d99a78c9828..8cab734bdab 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -33,3 +33,5 @@ obj-$(CONFIG_RESET_ZYNQMP) += reset-zynqmp.o obj-$(CONFIG_RESET_DRA7) += reset-dra7.o obj-$(CONFIG_RESET_AT91) += reset-at91.o obj-$(CONFIG_$(PHASE_)RESET_JH7110) += reset-jh7110.o +obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o +obj-$(CONFIG_RESET_SPACEMIT_K1) += reset-spacemit-k1.o diff --git a/drivers/reset/reset-rzg2l-usbphy-ctrl.c b/drivers/reset/reset-rzg2l-usbphy-ctrl.c new file mode 100644 index 00000000000..622d7b9cf4f --- /dev/null +++ b/drivers/reset/reset-rzg2l-usbphy-ctrl.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 Renesas Electronics Corporation + */ + +#include <asm/io.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/device_compat.h> +#include <dm/lists.h> +#include <renesas/rzg2l-usbphy.h> +#include <reset-uclass.h> +#include <reset.h> + +#define RESET 0x000 + +#define RESET_SEL_PLLRESET BIT(12) +#define RESET_PLLRESET BIT(8) + +#define RESET_SEL_P2RESET BIT(5) +#define RESET_SEL_P1RESET BIT(4) +#define RESET_PHYRST_2 BIT(1) +#define RESET_PHYRST_1 BIT(0) + +#define PHY_RESET_MASK (RESET_PHYRST_1 | RESET_PHYRST_2) + +#define NUM_PORTS 2 + +static int rzg2l_usbphy_ctrl_assert(struct reset_ctl *reset_ctl) +{ + struct rzg2l_usbphy_ctrl_priv *priv = dev_get_priv(reset_ctl->dev); + u32 val; + + val = readl(priv->regs + RESET); + val |= reset_ctl->id ? RESET_PHYRST_2 : RESET_PHYRST_1; + + /* If both ports are in reset, we can also place the PLL into reset. */ + if ((val & PHY_RESET_MASK) == PHY_RESET_MASK) + val |= RESET_PLLRESET; + + writel(val, priv->regs + RESET); + return 0; +} + +static int rzg2l_usbphy_ctrl_deassert(struct reset_ctl *reset_ctl) +{ + struct rzg2l_usbphy_ctrl_priv *priv = dev_get_priv(reset_ctl->dev); + u32 val = reset_ctl->id ? RESET_PHYRST_2 : RESET_PHYRST_1; + + /* If either port is out of reset, the PLL must also be out of reset. */ + val |= RESET_PLLRESET; + + clrbits_le32(priv->regs + RESET, val); + return 0; +} + +static int rzg2l_usbphy_ctrl_of_xlate(struct reset_ctl *reset_ctl, + struct ofnode_phandle_args *args) +{ + if (args->args[0] >= NUM_PORTS) + return -EINVAL; + + reset_ctl->id = args->args[0]; + return 0; +} + +struct reset_ops rzg2l_usbphy_ctrl_ops = { + .rst_assert = rzg2l_usbphy_ctrl_assert, + .rst_deassert = rzg2l_usbphy_ctrl_deassert, + .of_xlate = rzg2l_usbphy_ctrl_of_xlate, +}; + +static int rzg2l_usbphy_ctrl_probe(struct udevice *dev) +{ + struct rzg2l_usbphy_ctrl_priv *priv = dev_get_priv(dev); + struct reset_ctl rst; + int ret; + + priv->regs = dev_read_addr(dev); + + ret = reset_get_by_index(dev, 0, &rst); + if (ret < 0) { + dev_err(dev, "failed to get reset line: %d\n", ret); + return ret; + } + + ret = reset_deassert(&rst); + if (ret < 0) { + dev_err(dev, "failed to de-assert reset line: %d\n", ret); + return ret; + } + + /* put pll and phy into reset state */ + setbits_le32(priv->regs + RESET, + RESET_SEL_PLLRESET | RESET_PLLRESET | + RESET_SEL_P1RESET | RESET_PHYRST_1 | + RESET_SEL_P2RESET | RESET_PHYRST_2); + + return 0; +} + +static const struct udevice_id rzg2l_usbphy_ctrl_ids[] = { + { .compatible = "renesas,rzg2l-usbphy-ctrl", }, + { /* sentinel */ } +}; + +static int rzg2l_usbphy_ctrl_bind(struct udevice *dev) +{ + struct driver *drv; + ofnode node; + int ret; + + node = ofnode_find_subnode(dev_ofnode(dev), "regulator-vbus"); + if (!ofnode_valid(node)) { + dev_err(dev, "Failed to find vbus regulator devicetree node\n"); + return -ENOENT; + } + + drv = lists_driver_lookup_name("rzg2l_usbphy_regulator"); + if (!drv) { + dev_err(dev, "Failed to find vbus regulator driver\n"); + return -ENOENT; + } + + ret = device_bind(dev, drv, dev->name, NULL, node, NULL); + if (ret) { + dev_err(dev, "Failed to bind vbus regulator: %d\n", ret); + return ret; + } + + return 0; +} + +U_BOOT_DRIVER(rzg2l_usbphy_ctrl) = { + .name = "rzg2l_usbphy_ctrl", + .id = UCLASS_RESET, + .of_match = rzg2l_usbphy_ctrl_ids, + .bind = rzg2l_usbphy_ctrl_bind, + .probe = rzg2l_usbphy_ctrl_probe, + .ops = &rzg2l_usbphy_ctrl_ops, + .priv_auto = sizeof(struct rzg2l_usbphy_ctrl_priv), +}; diff --git a/drivers/reset/reset-spacemit-k1.c b/drivers/reset/reset-spacemit-k1.c new file mode 100644 index 00000000000..613e002fc4f --- /dev/null +++ b/drivers/reset/reset-spacemit-k1.c @@ -0,0 +1,548 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Spacemit Inc. + * Copyright (C) 2025 Huan Zhou <pericycle.cc@gmail.com> + */ + +#include <asm/io.h> +#include <config.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dt-bindings/reset/spacemit-k1-reset.h> +#include <linux/bitops.h> +#include <reset-uclass.h> + +/* APBC register offset */ +#define APBC_UART1_CLK_RST 0x0 +#define APBC_UART2_CLK_RST 0x4 +#define APBC_GPIO_CLK_RST 0x8 +#define APBC_PWM0_CLK_RST 0xc +#define APBC_PWM1_CLK_RST 0x10 +#define APBC_PWM2_CLK_RST 0x14 +#define APBC_PWM3_CLK_RST 0x18 +#define APBC_TWSI8_CLK_RST 0x20 +#define APBC_UART3_CLK_RST 0x24 +#define APBC_RTC_CLK_RST 0x28 +#define APBC_TWSI0_CLK_RST 0x2c +#define APBC_TWSI1_CLK_RST 0x30 +#define APBC_TIMERS1_CLK_RST 0x34 +#define APBC_TWSI2_CLK_RST 0x38 +#define APBC_AIB_CLK_RST 0x3c +#define APBC_TWSI4_CLK_RST 0x40 +#define APBC_TIMERS2_CLK_RST 0x44 +#define APBC_ONEWIRE_CLK_RST 0x48 +#define APBC_TWSI5_CLK_RST 0x4c +#define APBC_DRO_CLK_RST 0x58 +#define APBC_IR_CLK_RST 0x5c +#define APBC_TWSI6_CLK_RST 0x60 +#define APBC_TWSI7_CLK_RST 0x68 +#define APBC_TSEN_CLK_RST 0x6c + +#define APBC_UART4_CLK_RST 0x70 +#define APBC_UART5_CLK_RST 0x74 +#define APBC_UART6_CLK_RST 0x78 +#define APBC_SSP3_CLK_RST 0x7c + +#define APBC_SSPA0_CLK_RST 0x80 +#define APBC_SSPA1_CLK_RST 0x84 + +#define APBC_IPC_AP2AUD_CLK_RST 0x90 +#define APBC_UART7_CLK_RST 0x94 +#define APBC_UART8_CLK_RST 0x98 +#define APBC_UART9_CLK_RST 0x9c + +#define APBC_CAN0_CLK_RST 0xa0 +#define APBC_PWM4_CLK_RST 0xa8 +#define APBC_PWM5_CLK_RST 0xac +#define APBC_PWM6_CLK_RST 0xb0 +#define APBC_PWM7_CLK_RST 0xb4 +#define APBC_PWM8_CLK_RST 0xb8 +#define APBC_PWM9_CLK_RST 0xbc +#define APBC_PWM10_CLK_RST 0xc0 +#define APBC_PWM11_CLK_RST 0xc4 +#define APBC_PWM12_CLK_RST 0xc8 +#define APBC_PWM13_CLK_RST 0xcc +#define APBC_PWM14_CLK_RST 0xd0 +#define APBC_PWM15_CLK_RST 0xd4 +#define APBC_PWM16_CLK_RST 0xd8 +#define APBC_PWM17_CLK_RST 0xdc +#define APBC_PWM18_CLK_RST 0xe0 +#define APBC_PWM19_CLK_RST 0xe4 +/* end of APBC register offset */ + +/* MPMU register offset */ +#define MPMU_WDTPCR 0x200 +/* end of MPMU register offset */ + +/* APMU register offset */ +#define APMU_JPG_CLK_RES_CTRL 0x20 +#define APMU_CSI_CCIC2_CLK_RES_CTRL 0x24 +#define APMU_ISP_CLK_RES_CTRL 0x38 +#define APMU_LCD_CLK_RES_CTRL1 0x44 +#define APMU_LCD_SPI_CLK_RES_CTRL 0x48 +#define APMU_LCD_CLK_RES_CTRL2 0x4c +#define APMU_CCIC_CLK_RES_CTRL 0x50 +#define APMU_SDH0_CLK_RES_CTRL 0x54 +#define APMU_SDH1_CLK_RES_CTRL 0x58 +#define APMU_USB_CLK_RES_CTRL 0x5c +#define APMU_QSPI_CLK_RES_CTRL 0x60 +#define APMU_USB_CLK_RES_CTRL 0x5c +#define APMU_DMA_CLK_RES_CTRL 0x64 +#define APMU_AES_CLK_RES_CTRL 0x68 +#define APMU_VPU_CLK_RES_CTRL 0xa4 +#define APMU_GPU_CLK_RES_CTRL 0xcc +#define APMU_SDH2_CLK_RES_CTRL 0xe0 +#define APMU_PMUA_MC_CTRL 0xe8 +#define APMU_PMU_CC2_AP 0x100 +#define APMU_PMUA_EM_CLK_RES_CTRL 0x104 + +#define APMU_AUDIO_CLK_RES_CTRL 0x14c +#define APMU_HDMI_CLK_RES_CTRL 0x1B8 + +#define APMU_PCIE_CLK_RES_CTRL_0 0x3cc +#define APMU_PCIE_CLK_RES_CTRL_1 0x3d4 +#define APMU_PCIE_CLK_RES_CTRL_2 0x3dc + +#define APMU_EMAC0_CLK_RES_CTRL 0x3e4 +#define APMU_EMAC1_CLK_RES_CTRL 0x3ec +/* end of APMU register offset */ + +/* APBC2 register offset */ +#define APBC2_UART1_CLK_RST 0x00 +#define APBC2_SSP2_CLK_RST 0x04 +#define APBC2_TWSI3_CLK_RST 0x08 +#define APBC2_RTC_CLK_RST 0x0c +#define APBC2_TIMERS0_CLK_RST 0x10 +#define APBC2_KPC_CLK_RST 0x14 +#define APBC2_GPIO_CLK_RST 0x1c +/* end of APBC2 register offset */ + +enum spacemit_reset_base_type { + RST_BASE_TYPE_MPMU = 0, + RST_BASE_TYPE_APMU = 1, + RST_BASE_TYPE_APBC = 2, + RST_BASE_TYPE_APBS = 3, + RST_BASE_TYPE_CIU = 4, + RST_BASE_TYPE_DCIU = 5, + RST_BASE_TYPE_DDRC = 6, + RST_BASE_TYPE_AUDC = 7, + RST_BASE_TYPE_APBC2 = 8, +}; + +struct spacemit_reset_signal { + u32 offset; + u32 mask; + u32 deassert_val; + u32 assert_val; + enum spacemit_reset_base_type type; +}; + +struct spacemit_reset_base { + void __iomem *mpmu_base; + void __iomem *apmu_base; + void __iomem *apbc_base; + void __iomem *apbs_base; + void __iomem *ciu_base; + void __iomem *dciu_base; + void __iomem *ddrc_base; + void __iomem *audio_ctrl_base; + void __iomem *apbc2_base; +}; + +struct spacemit_reset { + struct spacemit_reset_base io_base; + const struct spacemit_reset_signal *signals; +}; + +enum { + RESET_TWSI6_SPL = 0, + RESET_TWSI8_SPL, + RESET_SDH_AXI_SPL, + RESET_SDH0_SPL, + RESET_USB_AXI_SPL, + RESET_USBP1_AXI_SPL, + RESET_USB3_0_SPL, + RESET_QSPI_SPL, + RESET_QSPI_BUS_SPL, + RESET_AES_SPL, + RESET_SDH2_SPL, + RESET_NUMBER_SPL +}; + +static const struct spacemit_reset_signal + k1_reset_signals[RESET_NUMBER] = { + [RESET_UART1] = { APBC_UART1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_UART2] = { APBC_UART2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_GPIO] = { APBC_GPIO_CLK_RST, BIT(2), 0, + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM0] = { APBC_PWM0_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM1] = { APBC_PWM1_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM2] = { APBC_PWM2_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM3] = { APBC_PWM3_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM4] = { APBC_PWM4_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM5] = { APBC_PWM5_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM6] = { APBC_PWM6_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM7] = { APBC_PWM7_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM8] = { APBC_PWM8_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM9] = { APBC_PWM9_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM10] = { APBC_PWM10_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM11] = { APBC_PWM11_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM12] = { APBC_PWM12_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM13] = { APBC_PWM13_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM14] = { APBC_PWM14_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM15] = { APBC_PWM15_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM16] = { APBC_PWM16_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM17] = { APBC_PWM17_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM18] = { APBC_PWM18_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_PWM19] = { APBC_PWM19_CLK_RST, + BIT(2) | BIT(0), + BIT(0), + BIT(2), + RST_BASE_TYPE_APBC }, + [RESET_SSP3] = { APBC_SSP3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_UART3] = { APBC_UART3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_RTC] = { APBC_RTC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_TWSI0] = { APBC_TWSI0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_TIMERS1] = { APBC_TIMERS1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_AIB] = { APBC_AIB_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_TIMERS2] = { APBC_TIMERS2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_ONEWIRE] = { APBC_ONEWIRE_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_SSPA0] = { APBC_SSPA0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_SSPA1] = { APBC_SSPA1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_DRO] = { APBC_DRO_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_IR] = { APBC_IR_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_TWSI1] = { APBC_TWSI1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_TSEN] = { APBC_TSEN_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_TWSI2] = { APBC_TWSI2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_TWSI4] = { APBC_TWSI4_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_TWSI5] = { APBC_TWSI5_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_TWSI6] = { APBC_TWSI6_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_TWSI7] = { APBC_TWSI7_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_TWSI8] = { APBC_TWSI8_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_IPC_AP2AUD] = { APBC_IPC_AP2AUD_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_UART4] = { APBC_UART4_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_UART5] = { APBC_UART5_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_UART6] = { APBC_UART6_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_UART7] = { APBC_UART7_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_UART8] = { APBC_UART8_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_UART9] = { APBC_UART9_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + [RESET_CAN0] = { APBC_CAN0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, + /* MPMU */ + [RESET_WDT] = { MPMU_WDTPCR, BIT(2), 0, BIT(2), RST_BASE_TYPE_MPMU }, + /* APMU */ + [RESET_JPG] = { APMU_JPG_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, + [RESET_CSI] = { APMU_CSI_CCIC2_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, + [RESET_CCIC2_PHY] = { APMU_CSI_CCIC2_CLK_RES_CTRL, + BIT(2), + BIT(2), + 0, + RST_BASE_TYPE_APMU }, + [RESET_CCIC3_PHY] = { APMU_CSI_CCIC2_CLK_RES_CTRL, + BIT(29), + BIT(29), + 0, + RST_BASE_TYPE_APMU }, + [RESET_ISP] = { APMU_ISP_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, + [RESET_ISP_AHB] = { APMU_ISP_CLK_RES_CTRL, BIT(3), BIT(3), 0, RST_BASE_TYPE_APMU }, + [RESET_ISP_CI] = { APMU_ISP_CLK_RES_CTRL, BIT(16), BIT(16), 0, RST_BASE_TYPE_APMU }, + [RESET_ISP_CPP] = { APMU_ISP_CLK_RES_CTRL, BIT(27), BIT(27), 0, RST_BASE_TYPE_APMU }, + [RESET_LCD] = { APMU_LCD_CLK_RES_CTRL1, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU }, + [RESET_DSI_ESC] = { APMU_LCD_CLK_RES_CTRL1, BIT(3), BIT(3), 0, RST_BASE_TYPE_APMU }, + [RESET_V2D] = { APMU_LCD_CLK_RES_CTRL1, BIT(27), BIT(27), 0, RST_BASE_TYPE_APMU }, + [RESET_MIPI] = { APMU_LCD_CLK_RES_CTRL1, BIT(15), BIT(15), 0, RST_BASE_TYPE_APMU }, + [RESET_LCD_SPI] = { APMU_LCD_SPI_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, + [RESET_LCD_SPI_BUS] = { APMU_LCD_SPI_CLK_RES_CTRL, + BIT(4), + BIT(4), + 0, + RST_BASE_TYPE_APMU }, + [RESET_LCD_SPI_HBUS] = { APMU_LCD_SPI_CLK_RES_CTRL, + BIT(2), + BIT(2), + 0, + RST_BASE_TYPE_APMU }, + [RESET_LCD_MCLK] = { APMU_LCD_CLK_RES_CTRL2, BIT(9), BIT(9), 0, RST_BASE_TYPE_APMU }, + [RESET_CCIC_4X] = { APMU_CCIC_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, + [RESET_CCIC1_PHY] = { APMU_CCIC_CLK_RES_CTRL, BIT(2), BIT(2), 0, RST_BASE_TYPE_APMU }, + [RESET_SDH_AXI] = { APMU_SDH0_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, + [RESET_SDH0] = { APMU_SDH0_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, + [RESET_SDH1] = { APMU_SDH1_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, + [RESET_USB_AXI] = { APMU_USB_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, + [RESET_USBP1_AXI] = { APMU_USB_CLK_RES_CTRL, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU }, + [RESET_USB3_0] = { APMU_USB_CLK_RES_CTRL, + BIT(9) | BIT(10) | BIT(11), + BIT(9) | BIT(10) | BIT(11), + 0, + RST_BASE_TYPE_APMU }, + [RESET_QSPI] = { APMU_QSPI_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, + [RESET_QSPI_BUS] = { APMU_QSPI_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, + [RESET_DMA] = { APMU_DMA_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, + [RESET_AES] = { APMU_AES_CLK_RES_CTRL, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU }, + [RESET_VPU] = { APMU_VPU_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, + [RESET_GPU] = { APMU_GPU_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, + [RESET_SDH2] = { APMU_SDH2_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, + [RESET_MC] = { APMU_PMUA_MC_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, + [RESET_EM_AXI] = { APMU_PMUA_EM_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, + [RESET_EM] = { APMU_PMUA_EM_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, + [RESET_AUDIO_SYS] = { APMU_AUDIO_CLK_RES_CTRL, + BIT(0) | BIT(2) | BIT(3), + BIT(0) | BIT(2) | BIT(3), + 0, + RST_BASE_TYPE_APMU }, + [RESET_HDMI] = { APMU_HDMI_CLK_RES_CTRL, BIT(9), BIT(9), 0, RST_BASE_TYPE_APMU }, + [RESET_PCIE0] = { APMU_PCIE_CLK_RES_CTRL_0, + BIT(3) | BIT(4) | BIT(5) | BIT(8), + BIT(3) | BIT(4) | BIT(5), + BIT(8), + RST_BASE_TYPE_APMU }, + [RESET_PCIE1] = { APMU_PCIE_CLK_RES_CTRL_1, + BIT(3) | BIT(4) | BIT(5) | BIT(8), + BIT(3) | BIT(4) | BIT(5), + BIT(8), + RST_BASE_TYPE_APMU }, + [RESET_PCIE2] = { APMU_PCIE_CLK_RES_CTRL_2, 0x138, 0x38, 0x100, RST_BASE_TYPE_APMU }, + [RESET_EMAC0] = { APMU_EMAC0_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, + [RESET_EMAC1] = { APMU_EMAC1_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, + [RESET_SEC_UART1] = { APBC2_UART1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, + [RESET_SEC_SSP2] = { APBC2_SSP2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, + [RESET_SEC_TWSI3] = { APBC2_TWSI3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, + [RESET_SEC_RTC] = { APBC2_RTC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, + [RESET_SEC_TIMERS0] = { APBC2_TIMERS0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, + [RESET_SEC_KPC] = { APBC2_KPC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, + [RESET_SEC_GPIO] = { APBC2_GPIO_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, + }; + +static u32 spacemit_reset_read(struct spacemit_reset *reset, u32 id) +{ + void __iomem *base; + + switch (reset->signals[id].type) { + case RST_BASE_TYPE_APMU: + base = reset->io_base.apmu_base; + break; + case RST_BASE_TYPE_APBC: + base = reset->io_base.apbc_base; + break; + default: + base = reset->io_base.apbc_base; + break; + } + + return readl(base + reset->signals[id].offset); +} + +static void spacemit_reset_write(struct spacemit_reset *reset, u32 value, u32 id) +{ + void __iomem *base; + + switch (reset->signals[id].type) { + case RST_BASE_TYPE_APMU: + base = reset->io_base.apmu_base; + break; + case RST_BASE_TYPE_APBC: + base = reset->io_base.apbc_base; + break; + default: + base = reset->io_base.apbc_base; + break; + } + + writel(value, base + reset->signals[id].offset); +} + +static void spacemit_reset_set(struct reset_ctl *rst, u32 id, bool assert) +{ + u32 value; + struct spacemit_reset *reset = dev_get_priv(rst->dev); + + value = spacemit_reset_read(reset, id); + + if (assert) { + value &= ~reset->signals[id].mask; + value |= reset->signals[id].assert_val; + } else { + value &= ~reset->signals[id].mask; + value |= reset->signals[id].deassert_val; + } + + spacemit_reset_write(reset, value, id); +} + +static int spacemit_reset_update(struct reset_ctl *rst, bool assert) +{ + if (rst->id < RESET_UART1 || rst->id >= RESET_NUMBER) + return 0; + + /* can not write to twsi8 */ + if (rst->id == RESET_TWSI8) + return 0; + + spacemit_reset_set(rst, rst->id, assert); + return 0; +} + +static int spacemit_reset_assert(struct reset_ctl *rst) +{ + return spacemit_reset_update(rst, true); +} + +static int spacemit_reset_deassert(struct reset_ctl *rst) +{ + return spacemit_reset_update(rst, false); +} + +static int spacemit_k1_reset_probe(struct udevice *dev) +{ + struct spacemit_reset *reset = dev_get_priv(dev); + + reset->io_base.mpmu_base = (void *)dev_remap_addr_index(dev, 0); + if (!reset->io_base.mpmu_base) { + pr_err("failed to map mpmu registers\n"); + goto out; + } + + reset->io_base.apmu_base = (void *)dev_remap_addr_index(dev, 1); + if (!reset->io_base.apmu_base) { + pr_err("failed to map apmu registers\n"); + goto out; + } + + reset->io_base.apbc_base = (void *)dev_remap_addr_index(dev, 2); + if (!reset->io_base.apbc_base) { + pr_err("failed to map apbc registers\n"); + goto out; + } + + reset->io_base.apbs_base = (void *)dev_remap_addr_index(dev, 3); + if (!reset->io_base.apbs_base) { + pr_err("failed to map apbs registers\n"); + goto out; + } + + reset->io_base.ciu_base = (void *)dev_remap_addr_index(dev, 4); + if (!reset->io_base.ciu_base) { + pr_err("failed to map ciu registers\n"); + goto out; + } + + reset->io_base.dciu_base = (void *)dev_remap_addr_index(dev, 5); + if (!reset->io_base.dciu_base) { + pr_err("failed to map dragon ciu registers\n"); + goto out; + } + + reset->io_base.ddrc_base = (void *)dev_remap_addr_index(dev, 6); + if (!reset->io_base.ddrc_base) { + pr_err("failed to map ddrc registers\n"); + goto out; + } + + reset->io_base.apbc2_base = (void *)dev_remap_addr_index(dev, 7); + if (!reset->io_base.apbc2_base) { + pr_err("failed to map apbc2 registers\n"); + goto out; + } + + reset->signals = k1_reset_signals; + +out: + return 0; +} + +const struct reset_ops k1_reset_ops = { + .rst_assert = spacemit_reset_assert, + .rst_deassert = spacemit_reset_deassert, +}; + +static const struct udevice_id k1_reset_ids[] = { + { .compatible = "spacemit,k1-reset", }, + {}, +}; + +U_BOOT_DRIVER(k1_reset) = { + .name = "spacemit,k1-reset", + .id = UCLASS_RESET, + .ops = &k1_reset_ops, + .of_match = k1_reset_ids, + .probe = spacemit_k1_reset_probe, + .priv_auto = sizeof(struct spacemit_reset), +}; diff --git a/drivers/rng/msm_rng.c b/drivers/rng/msm_rng.c index f790d3b60f9..aab602c5ed0 100644 --- a/drivers/rng/msm_rng.c +++ b/drivers/rng/msm_rng.c @@ -44,6 +44,11 @@ static int msm_rng_read(struct udevice *dev, void *data, size_t len) u32 *retdata = data; size_t maxsize; u32 val; + int ret; + + ret = clk_enable(&priv->clk); + if (ret < 0) + return ret; /* calculate max size bytes to transfer back to caller */ maxsize = min_t(size_t, MAX_HW_FIFO_SIZE, len); @@ -66,6 +71,8 @@ static int msm_rng_read(struct udevice *dev, void *data, size_t len) break; } while (currsize < maxsize); + clk_disable(&priv->clk); + return 0; } @@ -76,7 +83,7 @@ static int msm_rng_enable(struct msm_rng_priv *priv, int enable) if (enable) { /* Enable PRNG only if it is not already enabled */ val = readl_relaxed(priv->base + PRNG_CONFIG); - if (val & PRNG_CONFIG_HW_ENABLE) { + if (!(val & PRNG_CONFIG_HW_ENABLE)) { val = readl_relaxed(priv->base + PRNG_LFSR_CFG); val &= ~PRNG_LFSR_CFG_MASK; val |= PRNG_LFSR_CFG_CLOCKS; @@ -118,7 +125,9 @@ static int msm_rng_probe(struct udevice *dev) if (ret < 0) return ret; - return msm_rng_enable(priv, 1); + ret = msm_rng_enable(priv, 1); + clk_disable(&priv->clk); + return ret; } static int msm_rng_remove(struct udevice *dev) diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig index 121194e4418..475540ffac7 100644 --- a/drivers/sysreset/Kconfig +++ b/drivers/sysreset/Kconfig @@ -242,7 +242,6 @@ config SYSRESET_RAA215300 config SYSRESET_QCOM_PSHOLD bool "Support sysreset for Qualcomm SoCs via PSHOLD" - depends on ARCH_IPQ40XX help Add support for the system reboot on Qualcomm SoCs via PSHOLD. diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index e5a383407a2..477ecd02098 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1631,8 +1631,25 @@ usb_ep *dwc3_gadget_match_ep(struct usb_gadget *gadget, return dwc3_find_ep(gadget, "ep1in"); if (usb_endpoint_is_bulk_out(desc)) return dwc3_find_ep(gadget, "ep2out"); - if (usb_endpoint_is_int_in(desc)) + if (usb_endpoint_is_int_in(desc)) { + /* + * Special workaround for NXP UUU tool in SPL. + * + * The tool excepts the interrupt-in endpoint to be ep1in, + * otherwise it crashes. This is a result of the previous + * hard-coded EP setup in drivers/usb/gadget/epautoconf.c + * which did special-case EP allocation for SPL builds, + * and which was since converted to this callback, but + * without the special-case EP allocation in SPL part. + * + * This reinstates the SPL part in an isolated manner, + * only for NXP iMX SoCs, only for SPL builds, and only + * for the ep1in interrupt-in endpoint. + */ + if (IS_ENABLED(CONFIG_MACH_IMX) && IS_ENABLED(CONFIG_XPL_BUILD)) + return dwc3_find_ep(gadget, "ep1in"); return dwc3_find_ep(gadget, "ep3in"); + } return NULL; } @@ -574,7 +574,7 @@ static int fs_read_lmb_check(const char *filename, ulong addr, loff_t offset, lmb_dump_all(); - if (lmb_alloc_addr(addr, read_len, LMB_NONE) == addr) + if (!lmb_alloc_addr(addr, read_len, LMB_NONE)) return 0; log_err("** Reading file would overwrite reserved memory **\n"); diff --git a/include/configs/sifive-unleashed.h b/include/configs/sifive-unleashed.h index 2996b375723..cd8d0438ba6 100644 --- a/include/configs/sifive-unleashed.h +++ b/include/configs/sifive-unleashed.h @@ -11,7 +11,6 @@ #include <linux/sizes.h> -#define CFG_SYS_SDRAM_BASE 0x80000000 #define RISCV_MMODE_TIMERBASE 0x2000000 #define RISCV_MMODE_TIMEROFF 0xbff8 diff --git a/include/configs/sifive-unmatched.h b/include/configs/sifive-unmatched.h index 27e0912665b..e0064edc5c9 100644 --- a/include/configs/sifive-unmatched.h +++ b/include/configs/sifive-unmatched.h @@ -11,6 +11,5 @@ #include <linux/sizes.h> -#define CFG_SYS_SDRAM_BASE 0x80000000 #endif /* __SIFIVE_UNMATCHED_H */ diff --git a/include/dbsc5.h b/include/dbsc5.h new file mode 100644 index 00000000000..cec937d89e7 --- /dev/null +++ b/include/dbsc5.h @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024-2025 Renesas Electronics Corp. + */ + +#ifndef __INCLUDE_DBSC5_H__ +#define __INCLUDE_DBSC5_H__ + +/* The number of channels V4H has */ +#define DRAM_CH_CNT 4 +/* The number of slices V4H has */ +#define SLICE_CNT 2 +/* The number of chip select V4H has */ +#define CS_CNT 2 + +struct renesas_dbsc5_board_config { + /* Channels in use */ + u8 bdcfg_phyvalid; + /* Read vref (SoC) training range */ + u32 bdcfg_vref_r; + /* Write vref (MR14, MR15) training range */ + u16 bdcfg_vref_w; + /* CA vref (MR12) training range */ + u16 bdcfg_vref_ca; + /* RFM required check */ + bool bdcfg_rfm_chk; + + /* Board parameter about channels */ + struct { + /* + * 0x00: 4Gb dual channel die / 2Gb single channel die + * 0x01: 6Gb dual channel die / 3Gb single channel die + * 0x02: 8Gb dual channel die / 4Gb single channel die + * 0x03: 12Gb dual channel die / 6Gb single channel die + * 0x04: 16Gb dual channel die / 8Gb single channel die + * 0x05: 24Gb dual channel die / 12Gb single channel die + * 0x06: 32Gb dual channel die / 16Gb single channel die + * 0x07: 24Gb single channel die + * 0x08: 32Gb single channel die + * 0xFF: NO_MEMORY + */ + u8 bdcfg_ddr_density[CS_CNT]; + /* SoC caX([6][5][4][3][2][1][0]) -> MEM caY: */ + u32 bdcfg_ca_swap; + /* SoC dqsX([1][0]) -> MEM dqsY: */ + u8 bdcfg_dqs_swap; + /* SoC dq([7][6][5][4][3][2][1][0]) -> MEM dqY/dm: (8 means DM) */ + u32 bdcfg_dq_swap[SLICE_CNT]; + /* SoC dm -> MEM dqY/dm: (8 means DM) */ + u8 bdcfg_dm_swap[SLICE_CNT]; + /* SoC ckeX([1][0]) -> MEM csY */ + u8 bdcfg_cs_swap; + } ch[4]; +}; + +#endif /* __INCLUDE_DBSC5_H__ */ diff --git a/include/dt-bindings/reset/spacemit-k1-reset.h b/include/dt-bindings/reset/spacemit-k1-reset.h new file mode 100644 index 00000000000..74db58b27ef --- /dev/null +++ b/include/dt-bindings/reset/spacemit-k1-reset.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2022 Spacemit Inc. + * Copyright (C) 2025 Huan Zhou <pericycle.cc@gmail.com> + */ + +#ifndef __DT_BINDINGS_RESET_SAPCEMIT_K1_H__ +#define __DT_BINDINGS_RESET_SAPCEMIT_K1_H__ +/* APBC */ +#define RESET_UART1 1 +#define RESET_UART2 2 +#define RESET_GPIO 3 +#define RESET_PWM0 4 +#define RESET_PWM1 5 +#define RESET_PWM2 6 +#define RESET_PWM3 7 +#define RESET_PWM4 8 +#define RESET_PWM5 9 +#define RESET_PWM6 10 +#define RESET_PWM7 11 +#define RESET_PWM8 12 +#define RESET_PWM9 13 +#define RESET_PWM10 14 +#define RESET_PWM11 15 +#define RESET_PWM12 16 +#define RESET_PWM13 17 +#define RESET_PWM14 18 +#define RESET_PWM15 19 +#define RESET_PWM16 20 +#define RESET_PWM17 21 +#define RESET_PWM18 22 +#define RESET_PWM19 23 +#define RESET_SSP3 24 +#define RESET_UART3 25 +#define RESET_RTC 26 +#define RESET_TWSI0 27 +#define RESET_TIMERS1 28 +#define RESET_AIB 29 +#define RESET_TIMERS2 30 +#define RESET_ONEWIRE 31 +#define RESET_SSPA0 32 +#define RESET_SSPA1 33 +#define RESET_DRO 34 +#define RESET_IR 35 +#define RESET_TWSI1 36 +#define RESET_TSEN 37 +#define RESET_TWSI2 38 +#define RESET_TWSI4 39 +#define RESET_TWSI5 40 +#define RESET_TWSI6 41 +#define RESET_TWSI7 42 +#define RESET_TWSI8 43 +#define RESET_IPC_AP2AUD 44 +#define RESET_UART4 45 +#define RESET_UART5 46 +#define RESET_UART6 47 +#define RESET_UART7 48 +#define RESET_UART8 49 +#define RESET_UART9 50 +#define RESET_CAN0 51 + +/* MPMU */ +#define RESET_WDT 52 + +/* APMU */ +#define RESET_JPG 53 +#define RESET_CSI 54 +#define RESET_CCIC2_PHY 55 +#define RESET_CCIC3_PHY 56 +#define RESET_ISP 57 +#define RESET_ISP_AHB 58 +#define RESET_ISP_CI 59 +#define RESET_ISP_CPP 60 +#define RESET_LCD 61 +#define RESET_DSI_ESC 62 +#define RESET_V2D 63 +#define RESET_MIPI 64 +#define RESET_LCD_SPI 65 +#define RESET_LCD_SPI_BUS 66 +#define RESET_LCD_SPI_HBUS 67 +#define RESET_LCD_MCLK 68 +#define RESET_CCIC_4X 69 +#define RESET_CCIC1_PHY 70 +#define RESET_SDH_AXI 71 +#define RESET_SDH0 72 +#define RESET_SDH1 73 +#define RESET_USB_AXI 74 +#define RESET_USBP1_AXI 75 +#define RESET_USB3_0 76 +#define RESET_QSPI 77 +#define RESET_QSPI_BUS 78 +#define RESET_DMA 79 +#define RESET_AES 80 +#define RESET_VPU 81 +#define RESET_GPU 82 +#define RESET_SDH2 83 +#define RESET_MC 84 +#define RESET_EM_AXI 85 +#define RESET_EM 86 +#define RESET_AUDIO_SYS 87 +#define RESET_HDMI 88 +#define RESET_PCIE0 89 +#define RESET_PCIE1 90 +#define RESET_PCIE2 91 +#define RESET_EMAC0 92 +#define RESET_EMAC1 93 + +/* APBC2 */ +#define RESET_SEC_UART1 94 +#define RESET_SEC_SSP2 95 +#define RESET_SEC_TWSI3 96 +#define RESET_SEC_RTC 97 +#define RESET_SEC_TIMERS0 98 +#define RESET_SEC_KPC 99 +#define RESET_SEC_GPIO 100 +#define RESET_NUMBER 101 + +#endif diff --git a/include/lmb.h b/include/lmb.h index 09297a4f530..0d316c64c0a 100644 --- a/include/lmb.h +++ b/include/lmb.h @@ -135,9 +135,9 @@ phys_addr_t lmb_alloc_base(phys_size_t size, ulong align, phys_addr_t max_addr, * parameter. The base parameter is used to specify the base address * of the requested region. * - * Return: Base address on success, 0 on error. + * Return: 0 on success -1 on error */ -phys_addr_t lmb_alloc_addr(phys_addr_t base, phys_size_t size, u32 flags); +int lmb_alloc_addr(phys_addr_t base, phys_size_t size, u32 flags); /** * lmb_is_reserved_flags() - Test if address is in reserved region with flag @@ -175,7 +175,7 @@ void lmb_pop(struct lmb *store); static inline int lmb_read_check(phys_addr_t addr, phys_size_t len) { - return lmb_alloc_addr(addr, len, LMB_NONE) == addr ? 0 : -1; + return lmb_alloc_addr(addr, len, LMB_NONE); } /** diff --git a/include/phy.h b/include/phy.h index 36785031eeb..36354aaf774 100644 --- a/include/phy.h +++ b/include/phy.h @@ -334,6 +334,30 @@ int gen10g_shutdown(struct phy_device *phydev); int gen10g_discover_mmds(struct phy_device *phydev); /** + * phy_set_bits - Convenience function for setting bits in a PHY register + * @phydev: the phy_device struct + * @devad: The MMD to read from + * @regnum: register number to write + * @val: bits to set + */ +static inline int phy_set_bits(struct phy_device *phydev, int devad, u32 regnum, u16 val) +{ + return phy_modify(phydev, devad, regnum, 0, val); +} + +/** + * phy_clear_bits - Convenience function for clearing bits in a PHY register + * @phydev: the phy_device struct + * @devad: The MMD to write to + * @regnum: register number to write + * @val: bits to clear + */ +static inline int phy_clear_bits(struct phy_device *phydev, int devad, u32 regnum, u16 val) +{ + return phy_modify(phydev, devad, regnum, val, 0); +} + +/** * U_BOOT_PHY_DRIVER() - Declare a new U-Boot driver * @__name: name of the driver */ diff --git a/include/renesas/rzg2l-usbphy.h b/include/renesas/rzg2l-usbphy.h new file mode 100644 index 00000000000..1a46b585f17 --- /dev/null +++ b/include/renesas/rzg2l-usbphy.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * RZ/G2L USB PHY common definitions + * + * Copyright (C) 2021-2023 Renesas Electronics Corp. + */ + +#ifndef RENESAS_RZG2L_USBPHY_H +#define RENESAS_RZG2L_USBPHY_H + +#include <fdtdec.h> + +struct rzg2l_usbphy_ctrl_priv { + fdt_addr_t regs; +}; + +#endif /* RENESAS_RZG2L_USBPHY_H */ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 6d00b186250..c39b53922bb 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -491,8 +491,7 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type type, return EFI_NOT_FOUND; addr = map_to_sysmem((void *)(uintptr_t)*memory); - addr = (u64)lmb_alloc_addr(addr, len, flags); - if (!addr) + if (lmb_alloc_addr(addr, len, flags)) return EFI_NOT_FOUND; break; default: diff --git a/lib/efi_loader/elf_efi.ldsi b/lib/efi_loader/elf_efi.ldsi index 190a88fb69e..4fa5ca43872 100644 --- a/lib/efi_loader/elf_efi.ldsi +++ b/lib/efi_loader/elf_efi.ldsi @@ -21,10 +21,10 @@ SECTIONS *(.gnu.linkonce.t.*) *(.srodata) *(.rodata*) - . = ALIGN(16); - *(.dynamic); - . = ALIGN(512); } + . = ALIGN(16); + .dynamic : { *(.dynamic) } + . = ALIGN(512); .rela.dyn : { *(.rela.dyn) } .rela.plt : { *(.rela.plt) } .rela.got : { *(.rela.got) } diff --git a/lib/lmb.c b/lib/lmb.c index 981ea1b2ca0..bb6f232f6bc 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -742,7 +742,7 @@ phys_addr_t lmb_alloc_base(phys_size_t size, ulong align, phys_addr_t max_addr, return _lmb_alloc_base(size, align, max_addr, flags); } -phys_addr_t lmb_alloc_addr(phys_addr_t base, phys_size_t size, u32 flags) +int lmb_alloc_addr(phys_addr_t base, phys_size_t size, u32 flags) { long rgn; struct lmb_region *lmb_memory = lmb.available_mem.data; @@ -759,11 +759,11 @@ phys_addr_t lmb_alloc_addr(phys_addr_t base, phys_size_t size, u32 flags) base + size - 1, 1)) { /* ok, reserve the memory */ if (!lmb_reserve(base, size, flags)) - return base; + return 0; } } - return 0; + return -1; } /* Return number of bytes from a given address that are free */ diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 18993435eae..275c308154b 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -513,8 +513,8 @@ $(obj)/%_efi.S: $(obj)/%.efi $(call cmd,S_efi) quiet_cmd_efi_objcopy = OBJCOPY $@ -cmd_efi_objcopy = $(OBJCOPY) -j .header -j .text -j .sdata -j .data -j \ - .dynamic -j .dynsym -j .rel* -j .rela* -j .reloc \ +cmd_efi_objcopy = $(OBJCOPY) -j .header -j .text -j .sdata -j .data \ + -j .dynamic -j .dynstr -j .dynsym -j .rel* -j .reloc \ $(if $(EFI_TARGET),$(EFI_TARGET),-O binary) $^ $@ $(obj)/%.efi: $(obj)/%_efi.so diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index f9f8891c0c4..414019c5b89 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2692,6 +2692,12 @@ sub u_boot_line { ERROR("PRE_SCHEMA", "Driver model schema uses 'bootph-...' tags now\n" . $herecurr); } + + # Do not allow CONFIG_xPL_BUILD in device trees + if ($realfile =~ /\.dtsi?$/ && $line =~ /^\+.*CONFIG_(X|S|T|V)PL_BUILD.*/) { + ERROR("CONFIG_xPL_BUILD", + "Do not use CONFIG_xPL_BUILD in device trees\n" . $herecurr); + } } sub exclude_global_initialisers { diff --git a/scripts/event_dump.py b/scripts/event_dump.py index 24dfe2bda91..61bb3a8eb92 100755 --- a/scripts/event_dump.py +++ b/scripts/event_dump.py @@ -107,7 +107,7 @@ def main(argv): Args: argv (list of str): List of program arguments, excluding arvg[0] """ - epilog = 'Show a list of even spies in a U-Boot EFL file' + epilog = 'Show a list of event spies in a U-Boot ELF file' parser = ArgumentParser(epilog=epilog) parser.add_argument('elf', type=str, help='ELF file to decode') parser.add_argument('-e', '--endian', type=str, default='auto', diff --git a/test/lib/lmb.c b/test/lib/lmb.c index 24416e83491..ad916740d90 100644 --- a/test/lib/lmb.c +++ b/test/lib/lmb.c @@ -566,21 +566,21 @@ static int test_alloc_addr(struct unit_test_state *uts, const phys_addr_t ram) /* Try to allocate a page twice */ b = lmb_alloc_addr(alloc_addr_a, 0x1000, LMB_NONE); - ut_asserteq(b, alloc_addr_a); - b = lmb_alloc_addr(alloc_addr_a, 0x1000, LMB_NOOVERWRITE); ut_asserteq(b, 0); + b = lmb_alloc_addr(alloc_addr_a, 0x1000, LMB_NOOVERWRITE); + ut_asserteq(b, -1); b = lmb_alloc_addr(alloc_addr_a, 0x1000, LMB_NONE); - ut_asserteq(b, alloc_addr_a); + ut_asserteq(b, 0); b = lmb_alloc_addr(alloc_addr_a, 0x2000, LMB_NONE); - ut_asserteq(b, alloc_addr_a); + ut_asserteq(b, 0); ret = lmb_free(alloc_addr_a, 0x2000); ut_asserteq(ret, 0); b = lmb_alloc_addr(alloc_addr_a, 0x1000, LMB_NOOVERWRITE); - ut_asserteq(b, alloc_addr_a); - b = lmb_alloc_addr(alloc_addr_a, 0x1000, LMB_NONE); ut_asserteq(b, 0); + b = lmb_alloc_addr(alloc_addr_a, 0x1000, LMB_NONE); + ut_asserteq(b, -1); b = lmb_alloc_addr(alloc_addr_a, 0x1000, LMB_NOOVERWRITE); - ut_asserteq(b, 0); + ut_asserteq(b, -1); ret = lmb_free(alloc_addr_a, 0x1000); ut_asserteq(ret, 0); @@ -667,22 +667,22 @@ static int test_alloc_addr(struct unit_test_state *uts, const phys_addr_t ram) /* allocate blocks */ a = lmb_alloc_addr(ram, alloc_addr_a - ram, LMB_NONE); - ut_asserteq(a, ram); + ut_asserteq(a, 0); ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 3, ram, 0x8010000, alloc_addr_b, 0x10000, alloc_addr_c, 0x10000); b = lmb_alloc_addr(alloc_addr_a + 0x10000, alloc_addr_b - alloc_addr_a - 0x10000, LMB_NONE); - ut_asserteq(b, alloc_addr_a + 0x10000); + ut_asserteq(b, 0); ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 2, ram, 0x10010000, alloc_addr_c, 0x10000, 0, 0); c = lmb_alloc_addr(alloc_addr_b + 0x10000, alloc_addr_c - alloc_addr_b - 0x10000, LMB_NONE); - ut_asserteq(c, alloc_addr_b + 0x10000); + ut_asserteq(c, 0); ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 1, ram, 0x18010000, 0, 0, 0, 0); d = lmb_alloc_addr(alloc_addr_c + 0x10000, ram_end - alloc_addr_c - 0x10000, LMB_NONE); - ut_asserteq(d, alloc_addr_c + 0x10000); + ut_asserteq(d, 0); ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 1, ram, ram_size, 0, 0, 0, 0); @@ -692,57 +692,58 @@ static int test_alloc_addr(struct unit_test_state *uts, const phys_addr_t ram) ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 1, ram, ram_size, 0, 0, 0, 0); - ret = lmb_free(d, ram_end - alloc_addr_c - 0x10000); + /* free thge allocation from d */ + ret = lmb_free(alloc_addr_c + 0x10000, ram_end - alloc_addr_c - 0x10000); ut_asserteq(ret, 0); /* allocate at 3 points in free range */ d = lmb_alloc_addr(ram_end - 4, 4, LMB_NONE); - ut_asserteq(d, ram_end - 4); + ut_asserteq(d, 0); ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 2, ram, 0x18010000, - d, 4, 0, 0); - ret = lmb_free(d, 4); + ram_end - 4, 4, 0, 0); + ret = lmb_free(ram_end - 4, 4); ut_asserteq(ret, 0); ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 1, ram, 0x18010000, 0, 0, 0, 0); d = lmb_alloc_addr(ram_end - 128, 4, LMB_NONE); - ut_asserteq(d, ram_end - 128); + ut_asserteq(d, 0); ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 2, ram, 0x18010000, - d, 4, 0, 0); - ret = lmb_free(d, 4); + ram_end - 128, 4, 0, 0); + ret = lmb_free(ram_end - 128, 4); ut_asserteq(ret, 0); ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 1, ram, 0x18010000, 0, 0, 0, 0); d = lmb_alloc_addr(alloc_addr_c + 0x10000, 4, LMB_NONE); - ut_asserteq(d, alloc_addr_c + 0x10000); + ut_asserteq(d, 0); ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 1, ram, 0x18010004, 0, 0, 0, 0); - ret = lmb_free(d, 4); + ret = lmb_free(alloc_addr_c + 0x10000, 4); ut_asserteq(ret, 0); ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 1, ram, 0x18010000, 0, 0, 0, 0); - /* allocate at the bottom */ - ret = lmb_free(a, alloc_addr_a - ram); + /* allocate at the bottom a was assigned to ram at the top */ + ret = lmb_free(ram, alloc_addr_a - ram); ut_asserteq(ret, 0); ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 1, ram + 0x8000000, 0x10010000, 0, 0, 0, 0); d = lmb_alloc_addr(ram, 4, LMB_NONE); - ut_asserteq(d, ram); - ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 2, d, 4, + ut_asserteq(d, 0); + ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 2, ram, 4, ram + 0x8000000, 0x10010000, 0, 0); /* check that allocating outside memory fails */ if (ram_end != 0) { ret = lmb_alloc_addr(ram_end, 1, LMB_NONE); - ut_asserteq(ret, 0); + ut_asserteq(ret, -1); } if (ram != 0) { ret = lmb_alloc_addr(ram - 1, 1, LMB_NONE); - ut_asserteq(ret, 0); + ut_asserteq(ret, -1); } lmb_pop(&store); diff --git a/tools/qconfig.py b/tools/qconfig.py index 259adbe1bc9..c96a305a48f 100755 --- a/tools/qconfig.py +++ b/tools/qconfig.py @@ -1453,7 +1453,7 @@ def do_scan_source(path, do_update): print('\nCONFIG options used as Proper in Makefiles but without a non-xPL_ variant:') not_found = check_not_found(all_uses, MODE_PROPER) show_uses(not_found) - proper_not_found |= {not_found.keys()} + proper_not_found |= not_found.keys() # Scan the source code all_uses, _ = scan_src_files(src_list) @@ -1471,7 +1471,7 @@ def do_scan_source(path, do_update): print('\nCONFIG options used as Proper in source but without a non-xPL_ variant:') not_found = check_not_found(all_uses, MODE_PROPER) show_uses(not_found) - proper_not_found |= {not_found.keys()} + proper_not_found |= not_found.keys() print('\nCONFIG options used as SPL but without an xPL_ variant:') for item in sorted(spl_not_found): diff --git a/tools/sfspl.c b/tools/sfspl.c index c76420ce21b..516e96e8dd9 100644 --- a/tools/sfspl.c +++ b/tools/sfspl.c @@ -70,11 +70,14 @@ static int sfspl_verify_header(unsigned char *buf, int size, printf("Truncated file\n"); return EXIT_FAILURE; } + if ((size_t)size > hdr_size + file_size) + printf("File too long, expected %u bytes\n", + hdr_size + file_size); if (hdr->version != DEFAULT_VERSION) { printf("Unknown file format version\n"); return EXIT_FAILURE; } - crc_check = crc32(0, &buf[hdr_size], size - hdr_size); + crc_check = crc32(0, &buf[hdr_size], file_size); if (crc_check != crc) { printf("Incorrect CRC32\n"); return EXIT_FAILURE; |