diff options
69 files changed, 3967 insertions, 23 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 2ebec1f7b40..ba9fdb5a667 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -279,6 +279,19 @@ F: arch/arm/cpu/armv8/hisilicon F: arch/arm/include/asm/arch-hi6220/ F: arch/arm/include/asm/arch-hi3660/ +ARM HPE GXP ARCHITECTURE +M: Jean-Marie Verdun <verdun@hpe.com> +M: Nick Hawkins <nick.hawkins@hpe.com> +S: Maintained +F: arch/arm/dts/hpe-bmc* +F: arch/arm/dts/hpe-gxp* +F: arch/arm/mach-hpe/ +F: board/hpe/ +F: configs/gxp_defconfig +F: doc/device-tree-bindings/spi/hpe,gxp-spi.yaml +F: drivers/timer/gxp-timer.c +F: drivers/spi/gxp_spi.c + ARM IPQ40XX M: Robert Marko <robert.marko@sartura.hr> M: Luka Kovacic <luka.kovacic@sartura.hr> @@ -2415,6 +2415,7 @@ rarpboot- boot image via network using RARP/TFTP protocol diskboot- boot from IDE devicebootd - boot default, i.e., run 'bootcmd' loads - load S-Record file over serial line loadb - load binary file over serial line (kermit mode) +loadm - load binary blob from source address to destination address md - memory display mm - memory modify (auto-incrementing) nm - memory modify (constant address) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c618aad8018..dab785efad5 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1352,6 +1352,12 @@ config ARCH_VEXPRESS64 select ENV_IS_IN_FLASH if MTD imply DISTRO_DEFAULTS +config TARGET_CORSTONE1000 + bool "Support Corstone1000 Platform" + select ARM64 + select PL01X_SERIAL + select DM + config TARGET_TOTAL_COMPUTE bool "Support Total Compute Platform" select ARM64 @@ -2089,6 +2095,12 @@ config TARGET_XENGUEST_ARM64 select SSCANF imply OF_HAS_PRIOR_STAGE +config ARCH_GXP + bool "Support HPE GXP SoCs" + select DM + select OF_CONTROL + imply CMD_DM + endchoice config SUPPORT_PASSING_ATAGS @@ -2199,6 +2211,8 @@ source "arch/arm/mach-davinci/Kconfig" source "arch/arm/mach-exynos/Kconfig" +source "arch/arm/mach-hpe/gxp/Kconfig" + source "arch/arm/mach-highbank/Kconfig" source "arch/arm/mach-integrator/Kconfig" @@ -2300,7 +2314,7 @@ source "arch/arm/mach-nexell/Kconfig" source "arch/arm/mach-npcm/Kconfig" source "board/armltd/total_compute/Kconfig" - +source "board/armltd/corstone1000/Kconfig" source "board/bosch/shc/Kconfig" source "board/bosch/guardian/Kconfig" source "board/Marvell/octeontx/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index a342d72daac..64c58f4c4a3 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -63,6 +63,7 @@ machine-$(CONFIG_ARCH_BCMBCA) += bcmbca machine-$(CONFIG_ARCH_BCMSTB) += bcmstb machine-$(CONFIG_ARCH_DAVINCI) += davinci machine-$(CONFIG_ARCH_EXYNOS) += exynos +machine-$(CONFIG_ARCH_GXP) += hpe machine-$(CONFIG_ARCH_HIGHBANK) += highbank machine-$(CONFIG_ARCH_IPQ40XX) += ipq40xx machine-$(CONFIG_ARCH_K3) += k3 diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 85346c5e84f..4b940f85169 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -1069,6 +1069,8 @@ dtb-$(CONFIG_TARGET_OMAP3_BEAGLE) += \ omap3-beagle-xm.dtb \ omap3-beagle.dtb +dtb-$(CONFIG_TARGET_DEVKIT8000) += omap3-devkit8000.dtb + dtb-$(CONFIG_TARGET_OMAP3_IGEP00X0) += \ omap3-igep0020.dtb @@ -1245,6 +1247,8 @@ dtb-$(CONFIG_TARGET_POMELO) += phytium-pomelo.dtb dtb-$(CONFIG_TARGET_PRESIDIO_ASIC) += ca-presidio-engboard.dtb +dtb-$(CONFIG_TARGET_GXP) += hpe-bmc-dl360gen10.dts + dtb-$(CONFIG_TARGET_IMX8MM_CL_IOT_GATE) += imx8mm-cl-iot-gate.dtb \ imx8mm-cl-iot-gate-ied.dtbo \ imx8mm-cl-iot-gate-ied-adc0.dtbo \ @@ -1271,6 +1275,9 @@ dtb-$(CONFIG_TARGET_EA_LPC3250DEVKITV2) += lpc3250-ea3250.dtb dtb-$(CONFIG_ARCH_QEMU) += qemu-arm.dtb qemu-arm64.dtb +dtb-$(CONFIG_TARGET_CORSTONE1000) += corstone1000-mps3.dtb \ + corstone1000-fvp.dtb + include $(srctree)/scripts/Makefile.dts targets += $(dtb-y) diff --git a/arch/arm/dts/corstone1000-fvp.dts b/arch/arm/dts/corstone1000-fvp.dts new file mode 100644 index 00000000000..26b0f1b3cea --- /dev/null +++ b/arch/arm/dts/corstone1000-fvp.dts @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 or MIT +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * Copyright (c) 2022, Linaro Limited. All rights reserved. + * + */ + +/dts-v1/; + +#include "corstone1000.dtsi" + +/ { + model = "ARM Corstone1000 FVP (Fixed Virtual Platform)"; + compatible = "arm,corstone1000-fvp"; + + smsc: ethernet@4010000 { + compatible = "smsc,lan91c111"; + reg = <0x40100000 0x10000>; + phy-mode = "mii"; + interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>; + reg-io-width = <2>; + }; + + vmmc_v3_3d: fixed_v3_3d { + compatible = "regulator-fixed"; + regulator-name = "vmmc_supply"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + sdmmc0: mmc@40300000 { + compatible = "arm,pl18x", "arm,primecell"; + reg = <0x40300000 0x1000>; + interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; + max-frequency = <12000000>; + vmmc-supply = <&vmmc_v3_3d>; + clocks = <&smbclk>, <&refclk100mhz>; + clock-names = "smclk", "apb_pclk"; + }; + + sdmmc1: mmc@50000000 { + compatible = "arm,pl18x", "arm,primecell"; + reg = <0x50000000 0x10000>; + interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>; + max-frequency = <12000000>; + vmmc-supply = <&vmmc_v3_3d>; + clocks = <&smbclk>, <&refclk100mhz>; + clock-names = "smclk", "apb_pclk"; + }; +}; diff --git a/arch/arm/dts/corstone1000-mps3.dts b/arch/arm/dts/corstone1000-mps3.dts new file mode 100644 index 00000000000..e3146747c2d --- /dev/null +++ b/arch/arm/dts/corstone1000-mps3.dts @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 or MIT +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * Copyright (c) 2022, Linaro Limited. All rights reserved. + * + */ + +/dts-v1/; + +#include "corstone1000.dtsi" + +/ { + model = "ARM Corstone1000 FPGA MPS3 board"; + compatible = "arm,corstone1000-mps3"; + + smsc: ethernet@4010000 { + compatible = "smsc,lan9220", "smsc,lan9115"; + reg = <0x40100000 0x10000>; + phy-mode = "mii"; + interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>; + reg-io-width = <2>; + smsc,irq-push-pull; + }; + + usb_host: usb@40200000 { + compatible = "nxp,usb-isp1763"; + reg = <0x40200000 0x100000>; + interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>; + bus-width = <16>; + dr_mode = "host"; + }; +}; diff --git a/arch/arm/dts/corstone1000.dtsi b/arch/arm/dts/corstone1000.dtsi new file mode 100644 index 00000000000..4e46826f883 --- /dev/null +++ b/arch/arm/dts/corstone1000.dtsi @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0 or MIT +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * Copyright (c) 2022, Linaro Limited. All rights reserved. + * + */ + +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a35"; + reg = <0>; + next-level-cache = <&L2_0>; + }; + }; + + memory@88200000 { + device_type = "memory"; + reg = <0x88200000 0x77e00000>; + }; + + gic: interrupt-controller@1c000000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x1c010000 0x1000>, + <0x1c02f000 0x2000>, + <0x1c04f000 0x1000>, + <0x1c06f000 0x2000>; + interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(1) | + IRQ_TYPE_LEVEL_LOW)>; + }; + + L2_0: l2-cache0 { + compatible = "cache"; + cache-level = <2>; + cache-size = <0x80000>; + cache-line-size = <64>; + cache-sets = <1024>; + }; + + refclk100mhz: refclk100mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + clock-output-names = "apb_pclk"; + }; + + smbclk: refclk24mhzx2 { + /* Reference 24MHz clock x 2 */ + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <48000000>; + clock-output-names = "smclk"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | + IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) | + IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) | + IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) | + IRQ_TYPE_LEVEL_LOW)>; + }; + + uartclk: uartclk { + /* UART clock - 50MHz */ + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + clock-output-names = "uartclk"; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2"; + method = "smc"; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&gic>; + ranges; + + timer@1a220000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x1a220000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + clock-frequency = <50000000>; + ranges; + + frame@1a230000 { + frame-number = <0>; + interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; + reg = <0x1a230000 0x1000>; + }; + }; + + uart0: serial@1a510000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1a510000 0x1000>; + interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&uartclk>, <&refclk100mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + uart1: serial@1a520000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1a520000 0x1000>; + interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&uartclk>, <&refclk100mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + mhu_hse1: mailbox@1b820000 { + compatible = "arm,mhuv2-tx", "arm,primecell"; + reg = <0x1b820000 0x1000>; + clocks = <&refclk100mhz>; + clock-names = "apb_pclk"; + interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>; + #mbox-cells = <2>; + arm,mhuv2-protocols = <0 0>; + secure-status = "okay"; /* secure-world-only */ + status = "disabled"; + }; + + mhu_seh1: mailbox@1b830000 { + compatible = "arm,mhuv2-rx", "arm,primecell"; + reg = <0x1b830000 0x1000>; + clocks = <&refclk100mhz>; + clock-names = "apb_pclk"; + interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>; + #mbox-cells = <2>; + arm,mhuv2-protocols = <0 0>; + secure-status = "okay"; /* secure-world-only */ + status = "disabled"; + }; + }; +}; diff --git a/arch/arm/dts/hpe-bmc-dl360gen10.dts b/arch/arm/dts/hpe-bmc-dl360gen10.dts new file mode 100644 index 00000000000..b8030d9d9fd --- /dev/null +++ b/arch/arm/dts/hpe-bmc-dl360gen10.dts @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree file for HPE DL360Gen10 + */ + +/include/ "hpe-gxp-u-boot.dtsi" + +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "hpe,gxp-dl360gen10", "hpe,gxp"; + model = "Hewlett Packard Enterprise ProLiant dl360 Gen10"; + + aliases { + serial0 = &uartc; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0x40000000 0x20000000>; + }; +}; diff --git a/arch/arm/dts/hpe-gxp-u-boot.dtsi b/arch/arm/dts/hpe-gxp-u-boot.dtsi new file mode 100644 index 00000000000..7a2b488521f --- /dev/null +++ b/arch/arm/dts/hpe-gxp-u-boot.dtsi @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree file for HPE GXP + */ + +/include/ "hpe-gxp.dtsi" + +/ { + + axi { + u-boot,dm-pre-reloc; + + ahb@c0000000 { + u-boot,dm-pre-reloc; + + spi0: spi@200 { + compatible = "hpe,gxp-spi"; + reg = <0x200 0x80>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + }; + }; + }; +}; diff --git a/arch/arm/dts/hpe-gxp.dtsi b/arch/arm/dts/hpe-gxp.dtsi new file mode 100644 index 00000000000..cf735b3c4f3 --- /dev/null +++ b/arch/arm/dts/hpe-gxp.dtsi @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree file for HPE GXP + */ + +/dts-v1/; +/ { + model = "Hewlett Packard Enterprise GXP BMC"; + compatible = "hpe,gxp"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + compatible = "arm,cortex-a9"; + reg = <0>; + device_type = "cpu"; + next-level-cache = <&L2>; + }; + }; + + clocks { + pll: clock-0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1600000000>; + }; + + iopclk: clock-1 { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clock-div = <4>; + clock-mult = <1>; + clocks = <&pll>; + }; + }; + + axi { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + dma-ranges; + + L2: cache-controller@b0040000 { + compatible = "arm,pl310-cache"; + reg = <0xb0040000 0x1000>; + cache-unified; + cache-level = <2>; + }; + + ahb@c0000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xc0000000 0x30000000>; + dma-ranges; + + vic0: interrupt-controller@eff0000 { + compatible = "arm,pl192-vic"; + reg = <0xeff0000 0x1000>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + vic1: interrupt-controller@80f00000 { + compatible = "arm,pl192-vic"; + reg = <0x80f00000 0x1000>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + uarta: serial@e0 { + compatible = "ns16550a"; + reg = <0xe0 0x8>; + interrupts = <17>; + interrupt-parent = <&vic0>; + clock-frequency = <1846153>; + reg-shift = <0>; + }; + + uartb: serial@e8 { + compatible = "ns16550a"; + reg = <0xe8 0x8>; + interrupts = <18>; + interrupt-parent = <&vic0>; + clock-frequency = <1846153>; + reg-shift = <0>; + }; + + uartc: serial@f0 { + compatible = "ns16550a"; + reg = <0xf0 0x8>; + interrupts = <19>; + interrupt-parent = <&vic0>; + clock-frequency = <1846153>; + reg-shift = <0>; + }; + + usb0: usb@efe0000 { + compatible = "hpe,gxp-ehci", "generic-ehci"; + reg = <0xefe0000 0x100>; + interrupts = <7>; + interrupt-parent = <&vic0>; + }; + + st: timer@80 { + compatible = "hpe,gxp-timer"; + reg = <0x80 0x16>; + interrupts = <0>; + interrupt-parent = <&vic0>; + clocks = <&iopclk>; + clock-names = "iop"; + }; + + usb1: usb@efe0100 { + compatible = "hpe,gxp-ohci", "generic-ohci"; + reg = <0xefe0100 0x110>; + interrupts = <6>; + interrupt-parent = <&vic0>; + }; + }; + }; +}; diff --git a/arch/arm/dts/omap3-devkit8000-u-boot.dtsi b/arch/arm/dts/omap3-devkit8000-u-boot.dtsi new file mode 100644 index 00000000000..a5768b7281d --- /dev/null +++ b/arch/arm/dts/omap3-devkit8000-u-boot.dtsi @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * U-Boot additions + * + * (C) Copyright 2017 Derald D. Woods <woods.technical@gmail.com> + */ + +#include "omap3-u-boot.dtsi" + +/ { + chosen { + stdout-path = &uart3; + }; + + ethernet@2c000000 { + compatible = "davicom,dm9000"; + reg = <0x2c000000 2 0x2c000400 2>; + bank-width = <2>; + }; +}; diff --git a/arch/arm/dts/omap3-devkit8000.dts b/arch/arm/dts/omap3-devkit8000.dts new file mode 100644 index 00000000000..eee3ba073b1 --- /dev/null +++ b/arch/arm/dts/omap3-devkit8000.dts @@ -0,0 +1,349 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Anthoine Bourgeois <anthoine.bourgeois@gmail.com> + */ +/dts-v1/; + +#include "omap34xx.dtsi" +/ { + model = "TimLL OMAP3 Devkit8000"; + compatible = "timll,omap3-devkit8000", "ti,omap3430", "ti,omap3"; + + aliases { + display1 = &dvi0; + display2 = &tv0; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + leds { + compatible = "gpio-leds"; + + heartbeat { + label = "devkit8000::led1"; + gpios = <&gpio6 26 GPIO_ACTIVE_HIGH>; /* 186 -> LED1 */ + default-state = "on"; + linux,default-trigger = "heartbeat"; + }; + + mmc { + label = "devkit8000::led2"; + gpios = <&gpio6 3 GPIO_ACTIVE_HIGH>; /* 163 -> LED2 */ + default-state = "on"; + linux,default-trigger = "none"; + }; + + usr { + label = "devkit8000::led3"; + gpios = <&gpio6 4 GPIO_ACTIVE_HIGH>; /* 164 -> LED3 */ + default-state = "on"; + linux,default-trigger = "usr"; + }; + + pmu_stat { + label = "devkit8000::pmu_stat"; + gpios = <&twl_gpio 19 GPIO_ACTIVE_HIGH>; /* LEDB */ + }; + }; + + sound { + compatible = "ti,omap-twl4030"; + ti,model = "devkit8000"; + + ti,mcbsp = <&mcbsp2>; + ti,audio-routing = + "Ext Spk", "PREDRIVEL", + "Ext Spk", "PREDRIVER", + "MAINMIC", "Main Mic", + "Main Mic", "Mic Bias 1"; + }; + + tfp410: encoder0 { + compatible = "ti,tfp410"; + powerdown-gpios = <&twl_gpio 7 GPIO_ACTIVE_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + tfp410_in: endpoint { + remote-endpoint = <&dpi_dvi_out>; + }; + }; + + port@1 { + reg = <1>; + + tfp410_out: endpoint { + remote-endpoint = <&dvi_connector_in>; + }; + }; + }; + }; + + dvi0: connector0 { + compatible = "dvi-connector"; + label = "dvi"; + + digital; + + ddc-i2c-bus = <&i2c2>; + + port { + dvi_connector_in: endpoint { + remote-endpoint = <&tfp410_out>; + }; + }; + }; + + tv0: connector1 { + compatible = "svideo-connector"; + label = "tv"; + + port { + tv_connector_in: endpoint { + remote-endpoint = <&venc_out>; + }; + }; + }; +}; + +&i2c1 { + clock-frequency = <2600000>; + + twl: twl@48 { + reg = <0x48>; + interrupts = <7>; /* SYS_NIRQ cascaded to intc */ + + twl_audio: audio { + compatible = "ti,twl4030-audio"; + codec { + }; + }; + }; +}; + +&i2c2 { + clock-frequency = <400000>; +}; + +&i2c3 { + status = "disabled"; +}; + +#include "twl4030.dtsi" +#include "twl4030_omap3.dtsi" + +&mmc1 { + vmmc-supply = <&vmmc1>; + vqmmc-supply = <&vsim>; + bus-width = <8>; +}; + +&mmc2 { + status = "disabled"; +}; + +&mmc3 { + status = "disabled"; +}; + +&twl_gpio { + ti,use-leds; + /* + * pulldowns: + * BIT(1), BIT(2), BIT(6), BIT(7), BIT(8), BIT(13) + * BIT(15), BIT(16), BIT(17) + */ + ti,pulldowns = <0x03a1c6>; +}; + +&wdt2 { + status = "disabled"; +}; + +&mcbsp2 { + status = "okay"; +}; + +&gpmc { + ranges = <0 0 0x30000000 0x1000000 /* CS0: 16MB for NAND */ + 6 0 0x2c000000 0x1000000>; /* CS6: 16MB for DM9000 */ + + nand@0,0 { + compatible = "ti,omap2-nand"; + reg = <0 0 4>; /* CS0, offset 0, IO size 4 */ + interrupt-parent = <&gpmc>; + interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ + <1 IRQ_TYPE_NONE>; /* termcount */ + nand-bus-width = <16>; + gpmc,device-width = <2>; + ti,nand-ecc-opt = "sw"; + + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <44>; + gpmc,cs-wr-off-ns = <44>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <34>; + gpmc,adv-wr-off-ns = <44>; + gpmc,we-off-ns = <40>; + gpmc,oe-off-ns = <54>; + gpmc,access-ns = <64>; + gpmc,rd-cycle-ns = <82>; + gpmc,wr-cycle-ns = <82>; + gpmc,wr-access-ns = <40>; + gpmc,wr-data-mux-bus-ns = <0>; + + #address-cells = <1>; + #size-cells = <1>; + + x-loader@0 { + label = "X-Loader"; + reg = <0 0x80000>; + }; + + bootloaders@80000 { + label = "U-Boot"; + reg = <0x80000 0x1e0000>; + }; + + bootloaders_env@260000 { + label = "U-Boot Env"; + reg = <0x260000 0x20000>; + }; + + kernel@280000 { + label = "Kernel"; + reg = <0x280000 0x400000>; + }; + + filesystem@680000 { + label = "File System"; + reg = <0x680000 0xf980000>; + }; + }; + + ethernet@6,0 { + compatible = "davicom,dm9000"; + reg = <6 0x000 2 + 6 0x400 2>; /* CS6, offset 0 and 0x400, IO size 2 */ + bank-width = <2>; + interrupt-parent = <&gpio1>; + interrupts = <25 IRQ_TYPE_LEVEL_LOW>; + davicom,no-eeprom; + + gpmc,mux-add-data = <0>; + gpmc,device-width = <1>; + gpmc,wait-pin = <0>; + gpmc,cycle2cycle-samecsen; + gpmc,cycle2cycle-diffcsen; + + gpmc,cs-on-ns = <6>; + gpmc,cs-rd-off-ns = <180>; + gpmc,cs-wr-off-ns = <180>; + gpmc,adv-on-ns = <0>; + gpmc,adv-rd-off-ns = <18>; + gpmc,adv-wr-off-ns = <48>; + gpmc,oe-on-ns = <54>; + gpmc,oe-off-ns = <168>; + gpmc,we-on-ns = <54>; + gpmc,we-off-ns = <168>; + gpmc,rd-cycle-ns = <186>; + gpmc,wr-cycle-ns = <186>; + gpmc,access-ns = <144>; + gpmc,page-burst-access-ns = <24>; + gpmc,bus-turnaround-ns = <90>; + gpmc,cycle2cycle-delay-ns = <90>; + gpmc,wait-monitoring-ns = <0>; + gpmc,clk-activation-ns = <0>; + gpmc,wr-data-mux-bus-ns = <0>; + gpmc,wr-access-ns = <0>; + }; +}; + +&omap3_pmx_core { + dss_dpi_pins: pinmux_dss_dpi_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ + OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ + OMAP3_CORE1_IOPAD(0x20d8, PIN_OUTPUT | MUX_MODE0) /* dss_vsync.dss_vsync */ + OMAP3_CORE1_IOPAD(0x20da, PIN_OUTPUT | MUX_MODE0) /* dss_acbias.dss_acbias */ + OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE0) /* dss_data0.dss_data0 */ + OMAP3_CORE1_IOPAD(0x20de, PIN_OUTPUT | MUX_MODE0) /* dss_data1.dss_data1 */ + OMAP3_CORE1_IOPAD(0x20e0, PIN_OUTPUT | MUX_MODE0) /* dss_data2.dss_data2 */ + OMAP3_CORE1_IOPAD(0x20e2, PIN_OUTPUT | MUX_MODE0) /* dss_data3.dss_data3 */ + OMAP3_CORE1_IOPAD(0x20e4, PIN_OUTPUT | MUX_MODE0) /* dss_data4.dss_data4 */ + OMAP3_CORE1_IOPAD(0x20e6, PIN_OUTPUT | MUX_MODE0) /* dss_data5.dss_data5 */ + OMAP3_CORE1_IOPAD(0x20e8, PIN_OUTPUT | MUX_MODE0) /* dss_data6.dss_data6 */ + OMAP3_CORE1_IOPAD(0x20ea, PIN_OUTPUT | MUX_MODE0) /* dss_data7.dss_data7 */ + OMAP3_CORE1_IOPAD(0x20ec, PIN_OUTPUT | MUX_MODE0) /* dss_data8.dss_data8 */ + OMAP3_CORE1_IOPAD(0x20ee, PIN_OUTPUT | MUX_MODE0) /* dss_data9.dss_data9 */ + OMAP3_CORE1_IOPAD(0x20f0, PIN_OUTPUT | MUX_MODE0) /* dss_data10.dss_data10 */ + OMAP3_CORE1_IOPAD(0x20f2, PIN_OUTPUT | MUX_MODE0) /* dss_data11.dss_data11 */ + OMAP3_CORE1_IOPAD(0x20f4, PIN_OUTPUT | MUX_MODE0) /* dss_data12.dss_data12 */ + OMAP3_CORE1_IOPAD(0x20f6, PIN_OUTPUT | MUX_MODE0) /* dss_data13.dss_data13 */ + OMAP3_CORE1_IOPAD(0x20f8, PIN_OUTPUT | MUX_MODE0) /* dss_data14.dss_data14 */ + OMAP3_CORE1_IOPAD(0x20fa, PIN_OUTPUT | MUX_MODE0) /* dss_data15.dss_data15 */ + OMAP3_CORE1_IOPAD(0x20fc, PIN_OUTPUT | MUX_MODE0) /* dss_data16.dss_data16 */ + OMAP3_CORE1_IOPAD(0x20fe, PIN_OUTPUT | MUX_MODE0) /* dss_data17.dss_data17 */ + OMAP3_CORE1_IOPAD(0x2100, PIN_OUTPUT | MUX_MODE0) /* dss_data18.dss_data18 */ + OMAP3_CORE1_IOPAD(0x2102, PIN_OUTPUT | MUX_MODE0) /* dss_data19.dss_data19 */ + OMAP3_CORE1_IOPAD(0x2104, PIN_OUTPUT | MUX_MODE0) /* dss_data20.dss_data20 */ + OMAP3_CORE1_IOPAD(0x2106, PIN_OUTPUT | MUX_MODE0) /* dss_data21.dss_data21 */ + OMAP3_CORE1_IOPAD(0x2108, PIN_OUTPUT | MUX_MODE0) /* dss_data22.dss_data22 */ + OMAP3_CORE1_IOPAD(0x210a, PIN_OUTPUT | MUX_MODE0) /* dss_data23.dss_data23 */ + >; + }; +}; + +&vpll1 { + /* Needed for DSS */ + regulator-name = "vdds_dsi"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; +}; + +&dss { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&dss_dpi_pins>; + + vdds_dsi-supply = <&vpll1>; + vdda_dac-supply = <&vdac>; + + port { + #address-cells = <1>; + #size-cells = <0>; + dpi_dvi_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&tfp410_in>; + data-lines = <24>; + }; + + endpoint@1 { + reg = <1>; + }; + }; +}; + +&venc { + status = "okay"; + + vdda-supply = <&vdac>; + + port { + venc_out: endpoint { + remote-endpoint = <&tv_connector_in>; + ti,channels = <2>; + }; + }; +}; diff --git a/arch/arm/dts/omap3-u-boot.dtsi b/arch/arm/dts/omap3-u-boot.dtsi index 32bea6b6d9b..96d8ac54539 100644 --- a/arch/arm/dts/omap3-u-boot.dtsi +++ b/arch/arm/dts/omap3-u-boot.dtsi @@ -78,4 +78,5 @@ &i2c1 { u-boot,dm-spl; + clock-frequency = <100000>; }; diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2600.h b/arch/arm/include/asm/arch-aspeed/scu_ast2600.h index 7c5aab98b63..251bfa269bf 100644 --- a/arch/arm/include/asm/arch-aspeed/scu_ast2600.h +++ b/arch/arm/include/asm/arch-aspeed/scu_ast2600.h @@ -87,6 +87,9 @@ #define SCU_HWSTRAP1_CPU_FREQ_SHIFT 8 #define SCU_HWSTRAP1_MAC2_INTF BIT(7) #define SCU_HWSTRAP1_MAC1_INTF BIT(6) +#define SCU_HWSTRAP1_BOOT_EMMC BIT(2) + +#define SCU_HWSTRAP2_BOOT_UART BIT(8) #define SCU_EFUSE_DIS_DP BIT(17) #define SCU_EFUSE_DIS_VGA BIT(14) diff --git a/arch/arm/include/asm/arch-npcm7xx/aes.h b/arch/arm/include/asm/arch-npcm7xx/aes.h new file mode 100644 index 00000000000..255efcb5ce0 --- /dev/null +++ b/arch/arm/include/asm/arch-npcm7xx/aes.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef _NPCM_AES_H_ +#define _NPCM_AES_H_ + +#define AES_OP_ENCRYPT 0 +#define AES_OP_DECRYPT 1 +#define SIZE_AES_BLOCK (AES128_KEY_LENGTH) + +struct npcm_aes_regs { + unsigned char reserved_0[0x400]; // 0x000 + unsigned int aes_key_0; // 0x400 + unsigned int aes_key_1; // 0x404 + unsigned int aes_key_2; // 0x408 + unsigned int aes_key_3; // 0x40c + unsigned char reserved_1[0x30]; // 0x410 + unsigned int aes_iv_0; // 0x440 + unsigned char reserved_2[0x1c]; // 0x444 + unsigned int aes_ctr_0; // 0x460 + unsigned char reserved_3[0x0c]; // 0x464 + unsigned int aes_busy; // 0x470 + unsigned char reserved_4[0x04]; // 0x474 + unsigned int aes_sk; // 0x478 + unsigned char reserved_5[0x14]; // 0x47c + unsigned int aes_prev_iv_0; // 0x490 + unsigned char reserved_6[0x0c]; // 0x494 + unsigned int aes_din_dout; // 0x4a0 + unsigned char reserved_7[0x1c]; // 0x4a4 + unsigned int aes_control; // 0x4c0 + unsigned int aes_version; // 0x4c4 + unsigned int aes_hw_flags; // 0x4c8 + unsigned char reserved_8[0x28]; // 0x4cc + unsigned int aes_sw_reset; // 0x4f4 + unsigned char reserved_9[0x08]; // 0x4f8 + unsigned int aes_fifo_data; // 0x500 + unsigned char reserved_10[0xfc]; // 0x504 + unsigned int aes_fifo_status; // 0x600 +}; + +#define AES_BUSY_BIT BIT(0) +#define SW_RESET_BIT BIT(0) +#define AES_SK_BIT BIT(0) + +#define DIN_FIFO_FULL BIT(0) +#define DIN_FIFO_EMPTY BIT(1) +#define DOUT_FIFO_FULL BIT(2) +#define DOUT_FIFO_EMPTY BIT(3) +#define DIN_FIFO_OVERFLOW BIT(4) +#define DOUT_FIFO_UNDERFLOW BIT(5) + +int npcm_aes_select_key(u8 fkeyind); + +#endif diff --git a/arch/arm/include/asm/arch-npcm7xx/otp.h b/arch/arm/include/asm/arch-npcm7xx/otp.h new file mode 100644 index 00000000000..11d1e8550c9 --- /dev/null +++ b/arch/arm/include/asm/arch-npcm7xx/otp.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef _NPCM_OTP_H_ +#define _NPCM_OTP_H_ + +#ifdef CONFIG_ARCH_NPCM8XX +enum { + NPCM_KEY_SA = 0, + NPCM_FUSE_SA = 0, + NPCM_NUM_OF_SA = 1 +}; +#else +enum { + NPCM_KEY_SA = 0, + NPCM_FUSE_SA = 1, + NPCM_NUM_OF_SA = 2 +}; +#endif + +struct npcm_otp_regs { + unsigned int fst; + unsigned int faddr; + unsigned int fdata; + unsigned int fcfg; + unsigned int fustrap_fkeyind; + unsigned int fctl; +}; + +#define FST_RDY BIT(0) +#define FST_RDST BIT(1) +#define FST_RIEN BIT(2) + +#ifdef CONFIG_ARCH_NPCM8XX +#define FADDR_BYTEADDR(addr) ((addr) << 3) +#define FADDR_BITPOS(pos) ((pos) << 0) +#define FADDR_VAL(addr, pos) (FADDR_BITPOS(pos) | FADDR_BYTEADDR(addr)) +#define FADDR_IN_PROG BIT(16) +#else +#define FADDR_BYTEADDR(addr) ((addr) << 0) +#define FADDR_BITPOS(pos) ((pos) << 10) +#define FADDR_VAL(addr, pos) (FADDR_BYTEADDR(addr) | FADDR_BITPOS(pos)) +#define FADDR_IN_PROG BIT(16) +#endif + +#define FDATA_MASK (0xff) + +#define FUSTRAP_O_SECBOOT BIT(23) + +#define FCFG_FDIS BIT(31) + +#define FKEYIND_KVAL BIT(0) +#define FKEYIND_KSIZE_MASK (0x00000070) +#define FKEYIND_KSIZE_128 (0x40) +#define FKEYIND_KSIZE_192 (0x50) +#define FKEYIND_KSIZE_256 (0x60) +#define FKEYIND_KIND_MASK (0x000c0000) +#define FKEYIND_KIND_KEY(indx) ((indx) << 18) + +// Program cycle initiation values (sequence of two adjacent writes) +#define PROGRAM_ARM 0x1 +#define PROGRAM_INIT 0xBF79E5D0 + +#define OTP2_BASE 0xF018A000 +#define FUSTRAP (OTP2_BASE + 0x10) + +// Read cycle initiation value +#define READ_INIT 0x02 + +// Value to clean FDATA contents +#define FDATA_CLEAN_VALUE 0x01 + +#ifdef CONFIG_ARCH_NPCM8XX +#define NPCM_OTP_ARR_BYTE_SIZE 8192 +#else +#define NPCM_OTP_ARR_BYTE_SIZE 1024 +#endif + +#define MIN_PROGRAM_PULSES 4 +#define MAX_PROGRAM_PULSES 20 +#define NPCM_OTP_ARR_BYTE_SIZE 1024 + +int fuse_prog_image(u32 bank, uintptr_t address); +int fuse_program_data(u32 bank, u32 word, u8 *data, u32 size); +int npcm_otp_select_key(u8 key_index); +bool npcm_otp_is_fuse_array_disabled(u32 arr); +void npcm_otp_nibble_parity_ecc_encode(u8 *datain, u8 *dataout, u32 size); +void npcm_otp_majority_rule_ecc_encode(u8 *datain, u8 *dataout, u32 size); +void npcm_arch_preboot_os(void); + +#endif diff --git a/arch/arm/mach-aspeed/ast2600/spl.c b/arch/arm/mach-aspeed/ast2600/spl.c index 6c49d6aede8..53c8a15bf9c 100644 --- a/arch/arm/mach-aspeed/ast2600/spl.c +++ b/arch/arm/mach-aspeed/ast2600/spl.c @@ -7,6 +7,7 @@ #include <dm.h> #include <spl.h> #include <init.h> +#include <linux/err.h> #include <asm/io.h> #include <asm/arch/scu_ast2600.h> #include <asm/global_data.h> @@ -21,8 +22,37 @@ void board_init_f(ulong dummy) dram_init(); } +/* + * Try to detect the boot mode. Fallback to the default, + * memory mapped SPI XIP booting if detection failed. + */ u32 spl_boot_device(void) { + int rc; + struct udevice *scu_dev; + struct ast2600_scu *scu; + + rc = uclass_get_device_by_driver(UCLASS_CLK, + DM_DRIVER_GET(aspeed_ast2600_scu), &scu_dev); + if (rc) { + debug("%s: failed to get SCU driver\n", __func__); + goto out; + } + + scu = devfdt_get_addr_ptr(scu_dev); + if (IS_ERR_OR_NULL(scu)) { + debug("%s: failed to get SCU base\n", __func__); + goto out; + } + + /* boot from UART has higher priority */ + if (scu->hwstrap2 & SCU_HWSTRAP2_BOOT_UART) + return BOOT_DEVICE_UART; + + if (scu->hwstrap1 & SCU_HWSTRAP1_BOOT_EMMC) + return BOOT_DEVICE_MMC1; + +out: return BOOT_DEVICE_RAM; } diff --git a/arch/arm/mach-aspeed/ast2600/u-boot-spl.lds b/arch/arm/mach-aspeed/ast2600/u-boot-spl.lds new file mode 100644 index 00000000000..22b4e16d35c --- /dev/null +++ b/arch/arm/mach-aspeed/ast2600/u-boot-spl.lds @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2004-2008 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2022 + * Chia-Wei Wang <chiawei_wang@aspeedtech.com> + */ + +MEMORY { .nor : ORIGIN = CONFIG_SPL_TEXT_BASE, + LENGTH = CONFIG_SPL_SIZE_LIMIT } +MEMORY { .bss : ORIGIN = CONFIG_SPL_BSS_START_ADDR, + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + __image_copy_start = .; + *(.vectors) + CPUDIR/start.o (.text*) + *(.text*) + *(.glue*) + } > .nor + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } > .nor + + . = ALIGN(4); + .data : { + *(.data*) + } > .nor + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } > .nor + + . = ALIGN(4); + .binman_sym_table : { + __binman_sym_start = .; + KEEP(*(SORT(.binman_sym*))); + __binman_sym_end = .; + } > .nor + + . = ALIGN(4); + + __image_copy_end = .; + + .rel.dyn : { + __rel_dyn_start = .; + *(.rel*) + __rel_dyn_end = .; + } > .nor + + .end : + { + *(.__end) + } > .nor + + _image_binary_end = .; + + .bss : { + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } > .bss + + __bss_size = __bss_end - __bss_start; +} + +#if defined(IMAGE_MAX_SIZE) +ASSERT(__image_copy_end - __image_copy_start <= (IMAGE_MAX_SIZE), \ + "SPL image too big"); +#endif + +#if defined(CONFIG_SPL_BSS_MAX_SIZE) +ASSERT(__bss_end - __bss_start <= (CONFIG_SPL_BSS_MAX_SIZE), \ + "SPL image BSS too big"); +#endif + +#if defined(CONFIG_SPL_MAX_FOOTPRINT) +ASSERT(__bss_end - _start <= (CONFIG_SPL_MAX_FOOTPRINT), \ + "SPL image plus BSS too big"); +#endif diff --git a/arch/arm/mach-hpe/Makefile b/arch/arm/mach-hpe/Makefile new file mode 100644 index 00000000000..afe5f7a29ee --- /dev/null +++ b/arch/arm/mach-hpe/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_SOC_GXP) += gxp/ diff --git a/arch/arm/mach-hpe/gxp/Kconfig b/arch/arm/mach-hpe/gxp/Kconfig new file mode 100644 index 00000000000..2d43133ab06 --- /dev/null +++ b/arch/arm/mach-hpe/gxp/Kconfig @@ -0,0 +1,9 @@ +if ARCH_GXP + +config SOC_GXP + bool + select CPU_V7A + +source "board/hpe/gxp/Kconfig" + +endif diff --git a/arch/arm/mach-hpe/gxp/Makefile b/arch/arm/mach-hpe/gxp/Makefile new file mode 100644 index 00000000000..f3cc6684b89 --- /dev/null +++ b/arch/arm/mach-hpe/gxp/Makefile @@ -0,0 +1 @@ +obj-y += reset.o diff --git a/arch/arm/mach-hpe/gxp/reset.c b/arch/arm/mach-hpe/gxp/reset.c new file mode 100644 index 00000000000..ce018a35d94 --- /dev/null +++ b/arch/arm/mach-hpe/gxp/reset.c @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * GXP driver + * + * (C) Copyright 2022 Hewlett Packard Enterprise Development LP. + * Author: Nick Hawkins <nick.hawkins@hpe.com> + * Author: Jean-Marie Verdun <verdun@hpe.com> + */ + +#include <asm/io.h> + +#define GXP_CCR 0xc0000000 + +/* empty to satisfy current lowlevel_init, can be removed any time */ +void lowlevel_init(void) +{ +} + +void reset_cpu(ulong ignored) +{ + writel(1, GXP_CCR); + + while (1) + ; /* loop forever till reset */ +} diff --git a/board/armltd/corstone1000/Kconfig b/board/armltd/corstone1000/Kconfig new file mode 100644 index 00000000000..709674d4cf7 --- /dev/null +++ b/board/armltd/corstone1000/Kconfig @@ -0,0 +1,12 @@ +if TARGET_CORSTONE1000 + +config SYS_BOARD + default "corstone1000" + +config SYS_VENDOR + default "armltd" + +config SYS_CONFIG_NAME + default "corstone1000" + +endif diff --git a/board/armltd/corstone1000/MAINTAINERS b/board/armltd/corstone1000/MAINTAINERS new file mode 100644 index 00000000000..8c905686de7 --- /dev/null +++ b/board/armltd/corstone1000/MAINTAINERS @@ -0,0 +1,7 @@ +CORSTONE1000 BOARD +M: Rui Miguel Silva <rui.silva@linaro.org> +M: Vishnu Banavath <vishnu.banavath@arm.com> +S: Maintained +F: board/armltd/corstone1000/ +F: include/configs/corstone1000.h +F: configs/corstone1000_defconfig diff --git a/board/armltd/corstone1000/Makefile b/board/armltd/corstone1000/Makefile new file mode 100644 index 00000000000..77a82c28929 --- /dev/null +++ b/board/armltd/corstone1000/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2022 Arm Limited +# (C) Copyright 2022 Linaro +# Rui Miguel Silva <rui.silva@linaro.org> + +obj-y := corstone1000.o diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c new file mode 100644 index 00000000000..4f4b96a095c --- /dev/null +++ b/board/armltd/corstone1000/corstone1000.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2022 ARM Limited + * (C) Copyright 2022 Linaro + * Rui Miguel Silva <rui.silva@linaro.org> + */ + +#include <common.h> +#include <dm.h> +#include <netdev.h> +#include <dm/platform_data/serial_pl01x.h> +#include <asm/armv8/mmu.h> +#include <asm/global_data.h> + +static struct mm_region corstone1000_mem_map[] = { + { + /* CVM */ + .virt = 0x02000000UL, + .phys = 0x02000000UL, + .size = 0x02000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + /* QSPI */ + .virt = 0x08000000UL, + .phys = 0x08000000UL, + .size = 0x08000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + /* Host Peripherals */ + .virt = 0x1A000000UL, + .phys = 0x1A000000UL, + .size = 0x26000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* USB */ + .virt = 0x40200000UL, + .phys = 0x40200000UL, + .size = 0x00100000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* ethernet */ + .virt = 0x40100000UL, + .phys = 0x40100000UL, + .size = 0x00100000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* OCVM */ + .virt = 0x80000000UL, + .phys = 0x80000000UL, + .size = 0x80000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + /* List terminator */ + 0, + } +}; + +struct mm_region *mem_map = corstone1000_mem_map; + +int board_init(void) +{ + return 0; +} + +int dram_init(void) +{ + gd->ram_size = PHYS_SDRAM_1_SIZE; + + return 0; +} + +int dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + + return 0; +} + +void reset_cpu(ulong addr) +{ +} diff --git a/board/armltd/corstone1000/corstone1000.env b/board/armltd/corstone1000/corstone1000.env new file mode 100644 index 00000000000..b24ff07fc6b --- /dev/null +++ b/board/armltd/corstone1000/corstone1000.env @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +usb_pgood_delay=250 +boot_bank_flag=0x08002000 +kernel_addr_bank_0=0x083EE000 +kernel_addr_bank_1=0x0936E000 +retrieve_kernel_load_addr= + if itest.l *${boot_bank_flag} == 0; then + setenv kernel_addr $kernel_addr_bank_0; + else + setenv kernel_addr $kernel_addr_bank_1; + fi; +kernel_addr_r=0x88200000 diff --git a/board/hpe/gxp/Kconfig b/board/hpe/gxp/Kconfig new file mode 100644 index 00000000000..5b154a3f6e5 --- /dev/null +++ b/board/hpe/gxp/Kconfig @@ -0,0 +1,46 @@ +choice + prompt "SoC select" + +config TARGET_GXP + bool "GXP" + select DM + select SOC_GXP + imply CMD_DM + +config TARGET_GXP2 + bool "GXP2" + select DM + select SOC_GXP + select GXP_ECC + imply CMD_DM + +endchoice + +choice + prompt "GXP VROM size" + default GXP_VROM_64MB + optional + +config GXP_VROM_64MB + bool "64MB" + +config GXP_VROM_32MB + bool "32MB" +endchoice + +config GXP_ECC + bool "Enable memory ECC protected" + help + Use half of memory to enable ECC protected + +config SYS_BOARD + default "gxp" + +config SYS_VENDOR + default "hpe" + +config SYS_CONFIG_NAME + default "gxp" + +config SYS_TEXT_BASE + default 0x50000000 diff --git a/board/hpe/gxp/Makefile b/board/hpe/gxp/Makefile new file mode 100644 index 00000000000..775d6bf8497 --- /dev/null +++ b/board/hpe/gxp/Makefile @@ -0,0 +1 @@ +obj-y += gxp_board.o diff --git a/board/hpe/gxp/gxp.env b/board/hpe/gxp/gxp.env new file mode 100644 index 00000000000..4760bf1663a --- /dev/null +++ b/board/hpe/gxp/gxp.env @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +recover_file=openbmc-hpe-recovery-image.mtd +recover_cmd=usb start; mw.b 0xD100000D 0x40; + if fatload usb 0 0x50000000 $recover_file 0x4C0000 0x80000; then + setenv bootargs console=ttyS0,115200 recovery; + setenv force_recovery; + saveenv; + bootm 0x50000000; + else + while itest 0 < 1; do + mw.b 0xd1000005 0xc0; + sleep .1; + mw.b 0xd1000005 0x00; + sleep .1; + done; + fi; + reset; +spiboot=if itest.b *0xD10000B2 == 6; then + run recover_cmd; + fi; + if printenv force_recovery; then + run recover_cmd; + else + bootm 0xfc080000; + run recover_cmd; + fi; diff --git a/board/hpe/gxp/gxp_board.c b/board/hpe/gxp/gxp_board.c new file mode 100644 index 00000000000..d94d9b8a19e --- /dev/null +++ b/board/hpe/gxp/gxp_board.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * GXP timer driver + * + * (C) Copyright 2022 Hewlett Packard Enterprise Development LP. + * Author: Nick Hawkins <nick.hawkins@hpe.com> + * Author: Jean-Marie Verdun <verdun@hpe.com> + */ + +#include <linux/sizes.h> +#include <asm/io.h> +#include <dm.h> +#include <dm/uclass.h> +#include <ram.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define ECHI_CMD 0xcefe0010 + +int board_init(void) +{ + writel(0x00080002, ECHI_CMD); + + return 0; +} + +int dram_init(void) +{ + if (IS_ENABLED(CONFIG_TARGET_GXP)) { + if (IS_ENABLED(CONFIG_GXP_ECC)) { + /* 0x0f800000 */ + gd->ram_size = SZ_128M + SZ_64M + SZ_32M + SZ_16M + SZ_8M; + } else { + /* 0x1f000000 */ + gd->ram_size = SZ_256M + SZ_128M + SZ_64M + SZ_32M + SZ_16M; + } + + if (IS_ENABLED(CONFIG_GXP_VROM_64MB)) { + if (IS_ENABLED(CONFIG_GXP_ECC)) { + /* 0x0c000000 */ + gd->ram_size = SZ_128M + SZ_64M; + } else { + /* 0x18000000 */ + gd->ram_size = SZ_256M + SZ_128M; + } + } + + if (IS_ENABLED(CONFIG_GXP_VROM_32MB)) { + if (IS_ENABLED(CONFIG_GXP_ECC)) { + /* 0x0e000000 */ + gd->ram_size = SZ_128M + SZ_64M + SZ_32M; + } else { + /* 0x1c000000 */ + gd->ram_size = SZ_256M + SZ_128M + SZ_64M; + } + } + } + + if (IS_ENABLED(CONFIG_TARGET_GXP2)) { + /* 0x1b200000 */ + gd->ram_size = SZ_256M + SZ_128M + SZ_32M + SZ_16M + SZ_2M; + if (IS_ENABLED(CONFIG_GXP_VROM_64MB)) { + /* 0x14000000 */ + gd->ram_size = SZ_256M + SZ_64M; + } + + if (IS_ENABLED(CONFIG_GXP_VROM_32MB)) { + /* 0x18000000 */ + gd->ram_size = SZ_256M + SZ_128M; + } + } + + return 0; +} + diff --git a/cmd/Kconfig b/cmd/Kconfig index 9a0b7203112..dea3729d132 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1160,6 +1160,11 @@ config CMD_LOADB help Load a binary file over serial line. +config CMD_LOADM + bool "loadm" + help + Load a binary over memory mapped. + config CMD_LOADS bool "loads" default y diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 827fcd97dfd..37ce659fa12 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -35,6 +35,18 @@ static void *image_addr; static size_t image_size; /** + * efi_get_image_parameters() - return image parameters + * + * @img_addr: address of loaded image in memory + * @img_size: size of loaded image + */ +void efi_get_image_parameters(void **img_addr, size_t *img_size) +{ + *img_addr = image_addr; + *img_size = image_size; +} + +/** * efi_clear_bootdev() - clear boot device */ static void efi_clear_bootdev(void) diff --git a/cmd/load.c b/cmd/load.c index 7e4a552d90e..1224a7f85bb 100644 --- a/cmd/load.c +++ b/cmd/load.c @@ -1063,6 +1063,44 @@ static ulong load_serial_ymodem(ulong offset, int mode) #endif +#if defined(CONFIG_CMD_LOADM) +static int do_load_memory_bin(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + ulong addr, dest, size; + void *src, *dst; + + if (argc != 4) + return CMD_RET_USAGE; + + addr = simple_strtoul(argv[1], NULL, 16); + + dest = simple_strtoul(argv[2], NULL, 16); + + size = simple_strtoul(argv[3], NULL, 16); + + if (!size) { + printf("loadm: can not load zero bytes\n"); + return 1; + } + + src = map_sysmem(addr, size); + dst = map_sysmem(dest, size); + + memcpy(dst, src, size); + + unmap_sysmem(src); + unmap_sysmem(dst); + + if (IS_ENABLED(CONFIG_CMD_BOOTEFI)) + efi_set_bootdev("Mem", "", "", map_sysmem(dest, 0), size); + + printf("loaded bin to memory: size: %lu\n", size); + + return 0; +} +#endif + /* -------------------------------------------------------------------- */ #if defined(CONFIG_CMD_LOADS) @@ -1137,3 +1175,13 @@ U_BOOT_CMD( ); #endif /* CONFIG_CMD_LOADB */ + +#if defined(CONFIG_CMD_LOADM) +U_BOOT_CMD( + loadm, 4, 0, do_load_memory_bin, + "load binary blob from source address to destination address", + "[src_addr] [dst_addr] [size]\n" + " - load a binary blob from one memory location to other" + " from src_addr to dst_addr by size bytes" +); +#endif /* CONFIG_CMD_LOADM */ diff --git a/cmd/misc.c b/cmd/misc.c index bcd8d960ee0..ec32b41ed1e 100644 --- a/cmd/misc.c +++ b/cmd/misc.c @@ -44,7 +44,6 @@ static int do_misc_list(struct cmd_tbl *cmdtp, int flag, static int do_misc_op(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], enum misc_op op) { - int (*misc_op)(struct udevice *, int, void *, int); struct udevice *dev; int offset; void *buf; @@ -62,11 +61,10 @@ static int do_misc_op(struct cmd_tbl *cmdtp, int flag, size = hextoul(argv[3], NULL); if (op == MISC_OP_READ) - misc_op = misc_read; + ret = misc_read(dev, offset, buf, size); else - misc_op = misc_write; + ret = misc_write(dev, offset, buf, size); - ret = misc_op(dev, offset, buf, size); if (ret < 0) { if (ret == -ENOSYS) { printf("The device does not support %s\n", diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig new file mode 100644 index 00000000000..49a651aba23 --- /dev/null +++ b/configs/corstone1000_defconfig @@ -0,0 +1,52 @@ +CONFIG_ARM=y +CONFIG_SKIP_LOWLEVEL_INIT=y +CONFIG_TARGET_CORSTONE1000=y +CONFIG_SYS_TEXT_BASE=0x80000000 +CONFIG_SYS_MALLOC_LEN=0x2000000 +CONFIG_NR_DRAM_BANKS=1 +CONFIG_DEFAULT_DEVICE_TREE="corstone1000-mps3" +CONFIG_IDENT_STRING=" corstone1000 aarch64 " +CONFIG_SYS_LOAD_ADDR=0x82100000 +CONFIG_DISTRO_DEFAULTS=y +CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y +CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x83f00000 +CONFIG_FIT=y +CONFIG_BOOTDELAY=3 +CONFIG_USE_BOOTARGS=y +CONFIG_BOOTARGS="console=ttyAMA0 loglevel=9 ip=dhcp earlyprintk" +CONFIG_BOOTCOMMAND="run retrieve_kernel_load_addr; echo Loading kernel from $kernel_addr to memory ... ; loadm $kernel_addr $kernel_addr_r 0xc00000; usb start; usb reset; run distro_bootcmd; bootefi $kernel_addr_r $fdtcontroladdr;" +CONFIG_CONSOLE_RECORD=y +CONFIG_LOGLEVEL=7 +# CONFIG_DISPLAY_CPUINFO is not set +# CONFIG_DISPLAY_BOARDINFO is not set +CONFIG_SYS_PROMPT="corstone1000# " +CONFIG_SYS_MAXARGS=64 +CONFIG_SYS_CBSIZE=512 +# CONFIG_CMD_CONSOLE is not set +CONFIG_CMD_BOOTZ=y +# CONFIG_CMD_XIMG is not set +CONFIG_CMD_LOADM=y +# CONFIG_CMD_LOADS is not set +# CONFIG_CMD_SETEXPR is not set +# CONFIG_CMD_NFS is not set +CONFIG_CMD_CACHE=y +CONFIG_CMD_RTC=y +CONFIG_CMD_TIME=y +CONFIG_CMD_GETTIME=y +CONFIG_OF_CONTROL=y +CONFIG_VERSION_VARIABLE=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_REGMAP=y +CONFIG_MISC=y +# CONFIG_MMC is not set +CONFIG_PHYLIB=y +CONFIG_PHY_SMSC=y +CONFIG_DM_ETH=y +CONFIG_SMC911X=y +CONFIG_PHY=y +CONFIG_RAM=y +CONFIG_DM_RTC=y +CONFIG_RTC_EMULATION=y +CONFIG_DM_SERIAL=y +CONFIG_USB=y +CONFIG_ERRNO_STR=y diff --git a/configs/devkit8000_defconfig b/configs/devkit8000_defconfig index 4e144a9c169..a5e9f614df1 100644 --- a/configs/devkit8000_defconfig +++ b/configs/devkit8000_defconfig @@ -2,21 +2,26 @@ CONFIG_ARM=y CONFIG_ARCH_OMAP2PLUS=y CONFIG_SYS_TEXT_BASE=0x80100000 CONFIG_SYS_MALLOC_LEN=0x40000 -CONFIG_SYS_MALLOC_F_LEN=0x400 +CONFIG_SYS_MALLOC_F_LEN=0x4000 CONFIG_NR_DRAM_BANKS=2 +CONFIG_DEFAULT_DEVICE_TREE="omap3-devkit8000" CONFIG_SPL_TEXT_BASE=0x40200000 CONFIG_TARGET_DEVKIT8000=y +CONFIG_SPL_SYS_MALLOC_F_LEN=0x400 CONFIG_SPL=y CONFIG_DISTRO_DEFAULTS=y CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x4020ff00 CONFIG_BOOTCOMMAND="run autoboot" +CONFIG_USE_PREBOOT=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_SPL_MAX_SIZE=0xec00 CONFIG_SPL_BSS_START_ADDR=0x80000500 +CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SYS_SPL_MALLOC=y CONFIG_HAS_CUSTOM_SPL_MALLOC_START=y CONFIG_CUSTOM_SYS_SPL_MALLOC_ADDR=0x80208000 +# CONFIG_SPL_FS_EXT4 is not set CONFIG_SPL_NAND_DRIVERS=y CONFIG_SPL_NAND_ECC=y CONFIG_SPL_NAND_SIMPLE=y @@ -31,8 +36,8 @@ CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS=8 CONFIG_SYS_MAXARGS=64 # CONFIG_CMD_IMI is not set CONFIG_CMD_SPL=y -CONFIG_CMD_SPL_NAND_OFS=0x680000 -CONFIG_CMD_SPL_WRITE_SIZE=0x400 +CONFIG_CMD_SPL_NAND_OFS=0x280000 +CONFIG_CMD_SPL_WRITE_SIZE=0x20000 # CONFIG_CMD_FLASH is not set CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y @@ -50,16 +55,25 @@ CONFIG_JFFS2_PART_SIZE=0xF980000 CONFIG_CMD_MTDPARTS=y CONFIG_MTDIDS_DEFAULT="nand0=nand" CONFIG_MTDPARTS_DEFAULT="mtdparts=nand:512k(x-loader),1920k(u-boot),128k(u-boot-env),4m(kernel),-(fs)" +# CONFIG_ISO_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_OF_CONTROL=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_OF_SPL_REMOVE_PROPS="clocks clock-names interrupt-parent" CONFIG_ENV_OVERWRITE=y CONFIG_ENV_IS_IN_NAND=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_VERSION_VARIABLE=y CONFIG_NET_RETRY_COUNT=20 CONFIG_BOOTP_SEND_HOSTNAME=y +CONFIG_SPL_DM=y +CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_SPL_OF_TRANSLATE=y CONFIG_SYS_I2C_LEGACY=y CONFIG_SPL_SYS_I2C_LEGACY=y CONFIG_TWL4030_LED=y CONFIG_MMC_OMAP_HS=y +CONFIG_DM_I2C=y CONFIG_MTD=y CONFIG_MTD_RAW_NAND=y CONFIG_NAND_OMAP_ECCSCHEME_HAM1_CODE_HW=y @@ -70,7 +84,6 @@ CONFIG_SYS_NAND_OOBSIZE=0x40 CONFIG_SYS_NAND_BUSWIDTH_16BIT=y CONFIG_SYS_NAND_U_BOOT_LOCATIONS=y CONFIG_SYS_NAND_U_BOOT_OFFS=0x80000 +CONFIG_DM_ETH=y CONFIG_DRIVER_DM9000=y -CONFIG_CONS_INDEX=3 CONFIG_JFFS2_NAND=y -CONFIG_OF_LIBFDT=y diff --git a/configs/evb-ast2600_defconfig b/configs/evb-ast2600_defconfig index bfd0a5f2b10..a91a53da4fc 100644 --- a/configs/evb-ast2600_defconfig +++ b/configs/evb-ast2600_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_SYS_DCACHE_OFF=y CONFIG_SPL_SYS_THUMB_BUILD=y +CONFIG_SPL_LDSCRIPT="arch/arm/mach-aspeed/ast2600/u-boot-spl.lds" CONFIG_ARCH_ASPEED=y CONFIG_SYS_TEXT_BASE=0x80000000 CONFIG_SYS_MALLOC_LEN=0x2000000 @@ -32,10 +33,13 @@ CONFIG_BOOTCOMMAND="run bootspi" # CONFIG_DISPLAY_CPUINFO is not set CONFIG_SPL_SIZE_LIMIT_SUBTRACT_GD=y CONFIG_SPL_SIZE_LIMIT_SUBTRACT_MALLOC=y -CONFIG_SPL_NO_BSS_LIMIT=y +CONFIG_SPL_HAS_BSS_LINKER_SECTION=y +CONFIG_SPL_BSS_START_ADDR=0x83000000 +CONFIG_SPL_BSS_MAX_SIZE=0x1000000 CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_STACK_R=y CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000000 +CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_FIT_IMAGE_TINY=y CONFIG_SPL_DM_RESET=y CONFIG_SPL_RAM_SUPPORT=y diff --git a/configs/gxp_defconfig b/configs/gxp_defconfig new file mode 100644 index 00000000000..4408c6ce370 --- /dev/null +++ b/configs/gxp_defconfig @@ -0,0 +1,60 @@ +CONFIG_ARM=y +CONFIG_SKIP_LOWLEVEL_INIT=y +CONFIG_SYS_THUMB_BUILD=y +CONFIG_ARCH_GXP=y +CONFIG_SYS_MALLOC_LEN=0x4000000 +CONFIG_GXP_VROM_64MB=y +CONFIG_NR_DRAM_BANKS=1 +CONFIG_ENV_SIZE=0x10000 +CONFIG_ENV_OFFSET=0x60000 +CONFIG_ENV_SECT_SIZE=0x10000 +CONFIG_DEFAULT_DEVICE_TREE="hpe-bmc-dl360gen10" +CONFIG_ENV_OFFSET_REDUND=0x70000 +CONFIG_SYS_LOAD_ADDR=0x40100000 +CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y +CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x2000000 +CONFIG_FIT=y +CONFIG_FIT_SIGNATURE=y +CONFIG_FIT_VERBOSE=y +CONFIG_BOOTDELAY=5 +CONFIG_AUTOBOOT_KEYED=y +CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n" +CONFIG_AUTOBOOT_STOP_STR=" " +CONFIG_USE_BOOTARGS=y +CONFIG_BOOTARGS="earlyprintk console=ttyS2,115200 user_debug=31" +CONFIG_USE_BOOTCOMMAND=y +CONFIG_BOOTCOMMAND="run spiboot" +# CONFIG_DISPLAY_CPUINFO is not set +# CONFIG_DISPLAY_BOARDINFO is not set +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="gxp# " +# CONFIG_BOOTM_NETBSD is not set +# CONFIG_BOOTM_PLAN9 is not set +# CONFIG_BOOTM_RTEMS is not set +# CONFIG_BOOTM_VXWORKS is not set +CONFIG_CMD_GPT=y +# CONFIG_RANDOM_UUID is not set +CONFIG_CMD_MISC=y +CONFIG_CMD_FAT=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_SYS_REDUNDAND_ENVIRONMENT=y +CONFIG_NETCONSOLE=y +CONFIG_MISC=y +# CONFIG_MMC is not set +CONFIG_DM_SPI_FLASH=y +CONFIG_SF_DEFAULT_MODE=3 +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_POWER is not set +CONFIG_RAM=y +CONFIG_DM_SERIAL=y +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_GXP_SPI=y +CONFIG_TIMER=y +CONFIG_GXP_TIMER=y +CONFIG_SHA512=y diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index 9d72e39bc20..46a9b16ad3f 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -47,6 +47,7 @@ CONFIG_CMD_GPT=y CONFIG_CMD_GPT_RENAME=y CONFIG_CMD_IDE=y CONFIG_CMD_I2C=y +CONFIG_CMD_LOADM=y CONFIG_CMD_OSD=y CONFIG_CMD_PCI=y CONFIG_CMD_READ=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index be40562cc3f..86204c79088 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -67,6 +67,7 @@ CONFIG_CMD_GPT=y CONFIG_CMD_GPT_RENAME=y CONFIG_CMD_IDE=y CONFIG_CMD_I2C=y +CONFIG_CMD_LOADM=y CONFIG_CMD_LSBLK=y CONFIG_CMD_MUX=y CONFIG_CMD_OSD=y diff --git a/doc/device-tree-bindings/spi/hpe,gxp-spi.yaml b/doc/device-tree-bindings/spi/hpe,gxp-spi.yaml new file mode 100644 index 00000000000..5e23de1847c --- /dev/null +++ b/doc/device-tree-bindings/spi/hpe,gxp-spi.yaml @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/spi/hpe,gxp-spi.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: HPE GXP SPI Controller + +maintainers: + - Nick Hawkins <nick.hawkins@hpe.com> + - Jean-Marie Verdun <verdun@hpe.com> + +allOf: + - $ref: "spi-controller.yaml#" + +properties: + compatible: + const: mikrotik,rb4xx-spi + + reg: + maxItems: 1 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + spi@c00000200{ + compatible = "hpe,gxp-spi"; + reg = <0xc0000200 0x80>; + #address-cells = <1>; + #size-cells = <0>; + }; + diff --git a/doc/usage/cmd/loadm.rst b/doc/usage/cmd/loadm.rst new file mode 100644 index 00000000000..b6571140437 --- /dev/null +++ b/doc/usage/cmd/loadm.rst @@ -0,0 +1,49 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +loadm command +============= + +Synopsis +-------- + +:: + + loadm <src_addr> <dst_addr> <len> + +Description +----------- + +The loadm command is used to copy memory content from source address +to destination address and, if efi is enabled, will setup a "Mem" efi +boot device. + +The number of transferred bytes must be set by bytes parameter + +src_addr + start address of the memory location to be loaded + +dst_addr + destination address of the byte stream to be loaded + +len + number of bytes to be copied in hexadecimal. Can not be 0 (zero). + +Example +------- + +:: + + => loadm ${kernel_addr} ${kernel_addr_r} ${kernel_size} + loaded bin to memory: size: 12582912 + +Configuration +------------- + +The command is only available if CONFIG_CMD_LOADM=y. + +Return value +------------ + +The return value $? is set 0 (true) if the loading is succefull, and +is set to 1 (false) in case of error. + diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 770418434ad..8d08ea14b00 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -44,6 +44,7 @@ Shell commands cmd/fatload cmd/for cmd/load + cmd/loadm cmd/loady cmd/mbr cmd/md diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 675081ecd37..12ef84ca05c 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -6,4 +6,6 @@ source drivers/crypto/fsl/Kconfig source drivers/crypto/aspeed/Kconfig +source drivers/crypto/nuvoton/Kconfig + endmenu diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 6b762565a1f..b9105186097 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -8,3 +8,4 @@ obj-y += rsa_mod_exp/ obj-y += fsl/ obj-y += hash/ obj-y += aspeed/ +obj-y += nuvoton/ diff --git a/drivers/crypto/nuvoton/Kconfig b/drivers/crypto/nuvoton/Kconfig new file mode 100644 index 00000000000..034fcadfcc8 --- /dev/null +++ b/drivers/crypto/nuvoton/Kconfig @@ -0,0 +1,14 @@ +config NPCM_AES + bool "Support the NPCM AES algorithm" + select NPCM_OTP + help + This provides a means to encrypt and decrypt data using the NPCM + AES (Advanced Encryption Standard). This algorithm uses a symmetric + key and is widely used as a streaming cipher. This command only + supports AES256-CBC. + +config NPCM_SHA + bool "Enable NPCM cryptographic HW SHA accelerator" + help + This option enables support of NPCM cryptographic HW SHA accelerator. + It supports SHA1 and SHA256 hashing algorithms. diff --git a/drivers/crypto/nuvoton/Makefile b/drivers/crypto/nuvoton/Makefile new file mode 100644 index 00000000000..5a1173dfe73 --- /dev/null +++ b/drivers/crypto/nuvoton/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_NPCM_AES) += npcm_aes.o +obj-$(CONFIG_NPCM_SHA) += npcm_sha.o diff --git a/drivers/crypto/nuvoton/npcm_aes.c b/drivers/crypto/nuvoton/npcm_aes.c new file mode 100644 index 00000000000..6493ea108ec --- /dev/null +++ b/drivers/crypto/nuvoton/npcm_aes.c @@ -0,0 +1,301 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Nuvoton Technology Corp. + */ + +#include <common.h> +#include <dm.h> +#include <uboot_aes.h> +#include <asm/io.h> +#include <asm/arch/aes.h> +#include <asm/arch/otp.h> +#include <malloc.h> + +#define ONE_SECOND 0xC00000 + +struct npcm_aes_priv { + struct npcm_aes_regs *regs; +}; + +static struct npcm_aes_priv *aes_priv; +static u8 fkeyind_to_set = 0xff; + +static int second_timeout(u32 *addr, u32 bitmask, u32 bitpol) +{ + ulong time, i = 0; + + time = get_timer(0); + + /* default 1 second timeout */ + while (((readl(addr) & bitmask) == bitpol) && i < ONE_SECOND) + i++; + + if (i == ONE_SECOND) { + printf("%xms timeout: addr = %x, mask = %x\n", (u32)get_timer(time), + *addr, bitmask); + return -1; + } + + return 0; +} + +int npcm_aes_select_key(u8 fkeyind) +{ + if (npcm_otp_is_fuse_array_disabled(NPCM_KEY_SA)) { + printf("AES key access denied\n"); + return -EACCES; + } + + if (fkeyind < 4) + fkeyind_to_set = fkeyind; + + return 0; +} + +static int npcm_aes_init(u8 dec_enc) +{ + struct npcm_aes_regs *regs = aes_priv->regs; + u32 ctrl, orgctrlval, wrtimeout; + + /* reset hw */ + writel(readl(®s->aes_sw_reset) | SW_RESET_BIT, ®s->aes_sw_reset); + writel(readl(®s->aes_fifo_status) | DIN_FIFO_OVERFLOW, ®s->aes_fifo_status); + writel(readl(®s->aes_fifo_status) | DOUT_FIFO_UNDERFLOW, ®s->aes_fifo_status); + + /* Workaround to over come Errata #648 */ + orgctrlval = readl(®s->aes_control); + ctrl = (0x00002004 | dec_enc); /* AES256(CBC) */ + + if (ctrl != orgctrlval) { + writel(ctrl, ®s->aes_control); + + if (ctrl != readl(®s->aes_control)) { + u32 read_ctrl; + int intwr; + + for (wrtimeout = 0; wrtimeout < 1000; wrtimeout++) { + for (intwr = 0 ; intwr < 10; intwr++) { + writel(ctrl, ®s->aes_control); + writew(ctrl, (u16 *)®s->aes_control + 1); + /* Write configurable info in a single write operation */ + mb(); + } + + read_ctrl = readl(®s->aes_control); + if (ctrl == read_ctrl) + break; + } + + if (wrtimeout == 1000) { + printf("\nTIMEOUT expected data=0x%x Actual AES_CONTROL data 0x%x\n\n", + ctrl, read_ctrl); + return -EAGAIN; + } + + printf("Workaround success, wrtimeout = %d\n", wrtimeout); + } + } + + if (second_timeout(®s->aes_busy, AES_BUSY_BIT, AES_BUSY_BIT)) + return -EAGAIN; + + return 0; +} + +static inline void npcm_aes_load_iv(u8 *iv) +{ + struct npcm_aes_regs *regs = aes_priv->regs; + u32 *p = (u32 *)iv; + u32 i; + + /* Initialization Vector is loaded in 32-bit chunks */ + for (i = 0; i < (SIZE_AES_BLOCK / sizeof(u32)); i++) + writel(p[i], ®s->aes_iv_0 + i); +} + +static inline void npcm_aes_load_key(u8 *key) +{ + struct npcm_aes_regs *regs = aes_priv->regs; + u32 *p = (u32 *)key; + u32 i; + + /* The key can be loaded either via the configuration or by using sideband + * key port (aes_select_key). + * If aes_select_key has been called ('fkeyind_to_set' was set to desired + * key index) and no key is specified (key is NULL), we should use the + * key index. Otherwise, we write the given key to the registers. + */ + if (!key && fkeyind_to_set < 4) { + npcm_otp_select_key(fkeyind_to_set); + + /* Sample the new key */ + writel(readl(®s->aes_sk) | AES_SK_BIT, ®s->aes_sk); + + } else { + /* Initialization Vector is loaded in 32-bit chunks */ + for (i = 0; i < (2 * SIZE_AES_BLOCK / sizeof(u32)); i++) + writel(p[i], ®s->aes_key_0 + i); + + fkeyind_to_set = 0xff; + } +} + +static inline void npcm_aes_write(u32 *in) +{ + struct npcm_aes_regs *regs = aes_priv->regs; + u32 i; + + /* 16 Byte AES Block is written in 32-bit chunks */ + for (i = 0; i < (SIZE_AES_BLOCK / sizeof(u32)); i++) + writel(in[i], ®s->aes_fifo_data); +} + +static inline void npcm_aes_read(u32 *out) +{ + struct npcm_aes_regs *regs = aes_priv->regs; + u32 i; + + /* Data is read in 32-bit chunks */ + for (i = 0; i < (SIZE_AES_BLOCK / sizeof(u32)); i++) + out[i] = readl(®s->aes_fifo_data); +} + +static void npcm_aes_feed(u32 num_aes_blocks, u32 *datain, u32 *dataout) +{ + struct npcm_aes_regs *regs = aes_priv->regs; + u32 aes_datablk; + u32 total_blocks = num_aes_blocks; + u32 blocks_left = num_aes_blocks; + + /* data mode */ + writel(readl(®s->aes_busy) | AES_BUSY_BIT, ®s->aes_busy); + + /* Clear overflow and underflow */ + writel(readl(®s->aes_fifo_status) | DIN_FIFO_OVERFLOW, ®s->aes_fifo_status); + writel(readl(®s->aes_fifo_status) | DOUT_FIFO_UNDERFLOW, ®s->aes_fifo_status); + + /* datain/dataout is advanced in 32-bit chunks */ + aes_datablk = (SIZE_AES_BLOCK / sizeof(u32)); + + /* Quit if there is no complete blocks */ + if (total_blocks == 0) + return; + + /* Write the first block */ + if (total_blocks > 1) { + npcm_aes_write(datain); + datain += aes_datablk; + blocks_left--; + } + + /* Write the second block */ + if (total_blocks > 2) { + second_timeout(®s->aes_fifo_status, DIN_FIFO_EMPTY, 0); + npcm_aes_write(datain); + datain += aes_datablk; + blocks_left--; + } + + /* Write & read available blocks */ + while (blocks_left > 0) { + second_timeout(®s->aes_fifo_status, DIN_FIFO_FULL, DIN_FIFO_FULL); + + /* Write next block */ + npcm_aes_write(datain); + datain += aes_datablk; + + /* Wait till DOUT FIFO is empty */ + second_timeout(®s->aes_fifo_status, DOUT_FIFO_EMPTY, DOUT_FIFO_EMPTY); + + /* Read next block */ + npcm_aes_read(dataout); + dataout += aes_datablk; + + blocks_left--; + } + + if (total_blocks > 2) { + second_timeout(®s->aes_fifo_status, DOUT_FIFO_FULL, 0); + + /* Read next block */ + npcm_aes_read(dataout); + dataout += aes_datablk; + + second_timeout(®s->aes_fifo_status, DOUT_FIFO_FULL, 0); + + /* Read next block */ + npcm_aes_read(dataout); + dataout += aes_datablk; + } else if (total_blocks > 1) { + second_timeout(®s->aes_fifo_status, DOUT_FIFO_FULL, 0); + + /* Read next block */ + npcm_aes_read(dataout); + dataout += aes_datablk; + } +} + +void aes_expand_key(u8 *key, u32 key_size, u8 *expkey) +{ + /* npcm hw expands the key automatically, just copy it */ + memcpy(expkey, key, SIZE_AES_BLOCK * 2); +} + +void aes_cbc_encrypt_blocks(u32 key_size, u8 *key_exp, u8 *iv, u8 *src, u8 *dst, + u32 num_aes_blocks) +{ + if (npcm_aes_init(AES_OP_ENCRYPT)) + return; + + npcm_aes_load_iv(iv); + + npcm_aes_load_key(key_exp); + + npcm_aes_feed(num_aes_blocks, (u32 *)src, (u32 *)dst); +} + +void aes_cbc_decrypt_blocks(u32 key_size, u8 *key_exp, u8 *iv, u8 *src, u8 *dst, + u32 num_aes_blocks) +{ + if (npcm_aes_init(AES_OP_DECRYPT)) + return; + + npcm_aes_load_iv(iv); + + npcm_aes_load_key(key_exp); + + npcm_aes_feed(num_aes_blocks, (u32 *)src, (u32 *)dst); +} + +static int npcm_aes_bind(struct udevice *dev) +{ + aes_priv = calloc(1, sizeof(struct npcm_aes_priv)); + if (!aes_priv) { + printf("%s: %d\n", __func__, __LINE__); + return -ENOMEM; + } + + aes_priv->regs = dev_read_addr_ptr(dev); + if (!aes_priv->regs) { + printf("Cannot find aes reg address, binding failed\n"); + return -EINVAL; + } + + printf("AES: NPCM AES module bind OK\n"); + + return 0; +} + +static const struct udevice_id npcm_aes_ids[] = { + { .compatible = "nuvoton,npcm845-aes" }, + { .compatible = "nuvoton,npcm750-aes" }, + { } +}; + +U_BOOT_DRIVER(npcm_aes) = { + .name = "npcm_aes", + .id = UCLASS_MISC, + .of_match = npcm_aes_ids, + .priv_auto = sizeof(struct npcm_aes_priv), + .bind = npcm_aes_bind, +}; diff --git a/drivers/crypto/nuvoton/npcm_sha.c b/drivers/crypto/nuvoton/npcm_sha.c new file mode 100644 index 00000000000..7ebdfa16f4f --- /dev/null +++ b/drivers/crypto/nuvoton/npcm_sha.c @@ -0,0 +1,897 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2022 Nuvoton Technology Corp. + */ + +#include <common.h> +#include <dm.h> +#include <hash.h> +#include <malloc.h> +#include <uboot_aes.h> +#include <asm/io.h> + +#define HASH_DIG_H_NUM 8 + +#define HASH_CTR_STS_SHA_EN BIT(0) +#define HASH_CTR_STS_SHA_BUSY BIT(1) +#define HASH_CTR_STS_SHA_RST BIT(2) +#define HASH_CFG_SHA1_SHA2 BIT(0) + +/* SHA type */ +enum npcm_sha_type { + npcm_sha_type_sha2 = 0, + npcm_sha_type_sha1, + npcm_sha_type_num +}; + +struct npcm_sha_regs { + unsigned int hash_data_in; + unsigned char hash_ctr_sts; + unsigned char reserved_0[0x03]; + unsigned char hash_cfg; + unsigned char reserved_1[0x03]; + unsigned char hash_ver; + unsigned char reserved_2[0x13]; + unsigned int hash_dig[HASH_DIG_H_NUM]; +}; + +struct npcm_sha_priv { + struct npcm_sha_regs *regs; +}; + +static struct npcm_sha_priv *sha_priv; + +#ifdef SHA_DEBUG_MODULE +#define sha_print(fmt, args...) printf(fmt, ##args) +#else +#define sha_print(fmt, args...) (void)0 +#endif + +#define SHA_BLOCK_LENGTH (512 / 8) +#define SHA_2_HASH_LENGTH (256 / 8) +#define SHA_1_HASH_LENGTH (160 / 8) +#define SHA_HASH_LENGTH(type) ((type == npcm_sha_type_sha2) ? \ + (SHA_2_HASH_LENGTH) : (SHA_1_HASH_LENGTH)) + +#define SHA_SECRUN_BUFF_SIZE 64 +#define SHA_TIMEOUT 100 +#define SHA_DATA_LAST_BYTE 0x80 + +#define SHA2_NUM_OF_SELF_TESTS 3 +#define SHA1_NUM_OF_SELF_TESTS 4 + +#define NUVOTON_ALIGNMENT 4 + +/*-----------------------------------------------------------------------------*/ +/* SHA instance struct handler */ +/*-----------------------------------------------------------------------------*/ +struct SHA_HANDLE_T { + u32 hv[SHA_2_HASH_LENGTH / sizeof(u32)]; + u32 length0; + u32 length1; + u32 block[SHA_BLOCK_LENGTH / sizeof(u32)]; + u8 type; + bool active; +}; + +// The # of bytes currently in the sha block buffer +#define SHA_BUFF_POS(length) ((length) & (SHA_BLOCK_LENGTH - 1)) + +// The # of free bytes in the sha block buffer +#define SHA_BUFF_FREE(length) (SHA_BLOCK_LENGTH - SHA_BUFF_POS(length)) + +static void SHA_FlushLocalBuffer_l(const u32 *buff); +static int SHA_BusyWait_l(void); +static void SHA_GetShaDigest_l(u8 *hashdigest, u8 type); +static void SHA_SetShaDigest_l(const u32 *hashdigest, u8 type); +static void SHA_SetBlock_l(const u8 *data, u32 len, u16 position, u32 *block); +static void SHA_ClearBlock_l(u16 len, u16 position, u32 *block); +static void SHA_SetLength32_l(struct SHA_HANDLE_T *handleptr, u32 *block); + +static int SHA_Init(struct SHA_HANDLE_T *handleptr); +static int SHA_Start(struct SHA_HANDLE_T *handleptr, u8 type); +static int SHA_Update(struct SHA_HANDLE_T *handleptr, const u8 *buffer, u32 len); +static int SHA_Finish(struct SHA_HANDLE_T *handleptr, u8 *hashdigest); +static int SHA_Reset(void); +static int SHA_Power(bool on); +#ifdef SHA_PRINT +static void SHA_PrintRegs(void); +static void SHA_PrintVersion(void); +#endif + +static struct SHA_HANDLE_T sha_handle; + +/*----------------------------------------------------------------------------*/ +/* Checks if give function returns int error, and returns the error */ +/* immediately after SHA disabling */ +/*----------------------------------------------------------------------------*/ +int npcm_sha_check(int status) +{ + if (status != 0) { + SHA_Power(false); + return status; + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_sha_calc */ +/* */ +/* Parameters: type - SHA module type */ +/* inBuff - Pointer to a buffer containing the data to */ +/* be hashed */ +/* len - Length of the data to hash */ +/* hashDigest - Pointer to a buffer where the reseulting */ +/* digest will be copied to */ +/* */ +/* Returns: 0 on success or other int error code on error */ +/* Side effects: */ +/* Description: */ +/* This routine performs complete SHA calculation in one */ +/* step */ +/*----------------------------------------------------------------------------*/ +int npcm_sha_calc(u8 type, const u8 *inbuff, u32 len, u8 *hashdigest) +{ + int status; + struct SHA_HANDLE_T handle; + + SHA_Init(&handle); + SHA_Power(true); + SHA_Reset(); + SHA_Start(&handle, type); + status = SHA_Update(&handle, inbuff, len); + npcm_sha_check(status); + status = SHA_Finish(&handle, hashdigest); + npcm_sha_check(status); + SHA_Power(false); + + return 0; +} + +/* + * Computes hash value of input pbuf using h/w acceleration + * + * @param in_addr A pointer to the input buffer + * @param bufleni Byte length of input buffer + * @param out_addr A pointer to the output buffer. When complete + * 32 bytes are copied to pout[0]...pout[31]. Thus, a user + * should allocate at least 32 bytes at pOut in advance. + * @param chunk_size chunk size for sha256 + */ +void hw_sha256(const uchar *in_addr, uint buflen, uchar *out_addr, uint chunk_size) +{ + puts("\nhw_sha256 using BMC HW accelerator\t"); + npcm_sha_calc(npcm_sha_type_sha2, (u8 *)in_addr, buflen, (u8 *)out_addr); +} + +/* + * Computes hash value of input pbuf using h/w acceleration + * + * @param in_addr A pointer to the input buffer + * @param bufleni Byte length of input buffer + * @param out_addr A pointer to the output buffer. When complete + * 32 bytes are copied to pout[0]...pout[31]. Thus, a user + * should allocate at least 32 bytes at pOut in advance. + * @param chunk_size chunk_size for sha1 + */ +void hw_sha1(const uchar *in_addr, uint buflen, uchar *out_addr, uint chunk_size) +{ + puts("\nhw_sha1 using BMC HW accelerator\t"); + npcm_sha_calc(npcm_sha_type_sha1, (u8 *)in_addr, buflen, (u8 *)out_addr); +} + +/* + * Create the context for sha progressive hashing using h/w acceleration + * + * @algo: Pointer to the hash_algo struct + * @ctxp: Pointer to the pointer of the context for hashing + * @return 0 if ok, -ve on error + */ +int hw_sha_init(struct hash_algo *algo, void **ctxp) +{ + const char *algo_name1 = "sha1"; + const char *algo_name2 = "sha256"; + + SHA_Init(&sha_handle); + SHA_Power(true); + SHA_Reset(); + if (!strcmp(algo_name1, algo->name)) + return SHA_Start(&sha_handle, npcm_sha_type_sha1); + else if (!strcmp(algo_name2, algo->name)) + return SHA_Start(&sha_handle, npcm_sha_type_sha2); + else + return -EPROTO; +} + +/* + * Update buffer for sha progressive hashing using h/w acceleration + * + * The context is freed by this function if an error occurs. + * + * @algo: Pointer to the hash_algo struct + * @ctx: Pointer to the context for hashing + * @buf: Pointer to the buffer being hashed + * @size: Size of the buffer being hashed + * @is_last: 1 if this is the last update; 0 otherwise + * @return 0 if ok, -ve on error + */ +int hw_sha_update(struct hash_algo *algo, void *ctx, const void *buf, + unsigned int size, int is_last) +{ + return SHA_Update(&sha_handle, buf, size); +} + +/* + * Copy sha hash result at destination location + * + * The context is freed after completion of hash operation or after an error. + * + * @algo: Pointer to the hash_algo struct + * @ctx: Pointer to the context for hashing + * @dest_buf: Pointer to the destination buffer where hash is to be copied + * @size: Size of the buffer being hashed + * @return 0 if ok, -ve on error + */ +int hw_sha_finish(struct hash_algo *algo, void *ctx, void *dest_buf, int size) +{ + int status; + + status = SHA_Finish(&sha_handle, dest_buf); + npcm_sha_check(status); + return SHA_Power(false); +} + +/*----------------------------------------------------------------------------*/ +/* Function: SHA_Init */ +/* */ +/* Parameters: handlePtr - SHA processing handle pointer */ +/* Returns: 0 on success or other int error code on error. */ +/* Side effects: */ +/* Description: */ +/* This routine initialize the SHA module */ +/*----------------------------------------------------------------------------*/ +static int SHA_Init(struct SHA_HANDLE_T *handleptr) +{ + handleptr->active = false; + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/* Function: SHA_Start */ +/* */ +/* Parameters: handlePtr - SHA processing handle pointer */ +/* type - SHA module type */ +/* */ +/* Returns: 0 on success or other int error code on error. */ +/* Side effects: */ +/* Description: */ +/* This routine start a single SHA process */ +/*----------------------------------------------------------------------------*/ +static int SHA_Start(struct SHA_HANDLE_T *handleptr, u8 type) +{ + struct npcm_sha_regs *regs = sha_priv->regs; + + // Initialize handle + handleptr->length0 = 0; + handleptr->length1 = 0; + handleptr->type = type; + handleptr->active = true; + + // Set SHA type + writeb(handleptr->type & HASH_CFG_SHA1_SHA2, ®s->hash_cfg); + + // Reset SHA hardware + SHA_Reset(); + + /* The handlePtr->hv is initialized with the correct IV as the SHA engine + * automatically fill the HASH_DIG_Hn registers according to SHA spec + * (following SHA_RST assertion) + */ + SHA_GetShaDigest_l((u8 *)handleptr->hv, type); + + // Init block with zeros + memset(handleptr->block, 0, sizeof(handleptr->block)); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/* Function: SHA_Update */ +/* */ +/* Parameters: handlePtr - SHA processing handle pointer */ +/* buffer - Pointer to the data that will be added to */ +/* the hash calculation */ +/* len - Length of data to add to SHA calculation */ +/* */ +/* */ +/* Returns: 0 on success or other int error code on error */ +/* Side effects: */ +/* Description: */ +/* This routine adds data to previously started SHA */ +/* calculation */ +/*----------------------------------------------------------------------------*/ +static int SHA_Update(struct SHA_HANDLE_T *handleptr, const u8 *buffer, u32 len) +{ + struct npcm_sha_regs *regs = sha_priv->regs; + u32 localbuffer[SHA_SECRUN_BUFF_SIZE / sizeof(u32)]; + u32 bufferlen = len; + u16 pos = 0; + u8 *blockptr; + int status; + + // Error check + if (!handleptr->active) + return -EPROTO; + + // Wait till SHA is not busy + status = SHA_BusyWait_l(); + npcm_sha_check(status); + + // Set SHA type + writeb(handleptr->type & HASH_CFG_SHA1_SHA2, ®s->hash_cfg); + + // Write SHA latest digest into SHA module + SHA_SetShaDigest_l(handleptr->hv, handleptr->type); + + // Set number of unhashed bytes which remained from last update + pos = SHA_BUFF_POS(handleptr->length0); + + // Copy unhashed bytes which remained from last update to secrun buffer + SHA_SetBlock_l((u8 *)handleptr->block, pos, 0, localbuffer); + + while (len) { + // Wait for the hardware to be available (in case we are hashing) + status = SHA_BusyWait_l(); + npcm_sha_check(status); + + // Move as much bytes as we can into the secrun buffer + bufferlen = min(len, SHA_BUFF_FREE(handleptr->length0)); + + // Copy current given buffer to the secrun buffer + SHA_SetBlock_l((u8 *)buffer, bufferlen, pos, localbuffer); + + // Update size of hashed bytes + handleptr->length0 += bufferlen; + + if (handleptr->length0 < bufferlen) + handleptr->length1++; + + // Update length of data left to digest + len -= bufferlen; + + // Update given buffer pointer + buffer += bufferlen; + + // If secrun buffer is full + if (SHA_BUFF_POS(handleptr->length0) == 0) { + /* We just filled up the buffer perfectly, so let it hash (we'll + * unload the hash only when we are done with all hashing) + */ + SHA_FlushLocalBuffer_l(localbuffer); + + pos = 0; + bufferlen = 0; + } + } + + // Wait till SHA is not busy + status = SHA_BusyWait_l(); + npcm_sha_check(status); + + /* Copy unhashed bytes from given buffer to handle block for next update/finish */ + blockptr = (u8 *)handleptr->block; + while (bufferlen) + blockptr[--bufferlen + pos] = *(--buffer); + + // Save SHA current digest + SHA_GetShaDigest_l((u8 *)handleptr->hv, handleptr->type); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/* Function: SHA_Finish */ +/* */ +/* Parameters: handlePtr - SHA processing handle pointer */ +/* hashDigest - Pointer to a buffer where the final digest */ +/* will be copied to */ +/* */ +/* Returns: 0 on success or other int error code on error */ +/* Side effects: */ +/* Description: */ +/* This routine finish SHA calculation and get */ +/* the resulting SHA digest */ +/*----------------------------------------------------------------------------*/ +static int SHA_Finish(struct SHA_HANDLE_T *handleptr, u8 *hashdigest) +{ + struct npcm_sha_regs *regs = sha_priv->regs; + u32 localbuffer[SHA_SECRUN_BUFF_SIZE / sizeof(u32)]; + const u8 lastbyte = SHA_DATA_LAST_BYTE; + u16 pos; + int status; + + // Error check + if (!handleptr->active) + return -EPROTO; + + // Set SHA type + writeb(handleptr->type & HASH_CFG_SHA1_SHA2, ®s->hash_cfg); + + // Wait till SHA is not busy + status = SHA_BusyWait_l(); + npcm_sha_check(status); + + // Finish off the current buffer with the SHA spec'ed padding + pos = SHA_BUFF_POS(handleptr->length0); + + // Init SHA digest + SHA_SetShaDigest_l(handleptr->hv, handleptr->type); + + // Load data into secrun buffer + SHA_SetBlock_l((u8 *)handleptr->block, pos, 0, localbuffer); + + // Set data last byte as in SHA algorithm spec + SHA_SetBlock_l(&lastbyte, 1, pos++, localbuffer); + + // If the remainder of data is longer then one block + if (pos > (SHA_BLOCK_LENGTH - 8)) { + /* The length will be in the next block Pad the rest of the last block with 0's */ + SHA_ClearBlock_l((SHA_BLOCK_LENGTH - pos), pos, localbuffer); + + // Hash the current block + SHA_FlushLocalBuffer_l(localbuffer); + + pos = 0; + + // Wait till SHA is not busy + status = SHA_BusyWait_l(); + npcm_sha_check(status); + } + + // Pad the rest of the last block with 0's except for the last 8-3 bytes + SHA_ClearBlock_l((SHA_BLOCK_LENGTH - (8 - 3)) - pos, pos, localbuffer); + + /* The last 8-3 bytes are set to the bit-length of the message in big-endian form */ + SHA_SetLength32_l(handleptr, localbuffer); + + // Hash all that, and save the hash for the caller + SHA_FlushLocalBuffer_l(localbuffer); + + // Wait till SHA is not busy + status = SHA_BusyWait_l(); + npcm_sha_check(status); + + // Save SHA final digest into given buffer + SHA_GetShaDigest_l(hashdigest, handleptr->type); + + // Free handle + handleptr->active = false; + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/* Function: SHA_Reset */ +/* */ +/* Parameters: none */ +/* Returns: none */ +/* Side effects: */ +/* Description: */ +/* This routine reset SHA module */ +/*----------------------------------------------------------------------------*/ +static int SHA_Reset(void) +{ + struct npcm_sha_regs *regs = sha_priv->regs; + + writel(readl(®s->hash_ctr_sts) | HASH_CTR_STS_SHA_RST, ®s->hash_ctr_sts); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/* Function: SHA_Power */ +/* */ +/* Parameters: on - true enable the module, false disable the module */ +/* Returns: none */ +/* Side effects: */ +/* Description: */ +/* This routine set SHA module power on/off */ +/*----------------------------------------------------------------------------*/ +static int SHA_Power(bool on) +{ + struct npcm_sha_regs *regs = sha_priv->regs; + u8 hash_sts; + + hash_sts = readb(®s->hash_ctr_sts) & ~HASH_CTR_STS_SHA_EN; + writeb(hash_sts | (on & HASH_CTR_STS_SHA_EN), ®s->hash_ctr_sts); + + return 0; +} + +#ifdef SHA_PRINT +/*----------------------------------------------------------------------------*/ +/* Function: SHA_PrintRegs */ +/* */ +/* Parameters: none */ +/* Returns: none */ +/* Side effects: */ +/* Description: */ +/* This routine prints the module registers */ +/*----------------------------------------------------------------------------*/ +static void SHA_PrintRegs(void) +{ +#ifdef SHA_DEBUG_MODULE + struct npcm_sha_regs *regs = sha_priv->regs; +#endif + unsigned int i; + + sha_print("/*--------------*/\n"); + sha_print("/* SHA */\n"); + sha_print("/*--------------*/\n\n"); + + sha_print("HASH_CTR_STS = 0x%02X\n", readb(®s->hash_ctr_sts)); + sha_print("HASH_CFG = 0x%02X\n", readb(®s->hash_cfg)); + + for (i = 0; i < HASH_DIG_H_NUM; i++) + sha_print("HASH_DIG_H%d = 0x%08X\n", i, readl(®s->hash_dig[i])); + + sha_print("HASH_VER = 0x%08X\n", readb(®s->hash_ver)); + + sha_print("\n"); +} + +/*----------------------------------------------------------------------------*/ +/* Function: SHA_PrintVersion */ +/* */ +/* Parameters: none */ +/* Returns: none */ +/* Side effects: */ +/* Description: */ +/* This routine prints the module version */ +/*----------------------------------------------------------------------------*/ +static void SHA_PrintVersion(void) +{ + struct npcm_sha_regs *regs = sha_priv->regs; + + printf("SHA MODULE VER = %d\n", readb(®s->hash_ver)); +} +#endif + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_sha_selftest */ +/* */ +/* Parameters: type - SHA module type */ +/* Returns: 0 on success or other int error code on error */ +/* Side effects: */ +/* Description: */ +/* This routine performs various tests on the SHA HW and SW */ +/*----------------------------------------------------------------------------*/ +int npcm_sha_selftest(u8 type) +{ + int status; + struct SHA_HANDLE_T handle; + u8 hashdigest[max(SHA_1_HASH_LENGTH, SHA_2_HASH_LENGTH)]; + u16 i, j; + + /*------------------------------------------------------------------------*/ + /* SHA1 tests info */ + /*------------------------------------------------------------------------*/ + + static const u8 sha1selftestbuff[SHA1_NUM_OF_SELF_TESTS][94] = { + {"abc"}, + {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"}, + {"0123456789012345678901234567890123456789012345678901234567890123"}, + {0x30, 0x5c, 0x30, 0x2c, 0x02, 0x01, 0x00, 0x30, 0x09, 0x06, 0x05, 0x2b, + 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x30, 0x06, 0x06, 0x04, 0x67, 0x2a, + 0x01, 0x0c, 0x04, 0x14, 0xe1, 0xb6, 0x93, 0xfe, 0x33, 0x43, 0xc1, 0x20, + 0x5d, 0x4b, 0xaa, 0xb8, 0x63, 0xfb, 0xcf, 0x6c, 0x46, 0x1e, 0x88, 0x04, + 0x30, 0x2c, 0x02, 0x01, 0x00, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, + 0x02, 0x1a, 0x05, 0x00, 0x30, 0x06, 0x06, 0x04, 0x67, 0x2a, 0x01, 0x0c, + 0x04, 0x14, 0x13, 0xc1, 0x0c, 0xfc, 0xc8, 0x92, 0xd7, 0xde, 0x07, 0x1c, + 0x40, 0xde, 0x4f, 0xcd, 0x07, 0x5b, 0x68, 0x20, 0x5a, 0x6c} + }; + + static const u8 sha1selftestbufflen[SHA1_NUM_OF_SELF_TESTS] = { + 3, 56, 64, 94 + }; + + static const u8 sha1selftestexpres[SHA1_NUM_OF_SELF_TESTS][SHA_1_HASH_LENGTH] = { + {0xA9, 0x99, 0x3E, 0x36, + 0x47, 0x06, 0x81, 0x6A, + 0xBA, 0x3E, 0x25, 0x71, + 0x78, 0x50, 0xC2, 0x6C, + 0x9C, 0xD0, 0xD8, 0x9D}, + {0x84, 0x98, 0x3E, 0x44, + 0x1C, 0x3B, 0xD2, 0x6E, + 0xBA, 0xAE, 0x4A, 0xA1, + 0xF9, 0x51, 0x29, 0xE5, + 0xE5, 0x46, 0x70, 0xF1}, + {0xCF, 0x08, 0x00, 0xF7, + 0x64, 0x4A, 0xCE, 0x3C, + 0xB4, 0xC3, 0xFA, 0x33, + 0x38, 0x8D, 0x3B, 0xA0, + 0xEA, 0x3C, 0x8B, 0x6E}, + {0xc9, 0x84, 0x45, 0xc8, + 0x64, 0x04, 0xb1, 0xe3, + 0x3c, 0x6b, 0x0a, 0x8c, + 0x8b, 0x80, 0x94, 0xfc, + 0xf3, 0xc9, 0x98, 0xab} + }; + + /*------------------------------------------------------------------------*/ + /* SHA2 tests info */ + /*------------------------------------------------------------------------*/ + + static const u8 sha2selftestbuff[SHA2_NUM_OF_SELF_TESTS][100] = { + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + {'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'} + }; + + static const u8 sha2selftestbufflen[SHA2_NUM_OF_SELF_TESTS] = { + 3, 56, 100 + }; + + static const u8 sha2selftestexpres[SHA2_NUM_OF_SELF_TESTS][SHA_2_HASH_LENGTH] = { + /* + * SHA-256 test vectors + */ + { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, + { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, + 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, + 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, + 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, + { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }, + }; + + if (type == npcm_sha_type_sha1) { + /*--------------------------------------------------------------------*/ + /* SHA 1 TESTS */ + /*--------------------------------------------------------------------*/ + for (i = 0; i < SHA1_NUM_OF_SELF_TESTS; i++) { + if (i != 3) { + status = npcm_sha_calc(npcm_sha_type_sha1, sha1selftestbuff[i], sha1selftestbufflen[i], hashdigest); + npcm_sha_check(status); + } else { + SHA_Power(true); + SHA_Reset(); + status = SHA_Start(&handle, npcm_sha_type_sha1); + npcm_sha_check(status); + status = SHA_Update(&handle, sha1selftestbuff[i], 73); + npcm_sha_check(status); + status = SHA_Update(&handle, &sha1selftestbuff[i][73], sha1selftestbufflen[i] - 73); + npcm_sha_check(status); + status = SHA_Finish(&handle, hashdigest); + npcm_sha_check(status); + SHA_Power(false); + } + + if (memcmp(hashdigest, sha1selftestexpres[i], SHA_1_HASH_LENGTH)) + return -1; + } + + } else { + /*--------------------------------------------------------------------*/ + /* SHA 2 TESTS */ + /*--------------------------------------------------------------------*/ + for (i = 0; i < SHA2_NUM_OF_SELF_TESTS; i++) { + SHA_Power(true); + SHA_Reset(); + status = SHA_Start(&handle, npcm_sha_type_sha2); + npcm_sha_check(status); + if (i == 2) { + for (j = 0; j < 10000; j++) { //not working + status = SHA_Update(&handle, sha2selftestbuff[i], sha2selftestbufflen[i]); + npcm_sha_check(status); + } + } else { + status = SHA_Update(&handle, sha2selftestbuff[i], sha2selftestbufflen[i]); + npcm_sha_check(status); + } + + status = SHA_Finish(&handle, hashdigest); + npcm_sha_check(status); + SHA_Power(false); + if (memcmp(hashdigest, sha2selftestexpres[i], SHA_2_HASH_LENGTH)) + return -1; + + npcm_sha_calc(npcm_sha_type_sha2, sha2selftestbuff[i], sha2selftestbufflen[i], hashdigest); + if (memcmp(hashdigest, sha2selftestexpres[i], SHA_2_HASH_LENGTH)) + return -1; + } + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/* Function: SHA_FlushLocalBuffer_l */ +/* */ +/* Parameters: */ +/* Returns: none */ +/* Side effects: */ +/* Description: This routine flush secrun buffer to SHA module */ +/*----------------------------------------------------------------------------*/ +static void SHA_FlushLocalBuffer_l(const u32 *buff) +{ + struct npcm_sha_regs *regs = sha_priv->regs; + u32 i; + + for (i = 0; i < (SHA_BLOCK_LENGTH / sizeof(u32)); i++) + writel(buff[i], ®s->hash_data_in); +} + +/*----------------------------------------------------------------------------*/ +/* Function: SHA_BusyWait_l */ +/* */ +/* Parameters: */ +/* Returns: 0 if no error was found or DEFS_STATUS_ERROR otherwise */ +/* Side effects: */ +/* Description: This routine wait for SHA unit to no longer be busy */ +/*----------------------------------------------------------------------------*/ +static int SHA_BusyWait_l(void) +{ + struct npcm_sha_regs *regs = sha_priv->regs; + u32 timeout = SHA_TIMEOUT; + + do { + if (timeout-- == 0) + return -ETIMEDOUT; + } while ((readb(®s->hash_ctr_sts) & HASH_CTR_STS_SHA_BUSY) + == HASH_CTR_STS_SHA_BUSY); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/* Function: SHA_GetShaDigest_l */ +/* */ +/* Parameters: hashDigest - buffer for the hash output. */ +/* type - SHA module type */ +/* Returns: none */ +/* Side effects: */ +/* Description: This routine copy the hash digest from the hardware */ +/* and into given buffer (in ram) */ +/*----------------------------------------------------------------------------*/ +static void SHA_GetShaDigest_l(u8 *hashdigest, u8 type) +{ + struct npcm_sha_regs *regs = sha_priv->regs; + u16 j; + u8 len = SHA_HASH_LENGTH(type) / sizeof(u32); + + // Copy Bytes from SHA module to given buffer + for (j = 0; j < len; j++) + ((u32 *)hashdigest)[j] = readl(®s->hash_dig[j]); +} + +/*----------------------------------------------------------------------------*/ +/* Function: SHA_SetShaDigest_l */ +/* */ +/* Parameters: hashDigest - input buffer to set as hash digest */ +/* type - SHA module type */ +/* Returns: none */ +/* Side effects: */ +/* Description: This routine set the hash digest in the hardware from */ +/* a given buffer (in ram) */ +/*----------------------------------------------------------------------------*/ +static void SHA_SetShaDigest_l(const u32 *hashdigest, u8 type) +{ + struct npcm_sha_regs *regs = sha_priv->regs; + u16 j; + u8 len = SHA_HASH_LENGTH(type) / sizeof(u32); + + // Copy Bytes from given buffer to SHA module + for (j = 0; j < len; j++) + writel(hashdigest[j], ®s->hash_dig[j]); +} + +/*----------------------------------------------------------------------------*/ +/* Function: SHA_SetBlock_l */ +/* */ +/* Parameters: data - data to copy */ +/* len - size of data */ +/* position - byte offset into the block at which data */ +/* should be placed */ +/* block - block buffer */ +/* Returns: none */ +/* Side effects: */ +/* Description: This routine load bytes into block buffer */ +/*----------------------------------------------------------------------------*/ +static void SHA_SetBlock_l(const u8 *data, u32 len, u16 position, u32 *block) +{ + u8 *dest = (u8 *)block; + + memcpy(dest + position, data, len); +} + +/*----------------------------------------------------------------------------*/ +/* Function: SHA_SetBlock_l */ +/* */ +/* Parameters: */ +/* len - size of data */ +/* position - byte offset into the block at which data */ +/* should be placed */ +/* block - block buffer */ +/* Returns: none */ +/* Side effects: */ +/* Description: This routine load zero's into the block buffer */ +/*----------------------------------------------------------------------------*/ +static void SHA_ClearBlock_l(u16 len, u16 position, u32 *block) +{ + u8 *dest = (u8 *)block; + + memset(dest + position, 0, len); +} + +/*----------------------------------------------------------------------------*/ +/* Function: SHA_SetLength32_l */ +/* */ +/* Parameters: */ +/* handlePtr - SHA processing handle pointer */ +/* block - block buffer */ +/* Returns: none */ +/* Side effects: */ +/* Description: This routine set the length of the hash's data */ +/* len is the 32-bit byte length of the message */ +/*lint -efunc(734,SHA_SetLength32_l) Supperess loss of percision lint warning */ +/*----------------------------------------------------------------------------*/ +static void SHA_SetLength32_l(struct SHA_HANDLE_T *handleptr, u32 *block) +{ + u16 *secrunbufferswappedptr = (u16 *)(void *)(block); + + secrunbufferswappedptr[(SHA_BLOCK_LENGTH / sizeof(u16)) - 1] = (u16) + ((handleptr->length0 << 3) << 8) | ((u16)(handleptr->length0 << 3) >> 8); + secrunbufferswappedptr[(SHA_BLOCK_LENGTH / sizeof(u16)) - 2] = (u16) + ((handleptr->length0 >> (16 - 3)) >> 8) | ((u16)(handleptr->length0 >> (16 - 3)) << 8); + secrunbufferswappedptr[(SHA_BLOCK_LENGTH / sizeof(u16)) - 3] = (u16) + ((handleptr->length1 << 3) << 8) | ((u16)(handleptr->length1 << 3) >> 8); + secrunbufferswappedptr[(SHA_BLOCK_LENGTH / sizeof(u16)) - 4] = (u16) + ((handleptr->length1 >> (16 - 3)) >> 8) | ((u16)(handleptr->length1 >> (16 - 3)) << 8); +} + +static int npcm_sha_bind(struct udevice *dev) +{ + sha_priv = calloc(1, sizeof(struct npcm_sha_priv)); + if (!sha_priv) + return -ENOMEM; + + sha_priv->regs = dev_remap_addr_index(dev, 0); + if (!sha_priv->regs) { + printf("Cannot find sha reg address, binding failed\n"); + return -EINVAL; + } + + printf("SHA: NPCM SHA module bind OK\n"); + + return 0; +} + +static const struct udevice_id npcm_sha_ids[] = { + { .compatible = "nuvoton,npcm845-sha" }, + { .compatible = "nuvoton,npcm750-sha" }, + { } +}; + +U_BOOT_DRIVER(npcm_sha) = { + .name = "npcm_sha", + .id = UCLASS_MISC, + .of_match = npcm_sha_ids, + .priv_auto = sizeof(struct npcm_sha_priv), + .bind = npcm_sha_bind, +}; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 7b6c371d1c2..28d5da49ff1 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -321,6 +321,15 @@ config SPL_MXC_OCOTP Programmable memory pages, that are stored on some Freescale i.MX processors, in SPL. +config NPCM_OTP + bool "Nnvoton NPCM BMC On-Chip OTP Memory Support" + depends on (ARM && ARCH_NPCM) + default n + help + Support NPCM BMC OTP memory (fuse). + To compile this driver as a module, choose M here: the module + will be called npcm_otp. + config NUVOTON_NCT6102D bool "Enable Nuvoton NCT6102D Super I/O driver" help diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 0a333640b9f..0bf05ca05ef 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -56,6 +56,7 @@ obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o obj-$(CONFIG_$(SPL_TPL_)LS2_SFP) += ls2_sfp.o obj-$(CONFIG_$(SPL_)MXC_OCOTP) += mxc_ocotp.o obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o +obj-$(CONFIG_NPCM_OTP) += npcm_otp.o obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o obj-$(CONFIG_P2SB) += p2sb-uclass.o obj-$(CONFIG_PCA9551_LED) += pca9551_led.o diff --git a/drivers/misc/npcm_otp.c b/drivers/misc/npcm_otp.c new file mode 100644 index 00000000000..304910888bb --- /dev/null +++ b/drivers/misc/npcm_otp.c @@ -0,0 +1,512 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Nuvoton Technology Corp. + */ + +#include <clk.h> +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <fuse.h> +#include <asm/io.h> +#include <linux/delay.h> +#include <asm/arch/otp.h> + +struct npcm_otp_priv { + struct npcm_otp_regs *regs[2]; +}; + +static struct npcm_otp_priv *otp_priv; + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_check_inputs */ +/* */ +/* Parameters: arr - fuse array number to check */ +/* word - fuse word (offset) to check */ +/* Returns: int */ +/* Side effects: */ +/* Description: Checks is arr and word are illegal and do not exceed */ +/* their range. Return 0 if they are legal, -1 if not */ +/*----------------------------------------------------------------------------*/ +static int npcm_otp_check_inputs(u32 arr, u32 word) +{ + if (arr >= NPCM_NUM_OF_SA) { + if (IS_ENABLED(CONFIG_ARCH_NPCM8XX)) + printf("\nError: npcm8XX otp includs only one bank: 0\n"); + if (IS_ENABLED(CONFIG_ARCH_NPCM7XX)) + printf("\nError: npcm7XX otp includs only two banks: 0 and 1\n"); + return -1; + } + + if (word >= NPCM_OTP_ARR_BYTE_SIZE) { + printf("\nError: npcm otp array comprises only %d bytes, numbered from 0 to %d\n", + NPCM_OTP_ARR_BYTE_SIZE, NPCM_OTP_ARR_BYTE_SIZE - 1); + return -1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_wait_for_otp_ready */ +/* */ +/* Parameters: array - fuse array to wait for */ +/* Returns: int */ +/* Side effects: */ +/* Description: Initialize the Fuse HW module. */ +/*----------------------------------------------------------------------------*/ +static int npcm_otp_wait_for_otp_ready(u32 arr, u32 timeout) +{ + struct npcm_otp_regs *regs = otp_priv->regs[arr]; + u32 time = timeout; + + /*------------------------------------------------------------------------*/ + /* check parameters validity */ + /*------------------------------------------------------------------------*/ + if (arr > NPCM_FUSE_SA) + return -EINVAL; + + while (--time > 1) { + if (readl(®s->fst) & FST_RDY) { + /* fuse is ready, clear the status. */ + writel(readl(®s->fst) | FST_RDST, ®s->fst); + return 0; + } + } + + /* try to clear the status in case it was set */ + writel(readl(®s->fst) | FST_RDST, ®s->fst); + + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_read_byte */ +/* */ +/* Parameters: arr - Storage Array type [input]. */ +/* addr - Byte-address to read from [input]. */ +/* data - Pointer to result [output]. */ +/* Returns: none */ +/* Side effects: */ +/* Description: Read 8-bit data from an OTP storage array. */ +/*----------------------------------------------------------------------------*/ +static void npcm_otp_read_byte(u32 arr, u32 addr, u8 *data) +{ + struct npcm_otp_regs *regs = otp_priv->regs[arr]; + + /* Wait for the Fuse Box Idle */ + npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF); + + /* Configure the byte address in the fuse array for read operation */ + writel(FADDR_VAL(addr, 0), ®s->faddr); + + /* Initiate a read cycle */ + writel(READ_INIT, ®s->fctl); + + /* Wait for read operation completion */ + npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF); + + /* Read the result */ + *data = readl(®s->fdata) & FDATA_MASK; + + /* Clean FDATA contents to prevent unauthorized software from reading + * sensitive information + */ + writel(FDATA_CLEAN_VALUE, ®s->fdata); +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_bit_is_programmed */ +/* */ +/* Parameters: arr - Storage Array type [input]. */ +/* byte_offset - Byte offset in array [input]. */ +/* bit_offset - Bit offset in byte [input]. */ +/* Returns: Nonzero if bit is programmed, zero otherwise. */ +/* Side effects: */ +/* Description: Check if a bit is programmed in an OTP storage array. */ +/*----------------------------------------------------------------------------*/ +static bool npcm_otp_bit_is_programmed(u32 arr, + u32 byte_offset, u8 bit_offset) +{ + u32 data = 0; + + /* Read the entire byte you wish to program */ + npcm_otp_read_byte(arr, byte_offset, (u8 *)&data); + + /* Check whether the bit is already programmed */ + if (data & (1 << bit_offset)) + return true; + + return false; +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_program_bit */ +/* */ +/* Parameters: arr - Storage Array type [input]. */ +/* byte)offset - Byte offset in array [input]. */ +/* bit_offset - Bit offset in byte [input]. */ +/* Returns: int */ +/* Side effects: */ +/* Description: Program (set to 1) a bit in an OTP storage array. */ +/*----------------------------------------------------------------------------*/ +static int npcm_otp_program_bit(u32 arr, u32 byte_offset, + u8 bit_offset) +{ + struct npcm_otp_regs *regs = otp_priv->regs[arr]; + int count; + u8 read_data; + + /* Wait for the Fuse Box Idle */ + npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF); + + /* Make sure the bit is not already programmed */ + if (npcm_otp_bit_is_programmed(arr, byte_offset, bit_offset)) + return 0; + + /* Configure the bit address in the fuse array for program operation */ + writel(FADDR_VAL(byte_offset, bit_offset), ®s->faddr); + writel(readl(®s->faddr) | FADDR_IN_PROG, ®s->faddr); + + // program up to MAX_PROGRAM_PULSES + for (count = 1; count <= MAX_PROGRAM_PULSES; count++) { + /* Initiate a program cycle */ + writel(PROGRAM_ARM, ®s->fctl); + writel(PROGRAM_INIT, ®s->fctl); + + /* Wait for program operation completion */ + npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF); + + // after MIN_PROGRAM_PULSES start verifying the result + if (count >= MIN_PROGRAM_PULSES) { + /* Initiate a read cycle */ + writel(READ_INIT, ®s->fctl); + + /* Wait for read operation completion */ + npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF); + + /* Read the result */ + read_data = readl(®s->fdata) & FDATA_MASK; + + /* If the bit is set the sequence ended correctly */ + if (read_data & (1 << bit_offset)) + break; + } + } + + // check if programmking failed + if (count > MAX_PROGRAM_PULSES) { + printf("program fail\n"); + return -EINVAL; + } + + /* + * Clean FDATA contents to prevent unauthorized software from reading + * sensitive information + */ + writel(FDATA_CLEAN_VALUE, ®s->fdata); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_program_byte */ +/* */ +/* Parameters: arr - Storage Array type [input]. */ +/* byte_offset - Byte offset in array [input]. */ +/* value - Byte to program [input]. */ +/* Returns: int */ +/* Side effects: */ +/* Description: Program (set to 1) a given byte's relevant bits in an */ +/* OTP storage array. */ +/*----------------------------------------------------------------------------*/ +static int npcm_otp_program_byte(u32 arr, u32 byte_offset, + u8 value) +{ + int status = 0; + unsigned int i; + u8 data = 0; + int rc; + + rc = npcm_otp_check_inputs(arr, byte_offset); + if (rc != 0) + return rc; + + /* Wait for the Fuse Box Idle */ + npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF); + + /* Read the entire byte you wish to program */ + npcm_otp_read_byte(arr, byte_offset, &data); + + /* In case all relevant bits are already programmed - nothing to do */ + if ((~data & value) == 0) + return status; + + /* Program unprogrammed bits. */ + for (i = 0; i < 8; i++) { + if (value & (1 << i)) { + /* Program (set to 1) the relevant bit */ + int last_status = npcm_otp_program_bit(arr, byte_offset, (u8)i); + + if (last_status != 0) + status = last_status; + } + } + return status; +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_is_fuse_array_disabled */ +/* */ +/* Parameters: arr - Storage Array type [input]. */ +/* Returns: bool */ +/* Side effects: */ +/* Description: Return true if access to the first 2048 bits of the */ +/* specified fuse array is disabled, false if not */ +/*----------------------------------------------------------------------------*/ +bool npcm_otp_is_fuse_array_disabled(u32 arr) +{ + struct npcm_otp_regs *regs = otp_priv->regs[arr]; + + return (readl(®s->fcfg) & FCFG_FDIS) != 0; +} + +int npcm_otp_select_key(u8 key_index) +{ + struct npcm_otp_regs *regs = otp_priv->regs[NPCM_KEY_SA]; + u32 idx = 0; + u32 time = 0xDAEDBEEF; + + if (key_index >= 4) + return -1; + + /* Do not destroy ECCDIS bit */ + idx = readl(®s->fustrap_fkeyind); + + /* Configure the key size */ + idx &= ~FKEYIND_KSIZE_MASK; + idx |= FKEYIND_KSIZE_256; + + /* Configure the key index (0 to 3) */ + idx &= ~FKEYIND_KIND_MASK; + idx |= FKEYIND_KIND_KEY(key_index); + + writel(idx, ®s->fustrap_fkeyind); + + /* Wait for selection completetion */ + while (--time > 1) { + if (readl(®s->fustrap_fkeyind) & FKEYIND_KVAL) + return 0; + udelay(1); + } + + return -1; +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_nibble_parity_ecc_encode */ +/* */ +/* Parameters: datain - pointer to decoded data buffer */ +/* dataout - pointer to encoded data buffer (buffer size */ +/* should be 2 x dataout) */ +/* size - size of encoded data (decoded data x 2) */ +/* Returns: none */ +/* Side effects: */ +/* Description: Decodes the data according to nibble parity ECC scheme. */ +/* Size specifies the encoded data size. */ +/* Decodes whole bytes only */ +/*----------------------------------------------------------------------------*/ +void npcm_otp_nibble_parity_ecc_encode(u8 *datain, u8 *dataout, u32 size) +{ + u32 i, idx; + u8 E0, E1, E2, E3; + + for (i = 0; i < (size / 2); i++) { + E0 = (datain[i] >> 0) & 0x01; + E1 = (datain[i] >> 1) & 0x01; + E2 = (datain[i] >> 2) & 0x01; + E3 = (datain[i] >> 3) & 0x01; + + idx = i * 2; + dataout[idx] = datain[i] & 0x0f; + dataout[idx] |= (E0 ^ E1) << 4; + dataout[idx] |= (E2 ^ E3) << 5; + dataout[idx] |= (E0 ^ E2) << 6; + dataout[idx] |= (E1 ^ E3) << 7; + + E0 = (datain[i] >> 4) & 0x01; + E1 = (datain[i] >> 5) & 0x01; + E2 = (datain[i] >> 6) & 0x01; + E3 = (datain[i] >> 7) & 0x01; + + idx = i * 2 + 1; + dataout[idx] = (datain[i] & 0xf0) >> 4; + dataout[idx] |= (E0 ^ E1) << 4; + dataout[idx] |= (E2 ^ E3) << 5; + dataout[idx] |= (E0 ^ E2) << 6; + dataout[idx] |= (E1 ^ E3) << 7; + } +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_majority_rule_ecc_encode */ +/* */ +/* Parameters: datain - pointer to decoded data buffer */ +/* dataout - pointer to encoded data buffer (buffer size */ +/* should be 3 x dataout) */ +/* size - size of encoded data (decoded data x 3) */ +/* Returns: none */ +/* Side effects: */ +/* Description: Decodes the data according to Major Rule ECC scheme. */ +/* Size specifies the encoded data size. */ +/* Decodes whole bytes only */ +/*----------------------------------------------------------------------------*/ +void npcm_otp_majority_rule_ecc_encode(u8 *datain, u8 *dataout, u32 size) +{ + u32 byte; + u32 bit; + u8 bit_val; + u32 decoded_size = size / 3; + + for (byte = 0; byte < decoded_size; byte++) { + for (bit = 0; bit < 8; bit++) { + bit_val = (datain[byte] >> bit) & 0x01; + + if (bit_val) { + dataout[byte] |= (1 << bit); + dataout[decoded_size + byte] |= (1 << bit); + dataout[decoded_size * 2 + byte] |= (1 << bit); + } else { + dataout[byte] &= ~(1 << bit); + dataout[decoded_size + byte] &= ~(1 << bit); + dataout[decoded_size * 2 + byte] &= ~(1 << bit); + } + } + } +} + +/*----------------------------------------------------------------------------*/ +/* Function: fuse_program_data */ +/* */ +/* Parameters: bank - Storage Array type [input]. */ +/* word - Byte offset in array [input]. */ +/* data - Pointer to data buffer to program. */ +/* size - Number of bytes to program. */ +/* Returns: none */ +/* Side effects: */ +/* Description: Programs the given byte array (size bytes) to the given */ +/* OTP storage array, starting from offset word. */ +/*----------------------------------------------------------------------------*/ +int fuse_program_data(u32 bank, u32 word, u8 *data, u32 size) +{ + u32 arr = (u32)bank; + u32 byte; + int rc; + + rc = npcm_otp_check_inputs(bank, word + size - 1); + if (rc != 0) + return rc; + + for (byte = 0; byte < size; byte++) { + u8 val; + + val = data[byte]; + if (val == 0) // optimization + continue; + + rc = npcm_otp_program_byte(arr, word + byte, data[byte]); + if (rc != 0) + return rc; + + // verify programming of every '1' bit + val = 0; + npcm_otp_read_byte((u32)bank, byte, &val); + if ((data[byte] & ~val) != 0) + return -1; + } + + return 0; +} + +int fuse_prog_image(u32 bank, uintptr_t address) +{ + return fuse_program_data(bank, 0, (u8 *)address, NPCM_OTP_ARR_BYTE_SIZE); +} + +int fuse_read(u32 bank, u32 word, u32 *val) +{ + int rc = npcm_otp_check_inputs(bank, word); + + if (rc != 0) + return rc; + + *val = 0; + npcm_otp_read_byte((u32)bank, word, (u8 *)val); + + return 0; +} + +int fuse_sense(u32 bank, u32 word, u32 *val) +{ + /* We do not support overriding */ + return -EINVAL; +} + +int fuse_prog(u32 bank, u32 word, u32 val) +{ + int rc; + + rc = npcm_otp_check_inputs(bank, word); + if (rc != 0) + return rc; + + return npcm_otp_program_byte(bank, word, (u8)val); +} + +int fuse_override(u32 bank, u32 word, u32 val) +{ + /* We do not support overriding */ + return -EINVAL; +} + +static int npcm_otp_bind(struct udevice *dev) +{ + struct npcm_otp_regs *regs; + + otp_priv = calloc(1, sizeof(struct npcm_otp_priv)); + if (!otp_priv) + return -ENOMEM; + + regs = dev_remap_addr_index(dev, 0); + if (!regs) { + printf("Cannot find reg address (arr #0), binding failed\n"); + return -EINVAL; + } + otp_priv->regs[0] = regs; + + if (IS_ENABLED(CONFIG_ARCH_NPCM7xx)) { + regs = dev_remap_addr_index(dev, 1); + if (!regs) { + printf("Cannot find reg address (arr #1), binding failed\n"); + return -EINVAL; + } + otp_priv->regs[1] = regs; + } + printf("OTP: NPCM OTP module bind OK\n"); + + return 0; +} + +static const struct udevice_id npcm_otp_ids[] = { + { .compatible = "nuvoton,npcm845-otp" }, + { .compatible = "nuvoton,npcm750-otp" }, + { } +}; + +U_BOOT_DRIVER(npcm_otp) = { + .name = "npcm_otp", + .id = UCLASS_MISC, + .of_match = npcm_otp_ids, + .priv_auto = sizeof(struct npcm_otp_priv), + .bind = npcm_otp_bind, +}; diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index a1e515cb2bc..e48d72d7445 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -186,6 +186,12 @@ config FSL_QSPI_AHB_FULL_MAP Enable the Freescale QSPI driver to use full AHB memory map space for flash access. +config GXP_SPI + bool "SPI driver for GXP" + imply SPI_FLASH_BAR + help + Enable support for SPI on GXP. + config ICH_SPI bool "Intel ICH SPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 06e81b465bc..8755408e629 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_EXYNOS_SPI) += exynos_spi.o obj-$(CONFIG_FSL_DSPI) += fsl_dspi.o obj-$(CONFIG_FSL_ESPI) += fsl_espi.o obj-$(CONFIG_SYNQUACER_SPI) += spi-synquacer.o +obj-$(CONFIG_GXP_SPI) += gxp_spi.o obj-$(CONFIG_ICH_SPI) += ich.o obj-$(CONFIG_IPROC_QSPI) += iproc_qspi.o obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o diff --git a/drivers/spi/gxp_spi.c b/drivers/spi/gxp_spi.c new file mode 100644 index 00000000000..70d76ac66ad --- /dev/null +++ b/drivers/spi/gxp_spi.c @@ -0,0 +1,304 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * GXP SPI driver + * + * (C) Copyright 2022 Hewlett Packard Enterprise Development LP. + * Author: Nick Hawkins <nick.hawkins@hpe.com> + * Author: Jean-Marie Verdun <verdun@hpe.com> + */ + +#include <spi.h> +#include <asm/io.h> +#include <dm.h> + +#define GXP_SPI0_MAX_CHIPSELECT 2 + +#define MANUAL_MODE 0 +#define AUTO_MODE 1 +#define OFFSET_SPIMCFG 0x00 +#define OFFSET_SPIMCTRL 0x04 +#define OFFSET_SPICMD 0x05 +#define OFFSET_SPIDCNT 0x06 +#define OFFSET_SPIADDR 0x08 +#define OFFSET_SPILDAT 0x40 +#define GXP_SPILDAT_SIZE 64 + +#define SPIMCTRL_START 0x01 +#define SPIMCTRL_BUSY 0x02 + +#define CMD_READ_ARRAY_FAST 0x0b + +struct gxp_spi_priv { + struct spi_slave slave; + void __iomem *base; + unsigned int mode; + +}; + +static void spi_set_mode(struct gxp_spi_priv *priv, int mode) +{ + unsigned char value; + + value = readb(priv->base + OFFSET_SPIMCTRL); + if (mode == MANUAL_MODE) { + writeb(0x55, priv->base + OFFSET_SPICMD); + writeb(0xaa, priv->base + OFFSET_SPICMD); + /* clear bit5 and bit4, auto_start and start_mask */ + value &= ~(0x03 << 4); + } else { + value |= (0x03 << 4); + } + writeb(value, priv->base + OFFSET_SPIMCTRL); +} + +static int gxp_spi_xfer(struct udevice *dev, unsigned int bitlen, const void *dout, void *din, + unsigned long flags) +{ + struct gxp_spi_priv *priv = dev_get_priv(dev->parent); + struct spi_slave *slave = dev_get_parent_priv(dev); + struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); + + unsigned int len = bitlen / 8; + unsigned int value; + unsigned int addr = 0; + unsigned char uchar_out[len]; + unsigned char *uchar_in = (unsigned char *)din; + int read_len; + int read_ptr; + + if (dout && din) { + /* + * error: gxp spi engin cannot send data to dout and read data from din at the same + * time + */ + return -1; + } + + memset(uchar_out, 0, sizeof(uchar_out)); + if (dout) + memcpy(uchar_out, dout, len); + + if (flags & SPI_XFER_BEGIN) { + /* the dout is cmd + addr, cmd=dout[0], add1~3=dout[1~3]. */ + /* cmd reg */ + writeb(uchar_out[0], priv->base + OFFSET_SPICMD); + + /* config reg */ + value = readl(priv->base + OFFSET_SPIMCFG); + value &= ~(1 << 24); + /* set chipselect */ + value |= (slave_plat->cs << 24); + + /* addr reg and addr size */ + if (len >= 4) { + addr = uchar_out[1] << 16 | uchar_out[2] << 8 | uchar_out[3]; + writel(addr, priv->base + OFFSET_SPIADDR); + value &= ~(0x07 << 16); + /* set the address size to 3 byte */ + value |= (3 << 16); + } else { + writel(0, priv->base + OFFSET_SPIADDR); + /* set the address size to 0 byte */ + value &= ~(0x07 << 16); + } + + /* dummy */ + /* clear dummy_cnt to */ + value &= ~(0x1f << 19); + if (uchar_out[0] == CMD_READ_ARRAY_FAST) { + /* fast read needs 8 dummy clocks */ + value |= (8 << 19); + } + + writel(value, priv->base + OFFSET_SPIMCFG); + + if (flags & SPI_XFER_END) { + /* no data cmd just start it */ + /* set the data direction bit to 1 */ + value = readb(priv->base + OFFSET_SPIMCTRL); + value |= (1 << 3); + writeb(value, priv->base + OFFSET_SPIMCTRL); + + /* set the data byte count */ + writeb(0, priv->base + OFFSET_SPIDCNT); + + /* set the start bit */ + value = readb(priv->base + OFFSET_SPIMCTRL); + value |= SPIMCTRL_START; + writeb(value, priv->base + OFFSET_SPIMCTRL); + + /* wait busy bit is cleared */ + do { + value = readb(priv->base + OFFSET_SPIMCTRL); + } while (value & SPIMCTRL_BUSY); + return 0; + } + } + + if (!(flags & SPI_XFER_END) && (flags & SPI_XFER_BEGIN)) { + /* first of spi_xfer calls */ + return 0; + } + + /* if dout != null, write data to buf and start transaction */ + if (dout) { + if (len > slave->max_write_size) { + printf("SF: write length is too big(>%d)\n", slave->max_write_size); + return -1; + } + + /* load the data bytes */ + memcpy((u8 *)priv->base + OFFSET_SPILDAT, dout, len); + + /* write: set the data direction bit to 1 */ + value = readb(priv->base + OFFSET_SPIMCTRL); + value |= (1 << 3); + writeb(value, priv->base + OFFSET_SPIMCTRL); + + /* set the data byte count */ + writeb(len, priv->base + OFFSET_SPIDCNT); + + /* set the start bit */ + value = readb(priv->base + OFFSET_SPIMCTRL); + value |= SPIMCTRL_START; + writeb(value, priv->base + OFFSET_SPIMCTRL); + + /* wait busy bit is cleared */ + do { + value = readb(priv->base + OFFSET_SPIMCTRL); + } while (value & SPIMCTRL_BUSY); + + return 0; + } + + /* if din !=null, start and read data */ + if (uchar_in) { + read_ptr = 0; + + while (read_ptr < len) { + read_len = len - read_ptr; + if (read_len > GXP_SPILDAT_SIZE) + read_len = GXP_SPILDAT_SIZE; + + /* read: set the data direction bit to 0 */ + value = readb(priv->base + OFFSET_SPIMCTRL); + value &= ~(1 << 3); + writeb(value, priv->base + OFFSET_SPIMCTRL); + + /* set the data byte count */ + writeb(read_len, priv->base + OFFSET_SPIDCNT); + + /* set the start bit */ + value = readb(priv->base + OFFSET_SPIMCTRL); + value |= SPIMCTRL_START; + writeb(value, priv->base + OFFSET_SPIMCTRL); + + /* wait busy bit is cleared */ + do { + value = readb(priv->base + OFFSET_SPIMCTRL); + } while (value & SPIMCTRL_BUSY); + + /* store the data bytes */ + memcpy(uchar_in + read_ptr, (u8 *)priv->base + OFFSET_SPILDAT, read_len); + /* update read_ptr and addr reg */ + read_ptr += read_len; + + addr = readl(priv->base + OFFSET_SPIADDR); + addr += read_len; + writel(addr, priv->base + OFFSET_SPIADDR); + } + + return 0; + } + return -2; +} + +static int gxp_spi_set_speed(struct udevice *dev, unsigned int speed) +{ + /* Accept any speed */ + return 0; +} + +static int gxp_spi_set_mode(struct udevice *dev, unsigned int mode) +{ + struct gxp_spi_priv *priv = dev_get_priv(dev->parent); + + priv->mode = mode; + + return 0; +} + +static int gxp_spi_claim_bus(struct udevice *dev) +{ + struct gxp_spi_priv *priv = dev_get_priv(dev->parent); + unsigned char cmd; + + spi_set_mode(priv, MANUAL_MODE); + + /* exit 4 bytes addr mode, uboot spi_flash only supports 3 byets address mode */ + cmd = 0xe9; + gxp_spi_xfer(dev, 1 * 8, &cmd, NULL, SPI_XFER_BEGIN | SPI_XFER_END); + return 0; +} + +static int gxp_spi_release_bus(struct udevice *dev) +{ + struct gxp_spi_priv *priv = dev_get_priv(dev->parent); + + spi_set_mode(priv, AUTO_MODE); + + return 0; +} + +int gxp_spi_cs_info(struct udevice *bus, unsigned int cs, struct spi_cs_info *info) +{ + if (cs < GXP_SPI0_MAX_CHIPSELECT) + return 0; + else + return -ENODEV; +} + +static int gxp_spi_probe(struct udevice *bus) +{ + struct gxp_spi_priv *priv = dev_get_priv(bus); + + priv->base = dev_read_addr_ptr(bus); + if (!priv->base) + return -ENOENT; + + return 0; +} + +static int gxp_spi_child_pre_probe(struct udevice *dev) +{ + struct spi_slave *slave = dev_get_parent_priv(dev); + + slave->max_write_size = GXP_SPILDAT_SIZE; + + return 0; +} + +static const struct dm_spi_ops gxp_spi_ops = { + .claim_bus = gxp_spi_claim_bus, + .release_bus = gxp_spi_release_bus, + .xfer = gxp_spi_xfer, + .set_speed = gxp_spi_set_speed, + .set_mode = gxp_spi_set_mode, + .cs_info = gxp_spi_cs_info, +}; + +static const struct udevice_id gxp_spi_ids[] = { + { .compatible = "hpe,gxp-spi" }, + { } +}; + +U_BOOT_DRIVER(gxp_spi) = { + .name = "gxp_spi", + .id = UCLASS_SPI, + .of_match = gxp_spi_ids, + .ops = &gxp_spi_ops, + .priv_auto = sizeof(struct gxp_spi_priv), + .probe = gxp_spi_probe, + .child_pre_probe = gxp_spi_child_pre_probe, +}; + diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 7b8ab56ed32..d592dba285c 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -139,6 +139,13 @@ config DESIGNWARE_APB_TIMER Enables support for the Designware APB Timer driver. This timer is present on Altera SoCFPGA SoCs. +config GXP_TIMER + bool "HPE GXP Timer" + depends on TIMER + help + Enables support for the GXP Timer driver. This timer is + present on HPE GXP SoCs. + config MPC83XX_TIMER bool "MPC83xx timer support" depends on TIMER diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile index b2f002d5978..cc2b8516b57 100644 --- a/drivers/timer/Makefile +++ b/drivers/timer/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_$(SPL_)ATMEL_PIT_TIMER) += atmel_pit_timer.o obj-$(CONFIG_$(SPL_)ATMEL_TCB_TIMER) += atmel_tcb_timer.o obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence-ttc.o obj-$(CONFIG_DESIGNWARE_APB_TIMER) += dw-apb-timer.o +obj-$(CONFIG_GXP_TIMER) += gxp-timer.o obj-$(CONFIG_MPC83XX_TIMER) += mpc83xx_timer.o obj-$(CONFIG_NOMADIK_MTU_TIMER) += nomadik-mtu-timer.o obj-$(CONFIG_NPCM_TIMER) += npcm-timer.o diff --git a/drivers/timer/gxp-timer.c b/drivers/timer/gxp-timer.c new file mode 100644 index 00000000000..6f316bc8c5c --- /dev/null +++ b/drivers/timer/gxp-timer.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * GXP timer driver + * + * (C) Copyright 2022 Hewlett Packard Enterprise Development LP. + * Author: Nick Hawkins <nick.hawkins@hpe.com> + * Author: Jean-Marie Verdun <verdun@hpe.com> + */ + +#include <clk.h> +#include <dm.h> +#include <timer.h> +#include <asm/io.h> + +#define USTIMELO 0x18 +#define USTIMEHI 0x1C + +struct gxp_timer_priv { + void __iomem *base; +}; + +static u64 gxp_timer_get_count(struct udevice *dev) +{ + struct gxp_timer_priv *priv = dev_get_priv(dev); + u64 val; + + val = readl(priv->base + USTIMEHI); + val = (val << 32) | readl(priv->base + USTIMELO); + + return val; +} + +static int gxp_timer_probe(struct udevice *dev) +{ + struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct gxp_timer_priv *priv = dev_get_priv(dev); + + priv->base = dev_read_addr_ptr(dev); + if (!priv->base) + return -ENOENT; + + uc_priv->clock_rate = 1000000; + + return 0; +} + +static const struct timer_ops gxp_timer_ops = { + .get_count = gxp_timer_get_count, +}; + +static const struct udevice_id gxp_timer_ids[] = { + { .compatible = "hpe,gxp-timer" }, + {} +}; + +U_BOOT_DRIVER(gxp_timer) = { + .name = "gxp-timer", + .id = UCLASS_TIMER, + .of_match = gxp_timer_ids, + .priv_auto = sizeof(struct gxp_timer_priv), + .probe = gxp_timer_probe, + .ops = &gxp_timer_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h new file mode 100644 index 00000000000..38d7fe8d0d4 --- /dev/null +++ b/include/configs/corstone1000.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2022 ARM Limited + * (C) Copyright 2022 Linaro + * Rui Miguel Silva <rui.silva@linaro.org> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> + * + * Configuration for Corstone1000. Parts were derived from other ARM + * configurations. + */ + +#ifndef __CORSTONE1000_H +#define __CORSTONE1000_H + +#include <linux/sizes.h> + +#define V2M_BASE 0x80000000 + +#define CONFIG_PL011_CLOCK 50000000 + +/* Physical Memory Map */ +#define PHYS_SDRAM_1 (V2M_BASE) +#define PHYS_SDRAM_1_SIZE 0x80000000 + +#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 + +#endif diff --git a/include/configs/devkit8000.h b/include/configs/devkit8000.h index 4e91f8caa32..d45115bdf68 100644 --- a/include/configs/devkit8000.h +++ b/include/configs/devkit8000.h @@ -14,17 +14,6 @@ #ifndef __CONFIG_H #define __CONFIG_H -/* High Level Configuration Options */ - -/* - * 1MB into the SDRAM to allow for SPL's bss at the beginning of SDRAM - * 64 bytes before this address should be set aside for u-boot.img's - * header. That is 0x800FFFC0--0x80100000 should not be used for any - * other needs. - */ - -/* Physical Memory Map */ - #include <configs/ti_omap3_common.h> /* Hardware drivers */ @@ -40,9 +29,12 @@ /* BOOTP/DHCP options */ +#define MEM_LAYOUT_ENV_SETTINGS \ + DEFAULT_LINUX_BOOT_ENV + /* Environment information */ #define CONFIG_EXTRA_ENV_SETTINGS \ - "loadaddr=0x82000000\0" \ + MEM_LAYOUT_ENV_SETTINGS \ "console=ttyO2,115200n8\0" \ "mmcdev=0\0" \ "vram=12M\0" \ diff --git a/include/configs/gxp.h b/include/configs/gxp.h new file mode 100644 index 00000000000..e3c97b20d51 --- /dev/null +++ b/include/configs/gxp.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * GXP board + * + * (C) Copyright 2022 Hewlett Packard Enterprise Development LP. + * Author: Nick Hawkins <nick.hawkins@hpe.com> + * Author: Jean-Marie Verdun <verdun@hpe.com> + */ + +#ifndef _GXP_H_ +#define _GXP_H_ + +#define CONFIG_SYS_SDRAM_BASE 0x40000000 + +#endif diff --git a/include/efi_loader.h b/include/efi_loader.h index c1e00ebac39..31de191e3df 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -591,6 +591,8 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void efi_save_gd(void); /* Call this to relocate the runtime section to an address space */ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map); +/* Call this to get image parameters */ +void efi_get_image_parameters(void **img_addr, size_t *img_size); /* Add a new object to the object list. */ void efi_add_handle(efi_handle_t obj); /* Create handle */ diff --git a/include/test/suites.h b/include/test/suites.h index ee6858a802a..ddb8827fdb1 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -39,6 +39,7 @@ int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc, int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_env(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); +int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 171661b8972..2493d743261 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -1158,6 +1158,8 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr, { struct blk_desc *desc = NULL; struct disk_partition fs_partition; + size_t image_size; + void *image_addr; int part = 0; char *filename; char *s; @@ -1173,6 +1175,13 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr, } else if (!strcmp(dev, "Uart")) { if (device) *device = efi_dp_from_uart(); + } else if (!strcmp(dev, "Mem")) { + efi_get_image_parameters(&image_addr, &image_size); + + if (device) + *device = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, + (uintptr_t)image_addr, + image_size); } else { part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition, 1); diff --git a/test/cmd/Makefile b/test/cmd/Makefile index a59adb1e6d6..4b2d7df0d2e 100644 --- a/test/cmd/Makefile +++ b/test/cmd/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o endif obj-y += mem.o obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o +obj-$(CONFIG_CMD_LOADM) += loadm.o obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o obj-$(CONFIG_CMD_PINMUX) += pinmux.o obj-$(CONFIG_CMD_PWM) += pwm.o diff --git a/test/cmd/loadm.c b/test/cmd/loadm.c new file mode 100644 index 00000000000..41e005ac592 --- /dev/null +++ b/test/cmd/loadm.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for loadm command + * + * Copyright 2022 ARM Limited + * Copyright 2022 Linaro + * + * Authors: + * Rui Miguel Silva <rui.silva@linaro.org> + */ + +#include <common.h> +#include <console.h> +#include <mapmem.h> +#include <asm/global_data.h> +#include <dm/test.h> +#include <test/suites.h> +#include <test/test.h> +#include <test/ut.h> + +#define BUF_SIZE 0x100 + +#define LOADM_TEST(_name, _flags) UNIT_TEST(_name, _flags, loadm_test) + +static int loadm_test_params(struct unit_test_state *uts) +{ + ut_assertok(console_record_reset_enable()); + run_command("loadm", 0); + ut_assert_nextline("loadm - load binary blob from source address to destination address"); + + ut_assertok(console_record_reset_enable()); + run_command("loadm 0x12345678", 0); + ut_assert_nextline("loadm - load binary blob from source address to destination address"); + + ut_assertok(console_record_reset_enable()); + run_command("loadm 0x12345678 0x12345678", 0); + ut_assert_nextline("loadm - load binary blob from source address to destination address"); + + ut_assertok(console_record_reset_enable()); + run_command("loadm 0x12345678 0x12345678 0", 0); + ut_assert_nextline("loadm: can not load zero bytes"); + + return 0; +} +LOADM_TEST(loadm_test_params, UT_TESTF_CONSOLE_REC); + +static int loadm_test_load (struct unit_test_state *uts) +{ + char *buf; + + buf = map_sysmem(0, BUF_SIZE); + memset(buf, '\0', BUF_SIZE); + memset(buf, 0xaa, BUF_SIZE / 2); + + ut_assertok(console_record_reset_enable()); + run_command("loadm 0x0 0x80 0x80", 0); + ut_assert_nextline("loaded bin to memory: size: 128"); + + unmap_sysmem(buf); + + return 0; +} +LOADM_TEST(loadm_test_load, UT_TESTF_CONSOLE_REC); + +int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + struct unit_test *tests = UNIT_TEST_SUITE_START(loadm_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(loadm_test); + + return cmd_ut_category("loadm", "loadm_test_", tests, n_ents, argc, + argv); +} diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 67a13ee32b8..d70b72678ae 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -74,6 +74,9 @@ static struct cmd_tbl cmd_ut_sub[] = { #ifdef CONFIG_CMD_ADDRMAP U_BOOT_CMD_MKENT(addrmap, CONFIG_SYS_MAXARGS, 1, do_ut_addrmap, "", ""), #endif +#ifdef CONFIG_CMD_LOADM + U_BOOT_CMD_MKENT(loadm, CONFIG_SYS_MAXARGS, 1, do_ut_loadm, "", ""), +#endif }; static int do_ut_all(struct cmd_tbl *cmdtp, int flag, int argc, @@ -156,6 +159,9 @@ static char ut_help_text[] = #ifdef CONFIG_CMD_ADDRMAP "ut addrmap - Very basic test of addrmap command\n" #endif +#ifdef CONFIG_CMD_LOADM + "ut loadm [test-name]- test of parameters and load memory blob\n" +#endif ; #endif /* CONFIG_SYS_LONGHELP */ |