From: Michal Simek Date: Tue, 13 Jan 2015 09:19:59 +0000 (+0100) Subject: Merge tag 'v2015.01' into master X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=558c6df46f249b014ce808715a016464b3873e27;p=thirdparty%2Fu-boot.git Merge tag 'v2015.01' into master Add AFX/CSE board support - Kconfig entry, defconfigs Add RSA Kconfig entry and targets for it Add zc770-xm011 and zynq-cc108 DTBs from the Linux kernel Sync zynq-7000.dtsi with the Linux kernel. Use spl_load_image_fat for bitstream loading in SPL. Disable CONFIG_OF_CONTROL for all zynq boards. Nand: - Fix zynq_nand_read_subpage_raw parameters. - Remove nand.h from sys_proto.h and move it zynq_nand.c - Do not call nand_release(). Removed by: "mtd, ubi, ubifs: resync with Linux-3.14" (sha1: ff94bc40af3481d47546595ba73c136de6af6929) QSPI: - spi_flash_params has been moved from spi_flash.h to sf_internal.h - fix zynq_qspi.c driver to reflect this. Signed-off-by: Michal Simek --- 558c6df46f249b014ce808715a016464b3873e27 diff --cc Makefile index 12ea1a52602,36a9a283b05..3d1cad8fb4d mode 100755,100644..100755 --- a/Makefile +++ b/Makefile @@@ -738,12 -743,11 +743,17 @@@ endi endif endif +ifneq ($(CONFIG_ZYNQ),) +ifeq ($(CONFIG_SPL),y) +ALL-y += boot.bin +endif +endif + + # Add optional build target if defined in board/cpu/soc headers + ifneq ($(CONFIG_BUILD_TARGET),) + ALL-y += $(CONFIG_BUILD_TARGET:"%"=%) + endif + LDFLAGS_u-boot += $(LDFLAGS_FINAL) ifneq ($(CONFIG_SYS_TEXT_BASE),) LDFLAGS_u-boot += -Ttext $(CONFIG_SYS_TEXT_BASE) diff --cc arch/arm/cpu/armv7/zynq/Kconfig index 00000000000,3a52535ce00..2482bbb068c mode 000000,100644..100644 --- a/arch/arm/cpu/armv7/zynq/Kconfig +++ b/arch/arm/cpu/armv7/zynq/Kconfig @@@ -1,0 -1,39 +1,47 @@@ + if ZYNQ + + choice + prompt "Xilinx Zynq board select" + + config TARGET_ZYNQ_ZED + bool "Zynq ZedBoard" + + config TARGET_ZYNQ_MICROZED + bool "Zynq MicroZed" + + config TARGET_ZYNQ_ZC70X + bool "Zynq ZC702/ZC706 Board" + + config TARGET_ZYNQ_ZC770 + bool "Zynq ZC770 Board" + + config TARGET_ZYNQ_ZYBO + bool "Zynq Zybo Board" + ++config TARGET_ZYNQ_AFX ++ bool "Zynq AFX Board" ++ ++config TARGET_ZYNQ_CSE ++ bool "Zynq CSE Board" ++ + endchoice + + config SYS_BOARD + default "zynq" + + config SYS_VENDOR + default "xilinx" + + config SYS_SOC + default "zynq" + + config SYS_CONFIG_NAME + default "zynq_zed" if TARGET_ZYNQ_ZED + default "zynq_microzed" if TARGET_ZYNQ_MICROZED + default "zynq_zc70x" if TARGET_ZYNQ_ZC70X + default "zynq_zc770" if TARGET_ZYNQ_ZC770 + default "zynq_zybo" if TARGET_ZYNQ_ZYBO ++ default "zynq_cse" if TARGET_ZYNQ_CSE ++ default "zynq_afx" if TARGET_ZYNQ_AFX + + endif diff --cc arch/arm/cpu/armv7/zynq/ddrc.c index 90ce4ff3186,d74f8dbbc45..5b20accbcb1 --- a/arch/arm/cpu/armv7/zynq/ddrc.c +++ b/arch/arm/cpu/armv7/zynq/ddrc.c @@@ -40,9 -40,8 +40,10 @@@ void zynq_ddrc_init(void * first stage bootloader. To get ECC to work all memory has * been initialized by writing any value. */ + /* cppcheck-suppress nullPointer */ memset((void *)0, 0, 1 * 1024 * 1024); + + gd->ram_size /= 2; } else { puts("ECC disabled "); } diff --cc arch/arm/dts/Makefile index 6e2e313829c,fac16cc384d..5b4900455a5 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@@ -28,8 -42,9 +42,11 @@@ dtb-$(CONFIG_ARCH_UNIPHIER) += dtb-$(CONFIG_ZYNQ) += zynq-zc702.dtb \ zynq-zc706.dtb \ zynq-zed.dtb \ + zynq-zybo.dtb \ zynq-microzed.dtb \ ++ zynq-cc108.dtb \ zynq-zc770-xm010.dtb \ ++ zynq-zc770-xm011.dtb \ zynq-zc770-xm012.dtb \ zynq-zc770-xm013.dtb dtb-$(CONFIG_AM33XX) += am335x-boneblack.dtb diff --cc arch/arm/dts/zynq-7000.dtsi index 2d076f194e0,2d076f194e0..3c3ae7a7094 --- a/arch/arm/dts/zynq-7000.dtsi +++ b/arch/arm/dts/zynq-7000.dtsi @@@ -1,10 -1,10 +1,7 @@@ /* -- * Xilinx Zynq 7000 DTSI -- * Describes the hardware common to all Zynq 7000-based boards. ++ * Copyright (C) 2011 - 2015 Xilinx, Inc. * -- * Copyright (C) 2013 Xilinx, Inc. -- * -- * SPDX-License-Identifier: GPL-2.0+ ++ * SPDX-License-Identifier: GPL-2.0+ */ /include/ "skeleton.dtsi" @@@ -21,11 -21,11 +18,11 @@@ reg = <0>; clocks = <&clkc 3>; clock-latency = <1000>; ++ cpu0-supply = <®ulator_vccpint>; operating-points = < /* kHz uV */ 666667 1000000 333334 1000000 -- 222223 1000000 >; }; @@@ -44,14 -44,14 +41,65 @@@ reg = < 0xf8891000 0x1000 0xf8893000 0x1000 >; }; -- amba { ++ regulator_vccpint: fixedregulator@0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCCPINT"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ amba: amba { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; interrupt-parent = <&intc>; ranges; -- i2c0: zynq-i2c@e0004000 { ++ adc: adc@f8007100 { ++ compatible = "xlnx,zynq-xadc-1.00.a"; ++ reg = <0xf8007100 0x20>; ++ interrupts = <0 7 4>; ++ interrupt-parent = <&intc>; ++ clocks = <&clkc 12>; ++ }; ++ ++ can0: can@e0008000 { ++ compatible = "xlnx,zynq-can-1.0"; ++ status = "disabled"; ++ clocks = <&clkc 19>, <&clkc 36>; ++ clock-names = "can_clk", "pclk"; ++ reg = <0xe0008000 0x1000>; ++ interrupts = <0 28 4>; ++ interrupt-parent = <&intc>; ++ tx-fifo-depth = <0x40>; ++ rx-fifo-depth = <0x40>; ++ }; ++ ++ can1: can@e0009000 { ++ compatible = "xlnx,zynq-can-1.0"; ++ status = "disabled"; ++ clocks = <&clkc 20>, <&clkc 37>; ++ clock-names = "can_clk", "pclk"; ++ reg = <0xe0009000 0x1000>; ++ interrupts = <0 51 4>; ++ interrupt-parent = <&intc>; ++ tx-fifo-depth = <0x40>; ++ rx-fifo-depth = <0x40>; ++ }; ++ ++ gpio0: gpio@e000a000 { ++ compatible = "xlnx,zynq-gpio-1.0"; ++ #gpio-cells = <2>; ++ clocks = <&clkc 42>; ++ gpio-controller; ++ interrupt-parent = <&intc>; ++ interrupts = <0 20 4>; ++ reg = <0xe000a000 0x1000>; ++ }; ++ ++ i2c0: i2c@e0004000 { compatible = "cdns,i2c-r1p10"; status = "disabled"; clocks = <&clkc 38>; @@@ -62,7 -62,7 +110,7 @@@ #size-cells = <0>; }; -- i2c1: zynq-i2c@e0005000 { ++ i2c1: i2c@e0005000 { compatible = "cdns,i2c-r1p10"; status = "disabled"; clocks = <&clkc 39>; @@@ -76,13 -76,13 +124,12 @@@ intc: interrupt-controller@f8f01000 { compatible = "arm,cortex-a9-gic"; #interrupt-cells = <3>; -- #address-cells = <1>; interrupt-controller; reg = <0xF8F01000 0x1000>, <0xF8F00100 0x100>; }; -- L2: cache-controller { ++ L2: cache-controller@f8f02000 { compatible = "arm,pl310-cache"; reg = <0xF8F02000 0x1000>; arm,data-latency = <3 2 2>; @@@ -91,43 -91,43 +138,127 @@@ cache-level = <2>; }; -- uart0: uart@e0000000 { -- compatible = "xlnx,xuartps"; ++ mc0: memory-controller@f8006000 { ++ compatible = "xlnx,zynq-ddrc-a05"; ++ reg = <0xf8006000 0x1000>; ++ xlnx,has-ecc = <0x0>; ++ }; ++ ++ ocmc: ocmc@f800c000 { ++ compatible = "xlnx,zynq-ocmc-1.0"; ++ interrupt-parent = <&intc>; ++ interrupts = <0 3 4>; ++ reg = <0xf800c000 0x1000>; ++ }; ++ ++ uart0: serial@e0000000 { ++ compatible = "xlnx,xuartps", "cdns,uart-r1p8"; status = "disabled"; clocks = <&clkc 23>, <&clkc 40>; -- clock-names = "ref_clk", "aper_clk"; ++ clock-names = "uart_clk", "pclk"; reg = <0xE0000000 0x1000>; interrupts = <0 27 4>; }; -- uart1: uart@e0001000 { -- compatible = "xlnx,xuartps"; ++ uart1: serial@e0001000 { ++ compatible = "xlnx,xuartps", "cdns,uart-r1p8"; status = "disabled"; clocks = <&clkc 24>, <&clkc 41>; -- clock-names = "ref_clk", "aper_clk"; ++ clock-names = "uart_clk", "pclk"; reg = <0xE0001000 0x1000>; interrupts = <0 50 4>; }; ++ spi0: spi@e0006000 { ++ compatible = "xlnx,zynq-spi-r1p6"; ++ reg = <0xe0006000 0x1000>; ++ status = "disabled"; ++ interrupt-parent = <&intc>; ++ interrupts = <0 26 4>; ++ clocks = <&clkc 25>, <&clkc 34>; ++ clock-names = "ref_clk", "pclk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi1: spi@e0007000 { ++ compatible = "xlnx,zynq-spi-r1p6"; ++ reg = <0xe0007000 0x1000>; ++ status = "disabled"; ++ interrupt-parent = <&intc>; ++ interrupts = <0 49 4>; ++ clocks = <&clkc 26>, <&clkc 35>; ++ clock-names = "ref_clk", "pclk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ qspi: spi@e000d000 { ++ clock-names = "ref_clk", "pclk"; ++ clocks = <&clkc 10>, <&clkc 43>; ++ compatible = "xlnx,zynq-qspi-1.0"; ++ status = "disabled"; ++ interrupt-parent = <&intc>; ++ interrupts = <0 19 4>; ++ reg = <0xe000d000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ smcc: memory-controller@e000e000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ status = "disabled"; ++ clock-names = "memclk", "aclk"; ++ clocks = <&clkc 11>, <&clkc 44>; ++ compatible = "arm,pl353-smc-r2p1"; ++ interrupt-parent = <&intc>; ++ interrupts = <0 18 4>; ++ ranges ; ++ reg = <0xe000e000 0x1000>; ++ nand0: flash@e1000000 { ++ status = "disabled"; ++ compatible = "arm,pl353-nand-r2p1"; ++ reg = <0xe1000000 0x1000000>; ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ }; ++ nor0: flash@e2000000 { ++ status = "disabled"; ++ compatible = "cfi-flash"; ++ reg = <0xe2000000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ }; ++ }; ++ gem0: ethernet@e000b000 { -- compatible = "cdns,gem"; -- reg = <0xe000b000 0x4000>; ++ compatible = "xlnx,ps7-ethernet-1.00.a"; ++ reg = <0xe000b000 0x1000>; status = "disabled"; interrupts = <0 22 4>; -- clocks = <&clkc 30>, <&clkc 30>, <&clkc 13>; -- clock-names = "pclk", "hclk", "tx_clk"; ++ clocks = <&clkc 13>, <&clkc 30>; ++ clock-names = "ref_clk", "aper_clk"; ++ local-mac-address = [00 0a 35 00 00 00]; ++ xlnx,has-mdio = <0x1>; ++ #address-cells = <1>; ++ #size-cells = <0>; }; gem1: ethernet@e000c000 { -- compatible = "cdns,gem"; -- reg = <0xe000c000 0x4000>; ++ compatible = "xlnx,ps7-ethernet-1.00.a"; ++ reg = <0xe000c000 0x1000>; status = "disabled"; interrupts = <0 45 4>; -- clocks = <&clkc 31>, <&clkc 31>, <&clkc 14>; -- clock-names = "pclk", "hclk", "tx_clk"; ++ clocks = <&clkc 14>, <&clkc 31>; ++ clock-names = "ref_clk", "aper_clk"; ++ local-mac-address = [00 0a 35 00 00 00]; ++ xlnx,has-mdio = <0x1>; ++ #address-cells = <1>; ++ #size-cells = <0>; }; -- sdhci0: ps7-sdhci@e0100000 { ++ sdhci0: sdhci@e0100000 { compatible = "arasan,sdhci-8.9a"; status = "disabled"; clock-names = "clk_xin", "clk_ahb"; @@@ -135,9 -135,9 +266,9 @@@ interrupt-parent = <&intc>; interrupts = <0 24 4>; reg = <0xe0100000 0x1000>; -- } ; ++ }; -- sdhci1: ps7-sdhci@e0101000 { ++ sdhci1: sdhci@e0101000 { compatible = "arasan,sdhci-8.9a"; status = "disabled"; clock-names = "clk_xin", "clk_ahb"; @@@ -145,7 -145,7 +276,7 @@@ interrupt-parent = <&intc>; interrupts = <0 47 4>; reg = <0xe0101000 0x1000>; -- } ; ++ }; slcr: slcr@f8000000 { #address-cells = <1>; @@@ -157,7 -157,7 +288,7 @@@ #clock-cells = <1>; compatible = "xlnx,ps7-clkc"; ps-clk-frequency = <33333333>; -- fclk-enable = <0>; ++ fclk-enable = <0xf>; clock-output-names = "armpll", "ddrpll", "iopll", "cpu_6or4x", "cpu_3or2x", "cpu_2x", "cpu_1x", "ddr2x", "ddr3x", "dci", "lqspi", "smc", "pcap", "gem0", "gem1", @@@ -173,6 -173,6 +304,33 @@@ }; }; ++ dmac_s: dmac@f8003000 { ++ compatible = "arm,pl330", "arm,primecell"; ++ reg = <0xf8003000 0x1000>; ++ interrupt-parent = <&intc>; ++ interrupt-names = "abort", "dma0", "dma1", "dma2", "dma3", ++ "dma4", "dma5", "dma6", "dma7"; ++ interrupts = <0 13 4>, ++ <0 14 4>, <0 15 4>, ++ <0 16 4>, <0 17 4>, ++ <0 40 4>, <0 41 4>, ++ <0 42 4>, <0 43 4>; ++ #dma-cells = <1>; ++ #dma-channels = <8>; ++ #dma-requests = <4>; ++ clocks = <&clkc 27>; ++ clock-names = "apb_pclk"; ++ }; ++ ++ devcfg: devcfg@f8007000 { ++ clock-names = "ref_clk", "fclk0", "fclk1", "fclk2", "fclk3"; ++ clocks = <&clkc 12>, <&clkc 15>, <&clkc 16>, <&clkc 17>, <&clkc 18>; ++ compatible = "xlnx,zynq-devcfg-1.0"; ++ interrupt-parent = <&intc>; ++ interrupts = <0 8 4>; ++ reg = <0xf8007000 0x100>; ++ }; ++ global_timer: timer@f8f00200 { compatible = "arm,cortex-a9-global-timer"; reg = <0xf8f00200 0x20>; @@@ -181,27 -181,27 +339,57 @@@ clocks = <&clkc 4>; }; -- ttc0: ttc0@f8001000 { ++ ttc0: timer@f8001000 { interrupt-parent = <&intc>; -- interrupts = < 0 10 4 0 11 4 0 12 4 >; ++ interrupts = <0 10 4>, <0 11 4>, <0 12 4>; compatible = "cdns,ttc"; clocks = <&clkc 6>; reg = <0xF8001000 0x1000>; }; -- ttc1: ttc1@f8002000 { ++ ttc1: timer@f8002000 { interrupt-parent = <&intc>; -- interrupts = < 0 37 4 0 38 4 0 39 4 >; ++ interrupts = <0 37 4>, <0 38 4>, <0 39 4>; compatible = "cdns,ttc"; clocks = <&clkc 6>; reg = <0xF8002000 0x1000>; }; -- scutimer: scutimer@f8f00600 { ++ ++ scutimer: timer@f8f00600 { interrupt-parent = <&intc>; -- interrupts = < 1 13 0x301 >; ++ interrupts = <1 13 0x301>; compatible = "arm,cortex-a9-twd-timer"; -- reg = < 0xf8f00600 0x20 >; ++ reg = <0xf8f00600 0x20>; clocks = <&clkc 4>; -- } ; ++ }; ++ ++ watchdog0: watchdog@f8005000 { ++ clocks = <&clkc 45>; ++ compatible = "xlnx,zynq-wdt-r1p2"; ++ device_type = "watchdog"; ++ interrupt-parent = <&intc>; ++ interrupts = <0 9 1>; ++ reg = <0xf8005000 0x1000>; ++ reset = <0>; ++ timeout-sec = <10>; ++ }; ++ ++ usb0: usb@e0002000 { ++ clocks = <&clkc 28>; ++ compatible = "xlnx,ps7-usb-1.00.a", "xlnx,zynq-usb-1.00.a"; ++ status = "disabled"; ++ interrupt-parent = <&intc>; ++ interrupts = <0 21 4>; ++ reg = <0xe0002000 0x1000>; ++ }; ++ ++ usb1: usb@e0003000 { ++ clocks = <&clkc 29>; ++ compatible = "xlnx,ps7-usb-1.00.a", "xlnx,zynq-usb-1.00.a"; ++ status = "disabled"; ++ interrupt-parent = <&intc>; ++ interrupts = <0 44 4>; ++ reg = <0xe0003000 0x1000>; ++ }; }; }; diff --cc arch/arm/dts/zynq-cc108.dts index 00000000000,00000000000..eb5da525c61 new file mode 100644 --- /dev/null +++ b/arch/arm/dts/zynq-cc108.dts @@@ -1,0 -1,0 +1,109 @@@ ++/* ++ * Device Tree Generator version: 1.1 ++ * ++ * (C) Copyright 2007-2013 Xilinx, Inc. ++ * (C) Copyright 2007-2013 Michal Simek ++ * (C) Copyright 2007-2012 PetaLogix Qld Pty Ltd ++ * ++ * Michal SIMEK ++ * ++ * CAUTION: This file is automatically generated by libgen. ++ * Version: Xilinx EDK 14.7 EDK_P.20131013 ++ * ++ */ ++/dts-v1/; ++/include/ "zynq-7000.dtsi" ++ ++/ { ++ compatible = "xlnx,zynq-cc108", "xlnx,zynq-7000"; ++ model = "Xilinx Zynq"; ++ ++ aliases { ++ ethernet0 = &gem0; ++ serial0 = &uart1; ++ spi0 = &qspi; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyPS0,115200 root=/dev/ram rw earlyprintk"; ++ linux,stdout-path = "/amba/serial@e0001000"; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x20000000>; ++ }; ++}; ++ ++&qspi { ++ status = "okay"; ++ is-dual = <0>; ++ num-cs = <1>; ++ flash@0 { /* 16 MB */ ++ compatible = "n25q128a11"; ++ reg = <0x0>; ++ spi-max-frequency = <50000000>; ++ spi-tx-bus-width = <1>; ++ spi-rx-bus-width = <4>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ partition@0 { ++ label = "qspi-fsbl-uboot-bs"; ++ reg = <0x0 0x400000>; /* 4MB */ ++ }; ++ partition@0x400000 { ++ label = "qspi-linux"; ++ reg = <0x400000 0x400000>; /* 4MB */ ++ }; ++ partition@0x800000 { ++ label = "qspi-rootfs"; ++ reg = <0x800000 0x400000>; /* 4MB */ ++ }; ++ partition@0xc00000 { ++ label = "qspi-devicetree"; ++ reg = <0xc00000 0x100000>; /* 1MB */ ++ }; ++ partition@0xd00000 { ++ label = "qspi-scratch"; ++ reg = <0xd00000 0x200000>; /* 2MB */ ++ }; ++ partition@0xf00000 { ++ label = "qspi-uboot-env"; ++ reg = <0xf00000 0x100000>; /* 1MB */ ++ }; ++ }; ++}; ++ ++&usb0 { ++ status = "okay"; ++ dr_mode = "peripheral"; ++ phy_type = "ulpi"; ++ usb-reset = <&gpio0 9 0>; ++}; ++ ++&usb1 { ++ status = "okay"; ++ dr_mode = "host"; ++ phy_type = "ulpi"; ++}; ++ ++ ++&gem0 { ++ status = "okay"; ++ phy-mode = "rgmii-id"; ++ phy-handle = <&phy0>; ++ ++ phy0: phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&sdhci1 { ++ status = "okay"; ++ broken-cd ; ++ wp-inverted ; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; diff --cc arch/arm/dts/zynq-zc770-xm011.dts index 00000000000,00000000000..0f1a5fc6452 new file mode 100644 --- /dev/null +++ b/arch/arm/dts/zynq-zc770-xm011.dts @@@ -1,0 -1,0 +1,108 @@@ ++/* ++ * Device Tree Generator version: 1.1 ++ * ++ * (C) Copyright 2007-2013 Xilinx, Inc. ++ * (C) Copyright 2007-2013 Michal Simek ++ * (C) Copyright 2007-2012 PetaLogix Qld Pty Ltd ++ * ++ * Michal SIMEK ++ * ++ * CAUTION: This file is automatically generated by libgen. ++ * Version: Xilinx EDK 14.5 EDK_P.58f ++ * ++ */ ++/dts-v1/; ++/include/ "zynq-7000.dtsi" ++ ++/ { ++ compatible = "xlnx,zynq-zc770-xm011", "xlnx,zynq-7000"; ++ model = "Xilinx Zynq"; ++ ++ aliases { ++ i2c0 = &i2c1; ++ serial0 = &uart1; ++ spi0 = &spi0; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyPS0,115200 root=/dev/ram rw earlyprintk"; ++ linux,stdout-path = "/amba/serial@e0001000"; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x40000000>; ++ }; ++}; ++ ++&smcc { ++ status = "okay"; ++ arm,addr25 = <0x0>; ++ arm,nor-chip-sel0 = <0x0>; ++ arm,nor-chip-sel1 = <0x0>; ++ arm,sram-chip-sel0 = <0x0>; ++ arm,sram-chip-sel1 = <0x0>; ++}; ++ ++&nand0 { ++ status = "okay"; ++ arm,nand-cycle-t0 = <0x4>; ++ arm,nand-cycle-t1 = <0x4>; ++ arm,nand-cycle-t2 = <0x1>; ++ arm,nand-cycle-t3 = <0x2>; ++ arm,nand-cycle-t4 = <0x2>; ++ arm,nand-cycle-t5 = <0x2>; ++ arm,nand-cycle-t6 = <0x4>; ++ ++ partition@nand-fsbl-uboot { ++ label = "nand-fsbl-uboot"; ++ reg = <0x0 0x100000>; ++ }; ++ partition@nand-linux { ++ label = "nand-linux"; ++ reg = <0x100000 0x500000>; ++ }; ++ partition@nand-device-tree { ++ label = "nand-device-tree"; ++ reg = <0x600000 0x20000>; ++ }; ++ partition@nand-rootfs { ++ label = "nand-rootfs"; ++ reg = <0x620000 0x5E0000>; ++ }; ++ partition@nand-bitstream { ++ label = "nand-bitstream"; ++ reg = <0xC00000 0x400000>; ++ }; ++}; ++ ++&spi0 { ++ status = "okay"; ++ num-cs = <4>; ++ is-decoded-cs = <0>; ++}; ++ ++&usb1 { ++ status = "okay"; ++ dr_mode = "host"; ++ phy_type = "ulpi"; ++}; ++ ++ ++&can0 { ++ status = "okay"; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ m24c02_eeprom@52 { ++ compatible = "at,24c02"; ++ reg = <0x52>; ++ }; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; diff --cc arch/arm/lib/bootm-fdt.c index 9f9ebb07094,d4f1578e9e9..3a2c440abbd --- a/arch/arm/lib/bootm-fdt.c +++ b/arch/arm/lib/bootm-fdt.c @@@ -20,7 -21,24 +21,7 @@@ DECLARE_GLOBAL_DATA_PTR; - int arch_fixup_memory_node(void *blob) + int arch_fixup_fdt(void *blob) { - bd_t *bd = gd->bd; - int bank, ret; - u64 start[CONFIG_NR_DRAM_BANKS]; - u64 size[CONFIG_NR_DRAM_BANKS]; - - for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { - start[bank] = bd->bi_dram[bank].start; - size[bank] = bd->bi_dram[bank].size; - } - - ret = fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS); -#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT) - if (ret) - return ret; - - ret = armv7_update_dt(blob); -#endif - return ret; + return 0; } diff --cc arch/arm/lib/bootm.c index 8c33345e02b,0c1298a31e7..9fc0cb7a5e1 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@@ -238,10 -231,32 +231,29 @@@ static void boot_prep_linux(bootm_heade } setup_board_tags(¶ms); setup_end_tag(gd->bd); - } else { - printf("FDT and ATAGS support not compiled in - hanging\n"); - hang(); } - do_nonsec_virt_switch(); } + #if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT) + bool armv7_boot_nonsec(void) + { + char *s = getenv("bootm_boot_mode"); + #ifdef CONFIG_ARMV7_BOOT_SEC_DEFAULT + bool nonsec = false; + #else + bool nonsec = true; + #endif + + if (s && !strcmp(s, "sec")) + nonsec = false; + + if (s && !strcmp(s, "nonsec")) + nonsec = true; + + return nonsec; + } + #endif + /* Subcommand: GO */ static void boot_jump_linux(bootm_headers_t *images, int flag) { diff --cc common/Kconfig index 00000000000,fd84fa08bd3..5f99e18bcb2 mode 000000,100644..100644 --- a/common/Kconfig +++ b/common/Kconfig @@@ -1,0 -1,316 +1,321 @@@ + menu "Command line interface" + depends on !SPL_BUILD + + config HUSH_PARSER + bool "Use hush shell" + select SYS_HUSH_PARSER + help + This option enables the "hush" shell (from Busybox) as command line + interpreter, thus enabling powerful command line syntax like + if...then...else...fi conditionals or `&&' and '||' + constructs ("shell scripts"). + + If disabled, you get the old, much simpler behaviour with a somewhat + smaller memory footprint. + + config SYS_HUSH_PARSER + bool + help + Backward compatibility. + + comment "Commands" + + menu "Info commands" + + config CMD_BDI + bool "bdinfo" + help + Print board info + + config CMD_CONSOLE + bool "coninfo" + help + Print console devices and information. + + config CMD_LICENSE + bool "license" + help + Print GPL license text + + endmenu + + menu "Boot commands" + + config CMD_BOOTD + bool "bootd" + help + Run the command stored in the environment "bootcmd", i.e. + "bootd" does the same thing as "run bootcmd". + + config CMD_BOOTM + bool "bootm" + default y + help + Boot an application image from the memory. + + config CMD_GO + bool "go" + default y + help + Start an application at a given address. + + config CMD_RUN + bool "run" + help + Run the command in the given environment variable. + + config CMD_IMI + bool "iminfo" + help + Print header information for application image. + + config CMD_IMLS + bool "imls" + help + List all images found in flash + + config CMD_XIMG + bool "imxtract" + help + Extract a part of a multi-image. + + endmenu + + menu "Environment commands" + + config CMD_EXPORTENV + bool "env export" + default y + help + Export environments. + + config CMD_IMPORTENV + bool "env import" + default y + help + Import environments. + + config CMD_EDITENV + bool "editenv" + help + Edit environment variable. + + config CMD_SAVEENV + bool "saveenv" + help + Run the command in the given environment variable. + + endmenu + + menu "Memory commands" + + config CMD_MEMORY + bool "md, mm, nm, mw, cp, cmp, base, loop" + help + Memeory commands. + md - memory display + mm - memory modify (auto-incrementing address) + nm - memory modify (constant address) + mw - memory write (fill) + cp - memory copy + cmp - memory compare + base - print or set address offset + loop - initinite loop on address range + + config CMD_CRC32 + bool "crc32" + default y + help + Compute CRC32. + + config LOOPW + bool "loopw" + help + Infinite write loop on address range + + config CMD_MEMTEST + bool "crc32" + help + Simple RAM read/write test. + + config CMD_MX_CYCLIC + bool "mdc, mwc" + help + mdc - memory display cyclic + mwc - memory write cyclic + + config CMD_MEMINFO + bool "meminfo" + help + Display memory information. + + endmenu + + menu "Device access commands" + + config CMD_LOADB + bool "loadb" + help + Load a binary file over serial line. + + config CMD_LOADS + bool "loads" + help + Load an S-Record file over serial line + + config CMD_FLASH + bool "flinfo, erase, protect" + help + NOR flash support. + flinfo - print FLASH memory information + erase - FLASH memory + protect - enable or disable FLASH write protection + + config CMD_NAND + bool "nand" + help + NAND support. + + config CMD_SPI + bool "sspi" + help + SPI utility command. + + config CMD_I2C + bool "i2c" + help + I2C support. + + config CMD_USB + bool "usb" + help + USB support. + + config CMD_FPGA + bool "fpga" + help + FPGA support. + + endmenu + + + menu "Shell scripting commands" + + config CMD_ECHO + bool "echo" + help + Echo args to console + + config CMD_ITEST + bool "itest" + help + Return true/false on integer compare. + + config CMD_SOURCE + bool "source" + help + Run script from memory + + endmenu + + menu "Network commands" + + config CMD_NET + bool "bootp, tftpboot" + help + Network commands. + bootp - boot image via network using BOOTP/TFTP protocol + tftpboot - boot image via network using TFTP protocol + + config CMD_TFTPPUT + bool "tftp put" + help + TFTP put command, for uploading files to a server + + config CMD_TFTPSRV + bool "tftpsrv" + help + Act as a TFTP server and boot the first received file + + config CMD_RARP + bool "rarpboot" + help + Boot image via network using RARP/TFTP protocol + + config CMD_DHCP + bool "dhcp" + help + Boot image via network using DHCP/TFTP protocol + + config CMD_NFS + bool "nfs" + help + Boot image via network using NFS protocol. + + config CMD_PING + bool "ping" + help + Send ICMP ECHO_REQUEST to network host + + config CMD_CDP + bool "cdp" + help + Perform CDP network configuration + + config CMD_SNTP + bool "sntp" + help + Synchronize RTC via network + + config CMD_DNS + bool "dns" + help + Lookup the IP of a hostname + + config CMD_DNS + bool "dns" + help + Lookup the IP of a hostname + + config CMD_LINK_LOCAL + bool "linklocal" + help + Acquire a network IP address using the link-local protocol + + endmenu + + menu "Misc commands" + + config CMD_TIME + bool "time" + help + Run commands and summarize execution time. + + # TODO: rename to CMD_SLEEP + config CMD_MISC + bool "sleep" + help + Delay execution for some time + + config CMD_TIMER + bool "timer" + help + Access the system timer. + + config CMD_SETGETDCR + bool "getdcr, setdcr, getidcr, setidcr" + depends on 4xx + help + getdcr - Get an AMCC PPC 4xx DCR's value + setdcr - Set an AMCC PPC 4xx DCR's value + getidcr - Get a register value via indirect DCR addressing + setidcr - Set a register value via indirect DCR addressing + ++config CMD_ZYNQ_RSA ++ bool "Zynq RSA" ++ help ++ Verifies the authenticated and encrypted zynq images. ++ + endmenu + + endmenu diff --cc common/spl/spl_mmc.c index f86ba680c2a,c2e596be69b..0dc94f755ae --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@@ -71,35 -85,6 +88,35 @@@ static int mmc_load_image_raw_os(struc } #endif +#ifdef CONFIG_SPL_FPGA_SUPPORT +static int mmc_load_fpga_image_fat(struct mmc *mmc) +{ + int err; + int devnum = 0; + const fpga_desc *const desc = fpga_get_desc(devnum); + xilinx_desc *desc_xilinx = desc->devdesc; + - /* FIXME = standard file size + header desc_xilinx->size + 0x6c */ - err = file_fat_read(CONFIG_SPL_FPGA_LOAD_ARGS_NAME, - (void *)CONFIG_SPL_FPGA_LOAD_ADDR, - 0); - if (err <= 0) { ++ err = spl_load_image_fat(&mmc->block_dev, ++ CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, ++ CONFIG_SPL_FPGA_LOAD_ARGS_NAME); ++ ++ if (err) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("spl: error reading image %s, err - %d\n", + CONFIG_SPL_FPGA_LOAD_ARGS_NAME, err); +#endif + return -1; + } +#ifdef CONFIG_SPL_FPGA_BIT - return fpga_loadbitstream(devnum, (char *)CONFIG_SPL_FPGA_LOAD_ADDR, ++ return fpga_loadbitstream(devnum, (char *)spl_image.load_addr, + desc_xilinx->size, BIT_FULL); +#else - return fpga_load(devnum, (const void *)CONFIG_SPL_FPGA_LOAD_ADDR, ++ return fpga_load(devnum, (const void *)spl_image.load_addr, + desc_xilinx->size, BIT_FULL); +#endif +} +#endif + void spl_mmc_load_image(void) { struct mmc *mmc; @@@ -130,24 -115,39 +147,44 @@@ #ifdef CONFIG_SPL_OS_BOOT if (spl_start_uboot() || mmc_load_image_raw_os(mmc)) #endif - err = mmc_load_image_raw(mmc, + #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION + err = mmc_load_image_raw_partition(mmc, + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION); + #else + err = mmc_load_image_raw_sector(mmc, CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); + #endif + #if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT) + } + if (err || boot_mode == MMCSD_MODE_FS) { + debug("boot mode - FS\n"); #ifdef CONFIG_SPL_FAT_SUPPORT - } else if (boot_mode == MMCSD_MODE_FAT) { - debug("boot mode - FAT\n"); + +#ifdef CONFIG_SPL_FPGA_SUPPORT + mmc_load_fpga_image_fat(mmc); +#endif + #ifdef CONFIG_SPL_OS_BOOT if (spl_start_uboot() || spl_load_image_fat_os(&mmc->block_dev, - CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION)) + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION)) #endif err = spl_load_image_fat(&mmc->block_dev, - CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION, - CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME); + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, + CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); + if(err) + #endif /* CONFIG_SPL_FAT_SUPPORT */ + { + #ifdef CONFIG_SPL_EXT_SUPPORT + #ifdef CONFIG_SPL_OS_BOOT + if (spl_start_uboot() || spl_load_image_ext_os(&mmc->block_dev, + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION)) #endif + err = spl_load_image_ext(&mmc->block_dev, + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, + CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); + #endif /* CONFIG_SPL_EXT_SUPPORT */ + } + #endif /* defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT) */ #ifdef CONFIG_SUPPORT_EMMC_BOOT } else if (boot_mode == MMCSD_MODE_EMMCBOOT) { /* diff --cc configs/zynq_afx_nand_RSA_defconfig index 00000000000,00000000000..632a2734d80 new file mode 100644 --- /dev/null +++ b/configs/zynq_afx_nand_RSA_defconfig @@@ -1,0 -1,0 +1,7 @@@ ++CONFIG_SPL=n ++CONFIG_SYS_EXTRA_OPTIONS="AFX_NAND" +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_AFX=y ++CONFIG_OF_CONTROL=n ++CONFIG_CMD_ZYNQ_RSA=y diff --cc configs/zynq_afx_nand_defconfig index 00000000000,00000000000..8880484efb2 new file mode 100644 --- /dev/null +++ b/configs/zynq_afx_nand_defconfig @@@ -1,0 -1,0 +1,6 @@@ ++CONFIG_SPL=n ++CONFIG_SYS_EXTRA_OPTIONS="AFX_NAND" +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_AFX=y ++CONFIG_OF_CONTROL=n diff --cc configs/zynq_afx_nor_RSA_defconfig index 00000000000,00000000000..281cbecb365 new file mode 100644 --- /dev/null +++ b/configs/zynq_afx_nor_RSA_defconfig @@@ -1,0 -1,0 +1,7 @@@ ++CONFIG_SPL=n ++CONFIG_SYS_EXTRA_OPTIONS="AFX_NOR" +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_AFX=y ++CONFIG_OF_CONTROL=n ++CONFIG_CMD_ZYNQ_RSA=y diff --cc configs/zynq_afx_nor_defconfig index 00000000000,00000000000..e16e3d2819e new file mode 100644 --- /dev/null +++ b/configs/zynq_afx_nor_defconfig @@@ -1,0 -1,0 +1,6 @@@ ++CONFIG_SPL=n ++CONFIG_SYS_EXTRA_OPTIONS="AFX_NOR" +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_AFX=y ++CONFIG_OF_CONTROL=n diff --cc configs/zynq_afx_qspi_RSA_defconfig index 00000000000,00000000000..adf07de766e new file mode 100644 --- /dev/null +++ b/configs/zynq_afx_qspi_RSA_defconfig @@@ -1,0 -1,0 +1,7 @@@ ++CONFIG_SPL=n ++CONFIG_SYS_EXTRA_OPTIONS="AFX_QSPI" +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_AFX=y ++CONFIG_OF_CONTROL=n ++CONFIG_CMD_ZYNQ_RSA=y diff --cc configs/zynq_afx_qspi_defconfig index 00000000000,00000000000..12c3a76f15d new file mode 100644 --- /dev/null +++ b/configs/zynq_afx_qspi_defconfig @@@ -1,0 -1,0 +1,6 @@@ ++CONFIG_SPL=n ++CONFIG_SYS_EXTRA_OPTIONS="AFX_QSPI" +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_AFX=y ++CONFIG_OF_CONTROL=n diff --cc configs/zynq_cc108_defconfig index 00000000000,00000000000..bf4e23e021c new file mode 100644 --- /dev/null +++ b/configs/zynq_cc108_defconfig @@@ -1,0 -1,0 +1,6 @@@ ++CONFIG_SPL=y +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_CC108=y ++CONFIG_OF_CONTROL=n ++CONFIG_DEFAULT_DEVICE_TREE="zynq-cc108" diff --cc configs/zynq_cse_nand_defconfig index 00000000000,00000000000..0379cd931f8 new file mode 100644 --- /dev/null +++ b/configs/zynq_cse_nand_defconfig @@@ -1,0 -1,0 +1,7 @@@ ++CONFIG_SPL=n ++CONFIG_SYS_EXTRA_OPTIONS="CSE_NAND" +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_CSE=y ++CONFIG_CMD_BOOTM=n ++CONFIG_CMD_GO=n diff --cc configs/zynq_cse_nor_defconfig index 00000000000,00000000000..4aeffcaf642 new file mode 100644 --- /dev/null +++ b/configs/zynq_cse_nor_defconfig @@@ -1,0 -1,0 +1,7 @@@ ++CONFIG_SPL=n ++CONFIG_SYS_EXTRA_OPTIONS="CSE_NOR" +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_CSE=y ++CONFIG_CMD_BOOTM=n ++CONFIG_CMD_GO=n diff --cc configs/zynq_cse_qspi_defconfig index 00000000000,00000000000..6b3e23c6e2a new file mode 100644 --- /dev/null +++ b/configs/zynq_cse_qspi_defconfig @@@ -1,0 -1,0 +1,7 @@@ ++CONFIG_SPL=n ++CONFIG_SYS_EXTRA_OPTIONS="CSE_QSPI" +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_CSE=y ++CONFIG_CMD_BOOTM=n ++CONFIG_CMD_GO=n diff --cc configs/zynq_microzed_defconfig index 00000000000,9588849bb5c..f9ae4a2fa22 mode 000000,100644..100644 --- a/configs/zynq_microzed_defconfig +++ b/configs/zynq_microzed_defconfig @@@ -1,0 -1,6 +1,6 @@@ + CONFIG_SPL=y + +S:CONFIG_ARM=y + +S:CONFIG_ZYNQ=y + +S:CONFIG_TARGET_ZYNQ_MICROZED=y -CONFIG_OF_CONTROL=y ++CONFIG_OF_CONTROL=n + CONFIG_DEFAULT_DEVICE_TREE="zynq-microzed" diff --cc configs/zynq_zc70x_RSA_defconfig index 00000000000,00000000000..630a7d5dde2 new file mode 100644 --- /dev/null +++ b/configs/zynq_zc70x_RSA_defconfig @@@ -1,0 -1,0 +1,7 @@@ ++CONFIG_SPL=y +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_ZC70X=y ++CONFIG_OF_CONTROL=n ++CONFIG_DEFAULT_DEVICE_TREE="zynq-zc702" ++CONFIG_CMD_ZYNQ_RSA=y diff --cc configs/zynq_zc70x_defconfig index 00000000000,cf507308e95..9902ea4dc90 mode 000000,100644..100644 --- a/configs/zynq_zc70x_defconfig +++ b/configs/zynq_zc70x_defconfig @@@ -1,0 -1,6 +1,6 @@@ + CONFIG_SPL=y + +S:CONFIG_ARM=y + +S:CONFIG_ZYNQ=y + +S:CONFIG_TARGET_ZYNQ_ZC70X=y -CONFIG_OF_CONTROL=y ++CONFIG_OF_CONTROL=n + CONFIG_DEFAULT_DEVICE_TREE="zynq-zc702" diff --cc configs/zynq_zc770_xm010_RSA_defconfig index 00000000000,00000000000..011ab4d6c2e new file mode 100644 --- /dev/null +++ b/configs/zynq_zc770_xm010_RSA_defconfig @@@ -1,0 -1,0 +1,8 @@@ ++CONFIG_SPL=n ++CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM010" +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_ZC770=y ++CONFIG_OF_CONTROL=n ++CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm010" ++CONFIG_CMD_ZYNQ_RSA=y diff --cc configs/zynq_zc770_xm010_defconfig index 00000000000,8bb405d1808..0c66fc3375c mode 000000,100644..100644 --- a/configs/zynq_zc770_xm010_defconfig +++ b/configs/zynq_zc770_xm010_defconfig @@@ -1,0 -1,7 +1,7 @@@ -CONFIG_SPL=y ++CONFIG_SPL=n + CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM010" + +S:CONFIG_ARM=y + +S:CONFIG_ZYNQ=y + +S:CONFIG_TARGET_ZYNQ_ZC770=y -CONFIG_OF_CONTROL=y ++CONFIG_OF_CONTROL=n + CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm010" diff --cc configs/zynq_zc770_xm011_RSA_defconfig index 00000000000,00000000000..f1292be3c8a new file mode 100644 --- /dev/null +++ b/configs/zynq_zc770_xm011_RSA_defconfig @@@ -1,0 -1,0 +1,8 @@@ ++CONFIG_SPL=n ++CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM011" +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_ZC770=y ++CONFIG_OF_CONTROL=n ++CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm011" ++CONFIG_CMD_ZYNQ_RSA=y diff --cc configs/zynq_zc770_xm011_defconfig index 00000000000,00000000000..744288095a5 new file mode 100644 --- /dev/null +++ b/configs/zynq_zc770_xm011_defconfig @@@ -1,0 -1,0 +1,7 @@@ ++CONFIG_SPL=n ++CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM011" +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_ZC770=y ++CONFIG_OF_CONTROL=n ++CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm011" diff --cc configs/zynq_zc770_xm012_RSA_defconfig index 00000000000,00000000000..f1a8cb77e42 new file mode 100644 --- /dev/null +++ b/configs/zynq_zc770_xm012_RSA_defconfig @@@ -1,0 -1,0 +1,8 @@@ ++CONFIG_SPL=n ++CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM012" +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_ZC770=y ++CONFIG_OF_CONTROL=n ++CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm012" ++CONFIG_CMD_ZYNQ_RSA=y diff --cc configs/zynq_zc770_xm012_defconfig index 00000000000,0ba5da589e9..a2c5b3a26c1 mode 000000,100644..100644 --- a/configs/zynq_zc770_xm012_defconfig +++ b/configs/zynq_zc770_xm012_defconfig @@@ -1,0 -1,7 +1,7 @@@ -CONFIG_SPL=y ++CONFIG_SPL=n + CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM012" + +S:CONFIG_ARM=y + +S:CONFIG_ZYNQ=y + +S:CONFIG_TARGET_ZYNQ_ZC770=y -CONFIG_OF_CONTROL=y ++CONFIG_OF_CONTROL=n + CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm012" diff --cc configs/zynq_zc770_xm013_RSA_defconfig index 00000000000,00000000000..01a67d57308 new file mode 100644 --- /dev/null +++ b/configs/zynq_zc770_xm013_RSA_defconfig @@@ -1,0 -1,0 +1,8 @@@ ++CONFIG_SPL=n ++CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM013" +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_ZC770=y ++CONFIG_OF_CONTROL=n ++CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm013" ++CONFIG_CMD_ZYNQ_RSA=y diff --cc configs/zynq_zc770_xm013_defconfig index 00000000000,13f8112a1b6..0fb5f74e166 mode 000000,100644..100644 --- a/configs/zynq_zc770_xm013_defconfig +++ b/configs/zynq_zc770_xm013_defconfig @@@ -1,0 -1,7 +1,7 @@@ -CONFIG_SPL=y ++CONFIG_SPL=n + CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM013" + +S:CONFIG_ARM=y + +S:CONFIG_ZYNQ=y + +S:CONFIG_TARGET_ZYNQ_ZC770=y -CONFIG_OF_CONTROL=y ++CONFIG_OF_CONTROL=n + CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm013" diff --cc configs/zynq_zed_RSA_defconfig index 00000000000,00000000000..feca419707f new file mode 100644 --- /dev/null +++ b/configs/zynq_zed_RSA_defconfig @@@ -1,0 -1,0 +1,7 @@@ ++CONFIG_SPL=y +++S:CONFIG_ARM=y +++S:CONFIG_ZYNQ=y +++S:CONFIG_TARGET_ZYNQ_ZED=y ++CONFIG_OF_CONTROL=n ++CONFIG_DEFAULT_DEVICE_TREE="zynq-zed" ++CONFIG_CMD_ZYNQ_RSA=y diff --cc configs/zynq_zed_defconfig index 00000000000,eb057fae35c..8ff24843594 mode 000000,100644..100644 --- a/configs/zynq_zed_defconfig +++ b/configs/zynq_zed_defconfig @@@ -1,0 -1,6 +1,6 @@@ + CONFIG_SPL=y + +S:CONFIG_ARM=y + +S:CONFIG_ZYNQ=y + +S:CONFIG_TARGET_ZYNQ_ZED=y -CONFIG_OF_CONTROL=y ++CONFIG_OF_CONTROL=n + CONFIG_DEFAULT_DEVICE_TREE="zynq-zed" diff --cc configs/zynq_zybo_defconfig index 00000000000,12311cd83b5..9ccfc52d540 mode 000000,100644..100644 --- a/configs/zynq_zybo_defconfig +++ b/configs/zynq_zybo_defconfig @@@ -1,0 -1,6 +1,6 @@@ + CONFIG_SPL=y + +S:CONFIG_ARM=y + +S:CONFIG_ZYNQ=y + +S:CONFIG_TARGET_ZYNQ_ZYBO=y -CONFIG_OF_CONTROL=y ++CONFIG_OF_CONTROL=n + CONFIG_DEFAULT_DEVICE_TREE="zynq-zybo" diff --cc drivers/mtd/nand/zynq_nand.c index 75ead1f3c43,00000000000..5caea3d7c1e mode 100644,000000..100644 --- a/drivers/mtd/nand/zynq_nand.c +++ b/drivers/mtd/nand/zynq_nand.c @@@ -1,1252 -1,0 +1,1252 @@@ +/* + * Xilinx Zynq NAND Flash Controller Driver + * This driver is based on plat_nand.c and mxc_nand.c drivers + * + * Copyright (C) 2009 - 2013 Xilinx, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include ++#include +#include +#include +#include +#include +#include +#include + +/* The NAND flash driver defines */ +#define ZYNQ_NAND_CMD_PHASE 1 /* End command valid in command phase */ +#define ZYNQ_NAND_DATA_PHASE 2 /* End command valid in data phase */ +#define ZYNQ_NAND_ECC_SIZE 512 /* Size of data for ECC operation */ + +/* Flash memory controller operating parameters */ +#define ZYNQ_NAND_CLR_CONFIG ((0x1 << 1) | /* Disable interrupt */ \ + (0x1 << 4) | /* Clear interrupt */ \ + (0x1 << 6)) /* Disable ECC interrupt */ + +/* Assuming 50MHz clock (20ns cycle time) and 3V operation */ +#define ZYNQ_NAND_SET_CYCLES ((0x2 << 20) | /* t_rr from nand_cycles */ \ + (0x2 << 17) | /* t_ar from nand_cycles */ \ + (0x1 << 14) | /* t_clr from nand_cycles */ \ + (0x3 << 11) | /* t_wp from nand_cycles */ \ + (0x2 << 8) | /* t_rea from nand_cycles */ \ + (0x5 << 4) | /* t_wc from nand_cycles */ \ + (0x5 << 0)) /* t_rc from nand_cycles */ + +#define ZYNQ_NAND_SET_OPMODE 0x0 + +#define ZYNQ_NAND_DIRECT_CMD ((0x4 << 23) | /* Chip 0 from interface 1 */ \ + (0x2 << 21)) /* UpdateRegs operation */ + +#define ZYNQ_NAND_ECC_CONFIG ((0x1 << 2) | /* ECC available on APB */ \ + (0x1 << 4) | /* ECC read at end of page */ \ + (0x0 << 5)) /* No Jumping */ + +#define ZYNQ_NAND_ECC_CMD1 ((0x80) | /* Write command */ \ + (0x00 << 8) | /* Read command */ \ + (0x30 << 16) | /* Read End command */ \ + (0x1 << 24)) /* Read End command calid */ + +#define ZYNQ_NAND_ECC_CMD2 ((0x85) | /* Write col change cmd */ \ + (0x05 << 8) | /* Read col change cmd */ \ + (0xE0 << 16) | /* Read col change end cmd */ \ + (0x1 << 24)) /* Read col change + end cmd valid */ +/* AXI Address definitions */ +#define START_CMD_SHIFT 3 +#define END_CMD_SHIFT 11 +#define END_CMD_VALID_SHIFT 20 +#define ADDR_CYCLES_SHIFT 21 +#define CLEAR_CS_SHIFT 21 +#define ECC_LAST_SHIFT 10 +#define COMMAND_PHASE (0 << 19) +#define DATA_PHASE (1 << 19) + +#define ZYNQ_NAND_ECC_LAST (1 << ECC_LAST_SHIFT) /* Set ECC_Last */ +#define ZYNQ_NAND_CLEAR_CS (1 << CLEAR_CS_SHIFT) /* Clear chip select */ + +/* ECC block registers bit position and bit mask */ +#define ZYNQ_NAND_ECC_BUSY (1 << 6) /* ECC block is busy */ +#define ZYNQ_NAND_ECC_MASK 0x00FFFFFF /* ECC value mask */ + +/* NAND MIO buswidth count*/ +#define ZYNQ_NAND_MIO_NUM_NAND_8BIT 13 +#define ZYNQ_NAND_MIO_NUM_NAND_16BIT 8 + +/* NAND buswidth */ +enum zynq_nand_bus_width { + NAND_BW_UNKNOWN = -1, + NAND_BW_8BIT, + NAND_BW_16BIT, +}; + +/* SMC register set */ +struct zynq_nand_smc_regs { + u32 csr; /* 0x00 */ + u32 reserved0[2]; + u32 cfr; /* 0x0C */ + u32 dcr; /* 0x10 */ + u32 scr; /* 0x14 */ + u32 sor; /* 0x18 */ + u32 reserved1[249]; + u32 esr; /* 0x400 */ + u32 emcr; /* 0x404 */ + u32 emcmd1r; /* 0x408 */ + u32 emcmd2r; /* 0x40C */ + u32 reserved2[2]; + u32 eval0r; /* 0x418 */ +}; + +#define zynq_nand_smc_base ((struct zynq_nand_smc_regs *)ZYNQ_SMC_BASEADDR) + +/* + * struct zynq_nand_command_format - Defines NAND flash command format + * @start_cmd: First cycle command (Start command) + * @end_cmd: Second cycle command (Last command) + * @addr_cycles: Number of address cycles required to send the address + * @end_cmd_valid: The second cycle command is valid for cmd or data phase + */ +struct zynq_nand_command_format { + int start_cmd; + int end_cmd; + u8 addr_cycles; + u8 end_cmd_valid; +}; + +/* + * struct zynq_nand_info - Defines the NAND flash driver instance + * @parts: Pointer to the mtd_partition structure + * @nand_base: Virtual address of the NAND flash device + * @end_cmd_pending: End command is pending + * @end_cmd: End command + */ +struct zynq_nand_info { +#ifdef CONFIG_MTD_PARTITIONS + struct mtd_partition *parts; +#endif + void __iomem *nand_base; + unsigned long end_cmd_pending; + unsigned long end_cmd; +}; + +#define ONDIE_ECC_FEATURE_ADDR 0x90 + +/* The NAND flash operations command format */ +static const struct zynq_nand_command_format zynq_nand_commands[] = { + {NAND_CMD_READ0, NAND_CMD_READSTART, 5, ZYNQ_NAND_CMD_PHASE}, + {NAND_CMD_RNDOUT, NAND_CMD_RNDOUTSTART, 2, ZYNQ_NAND_CMD_PHASE}, + {NAND_CMD_READID, NAND_CMD_NONE, 1, NAND_CMD_NONE}, + {NAND_CMD_STATUS, NAND_CMD_NONE, 0, NAND_CMD_NONE}, + {NAND_CMD_SEQIN, NAND_CMD_PAGEPROG, 5, ZYNQ_NAND_DATA_PHASE}, + {NAND_CMD_RNDIN, NAND_CMD_NONE, 2, NAND_CMD_NONE}, + {NAND_CMD_ERASE1, NAND_CMD_ERASE2, 3, ZYNQ_NAND_CMD_PHASE}, + {NAND_CMD_RESET, NAND_CMD_NONE, 0, NAND_CMD_NONE}, + {NAND_CMD_PARAM, NAND_CMD_NONE, 1, NAND_CMD_NONE}, + {NAND_CMD_GET_FEATURES, NAND_CMD_NONE, 1, NAND_CMD_NONE}, + {NAND_CMD_SET_FEATURES, NAND_CMD_NONE, 1, NAND_CMD_NONE}, + {NAND_CMD_NONE, NAND_CMD_NONE, 0, 0}, + /* Add all the flash commands supported by the flash device and Linux + * The cache program command is not supported by driver because driver + * cant differentiate between page program and cached page program from + * start command, these commands can be differentiated through end + * command, which doesn't fit in to the driver design. The cache program + * command is not supported by NAND subsystem also, look at 1612 line + * number (in nand_write_page function) of nand_base.c file. + * {NAND_CMD_SEQIN, NAND_CMD_CACHEDPROG, 5, ZYNQ_NAND_YES} + */ +}; + +/* Define default oob placement schemes for large and small page devices */ +static struct nand_ecclayout nand_oob_16 = { + .eccbytes = 3, + .eccpos = {13, 14, 15}, + .oobfree = { + { .offset = 0, .length = 12 } + } +}; + +static struct nand_ecclayout nand_oob_64 = { + .eccbytes = 12, + .eccpos = { + 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63}, + .oobfree = { + { .offset = 2, .length = 50 } + } +}; + +static struct nand_ecclayout ondie_nand_oob_64 = { + .eccbytes = 32, + + .eccpos = { + 8, 9, 10, 11, 12, 13, 14, 15, + 24, 25, 26, 27, 28, 29, 30, 31, + 40, 41, 42, 43, 44, 45, 46, 47, + 56, 57, 58, 59, 60, 61, 62, 63 + }, + + .oobfree = { + { .offset = 4, .length = 4 }, + { .offset = 20, .length = 4 }, + { .offset = 36, .length = 4 }, + { .offset = 52, .length = 4 } + } +}; + +/* Generic flash bbt decriptors */ +static u8 bbt_pattern[] = {'B', 'b', 't', '0' }; +static u8 mirror_pattern[] = {'1', 't', 'b', 'B' }; + +static struct nand_bbt_descr bbt_main_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | + NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, + .offs = 4, + .len = 4, + .veroffs = 20, + .maxblocks = 4, + .pattern = bbt_pattern +}; + +static struct nand_bbt_descr bbt_mirror_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | + NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, + .offs = 4, + .len = 4, + .veroffs = 20, + .maxblocks = 4, + .pattern = mirror_pattern +}; + +/* + * zynq_nand_waitfor_ecc_completion - Wait for ECC completion + * + * returns: status for command completion, -1 for Timeout + */ +static int zynq_nand_waitfor_ecc_completion(void) +{ + unsigned long timeout; + u32 status; + + /* Wait max 10ms */ + timeout = 10; + status = readl(&zynq_nand_smc_base->esr); + while (status & ZYNQ_NAND_ECC_BUSY) { + status = readl(&zynq_nand_smc_base->esr); + if (timeout == 0) + return -1; + timeout--; + udelay(1); + } + + return status; +} + +/* + * zynq_nand_init_nand_flash - Initialize NAND controller + * @option: Device property flags + * + * This function initializes the NAND flash interface on the NAND controller. + * + * returns: 0 on success or error value on failure + */ +static int zynq_nand_init_nand_flash(int option) +{ + u32 status; + + /* disable interrupts */ + writel(ZYNQ_NAND_CLR_CONFIG, &zynq_nand_smc_base->cfr); + /* Initialize the NAND interface by setting cycles and operation mode */ + writel(ZYNQ_NAND_SET_CYCLES, &zynq_nand_smc_base->scr); + if (option & NAND_BUSWIDTH_16) + writel((ZYNQ_NAND_SET_OPMODE | 0x1), &zynq_nand_smc_base->sor); + else + writel(ZYNQ_NAND_SET_OPMODE, &zynq_nand_smc_base->sor); + + writel(ZYNQ_NAND_DIRECT_CMD, &zynq_nand_smc_base->dcr); + + /* Wait till the ECC operation is complete */ + status = zynq_nand_waitfor_ecc_completion(); + if (status < 0) { + printf("%s: Timeout\n", __func__); + return status; + } + + /* Set the command1 and command2 register */ + writel(ZYNQ_NAND_ECC_CMD1, &zynq_nand_smc_base->emcmd1r); + writel(ZYNQ_NAND_ECC_CMD2, &zynq_nand_smc_base->emcmd2r); + + return 0; +} + +/* + * zynq_nand_calculate_hwecc - Calculate Hardware ECC + * @mtd: Pointer to the mtd_info structure + * @data: Pointer to the page data + * @ecc_code: Pointer to the ECC buffer where ECC data needs to be stored + * + * This function retrieves the Hardware ECC data from the controller and returns + * ECC data back to the MTD subsystem. + * + * returns: 0 on success or error value on failure + */ +static int zynq_nand_calculate_hwecc(struct mtd_info *mtd, const u8 *data, + u8 *ecc_code) +{ + u32 ecc_value = 0; + u8 ecc_reg, ecc_byte; + u32 ecc_status; + + /* Wait till the ECC operation is complete */ + ecc_status = zynq_nand_waitfor_ecc_completion(); + if (ecc_status < 0) { + printf("%s: Timeout\n", __func__); + return ecc_status; + } + + for (ecc_reg = 0; ecc_reg < 4; ecc_reg++) { + /* Read ECC value for each block */ + ecc_value = readl(&zynq_nand_smc_base->eval0r + ecc_reg); + ecc_status = (ecc_value >> 24) & 0xFF; + /* ECC value valid */ + if (ecc_status & 0x40) { + for (ecc_byte = 0; ecc_byte < 3; ecc_byte++) { + /* Copy ECC bytes to MTD buffer */ + *ecc_code = ecc_value & 0xFF; + ecc_value = ecc_value >> 8; + ecc_code++; + } + } else { + debug("%s: ecc status failed\n", __func__); + } + } + return 0; +} + +/* + * onehot - onehot function + * @value: value to check for onehot + * + * This function checks whether a value is onehot or not. + * onehot is if and only if onebit is set. + * + */ +static int onehot(unsigned short value) +{ + return ((value & (value-1)) == 0); +} + +/* + * zynq_nand_correct_data - ECC correction function + * @mtd: Pointer to the mtd_info structure + * @buf: Pointer to the page data + * @read_ecc: Pointer to the ECC value read from spare data area + * @calc_ecc: Pointer to the calculated ECC value + * + * This function corrects the ECC single bit errors & detects 2-bit errors. + * + * returns: 0 if no ECC errors found + * 1 if single bit error found and corrected. + * -1 if multiple ECC errors found. + */ +static int zynq_nand_correct_data(struct mtd_info *mtd, unsigned char *buf, + unsigned char *read_ecc, unsigned char *calc_ecc) +{ + unsigned char bit_addr; + unsigned int byte_addr; + unsigned short ecc_odd, ecc_even; + unsigned short read_ecc_lower, read_ecc_upper; + unsigned short calc_ecc_lower, calc_ecc_upper; + + read_ecc_lower = (read_ecc[0] | (read_ecc[1] << 8)) & 0xfff; + read_ecc_upper = ((read_ecc[1] >> 4) | (read_ecc[2] << 4)) & 0xfff; + + calc_ecc_lower = (calc_ecc[0] | (calc_ecc[1] << 8)) & 0xfff; + calc_ecc_upper = ((calc_ecc[1] >> 4) | (calc_ecc[2] << 4)) & 0xfff; + + ecc_odd = read_ecc_lower ^ calc_ecc_lower; + ecc_even = read_ecc_upper ^ calc_ecc_upper; + + if ((ecc_odd == 0) && (ecc_even == 0)) + return 0; /* no error */ + else if (ecc_odd == (~ecc_even & 0xfff)) { + /* bits [11:3] of error code is byte offset */ + byte_addr = (ecc_odd >> 3) & 0x1ff; + /* bits [2:0] of error code is bit offset */ + bit_addr = ecc_odd & 0x7; + /* Toggling error bit */ + buf[byte_addr] ^= (1 << bit_addr); + return 1; + } else if (onehot(ecc_odd | ecc_even) == 1) { + return 1; /* one error in parity */ + } else { + return -1; /* Uncorrectable error */ + } +} + +/* + * zynq_nand_read_oob - [REPLACABLE] the most common OOB data read function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @page: page number to read + * @sndcmd: flag whether to issue read command or not + */ +static int zynq_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, + int page) +{ + unsigned long data_width = 4; + unsigned long data_phase_addr = 0; + u8 *p; + + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + + p = chip->oob_poi; + chip->read_buf(mtd, p, (mtd->oobsize - data_width)); + p += (mtd->oobsize - data_width); + + data_phase_addr = (unsigned long)chip->IO_ADDR_R; + data_phase_addr |= ZYNQ_NAND_CLEAR_CS; + chip->IO_ADDR_R = (void __iomem *)data_phase_addr; + chip->read_buf(mtd, p, data_width); + + return 0; +} + +/* + * zynq_nand_write_oob - [REPLACABLE] the most common OOB data write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @page: page number to write + */ +static int zynq_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, + int page) +{ + int status = 0; + const u8 *buf = chip->oob_poi; + unsigned long data_width = 4; + unsigned long data_phase_addr = 0; + + chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page); + + chip->write_buf(mtd, buf, (mtd->oobsize - data_width)); + buf += (mtd->oobsize - data_width); + + data_phase_addr = (unsigned long)chip->IO_ADDR_W; + data_phase_addr |= ZYNQ_NAND_CLEAR_CS; + data_phase_addr |= (1 << END_CMD_VALID_SHIFT); + chip->IO_ADDR_W = (void __iomem *)data_phase_addr; + chip->write_buf(mtd, buf, data_width); + + /* Send command to program the OOB data */ + chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); + status = chip->waitfunc(mtd, chip); + + return status & NAND_STATUS_FAIL ? -EIO : 0; +} + +/* + * zynq_nand_read_page_raw - [Intern] read raw page data without ecc + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + * @oob_required: must write chip->oob_poi to OOB + * @page: page number to read + */ +static int zynq_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, + u8 *buf, int oob_required, int page) +{ + unsigned long data_width = 4; + unsigned long data_phase_addr = 0; + u8 *p; + + chip->read_buf(mtd, buf, mtd->writesize); + + p = chip->oob_poi; + chip->read_buf(mtd, p, (mtd->oobsize - data_width)); + p += (mtd->oobsize - data_width); + + data_phase_addr = (unsigned long)chip->IO_ADDR_R; + data_phase_addr |= ZYNQ_NAND_CLEAR_CS; + chip->IO_ADDR_R = (void __iomem *)data_phase_addr; + + chip->read_buf(mtd, p, data_width); + return 0; +} + +static int zynq_nand_read_page_raw_nooob(struct mtd_info *mtd, + struct nand_chip *chip, u8 *buf, int oob_required, int page) +{ + chip->read_buf(mtd, buf, mtd->writesize); + return 0; +} + +static int zynq_nand_read_subpage_raw(struct mtd_info *mtd, - struct nand_chip *chip, u32 data_offs, - u32 readlen, u8 *buf) ++ struct nand_chip *chip, uint32_t offs, ++ uint32_t len, uint8_t *buf, int page) +{ - if (data_offs != 0) { - chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_offs, -1); - buf += data_offs; ++ if (offs != 0) { ++ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offs, -1); ++ buf += offs; + } + - chip->read_buf(mtd, buf, readlen); ++ chip->read_buf(mtd, buf, len); + return 0; +} + +/* + * zynq_nand_write_page_raw - [Intern] raw page write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB + */ +static int zynq_nand_write_page_raw(struct mtd_info *mtd, + struct nand_chip *chip, const u8 *buf, int oob_required) +{ + unsigned long data_width = 4; + unsigned long data_phase_addr = 0; + u8 *p; + + chip->write_buf(mtd, buf, mtd->writesize); + + p = chip->oob_poi; + chip->write_buf(mtd, p, (mtd->oobsize - data_width)); + p += (mtd->oobsize - data_width); + + data_phase_addr = (unsigned long)chip->IO_ADDR_W; + data_phase_addr |= ZYNQ_NAND_CLEAR_CS; + data_phase_addr |= (1 << END_CMD_VALID_SHIFT); + chip->IO_ADDR_W = (void __iomem *)data_phase_addr; + + chip->write_buf(mtd, p, data_width); + + return 0; +} + +/* + * nand_write_page_hwecc - Hardware ECC based page write function + * @mtd: Pointer to the mtd info structure + * @chip: Pointer to the NAND chip info structure + * @buf: Pointer to the data buffer + * @oob_required: must write chip->oob_poi to OOB + * + * This functions writes data and hardware generated ECC values in to the page. + */ +static int zynq_nand_write_page_hwecc(struct mtd_info *mtd, + struct nand_chip *chip, const u8 *buf, int oob_required) +{ + int i, eccsize = chip->ecc.size; + int eccsteps = chip->ecc.steps; + u8 *ecc_calc = chip->buffers->ecccalc; + const u8 *p = buf; + u32 *eccpos = chip->ecc.layout->eccpos; + unsigned long data_phase_addr = 0; + unsigned long data_width = 4; + u8 *oob_ptr; + + for (; (eccsteps - 1); eccsteps--) { + chip->write_buf(mtd, p, eccsize); + p += eccsize; + } + chip->write_buf(mtd, p, (eccsize - data_width)); + p += (eccsize - data_width); + + /* Set ECC Last bit to 1 */ + data_phase_addr = (unsigned long) chip->IO_ADDR_W; + data_phase_addr |= ZYNQ_NAND_ECC_LAST; + chip->IO_ADDR_W = (void __iomem *)data_phase_addr; + chip->write_buf(mtd, p, data_width); + + /* Wait for ECC to be calculated and read the error values */ + p = buf; + chip->ecc.calculate(mtd, p, &ecc_calc[0]); + + for (i = 0; i < chip->ecc.total; i++) + chip->oob_poi[eccpos[i]] = ~(ecc_calc[i]); + + /* Clear ECC last bit */ + data_phase_addr = (unsigned long)chip->IO_ADDR_W; + data_phase_addr &= ~ZYNQ_NAND_ECC_LAST; + chip->IO_ADDR_W = (void __iomem *)data_phase_addr; + + /* Write the spare area with ECC bytes */ + oob_ptr = chip->oob_poi; + chip->write_buf(mtd, oob_ptr, (mtd->oobsize - data_width)); + + data_phase_addr = (unsigned long)chip->IO_ADDR_W; + data_phase_addr |= ZYNQ_NAND_CLEAR_CS; + data_phase_addr |= (1 << END_CMD_VALID_SHIFT); + chip->IO_ADDR_W = (void __iomem *)data_phase_addr; + oob_ptr += (mtd->oobsize - data_width); + chip->write_buf(mtd, oob_ptr, data_width); + + return 0; +} + +/* + * zynq_nand_write_page_swecc - [REPLACABLE] software ecc based page + * write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB + */ +static int zynq_nand_write_page_swecc(struct mtd_info *mtd, + struct nand_chip *chip, const u8 *buf, int oob_required) +{ + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + u8 *ecc_calc = chip->buffers->ecccalc; + const u8 *p = buf; + u32 *eccpos = chip->ecc.layout->eccpos; + + /* Software ecc calculation */ + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) + chip->ecc.calculate(mtd, p, &ecc_calc[i]); + + for (i = 0; i < chip->ecc.total; i++) + chip->oob_poi[eccpos[i]] = ecc_calc[i]; + + return chip->ecc.write_page_raw(mtd, chip, buf, 1); +} + +/* + * nand_read_page_hwecc - Hardware ECC based page read function + * @mtd: Pointer to the mtd info structure + * @chip: Pointer to the NAND chip info structure + * @buf: Pointer to the buffer to store read data + * @oob_required: must write chip->oob_poi to OOB + * @page: page number to read + * + * This functions reads data and checks the data integrity by comparing hardware + * generated ECC values and read ECC values from spare area. + * + * returns: 0 always and updates ECC operation status in to MTD structure + */ +static int zynq_nand_read_page_hwecc(struct mtd_info *mtd, + struct nand_chip *chip, u8 *buf, int oob_required, int page) +{ + int i, stat, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + u8 *p = buf; + u8 *ecc_calc = chip->buffers->ecccalc; + u8 *ecc_code = chip->buffers->ecccode; + u32 *eccpos = chip->ecc.layout->eccpos; + unsigned long data_phase_addr = 0; + unsigned long data_width = 4; + u8 *oob_ptr; + + for (; (eccsteps - 1); eccsteps--) { + chip->read_buf(mtd, p, eccsize); + p += eccsize; + } + chip->read_buf(mtd, p, (eccsize - data_width)); + p += (eccsize - data_width); + + /* Set ECC Last bit to 1 */ + data_phase_addr = (unsigned long)chip->IO_ADDR_R; + data_phase_addr |= ZYNQ_NAND_ECC_LAST; + chip->IO_ADDR_R = (void __iomem *)data_phase_addr; + chip->read_buf(mtd, p, data_width); + + /* Read the calculated ECC value */ + p = buf; + chip->ecc.calculate(mtd, p, &ecc_calc[0]); + + /* Clear ECC last bit */ + data_phase_addr = (unsigned long)chip->IO_ADDR_R; + data_phase_addr &= ~ZYNQ_NAND_ECC_LAST; + chip->IO_ADDR_R = (void __iomem *)data_phase_addr; + + /* Read the stored ECC value */ + oob_ptr = chip->oob_poi; + chip->read_buf(mtd, oob_ptr, (mtd->oobsize - data_width)); + + /* de-assert chip select */ + data_phase_addr = (unsigned long)chip->IO_ADDR_R; + data_phase_addr |= ZYNQ_NAND_CLEAR_CS; + chip->IO_ADDR_R = (void __iomem *)data_phase_addr; + + oob_ptr += (mtd->oobsize - data_width); + chip->read_buf(mtd, oob_ptr, data_width); + + for (i = 0; i < chip->ecc.total; i++) + ecc_code[i] = ~(chip->oob_poi[eccpos[i]]); + + eccsteps = chip->ecc.steps; + p = buf; + + /* Check ECC error for all blocks and correct if it is correctable */ + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); + if (stat < 0) + mtd->ecc_stats.failed++; + else + mtd->ecc_stats.corrected += stat; + } + return 0; +} + +/* + * zynq_nand_read_page_swecc - [REPLACABLE] software ecc based page + * read function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + * @page: page number to read + */ +static int zynq_nand_read_page_swecc(struct mtd_info *mtd, + struct nand_chip *chip, u8 *buf, int oob_required, int page) +{ + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + u8 *p = buf; + u8 *ecc_calc = chip->buffers->ecccalc; + u8 *ecc_code = chip->buffers->ecccode; + u32 *eccpos = chip->ecc.layout->eccpos; + + chip->ecc.read_page_raw(mtd, chip, buf, 1, page); + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) + chip->ecc.calculate(mtd, p, &ecc_calc[i]); + + for (i = 0; i < chip->ecc.total; i++) + ecc_code[i] = chip->oob_poi[eccpos[i]]; + + eccsteps = chip->ecc.steps; + p = buf; + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + int stat; + + stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); + if (stat < 0) + mtd->ecc_stats.failed++; + else + mtd->ecc_stats.corrected += stat; + } + return 0; +} + +/* + * zynq_nand_select_chip - Select the flash device + * @mtd: Pointer to the mtd_info structure + * @chip: Chip number to be selected + * + * This function is empty as the NAND controller handles chip select line + * internally based on the chip address passed in command and data phase. + */ +static void zynq_nand_select_chip(struct mtd_info *mtd, int chip) +{ + return; +} + +/* + * zynq_nand_cmd_function - Send command to NAND device + * @mtd: Pointer to the mtd_info structure + * @command: The command to be sent to the flash device + * @column: The column address for this command, -1 if none + * @page_addr: The page address for this command, -1 if none + */ +static void zynq_nand_cmd_function(struct mtd_info *mtd, unsigned int command, + int column, int page_addr) +{ + struct nand_chip *chip = mtd->priv; + const struct zynq_nand_command_format *curr_cmd = NULL; + struct zynq_nand_info *xnand; + void *cmd_addr; + unsigned long cmd_data = 0; + unsigned long cmd_phase_addr = 0; + unsigned long data_phase_addr = 0; + unsigned long end_cmd = 0; + unsigned long end_cmd_valid = 0; + unsigned long i; + + xnand = (struct zynq_nand_info *)chip->priv; + if (xnand->end_cmd_pending) { + /* Check for end command if this command request is same as the + * pending command then return + */ + if (xnand->end_cmd == command) { + xnand->end_cmd = 0; + xnand->end_cmd_pending = 0; + return; + } + } + + /* Emulate NAND_CMD_READOOB for large page device */ + if ((mtd->writesize > ZYNQ_NAND_ECC_SIZE) && + (command == NAND_CMD_READOOB)) { + column += mtd->writesize; + command = NAND_CMD_READ0; + } + + /* Get the command format */ + for (i = 0; (zynq_nand_commands[i].start_cmd != NAND_CMD_NONE || + zynq_nand_commands[i].end_cmd != NAND_CMD_NONE); i++) { + if (command == zynq_nand_commands[i].start_cmd) + curr_cmd = &zynq_nand_commands[i]; + } + if (curr_cmd == NULL) + return; + + /* Clear interrupt */ + writel((1 << 4), &zynq_nand_smc_base->cfr); + + /* Get the command phase address */ + if (curr_cmd->end_cmd_valid == ZYNQ_NAND_CMD_PHASE) + end_cmd_valid = 1; + + if (curr_cmd->end_cmd == NAND_CMD_NONE) + end_cmd = 0x0; + else + end_cmd = curr_cmd->end_cmd; + + cmd_phase_addr = (unsigned long)xnand->nand_base | + (curr_cmd->addr_cycles << ADDR_CYCLES_SHIFT) | + (end_cmd_valid << END_CMD_VALID_SHIFT) | + (COMMAND_PHASE) | + (end_cmd << END_CMD_SHIFT) | + (curr_cmd->start_cmd << START_CMD_SHIFT); + + cmd_addr = (void __iomem *)cmd_phase_addr; + + /* Get the data phase address */ + end_cmd_valid = 0; + + data_phase_addr = (unsigned long)xnand->nand_base | + (0x0 << CLEAR_CS_SHIFT) | + (end_cmd_valid << END_CMD_VALID_SHIFT) | + (DATA_PHASE) | + (end_cmd << END_CMD_SHIFT) | + (0x0 << ECC_LAST_SHIFT); + + chip->IO_ADDR_R = (void __iomem *)data_phase_addr; + chip->IO_ADDR_W = chip->IO_ADDR_R; + + /* Command phase AXI Read & Write */ + if (column != -1 && page_addr != -1) { + /* Adjust columns for 16 bit bus width */ + if (chip->options & NAND_BUSWIDTH_16) + column >>= 1; + cmd_data = column; + if (mtd->writesize > ZYNQ_NAND_ECC_SIZE) { + cmd_data |= page_addr << 16; + /* Another address cycle for devices > 128MiB */ + if (chip->chipsize > (128 << 20)) { + writel(cmd_data, cmd_addr); + cmd_data = (page_addr >> 16); + } + } else { + cmd_data |= page_addr << 8; + } + } + /* Erase */ + else if (page_addr != -1) + cmd_data = page_addr; + /* Change read/write column, read id etc */ + else if (column != -1) { + /* Adjust columns for 16 bit bus width */ + if ((chip->options & NAND_BUSWIDTH_16) && + ((command == NAND_CMD_READ0) || + (command == NAND_CMD_SEQIN) || + (command == NAND_CMD_RNDOUT) || + (command == NAND_CMD_RNDIN))) + column >>= 1; + cmd_data = column; + } else + ; + + writel(cmd_data, cmd_addr); + + if (curr_cmd->end_cmd_valid) { + xnand->end_cmd = curr_cmd->end_cmd; + xnand->end_cmd_pending = 1; + } + + ndelay(100); + + if ((command == NAND_CMD_READ0) || + (command == NAND_CMD_RESET) || + (command == NAND_CMD_PARAM) || + (command == NAND_CMD_GET_FEATURES)) { + while (!chip->dev_ready(mtd)) + ; + return; + } +} + +/* + * zynq_nand_read_buf - read chip data into buffer + * @mtd: MTD device structure + * @buf: buffer to store date + * @len: number of bytes to read + */ +static void zynq_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len) +{ + struct nand_chip *chip = mtd->priv; + const u32 *nand = chip->IO_ADDR_R; + + /* Make sure that buf is 32 bit aligned */ + if (((int)buf & 0x3) != 0) { + if (((int)buf & 0x1) != 0) { + if (len) { + *buf = readb(nand); + buf += 1; + len--; + } + } + + if (((int)buf & 0x3) != 0) { + if (len >= 2) { + *(u16 *)buf = readw(nand); + buf += 2; + len -= 2; + } + } + } + + /* copy aligned data */ + while (len >= 4) { + *(u32 *)buf = readl(nand); + buf += 4; + len -= 4; + } + + /* mop up any remaining bytes */ + if (len) { + if (len >= 2) { + *(u16 *)buf = readw(nand); + buf += 2; + len -= 2; + } + + if (len) + *buf = readb(nand); + } +} + +/* + * zynq_nand_write_buf - write buffer to chip + * @mtd: MTD device structure + * @buf: data buffer + * @len: number of bytes to write + */ +static void zynq_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) +{ + struct nand_chip *chip = mtd->priv; + const u32 *nand = chip->IO_ADDR_W; + + /* Make sure that buf is 32 bit aligned */ + if (((int)buf & 0x3) != 0) { + if (((int)buf & 0x1) != 0) { + if (len) { + writeb(*buf, nand); + buf += 1; + len--; + } + } + + if (((int)buf & 0x3) != 0) { + if (len >= 2) { + writew(*(u16 *)buf, nand); + buf += 2; + len -= 2; + } + } + } + + /* copy aligned data */ + while (len >= 4) { + writel(*(u32 *)buf, nand); + buf += 4; + len -= 4; + } + + /* mop up any remaining bytes */ + if (len) { + if (len >= 2) { + writew(*(u16 *)buf, nand); + buf += 2; + len -= 2; + } + + if (len) + writeb(*buf, nand); + } +} + +/* + * zynq_nand_device_ready - Check device ready/busy line + * @mtd: Pointer to the mtd_info structure + * + * returns: 0 on busy or 1 on ready state + */ +static int zynq_nand_device_ready(struct mtd_info *mtd) +{ + /* Check the raw_int_status1 bit */ + if ((readl(&zynq_nand_smc_base->csr)) & 0x40) { + /* Clear the interrupt condition */ + writel((1 << 4), &zynq_nand_smc_base->cfr); + return 1; + } + return 0; +} + +/* + * zynq_nand_check_is_16bit_bw_flash - checking for 16 or 8 bit buswidth nand + * + * This function will check nand buswidth whether it supports 16 or 8 bit + * based on the MIO configuration done by FSBL. + * + * User needs to correctly configure the MIO's based on the + * buswidth supported by the nand flash which is present on the board. + * + * function will return -1, if there is no MIO configuration for + * nand flash. + */ +static int zynq_nand_check_is_16bit_bw_flash(void) +{ + int is_16bit_bw = NAND_BW_UNKNOWN; + int mio_num_8bit = 0, mio_num_16bit = 0; + + mio_num_8bit = zynq_slcr_get_mio_pin_status("nand8"); + if (mio_num_8bit == ZYNQ_NAND_MIO_NUM_NAND_8BIT) + is_16bit_bw = NAND_BW_8BIT; + + mio_num_16bit = zynq_slcr_get_mio_pin_status("nand16"); + if ((mio_num_8bit == ZYNQ_NAND_MIO_NUM_NAND_8BIT) && + (mio_num_16bit == ZYNQ_NAND_MIO_NUM_NAND_16BIT)) + is_16bit_bw = NAND_BW_16BIT; + + return is_16bit_bw; +} + +static int zynq_nand_init(struct nand_chip *nand_chip, int devnum) +{ + struct zynq_nand_info *xnand; + struct mtd_info *mtd; + unsigned long ecc_page_size; + int err = -1; + u8 maf_id, dev_id, i; + u8 get_feature[4]; + u8 set_feature[4] = {0x08, 0x00, 0x00, 0x00}; + unsigned long ecc_cfg; + int ondie_ecc_enabled = 0; + int is_16bit_bw; + + xnand = calloc(1, sizeof(struct zynq_nand_info)); + if (!xnand) { + printf("%s: failed to allocate\n", __func__); + goto free; + } + + xnand->nand_base = (void *)ZYNQ_NAND_BASEADDR; + mtd = &nand_info[0]; + + nand_chip->priv = xnand; + mtd->priv = nand_chip; + + /* Set address of NAND IO lines */ + nand_chip->IO_ADDR_R = xnand->nand_base; + nand_chip->IO_ADDR_W = xnand->nand_base; + + /* Set the driver entry points for MTD */ + nand_chip->cmdfunc = zynq_nand_cmd_function; + nand_chip->dev_ready = zynq_nand_device_ready; + nand_chip->select_chip = zynq_nand_select_chip; + + /* If we don't set this delay driver sets 20us by default */ + nand_chip->chip_delay = 30; + + /* Buffer read/write routines */ + nand_chip->read_buf = zynq_nand_read_buf; + nand_chip->write_buf = zynq_nand_write_buf; + + /* Check the NAND buswidth */ + /* FIXME this will be changed by using NAND_BUSWIDTH_AUTO */ + is_16bit_bw = zynq_nand_check_is_16bit_bw_flash(); + if (is_16bit_bw == NAND_BW_UNKNOWN) { + printf("%s: Unable detect NAND based on MIO settings\n", + __func__); + goto free; + } else if (is_16bit_bw == NAND_BW_16BIT) { + nand_chip->options = NAND_BUSWIDTH_16; + } + nand_chip->bbt_options = NAND_BBT_USE_FLASH; + + /* Initialize the NAND flash interface on NAND controller */ + if (zynq_nand_init_nand_flash(nand_chip->options) < 0) { + printf("%s: nand flash init failed\n", __func__); + goto free; + } + + /* first scan to find the device and get the page size */ + if (nand_scan_ident(mtd, 1, NULL)) { + printf("%s: nand_scan_ident failed\n", __func__); + goto fail; + } + + /* Send the command for reading device ID */ + nand_chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); + nand_chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); + + /* Read manufacturer and device IDs */ + maf_id = nand_chip->read_byte(mtd); + dev_id = nand_chip->read_byte(mtd); + + if ((maf_id == 0x2c) && ((dev_id == 0xf1) || + (dev_id == 0xa1) || (dev_id == 0xb1) || + (dev_id == 0xaa) || (dev_id == 0xba) || + (dev_id == 0xda) || (dev_id == 0xca) || + (dev_id == 0xac) || (dev_id == 0xbc) || + (dev_id == 0xdc) || (dev_id == 0xcc) || + (dev_id == 0xa3) || (dev_id == 0xb3) || + (dev_id == 0xd3) || (dev_id == 0xc3))) { + nand_chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, + ONDIE_ECC_FEATURE_ADDR, -1); + + for (i = 0; i < 4; i++) + writeb(set_feature[i], nand_chip->IO_ADDR_W); + + /* wait for 1us after writing data with SET_FEATURES command */ + ndelay(1000); + + nand_chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, + ONDIE_ECC_FEATURE_ADDR, -1); + nand_chip->read_buf(mtd, get_feature, 4); + + if (get_feature[0] & 0x08) { + debug("%s: OnDie ECC flash\n", __func__); + ondie_ecc_enabled = 1; + } else { + printf("%s: Unable to detect OnDie ECC\n", __func__); + } + } + + if (ondie_ecc_enabled) { + /* bypass the controller ECC block */ + ecc_cfg = readl(&zynq_nand_smc_base->emcr); + ecc_cfg &= ~0xc; + writel(ecc_cfg, &zynq_nand_smc_base->emcr); + + /* The software ECC routines won't work + * with the SMC controller + */ + nand_chip->ecc.mode = NAND_ECC_HW; + nand_chip->ecc.strength = 1; + nand_chip->ecc.read_page = zynq_nand_read_page_raw_nooob; + nand_chip->ecc.read_subpage = zynq_nand_read_subpage_raw; + nand_chip->ecc.write_page = zynq_nand_write_page_raw; + nand_chip->ecc.read_page_raw = zynq_nand_read_page_raw; + nand_chip->ecc.write_page_raw = zynq_nand_write_page_raw; + nand_chip->ecc.read_oob = zynq_nand_read_oob; + nand_chip->ecc.write_oob = zynq_nand_write_oob; + nand_chip->ecc.size = mtd->writesize; + nand_chip->ecc.bytes = 0; + + /* NAND with on-die ECC supports subpage reads */ + nand_chip->options |= NAND_SUBPAGE_READ; + + /* On-Die ECC spare bytes offset 8 is used for ECC codes */ + if (ondie_ecc_enabled) { + nand_chip->ecc.layout = &ondie_nand_oob_64; + /* Use the BBT pattern descriptors */ + nand_chip->bbt_td = &bbt_main_descr; + nand_chip->bbt_md = &bbt_mirror_descr; + } + } else { + /* Hardware ECC generates 3 bytes ECC code for each 512 bytes */ + nand_chip->ecc.mode = NAND_ECC_HW; + nand_chip->ecc.strength = 1; + nand_chip->ecc.size = ZYNQ_NAND_ECC_SIZE; + nand_chip->ecc.bytes = 3; + nand_chip->ecc.calculate = zynq_nand_calculate_hwecc; + nand_chip->ecc.correct = zynq_nand_correct_data; + nand_chip->ecc.hwctl = NULL; + nand_chip->ecc.read_page = zynq_nand_read_page_hwecc; + nand_chip->ecc.write_page = zynq_nand_write_page_hwecc; + nand_chip->ecc.read_page_raw = zynq_nand_read_page_raw; + nand_chip->ecc.write_page_raw = zynq_nand_write_page_raw; + nand_chip->ecc.read_oob = zynq_nand_read_oob; + nand_chip->ecc.write_oob = zynq_nand_write_oob; + + switch (mtd->writesize) { + case 512: + ecc_page_size = 0x1; + /* Set the ECC memory config register */ + writel((ZYNQ_NAND_ECC_CONFIG | ecc_page_size), + &zynq_nand_smc_base->emcr); + break; + case 1024: + ecc_page_size = 0x2; + /* Set the ECC memory config register */ + writel((ZYNQ_NAND_ECC_CONFIG | ecc_page_size), + &zynq_nand_smc_base->emcr); + break; + case 2048: + ecc_page_size = 0x3; + /* Set the ECC memory config register */ + writel((ZYNQ_NAND_ECC_CONFIG | ecc_page_size), + &zynq_nand_smc_base->emcr); + break; + default: + /* The software ECC routines won't work with + * the SMC controller + */ + nand_chip->ecc.mode = NAND_ECC_HW; + nand_chip->ecc.calculate = nand_calculate_ecc; + nand_chip->ecc.correct = nand_correct_data; + nand_chip->ecc.read_page = zynq_nand_read_page_swecc; + /* nand_chip->ecc.read_subpage = nand_read_subpage; */ + nand_chip->ecc.write_page = zynq_nand_write_page_swecc; + nand_chip->ecc.read_page_raw = zynq_nand_read_page_raw; + nand_chip->ecc.write_page_raw = + zynq_nand_write_page_raw; + nand_chip->ecc.read_oob = zynq_nand_read_oob; + nand_chip->ecc.write_oob = zynq_nand_write_oob; + nand_chip->ecc.size = 256; + nand_chip->ecc.bytes = 3; + break; + } + + if (mtd->oobsize == 16) + nand_chip->ecc.layout = &nand_oob_16; + else if (mtd->oobsize == 64) + nand_chip->ecc.layout = &nand_oob_64; + else + ; + } + + /* second phase scan */ + if (nand_scan_tail(mtd)) { + printf("%s: nand_scan_tailfailed\n", __func__); + goto fail; + } + + if (nand_register(devnum)) + goto fail; + + return 0; +fail: - nand_release(mtd); +free: + kfree(xnand); + return err; +} + +static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE]; + +void board_nand_init(void) +{ + struct nand_chip *nand = &nand_chip[0]; + + if (zynq_nand_init(nand, 0)) + puts("ZYNQ NAND init failed\n"); +} diff --cc drivers/spi/zynq_qspi.c index 215b26f6c97,00000000000..d52abcc9a67 mode 100644,000000..100644 --- a/drivers/spi/zynq_qspi.c +++ b/drivers/spi/zynq_qspi.c @@@ -1,895 -1,0 +1,896 @@@ +/* + * (C) Copyright 2011 - 2013 Xilinx + * + * Xilinx Zynq Quad-SPI(QSPI) controller driver (master mode only) + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include ++#include "../mtd/spi/sf_internal.h" + +/* QSPI Transmit Data Register */ +#define ZYNQ_QSPI_TXD_00_00_OFFSET 0x1C /* Transmit 4-byte inst, WO */ +#define ZYNQ_QSPI_TXD_00_01_OFFSET 0x80 /* Transmit 1-byte inst, WO */ +#define ZYNQ_QSPI_TXD_00_10_OFFSET 0x84 /* Transmit 2-byte inst, WO */ +#define ZYNQ_QSPI_TXD_00_11_OFFSET 0x88 /* Transmit 3-byte inst, WO */ + +/* + * QSPI Configuration Register bit Masks + * + * This register contains various control bits that effect the operation + * of the QSPI controller + */ +#define ZYNQ_QSPI_CONFIG_IFMODE_MASK (1 << 31) /* Flash intrface mode*/ +#define ZYNQ_QSPI_CONFIG_MSA_MASK (1 << 15) /* Manual start enb */ +#define ZYNQ_QSPI_CONFIG_MCS_MASK (1 << 14) /* Manual chip select */ +#define ZYNQ_QSPI_CONFIG_PCS_MASK (1 << 10) /* Peri chip select */ +#define ZYNQ_QSPI_CONFIG_FW_MASK (0x3 << 6) /* FIFO width */ +#define ZYNQ_QSPI_CONFIG_MSTREN_MASK (1 << 0) /* Mode select */ +#define ZYNQ_QSPI_CONFIG_MANSRT_MASK 0x00010000 /* Manual TX Start */ +#define ZYNQ_QSPI_CONFIG_CPHA_MASK 0x00000004 /* Clock Phase Control */ +#define ZYNQ_QSPI_CONFIG_CPOL_MASK 0x00000002 /* Clock Polarity Control */ +#define ZYNQ_QSPI_CONFIG_SSCTRL_MASK 0x00003C00 /* Slave Select Mask */ +/* + * QSPI Interrupt Registers bit Masks + * + * All the four interrupt registers (Status/Mask/Enable/Disable) have the same + * bit definitions. + */ +#define ZYNQ_QSPI_IXR_TXNFULL_MASK 0x00000004 /* QSPI TX FIFO Overflow */ +#define ZYNQ_QSPI_IXR_TXFULL_MASK 0x00000008 /* QSPI TX FIFO is full */ +#define ZYNQ_QSPI_IXR_RXNEMTY_MASK 0x00000010 /* QSPI RX FIFO Not Empty */ +#define ZYNQ_QSPI_IXR_ALL_MASK (ZYNQ_QSPI_IXR_TXNFULL_MASK | \ + ZYNQ_QSPI_IXR_RXNEMTY_MASK) + +/* + * QSPI Enable Register bit Masks + * + * This register is used to enable or disable the QSPI controller + */ +#define ZYNQ_QSPI_ENABLE_ENABLE_MASK 0x00000001 /* QSPI Enable Bit Mask */ + +/* + * QSPI Linear Configuration Register + * + * It is named Linear Configuration but it controls other modes when not in + * linear mode also. + */ +#define ZYNQ_QSPI_LCFG_TWO_MEM_MASK 0x40000000 /* QSPI Enable Bit Mask */ +#define ZYNQ_QSPI_LCFG_SEP_BUS_MASK 0x20000000 /* QSPI Enable Bit Mask */ +#define ZYNQ_QSPI_LCFG_U_PAGE 0x10000000 /* QSPI Upper memory set */ + +#define ZYNQ_QSPI_LCFG_DUMMY_SHIFT 8 + +#define ZYNQ_QSPI_FR_QOUT_CODE 0x6B /* read instruction code */ +#define ZYNQ_QSPI_FR_DUALIO_CODE 0xBB + +/* + * The modebits configurable by the driver to make the SPI support different + * data formats + */ +#define MODEBITS (SPI_CPOL | SPI_CPHA) + +/* Definitions for the status of queue */ +#define ZYNQ_QSPI_QUEUE_STOPPED 0 +#define ZYNQ_QSPI_QUEUE_RUNNING 1 +#define ZYNQ_QSPI_RXFIFO_THRESHOLD 32 +#define ZYNQ_QSPI_FIFO_DEPTH 63 + +/* QSPI MIO's count for different connection topologies */ +#define ZYNQ_QSPI_MIO_NUM_QSPI0 6 +#define ZYNQ_QSPI_MIO_NUM_QSPI1 5 +#define ZYNQ_QSPI_MIO_NUM_QSPI1_CS 1 + +/* QSPI MIO's count for different connection topologies */ +#define ZYNQ_QSPI_MIO_NUM_QSPI0_DIO 4 +#define ZYNQ_QSPI_MIO_NUM_QSPI1_DIO 3 +#define ZYNQ_QSPI_MIO_NUM_QSPI1_CS_DIO 1 + +/* QSPI register offsets */ +struct zynq_qspi_regs { + u32 confr; /* 0x00 */ + u32 isr; /* 0x04 */ + u32 ier; /* 0x08 */ + u32 idisr; /* 0x0C */ + u32 imaskr; /* 0x10 */ + u32 enbr; /* 0x14 */ + u32 dr; /* 0x18 */ + u32 txd0r; /* 0x1C */ + u32 drxr; /* 0x20 */ + u32 sicr; /* 0x24 */ + u32 txftr; /* 0x28 */ + u32 rxftr; /* 0x2C */ + u32 gpior; /* 0x30 */ + u32 reserved0[19]; + u32 txd1r; /* 0x80 */ + u32 txd2r; /* 0x84 */ + u32 txd3r; /* 0x88 */ + u32 reserved1[5]; + u32 lcr; /* 0xA0 */ + u32 reserved2[22]; + u32 midr; /* 0xFC */ +}; + +#define zynq_qspi_base ((struct zynq_qspi_regs *)ZYNQ_QSPI_BASEADDR) + +struct zynq_qspi { + u32 input_clk_hz; + u32 speed_hz; + const void *txbuf; + void *rxbuf; + int bytes_to_transfer; + int bytes_to_receive; + unsigned int is_inst; + unsigned int is_dual; + unsigned int is_dio; + unsigned int u_page; +}; + +struct spi_device { + struct zynq_qspi master; + u32 max_speed_hz; + u8 chip_select; + u8 mode; + u8 bits_per_word; +}; + +struct spi_transfer { + const void *tx_buf; + void *rx_buf; + unsigned len; + unsigned cs_change:1; + u8 bits_per_word; + u16 delay_usecs; + u32 speed_hz; +}; + +struct zynq_qspi_slave { + struct spi_slave slave; + struct spi_device qspi; +}; +#define to_zynq_qspi_slave(s) container_of(s, struct zynq_qspi_slave, slave) + +/* + * zynq_qspi_init_hw - Initialize the hardware + * @is_dual: Indicates whether dual memories are used + * @cs: Indicates which chip select is used in dual stacked + * + * The default settings of the QSPI controller's configurable parameters on + * reset are + * - Master mode + * - Baud rate divisor is set to 2 + * - Threshold value for TX FIFO not full interrupt is set to 1 + * - Flash memory interface mode enabled + * - Size of the word to be transferred as 8 bit + * This function performs the following actions + * - Disable and clear all the interrupts + * - Enable manual slave select + * - Enable manual start + * - Deselect all the chip select lines + * - Set the size of the word to be transferred as 32 bit + * - Set the little endian mode of TX FIFO and + * - Enable the QSPI controller + */ +static void zynq_qspi_init_hw(int is_dual, int is_dio, unsigned int cs) +{ + u32 config_reg; + + writel(~ZYNQ_QSPI_ENABLE_ENABLE_MASK, &zynq_qspi_base->enbr); + writel(0x7F, &zynq_qspi_base->idisr); + + /* Disable linear mode as the boot loader may have used it */ + writel(0x0, &zynq_qspi_base->lcr); + + /* Clear the TX and RX threshold reg */ + writel(0x1, &zynq_qspi_base->txftr); + writel(ZYNQ_QSPI_RXFIFO_THRESHOLD, &zynq_qspi_base->rxftr); + + /* Clear the RX FIFO */ + while (readl(&zynq_qspi_base->isr) & ZYNQ_QSPI_IXR_RXNEMTY_MASK) + readl(&zynq_qspi_base->drxr); + + writel(0x7F, &zynq_qspi_base->isr); + config_reg = readl(&zynq_qspi_base->confr); + config_reg |= ZYNQ_QSPI_CONFIG_IFMODE_MASK | + ZYNQ_QSPI_CONFIG_MCS_MASK | ZYNQ_QSPI_CONFIG_PCS_MASK | + ZYNQ_QSPI_CONFIG_FW_MASK | ZYNQ_QSPI_CONFIG_MSTREN_MASK; + if (is_dual == SF_DUAL_STACKED_FLASH) + config_reg |= 0x10; + writel(config_reg, &zynq_qspi_base->confr); + + if (is_dual == SF_DUAL_PARALLEL_FLASH) { + if (is_dio == SF_DUALIO_FLASH) + /* Enable two memories on seperate buses */ + writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | + ZYNQ_QSPI_LCFG_SEP_BUS_MASK | + (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | + ZYNQ_QSPI_FR_DUALIO_CODE), + &zynq_qspi_base->lcr); + else + /* Enable two memories on seperate buses */ + writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | + ZYNQ_QSPI_LCFG_SEP_BUS_MASK | + (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | + ZYNQ_QSPI_FR_QOUT_CODE), + &zynq_qspi_base->lcr); + } else if (is_dual == SF_DUAL_STACKED_FLASH) { + if (is_dio == SF_DUALIO_FLASH) + /* Configure two memories on shared bus + * by enabling lower mem */ + writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | + (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | + ZYNQ_QSPI_FR_DUALIO_CODE), + &zynq_qspi_base->lcr); + else + /* Configure two memories on shared bus + * by enabling lower mem */ + writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | + (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | + ZYNQ_QSPI_FR_QOUT_CODE), + &zynq_qspi_base->lcr); + } + writel(ZYNQ_QSPI_ENABLE_ENABLE_MASK, &zynq_qspi_base->enbr); +} + +/* + * zynq_qspi_copy_read_data - Copy data to RX buffer + * @zqspi: Pointer to the zynq_qspi structure + * @data: The 32 bit variable where data is stored + * @size: Number of bytes to be copied from data to RX buffer + */ +static void zynq_qspi_copy_read_data(struct zynq_qspi *zqspi, u32 data, u8 size) +{ + u8 byte3; + + debug("%s: data 0x%04x rxbuf addr: 0x%08x size %d\n", __func__ , + data, (unsigned)(zqspi->rxbuf), size); + + if (zqspi->rxbuf) { + switch (size) { + case 1: + *((u8 *)zqspi->rxbuf) = data; + zqspi->rxbuf += 1; + break; + case 2: + *((u16 *)zqspi->rxbuf) = data; + zqspi->rxbuf += 2; + break; + case 3: + *((u16 *)zqspi->rxbuf) = data; + zqspi->rxbuf += 2; + byte3 = (u8)(data >> 16); + *((u8 *)zqspi->rxbuf) = byte3; + zqspi->rxbuf += 1; + break; + case 4: + /* Can not assume word aligned buffer */ + memcpy(zqspi->rxbuf, &data, size); + zqspi->rxbuf += 4; + break; + default: + /* This will never execute */ + break; + } + } + zqspi->bytes_to_receive -= size; + if (zqspi->bytes_to_receive < 0) + zqspi->bytes_to_receive = 0; +} + +/* + * zynq_qspi_copy_write_data - Copy data from TX buffer + * @zqspi: Pointer to the zynq_qspi structure + * @data: Pointer to the 32 bit variable where data is to be copied + * @size: Number of bytes to be copied from TX buffer to data + */ +static void zynq_qspi_copy_write_data(struct zynq_qspi *zqspi, + u32 *data, u8 size) +{ + if (zqspi->txbuf) { + switch (size) { + case 1: + *data = *((u8 *)zqspi->txbuf); + zqspi->txbuf += 1; + *data |= 0xFFFFFF00; + break; + case 2: + *data = *((u16 *)zqspi->txbuf); + zqspi->txbuf += 2; + *data |= 0xFFFF0000; + break; + case 3: + *data = *((u16 *)zqspi->txbuf); + zqspi->txbuf += 2; + *data |= (*((u8 *)zqspi->txbuf) << 16); + zqspi->txbuf += 1; + *data |= 0xFF000000; + break; + case 4: + /* Can not assume word aligned buffer */ + memcpy(data, zqspi->txbuf, size); + zqspi->txbuf += 4; + break; + default: + /* This will never execute */ + break; + } + } else { + *data = 0; + } + + debug("%s: data 0x%08x txbuf addr: 0x%08x size %d\n", __func__, + *data, (u32)zqspi->txbuf, size); + + zqspi->bytes_to_transfer -= size; + if (zqspi->bytes_to_transfer < 0) + zqspi->bytes_to_transfer = 0; +} + +/* + * zynq_qspi_chipselect - Select or deselect the chip select line + * @qspi: Pointer to the spi_device structure + * @is_on: Select(1) or deselect (0) the chip select line + */ +static void zynq_qspi_chipselect(struct spi_device *qspi, int is_on) +{ + u32 config_reg; + + debug("%s: is_on: %d\n", __func__, is_on); + + config_reg = readl(&zynq_qspi_base->confr); + + if (is_on) { + /* Select the slave */ + config_reg &= ~ZYNQ_QSPI_CONFIG_SSCTRL_MASK; + config_reg |= (((~(0x0001 << qspi->chip_select)) << 10) & + ZYNQ_QSPI_CONFIG_SSCTRL_MASK); + } else + /* Deselect the slave */ + config_reg |= ZYNQ_QSPI_CONFIG_SSCTRL_MASK; + + writel(config_reg, &zynq_qspi_base->confr); +} + +/* + * zynq_qspi_setup_transfer - Configure QSPI controller for specified transfer + * @qspi: Pointer to the spi_device structure + * @transfer: Pointer to the spi_transfer structure which provides information + * about next transfer setup parameters + * + * Sets the operational mode of QSPI controller for the next QSPI transfer and + * sets the requested clock frequency. + * + * returns: 0 on success and -1 on invalid input parameter + * + * Note: If the requested frequency is not an exact match with what can be + * obtained using the prescalar value, the driver sets the clock frequency which + * is lower than the requested frequency (maximum lower) for the transfer. If + * the requested frequency is higher or lower than that is supported by the QSPI + * controller the driver will set the highest or lowest frequency supported by + * controller. + */ +static int zynq_qspi_setup_transfer(struct spi_device *qspi, + struct spi_transfer *transfer) +{ + struct zynq_qspi *zqspi = &qspi->master; + u8 bits_per_word; + u32 config_reg; + u32 req_hz; + u32 baud_rate_val = 0; + + debug("%s: qspi: 0x%08x transfer: 0x%08x\n", __func__, + (u32)qspi, (u32)transfer); + + bits_per_word = (transfer) ? + transfer->bits_per_word : qspi->bits_per_word; + req_hz = (transfer) ? transfer->speed_hz : qspi->max_speed_hz; + + if (qspi->mode & ~MODEBITS) { + printf("%s: Unsupported mode bits %x\n", + __func__, qspi->mode & ~MODEBITS); + return -1; + } + + if (bits_per_word != 32) + bits_per_word = 32; + + config_reg = readl(&zynq_qspi_base->confr); + + /* Set the QSPI clock phase and clock polarity */ + config_reg &= (~ZYNQ_QSPI_CONFIG_CPHA_MASK) & + (~ZYNQ_QSPI_CONFIG_CPOL_MASK); + if (qspi->mode & SPI_CPHA) + config_reg |= ZYNQ_QSPI_CONFIG_CPHA_MASK; + if (qspi->mode & SPI_CPOL) + config_reg |= ZYNQ_QSPI_CONFIG_CPOL_MASK; + + /* Set the clock frequency */ + if (zqspi->speed_hz != req_hz) { + baud_rate_val = 0; + while ((baud_rate_val < 7) && + (zqspi->input_clk_hz / (2 << baud_rate_val)) > req_hz) { + baud_rate_val++; + } + config_reg &= 0xFFFFFFC7; + config_reg |= (baud_rate_val << 3); + zqspi->speed_hz = req_hz; + } + + writel(config_reg, &zynq_qspi_base->confr); + + debug("%s: mode %d, %u bits/w, %u clock speed\n", __func__, + qspi->mode & MODEBITS, qspi->bits_per_word, zqspi->speed_hz); + + return 0; +} + +/* + * zynq_qspi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible + * @zqspi: Pointer to the zynq_qspi structure + */ +static void zynq_qspi_fill_tx_fifo(struct zynq_qspi *zqspi, u32 size) +{ + u32 data = 0; + u32 fifocount = 0; + unsigned len, offset; + static const unsigned offsets[4] = { + ZYNQ_QSPI_TXD_00_00_OFFSET, ZYNQ_QSPI_TXD_00_01_OFFSET, + ZYNQ_QSPI_TXD_00_10_OFFSET, ZYNQ_QSPI_TXD_00_11_OFFSET }; + + while ((fifocount < size) && + (zqspi->bytes_to_transfer > 0)) { + if (zqspi->bytes_to_transfer >= 4) { + if (zqspi->txbuf) { + memcpy(&data, zqspi->txbuf, 4); + zqspi->txbuf += 4; + } else { + data = 0; + } + writel(data, &zynq_qspi_base->txd0r); + zqspi->bytes_to_transfer -= 4; + fifocount++; + } else { + /* Write TXD1, TXD2, TXD3 only if TxFIFO is empty. */ + if (!(readl(&zynq_qspi_base->isr) + & ZYNQ_QSPI_IXR_TXNFULL_MASK) && + !zqspi->rxbuf) + return; + len = zqspi->bytes_to_transfer; + zynq_qspi_copy_write_data(zqspi, &data, len); + offset = (zqspi->rxbuf) ? offsets[0] : offsets[len]; + writel(data, &zynq_qspi_base->confr + (offset / 4)); + } + } +} + +/* + * zynq_qspi_irq_poll - Interrupt service routine of the QSPI controller + * @zqspi: Pointer to the zynq_qspi structure + * + * This function handles TX empty and Mode Fault interrupts only. + * On TX empty interrupt this function reads the received data from RX FIFO and + * fills the TX FIFO if there is any data remaining to be transferred. + * On Mode Fault interrupt this function indicates that transfer is completed, + * the SPI subsystem will identify the error as the remaining bytes to be + * transferred is non-zero. + * + * returns: 0 for poll timeout + * 1 transfer operation complete + */ +static int zynq_qspi_irq_poll(struct zynq_qspi *zqspi) +{ + int max_loop; + u32 intr_status; + u32 rxindex = 0; + u32 rxcount; + + debug("%s: zqspi: 0x%08x\n", __func__, (u32)zqspi); + + /* Poll until any of the interrupt status bits are set */ + max_loop = 0; + do { + intr_status = readl(&zynq_qspi_base->isr); + max_loop++; + } while ((intr_status == 0) && (max_loop < 100000)); + + if (intr_status == 0) { + printf("%s: Timeout\n", __func__); + return 0; + } + + writel(intr_status, &zynq_qspi_base->isr); + + /* Disable all interrupts */ + writel(ZYNQ_QSPI_IXR_ALL_MASK, &zynq_qspi_base->idisr); + if ((intr_status & ZYNQ_QSPI_IXR_TXNFULL_MASK) || + (intr_status & ZYNQ_QSPI_IXR_RXNEMTY_MASK)) { + /* + * This bit is set when Tx FIFO has < THRESHOLD entries. We have + * the THRESHOLD value set to 1, so this bit indicates Tx FIFO + * is empty + */ + rxcount = zqspi->bytes_to_receive - zqspi->bytes_to_transfer; + rxcount = (rxcount % 4) ? ((rxcount/4)+1) : (rxcount/4); + while ((rxindex < rxcount) && + (rxindex < ZYNQ_QSPI_RXFIFO_THRESHOLD)) { + /* Read out the data from the RX FIFO */ + u32 data; + data = readl(&zynq_qspi_base->drxr); + + if (zqspi->bytes_to_receive >= 4) { + if (zqspi->rxbuf) { + memcpy(zqspi->rxbuf, &data, 4); + zqspi->rxbuf += 4; + } + zqspi->bytes_to_receive -= 4; + } else { + zynq_qspi_copy_read_data(zqspi, data, + zqspi->bytes_to_receive); + } + rxindex++; + } + + if (zqspi->bytes_to_transfer) { + /* There is more data to send */ + zynq_qspi_fill_tx_fifo(zqspi, + ZYNQ_QSPI_RXFIFO_THRESHOLD); + + writel(ZYNQ_QSPI_IXR_ALL_MASK, &zynq_qspi_base->ier); + } else { + /* + * If transfer and receive is completed then only send + * complete signal + */ + if (!zqspi->bytes_to_receive) { + /* return operation complete */ + writel(ZYNQ_QSPI_IXR_ALL_MASK, + &zynq_qspi_base->idisr); + return 1; + } + } + } + + return 0; +} + +/* + * zynq_qspi_start_transfer - Initiates the QSPI transfer + * @qspi: Pointer to the spi_device structure + * @transfer: Pointer to the spi_transfer structure which provide information + * about next transfer parameters + * + * This function fills the TX FIFO, starts the QSPI transfer, and waits for the + * transfer to be completed. + * + * returns: Number of bytes transferred in the last transfer + */ +static int zynq_qspi_start_transfer(struct spi_device *qspi, + struct spi_transfer *transfer) +{ + struct zynq_qspi *zqspi = &qspi->master; + static u8 current_u_page; + u32 data = 0; + + debug("%s: qspi: 0x%08x transfer: 0x%08x len: %d\n", __func__, + (u32)qspi, (u32)transfer, transfer->len); + + zqspi->txbuf = transfer->tx_buf; + zqspi->rxbuf = transfer->rx_buf; + zqspi->bytes_to_transfer = transfer->len; + zqspi->bytes_to_receive = transfer->len; + + if (zqspi->is_inst && (zqspi->is_dual == SF_DUAL_STACKED_FLASH) && + (current_u_page != zqspi->u_page)) { + if (zqspi->u_page) { + if (zqspi->is_dio == SF_DUALIO_FLASH) + writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | + ZYNQ_QSPI_LCFG_U_PAGE | + (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | + ZYNQ_QSPI_FR_DUALIO_CODE), + &zynq_qspi_base->lcr); + else + /* Configure two memories on shared bus + * by enabling upper mem + */ + writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | + ZYNQ_QSPI_LCFG_U_PAGE | + (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | + ZYNQ_QSPI_FR_QOUT_CODE), + &zynq_qspi_base->lcr); + } else { + if (zqspi->is_dio == SF_DUALIO_FLASH) + writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | + (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | + ZYNQ_QSPI_FR_DUALIO_CODE), + &zynq_qspi_base->lcr); + else + /* Configure two memories on shared bus + * by enabling lower mem + */ + writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | + (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | + ZYNQ_QSPI_FR_QOUT_CODE), + &zynq_qspi_base->lcr); + } + current_u_page = zqspi->u_page; + } + + if (transfer->len < 4) + zynq_qspi_fill_tx_fifo(zqspi, transfer->len); + else + zynq_qspi_fill_tx_fifo(zqspi, ZYNQ_QSPI_FIFO_DEPTH); + + writel(ZYNQ_QSPI_IXR_ALL_MASK, &zynq_qspi_base->ier); + /* Start the transfer by enabling manual start bit */ + + /* wait for completion */ + do { + data = zynq_qspi_irq_poll(zqspi); + } while (data == 0); + + return (transfer->len) - (zqspi->bytes_to_transfer); +} + +static int zynq_qspi_transfer(struct spi_device *qspi, + struct spi_transfer *transfer) +{ + struct zynq_qspi *zqspi = &qspi->master; + unsigned cs_change = 1; + int status = 0; + + debug("%s\n", __func__); + + while (1) { + if (transfer->bits_per_word || transfer->speed_hz) { + status = zynq_qspi_setup_transfer(qspi, transfer); + if (status < 0) + break; + } + + /* Select the chip if required */ + if (cs_change) + zynq_qspi_chipselect(qspi, 1); + + cs_change = transfer->cs_change; + + if (!transfer->tx_buf && !transfer->rx_buf && transfer->len) { + status = -1; + break; + } + + /* Request the transfer */ + if (transfer->len) { + status = zynq_qspi_start_transfer(qspi, transfer); + zqspi->is_inst = 0; + } + + if (status != transfer->len) { + if (status > 0) + status = -EMSGSIZE; + break; + } + status = 0; + + if (transfer->delay_usecs) + udelay(transfer->delay_usecs); + + if (cs_change) + /* Deselect the chip */ + zynq_qspi_chipselect(qspi, 0); + + break; + } + + zynq_qspi_setup_transfer(qspi, NULL); + + return 0; +} + +/* + * zynq_qspi_check_is_dual_flash - checking for dual or single qspi + * + * This function will check the type of the flash whether it supports + * single or dual qspi based on the MIO configuration done by FSBL. + * + * User needs to correctly configure the MIO's based on the + * number of qspi flashes present on the board. + * + * function will return -1, if there is no MIO configuration for + * qspi flash. + */ +static int zynq_qspi_check_is_dual_flash(int *is_dio) +{ + int is_dual = -1; + int lower_mio = 0, upper_mio = 0, upper_mio_cs1 = 0; + + lower_mio = zynq_slcr_get_mio_pin_status("qspi0"); + if (lower_mio == ZYNQ_QSPI_MIO_NUM_QSPI0) { + is_dual = SF_SINGLE_FLASH; + } else { + lower_mio = zynq_slcr_get_mio_pin_status("qspi0_dio"); + if (lower_mio == ZYNQ_QSPI_MIO_NUM_QSPI0_DIO) { + debug("QSPI in Single 2-bit\n"); + *is_dio = SF_DUALIO_FLASH; + is_dual = SF_SINGLE_FLASH; + } + } + + if (*is_dio != SF_DUALIO_FLASH) { + upper_mio_cs1 = zynq_slcr_get_mio_pin_status("qspi1_cs"); + if ((lower_mio == ZYNQ_QSPI_MIO_NUM_QSPI0) && + (upper_mio_cs1 == ZYNQ_QSPI_MIO_NUM_QSPI1_CS)) + is_dual = SF_DUAL_STACKED_FLASH; + + upper_mio = zynq_slcr_get_mio_pin_status("qspi1"); + if ((lower_mio == ZYNQ_QSPI_MIO_NUM_QSPI0) && + (upper_mio_cs1 == ZYNQ_QSPI_MIO_NUM_QSPI1_CS) && + (upper_mio == ZYNQ_QSPI_MIO_NUM_QSPI1)) + is_dual = SF_DUAL_PARALLEL_FLASH; + } else { + upper_mio_cs1 = zynq_slcr_get_mio_pin_status("qspi1_cs_dio"); + if ((lower_mio == ZYNQ_QSPI_MIO_NUM_QSPI0_DIO) && + (upper_mio_cs1 == ZYNQ_QSPI_MIO_NUM_QSPI1_CS_DIO)) { + debug("QSPI in DualStacked 2-bit\n"); + is_dual = SF_DUAL_STACKED_FLASH; + } + upper_mio = zynq_slcr_get_mio_pin_status("qspi1_dio"); + if ((lower_mio == ZYNQ_QSPI_MIO_NUM_QSPI0_DIO) && + (upper_mio_cs1 == ZYNQ_QSPI_MIO_NUM_QSPI1_CS_DIO) && + (upper_mio == ZYNQ_QSPI_MIO_NUM_QSPI1_DIO)) { + debug("QSPI in DualParallel 2-bit\n"); + is_dual = SF_DUAL_PARALLEL_FLASH; + } + } + + return is_dual; +} + +int spi_cs_is_valid(unsigned int bus, unsigned int cs) +{ + /* 1 bus with 2 chipselect */ + return bus == 0 && cs < 2; +} + +void spi_cs_activate(struct spi_slave *slave) +{ + debug("%s: slave 0x%08x\n", __func__, (unsigned)slave); +} + +void spi_cs_deactivate(struct spi_slave *slave) +{ + debug("%s: slave 0x%08x\n", __func__, (unsigned)slave); +} + +void spi_init() +{ + debug("%s\n", __func__); +} + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) +{ + int is_dual; + int is_dio = 0; + unsigned long lqspi_frequency; + struct zynq_qspi_slave *qspi; + + debug("%s: bus: %d cs: %d max_hz: %d mode: %d\n", + __func__, bus, cs, max_hz, mode); + + if (!spi_cs_is_valid(bus, cs)) + return NULL; + + is_dual = zynq_qspi_check_is_dual_flash(&is_dio); + + if (is_dual == -1) { + printf("%s: No QSPI device detected based on MIO settings\n", + __func__); + return NULL; + } + + zynq_qspi_init_hw(is_dual, is_dio, cs); + + qspi = spi_alloc_slave(struct zynq_qspi_slave, bus, cs); + if (!qspi) { + printf("%s: Fail to allocate zynq_qspi_slave\n", __func__); + return NULL; + } + + lqspi_frequency = zynq_clk_get_rate(lqspi_clk); + if (!lqspi_frequency) { + debug("Defaulting to 200000000 Hz qspi clk"); + qspi->qspi.master.input_clk_hz = 200000000; + } else { + qspi->qspi.master.input_clk_hz = lqspi_frequency; + debug("Qspi clk frequency set to %ld Hz\n", lqspi_frequency); + } + + qspi->slave.option = is_dual; + qspi->slave.dio = is_dio; + qspi->slave.op_mode_rx = SPI_OPM_RX_QOF; + qspi->slave.op_mode_tx = SPI_OPM_TX_QPP; + lqspi_frequency = qspi->qspi.master.input_clk_hz / 2; + qspi->qspi.max_speed_hz = min(max_hz, lqspi_frequency); + qspi->qspi.master.is_dio = is_dio; + qspi->qspi.master.is_dual = is_dual; + qspi->qspi.mode = mode; + qspi->qspi.chip_select = 0; + qspi->qspi.bits_per_word = 32; + zynq_qspi_setup_transfer(&qspi->qspi, NULL); + + return &qspi->slave; +} + +void spi_free_slave(struct spi_slave *slave) +{ + struct zynq_qspi_slave *qspi; + + debug("%s: slave: 0x%08x\n", __func__, (u32)slave); + + qspi = to_zynq_qspi_slave(slave); + free(qspi); +} + +int spi_claim_bus(struct spi_slave *slave) +{ + debug("%s: slave: 0x%08x\n", __func__, (u32)slave); + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ + debug("%s: slave: 0x%08x\n", __func__, (u32)slave); +} + +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, + void *din, unsigned long flags) +{ + struct zynq_qspi_slave *qspi; + struct spi_transfer transfer; + + debug("%s: slave: 0x%08x bitlen: %d dout: 0x%08x ", __func__, + (u32)slave, bitlen, (u32)dout); + debug("din: 0x%08x flags: 0x%lx\n", (u32)din, flags); + + qspi = (struct zynq_qspi_slave *)slave; + transfer.tx_buf = dout; + transfer.rx_buf = din; + transfer.len = bitlen / 8; + + /* + * Festering sore. + * Assume that the beginning of a transfer with bits to + * transmit must contain a device command. + */ + if (dout && flags & SPI_XFER_BEGIN) + qspi->qspi.master.is_inst = 1; + else + qspi->qspi.master.is_inst = 0; + + if (flags & SPI_XFER_END) + transfer.cs_change = 1; + else + transfer.cs_change = 0; + + if (flags & SPI_XFER_U_PAGE) + qspi->qspi.master.u_page = 1; + else + qspi->qspi.master.u_page = 0; + + transfer.delay_usecs = 0; + transfer.bits_per_word = 32; + transfer.speed_hz = qspi->qspi.max_speed_hz; + + zynq_qspi_transfer(&qspi->qspi, &transfer); + + return 0; +} diff --cc fs/fat/fat.c index 0206b14d5f8,bccc3e3ed8f..e22df5405ca --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@@ -317,23 -317,15 +317,22 @@@ get_cluster(fsdata *mydata, __u32 clust /* * Read at most 'maxsize' bytes from 'pos' in the file associated with 'dentptr' * into 'buffer'. - * Return the number of bytes read or -1 on fatal errors. + * Update the number of bytes read in *gotsize or return -1 on fatal errors. */ +#ifndef CONFIG_ZYNQ_OCM +#if defined(CONFIG_ZYNQ) && defined(CONFIG_SPL_BUILD) +__section(.ddr) +#endif __u8 get_contents_vfatname_block[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN); +#else +__u8 *get_contents_vfatname_block = (__u8 *)FAT_BUFF_PTR_OCM; +#endif - static long - get_contents(fsdata *mydata, dir_entry *dentptr, unsigned long pos, - __u8 *buffer, unsigned long maxsize) + static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, + __u8 *buffer, loff_t maxsize, loff_t *gotsize) { - unsigned long filesize = FAT2CPU32(dentptr->size), gotsize = 0; + loff_t filesize = FAT2CPU32(dentptr->size); unsigned int bytesperclust = mydata->clust_size * mydata->sect_size; __u32 curclust = START(dentptr); __u32 endclust, newclust; @@@ -819,17 -803,11 +819,16 @@@ exit return ret; } +#ifndef CONFIG_ZYNQ_OCM +#if defined(CONFIG_ZYNQ) && defined(CONFIG_SPL_BUILD) +__section(.ddr) +#endif __u8 do_fat_read_at_block[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN); +#endif - long - do_fat_read_at(const char *filename, unsigned long pos, void *buffer, - unsigned long maxsize, int dols, int dogetsize) + int do_fat_read_at(const char *filename, loff_t pos, void *buffer, + loff_t maxsize, int dols, int dogetsize, loff_t *size) { char fnamecopy[2048]; boot_sector bs; @@@ -842,15 -820,14 +841,18 @@@ __u32 cursect; int idx, isdir = 0; int files = 0, dirs = 0; - long ret = -1; + int ret = -1; int firsttime; __u32 root_cluster = 0; + __u32 read_blk; int rootdir_size = 0; - int j; +#ifdef CONFIG_ZYNQ_OCM + __u8 do_fat_read_at_block[MAX_CLUSTSIZE] + __aligned(ARCH_DMA_MINALIGN); +#endif + int buffer_blk_cnt; + int do_read; + __u8 *dir_ptr; if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) { debug("Error: reading boot sector\n"); diff --cc include/configs/microblaze-generic.h index 88eee5f4604,bb070600021..7680d307a51 --- a/include/configs/microblaze-generic.h +++ b/include/configs/microblaze-generic.h @@@ -11,61 -11,36 +11,59 @@@ #include "../board/xilinx/microblaze-generic/xparameters.h" - - #define CONFIG_MICROBLAZE 1 /* MicroBlaze CPU */ -/* MicroBlaze CPU */ #define MICROBLAZE_V5 1 -/* linear and spi flash memory */ -#ifdef XILINX_FLASH_START -#define FLASH -#undef SPIFLASH -#undef RAMENV /* hold environment in flash */ -#else -#ifdef XILINX_SPI_FLASH_BASEADDR -#undef FLASH -#define SPIFLASH -#undef RAMENV /* hold environment in flash */ -#else -#undef FLASH -#undef SPIFLASH -#define RAMENV /* hold environment in RAM */ -#endif +/* Memory test handling */ +#define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE +#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + 0x1000) + +/* global pointer */ +/* start of global data */ +#define CONFIG_SYS_GBL_DATA_OFFSET (CONFIG_SYS_SDRAM_SIZE - GENERATED_GBL_DATA_SIZE) + +/* monitor code */ +#define SIZE 0x40000 +#define CONFIG_SYS_MONITOR_LEN SIZE +#define CONFIG_SYS_MONITOR_BASE (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET - CONFIG_SYS_MONITOR_LEN - GENERATED_BD_INFO_SIZE) + +#define CONFIG_SYS_MONITOR_END (CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN) +#define CONFIG_SYS_MALLOC_LEN SIZE +#define CONFIG_SYS_MALLOC_BASE (CONFIG_SYS_MONITOR_BASE - CONFIG_SYS_MALLOC_LEN) + +/* stack */ +#define CONFIG_SYS_INIT_SP_OFFSET CONFIG_SYS_MALLOC_BASE + +#define CONFIG_SYS_BOOTMAPSZ (1 << 31) /* Initial Memory map for Linux */ + +#undef CONFIG_PHYLIB +#define CONFIG_LMB 1 + +/* Default cache size if not specified */ +#ifndef XILINX_DCACHE_BYTE_SIZE +# define XILINX_DCACHE_BYTE_SIZE 32768 #endif -/* uart */ + +/* The following table includes the supported baudrates */ +#define CONFIG_SYS_BAUDRATE_TABLE \ + {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400} + +/* use serial multi for all serial devices */ +#define CONFIG_SYS_CONSOLE_IS_IN_ENV 1 + #ifdef XILINX_UARTLITE_BASEADDR # define CONFIG_XILINX_UARTLITE -# define CONFIG_SERIAL_BASE XILINX_UARTLITE_BASEADDR -# define CONFIG_BAUDRATE XILINX_UARTLITE_BAUDRATE -# define CONFIG_SYS_BAUDRATE_TABLE { CONFIG_BAUDRATE } -# define CONSOLE_ARG "console=console=ttyUL0,115200\0" -#elif XILINX_UART16550_BASEADDR -# define CONFIG_SYS_NS16550 1 +# if defined(XILINX_UARTLITE_BAUDRATE) +# define CONFIG_BAUDRATE XILINX_UARTLITE_BAUDRATE +# endif +#endif + +#if XILINX_UART16550_BASEADDR +# define CONFIG_SYS_NS16550 1 # define CONFIG_SYS_NS16550_SERIAL +# define CONFIG_SYS_NS16550_COM1 ((XILINX_UART16550_BASEADDR & ~0xF) + 0x1000) +# define CONFIG_SYS_NS16550_CLK XILINX_UART16550_CLOCK_HZ + # if defined(__MICROBLAZEEL__) # define CONFIG_SYS_NS16550_REG_SIZE -4 # else diff --cc include/configs/zynq-common.h index 67083c10795,87b4fffeb9f..30e9dc8dae3 --- a/include/configs/zynq-common.h +++ b/include/configs/zynq-common.h @@@ -407,6 -223,13 +408,9 @@@ #define CONFIG_FIT_VERBOSE 1 /* enable fit_format_{error,warning}() */ #define CONFIG_IMAGE_FORMAT_LEGACY /* enable also legacy image format */ + /* FDT support */ + #define CONFIG_DISPLAY_BOARDINFO_LATE + -/* RSA support */ -#define CONFIG_FIT_SIGNATURE -#define CONFIG_RSA - /* Extend size of kernel image for uncompression */ #define CONFIG_SYS_BOOTM_LEN (60 * 1024 * 1024) @@@ -422,35 -245,12 +426,34 @@@ /* Commands */ #include -#define CONFIG_CMD_PING -#define CONFIG_CMD_DHCP -#define CONFIG_CMD_MII -#define CONFIG_CMD_TFTPPUT +#ifdef CONFIG_SYS_ENET +# define CONFIG_CMD_PING +# define CONFIG_CMD_DHCP +# define CONFIG_CMD_MII +# define CONFIG_CMD_TFTPPUT +#else +# undef CONFIG_CMD_NET +# undef CONFIG_CMD_NFS +#endif + +#if defined(CONFIG_CMD_ZYNQ_RSA) +#define CONFIG_RSA +#define CONFIG_SHA256 +#define CONFIG_CMD_ZYNQ_AES +#endif + +#define CONFIG_CMD_BOOTZ +#undef CONFIG_BOOTM_NETBSD + +#define CONFIG_SYS_HZ 1000 + +/* For development/debugging */ +#ifdef DEBUG +# define CONFIG_CMD_REGINFO +# define CONFIG_PANIC_HANG +#endif /* SPL part */ - #define CONFIG_SPL #define CONFIG_CMD_SPL #define CONFIG_SPL_FRAMEWORK #define CONFIG_SPL_LIBCOMMON_SUPPORT @@@ -494,11 -279,9 +492,11 @@@ /* Address in RAM where the parameters must be copied by SPL. */ #define CONFIG_SYS_SPL_ARGS_ADDR 0x10000000 +#define CONFIG_SYS_SPI_ARGS_OFFS 0 /* FIXME */ +#define CONFIG_SYS_SPI_ARGS_SIZE 0 /* FIXME */ - #define CONFIG_SPL_FAT_LOAD_ARGS_NAME "system.dtb" - #define CONFIG_SPL_FAT_LOAD_KERNEL_NAME "uImage" + #define CONFIG_SPL_FS_LOAD_ARGS_NAME "system.dtb" + #define CONFIG_SPL_FS_LOAD_KERNEL_NAME "uImage" /* Not using MMC raw mode - just for compilation purpose */ #define CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR 0 @@@ -510,22 -293,11 +508,20 @@@ #define CONFIG_SPL_SPI_SUPPORT #define CONFIG_SPL_SPI_LOAD #define CONFIG_SPL_SPI_FLASH_SUPPORT - #define CONFIG_SPL_SPI_BUS 0 - #define CONFIG_SYS_SPI_U_BOOT_OFFS 0x80000 - #define CONFIG_SPL_SPI_CS 0 + #define CONFIG_SYS_SPI_U_BOOT_OFFS 0x100000 #endif +#ifdef DEBUG +#define CONFIG_SPL_RAM_DEVICE +#define CONFIG_SPL_NET_SUPPORT +#define CONFIG_SPL_ETH_SUPPORT +#define CONFIG_SPL_ENV_SUPPORT +#define CONFIG_SPL_ETH_DEVICE "Gem.e000b000" +#endif + /* for booting directly linux */ #define CONFIG_SPL_OS_BOOT +#define CONFIG_SYS_SPI_KERNEL_OFFS 0 /* FIXME */ /* SP location before relocation, must use scratch RAM */ #define CONFIG_SPL_TEXT_BASE 0x0 diff --cc include/configs/zynq_cse.h index 16d77936b31,00000000000..db2da747067 mode 100644,000000..100644 --- a/include/configs/zynq_cse.h +++ b/include/configs/zynq_cse.h @@@ -1,81 -1,0 +1,79 @@@ +/* + * (C) Copyright 2013 Xilinx. + * + * Configuration settings for the Xilinx Zynq CSE board. + * See zynq-common.h for Zynq common configs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_ZYNQ_CSE_H +#define __CONFIG_ZYNQ_CSE_H + +#define CONFIG_SYS_NO_FLASH +#define CONFIG_ZYNQ_DCC +#define _CONFIG_CMD_DEFAULT_H +#define CONFIG_SKIP_LOWLEVEL_INIT +#define CONFIG_ENV_IS_NOWHERE +#define CONFIG_SYS_DCACHE_OFF + +#if defined(CONFIG_CSE_QSPI) +# define CONFIG_ZYNQ_QSPI + +#elif defined(CONFIG_CSE_NAND) +# define CONFIG_NAND_ZYNQ + +#elif defined(CONFIG_CSE_NOR) +#undef CONFIG_SYS_NO_FLASH + +#endif + +#include + +/* Undef unneeded configs */ +#undef CONFIG_SYS_SDRAM_BASE +#undef CONFIG_OF_LIBFDT +#undef CONFIG_EXTRA_ENV_SETTINGS +#undef CONFIG_BOARD_LATE_INIT +#undef CONFIG_FPGA +#undef CONFIG_FPGA_XILINX +#undef CONFIG_FPGA_ZYNQPL +#undef CONFIG_CMD_FPGA +#undef CONFIG_FIT +#undef CONFIG_FIT_VERBOSE - #undef CONFIG_CMD_GO - #undef CONFIG_CMD_BOOTM +#undef CONFIG_CMD_BOOTZ +#undef CONFIG_BOOTCOMMAND +#undef CONFIG_SYS_HUSH_PARSER +#undef CONFIG_SYS_PROMPT_HUSH_PS2 +#undef CONFIG_BOOTDELAY +#undef CONFIG_SYS_MALLOC_LEN +#undef CONFIG_ENV_SIZE +#undef CONFIG_CMDLINE_EDITING +#undef CONFIG_AUTO_COMPLETE +#undef CONFIG_ZLIB +#undef CONFIG_GZIP +#undef CONFIG_CMD_SPL + +/* Define needed configs */ +#define CONFIG_CMD_MEMORY +#define CONFIG_BOOTDELAY -1 /* -1 to Disable autoboot */ +#define CONFIG_SYS_MALLOC_LEN 0x4000 + +#if defined(CONFIG_CSE_QSPI) +# define CONFIG_SYS_SDRAM_SIZE (256 * 1024) +# define CONFIG_SYS_SDRAM_BASE 0xFFFD0000 +# define CONFIG_ENV_SIZE 1400 + +#elif defined(CONFIG_CSE_NAND) +# define CONFIG_SYS_SDRAM_SIZE (4 * 1024 * 1024) +# define CONFIG_SYS_SDRAM_BASE 0 +# define CONFIG_ENV_SIZE 0x10000 + +#elif defined(CONFIG_CSE_NOR) +# define CONFIG_SYS_SDRAM_SIZE (256 * 1024) +# define CONFIG_SYS_SDRAM_BASE 0xFFFD0000 +# define CONFIG_ENV_SIZE 1400 + +#endif + +#endif /* __CONFIG_ZYNQ_CSE_H */ diff --cc include/configs/zynq_zc770.h index d17217c7e2c,16b904743f1..1aac1cf1502 --- a/include/configs/zynq_zc770.h +++ b/include/configs/zynq_zc770.h @@@ -19,13 -19,7 +19,11 @@@ # define CONFIG_ZYNQ_GEM0 # define CONFIG_ZYNQ_GEM_PHY_ADDR0 7 # define CONFIG_ZYNQ_SDHCI0 -# define CONFIG_ZYNQ_SPI +# define CONFIG_ZYNQ_QSPI - # define CONFIG_DEFAULT_DEVICE_TREE zynq-zc770-xm010 + +#elif defined(CONFIG_ZC770_XM011) +# define CONFIG_ZYNQ_SERIAL_UART1 +# define CONFIG_NAND_ZYNQ - # define CONFIG_DEFAULT_DEVICE_TREE zynq-zc770-xm011 #elif defined(CONFIG_ZC770_XM012) # define CONFIG_ZYNQ_SERIAL_UART1 @@@ -36,8 -29,6 +33,7 @@@ # define CONFIG_ZYNQ_SERIAL_UART0 # define CONFIG_ZYNQ_GEM1 # define CONFIG_ZYNQ_GEM_PHY_ADDR1 7 +# define CONFIG_ZYNQ_QSPI - # define CONFIG_DEFAULT_DEVICE_TREE zynq-zc770-xm013 #else # define CONFIG_ZYNQ_SERIAL_UART0 diff --cc include/configs/zynq_zed.h index 832e7a0f53d,946de953e4a..224c7cd7c84 --- a/include/configs/zynq_zed.h +++ b/include/configs/zynq_zed.h @@@ -20,10 -20,7 +20,9 @@@ #define CONFIG_ZYNQ_USB #define CONFIG_ZYNQ_SDHCI0 +#define CONFIG_ZYNQ_QSPI + #define CONFIG_ZYNQ_BOOT_FREEBSD - #define CONFIG_DEFAULT_DEVICE_TREE zynq-zed #include diff --cc include/spi_flash.h index 7b64957103d,5913b39e268..a8b5da203a7 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@@ -15,58 -15,23 +15,25 @@@ #ifndef _SPI_FLASH_H_ #define _SPI_FLASH_H_ - #include + #include /* Because we dereference struct udevice here */ #include - #include - - /* sf param flags */ - #define SECT_4K 1 << 1 - #define SECT_32K 1 << 2 - #define E_FSR 1 << 3 - #define WR_QPP 1 << 4 - - /* Enum list - Full read commands */ - enum spi_read_cmds { - ARRAY_SLOW = 1 << 0, - DUAL_OUTPUT_FAST = 1 << 1, - DUAL_IO_FAST = 1 << 2, - QUAD_OUTPUT_FAST = 1 << 3, - QUAD_IO_FAST = 1 << 4, - }; - #define RD_EXTN ARRAY_SLOW | DUAL_OUTPUT_FAST | DUAL_IO_FAST - #define RD_FULL RD_EXTN | QUAD_OUTPUT_FAST | QUAD_IO_FAST - - /* Dual SPI flash memories */ - enum spi_dual_flash { - SF_SINGLE_FLASH = 0, - SF_DUAL_STACKED_FLASH = 1 << 0, - SF_DUAL_PARALLEL_FLASH = 1 << 1, - }; +#define SF_DUALIO_FLASH 1 + - /** - * struct spi_flash_params - SPI/QSPI flash device params structure - * - * @name: Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) - * @jedec: Device jedec ID (0x[1byte_manuf_id][2byte_dev_id]) - * @ext_jedec: Device ext_jedec ID - * @sector_size: Sector size of this device - * @nr_sectors: No.of sectors on this device - * @e_rd_cmd: Enum list for read commands - * @flags: Important param, for flash specific behaviour - */ - struct spi_flash_params { - const char *name; - u32 jedec; - u16 ext_jedec; - u32 sector_size; - u32 nr_sectors; - u8 e_rd_cmd; - u16 flags; - }; + #ifndef CONFIG_SF_DEFAULT_SPEED + # define CONFIG_SF_DEFAULT_SPEED 1000000 + #endif + #ifndef CONFIG_SF_DEFAULT_MODE + # define CONFIG_SF_DEFAULT_MODE SPI_MODE_3 + #endif + #ifndef CONFIG_SF_DEFAULT_CS + # define CONFIG_SF_DEFAULT_CS 0 + #endif + #ifndef CONFIG_SF_DEFAULT_BUS + # define CONFIG_SF_DEFAULT_BUS 0 + #endif - extern const struct spi_flash_params spi_flash_params_table[]; + struct spi_slave; /** * struct spi_flash - SPI flash structure diff --cc lib/rsa/rsa-verify.c index fd26bde621e,4ef19b66f4b..aac25ad5b57 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@@ -121,7 -124,49 +124,49 @@@ static void montgomery_mul(const struc for (i = 0; i < key->len; ++i) montgomery_mul_add_step(key, result, a[i], b); } - +#if IMAGE_ENABLE_VERIFY + /** + * num_pub_exponent_bits() - Number of bits in the public exponent + * + * @key: RSA key + * @num_bits: Storage for the number of public exponent bits + */ + static int num_public_exponent_bits(const struct rsa_public_key *key, + int *num_bits) + { + uint64_t exponent; + int exponent_bits; + const uint max_bits = (sizeof(exponent) * 8); + + exponent = key->exponent; + exponent_bits = 0; + + if (!exponent) { + *num_bits = exponent_bits; + return 0; + } + + for (exponent_bits = 1; exponent_bits < max_bits + 1; ++exponent_bits) + if (!(exponent >>= 1)) { + *num_bits = exponent_bits; + return 0; + } + + return -EINVAL; + } + + /** + * is_public_exponent_bit_set() - Check if a bit in the public exponent is set + * + * @key: RSA key + * @pos: The bit position to check + */ + static int is_public_exponent_bit_set(const struct rsa_public_key *key, + int pos) + { + return key->exponent & (1ULL << pos); + } + /** * pow_mod() - in-place public exponentiation *