diff options
111 files changed, 4852 insertions, 2359 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 857e236aa42..874cf2c0e57 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -546,6 +546,7 @@ M: Michal Simek <monstr@monstr.eu> S: Maintained T: git https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze.git F: arch/arm/mach-zynq/ +F: doc/board/xilinx/ F: drivers/clk/clk_zynq.c F: drivers/fpga/zynqpl.c F: drivers/gpio/zynq_gpio.c @@ -757,6 +758,7 @@ T: git https://gitlab.denx.de/u-boot/u-boot.git F: common/log* F: cmd/log.c F: doc/develop/logging.rst +F: lib/getopt.c F: test/log/ F: test/py/tests/test_log.py diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index d8b0a913be7..bd97604f16f 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -279,6 +279,7 @@ dtb-$(CONFIG_ARCH_ZYNQ) += \ zynq-zc770-xm013.dtb \ zynq-zed.dtb \ zynq-zturn.dtb \ + zynq-zturn-v5.dtb \ zynq-zybo.dtb \ zynq-zybo-z7.dtb dtb-$(CONFIG_ARCH_ZYNQMP) += \ diff --git a/arch/arm/dts/armada-cp110-master.dtsi b/arch/arm/dts/armada-cp110-master.dtsi index cd5c974482e..7d0d31da306 100644 --- a/arch/arm/dts/armada-cp110-master.dtsi +++ b/arch/arm/dts/armada-cp110-master.dtsi @@ -285,15 +285,18 @@ }; cpm_nand: nand@720000 { - compatible = "marvell,mvebu-pxa3xx-nand"; - reg = <0x720000 0x100>; + compatible = "marvell,armada-8k-nand-controller", + "marvell,armada370-nand-controller"; + reg = <0x720000 0x54>; #address-cells = <1>; - - clocks = <&cpm_syscon0 1 2>; + #size-cells = <0>; + interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "core", "reg"; + clocks = <&cpm_syscon0 1 2>, + <&cpm_syscon0 1 17>; + marvell,system-controller = <&cpm_syscon0>; nand-enable-arbiter; num-cs = <1>; - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; status = "disabled"; }; diff --git a/arch/arm/dts/armada-cp110-slave.dtsi b/arch/arm/dts/armada-cp110-slave.dtsi index b426a4eb691..6cf21778370 100644 --- a/arch/arm/dts/armada-cp110-slave.dtsi +++ b/arch/arm/dts/armada-cp110-slave.dtsi @@ -267,6 +267,22 @@ utmi-port = <UTMI_PHY_TO_USB3_HOST0>; status = "disabled"; }; + + cps_nand: nand@720000 { + compatible = "marvell,armada-8k-nand-controller", + "marvell,armada370-nand-controller"; + reg = <0x720000 0x54>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "core", "reg"; + clocks = <&cps_syscon0 1 2>, + <&cps_syscon0 1 17>; + marvell,system-controller = <&cps_syscon0>; + nand-enable-arbiter; + num-cs = <1>; + status = "disabled"; + }; }; cps_pcie0: pcie@f4600000 { diff --git a/arch/arm/dts/versal-mini-emmc0.dts b/arch/arm/dts/versal-mini-emmc0.dts index 7826a282134..6a6e7467a23 100644 --- a/arch/arm/dts/versal-mini-emmc0.dts +++ b/arch/arm/dts/versal-mini-emmc0.dts @@ -16,10 +16,10 @@ #size-cells = <2>; model = "Xilinx Versal MINI eMMC0"; - clk25: clk25 { + clk200: clk200 { compatible = "fixed-clock"; #clock-cells = <0x0>; - clock-frequency = <25000000>; + clock-frequency = <200000000>; }; dcc: dcc { @@ -38,9 +38,12 @@ sdhci0: sdhci@f1040000 { compatible = "xlnx,versal-8.9a", "arasan,sdhci-8.9a"; status = "okay"; + non-removable; + disable-wp; + bus-width = <8>; reg = <0x0 0xf1040000 0x0 0x10000>; clock-names = "clk_xin", "clk_ahb"; - clocks = <&clk25 &clk25>; + clocks = <&clk200 &clk200>; xlnx,device_id = <0>; no-1-8-v; xlnx,mio-bank = <0>; diff --git a/arch/arm/dts/versal-mini-emmc1.dts b/arch/arm/dts/versal-mini-emmc1.dts index 2f28f856a6a..c342e6bdf7a 100644 --- a/arch/arm/dts/versal-mini-emmc1.dts +++ b/arch/arm/dts/versal-mini-emmc1.dts @@ -16,10 +16,10 @@ #size-cells = <2>; model = "Xilinx Versal MINI eMMC1"; - clk25: clk25 { + clk200: clk200 { compatible = "fixed-clock"; #clock-cells = <0x0>; - clock-frequency = <25000000>; + clock-frequency = <200000000>; }; dcc: dcc { @@ -38,9 +38,12 @@ sdhci1: sdhci@f1050000 { compatible = "xlnx,versal-8.9a", "arasan,sdhci-8.9a"; status = "okay"; + non-removable; + disable-wp; + bus-width = <8>; reg = <0x0 0xf1050000 0x0 0x10000>; clock-names = "clk_xin", "clk_ahb"; - clocks = <&clk25 &clk25>; + clocks = <&clk200 &clk200>; xlnx,device_id = <1>; no-1-8-v; xlnx,mio-bank = <0>; diff --git a/arch/arm/dts/zynq-zturn-common.dtsi b/arch/arm/dts/zynq-zturn-common.dtsi new file mode 100644 index 00000000000..1d7af02893d --- /dev/null +++ b/arch/arm/dts/zynq-zturn-common.dtsi @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2015 Andrea Merello <adnrea.merello@gmail.com> + * Copyright (C) 2017 Alexander Graf <agraf@suse.de> + * + * Based on zynq-zed.dts which is: + * Copyright (C) 2011 - 2014 Xilinx + * Copyright (C) 2012 National Instruments Corp. + * + */ + +/dts-v1/; +/include/ "zynq-7000.dtsi" + +/ { + compatible = "xlnx,zynq-7000"; + + aliases { + ethernet0 = &gem0; + serial0 = &uart1; + serial1 = &uart0; + mmc0 = &sdhci0; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x40000000>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-leds { + compatible = "gpio-leds"; + usr-led1 { + label = "usr-led1"; + gpios = <&gpio0 0x0 0x1>; + default-state = "off"; + }; + + usr-led2 { + label = "usr-led2"; + gpios = <&gpio0 0x9 0x1>; + default-state = "off"; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + autorepeat; + K1 { + label = "K1"; + gpios = <&gpio0 0x32 0x1>; + linux,code = <0x66>; + wakeup-source; + autorepeat; + }; + }; +}; + +&clkc { + ps-clk-frequency = <33333333>; +}; + +&qspi { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&gem0 { + status = "okay"; + phy-mode = "rgmii-id"; + phy-handle = <ðernet_phy>; + + ethernet_phy: ethernet-phy@0 { + }; +}; + +&sdhci0 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&uart0 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&uart1 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&can0 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + clock-frequency = <400000>; + + stlm75@49 { + status = "okay"; + compatible = "lm75"; + reg = <0x49>; + }; + + accelerometer@53 { + compatible = "adi,adxl345", "adxl345", "adi,adxl34x", "adxl34x"; + reg = <0x53>; + interrupt-parent = <&intc>; + interrupts = <0x0 0x1e 0x4>; + }; +}; diff --git a/arch/arm/dts/zynq-zturn-v5.dts b/arch/arm/dts/zynq-zturn-v5.dts new file mode 100644 index 00000000000..536632a09a2 --- /dev/null +++ b/arch/arm/dts/zynq-zturn-v5.dts @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0 + +/dts-v1/; +/include/ "zynq-zturn-common.dtsi" + +/ { + model = "Zynq Z-Turn MYIR Board V5"; + compatible = "myir,zynq-zturn-v5", "xlnx,zynq-7000"; +}; + +&gem0 { + ethernet_phy: ethernet-phy@0 { + reg = <0x3>; + }; +}; diff --git a/arch/arm/dts/zynq-zturn.dts b/arch/arm/dts/zynq-zturn.dts index 600e8ee0255..620b24a25e0 100644 --- a/arch/arm/dts/zynq-zturn.dts +++ b/arch/arm/dts/zynq-zturn.dts @@ -1,122 +1,15 @@ // SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2015 Andrea Merello <adnrea.merello@gmail.com> - * Copyright (C) 2017 Alexander Graf <agraf@suse.de> - * - * Based on zynq-zed.dts which is: - * Copyright (C) 2011 - 2014 Xilinx - * Copyright (C) 2012 National Instruments Corp. - * - */ /dts-v1/; -/include/ "zynq-7000.dtsi" +/include/ "zynq-zturn-common.dtsi" / { model = "Zynq Z-Turn MYIR Board"; compatible = "myir,zynq-zturn", "xlnx,zynq-7000"; - - aliases { - ethernet0 = &gem0; - serial0 = &uart1; - serial1 = &uart0; - mmc0 = &sdhci0; - }; - - memory@0 { - device_type = "memory"; - reg = <0x0 0x40000000>; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - gpio-leds { - compatible = "gpio-leds"; - usr-led1 { - label = "usr-led1"; - gpios = <&gpio0 0x0 0x1>; - default-state = "off"; - }; - - usr-led2 { - label = "usr-led2"; - gpios = <&gpio0 0x9 0x1>; - default-state = "off"; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - autorepeat; - K1 { - label = "K1"; - gpios = <&gpio0 0x32 0x1>; - linux,code = <0x66>; - wakeup-source; - autorepeat; - }; - }; -}; - -&clkc { - ps-clk-frequency = <33333333>; -}; - -&qspi { - u-boot,dm-pre-reloc; - status = "okay"; }; &gem0 { - status = "okay"; - phy-mode = "rgmii-id"; - phy-handle = <ðernet_phy>; - ethernet_phy: ethernet-phy@0 { reg = <0x0>; }; }; - -&sdhci0 { - u-boot,dm-pre-reloc; - status = "okay"; -}; - -&uart0 { - u-boot,dm-pre-reloc; - status = "okay"; -}; - -&uart1 { - u-boot,dm-pre-reloc; - status = "okay"; -}; - -&usb0 { - status = "okay"; - dr_mode = "host"; -}; - -&can0 { - status = "okay"; -}; - -&i2c0 { - status = "okay"; - clock-frequency = <400000>; - - stlm75@49 { - status = "okay"; - compatible = "lm75"; - reg = <0x49>; - }; - - accelerometer@53 { - compatible = "adi,adxl345", "adxl345", "adi,adxl34x", "adxl34x"; - reg = <0x53>; - interrupt-parent = <&intc>; - interrupts = <0x0 0x1e 0x4>; - }; -}; diff --git a/arch/arm/dts/zynqmp-mini-qspi.dts b/arch/arm/dts/zynqmp-mini-qspi.dts index a76e6404661..9b4320fe6e2 100644 --- a/arch/arm/dts/zynqmp-mini-qspi.dts +++ b/arch/arm/dts/zynqmp-mini-qspi.dts @@ -70,7 +70,7 @@ reg = <0x0>; spi-tx-bus-width = <1>; spi-rx-bus-width = <4>; - spi-max-frequency = <108000000>; + spi-max-frequency = <40000000>; }; }; diff --git a/arch/arm/mach-zynq/spl.c b/arch/arm/mach-zynq/spl.c index cb8cfd2f353..d09141c3bc7 100644 --- a/arch/arm/mach-zynq/spl.c +++ b/arch/arm/mach-zynq/spl.c @@ -9,7 +9,6 @@ #include <init.h> #include <log.h> #include <spl.h> -#include <generated/dt.h> #include <asm/io.h> #include <asm/spl.h> @@ -86,16 +85,3 @@ void spl_board_prepare_for_boot(void) ps7_post_config(); debug("SPL bye\n"); } - -#ifdef CONFIG_SPL_LOAD_FIT -int board_fit_config_name_match(const char *name) -{ - /* Just empty function now - can't decide what to choose */ - debug("%s: Check %s, default %s\n", __func__, name, DEVICE_TREE); - - if (!strcmp(name, DEVICE_TREE)) - return 0; - - return -1; -} -#endif diff --git a/arch/arm/mach-zynqmp/include/mach/sys_proto.h b/arch/arm/mach-zynqmp/include/mach/sys_proto.h index f2b3ceab135..1c12eac715e 100644 --- a/arch/arm/mach-zynqmp/include/mach/sys_proto.h +++ b/arch/arm/mach-zynqmp/include/mach/sys_proto.h @@ -9,6 +9,16 @@ #define ZYNQMP_CSU_SILICON_VER_MASK 0xF #define KEY_PTR_LEN 32 +#define IV_SIZE 12 +#define RSA_KEY_SIZE 512 +#define MODULUS_LEN 512 +#define PRIV_EXPO_LEN 512 +#define PUB_EXPO_LEN 4 + +#define ZYNQMP_SHA3_INIT 1 +#define ZYNQMP_SHA3_UPDATE 2 +#define ZYNQMP_SHA3_FINAL 4 +#define ZYNQMP_SHA3_SIZE 48 #define ZYNQMP_FPGA_BIT_AUTH_DDR 1 #define ZYNQMP_FPGA_BIT_AUTH_OCM 2 diff --git a/arch/arm/mach-zynqmp/spl.c b/arch/arm/mach-zynqmp/spl.c index 9dd61e25f6f..88386b23e5d 100644 --- a/arch/arm/mach-zynqmp/spl.c +++ b/arch/arm/mach-zynqmp/spl.c @@ -119,13 +119,3 @@ int spl_start_uboot(void) return 0; } #endif - -#ifdef CONFIG_SPL_LOAD_FIT -int board_fit_config_name_match(const char *name) -{ - /* Just empty function now - can't decide what to choose */ - debug("%s: %s\n", __func__, name); - - return -1; -} -#endif diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index ff6b3c7e3d6..99a17bccb38 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -16,10 +16,14 @@ config TARGET_MICROBLAZE_GENERIC select OF_CONTROL select SUPPORT_SPL select SYSRESET + select DM_SPI + select DM_SPI_FLASH + select SPI imply CMD_DM endchoice +source "board/xilinx/Kconfig" source "board/xilinx/microblaze-generic/Kconfig" endmenu diff --git a/arch/microblaze/cpu/start.S b/arch/microblaze/cpu/start.S index cbec299b7d8..9479737aa29 100644 --- a/arch/microblaze/cpu/start.S +++ b/arch/microblaze/cpu/start.S @@ -13,31 +13,108 @@ .text .global _start _start: - /* - * reserve registers: - * r10: Stores little/big endian offset for vectors - * r2: Stores imm opcode - * r3: Stores brai opcode - */ - mts rmsr, r0 /* disable cache */ addi r8, r0, __end mts rslr, r8 - /* TODO: Redo this code to call board_init_f_*() */ + #if defined(CONFIG_SPL_BUILD) addi r1, r0, CONFIG_SPL_STACK_ADDR - mts rshr, r1 - addi r1, r1, -4 /* Decrement SP to top of memory */ -#else -#if CONFIG_VAL(SYS_MALLOC_F_LEN) - addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_VAL(SYS_MALLOC_F_LEN) #else addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET #endif - mts rshr, r1 + addi r1, r1, -4 /* Decrement SP to top of memory */ + /* Call board_init_f_alloc_reserve with the current stack pointer as + * parameter. */ + add r5, r0, r1 + bralid r15, board_init_f_alloc_reserve + nop + + /* board_init_f_alloc_reserve returns a pointer to the allocated area + * in r3. Set the new stack pointer below this area. */ + add r1, r0, r3 + mts rshr, r1 + addi r1, r1, -4 + + /* Call board_init_f_init_reserve with the address returned by + * board_init_f_alloc_reserve as parameter. */ + add r5, r0, r3 + bralid r15, board_init_f_init_reserve + nop + +#if !defined(CONFIG_SPL_BUILD) + /* Setup vectors with pre-relocation symbols */ + or r5, r0, r0 + bralid r15, __setup_exceptions + nop +#endif + + /* Flush cache before enable cache */ + addik r5, r0, 0 + addik r6, r0, XILINX_DCACHE_BYTE_SIZE + bralid r15, flush_cache + nop + + /* enable instruction and data cache */ + mfs r12, rmsr + ori r12, r12, 0x1a0 + mts rmsr, r12 + +clear_bss: + /* clear BSS segments */ + addi r5, r0, __bss_start + addi r4, r0, __bss_end + cmp r6, r5, r4 + beqi r6, 3f +2: + swi r0, r5, 0 /* write zero to loc */ + addi r5, r5, 4 /* increment to next loc */ + cmp r6, r5, r4 /* check if we have reach the end */ + bnei r6, 2b +3: /* jumping to board_init */ +#ifdef CONFIG_DEBUG_UART + bralid r15, debug_uart_init + nop +#endif +#ifndef CONFIG_SPL_BUILD + or r5, r0, r0 /* flags - empty */ + brai board_init_f +#else + brai board_init_r +#endif +1: bri 1b + +#ifndef CONFIG_SPL_BUILD + .text + .ent __setup_exceptions + .align 2 +/* + * Set up reset, interrupt, user exception and hardware exception vectors. + * + * Parameters: + * r5 - relocation offset (zero when setting up vectors before + * relocation, and gd->reloc_off when setting up vectors after + * relocation) + * - the relocation offset is added to the _exception_handler, + * _interrupt_handler and _hw_exception_handler symbols to reflect the + * post-relocation memory addresses + * + * Reserve registers: + * r10: Stores little/big endian offset for vectors + * r2: Stores imm opcode + * r3: Stores brai opcode + */ +__setup_exceptions: + addik r1, r1, -28 + swi r2, r1, 4 + swi r3, r1, 8 + swi r6, r1, 12 + swi r7, r1, 16 + swi r8, r1, 20 + swi r10, r1, 24 + /* Find-out if u-boot is running on BIG/LITTLE endian platform * There are some steps which is necessary to keep in mind: * 1. Setup offset value to r6 @@ -76,7 +153,7 @@ _start: swi r2, r0, 0x8 /* user vector exception - imm opcode */ swi r3, r0, 0xC /* user vector exception - brai opcode */ - addik r6, r0, _exception_handler + addik r6, r5, _exception_handler sw r6, r1, r0 /* * BIG ENDIAN memory map for user exception @@ -109,7 +186,7 @@ _start: swi r2, r0, 0x10 /* interrupt - imm opcode */ swi r3, r0, 0x14 /* interrupt - brai opcode */ - addik r6, r0, _interrupt_handler + addik r6, r5, _interrupt_handler sw r6, r1, r0 lhu r7, r1, r10 rsubi r8, r10, 0x12 @@ -121,67 +198,26 @@ _start: swi r2, r0, 0x20 /* hardware exception - imm opcode */ swi r3, r0, 0x24 /* hardware exception - brai opcode */ - addik r6, r0, _hw_exception_handler + addik r6, r5, _hw_exception_handler sw r6, r1, r0 lhu r7, r1, r10 rsubi r8, r10, 0x22 sh r7, r0, r8 rsubi r8, r10, 0x26 sh r6, r0, r8 -#endif /* CONFIG_SPL_BUILD */ - - /* Flush cache before enable cache */ - addik r5, r0, 0 - addik r6, r0, XILINX_DCACHE_BYTE_SIZE - bralid r15, flush_cache - nop - - /* enable instruction and data cache */ - mfs r12, rmsr - ori r12, r12, 0x1a0 - mts rmsr, r12 - /* TODO: Redo this code to call board_init_f_*() */ -clear_bss: - /* clear BSS segments */ - addi r5, r0, __bss_start - addi r4, r0, __bss_end - cmp r6, r5, r4 - beqi r6, 3f -2: - swi r0, r5, 0 /* write zero to loc */ - addi r5, r5, 4 /* increment to next loc */ - cmp r6, r5, r4 /* check if we have reach the end */ - bnei r6, 2b -3: /* jumping to board_init */ -#ifdef CONFIG_DEBUG_UART - bralid r15, debug_uart_init - nop -#endif -#ifndef CONFIG_SPL_BUILD - or r5, r0, r0 /* flags - empty */ - addi r31, r0, _gd -#if CONFIG_VAL(SYS_MALLOC_F_LEN) - addi r6, r0, CONFIG_SYS_INIT_SP_OFFSET - swi r6, r31, GD_MALLOC_BASE -#endif - brai board_init_f -#else - addi r31, r0, _gd -#if CONFIG_VAL(SYS_MALLOC_F_LEN) - addi r6, r0, CONFIG_SPL_STACK_ADDR - swi r6, r31, GD_MALLOC_BASE -#endif - brai board_init_r -#endif -1: bri 1b + lwi r10, r1, 24 + lwi r8, r1, 20 + lwi r7, r1, 16 + lwi r6, r1, 12 + lwi r3, r1, 8 + lwi r2, r1, 4 + addik r1, r1, 28 - .section .bss -.align 4 -_gd: - .space GENERATED_GBL_DATA_SIZE + rtsd r15, 8 + or r0, r0, r0 + .end __setup_exceptions -#ifndef CONFIG_SPL_BUILD /* * Read 16bit little endian */ @@ -249,39 +285,10 @@ relocate_code: addi r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */ rsub r23, r24, r23 /* keep - this is already here gd->reloc_off */ - addik r6, r0, 0x2 /* BIG/LITTLE endian offset */ - lwi r7, r0, 0x28 - swi r6, r0, 0x28 /* used first unused MB vector */ - lbui r10, r0, 0x28 /* used first unused MB vector */ - swi r7, r0, 0x28 - -#ifdef CONFIG_SYS_USR_EXCEP - addik r6, r0, _exception_handler - addk r6, r6, r23 /* add offset */ - sw r6, r1, r0 - lhu r7, r1, r10 - rsubi r8, r10, 0xa - sh r7, r0, r8 - rsubi r8, r10, 0xe - sh r6, r0, r8 -#endif - addik r6, r0, _hw_exception_handler - addk r6, r6, r23 /* add offset */ - sw r6, r1, r0 - lhu r7, r1, r10 - rsubi r8, r10, 0x22 - sh r7, r0, r8 - rsubi r8, r10, 0x26 - sh r6, r0, r8 - - addik r6, r0, _interrupt_handler - addk r6, r6, r23 /* add offset */ - sw r6, r1, r0 - lhu r7, r1, r10 - rsubi r8, r10, 0x12 - sh r7, r0, r8 - rsubi r8, r10, 0x16 - sh r6, r0, r8 + /* Setup vectors with post-relocation symbols */ + add r5, r0, r23 /* load gd->reloc_off to r5 */ + bralid r15, __setup_exceptions + nop /* Check if GOT exist */ addik r21, r23, _got_start diff --git a/board/xilinx/Kconfig b/board/xilinx/Kconfig index c80d0a88128..64507b5d843 100644 --- a/board/xilinx/Kconfig +++ b/board/xilinx/Kconfig @@ -50,9 +50,34 @@ config XILINX_OF_BOARD_DTB_ADDR config BOOT_SCRIPT_OFFSET hex "Boot script offset" - depends on ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL - default 0xFC0000 if ARCH_ZYNQ + depends on ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL || MICROBLAZE + default 0xFC0000 if ARCH_ZYNQ || MICROBLAZE default 0x3E80000 if ARCH_ZYNQMP default 0x7F80000 if ARCH_VERSAL help - Specifies distro boot script offset in NAND/NOR flash. + Specifies distro boot script offset in NAND/QSPI/NOR flash. + +config ZYNQ_MAC_IN_EEPROM + bool "Reading MAC address from EEPROM" + help + Enable this option if your MAC address is saved in eeprom and + xlnx,eeprom DT property in chosen node points to it. + +if ZYNQ_MAC_IN_EEPROM + +config ZYNQ_GEM_I2C_MAC_OFFSET + hex "Set the I2C MAC offset" + default 0x0 + depends on DM_I2C + help + Set the MAC offset for i2C. + +endif + +config CMD_FRU + bool "FRU information for product" + help + This option enables FRU commands to capture and display FRU + information present in the device. The FRU Information is used + to primarily to provide "inventory" information about the boards + that the FRU Information Device is located on. diff --git a/board/xilinx/common/Makefile b/board/xilinx/common/Makefile new file mode 100644 index 00000000000..212028478c0 --- /dev/null +++ b/board/xilinx/common/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# (C) Copyright 2020 Xilinx, Inc. +# Michal Simek <michal.simek@xilinx.com> +# + +obj-y += board.o +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_CMD_FRU) += fru.o fru_ops.o +endif diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c index b0f60c40a5c..cdc06a39ce5 100644 --- a/board/xilinx/common/board.c +++ b/board/xilinx/common/board.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * (C) Copyright 2014 - 2019 Xilinx, Inc. + * (C) Copyright 2014 - 2020 Xilinx, Inc. * Michal Simek <michal.simek@xilinx.com> */ @@ -11,7 +11,14 @@ #include <dm/uclass.h> #include <i2c.h> #include <linux/sizes.h> +#include <malloc.h> #include "board.h" +#include <dm.h> +#include <i2c_eeprom.h> +#include <net.h> +#include <generated/dt.h> + +#include "fru.h" #if defined(CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET) int zynq_board_read_rom_ethaddr(unsigned char *ethaddr) @@ -41,6 +48,277 @@ int zynq_board_read_rom_ethaddr(unsigned char *ethaddr) } #endif +#define EEPROM_HEADER_MAGIC 0xdaaddeed +#define EEPROM_HDR_MANUFACTURER_LEN 16 +#define EEPROM_HDR_NAME_LEN 16 +#define EEPROM_HDR_REV_LEN 8 +#define EEPROM_HDR_SERIAL_LEN 20 +#define EEPROM_HDR_NO_OF_MAC_ADDR 4 +#define EEPROM_HDR_ETH_ALEN ETH_ALEN + +struct xilinx_board_description { + u32 header; + char manufacturer[EEPROM_HDR_MANUFACTURER_LEN + 1]; + char name[EEPROM_HDR_NAME_LEN + 1]; + char revision[EEPROM_HDR_REV_LEN + 1]; + char serial[EEPROM_HDR_SERIAL_LEN + 1]; + u8 mac_addr[EEPROM_HDR_NO_OF_MAC_ADDR][EEPROM_HDR_ETH_ALEN + 1]; +}; + +static int highest_id = -1; +static struct xilinx_board_description **board_info; + +#define XILINX_I2C_DETECTION_BITS sizeof(struct fru_common_hdr) + +/* Variable which stores pointer to array which stores eeprom content */ +struct xilinx_legacy_format { + char board_sn[18]; /* 0x0 */ + char unused0[14]; /* 0x12 */ + char eth_mac[6]; /* 0x20 */ + char unused1[170]; /* 0x26 */ + char board_name[11]; /* 0xd0 */ + char unused2[5]; /* 0xdc */ + char board_revision[3]; /* 0xe0 */ + char unused3[29]; /* 0xe3 */ +}; + +static void xilinx_eeprom_legacy_cleanup(char *eeprom, int size) +{ + int i; + char byte; + + for (i = 0; i < size; i++) { + byte = eeprom[i]; + + /* Remove all ffs and spaces */ + if (byte == 0xff || byte == ' ') + eeprom[i] = 0; + + /* Convert strings to lower case */ + if (byte >= 'A' && byte <= 'Z') + eeprom[i] = byte + 'a' - 'A'; + } +} + +static int xilinx_read_eeprom_legacy(struct udevice *dev, char *name, + struct xilinx_board_description *desc) +{ + int ret, size; + struct xilinx_legacy_format *eeprom_content; + bool eth_valid = false; + + size = sizeof(*eeprom_content); + + eeprom_content = calloc(1, size); + if (!eeprom_content) + return -ENOMEM; + + debug("%s: I2C EEPROM read pass data at %p\n", __func__, + eeprom_content); + + ret = dm_i2c_read(dev, 0, (uchar *)eeprom_content, size); + if (ret) { + debug("%s: I2C EEPROM read failed\n", __func__); + free(eeprom_content); + return ret; + } + + xilinx_eeprom_legacy_cleanup((char *)eeprom_content, size); + + printf("Xilinx I2C Legacy format at %s:\n", name); + printf(" Board name:\t%s\n", eeprom_content->board_name); + printf(" Board rev:\t%s\n", eeprom_content->board_revision); + printf(" Board SN:\t%s\n", eeprom_content->board_sn); + + eth_valid = is_valid_ethaddr((const u8 *)eeprom_content->eth_mac); + if (eth_valid) + printf(" Ethernet mac:\t%pM\n", eeprom_content->eth_mac); + + /* Terminating \0 chars ensure end of string */ + strcpy(desc->name, eeprom_content->board_name); + strcpy(desc->revision, eeprom_content->board_revision); + strcpy(desc->serial, eeprom_content->board_sn); + if (eth_valid) + memcpy(desc->mac_addr[0], eeprom_content->eth_mac, ETH_ALEN); + + desc->header = EEPROM_HEADER_MAGIC; + + free(eeprom_content); + + return ret; +} + +static bool xilinx_detect_legacy(u8 *buffer) +{ + int i; + char c; + + for (i = 0; i < XILINX_I2C_DETECTION_BITS; i++) { + c = buffer[i]; + + if (c < '0' || c > '9') + return false; + } + + return true; +} + +static int xilinx_read_eeprom_fru(struct udevice *dev, char *name, + struct xilinx_board_description *desc) +{ + int ret, eeprom_size; + u8 *fru_content; + + /* FIXME this is shortcut - if eeprom type is wrong it will fail */ + eeprom_size = i2c_eeprom_size(dev); + + fru_content = calloc(1, eeprom_size); + if (!fru_content) + return -ENOMEM; + + debug("%s: I2C EEPROM read pass data at %p\n", __func__, + fru_content); + + ret = dm_i2c_read(dev, 0, (uchar *)fru_content, + eeprom_size); + if (ret) { + debug("%s: I2C EEPROM read failed\n", __func__); + free(fru_content); + return ret; + } + + printf("Xilinx I2C FRU format at %s:\n", name); + fru_capture((unsigned long)fru_content); + ret = fru_display(0); + if (ret) { + printf("FRU format decoding failed.\n"); + return ret; + } + + if (desc->header == EEPROM_HEADER_MAGIC) { + debug("Information already filled\n"); + return -EINVAL; + } + + /* It is clear that FRU was captured and structures were filled */ + strncpy(desc->manufacturer, (char *)fru_data.brd.manufacturer_name, + sizeof(desc->manufacturer)); + strncpy(desc->name, (char *)fru_data.brd.product_name, + sizeof(desc->name)); + strncpy(desc->revision, (char *)fru_data.brd.rev, + sizeof(desc->revision)); + strncpy(desc->serial, (char *)fru_data.brd.serial_number, + sizeof(desc->serial)); + desc->header = EEPROM_HEADER_MAGIC; + + return 0; +} + +static bool xilinx_detect_fru(u8 *buffer) +{ + u8 checksum = 0; + int i; + + checksum = fru_checksum((u8 *)buffer, sizeof(struct fru_common_hdr)); + if (checksum) { + debug("%s Common header CRC FAIL\n", __func__); + return false; + } + + bool all_zeros = true; + /* Checksum over all zeros is also zero that's why detect this case */ + for (i = 0; i < sizeof(struct fru_common_hdr); i++) { + if (buffer[i] != 0) + all_zeros = false; + } + + if (all_zeros) + return false; + + debug("%s Common header CRC PASS\n", __func__); + return true; +} + +static int xilinx_read_eeprom_single(char *name, + struct xilinx_board_description *desc) +{ + int ret; + struct udevice *dev; + ofnode eeprom; + u8 buffer[XILINX_I2C_DETECTION_BITS]; + + eeprom = ofnode_get_aliases_node(name); + if (!ofnode_valid(eeprom)) + return -ENODEV; + + ret = uclass_get_device_by_ofnode(UCLASS_I2C_EEPROM, eeprom, &dev); + if (ret) + return ret; + + ret = dm_i2c_read(dev, 0, buffer, sizeof(buffer)); + if (ret) { + debug("%s: I2C EEPROM read failed\n", __func__); + return ret; + } + + debug("%s: i2c memory detected: %s\n", __func__, name); + + if (CONFIG_IS_ENABLED(CMD_FRU) && xilinx_detect_fru(buffer)) + return xilinx_read_eeprom_fru(dev, name, desc); + + if (xilinx_detect_legacy(buffer)) + return xilinx_read_eeprom_legacy(dev, name, desc); + + return -ENODEV; +} + +__maybe_unused int xilinx_read_eeprom(void) +{ + int id, ret; + char name_buf[8]; /* 8 bytes should be enough for nvmem+number */ + struct xilinx_board_description *desc; + + highest_id = dev_read_alias_highest_id("nvmem"); + /* No nvmem aliases present */ + if (highest_id < 0) + return -EINVAL; + + board_info = calloc(1, sizeof(desc) * highest_id); + if (!board_info) + return -ENOMEM; + + debug("%s: Highest ID %d, board_info %p\n", __func__, + highest_id, board_info); + + for (id = 0; id <= highest_id; id++) { + snprintf(name_buf, sizeof(name_buf), "nvmem%d", id); + + /* Alloc structure */ + desc = board_info[id]; + if (!desc) { + desc = calloc(1, sizeof(*desc)); + if (!desc) + return -ENOMEM; + + board_info[id] = desc; + } + + /* Ignoring return value for supporting multiple chips */ + ret = xilinx_read_eeprom_single(name_buf, desc); + if (ret) { + free(desc); + board_info[id] = NULL; + } + } + + /* + * Consider to clean board_info structure when board/cards are not + * detected. + */ + + return 0; +} + #if defined(CONFIG_OF_BOARD) || defined(CONFIG_OF_SEPARATE) void *board_fdt_blob_setup(void) { @@ -75,12 +353,36 @@ void *board_fdt_blob_setup(void) } #endif +#if defined(CONFIG_BOARD_LATE_INIT) +static int env_set_by_index(const char *name, int index, char *data) +{ + char var[32]; + + if (!index) + sprintf(var, "board_%s", name); + else + sprintf(var, "card%d_%s", index, name); + + return env_set(var, data); +} + int board_late_init_xilinx(void) { u32 ret = 0; + int i, id, macid = 0; + struct xilinx_board_description *desc; phys_size_t bootm_size = gd->ram_size; + struct bd_info *bd = gd->bd; + + if (!CONFIG_IS_ENABLED(MICROBLAZE) && bd->bi_dram[0].start) { + ulong scriptaddr; - if (CONFIG_IS_ENABLED(ARCH_ZYNQ)) + scriptaddr = env_get_hex("scriptaddr", 0); + ret |= env_set_hex("scriptaddr", + bd->bi_dram[0].start + scriptaddr); + } + + if (CONFIG_IS_ENABLED(ARCH_ZYNQ) || CONFIG_IS_ENABLED(MICROBLAZE)) bootm_size = min(bootm_size, (phys_size_t)(SZ_512M + SZ_256M)); ret |= env_set_hex("script_offset_f", CONFIG_BOOT_SCRIPT_OFFSET); @@ -88,8 +390,49 @@ int board_late_init_xilinx(void) ret |= env_set_addr("bootm_low", (void *)gd->ram_base); ret |= env_set_addr("bootm_size", (void *)bootm_size); + for (id = 0; id <= highest_id; id++) { + desc = board_info[id]; + if (desc && desc->header == EEPROM_HEADER_MAGIC) { + if (desc->manufacturer[0]) + ret |= env_set_by_index("manufacturer", id, + desc->manufacturer); + if (desc->name[0]) + ret |= env_set_by_index("name", id, + desc->name); + if (desc->revision[0]) + ret |= env_set_by_index("rev", id, + desc->revision); + if (desc->serial[0]) + ret |= env_set_by_index("serial", id, + desc->serial); + + if (!CONFIG_IS_ENABLED(NET)) + continue; + + for (i = 0; i < EEPROM_HDR_NO_OF_MAC_ADDR; i++) { + if (!desc->mac_addr[i]) + continue; + + if (is_valid_ethaddr((const u8 *)desc->mac_addr[i])) + ret |= eth_env_set_enetaddr_by_index("eth", + macid++, desc->mac_addr[i]); + } + } + } + if (ret) printf("%s: Saving run time variables FAILED\n", __func__); return 0; } +#endif + +int __maybe_unused board_fit_config_name_match(const char *name) +{ + debug("%s: Check %s, default %s\n", __func__, name, DEVICE_TREE); + + if (!strcmp(name, DEVICE_TREE)) + return 0; + + return -1; +} diff --git a/board/xilinx/common/board.h b/board/xilinx/common/board.h index 180dfbca108..69e642429b8 100644 --- a/board/xilinx/common/board.h +++ b/board/xilinx/common/board.h @@ -9,4 +9,6 @@ int board_late_init_xilinx(void); +int xilinx_read_eeprom(void); + #endif /* BOARD_XILINX_COMMON_BOARD_H */ diff --git a/board/xilinx/common/fru.c b/board/xilinx/common/fru.c new file mode 100644 index 00000000000..ccf48723ff8 --- /dev/null +++ b/board/xilinx/common/fru.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) Copyright 2019 - 2020 Xilinx, Inc. + */ + +#include <common.h> +#include <command.h> +#include <fdtdec.h> +#include <malloc.h> + +#include "fru.h" + +static int do_fru_capture(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + unsigned long addr; + char *endp; + + if (argc < cmdtp->maxargs) + return CMD_RET_USAGE; + + addr = simple_strtoul(argv[2], &endp, 16); + if (*argv[1] == 0 || *endp != 0) + return -1; + + return fru_capture(addr); +} + +static int do_fru_display(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + fru_display(1); + return CMD_RET_SUCCESS; +} + +static int do_fru_generate(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + unsigned long addr; + + if (argc < cmdtp->maxargs) + return CMD_RET_USAGE; + + addr = simple_strtoul(argv[2], NULL, 16); + + return fru_generate(addr, argv[3], argv[4], argv[5], argv[6], argv[7]); +} + +static struct cmd_tbl cmd_fru_sub[] = { + U_BOOT_CMD_MKENT(capture, 3, 0, do_fru_capture, "", ""), + U_BOOT_CMD_MKENT(display, 2, 0, do_fru_display, "", ""), + U_BOOT_CMD_MKENT(board_gen, 8, 0, do_fru_generate, "", ""), +}; + +static int do_fru(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct cmd_tbl *c; + int ret; + + if (argc < 2) + return CMD_RET_USAGE; + + c = find_cmd_tbl(argv[1], &cmd_fru_sub[0], + ARRAY_SIZE(cmd_fru_sub)); + if (!c) + return CMD_RET_USAGE; + + ret = c->cmd(c, flag, argc, argv); + + return cmd_process_error(c, ret); +} + +/***************************************************/ +#ifdef CONFIG_SYS_LONGHELP +static char fru_help_text[] = + "capture <addr> - Parse and capture FRU table present at address.\n" + "fru display - Displays content of FRU table that was captured using\n" + " fru capture command\n" + "fru board_gen <addr> <manufacturer> <board name> <serial number>\n" + " <part number> <revision> - Generate FRU format with\n" + " board info area filled based on parameters. <addr> is\n" + " pointing to place where FRU is generated.\n" + ; +#endif + +U_BOOT_CMD( + fru, 8, 1, do_fru, + "FRU table info", + fru_help_text +) diff --git a/board/xilinx/common/fru.h b/board/xilinx/common/fru.h new file mode 100644 index 00000000000..a3e65202571 --- /dev/null +++ b/board/xilinx/common/fru.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2019 Xilinx, Inc. + * Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com> + */ + +#ifndef __FRU_H +#define __FRU_H + +struct fru_common_hdr { + u8 version; + u8 off_internal; + u8 off_chassis; + u8 off_board; + u8 off_product; + u8 off_multirec; + u8 pad; + u8 crc; +}; + +#define FRU_BOARD_MAX_LEN 32 + +struct __packed fru_board_info_header { + u8 ver; + u8 len; + u8 lang_code; + u8 time[3]; +}; + +struct __packed fru_board_info_member { + u8 type_len; + u8 *name; +}; + +struct fru_board_data { + u8 ver; + u8 len; + u8 lang_code; + u8 time[3]; + u8 manufacturer_type_len; + u8 manufacturer_name[FRU_BOARD_MAX_LEN]; + u8 product_name_type_len; + u8 product_name[FRU_BOARD_MAX_LEN]; + u8 serial_number_type_len; + u8 serial_number[FRU_BOARD_MAX_LEN]; + u8 part_number_type_len; + u8 part_number[FRU_BOARD_MAX_LEN]; + u8 file_id_type_len; + u8 file_id[FRU_BOARD_MAX_LEN]; + /* Xilinx custom fields */ + u8 rev_type_len; + u8 rev[FRU_BOARD_MAX_LEN]; +}; + +struct fru_table { + bool captured; + struct fru_common_hdr hdr; + struct fru_board_data brd; +}; + +#define FRU_TYPELEN_CODE_MASK 0xC0 +#define FRU_TYPELEN_LEN_MASK 0x3F +#define FRU_COMMON_HDR_VER_MASK 0xF +#define FRU_COMMON_HDR_LEN_MULTIPLIER 8 +#define FRU_LANG_CODE_ENGLISH 0 +#define FRU_LANG_CODE_ENGLISH_1 25 +#define FRU_TYPELEN_EOF 0xC1 + +/* This should be minimum of fields */ +#define FRU_BOARD_AREA_TOTAL_FIELDS 5 +#define FRU_TYPELEN_TYPE_SHIFT 6 +#define FRU_TYPELEN_TYPE_BINARY 0 +#define FRU_TYPELEN_TYPE_ASCII8 3 + +int fru_display(int verbose); +int fru_capture(unsigned long addr); +int fru_generate(unsigned long addr, char *manufacturer, char *board_name, + char *serial_no, char *part_no, char *revision); +u8 fru_checksum(u8 *addr, u8 len); + +extern struct fru_table fru_data; + +#endif /* FRU_H */ diff --git a/board/xilinx/common/fru_ops.c b/board/xilinx/common/fru_ops.c new file mode 100644 index 00000000000..fc3add7d93d --- /dev/null +++ b/board/xilinx/common/fru_ops.c @@ -0,0 +1,362 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) Copyright 2019 - 2020 Xilinx, Inc. + */ + +#include <common.h> +#include <cpu_func.h> +#include <env.h> +#include <fdtdec.h> +#include <log.h> +#include <malloc.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> + +#include "fru.h" + +struct fru_table fru_data __section(.data); + +static u16 fru_cal_area_len(u8 len) +{ + return len * FRU_COMMON_HDR_LEN_MULTIPLIER; +} + +static u8 fru_version(u8 ver) +{ + return ver & FRU_COMMON_HDR_VER_MASK; +} + +static int fru_check_language(u8 code) +{ + if (code != FRU_LANG_CODE_ENGLISH && code != FRU_LANG_CODE_ENGLISH_1) { + printf("FRU_ERROR: Only English Language is supported\n"); + return -EINVAL; + } + + return 0; +} + +u8 fru_checksum(u8 *addr, u8 len) +{ + u8 checksum = 0; + + while (len--) { + checksum += *addr; + addr++; + } + + return checksum; +} + +static int fru_check_type_len(u8 type_len, u8 language, u8 *type) +{ + int len; + + if (type_len == FRU_TYPELEN_EOF) + return -EINVAL; + + *type = (type_len & FRU_TYPELEN_CODE_MASK) >> FRU_TYPELEN_TYPE_SHIFT; + + len = type_len & FRU_TYPELEN_LEN_MASK; + + return len; +} + +/* Return len */ +static u8 fru_gen_type_len(u8 *addr, char *name) +{ + int len = strlen(name); + struct fru_board_info_member *member; + + member = (struct fru_board_info_member *)addr; + member->type_len = FRU_TYPELEN_TYPE_ASCII8 << FRU_TYPELEN_TYPE_SHIFT; + member->type_len |= len; + + debug("%lx/%lx: Add %s to 0x%lx (len 0x%x)\n", (ulong)addr, + (ulong)&member->type_len, name, (ulong)&member->name, len); + memcpy(&member->name, name, len); + + /* Add +1 for type_len parameter */ + return 1 + len; +} + +int fru_generate(unsigned long addr, char *manufacturer, char *board_name, + char *serial_no, char *part_no, char *revision) +{ + struct fru_common_hdr *header = (struct fru_common_hdr *)addr; + struct fru_board_info_header *board_info; + u8 *member; + u8 len, pad, modulo; + + header->version = 1; /* Only version 1.0 is supported now */ + header->off_internal = 0; /* not present */ + header->off_chassis = 0; /* not present */ + header->off_board = (sizeof(*header)) / 8; /* Starting offset 8 */ + header->off_product = 0; /* not present */ + header->off_multirec = 0; /* not present */ + header->pad = 0; + /* + * This unsigned byte can be used to calculate a zero checksum + * for the data area following the header. I.e. the modulo 256 sum of + * the record data bytes plus the checksum byte equals zero. + */ + header->crc = 0; /* Clear before calculation */ + header->crc = 0 - fru_checksum((u8 *)header, sizeof(*header)); + + /* board info is just right after header */ + board_info = (void *)((u8 *)header + sizeof(*header)); + + debug("header %lx, board_info %lx\n", (ulong)header, (ulong)board_info); + + board_info->ver = 1; /* 1.0 spec */ + board_info->lang_code = 0; /* English */ + board_info->time[0] = 0; /* unspecified */ + board_info->time[1] = 0; /* unspecified */ + board_info->time[2] = 0; /* unspecified */ + + /* Member fields are just after board_info header */ + member = (u8 *)board_info + sizeof(*board_info); + + len = fru_gen_type_len(member, manufacturer); /* Board Manufacturer */ + member += len; + len = fru_gen_type_len(member, board_name); /* Board Product name */ + member += len; + len = fru_gen_type_len(member, serial_no); /* Board Serial number */ + member += len; + len = fru_gen_type_len(member, part_no); /* Board part number */ + member += len; + len = fru_gen_type_len(member, "U-Boot generator"); /* File ID */ + member += len; + len = fru_gen_type_len(member, revision); /* Revision */ + member += len; + + *member++ = 0xc1; /* Indication of no more fields */ + + len = member - (u8 *)board_info; /* Find current length */ + len += 1; /* Add checksum there too for calculation */ + + modulo = len % 8; + + if (modulo) { + /* Do not fill last item which is checksum */ + for (pad = 0; pad < 8 - modulo; pad++) + *member++ = 0; + + /* Increase structure size */ + len += 8 - modulo; + } + + board_info->len = len / 8; /* Size in multiples of 8 bytes */ + + *member = 0; /* Clear before calculation */ + *member = 0 - fru_checksum((u8 *)board_info, len); + + debug("checksum %x(addr %x)\n", *member, len); + + env_set_hex("fru_addr", addr); + env_set_hex("filesize", (unsigned long)member - addr + 1); + + return 0; +} + +static int fru_parse_board(unsigned long addr) +{ + u8 i, type; + int len; + u8 *data, *term; + + memcpy(&fru_data.brd.ver, (void *)addr, 6); + addr += 6; + data = (u8 *)&fru_data.brd.manufacturer_type_len; + + for (i = 0; ; i++, data += FRU_BOARD_MAX_LEN) { + len = fru_check_type_len(*(u8 *)addr, fru_data.brd.lang_code, + &type); + /* + * Stop cature if it end of fields + */ + if (len == -EINVAL) + break; + + /* This record type/len field */ + *data++ = *(u8 *)addr; + + /* Add offset to match data */ + addr += 1; + + /* If len is 0 it means empty field that's why skip writing */ + if (!len) + continue; + + /* Record data field */ + memcpy(data, (u8 *)addr, len); + term = data + (u8)len; + *term = 0; + addr += len; + } + + if (i < FRU_BOARD_AREA_TOTAL_FIELDS) { + printf("Board area require minimum %d fields\n", + FRU_BOARD_AREA_TOTAL_FIELDS); + return -EINVAL; + } + + return 0; +} + +int fru_capture(unsigned long addr) +{ + struct fru_common_hdr *hdr; + u8 checksum = 0; + + checksum = fru_checksum((u8 *)addr, sizeof(struct fru_common_hdr)); + if (checksum) { + printf("%s Common header CRC error\n", __func__); + return -EINVAL; + } + + hdr = (struct fru_common_hdr *)addr; + + memcpy((void *)&fru_data.hdr, (void *)hdr, + sizeof(struct fru_common_hdr)); + + fru_data.captured = true; + + if (hdr->off_board) { + addr += fru_cal_area_len(hdr->off_board); + fru_parse_board(addr); + } + + env_set_hex("fru_addr", addr); + + return 0; +} + +static int fru_display_board(struct fru_board_data *brd, int verbose) +{ + u32 time = 0; + u8 type; + int len; + u8 *data; + static const char * const typecode[] = { + "Binary/Unspecified", + "BCD plus", + "6-bit ASCII", + "8-bit ASCII", + "2-byte UNICODE" + }; + static const char * const boardinfo[] = { + "Manufacturer Name", + "Product Name", + "Serial No", + "Part Number", + "File ID", + /* Xilinx spec */ + "Revision Number", + }; + + if (verbose) { + printf("*****BOARD INFO*****\n"); + printf("Version:%d\n", fru_version(brd->ver)); + printf("Board Area Length:%d\n", fru_cal_area_len(brd->len)); + } + + if (fru_check_language(brd->lang_code)) + return -EINVAL; + + time = brd->time[2] << 16 | brd->time[1] << 8 | + brd->time[0]; + + if (verbose) + printf("Time in Minutes from 0:00hrs 1/1/96: %d\n", time); + + data = (u8 *)&brd->manufacturer_type_len; + + for (u8 i = 0; i < (sizeof(boardinfo) / sizeof(*boardinfo)); i++) { + len = fru_check_type_len(*data++, brd->lang_code, + &type); + if (len == -EINVAL) { + printf("**** EOF for Board Area ****\n"); + break; + } + + if (type <= FRU_TYPELEN_TYPE_ASCII8 && + (brd->lang_code == FRU_LANG_CODE_ENGLISH || + brd->lang_code == FRU_LANG_CODE_ENGLISH_1)) + debug("Type code: %s\n", typecode[type]); + else + debug("Type code: %s\n", typecode[type + 1]); + + if (!len) { + debug("%s not found\n", boardinfo[i]); + continue; + } + + switch (type) { + case FRU_TYPELEN_TYPE_BINARY: + debug("Length: %d\n", len); + printf(" %s: 0x%x\n", boardinfo[i], *data); + break; + case FRU_TYPELEN_TYPE_ASCII8: + debug("Length: %d\n", len); + printf(" %s: %s\n", boardinfo[i], data); + break; + default: + debug("Unsupported type %x\n", type); + } + + data += FRU_BOARD_MAX_LEN; + } + + return 0; +} + +static void fru_display_common_hdr(struct fru_common_hdr *hdr, int verbose) +{ + if (!verbose) + return; + + printf("*****COMMON HEADER*****\n"); + printf("Version:%d\n", fru_version(hdr->version)); + if (hdr->off_internal) + printf("Internal Use Area Offset:%d\n", + fru_cal_area_len(hdr->off_internal)); + else + printf("*** No Internal Area ***\n"); + + if (hdr->off_chassis) + printf("Chassis Info Area Offset:%d\n", + fru_cal_area_len(hdr->off_chassis)); + else + printf("*** No Chassis Info Area ***\n"); + + if (hdr->off_board) + printf("Board Area Offset:%d\n", + fru_cal_area_len(hdr->off_board)); + else + printf("*** No Board Area ***\n"); + + if (hdr->off_product) + printf("Product Info Area Offset:%d\n", + fru_cal_area_len(hdr->off_product)); + else + printf("*** No Product Info Area ***\n"); + + if (hdr->off_multirec) + printf("MultiRecord Area Offset:%d\n", + fru_cal_area_len(hdr->off_multirec)); + else + printf("*** No MultiRecord Area ***\n"); +} + +int fru_display(int verbose) +{ + if (!fru_data.captured) { + printf("FRU data not available please run fru parse\n"); + return -EINVAL; + } + + fru_display_common_hdr(&fru_data.hdr, verbose); + + return fru_display_board(&fru_data.brd, verbose); +} diff --git a/board/xilinx/microblaze-generic/microblaze-generic.c b/board/xilinx/microblaze-generic/microblaze-generic.c index 4e569e910d9..e5909997690 100644 --- a/board/xilinx/microblaze-generic/microblaze-generic.c +++ b/board/xilinx/microblaze-generic/microblaze-generic.c @@ -18,6 +18,7 @@ #include <dm/lists.h> #include <fdtdec.h> #include <linux/sizes.h> +#include "../common/board.h" DECLARE_GLOBAL_DATA_PTR; @@ -36,7 +37,8 @@ int dram_init(void) int board_late_init(void) { - ulong max_size, lowmem_size; + ulong max_size; + u32 status = 0; #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SYSRESET_MICROBLAZE) int ret; @@ -55,12 +57,19 @@ int board_late_init(void) max_size = gd->start_addr_sp - CONFIG_STACK_SIZE; max_size = round_down(max_size, SZ_16M); - /* Linux default LOWMEM_SIZE is 0x30000000 = 768MB */ - lowmem_size = gd->ram_base + 768 * 1024 * 1024; + status |= env_set_hex("scriptaddr", max_size + SZ_2M); - env_set_addr("initrd_high", (void *)min_t(ulong, max_size, - lowmem_size)); - env_set_addr("fdt_high", (void *)min_t(ulong, max_size, lowmem_size)); + status |= env_set_hex("pxefile_addr_r", max_size + SZ_1M); - return 0; + status |= env_set_hex("kernel_addr_r", gd->ram_base + SZ_32M); + + status |= env_set_hex("fdt_addr_r", gd->ram_base + SZ_32M - SZ_1M); + + status |= env_set_hex("ramdisk_addr_r", + gd->ram_base + SZ_32M + SZ_4M + SZ_2M); + + if (status) + printf("%s: Saving run time variables FAILED\n", __func__); + + return board_late_init_xilinx(); } diff --git a/board/xilinx/versal/Makefile b/board/xilinx/versal/Makefile index 90e03431540..4a46ca02d70 100644 --- a/board/xilinx/versal/Makefile +++ b/board/xilinx/versal/Makefile @@ -6,4 +6,3 @@ obj-y := board.o obj-$(CONFIG_CMD_VERSAL) += cmds.o -obj-y += ../common/board.o diff --git a/board/xilinx/versal/board.c b/board/xilinx/versal/board.c index a5ca4ca8740..912c1143a8a 100644 --- a/board/xilinx/versal/board.c +++ b/board/xilinx/versal/board.c @@ -36,6 +36,9 @@ int board_init(void) fpga_add(fpga_xilinx, &versalpl); #endif + if (CONFIG_IS_ENABLED(DM_I2C) && CONFIG_IS_ENABLED(I2C_EEPROM)) + xilinx_read_eeprom(); + return 0; } diff --git a/board/xilinx/zynq/Makefile b/board/xilinx/zynq/Makefile index 096a7aceb93..85661715891 100644 --- a/board/xilinx/zynq/Makefile +++ b/board/xilinx/zynq/Makefile @@ -4,7 +4,6 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. obj-y := board.o -obj-y += ../common/board.o ifneq ($(CONFIG_XILINX_PS_INIT_FILE),"") PS_INIT_FILE := $(shell cd $(srctree); readlink -f $(CONFIG_XILINX_PS_INIT_FILE)) diff --git a/board/xilinx/zynq/zynq-zturn-v5/ps7_init_gpl.c b/board/xilinx/zynq/zynq-zturn-v5/ps7_init_gpl.c new file mode 100644 index 00000000000..5d573868cb1 --- /dev/null +++ b/board/xilinx/zynq/zynq-zturn-v5/ps7_init_gpl.c @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) Xilinx, Inc. + */ + +#include <asm/arch/ps7_init_gpl.h> + +static unsigned long ps7_pll_init_data[] = { + EMIT_WRITE(0xF8000008, 0x0000DF0DU), + EMIT_MASKWRITE(0xF8000110, 0x003FFFF0U, 0x000FA220U), + EMIT_MASKWRITE(0xF8000100, 0x0007F000U, 0x00028000U), + EMIT_MASKWRITE(0xF8000100, 0x00000010U, 0x00000010U), + EMIT_MASKWRITE(0xF8000100, 0x00000001U, 0x00000001U), + EMIT_MASKWRITE(0xF8000100, 0x00000001U, 0x00000000U), + EMIT_MASKPOLL(0xF800010C, 0x00000001U), + EMIT_MASKWRITE(0xF8000100, 0x00000010U, 0x00000000U), + EMIT_MASKWRITE(0xF8000120, 0x1F003F30U, 0x1F000200U), + EMIT_MASKWRITE(0xF8000114, 0x003FFFF0U, 0x0012C220U), + EMIT_MASKWRITE(0xF8000104, 0x0007F000U, 0x00020000U), + EMIT_MASKWRITE(0xF8000104, 0x00000010U, 0x00000010U), + EMIT_MASKWRITE(0xF8000104, 0x00000001U, 0x00000001U), + EMIT_MASKWRITE(0xF8000104, 0x00000001U, 0x00000000U), + EMIT_MASKPOLL(0xF800010C, 0x00000002U), + EMIT_MASKWRITE(0xF8000104, 0x00000010U, 0x00000000U), + EMIT_MASKWRITE(0xF8000124, 0xFFF00003U, 0x0C200003U), + EMIT_MASKWRITE(0xF8000118, 0x003FFFF0U, 0x001452C0U), + EMIT_MASKWRITE(0xF8000108, 0x0007F000U, 0x0001E000U), + EMIT_MASKWRITE(0xF8000108, 0x00000010U, 0x00000010U), + EMIT_MASKWRITE(0xF8000108, 0x00000001U, 0x00000001U), + EMIT_MASKWRITE(0xF8000108, 0x00000001U, 0x00000000U), + EMIT_MASKPOLL(0xF800010C, 0x00000004U), + EMIT_MASKWRITE(0xF8000108, 0x00000010U, 0x00000000U), + EMIT_WRITE(0xF8000004, 0x0000767BU), + EMIT_EXIT(), +}; + +static unsigned long ps7_clock_init_data[] = { + EMIT_WRITE(0xF8000008, 0x0000DF0DU), + EMIT_MASKWRITE(0xF8000128, 0x03F03F01U, 0x00700F01U), + EMIT_MASKWRITE(0xF8000138, 0x00000011U, 0x00000001U), + EMIT_MASKWRITE(0xF8000140, 0x03F03F71U, 0x00100801U), + EMIT_MASKWRITE(0xF800014C, 0x00003F31U, 0x00000501U), + EMIT_MASKWRITE(0xF8000150, 0x00003F33U, 0x00001401U), + EMIT_MASKWRITE(0xF8000154, 0x00003F33U, 0x00000A03U), + EMIT_MASKWRITE(0xF800015C, 0x03F03F33U, 0x00200501U), + EMIT_MASKWRITE(0xF8000160, 0x007F007FU, 0x00000000U), + EMIT_MASKWRITE(0xF8000168, 0x00003F31U, 0x00000501U), + EMIT_MASKWRITE(0xF8000170, 0x03F03F30U, 0x00200500U), + EMIT_MASKWRITE(0xF8000180, 0x03F03F30U, 0x00400500U), + EMIT_MASKWRITE(0xF80001C4, 0x00000001U, 0x00000001U), + EMIT_MASKWRITE(0xF800012C, 0x01FFCCCDU, 0x01FD044DU), + EMIT_WRITE(0xF8000004, 0x0000767BU), + EMIT_EXIT(), +}; + +static unsigned long ps7_ddr_init_data[] = { + EMIT_MASKWRITE(0xF8006000, 0x0001FFFFU, 0x00000080U), + EMIT_MASKWRITE(0xF8006004, 0x0007FFFFU, 0x00001082U), + EMIT_MASKWRITE(0xF8006008, 0x03FFFFFFU, 0x03C0780FU), + EMIT_MASKWRITE(0xF800600C, 0x03FFFFFFU, 0x02001001U), + EMIT_MASKWRITE(0xF8006010, 0x03FFFFFFU, 0x00014001U), + EMIT_MASKWRITE(0xF8006014, 0x001FFFFFU, 0x0004285BU), + EMIT_MASKWRITE(0xF8006018, 0xF7FFFFFFU, 0x44E458D3U), + EMIT_MASKWRITE(0xF800601C, 0xFFFFFFFFU, 0x7282BCE5U), + EMIT_MASKWRITE(0xF8006020, 0x7FDFFFFCU, 0x270872D0U), + EMIT_MASKWRITE(0xF8006024, 0x0FFFFFC3U, 0x00000000U), + EMIT_MASKWRITE(0xF8006028, 0x00003FFFU, 0x00002007U), + EMIT_MASKWRITE(0xF800602C, 0xFFFFFFFFU, 0x00000008U), + EMIT_MASKWRITE(0xF8006030, 0xFFFFFFFFU, 0x00040B30U), + EMIT_MASKWRITE(0xF8006034, 0x13FF3FFFU, 0x000116D4U), + EMIT_MASKWRITE(0xF8006038, 0x00000003U, 0x00000000U), + EMIT_MASKWRITE(0xF800603C, 0x000FFFFFU, 0x00000777U), + EMIT_MASKWRITE(0xF8006040, 0xFFFFFFFFU, 0xFFF00000U), + EMIT_MASKWRITE(0xF8006044, 0x0FFFFFFFU, 0x0F666666U), + EMIT_MASKWRITE(0xF8006048, 0x0003F03FU, 0x0003C008U), + EMIT_MASKWRITE(0xF8006050, 0xFF0F8FFFU, 0x77010800U), + EMIT_MASKWRITE(0xF8006058, 0x00010000U, 0x00000000U), + EMIT_MASKWRITE(0xF800605C, 0x0000FFFFU, 0x00005003U), + EMIT_MASKWRITE(0xF8006060, 0x000017FFU, 0x0000003EU), + EMIT_MASKWRITE(0xF8006064, 0x00021FE0U, 0x00020000U), + EMIT_MASKWRITE(0xF8006068, 0x03FFFFFFU, 0x00284141U), + EMIT_MASKWRITE(0xF800606C, 0x0000FFFFU, 0x00001610U), + EMIT_MASKWRITE(0xF8006078, 0x03FFFFFFU, 0x00466111U), + EMIT_MASKWRITE(0xF800607C, 0x000FFFFFU, 0x00032222U), + EMIT_MASKWRITE(0xF80060A4, 0xFFFFFFFFU, 0x10200802U), + EMIT_MASKWRITE(0xF80060A8, 0x0FFFFFFFU, 0x0690CB73U), + EMIT_MASKWRITE(0xF80060AC, 0x000001FFU, 0x000001FEU), + EMIT_MASKWRITE(0xF80060B0, 0x1FFFFFFFU, 0x1CFFFFFFU), + EMIT_MASKWRITE(0xF80060B4, 0x00000200U, 0x00000200U), + EMIT_MASKWRITE(0xF80060B8, 0x01FFFFFFU, 0x00200066U), + EMIT_MASKWRITE(0xF80060C4, 0x00000003U, 0x00000000U), + EMIT_MASKWRITE(0xF80060C8, 0x000000FFU, 0x00000000U), + EMIT_MASKWRITE(0xF80060DC, 0x00000001U, 0x00000000U), + EMIT_MASKWRITE(0xF80060F0, 0x0000FFFFU, 0x00000000U), + EMIT_MASKWRITE(0xF80060F4, 0x0000000FU, 0x00000008U), + EMIT_MASKWRITE(0xF8006114, 0x000000FFU, 0x00000000U), + EMIT_MASKWRITE(0xF8006118, 0x7FFFFFCFU, 0x40000001U), + EMIT_MASKWRITE(0xF800611C, 0x7FFFFFCFU, 0x40000001U), + EMIT_MASKWRITE(0xF8006120, 0x7FFFFFCFU, 0x40000001U), + EMIT_MASKWRITE(0xF8006124, 0x7FFFFFCFU, 0x40000001U), + EMIT_MASKWRITE(0xF800612C, 0x000FFFFFU, 0x0002A81FU), + EMIT_MASKWRITE(0xF8006130, 0x000FFFFFU, 0x00029822U), + EMIT_MASKWRITE(0xF8006134, 0x000FFFFFU, 0x00026C10U), + EMIT_MASKWRITE(0xF8006138, 0x000FFFFFU, 0x00026013U), + EMIT_MASKWRITE(0xF8006140, 0x000FFFFFU, 0x00000035U), + EMIT_MASKWRITE(0xF8006144, 0x000FFFFFU, 0x00000035U), + EMIT_MASKWRITE(0xF8006148, 0x000FFFFFU, 0x00000035U), + EMIT_MASKWRITE(0xF800614C, 0x000FFFFFU, 0x00000035U), + EMIT_MASKWRITE(0xF8006154, 0x000FFFFFU, 0x0000009FU), + EMIT_MASKWRITE(0xF8006158, 0x000FFFFFU, 0x000000A2U), + EMIT_MASKWRITE(0xF800615C, 0x000FFFFFU, 0x00000090U), + EMIT_MASKWRITE(0xF8006160, 0x000FFFFFU, 0x00000093U), + EMIT_MASKWRITE(0xF8006168, 0x001FFFFFU, 0x000000FFU), + EMIT_MASKWRITE(0xF800616C, 0x001FFFFFU, 0x000000FBU), + EMIT_MASKWRITE(0xF8006170, 0x001FFFFFU, 0x000000F0U), + EMIT_MASKWRITE(0xF8006174, 0x001FFFFFU, 0x000000EDU), + EMIT_MASKWRITE(0xF800617C, 0x000FFFFFU, 0x000000DFU), + EMIT_MASKWRITE(0xF8006180, 0x000FFFFFU, 0x000000E2U), + EMIT_MASKWRITE(0xF8006184, 0x000FFFFFU, 0x000000D0U), + EMIT_MASKWRITE(0xF8006188, 0x000FFFFFU, 0x000000D3U), + EMIT_MASKWRITE(0xF8006190, 0x6FFFFEFEU, 0x00040080U), + EMIT_MASKWRITE(0xF8006194, 0x000FFFFFU, 0x0001FC82U), + EMIT_MASKWRITE(0xF8006204, 0xFFFFFFFFU, 0x00000000U), + EMIT_MASKWRITE(0xF8006208, 0x000703FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF800620C, 0x000703FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF8006210, 0x000703FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF8006214, 0x000703FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF8006218, 0x000F03FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF800621C, 0x000F03FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF8006220, 0x000F03FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF8006224, 0x000F03FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF80062A8, 0x00000FF5U, 0x00000000U), + EMIT_MASKWRITE(0xF80062AC, 0xFFFFFFFFU, 0x00000000U), + EMIT_MASKWRITE(0xF80062B0, 0x003FFFFFU, 0x00005125U), + EMIT_MASKWRITE(0xF80062B4, 0x0003FFFFU, 0x000012A8U), + EMIT_MASKPOLL(0xF8000B74, 0x00002000U), + EMIT_MASKWRITE(0xF8006000, 0x0001FFFFU, 0x00000081U), + EMIT_MASKPOLL(0xF8006054, 0x00000007U), + EMIT_EXIT(), +}; + +static unsigned long ps7_mio_init_data[] = { + EMIT_WRITE(0xF8000008, 0x0000DF0DU), + EMIT_MASKWRITE(0xF8000B40, 0x00000FFFU, 0x00000600U), + EMIT_MASKWRITE(0xF8000B44, 0x00000FFFU, 0x00000600U), + EMIT_MASKWRITE(0xF8000B48, 0x00000FFFU, 0x00000672U), + EMIT_MASKWRITE(0xF8000B4C, 0x00000FFFU, 0x00000672U), + EMIT_MASKWRITE(0xF8000B50, 0x00000FFFU, 0x00000674U), + EMIT_MASKWRITE(0xF8000B54, 0x00000FFFU, 0x00000674U), + EMIT_MASKWRITE(0xF8000B58, 0x00000FFFU, 0x00000600U), + EMIT_MASKWRITE(0xF8000B5C, 0xFFFFFFFFU, 0x0018C61CU), + EMIT_MASKWRITE(0xF8000B60, 0xFFFFFFFFU, 0x00F9861CU), + EMIT_MASKWRITE(0xF8000B64, 0xFFFFFFFFU, 0x00F9861CU), + EMIT_MASKWRITE(0xF8000B68, 0xFFFFFFFFU, 0x00F9861CU), + EMIT_MASKWRITE(0xF8000B6C, 0x00007FFFU, 0x00000260U), + EMIT_MASKWRITE(0xF8000B70, 0x00000001U, 0x00000001U), + EMIT_MASKWRITE(0xF8000B70, 0x00000021U, 0x00000020U), + EMIT_MASKWRITE(0xF8000B70, 0x07FEFFFFU, 0x00000823U), + EMIT_MASKWRITE(0xF8000700, 0x00003FFFU, 0x00001600U), + EMIT_MASKWRITE(0xF8000704, 0x00003FFFU, 0x00000602U), + EMIT_MASKWRITE(0xF8000708, 0x00003FFFU, 0x00000602U), + EMIT_MASKWRITE(0xF800070C, 0x00003FFFU, 0x00000602U), + EMIT_MASKWRITE(0xF8000710, 0x00003FFFU, 0x00000602U), + EMIT_MASKWRITE(0xF8000714, 0x00003FFFU, 0x00000602U), + EMIT_MASKWRITE(0xF8000718, 0x00003FFFU, 0x00000602U), + EMIT_MASKWRITE(0xF800071C, 0x00003FFFU, 0x00000600U), + EMIT_MASKWRITE(0xF8000720, 0x00003FFFU, 0x00000602U), + EMIT_MASKWRITE(0xF8000724, 0x00003FFFU, 0x00000600U), + EMIT_MASKWRITE(0xF8000728, 0x00003FFFU, 0x000016E1U), + EMIT_MASKWRITE(0xF800072C, 0x00003FFFU, 0x000016E0U), + EMIT_MASKWRITE(0xF8000730, 0x00003FFFU, 0x00001640U), + EMIT_MASKWRITE(0xF8000734, 0x00003FFFU, 0x00001640U), + EMIT_MASKWRITE(0xF8000738, 0x00003FFFU, 0x00001621U), + EMIT_MASKWRITE(0xF800073C, 0x00003FFFU, 0x00001620U), + EMIT_MASKWRITE(0xF8000740, 0x00003FFFU, 0x00001202U), + EMIT_MASKWRITE(0xF8000744, 0x00003FFFU, 0x00001202U), + EMIT_MASKWRITE(0xF8000748, 0x00003FFFU, 0x00001202U), + EMIT_MASKWRITE(0xF800074C, 0x00003FFFU, 0x00001202U), + EMIT_MASKWRITE(0xF8000750, 0x00003FFFU, 0x00001202U), + EMIT_MASKWRITE(0xF8000754, 0x00003FFFU, 0x00001202U), + EMIT_MASKWRITE(0xF8000758, 0x00003FFFU, 0x00001203U), + EMIT_MASKWRITE(0xF800075C, 0x00003FFFU, 0x00001203U), + EMIT_MASKWRITE(0xF8000760, 0x00003FFFU, 0x00001203U), + EMIT_MASKWRITE(0xF8000764, 0x00003FFFU, 0x00001203U), + EMIT_MASKWRITE(0xF8000768, 0x00003FFFU, 0x00001203U), + EMIT_MASKWRITE(0xF800076C, 0x00003FFFU, 0x00001203U), + EMIT_MASKWRITE(0xF8000770, 0x00003FFFU, 0x00001204U), + EMIT_MASKWRITE(0xF8000774, 0x00003FFFU, 0x00001205U), + EMIT_MASKWRITE(0xF8000778, 0x00003FFFU, 0x00001204U), + EMIT_MASKWRITE(0xF800077C, 0x00003FFFU, 0x00001205U), + EMIT_MASKWRITE(0xF8000780, 0x00003FFFU, 0x00001204U), + EMIT_MASKWRITE(0xF8000784, 0x00003FFFU, 0x00001204U), + EMIT_MASKWRITE(0xF8000788, 0x00003FFFU, 0x00001204U), + EMIT_MASKWRITE(0xF800078C, 0x00003FFFU, 0x00001204U), + EMIT_MASKWRITE(0xF8000790, 0x00003FFFU, 0x00001205U), + EMIT_MASKWRITE(0xF8000794, 0x00003FFFU, 0x00001204U), + EMIT_MASKWRITE(0xF8000798, 0x00003FFFU, 0x00001204U), + EMIT_MASKWRITE(0xF800079C, 0x00003FFFU, 0x00001204U), + EMIT_MASKWRITE(0xF80007A0, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF80007A4, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF80007A8, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF80007AC, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF80007B0, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF80007B4, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF80007B8, 0x00003F01U, 0x00000201U), + EMIT_MASKWRITE(0xF80007BC, 0x00003F01U, 0x00000201U), + EMIT_MASKWRITE(0xF80007C0, 0x00003FFFU, 0x000012E0U), + EMIT_MASKWRITE(0xF80007C4, 0x00003FFFU, 0x000012E1U), + EMIT_MASKWRITE(0xF80007C8, 0x00003FFFU, 0x00000200U), + EMIT_MASKWRITE(0xF80007CC, 0x00003FFFU, 0x00000200U), + EMIT_MASKWRITE(0xF80007D0, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF80007D4, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF8000830, 0x003F003FU, 0x002E002FU), + EMIT_WRITE(0xF8000004, 0x0000767BU), + EMIT_EXIT(), +}; + +static unsigned long ps7_peripherals_init_data[] = { + EMIT_WRITE(0xF8000008, 0x0000DF0DU), + EMIT_MASKWRITE(0xF8000B48, 0x00000180U, 0x00000180U), + EMIT_MASKWRITE(0xF8000B4C, 0x00000180U, 0x00000180U), + EMIT_MASKWRITE(0xF8000B50, 0x00000180U, 0x00000180U), + EMIT_MASKWRITE(0xF8000B54, 0x00000180U, 0x00000180U), + EMIT_WRITE(0xF8000004, 0x0000767BU), + EMIT_MASKWRITE(0xE000D000, 0x00080000U, 0x00080000U), + EMIT_MASKWRITE(0xF8007000, 0x20000000U, 0x00000000U), + EMIT_MASKWRITE(0xE000A244, 0x003FFFFFU, 0x00080000U), + EMIT_MASKWRITE(0xE000A00C, 0x003F003FU, 0x00370008U), + EMIT_MASKWRITE(0xE000A248, 0x003FFFFFU, 0x00080000U), + EMIT_MASKWRITE(0xE000A00C, 0x003F003FU, 0x00370000U), + EMIT_MASKDELAY(0xF8F00200, 1), + EMIT_MASKWRITE(0xE000A00C, 0x003F003FU, 0x00370008U), + EMIT_EXIT(), +}; + +static unsigned long ps7_post_config_0[] = { + EMIT_WRITE(0xF8000008, 0x0000DF0DU), + EMIT_MASKWRITE(0xF8000900, 0x0000000FU, 0x0000000FU), + EMIT_MASKWRITE(0xF8000240, 0xFFFFFFFFU, 0x00000000U), + EMIT_WRITE(0xF8000004, 0x0000767BU), + EMIT_EXIT(), +}; + +int ps7_post_config(void) +{ + return ps7_config(ps7_post_config_0); +} + +int ps7_init(void) +{ + int ret; + + ret = ps7_config(ps7_mio_init_data); + if (ret != PS7_INIT_SUCCESS) + return ret; + + ret = ps7_config(ps7_pll_init_data); + if (ret != PS7_INIT_SUCCESS) + return ret; + + ret = ps7_config(ps7_clock_init_data); + if (ret != PS7_INIT_SUCCESS) + return ret; + + ret = ps7_config(ps7_ddr_init_data); + if (ret != PS7_INIT_SUCCESS) + return ret; + + ret = ps7_config(ps7_peripherals_init_data); + if (ret != PS7_INIT_SUCCESS) + return ret; + return PS7_INIT_SUCCESS; +} diff --git a/board/xilinx/zynqmp/MAINTAINERS b/board/xilinx/zynqmp/MAINTAINERS index 04fc7f32fe8..9cd4f3f53ef 100644 --- a/board/xilinx/zynqmp/MAINTAINERS +++ b/board/xilinx/zynqmp/MAINTAINERS @@ -3,6 +3,7 @@ M: Michal Simek <michal.simek@xilinx.com> S: Maintained F: arch/arm/dts/zynqmp-* F: arch/arm/dts/avnet-ultra96* +F: board/xilinx/common/ F: board/xilinx/zynqmp/ F: include/configs/xilinx_zynqmp* F: configs/xilinx_zynqmp* diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile index 398c6aaa452..7d8277ca400 100644 --- a/board/xilinx/zynqmp/Makefile +++ b/board/xilinx/zynqmp/Makefile @@ -4,7 +4,6 @@ # Michal Simek <michal.simek@xilinx.com> obj-y := zynqmp.o -obj-y += ../common/board.o ifneq ($(CONFIG_XILINX_PS_INIT_FILE),"") PS_INIT_FILE := $(shell cd $(srctree); readlink -f $(CONFIG_XILINX_PS_INIT_FILE)) diff --git a/board/xilinx/zynqmp/cmds.c b/board/xilinx/zynqmp/cmds.c index c0d28a73e45..cf63ad97fab 100644 --- a/board/xilinx/zynqmp/cmds.c +++ b/board/xilinx/zynqmp/cmds.c @@ -9,11 +9,22 @@ #include <cpu_func.h> #include <env.h> #include <malloc.h> +#include <memalign.h> #include <zynqmp_firmware.h> #include <asm/arch/hardware.h> #include <asm/arch/sys_proto.h> #include <asm/io.h> +struct aes { + u64 srcaddr; + u64 ivaddr; + u64 keyaddr; + u64 dstaddr; + u64 len; + u64 op; + u64 keysrc; +}; + static int do_zynqmp_verify_secure(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -107,6 +118,66 @@ static int do_zynqmp_mmio_write(struct cmd_tbl *cmdtp, int flag, int argc, return ret; } +static int do_zynqmp_aes(struct cmd_tbl *cmdtp, int flag, int argc, + char * const argv[]) +{ + ALLOC_CACHE_ALIGN_BUFFER(struct aes, aes, 1); + int ret; + u32 ret_payload[PAYLOAD_ARG_CNT]; + + if (zynqmp_firmware_version() <= PMUFW_V1_0) { + puts("ERR: PMUFW v1.0 or less is detected\n"); + puts("ERR: Encrypt/Decrypt feature is not supported\n"); + puts("ERR: Please upgrade PMUFW\n"); + return CMD_RET_FAILURE; + } + + if (argc < cmdtp->maxargs - 1) + return CMD_RET_USAGE; + + aes->srcaddr = simple_strtoul(argv[2], NULL, 16); + aes->ivaddr = simple_strtoul(argv[3], NULL, 16); + aes->len = simple_strtoul(argv[4], NULL, 16); + aes->op = simple_strtoul(argv[5], NULL, 16); + aes->keysrc = simple_strtoul(argv[6], NULL, 16); + aes->dstaddr = simple_strtoul(argv[7], NULL, 16); + + flush_dcache_range((ulong)aes, (ulong)(aes) + + roundup(sizeof(struct aes), ARCH_DMA_MINALIGN)); + + if (aes->srcaddr && aes->ivaddr && aes->dstaddr) { + flush_dcache_range(aes->srcaddr, + (aes->srcaddr + + roundup(aes->len, ARCH_DMA_MINALIGN))); + flush_dcache_range(aes->ivaddr, + (aes->ivaddr + + roundup(IV_SIZE, ARCH_DMA_MINALIGN))); + flush_dcache_range(aes->dstaddr, + (aes->dstaddr + + roundup(aes->len, ARCH_DMA_MINALIGN))); + } + + if (aes->keysrc == 0) { + if (argc < cmdtp->maxargs) + return CMD_RET_USAGE; + + aes->keyaddr = simple_strtoul(argv[8], NULL, 16); + if (aes->keyaddr) + flush_dcache_range(aes->keyaddr, + (aes->keyaddr + + roundup(KEY_PTR_LEN, + ARCH_DMA_MINALIGN))); + } + + ret = xilinx_pm_request(PM_SECURE_AES, upper_32_bits((ulong)aes), + lower_32_bits((ulong)aes), 0, 0, ret_payload); + if (ret || ret_payload[1]) + printf("Failed: AES op status:0x%x, errcode:0x%x\n", + ret, ret_payload[1]); + + return ret; +} + #ifdef CONFIG_DEFINE_TCM_OCM_MMAP static int do_zynqmp_tcm_init(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) @@ -148,11 +219,145 @@ static int do_zynqmp_pmufw(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } +static int do_zynqmp_rsa(struct cmd_tbl *cmdtp, int flag, int argc, + char * const argv[]) +{ + u64 srcaddr, mod, exp; + u32 srclen, rsaop, size, ret_payload[PAYLOAD_ARG_CNT]; + int ret; + + if (argc != cmdtp->maxargs) + return CMD_RET_USAGE; + + if (zynqmp_firmware_version() <= PMUFW_V1_0) { + puts("ERR: PMUFW v1.0 or less is detected\n"); + puts("ERR: Encrypt/Decrypt feature is not supported\n"); + puts("ERR: Please upgrade PMUFW\n"); + return CMD_RET_FAILURE; + } + + srcaddr = simple_strtoul(argv[2], NULL, 16); + srclen = simple_strtoul(argv[3], NULL, 16); + if (srclen != RSA_KEY_SIZE) { + puts("ERR: srclen should be equal to 0x200(512 bytes)\n"); + return CMD_RET_USAGE; + } + + mod = simple_strtoul(argv[4], NULL, 16); + exp = simple_strtoul(argv[5], NULL, 16); + rsaop = simple_strtoul(argv[6], NULL, 16); + if (!(rsaop == 0 || rsaop == 1)) { + puts("ERR: rsaop should be either 0 or 1\n"); + return CMD_RET_USAGE; + } + + memcpy((void *)srcaddr + srclen, (void *)mod, MODULUS_LEN); + + /* + * For encryption we load public exponent (key size 4096-bits), + * for decryption we load private exponent (32-bits) + */ + if (rsaop) { + memcpy((void *)srcaddr + srclen + MODULUS_LEN, + (void *)exp, PUB_EXPO_LEN); + size = srclen + MODULUS_LEN + PUB_EXPO_LEN; + } else { + memcpy((void *)srcaddr + srclen + MODULUS_LEN, + (void *)exp, PRIV_EXPO_LEN); + size = srclen + MODULUS_LEN + PRIV_EXPO_LEN; + } + + flush_dcache_range((ulong)srcaddr, + (ulong)(srcaddr) + roundup(size, ARCH_DMA_MINALIGN)); + + ret = xilinx_pm_request(PM_SECURE_RSA, upper_32_bits((ulong)srcaddr), + lower_32_bits((ulong)srcaddr), srclen, rsaop, + ret_payload); + if (ret || ret_payload[1]) { + printf("Failed: RSA status:0x%x, errcode:0x%x\n", + ret, ret_payload[1]); + return CMD_RET_FAILURE; + } + + return CMD_RET_SUCCESS; +} + +static int do_zynqmp_sha3(struct cmd_tbl *cmdtp, int flag, + int argc, char * const argv[]) +{ + u64 srcaddr, hashaddr; + u32 srclen, ret_payload[PAYLOAD_ARG_CNT]; + int ret; + + if (argc > cmdtp->maxargs || argc < (cmdtp->maxargs - 1)) + return CMD_RET_USAGE; + + if (zynqmp_firmware_version() <= PMUFW_V1_0) { + puts("ERR: PMUFW v1.0 or less is detected\n"); + puts("ERR: Encrypt/Decrypt feature is not supported\n"); + puts("ERR: Please upgrade PMUFW\n"); + return CMD_RET_FAILURE; + } + + srcaddr = simple_strtoul(argv[2], NULL, 16); + srclen = simple_strtoul(argv[3], NULL, 16); + + if (argc == 5) { + hashaddr = simple_strtoul(argv[4], NULL, 16); + flush_dcache_range(hashaddr, + hashaddr + roundup(ZYNQMP_SHA3_SIZE, + ARCH_DMA_MINALIGN)); + } else { + hashaddr = srcaddr; + } + + /* Check srcaddr or srclen != 0 */ + if (!srcaddr || !srclen) { + puts("ERR: srcaddr & srclen should not be 0\n"); + return CMD_RET_USAGE; + } + + flush_dcache_range(srcaddr, + srcaddr + roundup(srclen, ARCH_DMA_MINALIGN)); + + ret = xilinx_pm_request(PM_SECURE_SHA, 0, 0, 0, + ZYNQMP_SHA3_INIT, ret_payload); + if (ret || ret_payload[1]) { + printf("Failed: SHA INIT status:0x%x, errcode:0x%x\n", + ret, ret_payload[1]); + return CMD_RET_FAILURE; + } + + ret = xilinx_pm_request(PM_SECURE_SHA, upper_32_bits((ulong)srcaddr), + lower_32_bits((ulong)srcaddr), + srclen, ZYNQMP_SHA3_UPDATE, ret_payload); + if (ret || ret_payload[1]) { + printf("Failed: SHA UPDATE status:0x%x, errcode:0x%x\n", + ret, ret_payload[1]); + return CMD_RET_FAILURE; + } + + ret = xilinx_pm_request(PM_SECURE_SHA, upper_32_bits((ulong)hashaddr), + lower_32_bits((ulong)hashaddr), + ZYNQMP_SHA3_SIZE, ZYNQMP_SHA3_FINAL, + ret_payload); + if (ret || ret_payload[1]) { + printf("Failed: SHA FINAL status:0x%x, errcode:0x%x\n", + ret, ret_payload[1]); + return CMD_RET_FAILURE; + } + + return CMD_RET_SUCCESS; +} + static struct cmd_tbl cmd_zynqmp_sub[] = { U_BOOT_CMD_MKENT(secure, 5, 0, do_zynqmp_verify_secure, "", ""), U_BOOT_CMD_MKENT(pmufw, 4, 0, do_zynqmp_pmufw, "", ""), U_BOOT_CMD_MKENT(mmio_read, 3, 0, do_zynqmp_mmio_read, "", ""), U_BOOT_CMD_MKENT(mmio_write, 5, 0, do_zynqmp_mmio_write, "", ""), + U_BOOT_CMD_MKENT(aes, 9, 0, do_zynqmp_aes, "", ""), + U_BOOT_CMD_MKENT(rsa, 7, 0, do_zynqmp_rsa, "", ""), + U_BOOT_CMD_MKENT(sha3, 5, 0, do_zynqmp_sha3, "", ""), #ifdef CONFIG_DEFINE_TCM_OCM_MMAP U_BOOT_CMD_MKENT(tcminit, 3, 0, do_zynqmp_tcm_init, "", ""), #endif @@ -196,6 +401,14 @@ static char zynqmp_help_text[] = "zynqmp mmio_read address - read from address\n" "zynqmp mmio_write address mask value - write value after masking to\n" " address\n" + "zynqmp aes srcaddr ivaddr len aesop keysrc dstaddr [keyaddr] -\n" + " Encrypts or decrypts blob of data at src address and puts it\n" + " back to dstaddr using key and iv at keyaddr and ivaddr\n" + " respectively. keysrc value specifies from which source key\n" + " has to be used, it can be User/Device/PUF key. A value of 0\n" + " for KUP(user key),1 for DeviceKey and 2 for PUF key. The\n" + " aesop value specifies the operation which can be 0 for\n" + " decrypt and 1 for encrypt operation\n" #ifdef CONFIG_DEFINE_TCM_OCM_MMAP "zynqmp tcminit mode - Initialize the TCM with zeros. TCM needs to be\n" " initialized before accessing to avoid ECC\n" @@ -204,11 +417,24 @@ static char zynqmp_help_text[] = " lock(0)/split(1)\n" #endif "zynqmp pmufw address size - load PMU FW configuration object\n" + "zynqmp rsa srcaddr srclen mod exp rsaop -\n" + " Performs RSA encryption and RSA decryption on blob of data\n" + " at srcaddr and puts it back in srcaddr using modulus and\n" + " public or private exponent\n" + " srclen : must be key size(4096 bits)\n" + " exp : private key exponent for RSA decryption(4096 bits)\n" + " public key exponent for RSA encryption(32 bits)\n" + " rsaop : 0 for RSA Decryption, 1 for RSA Encryption\n" + "zynqmp sha3 srcaddr srclen [key_addr] -\n" + " Generates sha3 hash value for data blob at srcaddr and puts\n" + " 48 bytes hash value into srcaddr\n" + " Optional key_addr can be specified for saving sha3 hash value\n" + " Note: srcaddr/srclen should not be 0\n" ; #endif U_BOOT_CMD( - zynqmp, 5, 1, do_zynqmp, + zynqmp, 9, 1, do_zynqmp, "ZynqMP sub-system", zynqmp_help_text ) diff --git a/board/xilinx/zynqmp/tap_delays.c b/board/xilinx/zynqmp/tap_delays.c index 5fde0aed7db..1cab25f00a5 100644 --- a/board/xilinx/zynqmp/tap_delays.c +++ b/board/xilinx/zynqmp/tap_delays.c @@ -6,8 +6,10 @@ */ #include <common.h> +#include <zynqmp_tap_delay.h> #include <asm/arch/sys_proto.h> #include <linux/delay.h> +#include <mmc.h> #define SD_DLL_CTRL 0xFF180358 #define SD_ITAP_DLY 0xFF180314 @@ -25,43 +27,9 @@ #define SD1_ITAPDLYENA_MASK 0x01000000 #define SD1_ITAPDLYENA 0x01000000 #define SD0_ITAPDLYSEL_MASK 0x000000FF -#define SD0_ITAPDLYSEL_HSD 0x00000015 -#define SD0_ITAPDLYSEL_SD_DDR50 0x0000003D -#define SD0_ITAPDLYSEL_MMC_DDR50 0x00000012 - #define SD1_ITAPDLYSEL_MASK 0x00FF0000 -#define SD1_ITAPDLYSEL_HSD 0x00150000 -#define SD1_ITAPDLYSEL_SD_DDR50 0x003D0000 -#define SD1_ITAPDLYSEL_MMC_DDR50 0x00120000 - #define SD0_OTAPDLYSEL_MASK 0x0000003F -#define SD0_OTAPDLYSEL_MMC_HSD 0x00000006 -#define SD0_OTAPDLYSEL_SD_HSD 0x00000005 -#define SD0_OTAPDLYSEL_SDR50 0x00000003 -#define SD0_OTAPDLYSEL_SDR104_B0 0x00000003 -#define SD0_OTAPDLYSEL_SDR104_B2 0x00000002 -#define SD0_OTAPDLYSEL_SD_DDR50 0x00000004 -#define SD0_OTAPDLYSEL_MMC_DDR50 0x00000006 - #define SD1_OTAPDLYSEL_MASK 0x003F0000 -#define SD1_OTAPDLYSEL_MMC_HSD 0x00060000 -#define SD1_OTAPDLYSEL_SD_HSD 0x00050000 -#define SD1_OTAPDLYSEL_SDR50 0x00030000 -#define SD1_OTAPDLYSEL_SDR104_B0 0x00030000 -#define SD1_OTAPDLYSEL_SDR104_B2 0x00020000 -#define SD1_OTAPDLYSEL_SD_DDR50 0x00040000 -#define SD1_OTAPDLYSEL_MMC_DDR50 0x00060000 - -#define MMC_BANK2 0x2 - -#define MMC_TIMING_UHS_SDR25 1 -#define MMC_TIMING_UHS_SDR50 2 -#define MMC_TIMING_UHS_SDR104 3 -#define MMC_TIMING_UHS_DDR50 4 -#define MMC_TIMING_MMC_HS200 5 -#define MMC_TIMING_SD_HS 6 -#define MMC_TIMING_MMC_DDR52 7 -#define MMC_TIMING_MMC_HS 8 void zynqmp_dll_reset(u8 deviceid) { @@ -82,149 +50,49 @@ void zynqmp_dll_reset(u8 deviceid) zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0); } -static void arasan_zynqmp_tap_sdr104(u8 deviceid, u8 timing, u8 bank) -{ - if (deviceid == 0) { - /* Program OTAP */ - if (bank == MMC_BANK2) - zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, - SD0_OTAPDLYSEL_SDR104_B2); - else - zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, - SD0_OTAPDLYSEL_SDR104_B0); - } else { - /* Program OTAP */ - if (bank == MMC_BANK2) - zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, - SD1_OTAPDLYSEL_SDR104_B2); - else - zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, - SD1_OTAPDLYSEL_SDR104_B0); - } -} - -static void arasan_zynqmp_tap_hs(u8 deviceid, u8 timing, u8 bank) -{ - if (deviceid == 0) { - /* Program ITAP */ - zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, - SD0_ITAPCHGWIN); - zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK, - SD0_ITAPDLYENA); - zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK, - SD0_ITAPDLYSEL_HSD); - zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0); - /* Program OTAP */ - if (timing == MMC_TIMING_MMC_HS) - zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, - SD0_OTAPDLYSEL_MMC_HSD); - else - zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, - SD0_OTAPDLYSEL_SD_HSD); - } else { - /* Program ITAP */ - zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, - SD1_ITAPCHGWIN); - zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK, - SD1_ITAPDLYENA); - zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK, - SD1_ITAPDLYSEL_HSD); - zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0); - /* Program OTAP */ - if (timing == MMC_TIMING_MMC_HS) - zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, - SD1_OTAPDLYSEL_MMC_HSD); - else - zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, - SD1_OTAPDLYSEL_SD_HSD); - } -} - -static void arasan_zynqmp_tap_ddr50(u8 deviceid, u8 timing, u8 bank) +void arasan_zynqmp_set_tapdelay(u8 deviceid, u32 itap_delay, u32 otap_delay) { if (deviceid == 0) { + zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, + SD0_DLL_RST); /* Program ITAP */ - zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, - SD0_ITAPCHGWIN); - zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK, - SD0_ITAPDLYENA); - if (timing == MMC_TIMING_UHS_DDR50) - zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK, - SD0_ITAPDLYSEL_SD_DDR50); - else + if (itap_delay) { + zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, + SD0_ITAPCHGWIN); + zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK, + SD0_ITAPDLYENA); zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK, - SD0_ITAPDLYSEL_MMC_DDR50); - zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0); + itap_delay); + zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, + 0x0); + } + /* Program OTAP */ - if (timing == MMC_TIMING_UHS_DDR50) - zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, - SD0_OTAPDLYSEL_SD_DDR50); - else + if (otap_delay) zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, - SD0_OTAPDLYSEL_MMC_DDR50); - } else { - /* Program ITAP */ - zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, - SD1_ITAPCHGWIN); - zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK, - SD1_ITAPDLYENA); - if (timing == MMC_TIMING_UHS_DDR50) - zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK, - SD1_ITAPDLYSEL_SD_DDR50); - else - zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK, - SD1_ITAPDLYSEL_MMC_DDR50); - zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0); - /* Program OTAP */ - if (timing == MMC_TIMING_UHS_DDR50) - zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, - SD1_OTAPDLYSEL_SD_DDR50); - else - zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, - SD1_OTAPDLYSEL_MMC_DDR50); - } -} + otap_delay); -static void arasan_zynqmp_tap_sdr50(u8 deviceid, u8 timing, u8 bank) -{ - if (deviceid == 0) { - /* Program OTAP */ - zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, - SD0_OTAPDLYSEL_SDR50); + zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0); } else { - /* Program OTAP */ - zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, - SD1_OTAPDLYSEL_SDR50); - } -} - -void arasan_zynqmp_set_tapdelay(u8 deviceid, u8 timing, u8 bank) -{ - if (deviceid == 0) - zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, - SD0_DLL_RST); - else zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, SD1_DLL_RST); + /* Program ITAP */ + if (itap_delay) { + zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, + SD1_ITAPCHGWIN); + zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK, + SD1_ITAPDLYENA); + zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK, + (itap_delay << 16)); + zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, + 0x0); + } - switch (timing) { - case MMC_TIMING_UHS_SDR25: - arasan_zynqmp_tap_hs(deviceid, timing, bank); - break; - case MMC_TIMING_UHS_SDR50: - arasan_zynqmp_tap_sdr50(deviceid, timing, bank); - break; - case MMC_TIMING_UHS_SDR104: - case MMC_TIMING_MMC_HS200: - arasan_zynqmp_tap_sdr104(deviceid, timing, bank); - break; - case MMC_TIMING_UHS_DDR50: - arasan_zynqmp_tap_ddr50(deviceid, timing, bank); - break; - } + /* Program OTAP */ + if (otap_delay) + zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, + (otap_delay << 16)); - if (deviceid == 0) - zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0); - else zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0); + } } diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index 28f067a2515..731285a7367 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -40,12 +40,12 @@ #include "pm_cfg_obj.h" #define ZYNQMP_VERSION_SIZE 7 -#define EFUSE_VCU_DIS_MASK 0x100 -#define EFUSE_VCU_DIS_SHIFT 8 -#define EFUSE_GPU_DIS_MASK 0x20 -#define EFUSE_GPU_DIS_SHIFT 5 -#define IDCODE2_PL_INIT_MASK 0x200 -#define IDCODE2_PL_INIT_SHIFT 9 +#define EFUSE_VCU_DIS_MASK 0x100 +#define EFUSE_VCU_DIS_SHIFT 8 +#define EFUSE_GPU_DIS_MASK 0x20 +#define EFUSE_GPU_DIS_SHIFT 5 +#define IDCODE2_PL_INIT_MASK 0x200 +#define IDCODE2_PL_INIT_SHIFT 9 DECLARE_GLOBAL_DATA_PTR; @@ -100,7 +100,7 @@ static const struct { { .id = 0x04738093, .device = 9, - .variants = ZYNQMP_VARIANT_EG, + .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG, }, { .id = 0x04740093, @@ -190,8 +190,13 @@ static char *zynqmp_get_silicon_idcode_name(void) u32 idcode, idcode2; char name[ZYNQMP_VERSION_SIZE]; u32 ret_payload[PAYLOAD_ARG_CNT]; + int ret; - xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload); + ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload); + if (ret) { + debug("%s: Getting chipid failed\n", __func__); + return "unknown"; + } /* * Firmware returns: @@ -204,7 +209,7 @@ static char *zynqmp_get_silicon_idcode_name(void) idcode = ret_payload[1]; idcode2 = ret_payload[2] >> ZYNQMP_CSU_VERSION_EMPTY_SHIFT; - debug("%s, IDCODE: 0x%0X, IDCODE2: 0x%0X\r\n", __func__, idcode, + debug("%s, IDCODE: 0x%0x, IDCODE2: 0x%0x\r\n", __func__, idcode, idcode2); for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { @@ -216,8 +221,10 @@ static char *zynqmp_get_silicon_idcode_name(void) return "unknown"; /* Add device prefix to the name */ - strncpy(name, "zu", ZYNQMP_VERSION_SIZE); - strncat(&name[2], simple_itoa(zynqmp_devices[i].device), 2); + ret = snprintf(name, ZYNQMP_VERSION_SIZE, "zu%d", + zynqmp_devices[i].device); + if (ret < 0) + return "unknown"; if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_EV) { /* Devices with EV variant might be EG/CG/EV family */ @@ -321,6 +328,9 @@ int board_init(void) if (sizeof(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE) > 1) zynqmp_pmufw_load_config_object(zynqmp_pm_cfg_obj, zynqmp_pm_cfg_obj_size); +#else + if (CONFIG_IS_ENABLED(DM_I2C) && CONFIG_IS_ENABLED(I2C_EEPROM)) + xilinx_read_eeprom(); #endif printf("EL Level:\tEL%d\n", current_el()); diff --git a/cmd/Kconfig b/cmd/Kconfig index 9f362907966..1595de999b5 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2239,6 +2239,7 @@ config CMD_KGDB config CMD_LOG bool "log - Generation, control and access to logging" select LOG + select GETOPT help This provides access to logging features. It allows the output of log data to be controlled to a limited extent (setting up the default diff --git a/cmd/log.c b/cmd/log.c index 6afe6ead251..ca1c51e0672 100644 --- a/cmd/log.c +++ b/cmd/log.c @@ -7,27 +7,298 @@ #include <common.h> #include <command.h> #include <dm.h> +#include <getopt.h> #include <log.h> +#include <malloc.h> static char log_fmt_chars[LOGF_COUNT] = "clFLfm"; +static enum log_level_t parse_log_level(char *const arg) +{ + enum log_level_t ret; + ulong level; + + if (!strict_strtoul(arg, 10, &level)) { + if (level > _LOG_MAX_LEVEL) { + printf("Only log levels <= %d are supported\n", + _LOG_MAX_LEVEL); + return LOGL_NONE; + } + return level; + } + + ret = log_get_level_by_name(arg); + if (ret == LOGL_NONE) + printf("Unknown log level \"%s\"\n", arg); + return ret; +} + static int do_log_level(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { + enum log_level_t log_level; + if (argc > 1) { - long log_level = simple_strtol(argv[1], NULL, 10); + log_level = parse_log_level(argv[1]); - if (log_level < 0 || log_level > _LOG_MAX_LEVEL) { - printf("Only log levels <= %d are supported\n", - _LOG_MAX_LEVEL); + if (log_level == LOGL_NONE) return CMD_RET_FAILURE; - } gd->default_log_level = log_level; } else { - printf("Default log level: %d\n", gd->default_log_level); + for (log_level = LOGL_FIRST; log_level <= _LOG_MAX_LEVEL; + log_level++) + printf("%s%s\n", log_get_level_name(log_level), + log_level == gd->default_log_level ? + " (default)" : ""); } - return 0; + return CMD_RET_SUCCESS; +} + +static int do_log_categories(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + enum log_category_t cat; + const char *name; + + for (cat = LOGC_FIRST; cat < LOGC_COUNT; cat++) { + name = log_get_cat_name(cat); + /* + * Invalid category names (e.g. <invalid> or <missing>) begin + * with '<'. + */ + if (name[0] == '<') + continue; + printf("%s\n", name); + } + + return CMD_RET_SUCCESS; +} + +static int do_log_drivers(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct log_device *ldev; + + list_for_each_entry(ldev, &gd->log_head, sibling_node) + printf("%s\n", ldev->drv->name); + + return CMD_RET_SUCCESS; +} + +static int do_log_filter_list(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int opt; + const char *drv_name = "console"; + struct getopt_state gs; + struct log_filter *filt; + struct log_device *ldev; + + getopt_init_state(&gs); + while ((opt = getopt(&gs, argc, argv, "d:")) > 0) { + switch (opt) { + case 'd': + drv_name = gs.arg; + break; + default: + return CMD_RET_USAGE; + } + } + + if (gs.index != argc) + return CMD_RET_USAGE; + + ldev = log_device_find_by_name(drv_name); + if (!ldev) { + printf("Could not find log device for \"%s\"\n", drv_name); + return CMD_RET_FAILURE; + } + + /* <3> < 6 > <2+1 + 7 > < 16 > < unbounded... */ + printf("num policy level categories files\n"); + list_for_each_entry(filt, &ldev->filter_head, sibling_node) { + printf("%3d %6.6s %s %-7.7s ", filt->filter_num, + filt->flags & LOGFF_DENY ? "deny" : "allow", + filt->flags & LOGFF_LEVEL_MIN ? ">=" : "<=", + log_get_level_name(filt->level)); + + if (filt->flags & LOGFF_HAS_CAT) { + int i; + + if (filt->cat_list[0] != LOGC_END) + printf("%16.16s %s\n", + log_get_cat_name(filt->cat_list[0]), + filt->file_list ? filt->file_list : ""); + + for (i = 1; i < LOGF_MAX_CATEGORIES && + filt->cat_list[i] != LOGC_END; i++) + printf("%21c %16.16s\n", ' ', + log_get_cat_name(filt->cat_list[i])); + } else { + printf("%16c %s\n", ' ', + filt->file_list ? filt->file_list : ""); + } + } + + return CMD_RET_SUCCESS; +} + +static int do_log_filter_add(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + bool level_set = false; + bool print_num = false; + bool type_set = false; + char *file_list = NULL; + const char *drv_name = "console"; + int opt, err; + int cat_count = 0; + int flags = 0; + enum log_category_t cat_list[LOGF_MAX_CATEGORIES + 1]; + enum log_level_t level = LOGL_MAX; + struct getopt_state gs; + + getopt_init_state(&gs); + while ((opt = getopt(&gs, argc, argv, "Ac:d:Df:l:L:p")) > 0) { + switch (opt) { + case 'A': +#define do_type() do { \ + if (type_set) { \ + printf("Allow or deny set twice\n"); \ + return CMD_RET_USAGE; \ + } \ + type_set = true; \ +} while (0) + do_type(); + break; + case 'c': { + enum log_category_t cat; + + if (cat_count >= LOGF_MAX_CATEGORIES) { + printf("Too many categories\n"); + return CMD_RET_FAILURE; + } + + cat = log_get_cat_by_name(gs.arg); + if (cat == LOGC_NONE) { + printf("Unknown category \"%s\"\n", gs.arg); + return CMD_RET_FAILURE; + } + + cat_list[cat_count++] = cat; + break; + } + case 'd': + drv_name = gs.arg; + break; + case 'D': + do_type(); + flags |= LOGFF_DENY; + break; + case 'f': + file_list = gs.arg; + break; + case 'l': +#define do_level() do { \ + if (level_set) { \ + printf("Log level set twice\n"); \ + return CMD_RET_USAGE; \ + } \ + level = parse_log_level(gs.arg); \ + if (level == LOGL_NONE) \ + return CMD_RET_FAILURE; \ + level_set = true; \ +} while (0) + do_level(); + break; + case 'L': + do_level(); + flags |= LOGFF_LEVEL_MIN; + break; + case 'p': + print_num = true; + break; + default: + return CMD_RET_USAGE; + } + } + + if (gs.index != argc) + return CMD_RET_USAGE; + + cat_list[cat_count] = LOGC_END; + err = log_add_filter_flags(drv_name, cat_count ? cat_list : NULL, level, + file_list, flags); + if (err < 0) { + printf("Could not add filter (err = %d)\n", err); + return CMD_RET_FAILURE; + } else if (print_num) { + printf("%d\n", err); + } + + return CMD_RET_SUCCESS; +} + +static int do_log_filter_remove(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + bool all = false; + int opt, err; + ulong filter_num; + const char *drv_name = "console"; + struct getopt_state gs; + + getopt_init_state(&gs); + while ((opt = getopt(&gs, argc, argv, "ad:")) > 0) { + switch (opt) { + case 'a': + all = true; + break; + case 'd': + drv_name = gs.arg; + break; + default: + return CMD_RET_USAGE; + } + } + + if (all) { + struct log_filter *filt, *tmp_filt; + struct log_device *ldev; + + if (gs.index != argc) + return CMD_RET_USAGE; + + ldev = log_device_find_by_name(drv_name); + if (!ldev) { + printf("Could not find log device for \"%s\"\n", + drv_name); + return CMD_RET_FAILURE; + } + + list_for_each_entry_safe(filt, tmp_filt, &ldev->filter_head, + sibling_node) { + list_del(&filt->sibling_node); + free(filt); + } + } else { + if (gs.index + 1 != argc) + return CMD_RET_USAGE; + + if (strict_strtoul(argv[gs.index], 10, &filter_num)) { + printf("Invalid filter number \"%s\"\n", argv[gs.index]); + return CMD_RET_FAILURE; + } + + err = log_remove_filter(drv_name, filter_num); + if (err) { + printf("Could not remove filter (err = %d)\n", err); + return CMD_RET_FAILURE; + } + } + + return CMD_RET_SUCCESS; } static int do_log_format(struct cmd_tbl *cmdtp, int flag, int argc, @@ -103,39 +374,31 @@ static int do_log_rec(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } -static struct cmd_tbl log_sub[] = { - U_BOOT_CMD_MKENT(level, CONFIG_SYS_MAXARGS, 1, do_log_level, "", ""), -#ifdef CONFIG_LOG_TEST - U_BOOT_CMD_MKENT(test, 2, 1, do_log_test, "", ""), -#endif - U_BOOT_CMD_MKENT(format, CONFIG_SYS_MAXARGS, 1, do_log_format, "", ""), - U_BOOT_CMD_MKENT(rec, CONFIG_SYS_MAXARGS, 1, do_log_rec, "", ""), -}; - -static int do_log(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -{ - struct cmd_tbl *cp; - - if (argc < 2) - return CMD_RET_USAGE; - - /* drop initial "log" arg */ - argc--; - argv++; - - cp = find_cmd_tbl(argv[0], log_sub, ARRAY_SIZE(log_sub)); - if (cp) - return cp->cmd(cmdtp, flag, argc, argv); - - return CMD_RET_USAGE; -} - #ifdef CONFIG_SYS_LONGHELP static char log_help_text[] = - "level - get/set log level\n" -#ifdef CONFIG_LOG_TEST - "log test - run log tests\n" -#endif + "level [<level>] - get/set log level\n" + "categories - list log categories\n" + "drivers - list log drivers\n" + "log filter-list [OPTIONS] - list all filters for a log driver\n" + "\t-d <driver> - Specify the log driver to list filters from; defaults\n" + "\t to console\n" + "log filter-add [OPTIONS] - add a new filter to a driver\n" + "\t-A - Allow messages matching this filter; mutually exclusive with -D\n" + "\t This is the default.\n" + "\t-c <category> - Category to match; may be specified multiple times\n" + "\t-d <driver> - Specify the log driver to add the filter to; defaults\n" + "\t to console\n" + "\t-D - Deny messages matching this filter; mutually exclusive with -A\n" + "\t-f <files_list> - A comma-separated list of files to match\n" + "\t-l <level> - Match log levels less than or equal to <level>;\n" + "\t mutually-exclusive with -L\n" + "\t-L <level> - Match log levels greather than or equal to <level>;\n" + "\t mutually-exclusive with -l\n" + "\t-p - Print the filter number on success\n" + "log filter-remove [OPTIONS] [<num>] - Remove filter number <num>\n" + "\t-a - Remove ALL filters\n" + "\t-d <driver> - Specify the log driver to remove the filter from;\n" + "\t defaults to console\n" "log format <fmt> - set log output format. <fmt> is a string where\n" "\teach letter indicates something that should be displayed:\n" "\tc=category, l=level, F=file, L=line number, f=function, m=msg\n" @@ -145,7 +408,14 @@ static char log_help_text[] = ; #endif -U_BOOT_CMD( - log, CONFIG_SYS_MAXARGS, 1, do_log, - "log system", log_help_text +U_BOOT_CMD_WITH_SUBCMDS(log, "log system", log_help_text, + U_BOOT_SUBCMD_MKENT(level, 2, 1, do_log_level), + U_BOOT_SUBCMD_MKENT(categories, 1, 1, do_log_categories), + U_BOOT_SUBCMD_MKENT(drivers, 1, 1, do_log_drivers), + U_BOOT_SUBCMD_MKENT(filter-list, 3, 1, do_log_filter_list), + U_BOOT_SUBCMD_MKENT(filter-add, CONFIG_SYS_MAXARGS, 1, + do_log_filter_add), + U_BOOT_SUBCMD_MKENT(filter-remove, 4, 1, do_log_filter_remove), + U_BOOT_SUBCMD_MKENT(format, 2, 1, do_log_format), + U_BOOT_SUBCMD_MKENT(rec, 7, 1, do_log_rec), ); diff --git a/common/fdt_support.c b/common/fdt_support.c index a565b470f81..5ae75df3c65 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -611,14 +611,9 @@ int fdt_record_loadable(void *blob, u32 index, const char *name, if (node < 0) return node; - /* - * We record these as 32bit entities, possibly truncating addresses. - * However, spl_fit.c is not 64bit safe either: i.e. we should not - * have an issue here. - */ - fdt_setprop_u32(blob, node, "load-addr", load_addr); + fdt_setprop_u64(blob, node, "load", load_addr); if (entry_point != -1) - fdt_setprop_u32(blob, node, "entry-point", entry_point); + fdt_setprop_u64(blob, node, "entry", entry_point); fdt_setprop_u32(blob, node, "size", size); if (type) fdt_setprop_string(blob, node, "type", type); diff --git a/common/image-fit.c b/common/image-fit.c index d54eff9033c..c82d4d8015f 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -791,17 +791,18 @@ static int fit_image_get_address(const void *fit, int noffset, char *name, return -1; } - if (len > sizeof(ulong)) { - printf("Unsupported %s address size\n", name); - return -1; - } - cell_len = len >> 2; /* Use load64 to avoid compiling warning for 32-bit target */ while (cell_len--) { load64 = (load64 << 32) | uimage_to_cpu(*cell); cell++; } + + if (len > sizeof(ulong) && (uint32_t)(load64 >> 32)) { + printf("Unsupported %s address size\n", name); + return -1; + } + *load = (ulong)load64; return 0; diff --git a/common/log.c b/common/log.c index 9f98e9aff8b..4b6f3fcd04a 100644 --- a/common/log.c +++ b/common/log.c @@ -13,7 +13,7 @@ DECLARE_GLOBAL_DATA_PTR; -static const char *log_cat_name[] = { +static const char *const log_cat_name[] = { "none", "arch", "board", @@ -31,7 +31,7 @@ static const char *log_cat_name[] = { _Static_assert(ARRAY_SIZE(log_cat_name) == LOGC_COUNT - LOGC_NONE, "log_cat_name size"); -static const char *log_level_name[] = { +static const char *const log_level_name[] = { "EMERG", "ALERT", "CRIT", @@ -99,7 +99,7 @@ enum log_level_t log_get_level_by_name(const char *name) return LOGL_NONE; } -static struct log_device *log_device_find_by_name(const char *drv_name) +struct log_device *log_device_find_by_name(const char *drv_name) { struct log_device *ldev; @@ -111,15 +111,7 @@ static struct log_device *log_device_find_by_name(const char *drv_name) return NULL; } -/** - * log_has_cat() - check if a log category exists within a list - * - * @cat_list: List of categories to check, at most LOGF_MAX_CATEGORIES entries - * long, terminated by LC_END if fewer - * @cat: Category to search for - * @return true if @cat is in @cat_list, else false - */ -static bool log_has_cat(enum log_category_t cat_list[], enum log_category_t cat) +bool log_has_cat(enum log_category_t cat_list[], enum log_category_t cat) { int i; @@ -131,16 +123,7 @@ static bool log_has_cat(enum log_category_t cat_list[], enum log_category_t cat) return false; } -/** - * log_has_file() - check if a file is with a list - * - * @file_list: List of files to check, separated by comma - * @file: File to check for. This string is matched against the end of each - * file in the list, i.e. ignoring any preceding path. The list is - * intended to consist of relative pathnames, e.g. common/main.c,cmd/log.c - * @return true if @file is in @file_list, else false - */ -static bool log_has_file(const char *file_list, const char *file) +bool log_has_file(const char *file_list, const char *file) { int file_len = strlen(file); const char *s, *p; @@ -179,15 +162,25 @@ static bool log_passes_filters(struct log_device *ldev, struct log_rec *rec) } list_for_each_entry(filt, &ldev->filter_head, sibling_node) { - if (rec->level > filt->max_level) + if (filt->flags & LOGFF_LEVEL_MIN) { + if (rec->level < filt->level) + continue; + } else if (rec->level > filt->level) { continue; + } + if ((filt->flags & LOGFF_HAS_CAT) && !log_has_cat(filt->cat_list, rec->cat)) continue; + if (filt->file_list && !log_has_file(filt->file_list, rec->file)) continue; - return true; + + if (filt->flags & LOGFF_DENY) + return false; + else + return true; } return false; @@ -263,8 +256,9 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file, return 0; } -int log_add_filter(const char *drv_name, enum log_category_t cat_list[], - enum log_level_t max_level, const char *file_list) +int log_add_filter_flags(const char *drv_name, enum log_category_t cat_list[], + enum log_level_t level, const char *file_list, + int flags) { struct log_filter *filt; struct log_device *ldev; @@ -278,6 +272,7 @@ int log_add_filter(const char *drv_name, enum log_category_t cat_list[], if (!filt) return -ENOMEM; + filt->flags = flags; if (cat_list) { filt->flags |= LOGFF_HAS_CAT; for (i = 0; ; i++) { @@ -290,16 +285,20 @@ int log_add_filter(const char *drv_name, enum log_category_t cat_list[], break; } } - filt->max_level = max_level; + filt->level = level; if (file_list) { filt->file_list = strdup(file_list); if (!filt->file_list) { - ret = ENOMEM; + ret = -ENOMEM; goto err; } } filt->filter_num = ldev->next_filter_num++; - list_add_tail(&filt->sibling_node, &ldev->filter_head); + /* Add deny filters to the beginning of the list */ + if (flags & LOGFF_DENY) + list_add(&filt->sibling_node, &ldev->filter_head); + else + list_add_tail(&filt->sibling_node, &ldev->filter_head); return filt->filter_num; diff --git a/common/spl/spl_atf.c b/common/spl/spl_atf.c index b54b4f0d22e..9bd25f6b32c 100644 --- a/common/spl/spl_atf.c +++ b/common/spl/spl_atf.c @@ -132,10 +132,11 @@ static int spl_fit_images_find(void *blob, int os) uintptr_t spl_fit_images_get_entry(void *blob, int node) { ulong val; + int ret; - val = fdt_getprop_u32(blob, node, "entry-point"); - if (val == FDT_ERROR) - val = fdt_getprop_u32(blob, node, "load-addr"); + ret = fit_image_get_entry(blob, node, &val); + if (ret) + ret = fit_image_get_load(blob, node, &val); debug("%s: entry point 0x%lx\n", __func__, val); return val; diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index fd6086a65c3..f5109e86d14 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -332,9 +332,15 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector, } if (image_info) { + ulong entry_point; + image_info->load_addr = load_addr; image_info->size = length; - image_info->entry_point = fdt_getprop_u32(fit, node, "entry"); + + if (!fit_image_get_entry(fit, node, &entry_point)) + image_info->entry_point = entry_point; + else + image_info->entry_point = FDT_ERROR; } return 0; diff --git a/common/spl/spl_opensbi.c b/common/spl/spl_opensbi.c index 14f335f75f0..41e0746bb01 100644 --- a/common/spl/spl_opensbi.c +++ b/common/spl/spl_opensbi.c @@ -61,11 +61,9 @@ void spl_invoke_opensbi(struct spl_image_info *spl_image) } /* Get U-Boot entry point */ - uboot_entry = fdt_getprop_u32(spl_image->fdt_addr, uboot_node, - "entry-point"); - if (uboot_entry == FDT_ERROR) - uboot_entry = fdt_getprop_u32(spl_image->fdt_addr, uboot_node, - "load-addr"); + ret = fit_image_get_entry(spl_image->fdt_addr, uboot_node, &uboot_entry); + if (ret) + ret = fit_image_get_load(spl_image->fdt_addr, uboot_node, &uboot_entry); /* Prepare obensbi_info object */ opensbi_info.magic = FW_DYNAMIC_INFO_MAGIC_VALUE; diff --git a/configs/aristainetos2_defconfig b/configs/aristainetos2_defconfig index 81863f601d6..35e4b09715f 100644 --- a/configs/aristainetos2_defconfig +++ b/configs/aristainetos2_defconfig @@ -58,6 +58,7 @@ CONFIG_DTB_RESELECT=y CONFIG_MULTI_DTB_FIT=y CONFIG_ENV_OVERWRITE=y CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_ENV_SPI_EARLY=y CONFIG_SYS_REDUNDAND_ENVIRONMENT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_VERSION_VARIABLE=y diff --git a/configs/aristainetos2b_defconfig b/configs/aristainetos2b_defconfig index 2e59c3014e3..d47a074645b 100644 --- a/configs/aristainetos2b_defconfig +++ b/configs/aristainetos2b_defconfig @@ -56,6 +56,7 @@ CONFIG_DTB_RESELECT=y CONFIG_MULTI_DTB_FIT=y CONFIG_ENV_OVERWRITE=y CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_ENV_SPI_EARLY=y CONFIG_SYS_REDUNDAND_ENVIRONMENT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_VERSION_VARIABLE=y diff --git a/configs/aristainetos2bcsl_defconfig b/configs/aristainetos2bcsl_defconfig index 8e6d2994fbe..30139621d83 100644 --- a/configs/aristainetos2bcsl_defconfig +++ b/configs/aristainetos2bcsl_defconfig @@ -56,6 +56,7 @@ CONFIG_DTB_RESELECT=y CONFIG_MULTI_DTB_FIT=y CONFIG_ENV_OVERWRITE=y CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_ENV_SPI_EARLY=y CONFIG_SYS_REDUNDAND_ENVIRONMENT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_VERSION_VARIABLE=y diff --git a/configs/aristainetos2c_defconfig b/configs/aristainetos2c_defconfig index 372d70567ad..50cadb749af 100644 --- a/configs/aristainetos2c_defconfig +++ b/configs/aristainetos2c_defconfig @@ -56,6 +56,7 @@ CONFIG_DTB_RESELECT=y CONFIG_MULTI_DTB_FIT=y CONFIG_ENV_OVERWRITE=y CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_ENV_SPI_EARLY=y CONFIG_SYS_REDUNDAND_ENVIRONMENT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_VERSION_VARIABLE=y diff --git a/configs/avnet_ultrazedev_cc_v1_0_ultrazedev_som_v1_0_defconfig b/configs/avnet_ultrazedev_cc_v1_0_ultrazedev_som_v1_0_defconfig index 25282ba428a..2426179d442 100644 --- a/configs/avnet_ultrazedev_cc_v1_0_ultrazedev_som_v1_0_defconfig +++ b/configs/avnet_ultrazedev_cc_v1_0_ultrazedev_som_v1_0_defconfig @@ -8,6 +8,8 @@ CONFIG_DEBUG_UART_BASE=0xff000000 CONFIG_DEBUG_UART_CLOCK=100000000 CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y +CONFIG_ZYNQ_MAC_IN_EEPROM=y +CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0xfa CONFIG_DEFAULT_DEVICE_TREE="avnet-ultrazedev-cc-v1.0-ultrazedev-som-v1.0" CONFIG_DEBUG_UART=y CONFIG_DISTRO_DEFAULTS=y @@ -42,7 +44,6 @@ CONFIG_I2C_MUX=y CONFIG_I2C_MUX_PCA954x=y CONFIG_MISC=y CONFIG_I2C_EEPROM=y -CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0xfa CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH_BAR=y diff --git a/configs/microblaze-generic_defconfig b/configs/microblaze-generic_defconfig index bfbdb492893..08c88856dcd 100644 --- a/configs/microblaze-generic_defconfig +++ b/configs/microblaze-generic_defconfig @@ -12,6 +12,7 @@ CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1 CONFIG_XILINX_MICROBLAZE0_USE_DIV=1 CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=1 CONFIG_DEFAULT_DEVICE_TREE="microblaze-generic" +CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_FIT_VERBOSE=y CONFIG_BOOTDELAY=-1 @@ -21,13 +22,12 @@ CONFIG_USE_PREBOOT=y CONFIG_PREBOOT="echo U-BOOT for ${hostname};setenv preboot;echo" CONFIG_SYS_CONSOLE_IS_IN_ENV=y CONFIG_DISPLAY_BOARDINFO=y +CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_SPL_BOARD_INIT=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_NOR_SUPPORT=y CONFIG_SPL_OS_BOOT=y CONFIG_SYS_OS_BASE=0x2c060000 -CONFIG_HUSH_PARSER=y -# CONFIG_AUTO_COMPLETE is not set CONFIG_SYS_PROMPT="U-Boot-mONStR> " CONFIG_CMD_IMLS=y CONFIG_CMD_SPL=y @@ -35,10 +35,7 @@ CONFIG_CMD_ASKENV=y CONFIG_CMD_GPIO=y CONFIG_CMD_SAVES=y # CONFIG_CMD_SETEXPR is not set -CONFIG_CMD_DHCP=y CONFIG_CMD_TFTPPUT=y -CONFIG_CMD_MII=y -CONFIG_CMD_PING=y CONFIG_CMD_CACHE=y CONFIG_CMD_JFFS2=y CONFIG_SPL_OF_CONTROL=y @@ -47,6 +44,7 @@ CONFIG_NET_RANDOM_ETHADDR=y CONFIG_NETCONSOLE=y CONFIG_SPL_DM=y CONFIG_XILINX_GPIO=y +CONFIG_DM_I2C=y CONFIG_LED=y CONFIG_LED_GPIO=y CONFIG_MTD=y @@ -56,6 +54,12 @@ CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y CONFIG_FLASH_CFI_MTD=y CONFIG_SYS_FLASH_PROTECTION=y CONFIG_SYS_FLASH_CFI=y +CONFIG_SPI_FLASH_ISSI=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_SST=y +CONFIG_SPI_FLASH_WINBOND=y CONFIG_PHY_ATHEROS=y CONFIG_PHY_BROADCOM=y CONFIG_PHY_DAVICOM=y @@ -71,6 +75,7 @@ CONFIG_XILINX_AXIEMAC=y CONFIG_XILINX_EMACLITE=y CONFIG_SYS_NS16550=y CONFIG_XILINX_UARTLITE=y +CONFIG_XILINX_SPI=y CONFIG_SYSRESET_GPIO=y CONFIG_SYSRESET_MICROBLAZE=y CONFIG_WDT=y diff --git a/configs/octeontx2_95xx_defconfig b/configs/octeontx2_95xx_defconfig index e37c83742b6..591caa7a0d4 100644 --- a/configs/octeontx2_95xx_defconfig +++ b/configs/octeontx2_95xx_defconfig @@ -86,6 +86,8 @@ CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_DM_ETH=y +CONFIG_NET_OCTEONTX2=y +CONFIG_OCTEONTX_SMI=y CONFIG_PCI=y CONFIG_DM_PCI=y CONFIG_DM_PCI_COMPAT=y diff --git a/configs/octeontx2_96xx_defconfig b/configs/octeontx2_96xx_defconfig index 403ea5121d1..0a8888ad0b3 100644 --- a/configs/octeontx2_96xx_defconfig +++ b/configs/octeontx2_96xx_defconfig @@ -99,6 +99,8 @@ CONFIG_DM_ETH=y CONFIG_E1000=y CONFIG_E1000_SPI=y CONFIG_CMD_E1000=y +CONFIG_NET_OCTEONTX2=y +CONFIG_OCTEONTX_SMI=y CONFIG_NVME=y CONFIG_PCI=y CONFIG_DM_PCI=y diff --git a/configs/octeontx_81xx_defconfig b/configs/octeontx_81xx_defconfig index 78efcf55330..c006a14bdcb 100644 --- a/configs/octeontx_81xx_defconfig +++ b/configs/octeontx_81xx_defconfig @@ -100,6 +100,8 @@ CONFIG_DM_ETH=y CONFIG_E1000=y CONFIG_E1000_SPI=y CONFIG_CMD_E1000=y +CONFIG_NET_OCTEONTX=y +CONFIG_OCTEONTX_SMI=y CONFIG_NVME=y CONFIG_PCI=y CONFIG_DM_PCI=y diff --git a/configs/octeontx_83xx_defconfig b/configs/octeontx_83xx_defconfig index f5b052871ca..86b4bc5190b 100644 --- a/configs/octeontx_83xx_defconfig +++ b/configs/octeontx_83xx_defconfig @@ -97,6 +97,8 @@ CONFIG_DM_ETH=y CONFIG_E1000=y CONFIG_E1000_SPI=y CONFIG_CMD_E1000=y +CONFIG_NET_OCTEONTX=y +CONFIG_OCTEONTX_SMI=y CONFIG_NVME=y CONFIG_PCI=y CONFIG_DM_PCI=y diff --git a/configs/syzygy_hub_defconfig b/configs/syzygy_hub_defconfig index 8f6900661ac..276c476baeb 100644 --- a/configs/syzygy_hub_defconfig +++ b/configs/syzygy_hub_defconfig @@ -9,6 +9,8 @@ CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_SPL=y CONFIG_DEBUG_UART_BASE=0xe0000000 CONFIG_DEBUG_UART_CLOCK=50000000 +CONFIG_ZYNQ_MAC_IN_EEPROM=y +CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0xFA CONFIG_DEFAULT_DEVICE_TREE="zynq-syzygy-hub" CONFIG_DEBUG_UART=y CONFIG_DISTRO_DEFAULTS=y @@ -40,7 +42,6 @@ CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQPL=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_CADENCE=y -CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0xFA CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_PHY_MARVELL=y diff --git a/configs/xilinx_versal_mini_defconfig b/configs/xilinx_versal_mini_defconfig index e72cef9c36d..427268bd588 100644 --- a/configs/xilinx_versal_mini_defconfig +++ b/configs/xilinx_versal_mini_defconfig @@ -7,7 +7,7 @@ CONFIG_NR_DRAM_BANKS=3 CONFIG_ENV_SIZE=0x80 CONFIG_SYS_MALLOC_LEN=0x2000 CONFIG_SYS_MEM_RSVD_FOR_MMU=y -CONFIG_COUNTER_FREQUENCY=2720000 +CONFIG_COUNTER_FREQUENCY=100000000 # CONFIG_PSCI_RESET is not set CONFIG_DEFAULT_DEVICE_TREE="versal-mini" # CONFIG_EXPERT is not set diff --git a/configs/xilinx_versal_mini_emmc0_defconfig b/configs/xilinx_versal_mini_emmc0_defconfig index b5c3ae48843..8837987e35e 100644 --- a/configs/xilinx_versal_mini_emmc0_defconfig +++ b/configs/xilinx_versal_mini_emmc0_defconfig @@ -6,7 +6,7 @@ CONFIG_SYS_TEXT_BASE=0x10000 CONFIG_NR_DRAM_BANKS=1 CONFIG_ENV_SIZE=0x80 CONFIG_SYS_MALLOC_LEN=0x80000 -CONFIG_COUNTER_FREQUENCY=2720000 +CONFIG_COUNTER_FREQUENCY=100000000 # CONFIG_PSCI_RESET is not set CONFIG_DEFAULT_DEVICE_TREE="versal-mini-emmc0" # CONFIG_EXPERT is not set diff --git a/configs/xilinx_versal_mini_emmc1_defconfig b/configs/xilinx_versal_mini_emmc1_defconfig index 871f8cc5c30..b07dc040607 100644 --- a/configs/xilinx_versal_mini_emmc1_defconfig +++ b/configs/xilinx_versal_mini_emmc1_defconfig @@ -6,7 +6,7 @@ CONFIG_SYS_TEXT_BASE=0x10000 CONFIG_NR_DRAM_BANKS=1 CONFIG_ENV_SIZE=0x80 CONFIG_SYS_MALLOC_LEN=0x80000 -CONFIG_COUNTER_FREQUENCY=2720000 +CONFIG_COUNTER_FREQUENCY=100000000 # CONFIG_PSCI_RESET is not set CONFIG_DEFAULT_DEVICE_TREE="versal-mini-emmc1" # CONFIG_EXPERT is not set diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig index 5175571c66d..7291c51c2dc 100644 --- a/configs/xilinx_versal_virt_defconfig +++ b/configs/xilinx_versal_virt_defconfig @@ -4,8 +4,9 @@ CONFIG_ARCH_VERSAL=y CONFIG_SYS_TEXT_BASE=0x8000000 CONFIG_SYS_MALLOC_F_LEN=0x100000 CONFIG_DM_GPIO=y +CONFIG_CMD_FRU=y CONFIG_DEFINE_TCM_OCM_MMAP=y -CONFIG_COUNTER_FREQUENCY=62500000 +CONFIG_COUNTER_FREQUENCY=100000000 CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_FIT_VERBOSE=y @@ -27,6 +28,7 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_MTD=y +CONFIG_CMD_SF_TEST=y CONFIG_CMD_USB=y CONFIG_CMD_TFTPPUT=y CONFIG_CMD_CACHE=y @@ -51,6 +53,7 @@ CONFIG_MISC=y CONFIG_I2C_EEPROM=y CONFIG_SYS_I2C_EEPROM_ADDR=0x0 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW=0x0 +CONFIG_SUPPORT_EMMC_BOOT=y CONFIG_MMC_IO_VOLTAGE=y CONFIG_MMC_UHS_SUPPORT=y CONFIG_MMC_HS400_SUPPORT=y @@ -83,6 +86,7 @@ CONFIG_PL01X_SERIAL=y CONFIG_XILINX_UARTLITE=y CONFIG_SPI=y CONFIG_DM_SPI=y +CONFIG_ZYNQ_SPI=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_DM_USB_GADGET=y diff --git a/configs/xilinx_zynq_virt_defconfig b/configs/xilinx_zynq_virt_defconfig index b1279452970..da84c01b0a1 100644 --- a/configs/xilinx_zynq_virt_defconfig +++ b/configs/xilinx_zynq_virt_defconfig @@ -6,6 +6,8 @@ CONFIG_SYS_SPI_U_BOOT_OFFS=0x100000 CONFIG_DM_GPIO=y CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_SPL=y +CONFIG_CMD_FRU=y +CONFIG_CMD_ZYNQ_AES=y CONFIG_DEFAULT_DEVICE_TREE="zynq-zc706" CONFIG_DISTRO_DEFAULTS=y CONFIG_SYS_CUSTOM_LDSCRIPT=y @@ -40,6 +42,7 @@ CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_MTD=y CONFIG_CMD_NAND_LOCK_UNLOCK=y +CONFIG_CMD_SF_TEST=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TFTPPUT=y @@ -49,7 +52,7 @@ CONFIG_CMD_MTDPARTS=y CONFIG_CMD_MTDPARTS_SPREAD=y CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES=y CONFIG_CMD_UBI=y -CONFIG_OF_LIST="zynq-zc702 zynq-zc706 zynq-zc770-xm010 zynq-zc770-xm011 zynq-zc770-xm011-x16 zynq-zc770-xm012 zynq-zc770-xm013 zynq-cc108 zynq-microzed zynq-minized zynq-picozed zynq-zed zynq-zturn zynq-zybo zynq-zybo-z7 zynq-dlc20-rev1.0" +CONFIG_OF_LIST="zynq-zc702 zynq-zc706 zynq-zc770-xm010 zynq-zc770-xm011 zynq-zc770-xm011-x16 zynq-zc770-xm012 zynq-zc770-xm013 zynq-cc108 zynq-microzed zynq-minized zynq-picozed zynq-zed zynq-zturn zynq-zturn-v5 zynq-zybo zynq-zybo-z7 zynq-dlc20-rev1.0" CONFIG_ENV_OVERWRITE=y CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y @@ -88,6 +91,8 @@ CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_SST=y CONFIG_SPI_FLASH_WINBOND=y CONFIG_PHY_MARVELL=y +CONFIG_PHY_MICREL=y +CONFIG_PHY_MICREL_KSZ90X1=y CONFIG_PHY_REALTEK=y CONFIG_PHY_XILINX=y CONFIG_MII=y diff --git a/configs/xilinx_zynqmp_virt_defconfig b/configs/xilinx_zynqmp_virt_defconfig index 264b662ece1..0c816de707a 100644 --- a/configs/xilinx_zynqmp_virt_defconfig +++ b/configs/xilinx_zynqmp_virt_defconfig @@ -7,6 +7,9 @@ CONFIG_DM_GPIO=y CONFIG_SPL=y CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y +CONFIG_ZYNQ_MAC_IN_EEPROM=y +CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0x20 +CONFIG_CMD_FRU=y CONFIG_ZYNQMP_USB=y CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu100-revC" CONFIG_AHCI=y @@ -19,6 +22,7 @@ CONFIG_USE_PREBOOT=y # CONFIG_DISPLAY_CPUINFO is not set CONFIG_BOARD_EARLY_INIT_F=y CONFIG_BOARD_EARLY_INIT_R=y +CONFIG_SPL_FPGA=y CONFIG_SPL_OS_BOOT=y CONFIG_SPL_RAM_SUPPORT=y CONFIG_SPL_RAM_DEVICE=y @@ -45,10 +49,12 @@ CONFIG_CMD_MTD=y CONFIG_CMD_NAND_LOCK_UNLOCK=y CONFIG_CMD_POWEROFF=y CONFIG_CMD_SDRAM=y +CONFIG_CMD_SF_TEST=y CONFIG_CMD_SPI=y CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y CONFIG_CMD_TIMER=y CONFIG_CMD_EXT4_WRITE=y @@ -58,6 +64,7 @@ CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES=y CONFIG_CMD_UBI=y CONFIG_SPL_OF_CONTROL=y CONFIG_OF_LIST="avnet-ultra96-rev1 zynqmp-a2197-revA zynqmp-e-a2197-00-revA zynqmp-g-a2197-00-revA zynqmp-m-a2197-01-revA zynqmp-m-a2197-02-revA zynqmp-m-a2197-03-revA zynqmp-p-a2197-00-revA zynqmp-zc1232-revA zynqmp-zc1254-revA zynqmp-zc1751-xm015-dc1 zynqmp-zc1751-xm016-dc2 zynqmp-zc1751-xm017-dc3 zynqmp-zc1751-xm018-dc4 zynqmp-zc1751-xm019-dc5 zynqmp-zcu100-revC zynqmp-zcu102-rev1.1 zynqmp-zcu102-rev1.0 zynqmp-zcu102-revA zynqmp-zcu102-revB zynqmp-zcu104-revA zynqmp-zcu104-revC zynqmp-zcu106-revA zynqmp-zcu111-revA zynqmp-zcu1275-revA zynqmp-zcu1275-revB zynqmp-zcu1285-revA zynqmp-zcu208-revA zynqmp-zcu216-revA zynqmp-topic-miamimp-xilinx-xdp-v1r1" +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names interrupt-parent interrupts iommus power-domains" CONFIG_ENV_IS_NOWHERE=y CONFIG_ENV_IS_IN_FAT=y CONFIG_ENV_IS_IN_NAND=y @@ -88,7 +95,6 @@ CONFIG_LED=y CONFIG_LED_GPIO=y CONFIG_MISC=y CONFIG_I2C_EEPROM=y -CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0x20 CONFIG_SYS_I2C_EEPROM_ADDR=0x0 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW=0x0 CONFIG_SUPPORT_EMMC_BOOT=y diff --git a/doc/api/getopt.rst b/doc/api/getopt.rst new file mode 100644 index 00000000000..773f79aeb63 --- /dev/null +++ b/doc/api/getopt.rst @@ -0,0 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright (C) 2020 Sean Anderson <seanga2@gmail.com> + +Option Parsing +============== + +.. kernel-doc:: include/getopt.h + :internal: diff --git a/doc/api/index.rst b/doc/api/index.rst index 787b6778e59..ae4a1b6c634 100644 --- a/doc/api/index.rst +++ b/doc/api/index.rst @@ -8,6 +8,7 @@ U-Boot API documentation dfu efi + getopt linker_lists pinctrl rng diff --git a/doc/board/xilinx/index.rst b/doc/board/xilinx/index.rst index 47f09290af0..2e31fe3f3a4 100644 --- a/doc/board/xilinx/index.rst +++ b/doc/board/xilinx/index.rst @@ -8,3 +8,5 @@ Xilinx xilinx zynq + zynqmp + zynqmp-r5 diff --git a/doc/board/xilinx/xilinx.rst b/doc/board/xilinx/xilinx.rst index f6ea5dbe215..8c9afb482d6 100644 --- a/doc/board/xilinx/xilinx.rst +++ b/doc/board/xilinx/xilinx.rst @@ -10,18 +10,28 @@ kernel. * ata - Documentation/devicetree/bindings/ata/ahci-ceva.txt +* clock + - Documentation/devicetree/bindings/clock/xlnx,zynqmp-clk.txt +* firmware + - Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt +* fpga + - Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.txt * gpio - Documentation/devicetree/bindings/gpio/gpio-xilinx.txt - Documentation/devicetree/bindings/gpio/gpio-zynq.txt * i2c - - Documentation/devicetree/bindings/i2c/i2c-xiic.txt - - Documentation/devicetree/bindings/i2c/i2c-cadence.txt + - Documentation/devicetree/bindings/i2c/xlnx,xps-iic-2.00.a.yaml + - Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml * mmc - - Documentation/devicetree/bindings/mmc/arasan,sdhci.txt + - Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml * net - Documentation/devicetree/bindings/net/macb.txt - Documentation/devicetree/bindings/net/xilinx_axienet.txt - Documentation/devicetree/bindings/net/xilinx_emaclite.txt +* nvmem + - Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt +* power + - Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.txt * serial - Documentation/devicetree/bindings/serial/cdns,uart.txt - Documentation/devicetree/bindings/serial/xlnx,opb-uartlite.txt diff --git a/doc/board/xilinx/zynq.rst b/doc/board/xilinx/zynq.rst index f564434b69c..438912fe42c 100644 --- a/doc/board/xilinx/zynq.rst +++ b/doc/board/xilinx/zynq.rst @@ -83,7 +83,7 @@ Mainline status --------------- - Added basic board configurations support. -- Added zynq u-boot bsp code - arch/arm/cpu/armv7/zynq +- Added zynq u-boot bsp code - arch/arm/mach-zynq - Added zynq boards named - zc70x, zed, microzed, zc770_xm010/xm011/xm012/xm013 - Added zynq drivers: @@ -99,11 +99,6 @@ Mainline status - Added basic FDT support for zynq boards - d-cache support for zynq_gem.c -TODO ----- - -Add FDT support on individual drivers - * [1] http://www.xilinx.com/products/boards-and-kits/EK-Z7-ZC702-G.htm * [2] http://www.xilinx.com/products/boards-and-kits/EK-Z7-ZC706-G.htm * [3] http://zedboard.org/product/zedboard diff --git a/doc/board/xilinx/zynqmp-r5.rst b/doc/board/xilinx/zynqmp-r5.rst new file mode 100644 index 00000000000..2cd368b0308 --- /dev/null +++ b/doc/board/xilinx/zynqmp-r5.rst @@ -0,0 +1,137 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. (C) Copyright 2020 Xilinx, Inc. + +ZYNQMP-R5 +========= + +About this +---------- + +This document describes the information about Xilinx Zynq UltraScale+ MPSOC +U-Boot Cortex R5 support. + +ZynqMP R5 boards +---------------- + +* zynqmp-r5 - U-Boot running on RPU Cortex-R5 + +Building +-------- + +configure and build armv7 toolchain:: + + $ make xilinx_zynqmp_r5_defconfig + $ make + +Notes +^^^^^ + +Output fragment is u-boot. + +Loading +------- + +ZynqMP R5 U-Boot was created for supporting loading OS on RPU. There are two +ways how to start U-Boot on R5. + +Bootgen +^^^^^^^ + +The first way is to use Xilinx FSBL (First stage +bootloader) to load u-boot and start it. The following bif can be used for boot +image generation via Xilinx bootgen utility:: + + + the_ROM_image: + { + [bootloader,destination_cpu=r5-0] fsbl_rpu.elf + [destination_cpu=r5-0]u-boot.elf + } + +Bootgen command for building boot.bin:: + + bootgen -image <bif>.bif -r -w -o i boot.bin + + +U-Boot cpu command +^^^^^^^^^^^^^^^^^^ + +The second way to load U-Boot to Cortex R5 is from U-Boot running on A53 as is +visible from the following log:: + + U-Boot SPL 2020.10-rc4-00090-g801b3d5c5757 (Sep 15 2020 - 14:07:24 +0200) + PMUFW: v1.1 + Loading new PMUFW cfg obj (2024 bytes) + EL Level: EL3 + Multiboot: 0 + Trying to boot from MMC2 + spl: could not initialize mmc. error: -19 + Trying to boot from MMC1 + spl_load_image_fat_os: error reading image u-boot.bin, err - -2 + NOTICE: ATF running on XCZU7EG/EV/silicon v4/RTL5.1 at 0xfffea000 + NOTICE: BL31: v2.2(release):v2.2-614-ged9dc512fb9c + NOTICE: BL31: Built : 09:32:09, Mar 13 2020 + + + U-Boot 2020.10-rc4-00090-g801b3d5c5757 (Sep 15 2020 - 14:07:24 +0200) + + Model: ZynqMP ZCU104 RevC + Board: Xilinx ZynqMP + DRAM: 2 GiB + PMUFW: v1.1 + EL Level: EL2 + Chip ID: zu7e + WDT: Started with servicing (60s timeout) + NAND: 0 MiB + MMC: mmc@ff170000: 0 + Loading Environment from FAT... *** Warning - bad CRC, using default environment + + In: serial + Out: serial + Err: serial + Bootmode: LVL_SHFT_SD_MODE1 + Reset reason: SOFT + Net: + ZYNQ GEM: ff0e0000, mdio bus ff0e0000, phyaddr 12, interface rgmii-id + eth0: ethernet@ff0e0000 + Hit any key to stop autoboot: 0 + ZynqMP> setenv autoload no + ZynqMP> dhcp + BOOTP broadcast 1 + DHCP client bound to address 192.168.0.167 (8 ms) + ZynqMP> tftpboot 20000000 192.168.0.105:u-boot-r5-2.elf + Using ethernet@ff0e0000 device + TFTP from server 192.168.0.105; our IP address is 192.168.0.167 + Filename 'u-boot-r5-2.elf'. + Load address: 0x20000000 + Loading: ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################ + 376 KiB/s + done + Bytes transferred = 2075464 (1fab48 hex) + ZynqMP> setenv autostart no + ZynqMP> bootelf -p 20000000 + ZynqMP> cpu 4 release 10000000 lockstep + Using TCM jump trampoline for address 0x10000000 + R5 lockstep mode + ZynqMP> + +Then on second uart you can see U-Boot up and running on R5:: + + U-Boot 2020.10-rc4-00071-g7045622cc9ba (Sep 16 2020 - 13:38:53 +0200) + + Model: Xilinx ZynqMP R5 + DRAM: 512 MiB + MMC: + In: serial@ff010000 + Out: serial@ff010000 + Err: serial@ff010000 + Net: No ethernet found. + ZynqMP r5> + +Please make sure MIO pins for uart are properly configured to see output. diff --git a/doc/board/xilinx/zynqmp.rst b/doc/board/xilinx/zynqmp.rst new file mode 100644 index 00000000000..a035cff1a5b --- /dev/null +++ b/doc/board/xilinx/zynqmp.rst @@ -0,0 +1,115 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. (C) Copyright 2020 Xilinx, Inc. + +ZYNQMP +====== + +About this +---------- + +This document describes the information about Xilinx Zynq UltraScale+ MPSOC +U-Boot support. Core support is available in arch/arm/mach-zynqmp folder. + +ZynqMP boards +------------- + +* zcu100 (ultra96 v1), zcu102, zcu104, zcu106 - Evaluation boards +* zc1232 - Characterization boards +* zcu111, zcu208, zcu216 - RFSOC evaluation boards +* zcu1254, zcu1275, zcu1285 - RFSOC characterization boards +* a2197 - System Controller on Versal boards +* mini - Mini U-Boot running out of OCM +* zc1751 - Characterization Processor boards + - zc1751-xm015-dc1 + - zc1751-xm016-dc2 + - zc1751-xm017-dc3 + - zc1751-xm018-dc4 + - zc1751-xm019-dc5 + +Building +-------- + +Configure and build for zcu102 board:: + + $ source arm64 toolchain + $ export DEVICE_TREE=zynqmp-zcu102-revA + $ make xilinx_zynqmp_virt_defconfig + $ make + +U-Boot SPL flow +--------------- + +For getting U-Boot SPL flow up and running it is necessary to do some additional +steps because booting device requires external images which are not the part of +U-Boot repository. + +PMU firmware +^^^^^^^^^^^^ +The Platform Management Unit (PMU) RAM can be loaded with a firmware (PMU +Firmware) at run-time and can be used to extend or customize the functionality +of PMU. The PMU firmware is the part of boot image (boot.bin) and it is +automatically loaded by BootROM. boot.bin can be directly generated by mkimage +tool as the part of make. If you want to create boot.bin with PMU Firmware +include please point CONFIG_PMUFW_INIT_FILE to PMU firmware binary. For example::: + + CONFIG_PMUFW_INIT_FILE="<path>/pmu.bin" + +If you see below message you need to load PMU Firmware:: + + PMUFW is not found - Please load it! + +The second external blob is PMU Configuration object which is object which is +passed from U-Boot SPL to PMU Firmware for initial system configuration. PMU +configuration object is the part of U-Boot SPL image. For pointing to this +object please use CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE symbol. For example::: + + CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE="<path>/pmu_obj.bin" + + +PMU configuration object +^^^^^^^^^^^^^^^^^^^^^^^^ + +Object can be obtain in several ways. The easiest way is to take pm_cfg_obj.c +from SDK/Vitis design and build it::: + + $ git clone https://github.com/Xilinx/embeddedsw.git + $ export EMBEDDED_SW=$PWD/embeddedsw + $ gcc -c pm_cfg_obj.c -I ${EMBEDDED_SW}/lib/bsp/standalone/src/common/ -I ${EMBEDDED_SW}/lib/sw_services/xilpm/src/zynqmp/client/common/ + $ objcopy -O binary pm_cfg_obj.o pmu_obj.bin + +The second way is to use tools/zynqmp_pm_cfg_obj_convert.py. For more +information about this tool please run it with -h parameter. + +The third way is to extract it from Xilinx FSBL elf file. Object is starting at +XPm_ConfigObject symbol. + + +Arm Trusted Firmware (ATF) +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +U-Boot itself can run from EL3 to EL1. Without ATF U-Boot runs in EL3. Boot flow +is U-Boot SPL->U-Boot in EL3. When ATF is used U-Boot normally runs in EL2. Boot +flow is U-Boot SPL->ATF->U-Boot in EL2. As the part of build process u-boot.itb +is generated. When BL31 shell variable is present u-boot.itb is generated with +ATF included. You can point to it by::: + + $ export BL31=<path>/bl31.bin + +Flashing +-------- + +SD Card +^^^^^^^ + +To write an image that boots from a SD card first create a FAT32 partition +and a FAT32 filesystem on the SD card:: + + sudo fdisk /dev/sdx + sudo mkfs.vfat -F 32 /dev/sdx1 + +Mount the SD card and copy the SPL and U-Boot to the root directory of the +SD card:: + + sudo mount -t vfat /dev/sdx1 /mnt + sudo cp spl/boot.bin /mnt + sudo cp u-boot.itb /mnt diff --git a/doc/develop/logging.rst b/doc/develop/logging.rst index 528280c3e8d..7fdd1132efe 100644 --- a/doc/develop/logging.rst +++ b/doc/develop/logging.rst @@ -21,26 +21,13 @@ is visible from the basic console output. U-Boot's logging feature aims to satisfy this goal for both users and developers. - Logging levels -------------- -There are a number logging levels available, in increasing order of verbosity: - -* LOGL_EMERG - Printed before U-Boot halts -* LOGL_ALERT - Indicates action must be taken immediate or U-Boot will crash -* LOGL_CRIT - Indicates a critical error that will cause boot failure -* LOGL_ERR - Indicates an error that may cause boot failure -* LOGL_WARNING - Warning about an unexpected condition -* LOGL_NOTE - Important information about progress -* LOGL_INFO - Information about normal boot progress -* LOGL_DEBUG - Debug information (useful for debugging a driver or subsystem) -* LOGL_DEBUG_CONTENT - Debug message showing full message content -* LOGL_DEBUG_IO - Debug message showing hardware I/O access +There are a number logging levels available. -To continue a log message in a separate call of function log() use - -* LOGL_CONT - Use same log level as in previous call +.. kernel-doc:: include/log.h + :identifiers: log_level_t Logging category ---------------- @@ -49,19 +36,8 @@ Logging can come from a wide variety of places within U-Boot. Each log message has a category which is intended to allow messages to be filtered according to their source. -The following main categories are defined: - -* LOGC_NONE - Unknown category (e.g. a debug() statement) -* UCLASS\_... - Related to a particular uclass (e.g. UCLASS_USB) -* LOGC_ARCH - Related to architecture-specific code -* LOGC_BOARD - Related to board-specific code -* LOGC_CORE - Related to core driver-model support -* LOGC_DT - Related to device tree control -* LOGC_EFI - Related to EFI implementation - -To continue a log message in a separate call of function log() use - -* LOGC_CONT - Use same category as in previous call +.. kernel-doc:: include/log.h + :identifiers: log_category_t Enabling logging ---------------- @@ -78,7 +54,6 @@ If CONFIG_LOG is not set, then no logging will be available. The above have SPL and TPL versions also, e.g. CONFIG_SPL_LOG_MAX_LEVEL and CONFIG_TPL_LOG_MAX_LEVEL. - Temporary logging within a single file -------------------------------------- @@ -89,12 +64,52 @@ Sometimes it is useful to turn on logging just in one file. You can use this #define LOG_DEBUG to enable building in of all logging statements in a single file. Put it at -the top of the file, before any #includes. This overrides any log-level setting -in U-Boot, including CONFIG_LOG_DEFAULT_LEVEL, but just for that file. +the top of the file, before any #includes. + +To actually get U-Boot to output this you need to also set the default logging +level - e.g. set CONFIG_LOG_DEFAULT_LEVEL to 7 (:c:type:`LOGL_DEBUG`) or more. +Otherwise debug output is suppressed and will not be generated. + +Using DEBUG +----------- + +U-Boot has traditionally used a #define called DEBUG to enable debugging on a +file-by-file basis. The debug() macro compiles to a printf() statement if +DEBUG is enabled, and an empty statement if not. + +With logging enabled, debug() statements are interpreted as logging output +with a level of LOGL_DEBUG and a category of LOGC_NONE. + +The logging facilities are intended to replace DEBUG, but if DEBUG is defined +at the top of a file, then it takes precedence. This means that debug() +statements will result in output to the console and this output will not be +logged. + +Logging statements +------------------ + +The main logging function is: +.. code-block:: c + + log(category, level, format_string, ...) + +Also debug() and error() will generate log records - these use LOG_CATEGORY +as the category, so you should #define this right at the top of the source +file to ensure the category is correct. + +You can also define CONFIG_LOG_ERROR_RETURN to enable the log_ret() macro. This +can be used whenever your function returns an error value: + +.. code-block:: c + + return log_ret(uclass_first_device(UCLASS_MMC, &dev)); + +This will write a log record when an error code is detected (a value < 0). This +can make it easier to trace errors that are generated deep in the call stack. Convenience functions ---------------------- +~~~~~~~~~~~~~~~~~~~~~ A number of convenience functions are available to shorten the code needed for logging: @@ -122,36 +137,6 @@ or Remember that all uclasses IDs are log categories too. - -Log command ------------ - -The 'log' command provides access to several features: - -* level - access the default log level -* format - access the console log format -* rec - output a log record -* test - run tests - -Type 'help log' for details. - - -Using DEBUG ------------ - -U-Boot has traditionally used a #define called DEBUG to enable debugging on a -file-by-file basis. The debug() macro compiles to a printf() statement if -DEBUG is enabled, and an empty statement if not. - -With logging enabled, debug() statements are interpreted as logging output -with a level of LOGL_DEBUG and a category of LOGC_NONE. - -The logging facilities are intended to replace DEBUG, but if DEBUG is defined -at the top of a file, then it takes precedence. This means that debug() -statements will result in output to the console and this output will not be -logged. - - Logging destinations -------------------- @@ -165,60 +150,84 @@ enabled or disabled independently: The syslog driver sends the value of environmental variable 'log_hostname' as HOSTNAME if available. - -Log format ----------- - -You can control the log format using the 'log format' command. The basic -format is:: - - LEVEL.category,file.c:123-func() message - -In the above, file.c:123 is the filename where the log record was generated and -func() is the function name. By default ('log format default') only the -function name and message are displayed on the console. You can control which -fields are present, but not the field order. - - Filters ------- -Filters are attached to log drivers to control what those drivers emit. Only -records that pass through the filter make it to the driver. +Filters are attached to log drivers to control what those drivers emit. FIlters +can either allow or deny a log message when they match it. Only records which +are allowed by a filter make it to the driver. Filters can be based on several criteria: -* maximum log level +* minimum or maximum log level * in a set of categories * in a set of files If no filters are attached to a driver then a default filter is used, which limits output to records with a level less than CONFIG_MAX_LOG_LEVEL. +Log command +----------- -Logging statements ------------------- +The 'log' command provides access to several features: -The main logging function is: +* level - list log levels or set the default log level +* categories - list log categories +* drivers - list log drivers +* filter-list - list filters +* filter-add - add a new filter +* filter-remove - remove filters +* format - access the console log format +* rec - output a log record -.. code-block:: c +Type 'help log' for details. - log(category, level, format_string, ...) +Log format +~~~~~~~~~~ -Also debug() and error() will generate log records - these use LOG_CATEGORY -as the category, so you should #define this right at the top of the source -file to ensure the category is correct. +You can control the log format using the 'log format' command. The basic +format is:: -You can also define CONFIG_LOG_ERROR_RETURN to enable the log_ret() macro. This -can be used whenever your function returns an error value: + LEVEL.category,file.c:123-func() message -.. code-block:: c +In the above, file.c:123 is the filename where the log record was generated and +func() is the function name. By default ('log format default') only the message +is displayed on the console. You can control which fields are present, but not +the field order. - return log_ret(uclass_first_device(UCLASS_MMC, &dev)); +Adding Filters +~~~~~~~~~~~~~~ -This will write a log record when an error code is detected (a value < 0). This -can make it easier to trace errors that are generated deep in the call stack. +To add new filters at runtime, use the 'log filter-add' command. For example, to +suppress messages from the SPI and MMC subsystems, run:: + + log filter-add -D -c spi -c mmc +You will also need to add another filter to allow other messages (because the +default filter no longer applies):: + + log filter-add -A -l info + +Log levels may be either symbolic names (like above) or numbers. For example, to +disable all debug and above (log level 7) messages from ``drivers/core/lists.c`` +and ``drivers/core/ofnode.c``, run:: + + log filter-add -D -f drivers/core/lists.c,drivers/core/ofnode.c -L 7 + +To view active filters, use the 'log filter-list' command. Some example output +is:: + + => log filter-list + num policy level categories files + 2 deny >= DEBUG drivers/core/lists.c,drivers/core/ofnode.c + 0 deny <= IO spi + mmc + 1 allow <= INFO + +Note that filters are processed in-order from top to bottom, not in the order of +their filter number. Filters are added to the top of the list if they deny when +they match, and to the bottom if they allow when they match. For more +information, consult the usage of the 'log' command, by running 'help log'. Code size --------- @@ -235,13 +244,12 @@ The last option turns every debug() statement into a logging call, which bloats the code hugely. The advantage is that it is then possible to enable all logging within U-Boot. - To Do ----- There are lots of useful additions that could be made. None of the below is -implemented! If you do one, please add a test in test/py/tests/test_log.py - +implemented! If you do one, please add a test in test/log/log_test.c +log filter-add -D -f drivers/core/lists.c,drivers/core/ofnode.c -l 6 Convenience functions to support setting the category: * log_arch(level, format_string, ...) - category LOGC_ARCH @@ -262,25 +270,15 @@ Convert error() statements in the code to log() statements Figure out what to do with BUG(), BUG_ON() and warn_non_spl() -Figure out what to do with assert() - Add a way to browse log records Add a way to record log records for browsing using an external tool -Add commands to add and remove filters - Add commands to add and remove log devices Allow sharing of printf format strings in log records to reduce storage size for large numbers of log records -Add a command-line option to sandbox to set the default logging level - -Convert core driver model code to use logging - -Convert uclasses to use logging with the correct category - Consider making log() calls emit an automatic newline, perhaps with a logn() function to avoid that @@ -291,9 +289,9 @@ number dropped due to them being generated before the log system was ready. Add a printf() format string pragma so that log statements are checked properly -Enhance the log console driver to show level / category / file / line -information - -Add a command to add new log records and delete existing records. +Add a command to delete existing log records. -Provide additional log() functions - e.g. logc() to specify the category +Logging API +----------- +.. kernel-doc:: include/log.h + :internal: diff --git a/doc/uImage.FIT/howto.txt b/doc/uImage.FIT/howto.txt index 8592719685e..019dda24a08 100644 --- a/doc/uImage.FIT/howto.txt +++ b/doc/uImage.FIT/howto.txt @@ -66,6 +66,90 @@ can point to a script which generates this image source file during the build process. It gets passed a list of device tree files (taken from the CONFIG_OF_LIST symbol). +The SPL also records to a DT all additional images (called loadables) which are +loaded. The information about loadables locations is passed via the DT node with +fit-images name. + +Loadables Example +----------------- +Consider the following case for an ARM64 platform where U-Boot runs in EL2 +started by ATF where SPL is loading U-Boot (as loadables) and ATF (as firmware). + +/dts-v1/; + +/ { + description = "Configuration to load ATF before U-Boot"; + + images { + uboot { + description = "U-Boot (64-bit)"; + data = /incbin/("u-boot-nodtb.bin"); + type = "firmware"; + os = "u-boot"; + arch = "arm64"; + compression = "none"; + load = <0x8 0x8000000>; + entry = <0x8 0x8000000>; + hash { + algo = "md5"; + }; + }; + atf { + description = "ARM Trusted Firmware"; + data = /incbin/("bl31.bin"); + type = "firmware"; + os = "arm-trusted-firmware"; + arch = "arm64"; + compression = "none"; + load = <0xfffea000>; + entry = <0xfffea000>; + hash { + algo = "md5"; + }; + }; + fdt_1 { + description = "zynqmp-zcu102-revA"; + data = /incbin/("arch/arm/dts/zynqmp-zcu102-revA.dtb"); + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + load = <0x100000>; + hash { + algo = "md5"; + }; + }; + }; + configurations { + default = "config_1"; + + config_1 { + description = "zynqmp-zcu102-revA"; + firmware = "atf"; + loadables = "uboot"; + fdt = "fdt_1"; + }; + }; +}; + +In this case the SPL records via fit-images DT node the information about +loadables U-Boot image. + +ZynqMP> fdt addr $fdtcontroladdr +ZynqMP> fdt print /fit-images +fit-images { + uboot { + os = "u-boot"; + type = "firmware"; + size = <0x001017c8>; + entry = <0x00000008 0x08000000>; + load = <0x00000008 0x08000000>; + }; +}; + +As you can see entry and load properties are 64bit wide to support loading +images above 4GB (in past entry and load properties where just 32bit). + + Example 1 -- old-style (non-FDT) kernel booting ----------------------------------------------- diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 7d1b89514c7..a68076bf351 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -476,6 +476,28 @@ ofnode ofnode_get_chosen_node(const char *name) return ofnode_path(prop); } +const void *ofnode_read_aliases_prop(const char *propname, int *sizep) +{ + ofnode node; + + node = ofnode_path("/aliases"); + + return ofnode_read_prop(node, propname, sizep); +} + +ofnode ofnode_get_aliases_node(const char *name) +{ + const char *prop; + + prop = ofnode_read_aliases_prop(name, NULL); + if (!prop) + return ofnode_null(); + + debug("%s: node_path: %s\n", __func__, prop); + + return ofnode_path(prop); +} + int ofnode_get_child_count(ofnode parent) { ofnode child; diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index 7583f24a200..d4dc856bafa 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -165,6 +165,14 @@ int __maybe_unused xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2, */ u32 regs[] = {api_id, arg0, arg1, arg2, arg3}; + if (api_id == PM_FPGA_LOAD) { + /* Swap addr_hi/low because of incompatibility */ + u32 temp = regs[1]; + + regs[1] = regs[2]; + regs[2] = temp; + } + ipi_req(regs, PAYLOAD_ARG_CNT, ret_payload, PAYLOAD_ARG_CNT); #else return -EPERM; diff --git a/drivers/mailbox/zynqmp-ipi.c b/drivers/mailbox/zynqmp-ipi.c index 9483ed9cefc..847a03648b8 100644 --- a/drivers/mailbox/zynqmp-ipi.c +++ b/drivers/mailbox/zynqmp-ipi.c @@ -56,7 +56,7 @@ static int zynqmp_ipi_send(struct mbox_chan *chan, const void *data) /* Wait until observation bit is cleared */ ret = wait_for_bit_le32(&ipi_int_apu->obs, IPI_BIT_MASK_PMU0, false, - 100, false); + 1000, false); debug("%s, send %ld bytes\n", __func__, msg->len); return ret; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b67e906a76b..29432ae7eb4 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -376,13 +376,6 @@ config SPL_I2C_EEPROM This option is an SPL-variant of the I2C_EEPROM option. See the help of I2C_EEPROM for details. -config ZYNQ_GEM_I2C_MAC_OFFSET - hex "Set the I2C MAC offset" - default 0x0 - depends on DM_I2C - help - Set the MAC offset for i2C. - if I2C_EEPROM config SYS_I2C_EEPROM_ADDR diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index d549a264d73..06289343124 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -812,7 +812,8 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, cfg->host_caps &= ~MMC_MODE_HS_52MHz; } - if (!(cfg->voltages & MMC_VDD_165_195)) + if (!(cfg->voltages & MMC_VDD_165_195) || + (host->quirks & SDHCI_QUIRK_NO_1_8_V)) caps_1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50); diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 775c17baac5..147ecc0d708 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -19,6 +19,20 @@ #include <sdhci.h> #include <zynqmp_tap_delay.h> +#define SDHCI_ARASAN_ITAPDLY_REGISTER 0xF0F8 +#define SDHCI_ARASAN_OTAPDLY_REGISTER 0xF0FC +#define SDHCI_ITAPDLY_CHGWIN 0x200 +#define SDHCI_ITAPDLY_ENABLE 0x100 +#define SDHCI_OTAPDLY_ENABLE 0x40 + +#define SDHCI_TUNING_LOOP_COUNT 40 +#define MMC_BANK2 0x2 + +struct arasan_sdhci_clk_data { + int clk_phase_in[MMC_TIMING_MMC_HS400 + 1]; + int clk_phase_out[MMC_TIMING_MMC_HS400 + 1]; +}; + struct arasan_sdhci_plat { struct mmc_config cfg; struct mmc mmc; @@ -26,29 +40,35 @@ struct arasan_sdhci_plat { struct arasan_sdhci_priv { struct sdhci_host *host; + struct arasan_sdhci_clk_data clk_data; u8 deviceid; u8 bank; + u8 no_1p8; }; -#if defined(CONFIG_ARCH_ZYNQMP) -#define MMC_HS200_BUS_SPEED 5 +#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) +/* Default settings for ZynqMP Clock Phases */ +const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63, 0, 0, 183, 54, 0, 0}; +const u32 zynqmp_oclk_phases[] = {0, 72, 60, 0, 60, 72, 135, 48, 72, 135, 0}; + +/* Default settings for Versal Clock Phases */ +const u32 versal_iclk_phases[] = {0, 132, 132, 0, 132, 0, 0, 162, 90, 0, 0}; +const u32 versal_oclk_phases[] = {0, 60, 48, 0, 48, 72, 90, 36, 60, 90, 0}; static const u8 mode2timing[] = { - [MMC_LEGACY] = UHS_SDR12_BUS_SPEED, - [MMC_HS] = HIGH_SPEED_BUS_SPEED, - [SD_HS] = HIGH_SPEED_BUS_SPEED, - [MMC_HS_52] = HIGH_SPEED_BUS_SPEED, - [MMC_DDR_52] = HIGH_SPEED_BUS_SPEED, - [UHS_SDR12] = UHS_SDR12_BUS_SPEED, - [UHS_SDR25] = UHS_SDR25_BUS_SPEED, - [UHS_SDR50] = UHS_SDR50_BUS_SPEED, - [UHS_DDR50] = UHS_DDR50_BUS_SPEED, - [UHS_SDR104] = UHS_SDR104_BUS_SPEED, - [MMC_HS_200] = MMC_HS200_BUS_SPEED, + [MMC_LEGACY] = MMC_TIMING_LEGACY, + [MMC_HS] = MMC_TIMING_MMC_HS, + [SD_HS] = MMC_TIMING_SD_HS, + [MMC_HS_52] = MMC_TIMING_UHS_SDR50, + [MMC_DDR_52] = MMC_TIMING_UHS_DDR50, + [UHS_SDR12] = MMC_TIMING_UHS_SDR12, + [UHS_SDR25] = MMC_TIMING_UHS_SDR25, + [UHS_SDR50] = MMC_TIMING_UHS_SDR50, + [UHS_DDR50] = MMC_TIMING_UHS_DDR50, + [UHS_SDR104] = MMC_TIMING_UHS_SDR104, + [MMC_HS_200] = MMC_TIMING_MMC_HS200, }; -#define SDHCI_TUNING_LOOP_COUNT 40 - static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid) { u16 clk; @@ -156,17 +176,352 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) return 0; } +/** + * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Output Clock Tap Delays + * + * Set the SD Output Clock Tap Delays for Output path + * + * @host: Pointer to the sdhci_host structure. + * @degrees: The clock phase shift between 0 - 359. + * Return: 0 on success and error value on error + */ +static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host, + int degrees) +{ + struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev); + struct mmc *mmc = (struct mmc *)host->mmc; + u8 tap_delay, tap_max = 0; + int ret; + int timing = mode2timing[mmc->selected_mode]; + + /* + * This is applicable for SDHCI_SPEC_300 and above + * ZynqMP does not set phase for <=25MHz clock. + * If degrees is zero, no need to do anything. + */ + if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 || + timing == MMC_TIMING_LEGACY || + timing == MMC_TIMING_UHS_SDR12 || !degrees) + return 0; + + switch (timing) { + case MMC_TIMING_MMC_HS: + case MMC_TIMING_SD_HS: + case MMC_TIMING_UHS_SDR25: + case MMC_TIMING_UHS_DDR50: + case MMC_TIMING_MMC_DDR52: + /* For 50MHz clock, 30 Taps are available */ + tap_max = 30; + break; + case MMC_TIMING_UHS_SDR50: + /* For 100MHz clock, 15 Taps are available */ + tap_max = 15; + break; + case MMC_TIMING_UHS_SDR104: + case MMC_TIMING_MMC_HS200: + /* For 200MHz clock, 8 Taps are available */ + tap_max = 8; + default: + break; + } + + tap_delay = (degrees * tap_max) / 360; + + arasan_zynqmp_set_tapdelay(priv->deviceid, 0, tap_delay); + + return ret; +} + +/** + * sdhci_zynqmp_sampleclk_set_phase - Set the SD Input Clock Tap Delays + * + * Set the SD Input Clock Tap Delays for Input path + * + * @host: Pointer to the sdhci_host structure. + * @degrees: The clock phase shift between 0 - 359. + * Return: 0 on success and error value on error + */ +static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host, + int degrees) +{ + struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev); + struct mmc *mmc = (struct mmc *)host->mmc; + u8 tap_delay, tap_max = 0; + int ret; + int timing = mode2timing[mmc->selected_mode]; + + /* + * This is applicable for SDHCI_SPEC_300 and above + * ZynqMP does not set phase for <=25MHz clock. + * If degrees is zero, no need to do anything. + */ + if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 || + timing == MMC_TIMING_LEGACY || + timing == MMC_TIMING_UHS_SDR12 || !degrees) + return 0; + + switch (timing) { + case MMC_TIMING_MMC_HS: + case MMC_TIMING_SD_HS: + case MMC_TIMING_UHS_SDR25: + case MMC_TIMING_UHS_DDR50: + case MMC_TIMING_MMC_DDR52: + /* For 50MHz clock, 120 Taps are available */ + tap_max = 120; + break; + case MMC_TIMING_UHS_SDR50: + /* For 100MHz clock, 60 Taps are available */ + tap_max = 60; + break; + case MMC_TIMING_UHS_SDR104: + case MMC_TIMING_MMC_HS200: + /* For 200MHz clock, 30 Taps are available */ + tap_max = 30; + default: + break; + } + + tap_delay = (degrees * tap_max) / 360; + + arasan_zynqmp_set_tapdelay(priv->deviceid, tap_delay, 0); + + return ret; +} + +/** + * sdhci_versal_sdcardclk_set_phase - Set the SD Output Clock Tap Delays + * + * Set the SD Output Clock Tap Delays for Output path + * + * @host: Pointer to the sdhci_host structure. + * @degrees The clock phase shift between 0 - 359. + * Return: 0 on success and error value on error + */ +static int sdhci_versal_sdcardclk_set_phase(struct sdhci_host *host, + int degrees) +{ + struct mmc *mmc = (struct mmc *)host->mmc; + u8 tap_delay, tap_max = 0; + int ret; + int timing = mode2timing[mmc->selected_mode]; + + /* + * This is applicable for SDHCI_SPEC_300 and above + * Versal does not set phase for <=25MHz clock. + * If degrees is zero, no need to do anything. + */ + if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 || + timing == MMC_TIMING_LEGACY || + timing == MMC_TIMING_UHS_SDR12 || !degrees) + return 0; + + switch (timing) { + case MMC_TIMING_MMC_HS: + case MMC_TIMING_SD_HS: + case MMC_TIMING_UHS_SDR25: + case MMC_TIMING_UHS_DDR50: + case MMC_TIMING_MMC_DDR52: + /* For 50MHz clock, 30 Taps are available */ + tap_max = 30; + break; + case MMC_TIMING_UHS_SDR50: + /* For 100MHz clock, 15 Taps are available */ + tap_max = 15; + break; + case MMC_TIMING_UHS_SDR104: + case MMC_TIMING_MMC_HS200: + /* For 200MHz clock, 8 Taps are available */ + tap_max = 8; + default: + break; + } + + tap_delay = (degrees * tap_max) / 360; + + /* Set the Clock Phase */ + if (tap_delay) { + u32 regval; + + regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER); + regval |= SDHCI_OTAPDLY_ENABLE; + sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER); + regval |= tap_delay; + sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER); + } + + return ret; +} + +/** + * sdhci_versal_sampleclk_set_phase - Set the SD Input Clock Tap Delays + * + * Set the SD Input Clock Tap Delays for Input path + * + * @host: Pointer to the sdhci_host structure. + * @degrees The clock phase shift between 0 - 359. + * Return: 0 on success and error value on error + */ +static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host, + int degrees) +{ + struct mmc *mmc = (struct mmc *)host->mmc; + u8 tap_delay, tap_max = 0; + int ret; + int timing = mode2timing[mmc->selected_mode]; + + /* + * This is applicable for SDHCI_SPEC_300 and above + * Versal does not set phase for <=25MHz clock. + * If degrees is zero, no need to do anything. + */ + if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 || + timing == MMC_TIMING_LEGACY || + timing == MMC_TIMING_UHS_SDR12 || !degrees) + return 0; + + switch (timing) { + case MMC_TIMING_MMC_HS: + case MMC_TIMING_SD_HS: + case MMC_TIMING_UHS_SDR25: + case MMC_TIMING_UHS_DDR50: + case MMC_TIMING_MMC_DDR52: + /* For 50MHz clock, 120 Taps are available */ + tap_max = 120; + break; + case MMC_TIMING_UHS_SDR50: + /* For 100MHz clock, 60 Taps are available */ + tap_max = 60; + break; + case MMC_TIMING_UHS_SDR104: + case MMC_TIMING_MMC_HS200: + /* For 200MHz clock, 30 Taps are available */ + tap_max = 30; + default: + break; + } + + tap_delay = (degrees * tap_max) / 360; + + /* Set the Clock Phase */ + if (tap_delay) { + u32 regval; + + regval = sdhci_readl(host, SDHCI_ARASAN_ITAPDLY_REGISTER); + regval |= SDHCI_ITAPDLY_CHGWIN; + sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); + regval |= SDHCI_ITAPDLY_ENABLE; + sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); + regval |= tap_delay; + sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); + regval &= ~SDHCI_ITAPDLY_CHGWIN; + sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); + } + + return ret; +} + static void arasan_sdhci_set_tapdelay(struct sdhci_host *host) { struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev); + struct arasan_sdhci_clk_data *clk_data = &priv->clk_data; struct mmc *mmc = (struct mmc *)host->mmc; - u8 uhsmode; + struct udevice *dev = mmc->dev; + u8 timing = mode2timing[mmc->selected_mode]; + u32 iclk_phase = clk_data->clk_phase_in[timing]; + u32 oclk_phase = clk_data->clk_phase_out[timing]; + + dev_dbg(dev, "%s, host:%s, mode:%d\n", __func__, host->name, timing); + + if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) && + device_is_compatible(dev, "xlnx,zynqmp-8.9a")) { + sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase); + sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase); + } else if (IS_ENABLED(CONFIG_ARCH_VERSAL) && + device_is_compatible(dev, "xlnx,versal-8.9a")) { + sdhci_versal_sampleclk_set_phase(host, iclk_phase); + sdhci_versal_sdcardclk_set_phase(host, oclk_phase); + } +} - uhsmode = mode2timing[mmc->selected_mode]; +static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing, + const char *prop) +{ + struct arasan_sdhci_priv *priv = dev_get_priv(dev); + struct arasan_sdhci_clk_data *clk_data = &priv->clk_data; + u32 clk_phase[2] = {0}; + + /* + * Read Tap Delay values from DT, if the DT does not contain the + * Tap Values then use the pre-defined values + */ + if (dev_read_u32_array(dev, prop, &clk_phase[0], 2)) { + dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n", + prop, clk_data->clk_phase_in[timing], + clk_data->clk_phase_out[timing]); + return; + } - if (uhsmode >= UHS_SDR25_BUS_SPEED) - arasan_zynqmp_set_tapdelay(priv->deviceid, uhsmode, - priv->bank); + /* The values read are Input and Output Clock Delays in order */ + clk_data->clk_phase_in[timing] = clk_phase[0]; + clk_data->clk_phase_out[timing] = clk_phase[1]; +} + +/** + * arasan_dt_parse_clk_phases - Read Tap Delay values from DT + * + * Called at initialization to parse the values of Tap Delays. + * + * @dev: Pointer to our struct udevice. + */ +static void arasan_dt_parse_clk_phases(struct udevice *dev) +{ + struct arasan_sdhci_priv *priv = dev_get_priv(dev); + struct arasan_sdhci_clk_data *clk_data = &priv->clk_data; + int i; + + if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) && + device_is_compatible(dev, "xlnx,zynqmp-8.9a")) { + for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) { + clk_data->clk_phase_in[i] = zynqmp_iclk_phases[i]; + clk_data->clk_phase_out[i] = zynqmp_oclk_phases[i]; + } + + if (priv->bank == MMC_BANK2) { + clk_data->clk_phase_out[MMC_TIMING_UHS_SDR104] = 90; + clk_data->clk_phase_out[MMC_TIMING_MMC_HS200] = 90; + } + } + + if (IS_ENABLED(CONFIG_ARCH_VERSAL) && + device_is_compatible(dev, "xlnx,versal-8.9a")) { + for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) { + clk_data->clk_phase_in[i] = versal_iclk_phases[i]; + clk_data->clk_phase_out[i] = versal_oclk_phases[i]; + } + } + + arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY, + "clk-phase-legacy"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS, + "clk-phase-mmc-hs"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_SD_HS, + "clk-phase-sd-hs"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR12, + "clk-phase-uhs-sdr12"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR25, + "clk-phase-uhs-sdr25"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR50, + "clk-phase-uhs-sdr50"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR104, + "clk-phase-uhs-sdr104"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_DDR50, + "clk-phase-uhs-ddr50"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_DDR52, + "clk-phase-mmc-ddr52"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS200, + "clk-phase-mmc-hs200"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS400, + "clk-phase-mmc-hs400"); } static void arasan_sdhci_set_control_reg(struct sdhci_host *host) @@ -184,12 +539,10 @@ static void arasan_sdhci_set_control_reg(struct sdhci_host *host) } if (mmc->selected_mode > SD_HS && - mmc->selected_mode <= UHS_DDR50) + mmc->selected_mode <= MMC_HS_200) sdhci_set_uhs_timing(host); } -#endif -#if defined(CONFIG_ARCH_ZYNQMP) const struct sdhci_ops arasan_ops = { .platform_execute_tuning = &arasan_sdhci_execute_tuning, .set_delay = &arasan_sdhci_set_tapdelay, @@ -236,6 +589,9 @@ static int arasan_sdhci_probe(struct udevice *dev) host->quirks |= SDHCI_QUIRK_BROKEN_HISPD_MODE; #endif + if (priv->no_1p8) + host->quirks |= SDHCI_QUIRK_NO_1_8_V; + plat->cfg.f_max = CONFIG_ZYNQ_SDHCI_MAX_FREQ; ret = mmc_of_parse(dev, &plat->cfg); @@ -267,8 +623,9 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) priv->host->name = dev->name; -#if defined(CONFIG_ARCH_ZYNQMP) +#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) priv->host->ops = &arasan_ops; + arasan_dt_parse_clk_phases(dev); #endif priv->host->ioaddr = (void *)dev_read_addr(dev); @@ -277,6 +634,7 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) priv->deviceid = dev_read_u32_default(dev, "xlnx,device_id", -1); priv->bank = dev_read_u32_default(dev, "xlnx,mio-bank", 0); + priv->no_1p8 = dev_read_bool(dev, "no-1-8-v"); return 0; } diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index cd7e598aa8a..3cf3b14f05b 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -195,6 +195,9 @@ endif config NAND_PXA3XX bool "Support for NAND on PXA3xx and Armada 370/XP/38x" select SYS_NAND_SELF_INIT + select DM_MTD + select REGMAP + select SYSCON imply CMD_NAND help This enables the driver for the NAND flash device found on diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c index 5fb3081c839..361a9e32935 100644 --- a/drivers/mtd/nand/raw/pxa3xx_nand.c +++ b/drivers/mtd/nand/raw/pxa3xx_nand.c @@ -22,6 +22,10 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/rawnand.h> #include <linux/types.h> +#include <syscon.h> +#include <regmap.h> +#include <dm/uclass.h> +#include <dm/read.h> #include "pxa3xx_nand.h" @@ -117,6 +121,10 @@ DECLARE_GLOBAL_DATA_PTR; #define EXT_CMD_TYPE_LAST_RW 1 /* Last naked read/write */ #define EXT_CMD_TYPE_MONO 0 /* Monolithic read/write */ +/* System control register and bit to enable NAND on some SoCs */ +#define GENCONF_SOC_DEVICE_MUX 0x208 +#define GENCONF_SOC_DEVICE_MUX_NFC_EN BIT(0) + /* * This should be large enough to read 'ONFI' and 'JEDEC'. * Let's use 7 bytes, which is the maximum ID count supported @@ -157,6 +165,7 @@ enum { enum pxa3xx_nand_variant { PXA3XX_NAND_VARIANT_PXA, PXA3XX_NAND_VARIANT_ARMADA370, + PXA3XX_NAND_VARIANT_ARMADA_8K, }; struct pxa3xx_nand_host { @@ -417,10 +426,21 @@ static struct nand_ecclayout ecc_layout_8KB_bch8bit = { /* convert nano-seconds to nand flash controller clock cycles */ #define ns2cycle(ns, clk) (int)((ns) * (clk / 1000000) / 1000) -static enum pxa3xx_nand_variant pxa3xx_nand_get_variant(void) +static const struct udevice_id pxa3xx_nand_dt_ids[] = { + { + .compatible = "marvell,mvebu-pxa3xx-nand", + .data = PXA3XX_NAND_VARIANT_ARMADA370, + }, + { + .compatible = "marvell,armada-8k-nand-controller", + .data = PXA3XX_NAND_VARIANT_ARMADA_8K, + }, + {} +}; + +static enum pxa3xx_nand_variant pxa3xx_nand_get_variant(struct udevice *dev) { - /* We only support the Armada 370/XP/38x for now */ - return PXA3XX_NAND_VARIANT_ARMADA370; + return dev_get_driver_data(dev); } static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host, @@ -697,7 +717,8 @@ static irqreturn_t pxa3xx_nand_irq(struct pxa3xx_nand_info *info) info->retcode = ERR_UNCORERR; if (status & NDSR_CORERR) { info->retcode = ERR_CORERR; - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 && + if ((info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) && info->ecc_bch) info->ecc_err_cnt = NDSR_ERR_CNT(status); else @@ -752,7 +773,8 @@ static irqreturn_t pxa3xx_nand_irq(struct pxa3xx_nand_info *info) nand_writel(info, NDCB0, info->ndcb2); /* NDCB3 register is available in NFCv2 (Armada 370/XP SoC) */ - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) nand_writel(info, NDCB0, info->ndcb3); } @@ -1666,7 +1688,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) } /* Device detection must be done with ECC disabled */ - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) nand_writel(info, NDECCCTRL, 0x0); if (nand_scan_ident(mtd, 1, NULL)) @@ -1716,7 +1739,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) * (aka split) command handling, */ if (mtd->writesize > info->chunk_size) { - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) { + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) { chip->cmdfunc = nand_cmdfunc_extended; } else { dev_err(mtd->dev, @@ -1752,19 +1776,19 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) return nand_scan_tail(mtd); } -static int alloc_nand_resource(struct pxa3xx_nand_info *info) +static int alloc_nand_resource(struct udevice *dev, struct pxa3xx_nand_info *info) { struct pxa3xx_nand_platform_data *pdata; struct pxa3xx_nand_host *host; struct nand_chip *chip = NULL; struct mtd_info *mtd; - int ret, cs; + int cs; pdata = info->pdata; if (pdata->num_cs <= 0) return -ENODEV; - info->variant = pxa3xx_nand_get_variant(); + info->variant = pxa3xx_nand_get_variant(dev); for (cs = 0; cs < pdata->num_cs; cs++) { chip = (struct nand_chip *) ((u8 *)&info[1] + sizeof(*host) * cs); @@ -1794,97 +1818,87 @@ static int alloc_nand_resource(struct pxa3xx_nand_info *info) /* Allocate a buffer to allow flash detection */ info->buf_size = INIT_BUFFER_SIZE; info->data_buff = kmalloc(info->buf_size, GFP_KERNEL); - if (info->data_buff == NULL) { - ret = -ENOMEM; - goto fail_disable_clk; - } + if (info->data_buff == NULL) + return -ENOMEM; /* initialize all interrupts to be disabled */ disable_int(info, NDSR_MASK); - return 0; + /* + * Some SoCs like A7k/A8k need to enable manually the NAND + * controller to avoid being bootloader dependent. This is done + * through the use of a single bit in the System Functions registers. + */ + if (pxa3xx_nand_get_variant(dev) == PXA3XX_NAND_VARIANT_ARMADA_8K) { + struct regmap *sysctrl_base = syscon_regmap_lookup_by_phandle( + dev, "marvell,system-controller"); + u32 reg; - kfree(info->data_buff); -fail_disable_clk: - return ret; + if (IS_ERR(sysctrl_base)) + return PTR_ERR(sysctrl_base); + + regmap_read(sysctrl_base, GENCONF_SOC_DEVICE_MUX, ®); + reg |= GENCONF_SOC_DEVICE_MUX_NFC_EN; + regmap_write(sysctrl_base, GENCONF_SOC_DEVICE_MUX, reg); + } + + return 0; } -static int pxa3xx_nand_probe_dt(struct pxa3xx_nand_info *info) +static int pxa3xx_nand_probe_dt(struct udevice *dev, struct pxa3xx_nand_info *info) { struct pxa3xx_nand_platform_data *pdata; - const void *blob = gd->fdt_blob; - int node = -1; pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; - /* Get address decoding nodes from the FDT blob */ - do { - node = fdt_node_offset_by_compatible(blob, node, - "marvell,mvebu-pxa3xx-nand"); - if (node < 0) - break; - - /* Bypass disabeld nodes */ - if (!fdtdec_get_is_enabled(blob, node)) - continue; - - /* Get the first enabled NAND controler base address */ - info->mmio_base = - (void __iomem *)fdtdec_get_addr_size_auto_noparent( - blob, node, "reg", 0, NULL, true); + info->mmio_base = dev_read_addr_ptr(dev); - pdata->num_cs = fdtdec_get_int(blob, node, "num-cs", 1); - if (pdata->num_cs != 1) { - pr_err("pxa3xx driver supports single CS only\n"); - break; - } - - if (fdtdec_get_bool(blob, node, "nand-enable-arbiter")) - pdata->enable_arbiter = 1; - - if (fdtdec_get_bool(blob, node, "nand-keep-config")) - pdata->keep_config = 1; + pdata->num_cs = dev_read_u32_default(dev, "num-cs", 1); + if (pdata->num_cs != 1) { + pr_err("pxa3xx driver supports single CS only\n"); + return -EINVAL; + } - /* - * ECC parameters. - * If these are not set, they will be selected according - * to the detected flash type. - */ - /* ECC strength */ - pdata->ecc_strength = fdtdec_get_int(blob, node, - "nand-ecc-strength", 0); + if (dev_read_bool(dev, "nand-enable-arbiter")) + pdata->enable_arbiter = 1; - /* ECC step size */ - pdata->ecc_step_size = fdtdec_get_int(blob, node, - "nand-ecc-step-size", 0); + if (dev_read_bool(dev, "nand-keep-config")) + pdata->keep_config = 1; - info->pdata = pdata; + /* + * ECC parameters. + * If these are not set, they will be selected according + * to the detected flash type. + */ + /* ECC strength */ + pdata->ecc_strength = dev_read_u32_default(dev, "nand-ecc-strength", 0); - /* Currently support only a single NAND controller */ - return 0; + /* ECC step size */ + pdata->ecc_step_size = dev_read_u32_default(dev, "nand-ecc-step-size", + 0); - } while (node >= 0); + info->pdata = pdata; - return -EINVAL; + return 0; } -static int pxa3xx_nand_probe(struct pxa3xx_nand_info *info) +static int pxa3xx_nand_probe(struct udevice *dev) { - struct mtd_info *mtd = &info->controller.active->mtd; struct pxa3xx_nand_platform_data *pdata; int ret, cs, probe_success; + struct pxa3xx_nand_info *info = dev_get_priv(dev); - ret = pxa3xx_nand_probe_dt(info); + ret = pxa3xx_nand_probe_dt(dev, info); if (ret) return ret; pdata = info->pdata; - ret = alloc_nand_resource(info); + ret = alloc_nand_resource(dev, info); if (ret) { - dev_err(mtd->dev, "alloc nand resource failed\n"); + dev_err(dev, "alloc nand resource failed\n"); return ret; } @@ -1918,22 +1932,24 @@ static int pxa3xx_nand_probe(struct pxa3xx_nand_info *info) return 0; } -/* - * Main initialization routine - */ +U_BOOT_DRIVER(pxa3xx_nand) = { + .name = "pxa3xx-nand", + .id = UCLASS_MTD, + .of_match = pxa3xx_nand_dt_ids, + .probe = pxa3xx_nand_probe, + .priv_auto_alloc_size = sizeof(struct pxa3xx_nand_info) + + sizeof(struct pxa3xx_nand_host) * CONFIG_SYS_MAX_NAND_DEVICE, +}; + void board_nand_init(void) { - struct pxa3xx_nand_info *info; - struct pxa3xx_nand_host *host; + struct udevice *dev; int ret; - info = kzalloc(sizeof(*info) + - sizeof(*host) * CONFIG_SYS_MAX_NAND_DEVICE, - GFP_KERNEL); - if (!info) - return; - - ret = pxa3xx_nand_probe(info); - if (ret) - return; + ret = uclass_get_device_by_driver(UCLASS_MTD, + DM_GET_DRIVER(pxa3xx_nand), &dev); + if (ret && ret != -ENODEV) { + pr_err("Failed to initialize %s. (error %d)\n", dev->name, + ret); + } } diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index dabd40a4cc1..9ceff0e7c12 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -67,7 +67,7 @@ struct flash_info { #define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ #define USE_CLSR BIT(14) /* use CLSR command */ #define SPI_NOR_HAS_SST26LOCK BIT(15) /* Flash supports lock/unlock via BPR */ -#define SPI_NOR_OCTAL_READ BIT(16) /* Flash supports Octal Read */ +#define SPI_NOR_OCTAL_READ BIT(16) /* Flash supports Octal Read */ }; extern const struct flash_info spi_nor_ids[]; diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c index 15e80049def..b0fcb13f1c9 100644 --- a/drivers/phy/marvell/comphy_cp110.c +++ b/drivers/phy/marvell/comphy_cp110.c @@ -7,6 +7,7 @@ #include <fdtdec.h> #include <log.h> #include <asm/io.h> +#include <asm/ptrace.h> #include <asm/arch/cpu.h> #include <asm/arch/soc.h> #include <linux/delay.h> @@ -22,6 +23,40 @@ DECLARE_GLOBAL_DATA_PTR; #define HPIPE_ADDR(base, lane) (SD_ADDR(base, lane) + 0x800) #define COMPHY_ADDR(base, lane) (base + 0x28 * lane) +/* Firmware related definitions used for SMC calls */ +#define MV_SIP_COMPHY_POWER_ON 0x82000001 +#define MV_SIP_COMPHY_POWER_OFF 0x82000002 +#define MV_SIP_COMPHY_PLL_LOCK 0x82000003 + +/* Used to distinguish between different possible callers (U-boot/Linux) */ +#define COMPHY_CALLER_UBOOT (0x1 << 21) + +#define COMPHY_FW_MODE_FORMAT(mode) ((mode) << 12) +#define COMPHY_FW_FORMAT(mode, idx, speeds) \ + (((mode) << 12) | ((idx) << 8) | ((speeds) << 2)) + +#define COMPHY_FW_PCIE_FORMAT(pcie_width, clk_src, mode, speeds) \ + (COMPHY_CALLER_UBOOT | ((pcie_width) << 18) | \ + ((clk_src) << 17) | COMPHY_FW_FORMAT(mode, 0, speeds)) + +#define COMPHY_SATA_MODE 0x1 +#define COMPHY_SGMII_MODE 0x2 /* SGMII 1G */ +#define COMPHY_HS_SGMII_MODE 0x3 /* SGMII 2.5G */ +#define COMPHY_USB3H_MODE 0x4 +#define COMPHY_USB3D_MODE 0x5 +#define COMPHY_PCIE_MODE 0x6 +#define COMPHY_RXAUI_MODE 0x7 +#define COMPHY_XFI_MODE 0x8 +#define COMPHY_SFI_MODE 0x9 +#define COMPHY_USB3_MODE 0xa +#define COMPHY_AP_MODE 0xb + +/* Comphy unit index macro */ +#define COMPHY_UNIT_ID0 0 +#define COMPHY_UNIT_ID1 1 +#define COMPHY_UNIT_ID2 2 +#define COMPHY_UNIT_ID3 3 + struct utmi_phy_data { void __iomem *utmi_base_addr; void __iomem *usb_cfg_addr; @@ -85,441 +120,6 @@ static u32 polling_with_timeout(void __iomem *addr, u32 val, return 0; } -static int comphy_pcie_power_up(u32 lane, u32 pcie_width, bool clk_src, - bool is_end_point, void __iomem *hpipe_base, - void __iomem *comphy_base) -{ - u32 mask, data, ret = 1; - void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); - void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); - void __iomem *addr; - u32 pcie_clk = 0; /* set input by default */ - - debug_enter(); - - /* - * ToDo: - * Add SAR (Sample-At-Reset) configuration for the PCIe clock - * direction. SAR code is currently not ported from Marvell - * U-Boot to mainline version. - * - * SerDes Lane 4/5 got the PCIe ref-clock #1, - * and SerDes Lane 0 got PCIe ref-clock #0 - */ - debug("PCIe clock = %x\n", pcie_clk); - debug("PCIe RC = %d\n", !is_end_point); - debug("PCIe width = %d\n", pcie_width); - - /* enable PCIe by4 and by2 */ - if (lane == 0) { - if (pcie_width == 4) { - reg_set(comphy_base + COMMON_PHY_SD_CTRL1, - 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET, - COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK); - } else if (pcie_width == 2) { - reg_set(comphy_base + COMMON_PHY_SD_CTRL1, - 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET, - COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK); - } - } - - /* - * If PCIe clock is output and clock source from SerDes lane 5, - * we need to configure the clock-source MUX. - * By default, the clock source is from lane 4 - */ - if (pcie_clk && clk_src && (lane == 5)) { - reg_set((void __iomem *)DFX_DEV_GEN_CTRL12, - 0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET, - DFX_DEV_GEN_PCIE_CLK_SRC_MASK); - } - - debug("stage: RFU configurations - hard reset comphy\n"); - /* RFU configurations - hard reset comphy */ - mask = COMMON_PHY_CFG1_PWR_UP_MASK; - data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; - mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; - data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; - mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK; - data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; - mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; - data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; - mask |= COMMON_PHY_PHY_MODE_MASK; - data |= 0x0 << COMMON_PHY_PHY_MODE_OFFSET; - reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); - - /* release from hard reset */ - mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK; - data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; - mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; - data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; - reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); - - /* Wait 1ms - until band gap and ref clock ready */ - mdelay(1); - /* Start comphy Configuration */ - debug("stage: Comphy configuration\n"); - /* Set PIPE soft reset */ - mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK; - data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET; - /* Set PHY datapath width mode for V0 */ - mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK; - data |= 0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET; - /* Set Data bus width USB mode for V0 */ - mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK; - data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET; - /* Set CORE_CLK output frequency for 250Mhz */ - mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK; - data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask); - /* Set PLL ready delay for 0x2 */ - data = 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET; - mask = HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK; - if (pcie_width != 1) { - data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET; - mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK; - data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET; - mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK; - } - reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG, data, mask); - - /* Set PIPE mode interface to PCIe3 - 0x1 & set lane order */ - data = 0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET; - mask = HPIPE_CLK_SRC_HI_MODE_PIPE_MASK; - if (pcie_width != 1) { - mask |= HPIPE_CLK_SRC_HI_LANE_STRT_MASK; - mask |= HPIPE_CLK_SRC_HI_LANE_MASTER_MASK; - mask |= HPIPE_CLK_SRC_HI_LANE_BREAK_MASK; - if (lane == 0) { - data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET; - data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET; - } else if (lane == (pcie_width - 1)) { - data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET; - } - } - reg_set(hpipe_addr + HPIPE_CLK_SRC_HI_REG, data, mask); - /* Config update polarity equalization */ - reg_set(hpipe_addr + HPIPE_LANE_EQ_CFG1_REG, - 0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET, - HPIPE_CFG_UPDATE_POLARITY_MASK); - /* Set PIPE version 4 to mode enable */ - reg_set(hpipe_addr + HPIPE_DFE_CTRL_28_REG, - 0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET, - HPIPE_DFE_CTRL_28_PIPE4_MASK); - /* TODO: check if pcie clock is output/input - for bringup use input*/ - /* Enable PIN clock 100M_125M */ - mask = 0; - data = 0; - /* Only if clock is output, configure the clock-source mux */ - if (pcie_clk) { - mask |= HPIPE_MISC_CLK100M_125M_MASK; - data |= 0x1 << HPIPE_MISC_CLK100M_125M_OFFSET; - } - /* - * Set PIN_TXDCLK_2X Clock Frequency Selection for outputs 500MHz - * clock - */ - mask |= HPIPE_MISC_TXDCLK_2X_MASK; - data |= 0x0 << HPIPE_MISC_TXDCLK_2X_OFFSET; - /* Enable 500MHz Clock */ - mask |= HPIPE_MISC_CLK500_EN_MASK; - data |= 0x1 << HPIPE_MISC_CLK500_EN_OFFSET; - if (pcie_clk) { /* output */ - /* Set reference clock comes from group 1 */ - mask |= HPIPE_MISC_REFCLK_SEL_MASK; - data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; - } else { - /* Set reference clock comes from group 2 */ - mask |= HPIPE_MISC_REFCLK_SEL_MASK; - data |= 0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET; - } - mask |= HPIPE_MISC_ICP_FORCE_MASK; - data |= 0x1 << HPIPE_MISC_ICP_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); - if (pcie_clk) { /* output */ - /* Set reference frequcency select - 0x2 for 25MHz*/ - mask = HPIPE_PWR_PLL_REF_FREQ_MASK; - data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; - } else { - /* Set reference frequcency select - 0x0 for 100MHz*/ - mask = HPIPE_PWR_PLL_REF_FREQ_MASK; - data = 0x0 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; - } - /* Set PHY mode to PCIe */ - mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; - data |= 0x3 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); - - /* ref clock alignment */ - if (pcie_width != 1) { - mask = HPIPE_LANE_ALIGN_OFF_MASK; - data = 0x0 << HPIPE_LANE_ALIGN_OFF_OFFSET; - reg_set(hpipe_addr + HPIPE_LANE_ALIGN_REG, data, mask); - } - - /* - * Set the amount of time spent in the LoZ state - set for 0x7 only if - * the PCIe clock is output - */ - if (pcie_clk) { - reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL, - 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET, - HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK); - } - - /* Set Maximal PHY Generation Setting(8Gbps) */ - mask = HPIPE_INTERFACE_GEN_MAX_MASK; - data = 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET; - /* Bypass frame detection and sync detection for RX DATA */ - mask = HPIPE_INTERFACE_DET_BYPASS_MASK; - data = 0x1 << HPIPE_INTERFACE_DET_BYPASS_OFFSET; - /* Set Link Train Mode (Tx training control pins are used) */ - mask |= HPIPE_INTERFACE_LINK_TRAIN_MASK; - data |= 0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET; - reg_set(hpipe_addr + HPIPE_INTERFACE_REG, data, mask); - - /* Set Idle_sync enable */ - mask = HPIPE_PCIE_IDLE_SYNC_MASK; - data = 0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET; - /* Select bits for PCIE Gen3(32bit) */ - mask |= HPIPE_PCIE_SEL_BITS_MASK; - data |= 0x2 << HPIPE_PCIE_SEL_BITS_OFFSET; - reg_set(hpipe_addr + HPIPE_PCIE_REG0, data, mask); - - /* Enable Tx_adapt_g1 */ - mask = HPIPE_TX_TRAIN_CTRL_G1_MASK; - data = 0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET; - /* Enable Tx_adapt_gn1 */ - mask |= HPIPE_TX_TRAIN_CTRL_GN1_MASK; - data |= 0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET; - /* Disable Tx_adapt_g0 */ - mask |= HPIPE_TX_TRAIN_CTRL_G0_MASK; - data |= 0x0 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask); - - /* Set reg_tx_train_chk_init */ - mask = HPIPE_TX_TRAIN_CHK_INIT_MASK; - data = 0x0 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET; - /* Enable TX_COE_FM_PIN_PCIE3_EN */ - mask |= HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK; - data |= 0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask); - - debug("stage: TRx training parameters\n"); - /* Set Preset sweep configurations */ - mask = HPIPE_TX_TX_STATUS_CHECK_MODE_MASK; - data = 0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET; - - mask |= HPIPE_TX_NUM_OF_PRESET_MASK; - data |= 0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET; - - mask |= HPIPE_TX_SWEEP_PRESET_EN_MASK; - data |= 0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_11_REG, data, mask); - - /* Tx train start configuration */ - mask = HPIPE_TX_TRAIN_START_SQ_EN_MASK; - data = 0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET; - - mask |= HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK; - data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET; - - mask |= HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK; - data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET; - - mask |= HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK; - data |= 0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask); - - /* Enable Tx train P2P */ - mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK; - data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask); - - /* Configure Tx train timeout */ - mask = HPIPE_TRX_TRAIN_TIMER_MASK; - data = 0x17 << HPIPE_TRX_TRAIN_TIMER_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_4_REG, data, mask); - - /* Disable G0/G1/GN1 adaptation */ - mask = HPIPE_TX_TRAIN_CTRL_G1_MASK | HPIPE_TX_TRAIN_CTRL_GN1_MASK - | HPIPE_TX_TRAIN_CTRL_G0_OFFSET; - data = 0; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask); - - /* Disable DTL frequency loop */ - mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; - data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); - - /* Configure G3 DFE */ - mask = HPIPE_G3_DFE_RES_MASK; - data = 0x3 << HPIPE_G3_DFE_RES_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask); - - /* Use TX/RX training result for DFE */ - mask = HPIPE_DFE_RES_FORCE_MASK; - data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); - - /* Configure initial and final coefficient value for receiver */ - mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK; - data = 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET; - - mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK; - data |= 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET; - - mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK; - data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SET_1_REG, data, mask); - - /* Trigger sampler enable pulse */ - mask = HPIPE_SMAPLER_MASK; - data = 0x1 << HPIPE_SMAPLER_OFFSET; - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); - udelay(5); - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, 0, mask); - - /* FFE resistor tuning for different bandwidth */ - mask = HPIPE_G3_FFE_DEG_RES_LEVEL_MASK; - data = 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET; - - mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK; - data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask); - - /* Pattern lock lost timeout disable */ - mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK; - data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask); - - /* Configure DFE adaptations */ - mask = HPIPE_CDR_MAX_DFE_ADAPT_1_MASK; - data = 0x1 << HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET; - mask |= HPIPE_CDR_MAX_DFE_ADAPT_0_MASK; - data |= 0x0 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET; - mask |= HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK; - data |= 0x0 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET; - reg_set(hpipe_addr + HPIPE_CDR_CONTROL_REG, data, mask); - mask = HPIPE_DFE_TX_MAX_DFE_ADAPT_MASK; - data = 0x0 << HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_CONTROL_REG, data, mask); - - /* Genration 2 setting 1*/ - mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK; - data = 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_SELMUPP_MASK; - data |= 0x1 << HPIPE_G2_SET_1_G2_RX_SELMUPP_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK; - data |= 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET; - reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask); - - /* DFE enable */ - mask = HPIPE_G2_DFE_RES_MASK; - data = 0x3 << HPIPE_G2_DFE_RES_OFFSET; - reg_set(hpipe_addr + HPIPE_G2_SETTINGS_4_REG, data, mask); - - /* Configure DFE Resolution */ - mask = HPIPE_LANE_CFG4_DFE_EN_SEL_MASK; - data = 0x1 << HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_LANE_CFG4_REG, data, mask); - - /* VDD calibration control */ - mask = HPIPE_EXT_SELLV_RXSAMPL_MASK; - data = 0x16 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET; - reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask); - - /* Set PLL Charge-pump Current Control */ - mask = HPIPE_G3_SETTING_5_G3_ICP_MASK; - data = 0x4 << HPIPE_G3_SETTING_5_G3_ICP_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SETTING_5_REG, data, mask); - - /* Set lane rqualization remote setting */ - mask = HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_MASK; - data = 0x1 << HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET; - mask |= HPIPE_LANE_CFG_FOM_ONLY_MODE_MASK; - data |= 0x1 << HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET; - mask |= HPIPE_LANE_CFG_FOM_PRESET_VECTOR_MASK; - data |= 0x2 << HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET; - reg_set(hpipe_addr + HPIPE_LANE_EQ_REMOTE_SETTING_REG, data, mask); - - if (!is_end_point) { - /* Set phy in root complex mode */ - mask = HPIPE_CFG_PHY_RC_EP_MASK; - data = 0x1 << HPIPE_CFG_PHY_RC_EP_OFFSET; - reg_set(hpipe_addr + HPIPE_LANE_EQU_CONFIG_0_REG, data, mask); - } - - debug("stage: Comphy power up\n"); - - /* - * For PCIe by4 or by2 - release from reset only after finish to - * configure all lanes - */ - if ((pcie_width == 1) || (lane == (pcie_width - 1))) { - u32 i, start_lane, end_lane; - - if (pcie_width != 1) { - /* allows writing to all lanes in one write */ - reg_set(comphy_base + COMMON_PHY_SD_CTRL1, - 0x0 << - COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET, - COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK); - start_lane = 0; - end_lane = pcie_width; - - /* - * Release from PIPE soft reset - * for PCIe by4 or by2 - release from soft reset - * all lanes - can't use read modify write - */ - reg_set(HPIPE_ADDR(hpipe_base, 0) + - HPIPE_RST_CLK_CTRL_REG, 0x24, 0xffffffff); - } else { - start_lane = lane; - end_lane = lane + 1; - - /* - * Release from PIPE soft reset - * for PCIe by4 or by2 - release from soft reset - * all lanes - */ - reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, - 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET, - HPIPE_RST_CLK_CTRL_PIPE_RST_MASK); - } - - - if (pcie_width != 1) { - /* disable writing to all lanes with one write */ - reg_set(comphy_base + COMMON_PHY_SD_CTRL1, - 0x3210 << - COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET, - COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK); - } - - debug("stage: Check PLL\n"); - /* Read lane status */ - for (i = start_lane; i < end_lane; i++) { - addr = HPIPE_ADDR(hpipe_base, i) + - HPIPE_LANE_STATUS1_REG; - data = HPIPE_LANE_STATUS1_PCLK_EN_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 15000); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", - hpipe_addr + HPIPE_LANE_STATUS1_REG, - data); - pr_err("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n"); - ret = 0; - } - } - } - - debug_exit(); - return ret; -} - static int comphy_usb3_power_up(u32 lane, void __iomem *hpipe_base, void __iomem *comphy_base) { @@ -642,15 +242,31 @@ static int comphy_usb3_power_up(u32 lane, void __iomem *hpipe_base, return ret; } +static int comphy_smc(u32 function_id, void __iomem *comphy_base_addr, + u32 lane, u32 mode) +{ + struct pt_regs pregs = {0}; + + pregs.regs[0] = function_id; + pregs.regs[1] = (unsigned long)comphy_base_addr; + pregs.regs[2] = lane; + pregs.regs[3] = mode; + + smc_call(&pregs); + + /* + * TODO: Firmware return 0 on success, temporary map it to u-boot + * convention, but after all comphy will be reworked the convention in + * u-boot should be change and this conversion removed + */ + return pregs.regs[0] ? 0 : 1; +} + static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base, - void __iomem *comphy_base, int cp_index, - u32 invert) + void __iomem *comphy_base_addr, int cp_index, + u32 type) { u32 mask, data, i, ret = 1; - void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); - void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); - void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); - void __iomem *addr; void __iomem *sata_base = NULL; int sata_node = -1; /* Set to -1 in order to read the first sata node */ @@ -703,255 +319,8 @@ static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base, data |= 0x0 << SATA3_CTRL_SATA_SSU_OFFSET; reg_set(sata_base + SATA3_VENDOR_DATA, data, mask); - debug("stage: RFU configurations - hard reset comphy\n"); - /* RFU configurations - hard reset comphy */ - mask = COMMON_PHY_CFG1_PWR_UP_MASK; - data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; - mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; - data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; - mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK; - data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; - mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; - data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; - reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); - - /* Set select data width 40Bit - SATA mode only */ - reg_set(comphy_addr + COMMON_PHY_CFG6_REG, - 0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET, - COMMON_PHY_CFG6_IF_40_SEL_MASK); - - /* release from hard reset in SD external */ - mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - /* Wait 1ms - until band gap and ref clock ready */ - mdelay(1); + ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, comphy_base_addr, lane, type); - debug("stage: Comphy configuration\n"); - /* Start comphy Configuration */ - /* Set reference clock to comes from group 1 - choose 25Mhz */ - reg_set(hpipe_addr + HPIPE_MISC_REG, - 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET, - HPIPE_MISC_REFCLK_SEL_MASK); - /* Reference frequency select set 1 (for SATA = 25Mhz) */ - mask = HPIPE_PWR_PLL_REF_FREQ_MASK; - data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; - /* PHY mode select (set SATA = 0x0 */ - mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; - data |= 0x0 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); - /* Set max PHY generation setting - 6Gbps */ - reg_set(hpipe_addr + HPIPE_INTERFACE_REG, - 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET, - HPIPE_INTERFACE_GEN_MAX_MASK); - /* Set select data width 40Bit (SEL_BITS[2:0]) */ - reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, - 0x2 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK); - - debug("stage: Analog paramters from ETP(HW)\n"); - /* Set analog parameters from ETP(HW) */ - /* G1 settings */ - mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; - data = 0x0 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK; - data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK; - data |= 0x0 << HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK; - data |= 0x3 << HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK; - data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); - - mask = HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK; - data = 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK; - data |= 0x2 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; - data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_MASK; - data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_MASK; - data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); - - /* G2 settings */ - mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK; - data = 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_SELMUPP_MASK; - data |= 0x1 << HPIPE_G2_SET_1_G2_RX_SELMUPP_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK; - data |= 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_SELMUFF_MASK; - data |= 0x3 << HPIPE_G2_SET_1_G2_RX_SELMUFF_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_MASK; - data |= 0x1 << HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_OFFSET; - reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask); - - /* G3 settings */ - mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK; - data = 0x2 << HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET; - mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK; - data |= 0x2 << HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET; - mask |= HPIPE_G3_SET_1_G3_RX_SELMUFI_MASK; - data |= 0x3 << HPIPE_G3_SET_1_G3_RX_SELMUFI_OFFSET; - mask |= HPIPE_G3_SET_1_G3_RX_SELMUFF_MASK; - data |= 0x3 << HPIPE_G3_SET_1_G3_RX_SELMUFF_OFFSET; - mask |= HPIPE_G3_SET_1_G3_RX_DFE_EN_MASK; - data |= 0x1 << HPIPE_G3_SET_1_G3_RX_DFE_EN_OFFSET; - mask |= HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_MASK; - data |= 0x2 << HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_OFFSET; - mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK; - data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SET_1_REG, data, mask); - - /* DTL Control */ - mask = HPIPE_PWR_CTR_DTL_SQ_DET_EN_MASK; - data = 0x1 << HPIPE_PWR_CTR_DTL_SQ_DET_EN_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_CLAMPING_SEL_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_CLAMPING_SEL_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); - - /* Trigger sampler enable pulse (by toggleing the bit) */ - mask = HPIPE_SMAPLER_MASK; - data = 0x1 << HPIPE_SMAPLER_OFFSET; - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); - mask = HPIPE_SMAPLER_MASK; - data = 0x0 << HPIPE_SMAPLER_OFFSET; - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); - - /* VDD Calibration Control 3 */ - mask = HPIPE_EXT_SELLV_RXSAMPL_MASK; - data = 0x10 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET; - reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask); - - /* DFE Resolution Control */ - mask = HPIPE_DFE_RES_FORCE_MASK; - data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); - - /* DFE F3-F5 Coefficient Control */ - mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; - data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; - mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; - data = 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); - - /* G3 Setting 3 */ - mask = HPIPE_G3_FFE_CAP_SEL_MASK; - data = 0xf << HPIPE_G3_FFE_CAP_SEL_OFFSET; - mask |= HPIPE_G3_FFE_RES_SEL_MASK; - data |= 0x4 << HPIPE_G3_FFE_RES_SEL_OFFSET; - mask |= HPIPE_G3_FFE_SETTING_FORCE_MASK; - data |= 0x1 << HPIPE_G3_FFE_SETTING_FORCE_OFFSET; - mask |= HPIPE_G3_FFE_DEG_RES_LEVEL_MASK; - data |= 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET; - mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK; - data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask); - - /* G3 Setting 4 */ - mask = HPIPE_G3_DFE_RES_MASK; - data = 0x2 << HPIPE_G3_DFE_RES_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask); - - /* Offset Phase Control */ - mask = HPIPE_OS_PH_OFFSET_MASK; - data = 0x5c << HPIPE_OS_PH_OFFSET_OFFSET; - mask |= HPIPE_OS_PH_OFFSET_FORCE_MASK; - data |= 0x1 << HPIPE_OS_PH_OFFSET_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask); - mask = HPIPE_OS_PH_VALID_MASK; - data = 0x1 << HPIPE_OS_PH_VALID_OFFSET; - reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask); - mask = HPIPE_OS_PH_VALID_MASK; - data = 0x0 << HPIPE_OS_PH_VALID_OFFSET; - reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask); - - /* Set G1 TX amplitude and TX post emphasis value */ - mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK; - data = 0x8 << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET; - mask |= HPIPE_G1_SET_0_G1_TX_AMP_ADJ_MASK; - data |= 0x1 << HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET; - mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; - data |= 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; - mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_EN_MASK; - data |= 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask); - - /* Set G2 TX amplitude and TX post emphasis value */ - mask = HPIPE_G2_SET_0_G2_TX_AMP_MASK; - data = 0xa << HPIPE_G2_SET_0_G2_TX_AMP_OFFSET; - mask |= HPIPE_G2_SET_0_G2_TX_AMP_ADJ_MASK; - data |= 0x1 << HPIPE_G2_SET_0_G2_TX_AMP_ADJ_OFFSET; - mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_MASK; - data |= 0x2 << HPIPE_G2_SET_0_G2_TX_EMPH1_OFFSET; - mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_EN_MASK; - data |= 0x1 << HPIPE_G2_SET_0_G2_TX_EMPH1_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G2_SET_0_REG, data, mask); - - /* Set G3 TX amplitude and TX post emphasis value */ - mask = HPIPE_G3_SET_0_G3_TX_AMP_MASK; - data = 0xe << HPIPE_G3_SET_0_G3_TX_AMP_OFFSET; - mask |= HPIPE_G3_SET_0_G3_TX_AMP_ADJ_MASK; - data |= 0x1 << HPIPE_G3_SET_0_G3_TX_AMP_ADJ_OFFSET; - mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_MASK; - data |= 0x6 << HPIPE_G3_SET_0_G3_TX_EMPH1_OFFSET; - mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_EN_MASK; - data |= 0x1 << HPIPE_G3_SET_0_G3_TX_EMPH1_EN_OFFSET; - mask |= HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_MASK; - data |= 0x4 << HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_OFFSET; - mask |= HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_MASK; - data |= 0x0 << HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SET_0_REG, data, mask); - - /* SERDES External Configuration 2 register */ - mask = SD_EXTERNAL_CONFIG2_SSC_ENABLE_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG2_SSC_ENABLE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask); - - /* DFE reset sequence */ - reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, - 0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET, - HPIPE_PWR_CTR_RST_DFE_MASK); - reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, - 0x0 << HPIPE_PWR_CTR_RST_DFE_OFFSET, - HPIPE_PWR_CTR_RST_DFE_MASK); - - /* Set RX / TX swaps */ - data = mask = 0; - if (invert & PHY_POLARITY_TXD_INVERT) { - data |= (1 << HPIPE_SYNC_PATTERN_TXD_SWAP_OFFSET); - mask |= HPIPE_SYNC_PATTERN_TXD_SWAP_MASK; - } - if (invert & PHY_POLARITY_RXD_INVERT) { - data |= (1 << HPIPE_SYNC_PATTERN_RXD_SWAP_OFFSET); - mask |= HPIPE_SYNC_PATTERN_RXD_SWAP_MASK; - } - reg_set(hpipe_addr + HPIPE_SYNC_PATTERN_REG, data, mask); - - /* SW reset for interupt logic */ - reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, - 0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET, - HPIPE_PWR_CTR_SFT_RST_MASK); - reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, - 0x0 << HPIPE_PWR_CTR_SFT_RST_OFFSET, - HPIPE_PWR_CTR_SFT_RST_MASK); - - debug("stage: Comphy power up\n"); /* * MAC configuration power up comphy - power up PLL/TX/RX * use indirect address for vendor spesific SATA control register @@ -981,469 +350,7 @@ static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base, reg_set(sata_base + SATA3_VENDOR_DATA, 0x1 << SATA_MBUS_REGRET_EN_OFFSET, SATA_MBUS_REGRET_EN_MASK); - debug("stage: Check PLL\n"); - - addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; - data = SD_EXTERNAL_STATUS0_PLL_TX_MASK & - SD_EXTERNAL_STATUS0_PLL_RX_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 15000); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", - hpipe_addr + HPIPE_LANE_STATUS1_REG, data); - pr_err("SD_EXTERNAL_STATUS0_PLL_TX is %d, SD_EXTERNAL_STATUS0_PLL_RX is %d\n", - (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK), - (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK)); - ret = 0; - } - - debug_exit(); - return ret; -} - -static int comphy_sgmii_power_up(u32 lane, u32 sgmii_speed, - void __iomem *hpipe_base, - void __iomem *comphy_base) -{ - u32 mask, data, ret = 1; - void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); - void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); - void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); - void __iomem *addr; - - debug_enter(); - debug("stage: RFU configurations - hard reset comphy\n"); - /* RFU configurations - hard reset comphy */ - mask = COMMON_PHY_CFG1_PWR_UP_MASK; - data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; - mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; - data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; - reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); - - /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ - mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; - mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; - if (sgmii_speed == PHY_SPEED_1_25G) { - data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; - data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; - } else { - /* 3.125G */ - data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; - data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; - } - mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; - data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; - data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; - data |= 1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); - - /* release from hard reset */ - mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; - data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; - data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - /* release from hard reset */ - mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - - /* Wait 1ms - until band gap and ref clock ready */ - mdelay(1); - - /* Start comphy Configuration */ - debug("stage: Comphy configuration\n"); - /* set reference clock */ - mask = HPIPE_MISC_REFCLK_SEL_MASK; - data = 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); - /* Power and PLL Control */ - mask = HPIPE_PWR_PLL_REF_FREQ_MASK; - data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; - mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; - data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); - /* Loopback register */ - mask = HPIPE_LOOPBACK_SEL_MASK; - data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask); - /* rx control 1 */ - mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; - data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; - mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; - data |= 0x0 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); - /* DTL Control */ - mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; - data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); - - /* Set analog paramters from ETP(HW) - for now use the default datas */ - debug("stage: Analog paramters from ETP(HW)\n"); - - reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, - 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET, - HPIPE_G1_SET_0_G1_TX_EMPH1_MASK); - - debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); - /* SERDES External Configuration */ - mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); - - /* check PLL rx & tx ready */ - addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; - data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | - SD_EXTERNAL_STATUS0_PLL_TX_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 15000); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", - sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); - pr_err("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n", - (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK), - (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)); - ret = 0; - } - - /* RX init */ - mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - /* check that RX init done */ - addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; - data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 100); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); - pr_err("SD_EXTERNAL_STATUS0_RX_INIT is 0\n"); - ret = 0; - } - - debug("stage: RF Reset\n"); - /* RF Reset */ - mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - debug_exit(); - return ret; -} - -static int comphy_sfi_power_up(u32 lane, void __iomem *hpipe_base, - void __iomem *comphy_base, u32 speed) -{ - u32 mask, data, ret = 1; - void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); - void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); - void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); - void __iomem *addr; - - debug_enter(); - debug("stage: RFU configurations - hard reset comphy\n"); - /* RFU configurations - hard reset comphy */ - mask = COMMON_PHY_CFG1_PWR_UP_MASK; - data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; - mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; - data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; - reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); - - /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ - mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; - data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; - data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; - data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; - data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; - data |= 0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); - - /* release from hard reset */ - mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; - data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; - data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - - /* Wait 1ms - until band gap and ref clock ready */ - mdelay(1); - - /* Start comphy Configuration */ - debug("stage: Comphy configuration\n"); - /* set reference clock */ - mask = HPIPE_MISC_ICP_FORCE_MASK; - data = (speed == PHY_SPEED_5_15625G) ? - (0x0 << HPIPE_MISC_ICP_FORCE_OFFSET) : - (0x1 << HPIPE_MISC_ICP_FORCE_OFFSET); - mask |= HPIPE_MISC_REFCLK_SEL_MASK; - data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); - /* Power and PLL Control */ - mask = HPIPE_PWR_PLL_REF_FREQ_MASK; - data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; - mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; - data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); - /* Loopback register */ - mask = HPIPE_LOOPBACK_SEL_MASK; - data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask); - /* rx control 1 */ - mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; - data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; - mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; - data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); - /* DTL Control */ - mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; - data = 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); - - /* Transmitter/Receiver Speed Divider Force */ - if (speed == PHY_SPEED_5_15625G) { - mask = HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_MASK; - data = 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_OFFSET; - mask |= HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_MASK; - data |= 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_OFFSET; - mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_MASK; - data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_OFFSET; - mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_MASK; - data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_OFFSET; - } else { - mask = HPIPE_TXDIGCK_DIV_FORCE_MASK; - data = 0x1 << HPIPE_TXDIGCK_DIV_FORCE_OFFSET; - } - reg_set(hpipe_addr + HPIPE_SPD_DIV_FORCE_REG, data, mask); - - /* Set analog paramters from ETP(HW) */ - debug("stage: Analog paramters from ETP(HW)\n"); - /* SERDES External Configuration 2 */ - mask = SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask); - /* 0x7-DFE Resolution control */ - mask = HPIPE_DFE_RES_FORCE_MASK; - data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); - /* 0xd-G1_Setting_0 */ - if (speed == PHY_SPEED_5_15625G) { - mask = HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; - data = 0x6 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; - } else { - mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK; - data = 0x1c << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET; - mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; - data |= 0xe << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; - } - reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask); - /* Genration 1 setting 2 (G1_Setting_2) */ - mask = HPIPE_G1_SET_2_G1_TX_EMPH0_MASK; - data = 0x0 << HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET; - mask |= HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK; - data |= 0x1 << HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SET_2_REG, data, mask); - /* Transmitter Slew Rate Control register (tx_reg1) */ - mask = HPIPE_TX_REG1_TX_EMPH_RES_MASK; - data = 0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET; - mask |= HPIPE_TX_REG1_SLC_EN_MASK; - data |= 0x3f << HPIPE_TX_REG1_SLC_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_REG1_REG, data, mask); - /* Impedance Calibration Control register (cal_reg1) */ - mask = HPIPE_CAL_REG_1_EXT_TXIMP_MASK; - data = 0xe << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET; - mask |= HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK; - data |= 0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_CAL_REG1_REG, data, mask); - /* Generation 1 Setting 5 (g1_setting_5) */ - mask = HPIPE_G1_SETTING_5_G1_ICP_MASK; - data = 0 << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SETTING_5_REG, data, mask); - /* 0xE-G1_Setting_1 */ - mask = HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK; - data = 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET; - if (speed == PHY_SPEED_5_15625G) { - mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; - data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK; - data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET; - } else { - mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; - data |= 0x2 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK; - data |= 0x2 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK; - data |= 0x0 << HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK; - data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK; - data |= 0x3 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET; - } - reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); - - /* 0xA-DFE_Reg3 */ - mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; - data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; - mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; - data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); - - /* 0x111-G1_Setting_4 */ - mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK; - data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask); - /* Genration 1 setting 3 (G1_Setting_3) */ - mask = HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK; - data = 0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET; - if (speed == PHY_SPEED_5_15625G) { - /* Force FFE (Feed Forward Equalization) to 5G */ - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK; - data |= 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK; - data |= 0x4 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; - data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; - } - reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); - - /* Connfigure RX training timer */ - mask = HPIPE_RX_TRAIN_TIMER_MASK; - data = 0x13 << HPIPE_RX_TRAIN_TIMER_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask); - - /* Enable TX train peak to peak hold */ - mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK; - data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask); - - /* Configure TX preset index */ - mask = HPIPE_TX_PRESET_INDEX_MASK; - data = 0x2 << HPIPE_TX_PRESET_INDEX_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_PRESET_INDEX_REG, data, mask); - - /* Disable pattern lock lost timeout */ - mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK; - data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask); - - /* Configure TX training pattern and TX training 16bit auto */ - mask = HPIPE_TX_TRAIN_16BIT_AUTO_EN_MASK; - data = 0x1 << HPIPE_TX_TRAIN_16BIT_AUTO_EN_OFFSET; - mask |= HPIPE_TX_TRAIN_PAT_SEL_MASK; - data |= 0x1 << HPIPE_TX_TRAIN_PAT_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask); - - /* Configure Training patten number */ - mask = HPIPE_TRAIN_PAT_NUM_MASK; - data = 0x88 << HPIPE_TRAIN_PAT_NUM_OFFSET; - reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_0_REG, data, mask); - - /* Configure differencial manchester encoter to ethernet mode */ - mask = HPIPE_DME_ETHERNET_MODE_MASK; - data = 0x1 << HPIPE_DME_ETHERNET_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_DME_REG, data, mask); - - /* Configure VDD Continuous Calibration */ - mask = HPIPE_CAL_VDD_CONT_MODE_MASK; - data = 0x1 << HPIPE_CAL_VDD_CONT_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_VDD_CAL_0_REG, data, mask); - - /* Trigger sampler enable pulse (by toggleing the bit) */ - mask = HPIPE_RX_SAMPLER_OS_GAIN_MASK; - data = 0x3 << HPIPE_RX_SAMPLER_OS_GAIN_OFFSET; - mask |= HPIPE_SMAPLER_MASK; - data |= 0x1 << HPIPE_SMAPLER_OFFSET; - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); - mask = HPIPE_SMAPLER_MASK; - data = 0x0 << HPIPE_SMAPLER_OFFSET; - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); - - /* Set External RX Regulator Control */ - mask = HPIPE_EXT_SELLV_RXSAMPL_MASK; - data = 0x1A << HPIPE_EXT_SELLV_RXSAMPL_OFFSET; - reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask); - - debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); - /* SERDES External Configuration */ - mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); - - - /* check PLL rx & tx ready */ - addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; - data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | - SD_EXTERNAL_STATUS0_PLL_TX_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 15000); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); - pr_err("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n", - (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK), - (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)); - ret = 0; - } - - /* RX init */ - mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - - /* check that RX init done */ - addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; - data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 100); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", - sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); - pr_err("SD_EXTERNAL_STATUS0_RX_INIT is 0\n"); - ret = 0; - } - - debug("stage: RF Reset\n"); - /* RF Reset */ - mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + ret = comphy_smc(MV_SIP_COMPHY_PLL_LOCK, comphy_base_addr, lane, type); debug_exit(); return ret; @@ -1973,6 +880,7 @@ int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, void __iomem *comphy_base_addr, *hpipe_base_addr; u32 comphy_max_count, lane, ret = 0; u32 pcie_width = 0; + u32 mode; debug_enter(); @@ -2011,19 +919,23 @@ int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, case PHY_TYPE_PEX1: case PHY_TYPE_PEX2: case PHY_TYPE_PEX3: - ret = comphy_pcie_power_up( - lane, pcie_width, ptr_comphy_map->clk_src, - serdes_map->end_point, - hpipe_base_addr, comphy_base_addr); + mode = COMPHY_FW_PCIE_FORMAT(pcie_width, + ptr_comphy_map->clk_src, + COMPHY_PCIE_MODE, + ptr_comphy_map->speed); + ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, + ptr_chip_cfg->comphy_base_addr, lane, + mode); break; case PHY_TYPE_SATA0: case PHY_TYPE_SATA1: case PHY_TYPE_SATA2: case PHY_TYPE_SATA3: - ret = comphy_sata_power_up( - lane, hpipe_base_addr, comphy_base_addr, - ptr_chip_cfg->cp_index, - serdes_map[lane].invert); + mode = COMPHY_FW_MODE_FORMAT(COMPHY_SATA_MODE); + ret = comphy_sata_power_up(lane, hpipe_base_addr, + comphy_base_addr, + ptr_chip_cfg->cp_index, + mode); break; case PHY_TYPE_USB3_HOST0: case PHY_TYPE_USB3_HOST1: @@ -2033,6 +945,25 @@ int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, break; case PHY_TYPE_SGMII0: case PHY_TYPE_SGMII1: + if (ptr_comphy_map->speed == PHY_SPEED_INVALID) { + debug("Warning: "); + debug("SGMII PHY speed in lane %d is invalid,", + lane); + debug(" set PHY speed to 1.25G\n"); + ptr_comphy_map->speed = PHY_SPEED_1_25G; + } + + /* + * UINIT_ID not relevant for SGMII0 and SGMII1 - will be + * ignored by firmware + */ + mode = COMPHY_FW_FORMAT(COMPHY_SGMII_MODE, + COMPHY_UNIT_ID0, + ptr_comphy_map->speed); + ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, + ptr_chip_cfg->comphy_base_addr, lane, + mode); + break; case PHY_TYPE_SGMII2: case PHY_TYPE_SGMII3: if (ptr_comphy_map->speed == PHY_SPEED_INVALID) { @@ -2040,14 +971,21 @@ int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, lane); ptr_comphy_map->speed = PHY_SPEED_1_25G; } - ret = comphy_sgmii_power_up( - lane, ptr_comphy_map->speed, hpipe_base_addr, - comphy_base_addr); + + mode = COMPHY_FW_FORMAT(COMPHY_SGMII_MODE, + COMPHY_UNIT_ID2, + ptr_comphy_map->speed); + ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, + ptr_chip_cfg->comphy_base_addr, lane, + mode); break; case PHY_TYPE_SFI: - ret = comphy_sfi_power_up(lane, hpipe_base_addr, - comphy_base_addr, - ptr_comphy_map->speed); + mode = COMPHY_FW_FORMAT(COMPHY_SFI_MODE, + COMPHY_UNIT_ID0, + ptr_comphy_map->speed); + ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, + ptr_chip_cfg->comphy_base_addr, lane, + mode); break; case PHY_TYPE_RXAUI0: case PHY_TYPE_RXAUI1: diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c index 2772c25f1d2..d9e35c6a2b4 100644 --- a/drivers/serial/serial_pl01x.c +++ b/drivers/serial/serial_pl01x.c @@ -19,6 +19,7 @@ #include <watchdog.h> #include <asm/io.h> #include <serial.h> +#include <dm/device_compat.h> #include <dm/platform_data/serial_pl01x.h> #include <linux/compiler.h> #include "serial_pl01x_internal.h" @@ -362,8 +363,18 @@ int pl01x_serial_ofdata_to_platdata(struct udevice *dev) plat->clock = dev_read_u32_default(dev, "clock", CONFIG_PL011_CLOCK); ret = clk_get_by_index(dev, 0, &clk); if (!ret) { - clk_enable(&clk); + ret = clk_enable(&clk); + if (ret && ret != -ENOSYS) { + dev_err(dev, "failed to enable clock\n"); + return ret; + } + plat->clock = clk_get_rate(&clk); + if (IS_ERR_VALUE(plat->clock)) { + dev_err(dev, "failed to get rate\n"); + return plat->clock; + } + debug("%s: CLK %d\n", __func__, plat->clock); } plat->type = dev_get_driver_data(dev); plat->skip_init = dev_read_bool(dev, "skip-init"); diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index 348630faf38..47a5571aecd 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -214,7 +214,7 @@ static void xilinx_spi_startup_block(struct udevice *dev, unsigned int bytes, struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); const unsigned char *txp = dout; unsigned char *rxp = din; - u32 reg, count; + u32 reg; u32 txbytes = bytes; u32 rxbytes = bytes; @@ -224,10 +224,10 @@ static void xilinx_spi_startup_block(struct udevice *dev, unsigned int bytes, * it sets txp to the initial value for the normal operation. */ for ( ; priv->startup < 2; priv->startup++) { - count = xilinx_spi_fill_txfifo(bus, txp, txbytes); + xilinx_spi_fill_txfifo(bus, txp, txbytes); reg = readl(®s->spicr) & ~SPICR_MASTER_INHIBIT; writel(reg, ®s->spicr); - count = xilinx_spi_read_rxfifo(bus, rxp, rxbytes); + xilinx_spi_read_rxfifo(bus, rxp, rxbytes); txp = din; if (priv->startup) { @@ -251,7 +251,7 @@ static int xilinx_spi_xfer(struct udevice *dev, unsigned int bitlen, unsigned char *rxp = din; u32 txbytes = bytes; u32 rxbytes = bytes; - u32 reg, count, timeout; + u32 reg, count; int ret; debug("spi_xfer: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", diff --git a/drivers/spi/zynq_qspi.c b/drivers/spi/zynq_qspi.c index 3f39ef05f2d..f2eddec950a 100644 --- a/drivers/spi/zynq_qspi.c +++ b/drivers/spi/zynq_qspi.c @@ -6,8 +6,10 @@ * Xilinx Zynq Quad-SPI(QSPI) controller driver (master mode only) */ +#include <clk.h> #include <common.h> #include <dm.h> +#include <dm/device_compat.h> #include <log.h> #include <malloc.h> #include <spi.h> @@ -105,17 +107,29 @@ static int zynq_qspi_ofdata_to_platdata(struct udevice *bus) plat->regs = (struct zynq_qspi_regs *)fdtdec_get_addr(blob, node, "reg"); - /* FIXME: Use 166MHz as a suitable default */ - plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", - 166666666); - plat->speed_hz = plat->frequency / 2; - - debug("%s: regs=%p max-frequency=%d\n", __func__, - plat->regs, plat->frequency); - return 0; } +/** + * zynq_qspi_init_hw - Initialize the hardware + * @priv: Pointer to the zynq_qspi_priv structure + * + * The default settings of the QSPI controller's configurable parameters on + * reset are + * - Master mode + * - Baud rate divisor is set to 2 + * - Threshold value for TX FIFO not full interrupt is set to 1 + * - Flash memory interface mode enabled + * - Size of the word to be transferred as 8 bit + * This function performs the following actions + * - Disable and clear all the interrupts + * - Enable manual slave select + * - Enable auto start + * - Deselect all the chip select lines + * - Set the size of the word to be transferred as 32 bit + * - Set the little endian mode of TX FIFO and + * - Enable the QSPI controller + */ static void zynq_qspi_init_hw(struct zynq_qspi_priv *priv) { struct zynq_qspi_regs *regs = priv->regs; @@ -159,19 +173,45 @@ static int zynq_qspi_probe(struct udevice *bus) { struct zynq_qspi_platdata *plat = dev_get_platdata(bus); struct zynq_qspi_priv *priv = dev_get_priv(bus); + struct clk clk; + unsigned long clock; + int ret; priv->regs = plat->regs; priv->fifo_depth = ZYNQ_QSPI_FIFO_DEPTH; + ret = clk_get_by_name(bus, "ref_clk", &clk); + if (ret < 0) { + dev_err(bus, "failed to get clock\n"); + return ret; + } + + clock = clk_get_rate(&clk); + if (IS_ERR_VALUE(clock)) { + dev_err(bus, "failed to get rate\n"); + return clock; + } + + ret = clk_enable(&clk); + if (ret && ret != -ENOSYS) { + dev_err(bus, "failed to enable clock\n"); + return ret; + } + /* init the zynq spi hw */ zynq_qspi_init_hw(priv); + plat->frequency = clock; + plat->speed_hz = plat->frequency / 2; + + debug("%s: max-frequency=%d\n", __func__, plat->speed_hz); + return 0; } -/* +/** * zynq_qspi_read_data - Copy data to RX buffer - * @zqspi: Pointer to the zynq_qspi structure + * @priv: Pointer to the zynq_qspi_priv structure * @data: The 32 bit variable where data is stored * @size: Number of bytes to be copied from data to RX buffer */ @@ -214,9 +254,9 @@ static void zynq_qspi_read_data(struct zynq_qspi_priv *priv, u32 data, u8 size) priv->bytes_to_receive = 0; } -/* +/** * zynq_qspi_write_data - Copy data from TX buffer - * @zqspi: Pointer to the zynq_qspi structure + * @priv: Pointer to the zynq_qspi_priv structure * @data: Pointer to the 32 bit variable where data is to be copied * @size: Number of bytes to be copied from TX buffer to data */ @@ -263,6 +303,11 @@ static void zynq_qspi_write_data(struct zynq_qspi_priv *priv, priv->bytes_to_transfer = 0; } +/** + * zynq_qspi_chipselect - Select or deselect the chip select line + * @priv: Pointer to the zynq_qspi_priv structure + * @is_on: Select(1) or deselect (0) the chip select line + */ static void zynq_qspi_chipselect(struct zynq_qspi_priv *priv, int is_on) { u32 confr; @@ -282,9 +327,10 @@ static void zynq_qspi_chipselect(struct zynq_qspi_priv *priv, int is_on) writel(confr, ®s->cr); } -/* +/** * zynq_qspi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible - * @zqspi: Pointer to the zynq_qspi structure + * @priv: Pointer to the zynq_qspi_priv structure + * @size: Number of bytes to be copied to fifo */ static void zynq_qspi_fill_tx_fifo(struct zynq_qspi_priv *priv, u32 size) { @@ -322,9 +368,9 @@ static void zynq_qspi_fill_tx_fifo(struct zynq_qspi_priv *priv, u32 size) } } -/* +/** * zynq_qspi_irq_poll - Interrupt service routine of the QSPI controller - * @zqspi: Pointer to the zynq_qspi structure + * @priv: Pointer to the zynq_qspi structure * * This function handles TX empty and Mode Fault interrupts only. * On TX empty interrupt this function reads the received data from RX FIFO and @@ -410,11 +456,9 @@ static int zynq_qspi_irq_poll(struct zynq_qspi_priv *priv) return 0; } -/* +/** * zynq_qspi_start_transfer - Initiates the QSPI transfer - * @qspi: Pointer to the spi_device structure - * @transfer: Pointer to the spi_transfer structure which provide information - * about next transfer parameters + * @priv: Pointer to the zynq_qspi_priv structure * * This function fills the TX FIFO, starts the QSPI transfer, and waits for the * transfer to be completed. diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c index 9923931e36e..cb911c34f68 100644 --- a/drivers/spi/zynq_spi.c +++ b/drivers/spi/zynq_spi.c @@ -8,10 +8,12 @@ #include <common.h> #include <dm.h> +#include <dm/device_compat.h> #include <log.h> #include <malloc.h> #include <spi.h> #include <time.h> +#include <clk.h> #include <asm/io.h> #include <linux/bitops.h> #include <linux/delay.h> @@ -79,17 +81,10 @@ static int zynq_spi_ofdata_to_platdata(struct udevice *bus) plat->regs = dev_read_addr_ptr(bus); - /* FIXME: Use 250MHz as a suitable default */ - plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", - 250000000); plat->deactivate_delay_us = fdtdec_get_int(blob, node, "spi-deactivate-delay", 0); plat->activate_delay_us = fdtdec_get_int(blob, node, "spi-activate-delay", 0); - plat->speed_hz = plat->frequency / 2; - - debug("%s: regs=%p max-frequency=%d\n", __func__, - plat->regs, plat->frequency); return 0; } @@ -128,13 +123,39 @@ static int zynq_spi_probe(struct udevice *bus) { struct zynq_spi_platdata *plat = dev_get_platdata(bus); struct zynq_spi_priv *priv = dev_get_priv(bus); + struct clk clk; + unsigned long clock; + int ret; priv->regs = plat->regs; priv->fifo_depth = ZYNQ_SPI_FIFO_DEPTH; + ret = clk_get_by_name(bus, "ref_clk", &clk); + if (ret < 0) { + dev_err(bus, "failed to get clock\n"); + return ret; + } + + clock = clk_get_rate(&clk); + if (IS_ERR_VALUE(clock)) { + dev_err(bus, "failed to get rate\n"); + return clock; + } + + ret = clk_enable(&clk); + if (ret && ret != -ENOSYS) { + dev_err(bus, "failed to enable clock\n"); + return ret; + } + /* init the zynq spi hw */ zynq_spi_init_hw(priv); + plat->frequency = clock; + plat->speed_hz = plat->frequency / 2; + + debug("%s: max-frequency=%d\n", __func__, plat->speed_hz); + return 0; } diff --git a/env/Kconfig b/env/Kconfig index aa63fae021e..67ce93061b7 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -376,6 +376,14 @@ config ENV_SPI_MODE Value of the SPI work mode for environment. See include/spi.h for value. +config ENV_SPI_EARLY + bool "Access Environment in SPI flashes before relocation" + depends on ENV_IS_IN_SPI_FLASH + help + Enable this if you want to use Environment in SPI flash + before relocation. Call env_init() and than you can use + env_get_f() for accessing Environment variables. + config ENV_IS_IN_UBI bool "Environment in a UBI volume" depends on !CHAIN_OF_TRUST diff --git a/env/common.c b/env/common.c index ed18378000f..6c32a9b4796 100644 --- a/env/common.c +++ b/env/common.c @@ -141,12 +141,11 @@ int env_import(const char *buf, int check, int flags) #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT static unsigned char env_flags; -int env_import_redund(const char *buf1, int buf1_read_fail, - const char *buf2, int buf2_read_fail, - int flags) +int env_check_redund(const char *buf1, int buf1_read_fail, + const char *buf2, int buf2_read_fail) { int crc1_ok, crc2_ok; - env_t *ep, *tmp_env1, *tmp_env2; + env_t *tmp_env1, *tmp_env2; tmp_env1 = (env_t *)buf1; tmp_env2 = (env_t *)buf2; @@ -159,14 +158,13 @@ int env_import_redund(const char *buf1, int buf1_read_fail, } if (buf1_read_fail && buf2_read_fail) { - env_set_default("bad env area", 0); return -EIO; } else if (!buf1_read_fail && buf2_read_fail) { gd->env_valid = ENV_VALID; - return env_import((char *)tmp_env1, 1, flags); + return -EINVAL; } else if (buf1_read_fail && !buf2_read_fail) { gd->env_valid = ENV_REDUND; - return env_import((char *)tmp_env2, 1, flags); + return -ENOENT; } crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) == @@ -175,7 +173,6 @@ int env_import_redund(const char *buf1, int buf1_read_fail, tmp_env2->crc; if (!crc1_ok && !crc2_ok) { - env_set_default("bad CRC", 0); return -ENOMSG; /* needed for env_load() */ } else if (crc1_ok && !crc2_ok) { gd->env_valid = ENV_VALID; @@ -195,12 +192,37 @@ int env_import_redund(const char *buf1, int buf1_read_fail, gd->env_valid = ENV_VALID; } + return 0; +} + +int env_import_redund(const char *buf1, int buf1_read_fail, + const char *buf2, int buf2_read_fail, + int flags) +{ + env_t *ep; + int ret; + + ret = env_check_redund(buf1, buf1_read_fail, buf2, buf2_read_fail); + + if (ret == -EIO) { + env_set_default("bad env area", 0); + return -EIO; + } else if (ret == -EINVAL) { + return env_import((char *)buf1, 1, flags); + } else if (ret == -ENOENT) { + return env_import((char *)buf2, 1, flags); + } else if (ret == -ENOMSG) { + env_set_default("bad CRC", 0); + return -ENOMSG; + } + if (gd->env_valid == ENV_VALID) - ep = tmp_env1; + ep = (env_t *)buf1; else - ep = tmp_env2; + ep = (env_t *)buf2; env_flags = ep->flags; + return env_import((char *)ep, 0, flags); } #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */ @@ -287,7 +287,10 @@ __weak void *env_sf_get_env_addr(void) #endif #if defined(INITENV) && (CONFIG_ENV_ADDR != 0x0) -static int env_sf_init(void) +/* + * check if Environment on CONFIG_ENV_ADDR is valid. + */ +static int env_sf_init_addr(void) { env_t *env_ptr = (env_t *)env_sf_get_env_addr(); @@ -303,12 +306,103 @@ static int env_sf_init(void) } #endif +#if defined(CONFIG_ENV_SPI_EARLY) +/* + * early load environment from SPI flash (before relocation) + * and check if it is valid. + */ +static int env_sf_init_early(void) +{ + int ret; + int read1_fail; + int read2_fail; + int crc1_ok; + env_t *tmp_env2 = NULL; + env_t *tmp_env1; + + /* + * if malloc is not ready yet, we cannot use + * this part yet. + */ + if (!gd->malloc_limit) + return -ENOENT; + + tmp_env1 = (env_t *)memalign(ARCH_DMA_MINALIGN, + CONFIG_ENV_SIZE); + if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT)) + tmp_env2 = (env_t *)memalign(ARCH_DMA_MINALIGN, + CONFIG_ENV_SIZE); + + if (!tmp_env1 || !tmp_env2) + goto out; + + ret = setup_flash_device(); + if (ret) + goto out; + + read1_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET, + CONFIG_ENV_SIZE, tmp_env1); + + if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT)) { + read2_fail = spi_flash_read(env_flash, + CONFIG_ENV_OFFSET_REDUND, + CONFIG_ENV_SIZE, tmp_env2); + ret = env_check_redund((char *)tmp_env1, read1_fail, + (char *)tmp_env2, read2_fail); + + if (ret == -EIO || ret == -ENOMSG) + goto err_read; + + if (gd->env_valid == ENV_VALID) + gd->env_addr = (unsigned long)&tmp_env1->data; + else + gd->env_addr = (unsigned long)&tmp_env2->data; + } else { + if (read1_fail) + goto err_read; + + crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) == + tmp_env1->crc; + if (!crc1_ok) + goto err_read; + + /* if valid -> this is our env */ + gd->env_valid = ENV_VALID; + gd->env_addr = (unsigned long)&tmp_env1->data; + } + + return 0; +err_read: + spi_flash_free(env_flash); + env_flash = NULL; + free(tmp_env1); + if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT)) + free(tmp_env2); +out: + /* env is not valid. always return 0 */ + gd->env_valid = ENV_INVALID; + return 0; +} +#endif + +static int env_sf_init(void) +{ +#if defined(INITENV) && (CONFIG_ENV_ADDR != 0x0) + return env_sf_init_addr(); +#elif defined(CONFIG_ENV_SPI_EARLY) + return env_sf_init_early(); +#endif + /* + * we must return with 0 if there is nothing done, + * else env_set_inited() get not called in env_init() + */ + return 0; +} + U_BOOT_ENV_LOCATION(sf) = { .location = ENVL_SPI_FLASH, ENV_NAME("SPIFlash") .load = env_sf_load, .save = CONFIG_IS_ENABLED(SAVEENV) ? ENV_SAVE_PTR(env_sf_save) : NULL, -#if defined(INITENV) && (CONFIG_ENV_ADDR != 0x0) .init = env_sf_init, -#endif }; diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 0aa11441848..f3920437968 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -384,7 +384,7 @@ struct global_data { */ int logc_prev; /** - * @logl_pref: logging level of the previous message + * @logl_prev: logging level of the previous message * * This value is used as logging level for continuation messages. */ diff --git a/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h index 8ca0e83c783..2b412423508 100644 --- a/include/configs/microblaze-generic.h +++ b/include/configs/microblaze-generic.h @@ -125,21 +125,67 @@ #define CONFIG_SYS_LOAD_ADDR 0 #define CONFIG_HOSTNAME "microblaze-generic" -#define CONFIG_BOOTCOMMAND "base 0;tftp 11000000 image.img;bootm" /* architecture dependent code */ #define CONFIG_SYS_USR_EXCEP /* user exception */ +#if defined(CONFIG_CMD_PXE) && defined(CONFIG_CMD_DHCP) +#define BOOT_TARGET_DEVICES_PXE(func) func(PXE, pxe, na) +#else +#define BOOT_TARGET_DEVICES_PXE(func) +#endif + +#if defined(CONFIG_CMD_DHCP) +#define BOOT_TARGET_DEVICES_DHCP(func) func(DHCP, dhcp, na) +#else +#define BOOT_TARGET_DEVICES_DHCP(func) +#endif + +#if defined(CONFIG_SPI_FLASH) +# define BOOT_TARGET_DEVICES_QSPI(func) func(QSPI, qspi, na) +#else +# define BOOT_TARGET_DEVICES_QSPI(func) +#endif + +#define BOOTENV_DEV_QSPI(devtypeu, devtypel, instance) \ + "bootcmd_qspi=sf probe 0 0 0 && " \ + "sf read ${scriptaddr} ${script_offset_f} ${script_size_f} && " \ + "echo QSPI: Trying to boot script at ${scriptaddr} && " \ + "source ${scriptaddr}; echo QSPI: SCRIPT FAILED: continuing...;\0" + +#define BOOTENV_DEV_NAME_QSPI(devtypeu, devtypel, instance) \ + "qspi " + +#define BOOT_TARGET_DEVICES_JTAG(func) func(JTAG, jtag, na) + +#define BOOTENV_DEV_JTAG(devtypeu, devtypel, instance) \ + "bootcmd_jtag=echo JTAG: Trying to boot script at ${scriptaddr} && " \ + "source ${scriptaddr}; echo JTAG: SCRIPT FAILED: continuing...;\0" + +#define BOOTENV_DEV_NAME_JTAG(devtypeu, devtypel, instance) \ + "jtag " + +#define BOOT_TARGET_DEVICES(func) \ + BOOT_TARGET_DEVICES_JTAG(func) \ + BOOT_TARGET_DEVICES_QSPI(func) \ + BOOT_TARGET_DEVICES_DHCP(func) \ + BOOT_TARGET_DEVICES_PXE(func) + +#include <config_distro_bootcmd.h> + #ifndef CONFIG_EXTRA_ENV_SETTINGS -#define CONFIG_EXTRA_ENV_SETTINGS "unlock=yes\0" \ - "nor0=flash-0\0"\ - "mtdparts=mtdparts=flash-0:"\ - "256k(u-boot),256k(env),3m(kernel),"\ - "1m(romfs),1m(cramfs),-(jffs2)\0"\ - "nc=setenv stdout nc;"\ - "setenv stdin nc\0" \ - "serial=setenv stdout serial;"\ - "setenv stdin serial\0" +#define CONFIG_EXTRA_ENV_SETTINGS \ + "unlock=yes\0"\ + "nor0=flash-0\0"\ + "mtdparts=mtdparts=flash-0:"\ + "256k(u-boot),256k(env),3m(kernel),"\ + "1m(romfs),1m(cramfs),-(jffs2)\0"\ + "nc=setenv stdout nc;"\ + "setenv stdin nc\0" \ + "serial=setenv stdout serial;"\ + "setenv stdin serial\0"\ + "script_size_f=0x40000\0"\ + BOOTENV #endif #if defined(CONFIG_XILINX_AXIEMAC) @@ -167,8 +213,7 @@ #define CONFIG_SYS_INIT_RAM_SIZE 0x100000 # define CONFIG_SPL_STACK_ADDR (CONFIG_SYS_INIT_RAM_ADDR + \ - CONFIG_SYS_INIT_RAM_SIZE - \ - CONFIG_SYS_MALLOC_F_LEN) + CONFIG_SYS_INIT_RAM_SIZE) /* Just for sure that there is a space for stack */ #define CONFIG_SPL_STACK_SIZE 0x100 diff --git a/include/configs/xilinx_versal.h b/include/configs/xilinx_versal.h index 8b416327b57..f1d2594f3b3 100644 --- a/include/configs/xilinx_versal.h +++ b/include/configs/xilinx_versal.h @@ -18,7 +18,6 @@ #define GICD_BASE 0xF9000000 #define GICR_BASE 0xF9080000 - #define CONFIG_SYS_INIT_SP_ADDR CONFIG_SYS_TEXT_BASE /* Generic Timer Definitions - setup in EL3. Setup by ATF for other cases */ diff --git a/include/configs/xilinx_versal_mini.h b/include/configs/xilinx_versal_mini.h index 0b201a2b4d6..00c97188198 100644 --- a/include/configs/xilinx_versal_mini.h +++ b/include/configs/xilinx_versal_mini.h @@ -10,7 +10,6 @@ #ifndef __CONFIG_VERSAL_MINI_H #define __CONFIG_VERSAL_MINI_H - #define CONFIG_EXTRA_ENV_SETTINGS #include <configs/xilinx_versal.h> diff --git a/include/configs/xilinx_zynqmp_mini.h b/include/configs/xilinx_zynqmp_mini.h index 3f57423b789..ef9c768e48e 100644 --- a/include/configs/xilinx_zynqmp_mini.h +++ b/include/configs/xilinx_zynqmp_mini.h @@ -10,7 +10,6 @@ #ifndef __CONFIG_ZYNQMP_MINI_H #define __CONFIG_ZYNQMP_MINI_H - #define CONFIG_EXTRA_ENV_SETTINGS #include <configs/xilinx_zynqmp.h> diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 4b7af370560..ced7f6ffb25 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -605,6 +605,28 @@ const char *ofnode_read_chosen_string(const char *propname); */ ofnode ofnode_get_chosen_node(const char *propname); +/** + * ofnode_read_aliases_prop() - get the value of a aliases property + * + * This looks for a property within the /aliases node and returns its value + * + * @propname: Property name to look for + * @sizep: Returns size of property, or FDT_ERR_... error code if function + * returns NULL + * @return property value if found, else NULL + */ +const void *ofnode_read_aliases_prop(const char *propname, int *sizep); + +/** + * ofnode_get_aliases_node() - get a referenced node from the aliases node + * + * This looks up a named property in the aliases node and uses that as a path to + * look up a code. + * + * @return the referenced node if present, else ofnode_null() + */ +ofnode ofnode_get_aliases_node(const char *propname); + struct display_timing; /** * ofnode_decode_display_timing() - decode display timings diff --git a/include/dt-bindings/clock/xlnx-versal-clk.h b/include/dt-bindings/clock/xlnx-versal-clk.h new file mode 100644 index 00000000000..264d634d226 --- /dev/null +++ b/include/dt-bindings/clock/xlnx-versal-clk.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019 Xilinx Inc. + * + */ + +#ifndef _DT_BINDINGS_CLK_VERSAL_H +#define _DT_BINDINGS_CLK_VERSAL_H + +#define PMC_PLL 1 +#define APU_PLL 2 +#define RPU_PLL 3 +#define CPM_PLL 4 +#define NOC_PLL 5 +#define PLL_MAX 6 +#define PMC_PRESRC 7 +#define PMC_POSTCLK 8 +#define PMC_PLL_OUT 9 +#define PPLL 10 +#define NOC_PRESRC 11 +#define NOC_POSTCLK 12 +#define NOC_PLL_OUT 13 +#define NPLL 14 +#define APU_PRESRC 15 +#define APU_POSTCLK 16 +#define APU_PLL_OUT 17 +#define APLL 18 +#define RPU_PRESRC 19 +#define RPU_POSTCLK 20 +#define RPU_PLL_OUT 21 +#define RPLL 22 +#define CPM_PRESRC 23 +#define CPM_POSTCLK 24 +#define CPM_PLL_OUT 25 +#define CPLL 26 +#define PPLL_TO_XPD 27 +#define NPLL_TO_XPD 28 +#define APLL_TO_XPD 29 +#define RPLL_TO_XPD 30 +#define EFUSE_REF 31 +#define SYSMON_REF 32 +#define IRO_SUSPEND_REF 33 +#define USB_SUSPEND 34 +#define SWITCH_TIMEOUT 35 +#define RCLK_PMC 36 +#define RCLK_LPD 37 +#define WDT 38 +#define TTC0 39 +#define TTC1 40 +#define TTC2 41 +#define TTC3 42 +#define GEM_TSU 43 +#define GEM_TSU_LB 44 +#define MUXED_IRO_DIV2 45 +#define MUXED_IRO_DIV4 46 +#define PSM_REF 47 +#define GEM0_RX 48 +#define GEM0_TX 49 +#define GEM1_RX 50 +#define GEM1_TX 51 +#define CPM_CORE_REF 52 +#define CPM_LSBUS_REF 53 +#define CPM_DBG_REF 54 +#define CPM_AUX0_REF 55 +#define CPM_AUX1_REF 56 +#define QSPI_REF 57 +#define OSPI_REF 58 +#define SDIO0_REF 59 +#define SDIO1_REF 60 +#define PMC_LSBUS_REF 61 +#define I2C_REF 62 +#define TEST_PATTERN_REF 63 +#define DFT_OSC_REF 64 +#define PMC_PL0_REF 65 +#define PMC_PL1_REF 66 +#define PMC_PL2_REF 67 +#define PMC_PL3_REF 68 +#define CFU_REF 69 +#define SPARE_REF 70 +#define NPI_REF 71 +#define HSM0_REF 72 +#define HSM1_REF 73 +#define SD_DLL_REF 74 +#define FPD_TOP_SWITCH 75 +#define FPD_LSBUS 76 +#define ACPU 77 +#define DBG_TRACE 78 +#define DBG_FPD 79 +#define LPD_TOP_SWITCH 80 +#define ADMA 81 +#define LPD_LSBUS 82 +#define CPU_R5 83 +#define CPU_R5_CORE 84 +#define CPU_R5_OCM 85 +#define CPU_R5_OCM2 86 +#define IOU_SWITCH 87 +#define GEM0_REF 88 +#define GEM1_REF 89 +#define GEM_TSU_REF 90 +#define USB0_BUS_REF 91 +#define UART0_REF 92 +#define UART1_REF 93 +#define SPI0_REF 94 +#define SPI1_REF 95 +#define CAN0_REF 96 +#define CAN1_REF 97 +#define I2C0_REF 98 +#define I2C1_REF 99 +#define DBG_LPD 100 +#define TIMESTAMP_REF 101 +#define DBG_TSTMP 102 +#define CPM_TOPSW_REF 103 +#define USB3_DUAL_REF 104 +#define OUTCLK_MAX 105 +#define REF_CLK 106 +#define PL_ALT_REF_CLK 107 +#define MUXED_IRO 108 +#define PL_EXT 109 +#define PL_LB 110 +#define MIO_50_OR_51 111 +#define MIO_24_OR_25 112 + +#endif diff --git a/include/dt-bindings/power/xlnx-versal-power.h b/include/dt-bindings/power/xlnx-versal-power.h new file mode 100644 index 00000000000..1b75175edce --- /dev/null +++ b/include/dt-bindings/power/xlnx-versal-power.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019 - 2020 Xilinx, Inc. + */ + +#ifndef _DT_BINDINGS_VERSAL_POWER_H +#define _DT_BINDINGS_VERSAL_POWER_H + +#define PM_DEV_USB_0 (0x18224018U) +#define PM_DEV_GEM_0 (0x18224019U) +#define PM_DEV_GEM_1 (0x1822401aU) +#define PM_DEV_SPI_0 (0x1822401bU) +#define PM_DEV_SPI_1 (0x1822401cU) +#define PM_DEV_I2C_0 (0x1822401dU) +#define PM_DEV_I2C_1 (0x1822401eU) +#define PM_DEV_CAN_FD_0 (0x1822401fU) +#define PM_DEV_CAN_FD_1 (0x18224020U) +#define PM_DEV_UART_0 (0x18224021U) +#define PM_DEV_UART_1 (0x18224022U) +#define PM_DEV_GPIO (0x18224023U) +#define PM_DEV_TTC_0 (0x18224024U) +#define PM_DEV_TTC_1 (0x18224025U) +#define PM_DEV_TTC_2 (0x18224026U) +#define PM_DEV_TTC_3 (0x18224027U) +#define PM_DEV_SWDT_FPD (0x18224029U) +#define PM_DEV_OSPI (0x1822402aU) +#define PM_DEV_QSPI (0x1822402bU) +#define PM_DEV_GPIO_PMC (0x1822402cU) +#define PM_DEV_SDIO_0 (0x1822402eU) +#define PM_DEV_SDIO_1 (0x1822402fU) +#define PM_DEV_RTC (0x18224034U) +#define PM_DEV_ADMA_0 (0x18224035U) +#define PM_DEV_ADMA_1 (0x18224036U) +#define PM_DEV_ADMA_2 (0x18224037U) +#define PM_DEV_ADMA_3 (0x18224038U) +#define PM_DEV_ADMA_4 (0x18224039U) +#define PM_DEV_ADMA_5 (0x1822403aU) +#define PM_DEV_ADMA_6 (0x1822403bU) +#define PM_DEV_ADMA_7 (0x1822403cU) +#define PM_DEV_AI (0x18224072U) + +#endif diff --git a/include/env.h b/include/env.h index af405955b0f..c15339a93f1 100644 --- a/include/env.h +++ b/include/env.h @@ -319,6 +319,24 @@ int env_import(const char *buf, int check, int flags); int env_export(struct environment_s *env_out); /** + * env_check_redund() - check the two redundant environments + * and find out, which is the valid one. + * + * @buf1: First environment (struct environemnt_s *) + * @buf1_read_fail: 0 if buf1 is valid, non-zero if invalid + * @buf2: Second environment (struct environemnt_s *) + * @buf2_read_fail: 0 if buf2 is valid, non-zero if invalid + * @return 0 if OK, + * -EIO if no environment is valid, + * -EINVAL if read of second entry is good + * -ENOENT if read of first entry is good + * -ENOMSG if the CRC was bad + */ + +int env_check_redund(const char *buf1, int buf1_read_fail, + const char *buf2, int buf2_read_fail); + +/** * env_import_redund() - Select and import one of two redundant environments * * @buf1: First environment (struct environemnt_s *) diff --git a/include/getopt.h b/include/getopt.h new file mode 100644 index 00000000000..6f5811e64be --- /dev/null +++ b/include/getopt.h @@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * getopt.h - a simple getopt(3) implementation. + * + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com> + * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + */ + +#ifndef __GETOPT_H +#define __GETOPT_H + +/** + * struct getopt_state - Saved state across getopt() calls + */ +struct getopt_state { + /** + * @index: Index of the next unparsed argument of @argv. If getopt() has + * parsed all of @argv, then @index will equal @argc. + */ + int index; + /* private: */ + /** @arg_index: Index within the current argument */ + int arg_index; + union { + /* public: */ + /** + * @opt: Option being parsed when an error occurs. @opt is only + * valid when getopt() returns ``?`` or ``:``. + */ + int opt; + /** + * @arg: The argument to an option, NULL if there is none. @arg + * is only valid when getopt() returns an option character. + */ + char *arg; + /* private: */ + }; +}; + +/** + * getopt_init_state() - Initialize a &struct getopt_state + * @gs: The state to initialize + * + * This must be called before using @gs with getopt(). + */ +void getopt_init_state(struct getopt_state *gs); + +int __getopt(struct getopt_state *gs, int argc, char *const argv[], + const char *optstring, bool silent); + +/** + * getopt() - Parse short command-line options + * @gs: Internal state and out-of-band return arguments. This must be + * initialized with getopt_init_context() beforehand. + * @argc: Number of arguments, not including the %NULL terminator + * @argv: Argument list, terminated by %NULL + * @optstring: Option specification, as described below + * + * getopt() parses short options. Short options are single characters. They may + * be followed by a required argument or an optional argument. Arguments to + * options may occur in the same argument as an option (like ``-larg``), or + * in the following argument (like ``-l arg``). An argument containing + * options begins with a ``-``. If an option expects no arguments, then it may + * be immediately followed by another option (like ``ls -alR``). + * + * @optstring is a list of accepted options. If an option is followed by ``:`` + * in @optstring, then it expects a mandatory argument. If an option is followed + * by ``::`` in @optstring, it expects an optional argument. @gs.arg points + * to the argument, if one is parsed. + * + * getopt() stops parsing options when it encounters the first non-option + * argument, when it encounters the argument ``--``, or when it runs out of + * arguments. For example, in ``ls -l foo -R``, option parsing will stop when + * getopt() encounters ``foo``, if ``l`` does not expect an argument. However, + * the whole list of arguments would be parsed if ``l`` expects an argument. + * + * An example invocation of getopt() might look like:: + * + * char *argv[] = { "program", "-cbx", "-a", "foo", "bar", 0 }; + * int opt, argc = ARRAY_SIZE(argv) - 1; + * struct getopt_state gs; + * + * getopt_init_state(&gs); + * while ((opt = getopt(&gs, argc, argv, "a::b:c")) != -1) + * printf("opt = %c, index = %d, arg = \"%s\"\n", opt, gs.index, gs.arg); + * printf("%d argument(s) left\n", argc - gs.index); + * + * and would produce an output of:: + * + * opt = c, index = 1, arg = "<NULL>" + * opt = b, index = 2, arg = "x" + * opt = a, index = 4, arg = "foo" + * 1 argument(s) left + * + * For further information, refer to the getopt(3) man page. + * + * Return: + * * An option character if an option is found. @gs.arg is set to the + * argument if there is one, otherwise it is set to ``NULL``. + * * ``-1`` if there are no more options, if a non-option argument is + * encountered, or if an ``--`` argument is encountered. + * * ``'?'`` if we encounter an option not in @optstring. @gs.opt is set to + * the unknown option. + * * ``':'`` if an argument is required, but no argument follows the + * option. @gs.opt is set to the option missing its argument. + * + * @gs.index is always set to the index of the next unparsed argument in @argv. + */ +static inline int getopt(struct getopt_state *gs, int argc, + char *const argv[], const char *optstring) +{ + return __getopt(gs, argc, argv, optstring, false); +} + +/** + * getopt_silent() - Parse short command-line options silently + * @gs: State + * @argc: Argument count + * @argv: Argument list + * @optstring: Option specification + * + * Same as getopt(), except no error messages are printed. + */ +static inline int getopt_silent(struct getopt_state *gs, int argc, + char *const argv[], const char *optstring) +{ + return __getopt(gs, argc, argv, optstring, true); +} + +#endif /* __GETOPT_H */ diff --git a/include/log.h b/include/log.h index 58787a35324..4d0692f155d 100644 --- a/include/log.h +++ b/include/log.h @@ -17,56 +17,92 @@ struct cmd_tbl; -/** Log levels supported, ranging from most to least important */ +/** + * enum log_level_t - Log levels supported, ranging from most to least important + */ enum log_level_t { - LOGL_EMERG = 0, /* U-Boot is unstable */ - LOGL_ALERT, /* Action must be taken immediately */ - LOGL_CRIT, /* Critical conditions */ - LOGL_ERR, /* Error that prevents something from working */ - LOGL_WARNING, /* Warning may prevent optimial operation */ - LOGL_NOTICE, /* Normal but significant condition, printf() */ - LOGL_INFO, /* General information message */ - LOGL_DEBUG, /* Basic debug-level message */ - LOGL_DEBUG_CONTENT, /* Debug message showing full message content */ - LOGL_DEBUG_IO, /* Debug message showing hardware I/O access */ - + /** @LOGL_EMERG: U-Boot is unstable */ + LOGL_EMERG = 0, + /** @LOGL_ALERT: Action must be taken immediately */ + LOGL_ALERT, + /** @LOGL_CRIT: Critical conditions */ + LOGL_CRIT, + /** @LOGL_ERR: Error that prevents something from working */ + LOGL_ERR, + /** @LOGL_WARNING: Warning may prevent optimial operation */ + LOGL_WARNING, + /** @LOGL_NOTICE: Normal but significant condition, printf() */ + LOGL_NOTICE, + /** @LOGL_INFO: General information message */ + LOGL_INFO, + /** @LOGL_DEBUG: Basic debug-level message */ + LOGL_DEBUG, + /** @LOGL_DEBUG_CONTENT: Debug message showing full message content */ + LOGL_DEBUG_CONTENT, + /** @LOGL_DEBUG_IO: Debug message showing hardware I/O access */ + LOGL_DEBUG_IO, + + /** @LOGL_COUNT: Total number of valid log levels */ LOGL_COUNT, + /** @LOGL_NONE: Used to indicate that there is no valid log level */ LOGL_NONE, - LOGL_LEVEL_MASK = 0xf, /* Mask for valid log levels */ - LOGL_FORCE_DEBUG = 0x10, /* Mask to force output due to LOG_DEBUG */ + /** @LOGL_LEVEL_MASK: Mask for valid log levels */ + LOGL_LEVEL_MASK = 0xf, + /** @LOGL_FORCE_DEBUG: Mask to force output due to LOG_DEBUG */ + LOGL_FORCE_DEBUG = 0x10, + /** @LOGL_FIRST: The first, most-important log level */ LOGL_FIRST = LOGL_EMERG, + /** @LOGL_MAX: The last, least-important log level */ LOGL_MAX = LOGL_DEBUG_IO, - LOGL_CONT = -1, /* Use same log level as in previous call */ + /** @LOGL_CONT: Use same log level as in previous call */ + LOGL_CONT = -1, }; /** - * Log categories supported. Most of these correspond to uclasses (i.e. - * enum uclass_id) but there are also some more generic categories. + * enum log_category_t - Log categories supported. + * + * Log categories between %LOGC_FIRST and %LOGC_NONE correspond to uclasses + * (i.e. &enum uclass_id), but there are also some more generic categories. * * Remember to update log_cat_name[] after adding a new category. */ enum log_category_t { + /** @LOGC_FIRST: First log category */ LOGC_FIRST = 0, /* First part mirrors UCLASS_... */ + /** @LOGC_NONE: Default log category */ LOGC_NONE = UCLASS_COUNT, /* First number is after all uclasses */ - LOGC_ARCH, /* Related to arch-specific code */ - LOGC_BOARD, /* Related to board-specific code */ - LOGC_CORE, /* Related to core features (non-driver-model) */ - LOGC_DM, /* Core driver-model */ - LOGC_DT, /* Device-tree */ - LOGC_EFI, /* EFI implementation */ - LOGC_ALLOC, /* Memory allocation */ - LOGC_SANDBOX, /* Related to the sandbox board */ - LOGC_BLOBLIST, /* Bloblist */ - LOGC_DEVRES, /* Device resources (devres_... functions) */ - /* Advanced Configuration and Power Interface (ACPI) */ + /** @LOGC_ARCH: Related to arch-specific code */ + LOGC_ARCH, + /** @LOGC_BOARD: Related to board-specific code */ + LOGC_BOARD, + /** @LOGC_CORE: Related to core features (non-driver-model) */ + LOGC_CORE, + /** @LOGC_DM: Core driver-model */ + LOGC_DM, + /** @LOGC_DT: Device-tree */ + LOGC_DT, + /** @LOGC_EFI: EFI implementation */ + LOGC_EFI, + /** @LOGC_ALLOC: Memory allocation */ + LOGC_ALLOC, + /** @LOGC_SANDBOX: Related to the sandbox board */ + LOGC_SANDBOX, + /** @LOGC_BLOBLIST: Bloblist */ + LOGC_BLOBLIST, + /** @LOGC_DEVRES: Device resources (``devres_...`` functions) */ + LOGC_DEVRES, + /** @LOGC_ACPI: Advanced Configuration and Power Interface (ACPI) */ LOGC_ACPI, - LOGC_COUNT, /* Number of log categories */ - LOGC_END, /* Sentinel value for a list of log categories */ - LOGC_CONT = -1, /* Use same category as in previous call */ + /** @LOGC_COUNT: Number of log categories */ + LOGC_COUNT, + /** @LOGC_END: Sentinel value for lists of log categories */ + LOGC_END, + /** @LOGC_CONT: Use same category as in previous call */ + LOGC_CONT = -1, }; /* Helper to cast a uclass ID to a log category */ @@ -85,7 +121,7 @@ static inline int log_uc_cat(enum uclass_id id) * @func: Function where log record was generated * @fmt: printf() format string for log record * @...: Optional parameters, according to the format string @fmt - * @return 0 if log record was emitted, -ve on error + * Return: 0 if log record was emitted, -ve on error */ int _log(enum log_category_t cat, enum log_level_t level, const char *file, int line, const char *func, const char *fmt, ...) @@ -240,7 +276,7 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line, * full pathname as it may be huge. Only use this when the user should be * warning, similar to BUG_ON() in linux. * - * @return true if assertion succeeded (condition is true), else false + * Return: true if assertion succeeded (condition is true), else false */ #define assert_noisy(x) \ ({ bool _val = (x); \ @@ -324,8 +360,9 @@ enum log_device_flags { */ struct log_driver { const char *name; + /** - * emit() - emit a log record + * @emit: emit a log record * * Called by the log system to pass a log record to a particular driver * for processing. The filter is checked before calling this function. @@ -361,21 +398,32 @@ enum { LOGF_MAX_CATEGORIES = 5, /* maximum categories per filter */ }; +/** + * enum log_filter_flags - Flags which modify a filter + */ enum log_filter_flags { - LOGFF_HAS_CAT = 1 << 0, /* Filter has a category list */ + /** @LOGFF_HAS_CAT: Filter has a category list */ + LOGFF_HAS_CAT = 1 << 0, + /** @LOGFF_DENY: Filter denies matching messages */ + LOGFF_DENY = 1 << 1, + /** @LOGFF_LEVEL_MIN: Filter's level is a minimum, not a maximum */ + LOGFF_LEVEL_MIN = 1 << 2, }; /** * struct log_filter - criterial to filter out log messages * + * If a message matches all criteria, then it is allowed. If LOGFF_DENY is set, + * then it is denied instead. + * * @filter_num: Sequence number of this filter. This is returned when adding a * new filter, and must be provided when removing a previously added * filter. - * @flags: Flags for this filter (LOGFF_...) - * @cat_list: List of categories to allow (terminated by LOGC_none). If empty - * then all categories are permitted. Up to LOGF_MAX_CATEGORIES entries + * @flags: Flags for this filter (``LOGFF_...``) + * @cat_list: List of categories to allow (terminated by %LOGC_END). If empty + * then all categories are permitted. Up to %LOGF_MAX_CATEGORIES entries * can be provided - * @max_level: Maximum log level to allow + * @level: Maximum (or minimum, if %LOGFF_MIN_LEVEL) log level to allow * @file_list: List of files to allow, separated by comma. If NULL then all * files are permitted * @sibling_node: Next filter in the list of filters for this log device @@ -384,7 +432,7 @@ struct log_filter { int filter_num; int flags; enum log_category_t cat_list[LOGF_MAX_CATEGORIES]; - enum log_level_t max_level; + enum log_level_t level; const char *file_list; struct list_head sibling_node; }; @@ -400,8 +448,9 @@ struct log_filter { * log_get_cat_name() - Get the name of a category * * @cat: Category to look up - * @return category name (which may be a uclass driver name) if found, or - * "<invalid>" if invalid, or "<missing>" if not found + * Return: category name (which may be a uclass driver name) if found, or + * "<invalid>" if invalid, or "<missing>" if not found. All error + * responses begin with '<'. */ const char *log_get_cat_name(enum log_category_t cat); @@ -409,7 +458,7 @@ const char *log_get_cat_name(enum log_category_t cat); * log_get_cat_by_name() - Look up a category by name * * @name: Name to look up - * @return category ID, or LOGC_NONE if not found + * Return: Category, or %LOGC_NONE if not found */ enum log_category_t log_get_cat_by_name(const char *name); @@ -417,7 +466,7 @@ enum log_category_t log_get_cat_by_name(const char *name); * log_get_level_name() - Get the name of a log level * * @level: Log level to look up - * @return log level name (in ALL CAPS) + * Return: Log level name (in ALL CAPS) */ const char *log_get_level_name(enum log_level_t level); @@ -425,10 +474,41 @@ const char *log_get_level_name(enum log_level_t level); * log_get_level_by_name() - Look up a log level by name * * @name: Name to look up - * @return log level ID, or LOGL_NONE if not found + * Return: Log level, or %LOGL_NONE if not found */ enum log_level_t log_get_level_by_name(const char *name); +/** + * log_device_find_by_name() - Look up a log device by its driver's name + * + * @drv_name: Name of the driver + * Return: the log device, or %NULL if not found + */ +struct log_device *log_device_find_by_name(const char *drv_name); + +/** + * log_has_cat() - check if a log category exists within a list + * + * @cat_list: List of categories to check, at most %LOGF_MAX_CATEGORIES entries + * long, terminated by %LC_END if fewer + * @cat: Category to search for + * + * Return: ``true`` if @cat is in @cat_list, else ``false`` + */ +bool log_has_cat(enum log_category_t cat_list[], enum log_category_t cat); + +/** + * log_has_file() - check if a file is with a list + * + * @file_list: List of files to check, separated by comma + * @file: File to check for. This string is matched against the end of each + * file in the list, i.e. ignoring any preceding path. The list is + * intended to consist of relative pathnames, e.g. common/main.c,cmd/log.c + * + * Return: ``true`` if @file is in @file_list, else ``false`` + */ +bool log_has_file(const char *file_list, const char *file); + /* Log format flags (bit numbers) for gd->log_fmt. See log_fmt_chars */ enum log_fmt { LOGF_CAT = 0, @@ -446,21 +526,48 @@ enum log_fmt { int do_log_test(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); /** + * log_add_filter_flags() - Add a new filter to a log device, specifying flags + * + * @drv_name: Driver name to add the filter to (since each driver only has a + * single device) + * @flags: Flags for this filter (``LOGFF_...``) + * @cat_list: List of categories to allow (terminated by %LOGC_END). If empty + * then all categories are permitted. Up to %LOGF_MAX_CATEGORIES entries + * can be provided + * @level: Maximum (or minimum, if %LOGFF_LEVEL_MIN) log level to allow + * @file_list: List of files to allow, separated by comma. If NULL then all + * files are permitted + * Return: + * the sequence number of the new filter (>=0) if the filter was added, or a + * -ve value on error + */ +int log_add_filter_flags(const char *drv_name, enum log_category_t cat_list[], + enum log_level_t level, const char *file_list, + int flags); + +/** * log_add_filter() - Add a new filter to a log device * * @drv_name: Driver name to add the filter to (since each driver only has a * single device) - * @cat_list: List of categories to allow (terminated by LOGC_none). If empty - * then all categories are permitted. Up to LOGF_MAX_CATEGORIES entries + * @cat_list: List of categories to allow (terminated by %LOGC_END). If empty + * then all categories are permitted. Up to %LOGF_MAX_CATEGORIES entries * can be provided * @max_level: Maximum log level to allow - * @file_list: List of files to allow, separated by comma. If NULL then all + * @file_list: List of files to allow, separated by comma. If %NULL then all * files are permitted - * @return the sequence number of the new filter (>=0) if the filter was added, - * or a -ve value on error + * Return: + * the sequence number of the new filter (>=0) if the filter was added, or a + * -ve value on error */ -int log_add_filter(const char *drv_name, enum log_category_t cat_list[], - enum log_level_t max_level, const char *file_list); +static inline int log_add_filter(const char *drv_name, + enum log_category_t cat_list[], + enum log_level_t max_level, + const char *file_list) +{ + return log_add_filter_flags(drv_name, cat_list, max_level, file_list, + 0); +} /** * log_remove_filter() - Remove a filter from a log device @@ -468,8 +575,9 @@ int log_add_filter(const char *drv_name, enum log_category_t cat_list[], * @drv_name: Driver name to remove the filter from (since each driver only has * a single device) * @filter_num: Filter number to remove (as returned by log_add_filter()) - * @return 0 if the filter was removed, -ENOENT if either the driver or the - * filter number was not found + * Return: + * 0 if the filter was removed, -%ENOENT if either the driver or the filter + * number was not found */ int log_remove_filter(const char *drv_name, int filter_num); @@ -490,7 +598,7 @@ int log_device_set_enable(struct log_driver *drv, bool enable); /** * log_init() - Set up the log system ready for use * - * @return 0 if OK, -ENOMEM if out of memory + * Return: 0 if OK, -%ENOMEM if out of memory */ int log_init(void); #else @@ -504,7 +612,7 @@ static inline int log_init(void) * log_get_default_format() - get default log format * * The default log format is configurable via - * CONFIG_LOGF_FILE, CONFIG_LOGF_LINE, CONFIG_LOGF_FUNC. + * %CONFIG_LOGF_FILE, %CONFIG_LOGF_LINE, and %CONFIG_LOGF_FUNC. * * Return: default log format */ diff --git a/include/mmc.h b/include/mmc.h index ac7b54f1a7e..1d377e0281f 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -360,6 +360,19 @@ enum mmc_voltage { #define MMC_NUM_BOOT_PARTITION 2 #define MMC_PART_RPMB 3 /* RPMB partition number */ +/* timing specification used */ +#define MMC_TIMING_LEGACY 0 +#define MMC_TIMING_MMC_HS 1 +#define MMC_TIMING_SD_HS 2 +#define MMC_TIMING_UHS_SDR12 3 +#define MMC_TIMING_UHS_SDR25 4 +#define MMC_TIMING_UHS_SDR50 5 +#define MMC_TIMING_UHS_SDR104 6 +#define MMC_TIMING_UHS_DDR50 7 +#define MMC_TIMING_MMC_DDR52 8 +#define MMC_TIMING_MMC_HS200 9 +#define MMC_TIMING_MMC_HS400 10 + /* Driver model support */ /** diff --git a/include/sdhci.h b/include/sdhci.h index f69d5f81fb1..1fd20ec0860 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -244,6 +244,7 @@ #define SDHCI_QUIRK_BROKEN_HISPD_MODE BIT(5) #define SDHCI_QUIRK_WAIT_SEND_CMD (1 << 6) #define SDHCI_QUIRK_USE_WIDE8 (1 << 8) +#define SDHCI_QUIRK_NO_1_8_V (1 << 9) /* to make gcc happy */ struct sdhci_host; diff --git a/include/test/log.h b/include/test/log.h index c661cde75a3..e9028914500 100644 --- a/include/test/log.h +++ b/include/test/log.h @@ -10,7 +10,10 @@ #include <test/test.h> +#define LOGF_TEST (BIT(LOGF_FUNC) | BIT(LOGF_MSG)) + /* Declare a new logging test */ #define LOG_TEST(_name) UNIT_TEST(_name, 0, log_test) +#define LOG_TEST_FLAGS(_name, _flags) UNIT_TEST(_name, _flags, log_test) #endif /* __TEST_LOG_H__ */ diff --git a/include/u-boot/rsa-mod-exp.h b/include/u-boot/rsa-mod-exp.h index 1da8af1bb83..7b7c2915a94 100644 --- a/include/u-boot/rsa-mod-exp.h +++ b/include/u-boot/rsa-mod-exp.h @@ -66,7 +66,7 @@ int rsa_mod_exp(struct udevice *dev, const uint8_t *sig, uint32_t sig_len, struct key_prop *node, uint8_t *out); #if defined(CONFIG_CMD_ZYNQ_RSA) -int zynq_pow_mod(u32 *keyptr, u32 *inout); +int zynq_pow_mod(uint32_t *keyptr, uint32_t *inout); #endif /** diff --git a/include/zynqmp_tap_delay.h b/include/zynqmp_tap_delay.h index b07e3e06922..7b713438f75 100644 --- a/include/zynqmp_tap_delay.h +++ b/include/zynqmp_tap_delay.h @@ -10,10 +10,11 @@ #ifdef CONFIG_ARCH_ZYNQMP void zynqmp_dll_reset(u8 deviceid); -void arasan_zynqmp_set_tapdelay(u8 device_id, u8 uhsmode, u8 bank); +void arasan_zynqmp_set_tapdelay(u8 device_id, u32 itap_delay, u32 otap_delay); #else inline void zynqmp_dll_reset(u8 deviceid) {} -inline void arasan_zynqmp_set_tapdelay(u8 device_id, u8 uhsmode, u8 bank) {} +inline void arasan_zynqmp_set_tapdelay(u8 device_id, u32 itap_delay, + u32 otap_delay) {} #endif #endif diff --git a/lib/Kconfig b/lib/Kconfig index 37aae73a266..79651eaad19 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -550,6 +550,11 @@ config SPL_HEXDUMP This enables functions for printing dumps of binary data in SPL. +config GETOPT + bool "Enable getopt" + help + This enables functions for parsing command-line options. + config OF_LIBFDT bool "Enable the FDT library" default y if OF_CONTROL diff --git a/lib/Makefile b/lib/Makefile index 0cd7bea2823..7c7fb9aae78 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -106,6 +106,7 @@ obj-y += string.o obj-y += tables_csum.o obj-y += time.o obj-y += hexdump.o +obj-$(CONFIG_GETOPT) += getopt.o obj-$(CONFIG_TRACE) += trace.o obj-$(CONFIG_LIB_UUID) += uuid.o obj-$(CONFIG_LIB_RAND) += rand.o diff --git a/lib/getopt.c b/lib/getopt.c new file mode 100644 index 00000000000..8b4515dc196 --- /dev/null +++ b/lib/getopt.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * getopt.c - a simple getopt(3) implementation. See getopt.h for explanation. + * + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com> + * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + */ + +#define LOG_CATEGORY LOGC_CORE + +#include <common.h> +#include <getopt.h> +#include <log.h> + +void getopt_init_state(struct getopt_state *gs) +{ + gs->index = 1; + gs->arg_index = 1; +} + +int __getopt(struct getopt_state *gs, int argc, char *const argv[], + const char *optstring, bool silent) +{ + char curopt; /* current option character */ + const char *curoptp; /* pointer to the current option in optstring */ + + while (1) { + log_debug("arg_index: %d index: %d\n", gs->arg_index, + gs->index); + + /* `--` indicates the end of options */ + if (gs->arg_index == 1 && argv[gs->index] && + !strcmp(argv[gs->index], "--")) { + gs->index++; + return -1; + } + + /* Out of arguments */ + if (gs->index >= argc) + return -1; + + /* Can't parse non-options */ + if (*argv[gs->index] != '-') + return -1; + + /* We have found an option */ + curopt = argv[gs->index][gs->arg_index]; + if (curopt) + break; + /* + * no more options in current argv[] element; try the next one + */ + gs->index++; + gs->arg_index = 1; + } + + /* look up current option in optstring */ + curoptp = strchr(optstring, curopt); + + if (!curoptp) { + if (!silent) + printf("%s: invalid option -- %c\n", argv[0], curopt); + gs->opt = curopt; + gs->arg_index++; + return '?'; + } + + if (*(curoptp + 1) != ':') { + /* option with no argument. Just return it */ + gs->arg = NULL; + gs->arg_index++; + return curopt; + } + + if (*(curoptp + 1) && *(curoptp + 2) == ':') { + /* optional argument */ + if (argv[gs->index][gs->arg_index + 1]) { + /* optional argument with directly following arg */ + gs->arg = argv[gs->index++] + gs->arg_index + 1; + gs->arg_index = 1; + return curopt; + } + if (gs->index + 1 == argc) { + /* We are at the last argv[] element */ + gs->arg = NULL; + gs->index++; + return curopt; + } + if (*argv[gs->index + 1] != '-') { + /* + * optional argument with arg in next argv[] element + */ + gs->index++; + gs->arg = argv[gs->index++]; + gs->arg_index = 1; + return curopt; + } + + /* no optional argument found */ + gs->arg = NULL; + gs->arg_index = 1; + gs->index++; + return curopt; + } + + if (argv[gs->index][gs->arg_index + 1]) { + /* required argument with directly following arg */ + gs->arg = argv[gs->index++] + gs->arg_index + 1; + gs->arg_index = 1; + return curopt; + } + + gs->index++; + gs->arg_index = 1; + + if (gs->index >= argc || argv[gs->index][0] == '-') { + if (!silent) + printf("option requires an argument -- %c\n", curopt); + gs->opt = curopt; + return ':'; + } + + gs->arg = argv[gs->index++]; + return curopt; +} diff --git a/lib/rsa/rsa-mod-exp.c b/lib/rsa/rsa-mod-exp.c index 78c688d14c3..74f9eb16cc2 100644 --- a/lib/rsa/rsa-mod-exp.c +++ b/lib/rsa/rsa-mod-exp.c @@ -321,7 +321,7 @@ int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len, * pow_mod calculation required for zynq is bit different from * pw_mod above here, hence defined zynq specific routine. */ -int zynq_pow_mod(u32 *keyptr, u32 *inout) +int zynq_pow_mod(uint32_t *keyptr, uint32_t *inout) { u32 *result, *ptr; uint i; diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index 01ac3c2094c..fb1ceb13180 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -207,6 +207,28 @@ static int dm_test_ofnode_read_chosen(struct unit_test_state *uts) } DM_TEST(dm_test_ofnode_read_chosen, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +static int dm_test_ofnode_read_aliases(struct unit_test_state *uts) +{ + const void *val; + ofnode node; + int size; + + node = ofnode_get_aliases_node("eth3"); + ut_assert(ofnode_valid(node)); + ut_asserteq_str("sbe5", ofnode_get_name(node)); + + node = ofnode_get_aliases_node("unknown"); + ut_assert(!ofnode_valid(node)); + + val = ofnode_read_aliases_prop("spi0", &size); + ut_assertnonnull(val); + ut_asserteq(7, size); + ut_asserteq_str("/spi@0", (const char *)val); + + return 0; +} +DM_TEST(dm_test_ofnode_read_aliases, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + static int dm_test_ofnode_get_child_count(struct unit_test_state *uts) { ofnode node, child_node; diff --git a/test/lib/Makefile b/test/lib/Makefile index 15cd512506b..98a9abf40e2 100644 --- a/test/lib/Makefile +++ b/test/lib/Makefile @@ -14,3 +14,4 @@ obj-$(CONFIG_ERRNO_STR) += test_errno_str.o obj-$(CONFIG_UT_LIB_ASN1) += asn1.o obj-$(CONFIG_UT_LIB_RSA) += rsa.o obj-$(CONFIG_AES) += test_aes.o +obj-$(CONFIG_GETOPT) += getopt.o diff --git a/test/lib/getopt.c b/test/lib/getopt.c new file mode 100644 index 00000000000..3c68b93c8a5 --- /dev/null +++ b/test/lib/getopt.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com> + * + * Portions of these tests were inspired by glibc's posix/bug-getopt1.c and + * posix/tst-getopt-cancel.c + */ + +#include <common.h> +#include <getopt.h> +#include <test/lib.h> +#include <test/test.h> +#include <test/ut.h> + +static int do_test_getopt(struct unit_test_state *uts, int line, + struct getopt_state *gs, const char *optstring, + int args, char *argv[], int expected_count, + int expected[]) +{ + int opt; + + getopt_init_state(gs); + for (int i = 0; i < expected_count; i++) { + opt = getopt_silent(gs, args, argv, optstring); + if (expected[i] != opt) { + /* + * Fudge the line number so we can tell which test + * failed + */ + ut_failf(uts, __FILE__, line, __func__, + "expected[i] == getopt()", + "Expected '%c' (%d) with i=%d, got '%c' (%d)", + expected[i], expected[i], i, opt, opt); + return CMD_RET_FAILURE; + } + } + + opt = getopt_silent(gs, args, argv, optstring); + if (opt != -1) { + ut_failf(uts, __FILE__, line, __func__, + "getopt() != -1", + "Expected -1, got '%c' (%d)", opt, opt); + return CMD_RET_FAILURE; + } + + return 0; +} + +#define test_getopt(optstring, argv, expected) do { \ + int ret = do_test_getopt(uts, __LINE__, &gs, optstring, \ + ARRAY_SIZE(argv) - 1, argv, \ + ARRAY_SIZE(expected), expected); \ + if (ret) \ + return ret; \ +} while (0) + +static int lib_test_getopt(struct unit_test_state *uts) +{ + struct getopt_state gs; + + /* Happy path */ + test_getopt("ab:c", + ((char *[]){ "program", "-cb", "x", "-a", "foo", 0 }), + ((int []){ 'c', 'b', 'a' })); + ut_asserteq(4, gs.index); + + /* Make sure we pick up the optional argument */ + test_getopt("a::b:c", + ((char *[]){ "program", "-cbx", "-a", "foo", 0 }), + ((int []){ 'c', 'b', 'a' })); + ut_asserteq(4, gs.index); + + /* Test required arguments */ + test_getopt("a:b", ((char *[]){ "program", "-a", 0 }), + ((int []){ ':' })); + ut_asserteq('a', gs.opt); + test_getopt("a:b", ((char *[]){ "program", "-b", "-a", 0 }), + ((int []){ 'b', ':' })); + ut_asserteq('a', gs.opt); + + /* Test invalid arguments */ + test_getopt("ab:c", ((char *[]){ "program", "-d", 0 }), + ((int []){ '?' })); + ut_asserteq('d', gs.opt); + + /* Test arg */ + test_getopt("a::b:c", + ((char *[]){ "program", "-a", 0 }), + ((int []){ 'a' })); + ut_asserteq(2, gs.index); + ut_assertnull(gs.arg); + + test_getopt("a::b:c", + ((char *[]){ "program", "-afoo", 0 }), + ((int []){ 'a' })); + ut_asserteq(2, gs.index); + ut_assertnonnull(gs.arg); + ut_asserteq_str("foo", gs.arg); + + test_getopt("a::b:c", + ((char *[]){ "program", "-a", "foo", 0 }), + ((int []){ 'a' })); + ut_asserteq(3, gs.index); + ut_assertnonnull(gs.arg); + ut_asserteq_str("foo", gs.arg); + + test_getopt("a::b:c", + ((char *[]){ "program", "-bfoo", 0 }), + ((int []){ 'b' })); + ut_asserteq(2, gs.index); + ut_assertnonnull(gs.arg); + ut_asserteq_str("foo", gs.arg); + + test_getopt("a::b:c", + ((char *[]){ "program", "-b", "foo", 0 }), + ((int []){ 'b' })); + ut_asserteq(3, gs.index); + ut_assertnonnull(gs.arg); + ut_asserteq_str("foo", gs.arg); + + return 0; +} +LIB_TEST(lib_test_getopt, 0); diff --git a/test/log/Makefile b/test/log/Makefile index fdf529582d6..88bc573e9fb 100644 --- a/test/log/Makefile +++ b/test/log/Makefile @@ -3,6 +3,7 @@ # Copyright (c) 2017 Google, Inc obj-$(CONFIG_LOG_TEST) += log_test.o +obj-$(CONFIG_CMD_LOG) += log_filter.o ifdef CONFIG_UT_LOG diff --git a/test/log/log_filter.c b/test/log/log_filter.c new file mode 100644 index 00000000000..e8a6e01a5cc --- /dev/null +++ b/test/log/log_filter.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com> + */ + +#include <common.h> +#include <console.h> +#include <log.h> +#include <test/log.h> +#include <test/ut.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Test invalid options */ +static int log_test_filter_invalid(struct unit_test_state *uts) +{ + ut_asserteq(1, run_command("log filter-add -AD", 0)); + ut_asserteq(1, run_command("log filter-add -l1 -L1", 0)); + ut_asserteq(1, run_command("log filter-add -l1 -L1", 0)); + ut_asserteq(1, run_command("log filter-add -lfoo", 0)); + ut_asserteq(1, run_command("log filter-add -cfoo", 0)); + ut_asserteq(1, run_command("log filter-add -ccore -ccore -ccore -ccore " + "-ccore -ccore", 0)); + + return 0; +} +LOG_TEST_FLAGS(log_test_filter_invalid, UT_TESTF_CONSOLE_REC); + +/* Test adding and removing filters */ +static int log_test_filter(struct unit_test_state *uts) +{ + bool any_found = false; + bool filt1_found = false; + bool filt2_found = false; + char cmd[32]; + struct log_filter *filt; + struct log_device *ldev; + ulong filt1, filt2; + +#define create_filter(args, filter_num) do {\ + ut_assertok(console_record_reset_enable()); \ + ut_assertok(run_command("log filter-add -p " args, 0)); \ + ut_assert_skipline(); \ + ut_assertok(strict_strtoul(uts->actual_str, 10, &(filter_num))); \ + ut_assert_console_end(); \ +} while (0) + + create_filter("", filt1); + create_filter("-DL warning -cmmc -cspi -ffile", filt2); + + ldev = log_device_find_by_name("console"); + ut_assertnonnull(ldev); + list_for_each_entry(filt, &ldev->filter_head, sibling_node) { + if (filt->filter_num == filt1) { + filt1_found = true; + ut_asserteq(0, filt->flags); + ut_asserteq(LOGL_MAX, filt->level); + ut_assertnull(filt->file_list); + } else if (filt->filter_num == filt2) { + filt2_found = true; + ut_asserteq(LOGFF_HAS_CAT | LOGFF_DENY | + LOGFF_LEVEL_MIN, filt->flags); + ut_asserteq(true, log_has_cat(filt->cat_list, + log_uc_cat(UCLASS_MMC))); + ut_asserteq(true, log_has_cat(filt->cat_list, + log_uc_cat(UCLASS_SPI))); + ut_asserteq(LOGL_WARNING, filt->level); + ut_asserteq_str("file", filt->file_list); + } + } + ut_asserteq(true, filt1_found); + ut_asserteq(true, filt2_found); + +#define remove_filter(filter_num) do { \ + ut_assertok(console_record_reset_enable()); \ + snprintf(cmd, sizeof(cmd), "log filter-remove %lu", filter_num); \ + ut_assertok(run_command(cmd, 0)); \ + ut_assert_console_end(); \ +} while (0) + + remove_filter(filt1); + remove_filter(filt2); + + filt1_found = false; + filt2_found = false; + list_for_each_entry(filt, &ldev->filter_head, sibling_node) { + if (filt->filter_num == filt1) + filt1_found = true; + else if (filt->filter_num == filt2) + filt2_found = true; + } + ut_asserteq(false, filt1_found); + ut_asserteq(false, filt2_found); + + create_filter("", filt1); + create_filter("", filt2); + + ut_assertok(console_record_reset_enable()); + ut_assertok(run_command("log filter-remove -a", 0)); + ut_assert_console_end(); + + list_for_each_entry(filt, &ldev->filter_head, sibling_node) + any_found = true; + ut_asserteq(false, any_found); + + return 0; +} +LOG_TEST_FLAGS(log_test_filter, UT_TESTF_CONSOLE_REC); diff --git a/test/log/log_test.c b/test/log/log_test.c index 6a60ff6be3c..ea4fc6bc30b 100644 --- a/test/log/log_test.c +++ b/test/log/log_test.c @@ -9,12 +9,17 @@ #include <common.h> #include <command.h> #include <log.h> +#include <test/log.h> +#include <test/ut.h> + +DECLARE_GLOBAL_DATA_PTR; /* emit some sample log records in different ways, for testing */ -static int log_run(enum uclass_id cat, const char *file) +static int do_log_run(int cat, const char *file) { int i; + gd->log_fmt = LOGF_TEST; debug("debug\n"); for (i = LOGL_FIRST; i < LOGL_COUNT; i++) { log(cat, i, "log %d\n", i); @@ -22,203 +27,358 @@ static int log_run(enum uclass_id cat, const char *file) i); } + gd->log_fmt = log_get_default_format(); return 0; } -static int log_test(int testnum) +#define log_run_cat(cat) do_log_run(cat, "file") +#define log_run_file(file) do_log_run(UCLASS_SPI, file) +#define log_run() do_log_run(UCLASS_SPI, "file") + +#define EXPECT_LOG BIT(0) +#define EXPECT_DIRECT BIT(1) +#define EXPECT_EXTRA BIT(2) + +static int do_check_log_entries(struct unit_test_state *uts, int flags, int min, + int max) { - int ret; + int i; - printf("test %d\n", testnum); - switch (testnum) { - case 0: { - /* Check a category filter using the first category */ - enum log_category_t cat_list[] = { - log_uc_cat(UCLASS_MMC), log_uc_cat(UCLASS_SPI), - LOGC_NONE, LOGC_END - }; - - ret = log_add_filter("console", cat_list, LOGL_MAX, NULL); - if (ret < 0) - return ret; - log_run(UCLASS_MMC, "file"); - ret = log_remove_filter("console", ret); - if (ret < 0) - return ret; - break; - } - case 1: { - /* Check a category filter using the second category */ - enum log_category_t cat_list[] = { - log_uc_cat(UCLASS_MMC), log_uc_cat(UCLASS_SPI), LOGC_END - }; - - ret = log_add_filter("console", cat_list, LOGL_MAX, NULL); - if (ret < 0) - return ret; - log_run(UCLASS_SPI, "file"); - ret = log_remove_filter("console", ret); - if (ret < 0) - return ret; - break; - } - case 2: { - /* Check a category filter that should block log entries */ - enum log_category_t cat_list[] = { - log_uc_cat(UCLASS_MMC), LOGC_NONE, LOGC_END - }; - - ret = log_add_filter("console", cat_list, LOGL_MAX, NULL); - if (ret < 0) - return ret; - log_run(UCLASS_SPI, "file"); - ret = log_remove_filter("console", ret); - if (ret < 0) - return ret; - break; - } - case 3: { - /* Check a passing file filter */ - ret = log_add_filter("console", NULL, LOGL_MAX, "file"); - if (ret < 0) - return ret; - log_run(UCLASS_SPI, "file"); - ret = log_remove_filter("console", ret); - if (ret < 0) - return ret; - break; - } - case 4: { - /* Check a failing file filter */ - ret = log_add_filter("console", NULL, LOGL_MAX, "file"); - if (ret < 0) - return ret; - log_run(UCLASS_SPI, "file2"); - ret = log_remove_filter("console", ret); - if (ret < 0) - return ret; - break; - } - case 5: { - /* Check a passing file filter (second in list) */ - ret = log_add_filter("console", NULL, LOGL_MAX, "file,file2"); - if (ret < 0) - return ret; - log_run(UCLASS_SPI, "file2"); - ret = log_remove_filter("console", ret); - if (ret < 0) - return ret; - break; - } - case 6: { - /* Check a passing file filter */ - ret = log_add_filter("console", NULL, LOGL_MAX, - "file,file2,log/log_test.c"); - if (ret < 0) - return ret; - log_run(UCLASS_SPI, "file2"); - ret = log_remove_filter("console", ret); - if (ret < 0) - return ret; - break; - } - case 7: { - /* Check a log level filter */ - ret = log_add_filter("console", NULL, LOGL_WARNING, NULL); - if (ret < 0) - return ret; - log_run(UCLASS_SPI, "file"); - ret = log_remove_filter("console", ret); - if (ret < 0) - return ret; - break; - } - case 8: { - /* Check two filters, one of which passes everything */ - int filt1, filt2; - - ret = log_add_filter("console", NULL, LOGL_WARNING, NULL); - if (ret < 0) - return ret; - filt1 = ret; - ret = log_add_filter("console", NULL, LOGL_MAX, NULL); - if (ret < 0) - return ret; - filt2 = ret; - log_run(UCLASS_SPI, "file"); - ret = log_remove_filter("console", filt1); - if (ret < 0) - return ret; - ret = log_remove_filter("console", filt2); - if (ret < 0) - return ret; - break; - } - case 9: { - /* Check three filters, which together pass everything */ - int filt1, filt2, filt3; - - ret = log_add_filter("console", NULL, LOGL_MAX, "file)"); - if (ret < 0) - return ret; - filt1 = ret; - ret = log_add_filter("console", NULL, LOGL_MAX, "file2"); - if (ret < 0) - return ret; - filt2 = ret; - ret = log_add_filter("console", NULL, LOGL_MAX, - "log/log_test.c"); - if (ret < 0) - return ret; - filt3 = ret; - log_run(UCLASS_SPI, "file2"); - ret = log_remove_filter("console", filt1); - if (ret < 0) - return ret; - ret = log_remove_filter("console", filt2); - if (ret < 0) - return ret; - ret = log_remove_filter("console", filt3); - if (ret < 0) - return ret; - break; - } - case 10: { - log_err("level %d\n", LOGL_EMERG); - log_err("level %d\n", LOGL_ALERT); - log_err("level %d\n", LOGL_CRIT); - log_err("level %d\n", LOGL_ERR); - log_warning("level %d\n", LOGL_WARNING); - log_notice("level %d\n", LOGL_NOTICE); - log_info("level %d\n", LOGL_INFO); - log_debug("level %d\n", LOGL_DEBUG); - log_content("level %d\n", LOGL_DEBUG_CONTENT); - log_io("level %d\n", LOGL_DEBUG_IO); - break; - } - case 11: - log_err("default\n"); - ret = log_device_set_enable(LOG_GET_DRIVER(console), false); - log_err("disabled\n"); - ret = log_device_set_enable(LOG_GET_DRIVER(console), true); - log_err("enabled\n"); - break; + for (i = min; i <= max; i++) { + if (flags & EXPECT_LOG) + ut_assert_nextline("do_log_run() log %d", i); + if (flags & EXPECT_DIRECT) + ut_assert_nextline("func() _log %d", i); } + if (flags & EXPECT_EXTRA) + for (; i <= LOGL_MAX ; i++) + ut_assert_nextline("func() _log %d", i); + + ut_assert_console_end(); + return 0; +} + +#define check_log_entries_flags_levels(flags, min, max) do {\ + int ret = do_check_log_entries(uts, flags, min, max); \ + if (ret) \ + return ret; \ +} while (0) + +#define check_log_entries_flags(flags) \ + check_log_entries_flags_levels(flags, LOGL_FIRST, _LOG_MAX_LEVEL) +#define check_log_entries() check_log_entries_flags(EXPECT_LOG | EXPECT_DIRECT) +#define check_log_entries_extra() \ + check_log_entries_flags(EXPECT_LOG | EXPECT_DIRECT | EXPECT_EXTRA) +#define check_log_entries_none() check_log_entries_flags(0) + +/* Check a category filter using the first category */ +int log_test_cat_allow(struct unit_test_state *uts) +{ + enum log_category_t cat_list[] = { + log_uc_cat(UCLASS_MMC), log_uc_cat(UCLASS_SPI), + LOGC_NONE, LOGC_END + }; + int filt; + + filt = log_add_filter("console", cat_list, LOGL_MAX, NULL); + ut_assert(filt >= 0); + + ut_assertok(console_record_reset_enable()); + log_run_cat(UCLASS_MMC); + check_log_entries_extra(); + + ut_assertok(console_record_reset_enable()); + log_run_cat(UCLASS_SPI); + check_log_entries_extra(); + + ut_assertok(log_remove_filter("console", filt)); + return 0; +} +LOG_TEST_FLAGS(log_test_cat_allow, UT_TESTF_CONSOLE_REC); + +/* Check a category filter that should block log entries */ +int log_test_cat_deny_implicit(struct unit_test_state *uts) +{ + enum log_category_t cat_list[] = { + log_uc_cat(UCLASS_MMC), LOGC_NONE, LOGC_END + }; + int filt; + + filt = log_add_filter("console", cat_list, LOGL_MAX, NULL); + ut_assert(filt >= 0); + + ut_assertok(console_record_reset_enable()); + log_run_cat(UCLASS_SPI); + check_log_entries_none(); + + ut_assertok(log_remove_filter("console", filt)); + return 0; +} +LOG_TEST_FLAGS(log_test_cat_deny_implicit, UT_TESTF_CONSOLE_REC); + +/* Check passing and failing file filters */ +int log_test_file(struct unit_test_state *uts) +{ + int filt; + + filt = log_add_filter("console", NULL, LOGL_MAX, "file"); + ut_assert(filt >= 0); + + ut_assertok(console_record_reset_enable()); + log_run_file("file"); + check_log_entries_flags(EXPECT_DIRECT | EXPECT_EXTRA); + + ut_assertok(console_record_reset_enable()); + log_run_file("file2"); + check_log_entries_none(); + + ut_assertok(log_remove_filter("console", filt)); + return 0; +} +LOG_TEST_FLAGS(log_test_file, UT_TESTF_CONSOLE_REC); + +/* Check a passing file filter (second in list) */ +int log_test_file_second(struct unit_test_state *uts) +{ + int filt; + + filt = log_add_filter("console", NULL, LOGL_MAX, "file,file2"); + ut_assert(filt >= 0); + + ut_assertok(console_record_reset_enable()); + log_run_file("file2"); + check_log_entries_flags(EXPECT_DIRECT | EXPECT_EXTRA); + + ut_assertok(log_remove_filter("console", filt)); + return 0; +} +LOG_TEST_FLAGS(log_test_file_second, UT_TESTF_CONSOLE_REC); + +/* Check a passing file filter (middle of list) */ +int log_test_file_mid(struct unit_test_state *uts) +{ + int filt; + + filt = log_add_filter("console", NULL, LOGL_MAX, + "file,file2,log/log_test.c"); + ut_assert(filt >= 0); + + ut_assertok(console_record_reset_enable()); + log_run_file("file2"); + check_log_entries_extra(); + + ut_assertok(log_remove_filter("console", filt)); + return 0; +} +LOG_TEST_FLAGS(log_test_file_mid, UT_TESTF_CONSOLE_REC); + +/* Check a log level filter */ +int log_test_level(struct unit_test_state *uts) +{ + int filt; + filt = log_add_filter("console", NULL, LOGL_WARNING, NULL); + ut_assert(filt >= 0); + + ut_assertok(console_record_reset_enable()); + log_run(); + check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT, LOGL_FIRST, + LOGL_WARNING); + + ut_assertok(log_remove_filter("console", filt)); + return 0; +} +LOG_TEST_FLAGS(log_test_level, UT_TESTF_CONSOLE_REC); + +/* Check two filters, one of which passes everything */ +int log_test_double(struct unit_test_state *uts) +{ + int filt1, filt2; + + filt1 = log_add_filter("console", NULL, LOGL_WARNING, NULL); + ut_assert(filt1 >= 0); + filt2 = log_add_filter("console", NULL, LOGL_MAX, NULL); + ut_assert(filt2 >= 0); + + ut_assertok(console_record_reset_enable()); + log_run(); + check_log_entries_extra(); + + ut_assertok(log_remove_filter("console", filt1)); + ut_assertok(log_remove_filter("console", filt2)); + return 0; +} +LOG_TEST_FLAGS(log_test_double, UT_TESTF_CONSOLE_REC); + +/* Check three filters, which together pass everything */ +int log_test_triple(struct unit_test_state *uts) +{ + int filt1, filt2, filt3; + + filt1 = log_add_filter("console", NULL, LOGL_MAX, "file)"); + ut_assert(filt1 >= 0); + filt2 = log_add_filter("console", NULL, LOGL_MAX, "file2"); + ut_assert(filt2 >= 0); + filt3 = log_add_filter("console", NULL, LOGL_MAX, "log/log_test.c"); + ut_assert(filt3 >= 0); + + ut_assertok(console_record_reset_enable()); + log_run_file("file2"); + check_log_entries_extra(); + + ut_assertok(log_remove_filter("console", filt1)); + ut_assertok(log_remove_filter("console", filt2)); + ut_assertok(log_remove_filter("console", filt3)); + return 0; +} +LOG_TEST_FLAGS(log_test_triple, UT_TESTF_CONSOLE_REC); + +int do_log_test_helpers(struct unit_test_state *uts) +{ + int i; + + ut_assertok(console_record_reset_enable()); + log_err("level %d\n", LOGL_EMERG); + log_err("level %d\n", LOGL_ALERT); + log_err("level %d\n", LOGL_CRIT); + log_err("level %d\n", LOGL_ERR); + log_warning("level %d\n", LOGL_WARNING); + log_notice("level %d\n", LOGL_NOTICE); + log_info("level %d\n", LOGL_INFO); + log_debug("level %d\n", LOGL_DEBUG); + log_content("level %d\n", LOGL_DEBUG_CONTENT); + log_io("level %d\n", LOGL_DEBUG_IO); + + for (i = LOGL_EMERG; i <= _LOG_MAX_LEVEL; i++) + ut_assert_nextline("%s() level %d", __func__, i); + ut_assert_console_end(); + return 0; +} + +int log_test_helpers(struct unit_test_state *uts) +{ + int ret; + + gd->log_fmt = LOGF_TEST; + ret = do_log_test_helpers(uts); + gd->log_fmt = log_get_default_format(); + return ret; +} +LOG_TEST_FLAGS(log_test_helpers, UT_TESTF_CONSOLE_REC); + +int do_log_test_disable(struct unit_test_state *uts) +{ + ut_assertok(console_record_reset_enable()); + log_err("default\n"); + ut_assert_nextline("%s() default", __func__); + + ut_assertok(log_device_set_enable(LOG_GET_DRIVER(console), false)); + log_err("disabled\n"); + + ut_assertok(log_device_set_enable(LOG_GET_DRIVER(console), true)); + log_err("enabled\n"); + ut_assert_nextline("%s() enabled", __func__); + ut_assert_console_end(); return 0; } -int do_log_test(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +int log_test_disable(struct unit_test_state *uts) { - int testnum = 0; int ret; - if (argc > 1) - testnum = simple_strtoul(argv[1], NULL, 10); + gd->log_fmt = LOGF_TEST; + ret = do_log_test_disable(uts); + gd->log_fmt = log_get_default_format(); + return ret; +} +LOG_TEST_FLAGS(log_test_disable, UT_TESTF_CONSOLE_REC); + +/* Check denying based on category */ +int log_test_cat_deny(struct unit_test_state *uts) +{ + int filt1, filt2; + enum log_category_t cat_list[] = { + log_uc_cat(UCLASS_SPI), LOGC_END + }; + + filt1 = log_add_filter("console", cat_list, LOGL_MAX, NULL); + ut_assert(filt1 >= 0); + filt2 = log_add_filter_flags("console", cat_list, LOGL_MAX, NULL, + LOGFF_DENY); + ut_assert(filt2 >= 0); + + ut_assertok(console_record_reset_enable()); + log_run_cat(UCLASS_SPI); + check_log_entries_none(); + + ut_assertok(log_remove_filter("console", filt1)); + ut_assertok(log_remove_filter("console", filt2)); + return 0; +} +LOG_TEST_FLAGS(log_test_cat_deny, UT_TESTF_CONSOLE_REC); + +/* Check denying based on file */ +int log_test_file_deny(struct unit_test_state *uts) +{ + int filt1, filt2; + + filt1 = log_add_filter("console", NULL, LOGL_MAX, "file"); + ut_assert(filt1 >= 0); + filt2 = log_add_filter_flags("console", NULL, LOGL_MAX, "file", + LOGFF_DENY); + ut_assert(filt2 >= 0); - ret = log_test(testnum); - if (ret) - printf("Test failure (err=%d)\n", ret); + ut_assertok(console_record_reset_enable()); + log_run_file("file"); + check_log_entries_none(); - return ret ? CMD_RET_FAILURE : 0; + ut_assertok(log_remove_filter("console", filt1)); + ut_assertok(log_remove_filter("console", filt2)); + return 0; +} +LOG_TEST_FLAGS(log_test_file_deny, UT_TESTF_CONSOLE_REC); + +/* Check denying based on level */ +int log_test_level_deny(struct unit_test_state *uts) +{ + int filt1, filt2; + + filt1 = log_add_filter("console", NULL, LOGL_INFO, NULL); + ut_assert(filt1 >= 0); + filt2 = log_add_filter_flags("console", NULL, LOGL_WARNING, NULL, + LOGFF_DENY); + ut_assert(filt2 >= 0); + + ut_assertok(console_record_reset_enable()); + log_run(); + check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT, + LOGL_WARNING + 1, _LOG_MAX_LEVEL); + + ut_assertok(log_remove_filter("console", filt1)); + ut_assertok(log_remove_filter("console", filt2)); + return 0; +} +LOG_TEST_FLAGS(log_test_level_deny, UT_TESTF_CONSOLE_REC); + +/* Check matching based on minimum level */ +int log_test_min(struct unit_test_state *uts) +{ + int filt1, filt2; + + filt1 = log_add_filter_flags("console", NULL, LOGL_WARNING, NULL, + LOGFF_LEVEL_MIN); + ut_assert(filt1 >= 0); + filt2 = log_add_filter_flags("console", NULL, LOGL_INFO, NULL, + LOGFF_DENY | LOGFF_LEVEL_MIN); + ut_assert(filt2 >= 0); + + ut_assertok(console_record_reset_enable()); + log_run(); + check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT, + LOGL_WARNING, LOGL_INFO - 1); + + ut_assertok(log_remove_filter("console", filt1)); + ut_assertok(log_remove_filter("console", filt2)); + return 0; } +LOG_TEST_FLAGS(log_test_min, UT_TESTF_CONSOLE_REC); diff --git a/test/log/syslog_test.h b/test/log/syslog_test.h index 1310257bfe1..bfaa6daef81 100644 --- a/test/log/syslog_test.h +++ b/test/log/syslog_test.h @@ -8,8 +8,6 @@ #ifndef __SYSLOG_TEST_H #define __SYSLOG_TEST_H -#define LOGF_TEST (BIT(LOGF_FUNC) | BIT(LOGF_MSG)) - /** * struct sb_log_env - private data for sandbox ethernet driver * diff --git a/test/py/tests/test_log.py b/test/py/tests/test_log.py index 275f9382d2f..387b392ce9e 100644 --- a/test/py/tests/test_log.py +++ b/test/py/tests/test_log.py @@ -10,110 +10,6 @@ and checks that the output is correct. import pytest -LOGL_FIRST, LOGL_WARNING, LOGL_INFO = (0, 4, 6) - -@pytest.mark.buildconfigspec('cmd_log') -def test_log(u_boot_console): - """Test that U-Boot logging works correctly.""" - def check_log_entries(lines, mask, max_level=LOGL_INFO): - """Check that the expected log records appear in the output - - Args: - lines: iterator containing lines to check - mask: bit mask to select which lines to check for: - bit 0: standard log line - bit 1: _log line - max_level: maximum log level to expect in the output - """ - for i in range(max_level): - if mask & 1: - assert 'log_run() log %d' % i == next(lines) - if mask & 3: - assert 'func() _log %d' % i == next(lines) - - def run_test(testnum): - """Run a particular test number (the 'log test' command) - - Args: - testnum: Test number to run - Returns: - iterator containing the lines output from the command - """ - output = u_boot_console.run_command('log format fm') - assert output == '' - with cons.log.section('basic'): - output = u_boot_console.run_command('log test %d' % testnum) - split = output.replace('\r', '').splitlines() - lines = iter(split) - assert 'test %d' % testnum == next(lines) - return lines - - def test0(): - lines = run_test(0) - check_log_entries(lines, 3) - - def test1(): - lines = run_test(1) - check_log_entries(lines, 3) - - def test2(): - lines = run_test(2) - - def test3(): - lines = run_test(3) - check_log_entries(lines, 2) - - def test4(): - lines = run_test(4) - assert next(lines, None) == None - - def test5(): - lines = run_test(5) - check_log_entries(lines, 2) - - def test6(): - lines = run_test(6) - check_log_entries(lines, 3) - - def test7(): - lines = run_test(7) - check_log_entries(lines, 3, LOGL_WARNING) - - def test8(): - lines = run_test(8) - check_log_entries(lines, 3) - - def test9(): - lines = run_test(9) - check_log_entries(lines, 3) - - def test10(): - lines = run_test(10) - for i in range(7): - assert 'log_test() level %d' % i == next(lines) - - def test11(): - """Test use of log_device_set_enable()""" - lines = run_test(11) - assert 'log_test() default' - # disabled should not be displayed - assert 'log_test() enabled' - - # TODO(sjg@chromium.org): Consider structuring this as separate tests - cons = u_boot_console - test0() - test1() - test2() - test3() - test4() - test5() - test6() - test7() - test8() - test9() - test10() - test11() - @pytest.mark.buildconfigspec('cmd_log') def test_log_format(u_boot_console): """Test the 'log format' and 'log rec' commands""" |