diff options
author | Tom Rini <trini@konsulko.com> | 2020-10-29 11:30:15 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2020-10-29 11:30:15 -0400 |
commit | 47754334b164eae4fde538c406ff3678dfb05042 (patch) | |
tree | 5683d789f5b9b57d0006dbfbb0f7d03782deca10 | |
parent | cdeb7b8f984e6d9bcdc5a6fdda6107af156d47bf (diff) | |
parent | 908daf86f96a44176ecd1e04f1ec71e143aa45f5 (diff) | |
download | u-boot-47754334b164eae4fde538c406ff3678dfb05042.tar.gz |
Merge tag 'xilinx-for-v2021.01-v2' of https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze
Xilinx changes for v2021.01-v2
common:
- Add support for 64bit loadables from SPL
xilinx:
- Update documentation and record ownership
- Enable eeprom board detection based legacy and fru formats
- Add support for FRU format
microblaze:
- Optimize low level ASM code
- Enable SPI/I2C
- Enable distro boot
zynq:
- Add support for Zturn V5
zynqmp:
- Improve silicon detection code
- Enable several kconfig options
- Align DT with the latest state
- Enabling security commands
- Enable and support FPGA loading from SPL
- Optimize xilinx_pm_request() calling
versal:
- Some DTs/Kconfig/defconfig alignments
- Add binding header for clock and power
zynq-sdhci:
- Add support for tap delay programming
zynq-spi/zynq-qspi:
- Use clock framework for getting clocks
xilinx-spi:
- Fix some code issues (unused variables)
serial:
- Check return value from clock functions in pl01x
74 files changed, 2987 insertions, 561 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 857e236aa4..1505e74559 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 diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index d8b0a913be..bd97604f16 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/versal-mini-emmc0.dts b/arch/arm/dts/versal-mini-emmc0.dts index 7826a28213..6a6e7467a2 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 2f28f856a6..c342e6bdf7 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 0000000000..1d7af02893 --- /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 0000000000..536632a09a --- /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 600e8ee025..620b24a25e 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 a76e640466..9b4320fe6e 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 cb8cfd2f35..d09141c3bc 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 f2b3ceab13..1c12eac715 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 9dd61e25f6..88386b23e5 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 ff6b3c7e3d..99a17bccb3 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 cbec299b7d..9479737aa2 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 c80d0a8812..64507b5d84 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 0000000000..212028478c --- /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 b0f60c40a5..cdc06a39ce 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 180dfbca10..69e642429b 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 0000000000..ccf48723ff --- /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 0000000000..a3e6520257 --- /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 0000000000..fc3add7d93 --- /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 4e569e910d..e590999769 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 90e0343154..4a46ca02d7 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 a5ca4ca874..912c1143a8 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 096a7aceb9..8566171589 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 0000000000..5d573868cb --- /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 04fc7f32fe..9cd4f3f53e 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 398c6aaa45..7d8277ca40 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 c0d28a73e4..cf63ad97fa 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 5fde0aed7d..1cab25f00a 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 28f067a251..731285a736 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/common/fdt_support.c b/common/fdt_support.c index a565b470f8..5ae75df3c6 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 d54eff9033..c82d4d8015 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/spl/spl_atf.c b/common/spl/spl_atf.c index b54b4f0d22..9bd25f6b32 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 fd6086a65c..f5109e86d1 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 14f335f75f..41e0746bb0 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/avnet_ultrazedev_cc_v1_0_ultrazedev_som_v1_0_defconfig b/configs/avnet_ultrazedev_cc_v1_0_ultrazedev_som_v1_0_defconfig index 25282ba428..2426179d44 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 bfbdb49289..08c88856dc 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/syzygy_hub_defconfig b/configs/syzygy_hub_defconfig index 8f6900661a..276c476bae 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 e72cef9c36..427268bd58 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 b5c3ae4884..8837987e35 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 871f8cc5c3..b07dc04060 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 5175571c66..7291c51c2d 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 b127945297..da84c01b0a 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 264b662ece..0c816de707 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/board/xilinx/index.rst b/doc/board/xilinx/index.rst index 47f09290af..2e31fe3f3a 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 f6ea5dbe21..8c9afb482d 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 f564434b69..438912fe42 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 0000000000..2cd368b030 --- /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 0000000000..a035cff1a5 --- /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/uImage.FIT/howto.txt b/doc/uImage.FIT/howto.txt index 8592719685..019dda24a0 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 7d1b89514c..a68076bf35 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 7583f24a20..d4dc856baf 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 9483ed9cef..847a03648b 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 b67e906a76..29432ae7eb 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 d549a264d7..0628934312 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 775c17baac..147ecc0d70 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/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index dabd40a4cc..9ceff0e7c1 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/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c index 2772c25f1d..d9e35c6a2b 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 348630faf3..47a5571aec 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 3f39ef05f2..f2eddec950 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 9923931e36..cb911c34f6 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/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h index 8ca0e83c78..2b41242350 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 8b416327b5..f1d2594f3b 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 0b201a2b4d..00c9718819 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 3f57423b78..ef9c768e48 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 4b7af37056..ced7f6ffb2 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 0000000000..264d634d22 --- /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 0000000000..1b75175edc --- /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/mmc.h b/include/mmc.h index ac7b54f1a7..1d377e0281 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 f69d5f81fb..1fd20ec086 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/u-boot/rsa-mod-exp.h b/include/u-boot/rsa-mod-exp.h index 1da8af1bb8..7b7c2915a9 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 b07e3e0692..7b713438f7 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/rsa/rsa-mod-exp.c b/lib/rsa/rsa-mod-exp.c index 78c688d14c..74f9eb16cc 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 01ac3c2094..fb1ceb1318 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; |