aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2022-01-14 10:43:14 -0500
committerTom Rini <trini@konsulko.com>2022-01-14 10:43:14 -0500
commit9b72d934c2f7d8ee894f87e082577743877eb76e (patch)
tree875f11c867129e7550c7e86ae672052b8b0612a8
parent25711b07ca1dcf73dc41b45ca040dadbcff0fa08 (diff)
parent1dcbcc715e87da6d30b8ae22f1ef04c881cfea5b (diff)
downloadu-boot-WIP/14Jan2022.zip
u-boot-WIP/14Jan2022.tar.gz
u-boot-WIP/14Jan2022.tar.bz2
Merge https://source.denx.de/u-boot/custodians/u-boot-marvellWIP/14Jan2022
- mvebu: Move PCIe code from serdes to PCIe driver (Pali) - mtd: nand: pxa3xx: use marvell, prefix for custom DT properties (Pierre) - Add PCIe support for Iomega iConnect board (Tony) - ddr: marvell: a38x: Misc improvements / fixes (Marek) - tools: kwbimage: Load address fixes (Pali) - mvebu: db-88f6720: Fix CONFIG_SPL_TEXT_BASE and remove wrong memory layout (Pali) - mvebu: Replace hardcoded values 0x0030/0x4030 by proper calculation (Pali)
-rw-r--r--arch/arm/dts/armada-375.dtsi5
-rw-r--r--arch/arm/dts/armada-380.dtsi3
-rw-r--r--arch/arm/dts/armada-385.dtsi4
-rw-r--r--arch/arm/dts/armada-38x.dtsi1
-rw-r--r--arch/arm/dts/armada-cp110.dtsi2
-rw-r--r--arch/arm/dts/armada-xp-98dx3236.dtsi2
-rw-r--r--arch/arm/dts/armada-xp-mv78230.dtsi5
-rw-r--r--arch/arm/dts/armada-xp-mv78260.dtsi9
-rw-r--r--arch/arm/dts/armada-xp-mv78460.dtsi10
-rw-r--r--arch/arm/dts/armada-xp-synology-ds414.dts1
-rw-r--r--arch/arm/dts/armada-xp-theadorable.dts1
-rw-r--r--arch/arm/dts/armada-xp.dtsi1
-rw-r--r--arch/arm/mach-mvebu/Makefile26
-rw-r--r--arch/arm/mach-mvebu/include/mach/cpu.h5
-rw-r--r--arch/arm/mach-mvebu/kwbimage.cfg.in10
-rw-r--r--arch/arm/mach-mvebu/serdes/a38x/Makefile1
-rw-r--r--arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c64
-rw-r--r--arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h28
-rw-r--r--arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c19
-rw-r--r--arch/arm/mach-mvebu/system-controller.c105
-rw-r--r--board/gdsys/a38x/MAINTAINERS1
-rw-r--r--board/gdsys/a38x/controlcenterdc.c6
-rw-r--r--board/gdsys/mpc8308/MAINTAINERS2
-rw-r--r--board/iomega/iconnect/MAINTAINERS1
-rw-r--r--board/iomega/iconnect/iconnect.c7
-rw-r--r--configs/controlcenterdc_defconfig1
-rw-r--r--configs/db-88f6720_defconfig2
-rw-r--r--configs/iconnect_defconfig5
-rw-r--r--drivers/ddr/marvell/a38x/ddr3_training_centralization.c26
-rw-r--r--drivers/ddr/marvell/a38x/mv_ddr_plat.c19
-rw-r--r--drivers/mtd/nand/raw/pxa3xx_nand.c4
-rw-r--r--drivers/pci/Kconfig1
-rw-r--r--drivers/pci/pci_mvebu.c275
-rw-r--r--include/configs/clearfog.h2
-rw-r--r--include/configs/db-88f6720.h15
-rw-r--r--include/configs/db-88f6820-amc.h2
-rw-r--r--include/configs/db-88f6820-gp.h2
-rw-r--r--include/configs/db-mv784mp-gp.h2
-rw-r--r--include/configs/ds414.h2
-rw-r--r--include/configs/helios4.h2
-rw-r--r--include/configs/maxbcm.h2
-rw-r--r--include/configs/theadorable.h2
-rw-r--r--include/configs/turris_omnia.h2
-rw-r--r--include/configs/x530.h2
-rw-r--r--tools/kwbimage.c549
-rw-r--r--tools/kwbimage.h10
-rw-r--r--tools/kwboot.c4
47 files changed, 920 insertions, 330 deletions
diff --git a/arch/arm/dts/armada-375.dtsi b/arch/arm/dts/armada-375.dtsi
index 62a548a..ff0ad7a 100644
--- a/arch/arm/dts/armada-375.dtsi
+++ b/arch/arm/dts/armada-375.dtsi
@@ -384,9 +384,10 @@
interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
};
- system-controller@18200 {
+ systemc: system-controller@18200 {
compatible = "marvell,armada-375-system-controller";
reg = <0x18200 0x100>;
+ #reset-cells = <2>;
};
gateclk: clock-gating-control@18220 {
@@ -616,6 +617,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 5>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
@@ -634,6 +636,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <1>;
clocks = <&gateclk 6>;
+ resets = <&systemc 0 1>;
status = "disabled";
};
diff --git a/arch/arm/dts/armada-380.dtsi b/arch/arm/dts/armada-380.dtsi
index cff1269..f3d7f4b 100644
--- a/arch/arm/dts/armada-380.dtsi
+++ b/arch/arm/dts/armada-380.dtsi
@@ -73,6 +73,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 8>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
@@ -92,6 +93,7 @@
marvell,pcie-port = <1>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 5>;
+ resets = <&systemc 0 1>;
status = "disabled";
};
@@ -111,6 +113,7 @@
marvell,pcie-port = <2>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 6>;
+ resets = <&systemc 0 2>;
status = "disabled";
};
};
diff --git a/arch/arm/dts/armada-385.dtsi b/arch/arm/dts/armada-385.dtsi
index f0022d1..581a7d9 100644
--- a/arch/arm/dts/armada-385.dtsi
+++ b/arch/arm/dts/armada-385.dtsi
@@ -78,6 +78,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 8>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
@@ -97,6 +98,7 @@
marvell,pcie-port = <1>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 5>;
+ resets = <&systemc 0 1>;
status = "disabled";
};
@@ -116,6 +118,7 @@
marvell,pcie-port = <2>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 6>;
+ resets = <&systemc 0 2>;
status = "disabled";
};
@@ -138,6 +141,7 @@
marvell,pcie-port = <3>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 7>;
+ resets = <&systemc 0 3>;
status = "disabled";
};
};
diff --git a/arch/arm/dts/armada-38x.dtsi b/arch/arm/dts/armada-38x.dtsi
index 72c49be..061bd78 100644
--- a/arch/arm/dts/armada-38x.dtsi
+++ b/arch/arm/dts/armada-38x.dtsi
@@ -328,6 +328,7 @@
compatible = "marvell,armada-380-system-controller",
"marvell,armada-370-xp-system-controller";
reg = <0x18200 0x100>;
+ #reset-cells = <2>;
};
gateclk: clock-gating-control@18220 {
diff --git a/arch/arm/dts/armada-cp110.dtsi b/arch/arm/dts/armada-cp110.dtsi
index abf1e4e..ddc10d2 100644
--- a/arch/arm/dts/armada-cp110.dtsi
+++ b/arch/arm/dts/armada-cp110.dtsi
@@ -231,7 +231,7 @@
#address-cells = <1>;
#size-cells = <0>;
clocks = <&CP110_LABEL(syscon0) 1 2>;
- nand-enable-arbiter;
+ marvell,nand-enable-arbiter;
num-cs = <1>;
nand-ecc-strength = <8>;
nand-ecc-step-size = <512>;
diff --git a/arch/arm/dts/armada-xp-98dx3236.dtsi b/arch/arm/dts/armada-xp-98dx3236.dtsi
index 5df1d18..1a48ff3 100644
--- a/arch/arm/dts/armada-xp-98dx3236.dtsi
+++ b/arch/arm/dts/armada-xp-98dx3236.dtsi
@@ -85,6 +85,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 5>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
};
@@ -136,6 +137,7 @@
systemc: system-controller@18200 {
compatible = "marvell,armada-370-xp-system-controller";
reg = <0x18200 0x500>;
+ #reset-cells = <2>;
};
gateclk: clock-gating-control@18220 {
diff --git a/arch/arm/dts/armada-xp-mv78230.dtsi b/arch/arm/dts/armada-xp-mv78230.dtsi
index 8558bf6..63d7f48 100644
--- a/arch/arm/dts/armada-xp-mv78230.dtsi
+++ b/arch/arm/dts/armada-xp-mv78230.dtsi
@@ -92,6 +92,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 5>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
@@ -110,6 +111,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <1>;
clocks = <&gateclk 6>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
@@ -128,6 +130,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <2>;
clocks = <&gateclk 7>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
@@ -146,6 +149,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <3>;
clocks = <&gateclk 8>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
@@ -164,6 +168,7 @@
marvell,pcie-port = <1>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 9>;
+ resets = <&systemc 0 1>;
status = "disabled";
};
};
diff --git a/arch/arm/dts/armada-xp-mv78260.dtsi b/arch/arm/dts/armada-xp-mv78260.dtsi
index 2d85fe8..5dc413d 100644
--- a/arch/arm/dts/armada-xp-mv78260.dtsi
+++ b/arch/arm/dts/armada-xp-mv78260.dtsi
@@ -107,6 +107,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 5>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
@@ -125,6 +126,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <1>;
clocks = <&gateclk 6>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
@@ -143,6 +145,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <2>;
clocks = <&gateclk 7>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
@@ -161,6 +164,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <3>;
clocks = <&gateclk 8>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
@@ -179,6 +183,7 @@
marvell,pcie-port = <1>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 9>;
+ resets = <&systemc 0 1>;
status = "disabled";
};
@@ -197,6 +202,7 @@
marvell,pcie-port = <1>;
marvell,pcie-lane = <1>;
clocks = <&gateclk 10>;
+ resets = <&systemc 0 1>;
status = "disabled";
};
@@ -215,6 +221,7 @@
marvell,pcie-port = <1>;
marvell,pcie-lane = <2>;
clocks = <&gateclk 11>;
+ resets = <&systemc 0 1>;
status = "disabled";
};
@@ -233,6 +240,7 @@
marvell,pcie-port = <1>;
marvell,pcie-lane = <3>;
clocks = <&gateclk 12>;
+ resets = <&systemc 0 1>;
status = "disabled";
};
@@ -251,6 +259,7 @@
marvell,pcie-port = <2>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 26>;
+ resets = <&systemc 0 2>;
status = "disabled";
};
};
diff --git a/arch/arm/dts/armada-xp-mv78460.dtsi b/arch/arm/dts/armada-xp-mv78460.dtsi
index 230a3fd..6fbd0ce 100644
--- a/arch/arm/dts/armada-xp-mv78460.dtsi
+++ b/arch/arm/dts/armada-xp-mv78460.dtsi
@@ -128,6 +128,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 5>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
@@ -146,6 +147,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <1>;
clocks = <&gateclk 6>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
@@ -164,6 +166,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <2>;
clocks = <&gateclk 7>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
@@ -182,6 +185,7 @@
marvell,pcie-port = <0>;
marvell,pcie-lane = <3>;
clocks = <&gateclk 8>;
+ resets = <&systemc 0 0>;
status = "disabled";
};
@@ -200,6 +204,7 @@
marvell,pcie-port = <1>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 9>;
+ resets = <&systemc 0 1>;
status = "disabled";
};
@@ -218,6 +223,7 @@
marvell,pcie-port = <1>;
marvell,pcie-lane = <1>;
clocks = <&gateclk 10>;
+ resets = <&systemc 0 1>;
status = "disabled";
};
@@ -236,6 +242,7 @@
marvell,pcie-port = <1>;
marvell,pcie-lane = <2>;
clocks = <&gateclk 11>;
+ resets = <&systemc 0 1>;
status = "disabled";
};
@@ -254,6 +261,7 @@
marvell,pcie-port = <1>;
marvell,pcie-lane = <3>;
clocks = <&gateclk 12>;
+ resets = <&systemc 0 1>;
status = "disabled";
};
@@ -272,6 +280,7 @@
marvell,pcie-port = <2>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 26>;
+ resets = <&systemc 0 2>;
status = "disabled";
};
@@ -290,6 +299,7 @@
marvell,pcie-port = <3>;
marvell,pcie-lane = <0>;
clocks = <&gateclk 27>;
+ resets = <&systemc 0 3>;
status = "disabled";
};
};
diff --git a/arch/arm/dts/armada-xp-synology-ds414.dts b/arch/arm/dts/armada-xp-synology-ds414.dts
index 861967c..35909e3 100644
--- a/arch/arm/dts/armada-xp-synology-ds414.dts
+++ b/arch/arm/dts/armada-xp-synology-ds414.dts
@@ -187,6 +187,7 @@
pcie@1,0 {
/* Port 0, Lane 0 */
status = "okay";
+ num-lanes = <4>;
};
/*
diff --git a/arch/arm/dts/armada-xp-theadorable.dts b/arch/arm/dts/armada-xp-theadorable.dts
index 24cc1cc..a06a65a 100644
--- a/arch/arm/dts/armada-xp-theadorable.dts
+++ b/arch/arm/dts/armada-xp-theadorable.dts
@@ -214,5 +214,6 @@
pcie@9,0 {
/* Port 2, Lane 0 */
status = "okay";
+ num-lanes = <4>;
};
};
diff --git a/arch/arm/dts/armada-xp.dtsi b/arch/arm/dts/armada-xp.dtsi
index d856d96..fb5640b 100644
--- a/arch/arm/dts/armada-xp.dtsi
+++ b/arch/arm/dts/armada-xp.dtsi
@@ -78,6 +78,7 @@
systemc: system-controller@18200 {
compatible = "marvell,armada-370-xp-system-controller";
reg = <0x18200 0x500>;
+ #reset-cells = <2>;
};
gateclk: clock-gating-control@18220 {
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 7e9c206..a5a2087 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -21,6 +21,7 @@ else # CONFIG_ARCH_KIRKWOOD
obj-y = cpu.o
obj-y += dram.o
+obj-$(CONFIG_DM_RESET) += system-controller.o
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_ARMADA_375) += ../../../drivers/ddr/marvell/axp/xor.o
obj-$(CONFIG_ARMADA_38X) += ../../../drivers/ddr/marvell/a38x/xor.o
@@ -30,6 +31,17 @@ obj-$(CONFIG_MVEBU_EFUSE) += efuse.o
extra-y += kwbimage.cfg
+ifneq ($(CONFIG_ARMADA_370)$(CONFIG_ARMADA_XP),)
+ KWB_REPLACE += CPU
+ KWB_CFG_CPU = SHEEVA
+else ifneq ($(CONFIG_ARMADA_375)$(CONFIG_ARMADA_38X)$(CONFIG_ARMADA_39X),)
+ KWB_REPLACE += CPU
+ KWB_CFG_CPU = A9
+endif
+
+KWB_REPLACE += LOAD_ADDRESS
+KWB_CFG_LOAD_ADDRESS = $(CONFIG_SPL_TEXT_BASE)
+
KWB_REPLACE += BOOT_FROM
ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_SPI),)
KWB_CFG_BOOT_FROM=spi
@@ -58,10 +70,20 @@ KWB_REPLACE += SEC_FUSE_DUMP
KWB_CFG_SEC_FUSE_DUMP = a38x
endif
+ifdef CONFIG_ARMADA_38X
+# BootROM output is by default enabled on pre-A38x and disabled on A38x
+# DEBUG flag on A38x for non-UART boot source only enable BootROM output and nothing more
+KWB_REPLACE += DEBUG
+KWB_CFG_DEBUG = 1
+endif
+
+quiet_cmd_kwbcfg = KWBCFG $@
+cmd_kwbcfg = sed -ne '$(foreach V,$(KWB_REPLACE),s/\#@$(V)/$(V) $(KWB_CFG_$(V))/;)p' \
+ <$< >$(dir $@)$(@F)
+
$(obj)/kwbimage.cfg: $(src)/kwbimage.cfg.in include/autoconf.mk \
include/config/auto.conf
- $(Q)sed -ne '$(foreach V,$(KWB_REPLACE),s/^#@$(V)/$(V) $(KWB_CFG_$(V))/;)p' \
- <$< >$(dir $@)$(@F)
+ $(call cmd,kwbcfg)
endif # CONFIG_SPL_BUILD
obj-y += gpio.o
diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
index a7a62c7..b99d86a 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -74,10 +74,11 @@ enum {
/*
* Default Device Address MAP BAR values
*/
+#define MBUS_PCI_MAX_PORTS 6
#define MBUS_PCI_MEM_BASE MVEBU_SDRAM_SIZE_MAX
-#define MBUS_PCI_MEM_SIZE (128 << 20)
+#define MBUS_PCI_MEM_SIZE ((MBUS_PCI_MAX_PORTS * 128) << 20)
#define MBUS_PCI_IO_BASE 0xF1100000
-#define MBUS_PCI_IO_SIZE (64 << 10)
+#define MBUS_PCI_IO_SIZE ((MBUS_PCI_MAX_PORTS * 64) << 10)
#define MBUS_SPI_BASE 0xF4000000
#define MBUS_SPI_SIZE (8 << 20)
#define MBUS_DFX_BASE 0xF6000000
diff --git a/arch/arm/mach-mvebu/kwbimage.cfg.in b/arch/arm/mach-mvebu/kwbimage.cfg.in
index 049d23c..ccb0997 100644
--- a/arch/arm/mach-mvebu/kwbimage.cfg.in
+++ b/arch/arm/mach-mvebu/kwbimage.cfg.in
@@ -5,8 +5,14 @@
# Armada 38x uses version 1 image format
VERSION 1
+# Type of the CPU core
+#@CPU
+
# Boot Media configurations
#@BOOT_FROM
-# Binary Header (bin_hdr) with DDR3 training code
-BINARY spl/u-boot-spl.bin
+# Enable BootROM output via DEBUG flag on SoCs which require it
+#@DEBUG
+
+# Include U-Boot SPL with DDR3 training code into Binary Header
+BINARY spl/u-boot-spl.bin #@LOAD_ADDRESS
diff --git a/arch/arm/mach-mvebu/serdes/a38x/Makefile b/arch/arm/mach-mvebu/serdes/a38x/Makefile
index 917fc13..5a70b37 100644
--- a/arch/arm/mach-mvebu/serdes/a38x/Makefile
+++ b/arch/arm/mach-mvebu/serdes/a38x/Makefile
@@ -1,6 +1,5 @@
# SPDX-License-Identifier: GPL-2.0+
-obj-$(CONFIG_SPL_BUILD) = ctrl_pex.o
obj-$(CONFIG_SPL_BUILD) += high_speed_env_spec.o
obj-$(CONFIG_SPL_BUILD) += high_speed_env_spec-38x.o
obj-$(CONFIG_SPL_BUILD) += seq_exec.o
diff --git a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
deleted file mode 100644
index 55c3f9c..0000000
--- a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
+++ /dev/null
@@ -1,64 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) Marvell International Ltd. and its affiliates
- */
-
-#include <common.h>
-#include <spl.h>
-#include <asm/io.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/soc.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-
-#include "ctrl_pex.h"
-#include "sys_env_lib.h"
-
-__weak void board_pex_config(void)
-{
- /* nothing in this weak default implementation */
-}
-
-int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
-{
- enum serdes_type serdes_type;
- u32 idx, tmp;
-
- DEBUG_INIT_FULL_S("\n### hws_pex_config ###\n");
-
- tmp = reg_read(SOC_CONTROL_REG1);
- tmp &= ~0x03;
-
- for (idx = 0; idx < count; idx++) {
- serdes_type = serdes_map[idx].serdes_type;
- if ((serdes_type != PEX0) &&
- ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
- (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
- /* for PEX by4 - relevant for the first port only */
- continue;
- }
-
- switch (serdes_type) {
- case PEX0:
- tmp |= 0x1 << PCIE0_ENABLE_OFFS;
- break;
- case PEX1:
- tmp |= 0x1 << PCIE1_ENABLE_OFFS;
- break;
- case PEX2:
- tmp |= 0x1 << PCIE2_ENABLE_OFFS;
- break;
- case PEX3:
- tmp |= 0x1 << PCIE3_ENABLE_OFFS;
- break;
- default:
- break;
- }
- }
-
- reg_write(SOC_CONTROL_REG1, tmp);
-
- board_pex_config();
-
- return MV_OK;
-}
diff --git a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
deleted file mode 100644
index 64193d5..0000000
--- a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) Marvell International Ltd. and its affiliates
- */
-
-#ifndef _CTRL_PEX_H
-#define _CTRL_PEX_H
-
-#include <pci.h>
-#include "high_speed_env_spec.h"
-
-/* Direct access to PEX0 Root Port's PCIe Capability structure */
-#define PEX0_RP_PCIE_CFG_OFFSET (0x00080000 + 0x60)
-
-/* SOC_CONTROL_REG1 fields */
-#define PCIE0_ENABLE_OFFS 0
-#define PCIE0_ENABLE_MASK (0x1 << PCIE0_ENABLE_OFFS)
-#define PCIE1_ENABLE_OFFS 1
-#define PCIE1_ENABLE_MASK (0x1 << PCIE1_ENABLE_OFFS)
-#define PCIE2_ENABLE_OFFS 2
-#define PCIE2_ENABLE_MASK (0x1 << PCIE2_ENABLE_OFFS)
-#define PCIE3_ENABLE_OFFS 3
-#define PCIE4_ENABLE_MASK (0x1 << PCIE3_ENABLE_OFFS)
-
-int hws_pex_config(const struct serdes_map *serdes_map, u8 count);
-void board_pex_config(void);
-
-#endif
diff --git a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
index 9ba60b5..2e467b5 100644
--- a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
+++ b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
@@ -12,7 +12,6 @@
#include "high_speed_env_spec.h"
#include "sys_env_lib.h"
-#include "ctrl_pex.h"
/*
* serdes_seq_db - holds all serdes sequences, their size and the
@@ -1555,9 +1554,6 @@ int hws_power_up_serdes_lanes(struct serdes_map *serdes_map, u8 count)
After finish the Power_up sequence for all lanes,
the lanes should be released from reset state. */
CHECK_STATUS(hws_pex_tx_config_seq(serdes_map, count));
-
- /* PEX configuration */
- CHECK_STATUS(hws_pex_config(serdes_map, count));
}
/* USB2 configuration */
@@ -1743,21 +1739,6 @@ int serdes_power_up_ctrl(u32 serdes_num, int serdes_power_up,
else
reg_data &= ~0x4000;
reg_write(SOC_CONTROL_REG1, reg_data);
-
- /*
- * Set Maximum Link Width to X1 or X4 in Root
- * Port's PCIe Link Capability register.
- * This register is read-only but if is not set
- * correctly then access to PCI config space of
- * endpoint card behind this Root Port does not
- * work.
- */
- reg_data = reg_read(PEX0_RP_PCIE_CFG_OFFSET +
- PCI_EXP_LNKCAP);
- reg_data &= ~PCI_EXP_LNKCAP_MLW;
- reg_data |= (is_pex_by1 ? 1 : 4) << 4;
- reg_write(PEX0_RP_PCIE_CFG_OFFSET +
- PCI_EXP_LNKCAP, reg_data);
}
CHECK_STATUS(mv_seq_exec(serdes_num, PEX_POWER_UP_SEQ));
diff --git a/arch/arm/mach-mvebu/system-controller.c b/arch/arm/mach-mvebu/system-controller.c
new file mode 100644
index 0000000..ea858b2
--- /dev/null
+++ b/arch/arm/mach-mvebu/system-controller.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0+
+// (C) 2021 Pali Rohár <pali@kernel.org>
+
+#include <common.h>
+#include <dm.h>
+#include <reset-uclass.h>
+#include <asm/io.h>
+
+#define MVEBU_SOC_CONTROL_1_REG 0x4
+
+#define MVEBU_PCIE_ID 0
+
+struct mvebu_reset_data {
+ void *base;
+};
+
+static int mvebu_reset_of_xlate(struct reset_ctl *rst,
+ struct ofnode_phandle_args *args)
+{
+ if (args->args_count < 2)
+ return -EINVAL;
+
+ rst->id = args->args[0];
+ rst->data = args->args[1];
+
+ /* Currently only PCIe is implemented */
+ if (rst->id != MVEBU_PCIE_ID)
+ return -EINVAL;
+
+ /* Four PCIe enable bits are shared across more PCIe links */
+ if (!(rst->data >= 0 && rst->data <= 3))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int mvebu_reset_request(struct reset_ctl *rst)
+{
+ return 0;
+}
+
+static int mvebu_reset_free(struct reset_ctl *rst)
+{
+ return 0;
+}
+
+static int mvebu_reset_assert(struct reset_ctl *rst)
+{
+ struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+
+ clrbits_32(data->base + MVEBU_SOC_CONTROL_1_REG, BIT(rst->data));
+ return 0;
+}
+
+static int mvebu_reset_deassert(struct reset_ctl *rst)
+{
+ struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+
+ setbits_32(data->base + MVEBU_SOC_CONTROL_1_REG, BIT(rst->data));
+ return 0;
+}
+
+static int mvebu_reset_status(struct reset_ctl *rst)
+{
+ struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+
+ return !(readl(data->base + MVEBU_SOC_CONTROL_1_REG) & BIT(rst->data));
+}
+
+static int mvebu_reset_of_to_plat(struct udevice *dev)
+{
+ struct mvebu_reset_data *data = dev_get_priv(dev);
+
+ data->base = (void *)dev_read_addr(dev);
+ if ((fdt_addr_t)data->base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const struct udevice_id mvebu_reset_of_match[] = {
+ { .compatible = "marvell,armada-370-xp-system-controller" },
+ { .compatible = "marvell,armada-375-system-controller" },
+ { .compatible = "marvell,armada-380-system-controller" },
+ { .compatible = "marvell,armada-390-system-controller" },
+ { },
+};
+
+static struct reset_ops mvebu_reset_ops = {
+ .of_xlate = mvebu_reset_of_xlate,
+ .request = mvebu_reset_request,
+ .rfree = mvebu_reset_free,
+ .rst_assert = mvebu_reset_assert,
+ .rst_deassert = mvebu_reset_deassert,
+ .rst_status = mvebu_reset_status,
+};
+
+U_BOOT_DRIVER(mvebu_reset) = {
+ .name = "mvebu-reset",
+ .id = UCLASS_RESET,
+ .of_match = mvebu_reset_of_match,
+ .of_to_plat = mvebu_reset_of_to_plat,
+ .priv_auto = sizeof(struct mvebu_reset_data),
+ .ops = &mvebu_reset_ops,
+};
diff --git a/board/gdsys/a38x/MAINTAINERS b/board/gdsys/a38x/MAINTAINERS
index d31e675..6492e79 100644
--- a/board/gdsys/a38x/MAINTAINERS
+++ b/board/gdsys/a38x/MAINTAINERS
@@ -1,5 +1,4 @@
A38X BOARD
-M: Dirk Eibach <dirk.eibach@gdsys.cc>
M: Mario Six <mario.six@gdsys.cc>
S: Maintained
F: board/gdsys/a38x/
diff --git a/board/gdsys/a38x/controlcenterdc.c b/board/gdsys/a38x/controlcenterdc.c
index dc424f2..7d65400 100644
--- a/board/gdsys/a38x/controlcenterdc.c
+++ b/board/gdsys/a38x/controlcenterdc.c
@@ -94,12 +94,16 @@ int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
return 0;
}
-void board_pex_config(void)
+void spl_board_init(void)
{
#ifdef CONFIG_SPL_BUILD
uint k;
struct gpio_desc gpio = {};
+ /* Enable PCIe link 2 */
+ setbits_32(MVEBU_REGISTER(0x18204), BIT(2));
+ mdelay(10);
+
if (!request_gpio_by_name(&gpio, "pca9698@22", 31, "fpga-program-gpio")) {
/* prepare FPGA reconfiguration */
dm_gpio_set_dir_flags(&gpio, GPIOD_IS_OUT);
diff --git a/board/gdsys/mpc8308/MAINTAINERS b/board/gdsys/mpc8308/MAINTAINERS
index dc0b389..57faba4 100644
--- a/board/gdsys/mpc8308/MAINTAINERS
+++ b/board/gdsys/mpc8308/MAINTAINERS
@@ -1,5 +1,5 @@
MPC8308 BOARD
-M: Dirk Eibach <dirk.eibach@gdsys.cc>
+M: Mario Six <mario.six@gdsys.cc>
S: Maintained
F: board/gdsys/mpc8308/
F: include/configs/gazerbeam.h
diff --git a/board/iomega/iconnect/MAINTAINERS b/board/iomega/iconnect/MAINTAINERS
index 167cf07..a1b018e 100644
--- a/board/iomega/iconnect/MAINTAINERS
+++ b/board/iomega/iconnect/MAINTAINERS
@@ -1,4 +1,5 @@
ICONNECT BOARD
+M: Tony Dinh <mibodhi@gmail.com>
M: Luka Perkov <luka@openwrt.org>
S: Maintained
F: board/iomega/iconnect/
diff --git a/board/iomega/iconnect/iconnect.c b/board/iomega/iconnect/iconnect.c
index fe4be28..9e123aa 100644
--- a/board/iomega/iconnect/iconnect.c
+++ b/board/iomega/iconnect/iconnect.c
@@ -92,3 +92,10 @@ int board_init(void)
return 0;
}
+
+int board_late_init(void)
+{
+ /* Do late init to ensure successful enumeration of PCIe devices */
+ pci_init();
+ return 0;
+}
diff --git a/configs/controlcenterdc_defconfig b/configs/controlcenterdc_defconfig
index d6844a4..b6eb955 100644
--- a/configs/controlcenterdc_defconfig
+++ b/configs/controlcenterdc_defconfig
@@ -33,6 +33,7 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_BOARD_LATE_INIT=y
CONFIG_LAST_STAGE_INIT=y
+CONFIG_SPL_BOARD_INIT=y
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
CONFIG_SPL_I2C=y
CONFIG_HUSH_PARSER=y
diff --git a/configs/db-88f6720_defconfig b/configs/db-88f6720_defconfig
index 32a7349..2e8f4c0 100644
--- a/configs/db-88f6720_defconfig
+++ b/configs/db-88f6720_defconfig
@@ -11,7 +11,7 @@ CONFIG_ENV_SIZE=0x10000
CONFIG_ENV_OFFSET=0x100000
CONFIG_ENV_SECT_SIZE=0x10000
CONFIG_DEFAULT_DEVICE_TREE="armada-375-db"
-CONFIG_SPL_TEXT_BASE=0x40004030
+CONFIG_SPL_TEXT_BASE=0x40000030
CONFIG_SPL_SERIAL=y
CONFIG_SPL=y
CONFIG_DEBUG_UART_BASE=0xf1012000
diff --git a/configs/iconnect_defconfig b/configs/iconnect_defconfig
index 605b98b..1c9c77a 100644
--- a/configs/iconnect_defconfig
+++ b/configs/iconnect_defconfig
@@ -2,6 +2,7 @@ CONFIG_ARM=y
CONFIG_SKIP_LOWLEVEL_INIT=y
CONFIG_SYS_DCACHE_OFF=y
CONFIG_ARCH_CPU_INIT=y
+CONFIG_SYS_THUMB_BUILD=y
CONFIG_ARCH_KIRKWOOD=y
CONFIG_SYS_KWD_CONFIG="board/iomega/iconnect/kwbimage.cfg"
CONFIG_SYS_TEXT_BASE=0x600000
@@ -18,9 +19,11 @@ CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="setenv bootargs ${console} ${mtdparts} ${bootargs_root}; ubi part rootfs; ubifsmount ubi:rootfs; ubifsload 0x800000 ${kernel}; bootm 0x800000"
CONFIG_USE_PREBOOT=y
# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_BOARD_LATE_INIT=y
CONFIG_SYS_PROMPT="iconnect => "
# CONFIG_CMD_FLASH is not set
CONFIG_CMD_NAND=y
+CONFIG_CMD_PCI=y
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_MII=y
@@ -43,6 +46,8 @@ CONFIG_MTD=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MVGBE=y
CONFIG_MII=y
+CONFIG_PCI=y
+CONFIG_PCI_MVEBU=y
CONFIG_SYS_NS16550=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
diff --git a/drivers/ddr/marvell/a38x/ddr3_training_centralization.c b/drivers/ddr/marvell/a38x/ddr3_training_centralization.c
index 648b37e..42308b6 100644
--- a/drivers/ddr/marvell/a38x/ddr3_training_centralization.c
+++ b/drivers/ddr/marvell/a38x/ddr3_training_centralization.c
@@ -55,6 +55,7 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode)
enum hws_training_ip_stat training_result[MAX_INTERFACE_NUM];
u32 if_id, pattern_id, bit_id;
u8 bus_id;
+ u8 current_byte_status;
u8 cur_start_win[BUS_WIDTH_IN_BITS];
u8 centralization_result[MAX_INTERFACE_NUM][BUS_WIDTH_IN_BITS];
u8 cur_end_win[BUS_WIDTH_IN_BITS];
@@ -166,6 +167,10 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode)
result[search_dir_id][7]));
}
+ current_byte_status =
+ mv_ddr_tip_sub_phy_byte_status_get(if_id,
+ bus_id);
+
for (bit_id = 0; bit_id < BUS_WIDTH_IN_BITS;
bit_id++) {
/* check if this code is valid for 2 edge, probably not :( */
@@ -174,11 +179,32 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode)
[HWS_LOW2HIGH]
[bit_id],
EDGE_1);
+ if (current_byte_status &
+ BYTE_SPLIT_OUT_MIX) {
+ if (cur_start_win[bit_id] >= 64)
+ cur_start_win[bit_id] -= 64;
+ else
+ cur_start_win[bit_id] = 0;
+ DEBUG_CENTRALIZATION_ENGINE
+ (DEBUG_LEVEL_INFO,
+ ("pattern %d IF %d pup %d bit %d subtract 64 adll from start\n",
+ pattern_id, if_id, bus_id, bit_id));
+ }
cur_end_win[bit_id] =
GET_TAP_RESULT(result
[HWS_HIGH2LOW]
[bit_id],
EDGE_1);
+ if (cur_end_win[bit_id] >= 64 &&
+ (current_byte_status &
+ BYTE_SPLIT_OUT_MIX)) {
+ cur_end_win[bit_id] -= 64;
+ DEBUG_CENTRALIZATION_ENGINE
+ (DEBUG_LEVEL_INFO,
+ ("pattern %d IF %d pup %d bit %d subtract 64 adll from end\n",
+ pattern_id, if_id, bus_id, bit_id));
+ }
+
/* window length */
current_window[bit_id] =
cur_end_win[bit_id] -
diff --git a/drivers/ddr/marvell/a38x/mv_ddr_plat.c b/drivers/ddr/marvell/a38x/mv_ddr_plat.c
index faafc86..7c7bce7 100644
--- a/drivers/ddr/marvell/a38x/mv_ddr_plat.c
+++ b/drivers/ddr/marvell/a38x/mv_ddr_plat.c
@@ -167,8 +167,6 @@ static u16 a38x_vco_freq_per_sar_ref_clk_40_mhz[] = {
};
-static u32 async_mode_at_tf;
-
static u32 dq_bit_map_2_phy_pin[] = {
1, 0, 2, 6, 9, 8, 3, 7, /* 0 */
8, 9, 1, 7, 2, 6, 3, 0, /* 1 */
@@ -734,7 +732,8 @@ static int ddr3_tip_a38x_set_divider(u8 dev_num, u32 if_id,
u32 divider = 0;
u32 sar_val, ref_clk_satr;
u32 async_val;
- u32 freq = mv_ddr_freq_get(frequency);
+ u32 cpu_freq;
+ u32 ddr_freq = mv_ddr_freq_get(frequency);
if (if_id != 0) {
DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR,
@@ -751,11 +750,14 @@ static int ddr3_tip_a38x_set_divider(u8 dev_num, u32 if_id,
ref_clk_satr = reg_read(DEVICE_SAMPLE_AT_RESET2_REG);
if (((ref_clk_satr >> DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET) & 0x1) ==
DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ)
- divider = a38x_vco_freq_per_sar_ref_clk_25_mhz[sar_val] / freq;
+ cpu_freq = a38x_vco_freq_per_sar_ref_clk_25_mhz[sar_val];
else
- divider = a38x_vco_freq_per_sar_ref_clk_40_mhz[sar_val] / freq;
+ cpu_freq = a38x_vco_freq_per_sar_ref_clk_40_mhz[sar_val];
+
+ divider = cpu_freq / ddr_freq;
- if ((async_mode_at_tf == 1) && (freq > 400)) {
+ if (((cpu_freq % ddr_freq != 0) || (divider != 2 && divider != 3)) &&
+ (ddr_freq > 400)) {
/* Set async mode */
dunit_write(0x20220, 0x1000, 0x1000);
dunit_write(0xe42f4, 0x200, 0x200);
@@ -869,8 +871,6 @@ int ddr3_tip_ext_write(u32 dev_num, u32 if_id, u32 reg_addr,
int mv_ddr_early_init(void)
{
- struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
-
/* FIXME: change this configuration per ddr type
* configure a380 and a390 to work with receiver odt timing
* the odt_config is defined:
@@ -882,9 +882,6 @@ int mv_ddr_early_init(void)
mv_ddr_sw_db_init(0, 0);
- if (tm->interface_params[0].memory_freq != MV_DDR_FREQ_SAR)
- async_mode_at_tf = 1;
-
return MV_OK;
}
diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c
index 8ff58a7..3a9c9ca 100644
--- a/drivers/mtd/nand/raw/pxa3xx_nand.c
+++ b/drivers/mtd/nand/raw/pxa3xx_nand.c
@@ -1862,10 +1862,10 @@ static int pxa3xx_nand_probe_dt(struct udevice *dev, struct pxa3xx_nand_info *in
return -EINVAL;
}
- if (dev_read_bool(dev, "nand-enable-arbiter"))
+ if (dev_read_bool(dev, "marvell,nand-enable-arbiter"))
pdata->enable_arbiter = 1;
- if (dev_read_bool(dev, "nand-keep-config"))
+ if (dev_read_bool(dev, "marvell,nand-keep-config"))
pdata->keep_config = 1;
/*
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 42f8cb6..630d6e6 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -265,6 +265,7 @@ config PCI_MVEBU
bool "Enable Armada XP/38x PCIe driver"
depends on ARCH_MVEBU
select MISC
+ select DM_RESET
help
Say Y here if you want to enable PCIe controller support on
Armada XP/38x SoCs.
diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c
index 18f79d2..b3ea034 100644
--- a/drivers/pci/pci_mvebu.c
+++ b/drivers/pci/pci_mvebu.c
@@ -18,13 +18,16 @@
#include <dm/lists.h>
#include <dm/of_access.h>
#include <pci.h>
+#include <reset.h>
#include <asm/io.h>
#include <asm/arch/cpu.h>
#include <asm/arch/soc.h>
#include <linux/bitops.h>
+#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/mbus.h>
+#include <linux/sizes.h>
/* PCIe unit register offsets */
#define SELECT(x, n) ((x >> n) & 1UL)
@@ -59,6 +62,9 @@
#define PCIE_DEBUG_CTRL 0x1a60
#define PCIE_DEBUG_SOFT_RESET BIT(20)
+#define LINK_WAIT_RETRIES 100
+#define LINK_WAIT_TIMEOUT 1000
+
struct mvebu_pcie {
struct pci_controller hose;
void __iomem *base;
@@ -66,8 +72,10 @@ struct mvebu_pcie {
struct resource mem;
void __iomem *iobase;
struct resource io;
+ u32 intregs;
u32 port;
u32 lane;
+ bool is_x4;
int devfn;
u32 lane_mask;
int first_busno;
@@ -80,14 +88,6 @@ struct mvebu_pcie {
u32 cfgcache[(0x3c - 0x10) / 4];
};
-/*
- * MVEBU PCIe controller needs MEMORY and I/O BARs to be mapped
- * into SoCs address space. Each controller will map 128M of MEM
- * and 64K of I/O space when registered.
- */
-static void __iomem *mvebu_pcie_membase = (void __iomem *)MBUS_PCI_MEM_BASE;
-static void __iomem *mvebu_pcie_iobase = (void __iomem *)MBUS_PCI_IO_BASE;
-
static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie)
{
u32 val;
@@ -95,6 +95,23 @@ static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie)
return !(val & PCIE_STAT_LINK_DOWN);
}
+static void mvebu_pcie_wait_for_link(struct mvebu_pcie *pcie)
+{
+ int retries;
+
+ /* check if the link is up or not */
+ for (retries = 0; retries < LINK_WAIT_RETRIES; retries++) {
+ if (mvebu_pcie_link_up(pcie)) {
+ printf("%s: Link up\n", pcie->name);
+ return;
+ }
+
+ udelay(LINK_WAIT_TIMEOUT);
+ }
+
+ printf("%s: Link down\n", pcie->name);
+}
+
static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie *pcie, int busno)
{
u32 stat;
@@ -357,15 +374,43 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie)
pcie->base + PCIE_BAR_CTRL_OFF(1));
/* Setup BAR[0] to internal registers. */
- writel(SOC_REGS_PHY_BASE, pcie->base + PCIE_BAR_LO_OFF(0));
+ writel(pcie->intregs, pcie->base + PCIE_BAR_LO_OFF(0));
writel(0, pcie->base + PCIE_BAR_HI_OFF(0));
}
-static int mvebu_pcie_probe(struct udevice *dev)
+/* Only enable PCIe link, do not setup it */
+static int mvebu_pcie_enable_link(struct mvebu_pcie *pcie, ofnode node)
+{
+ struct reset_ctl rst;
+ int ret;
+
+ ret = reset_get_by_index_nodev(node, 0, &rst);
+ if (ret == -ENOENT) {
+ return 0;
+ } else if (ret < 0) {
+ printf("%s: cannot get reset controller: %d\n", pcie->name, ret);
+ return ret;
+ }
+
+ ret = reset_request(&rst);
+ if (ret) {
+ printf("%s: cannot request reset controller: %d\n", pcie->name, ret);
+ return ret;
+ }
+
+ ret = reset_deassert(&rst);
+ reset_free(&rst);
+ if (ret) {
+ printf("%s: cannot enable PCIe port: %d\n", pcie->name, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Setup PCIe link but do not enable it */
+static void mvebu_pcie_setup_link(struct mvebu_pcie *pcie)
{
- struct mvebu_pcie *pcie = dev_get_plat(dev);
- struct udevice *ctlr = pci_get_controller(dev);
- struct pci_controller *hose = dev_get_uclass_priv(ctlr);
u32 reg;
/* Setup PCIe controller to Root Complex mode */
@@ -374,6 +419,26 @@ static int mvebu_pcie_probe(struct udevice *dev)
writel(reg, pcie->base + PCIE_CTRL_OFF);
/*
+ * Set Maximum Link Width to X1 or X4 in Root Port's PCIe Link
+ * Capability register. This register is defined by PCIe specification
+ * as read-only but this mvebu controller has it as read-write and must
+ * be set to number of SerDes PCIe lanes (1 or 4). If this register is
+ * not set correctly then link with endpoint card is not established.
+ */
+ reg = readl(pcie->base + PCIE_CAPAB_OFF + PCI_EXP_LNKCAP);
+ reg &= ~PCI_EXP_LNKCAP_MLW;
+ reg |= (pcie->is_x4 ? 4 : 1) << 4;
+ writel(reg, pcie->base + PCIE_CAPAB_OFF + PCI_EXP_LNKCAP);
+}
+
+static int mvebu_pcie_probe(struct udevice *dev)
+{
+ struct mvebu_pcie *pcie = dev_get_plat(dev);
+ struct udevice *ctlr = pci_get_controller(dev);
+ struct pci_controller *hose = dev_get_uclass_priv(ctlr);
+ u32 reg;
+
+ /*
* Change Class Code of PCI Bridge device to PCI Bridge (0x600400)
* because default value is Memory controller (0x508000) which
* U-Boot cannot recognize as P2P Bridge.
@@ -433,26 +498,26 @@ static int mvebu_pcie_probe(struct udevice *dev)
mvebu_pcie_set_local_bus_nr(pcie, 0);
mvebu_pcie_set_local_dev_nr(pcie, 1);
- pcie->mem.start = (u32)mvebu_pcie_membase;
- pcie->mem.end = pcie->mem.start + MBUS_PCI_MEM_SIZE - 1;
- mvebu_pcie_membase += MBUS_PCI_MEM_SIZE;
-
- if (mvebu_mbus_add_window_by_id(pcie->mem_target, pcie->mem_attr,
+ if (resource_size(&pcie->mem) &&
+ mvebu_mbus_add_window_by_id(pcie->mem_target, pcie->mem_attr,
(phys_addr_t)pcie->mem.start,
resource_size(&pcie->mem))) {
- printf("PCIe unable to add mbus window for mem at %08x+%08x\n",
+ printf("%s: unable to add mbus window for mem at %08x+%08x\n",
+ pcie->name,
(u32)pcie->mem.start, (unsigned)resource_size(&pcie->mem));
+ pcie->mem.start = 0;
+ pcie->mem.end = -1;
}
- pcie->io.start = (u32)mvebu_pcie_iobase;
- pcie->io.end = pcie->io.start + MBUS_PCI_IO_SIZE - 1;
- mvebu_pcie_iobase += MBUS_PCI_IO_SIZE;
-
- if (mvebu_mbus_add_window_by_id(pcie->io_target, pcie->io_attr,
+ if (resource_size(&pcie->io) &&
+ mvebu_mbus_add_window_by_id(pcie->io_target, pcie->io_attr,
(phys_addr_t)pcie->io.start,
resource_size(&pcie->io))) {
- printf("PCIe unable to add mbus window for IO at %08x+%08x\n",
+ printf("%s: unable to add mbus window for IO at %08x+%08x\n",
+ pcie->name,
(u32)pcie->io.start, (unsigned)resource_size(&pcie->io));
+ pcie->io.start = 0;
+ pcie->io.end = -1;
}
/* Setup windows and configure host bridge */
@@ -461,13 +526,23 @@ static int mvebu_pcie_probe(struct udevice *dev)
/* PCI memory space */
pci_set_region(hose->regions + 0, pcie->mem.start,
pcie->mem.start, resource_size(&pcie->mem), PCI_REGION_MEM);
- pci_set_region(hose->regions + 1,
- 0, 0,
- gd->ram_size,
- PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
- pci_set_region(hose->regions + 2, pcie->io.start,
- pcie->io.start, resource_size(&pcie->io), PCI_REGION_IO);
- hose->region_count = 3;
+ hose->region_count = 1;
+
+ if (resource_size(&pcie->mem)) {
+ pci_set_region(hose->regions + hose->region_count,
+ pcie->mem.start, pcie->mem.start,
+ resource_size(&pcie->mem),
+ PCI_REGION_MEM);
+ hose->region_count++;
+ }
+
+ if (resource_size(&pcie->io)) {
+ pci_set_region(hose->regions + hose->region_count,
+ pcie->io.start, pcie->io.start,
+ resource_size(&pcie->io),
+ PCI_REGION_IO);
+ hose->region_count++;
+ }
/* PCI Bridge support 32-bit I/O and 64-bit prefetch mem addressing */
pcie->cfgcache[(PCI_IO_BASE - 0x10) / 4] =
@@ -475,21 +550,7 @@ static int mvebu_pcie_probe(struct udevice *dev)
pcie->cfgcache[(PCI_PREF_MEMORY_BASE - 0x10) / 4] =
PCI_PREF_RANGE_TYPE_64 | (PCI_PREF_RANGE_TYPE_64 << 16);
- return 0;
-}
-
-static int mvebu_pcie_port_parse_dt(ofnode node, struct mvebu_pcie *pcie)
-{
- const u32 *addr;
- int len;
-
- addr = ofnode_get_property(node, "assigned-addresses", &len);
- if (!addr) {
- pr_err("property \"assigned-addresses\" not found");
- return -FDT_ERR_NOTFOUND;
- }
-
- pcie->base = (void *)(fdt32_to_cpu(addr[2]) + SOC_REGS_PHY_BASE);
+ mvebu_pcie_wait_for_link(pcie);
return 0;
}
@@ -554,31 +615,38 @@ static int mvebu_get_tgt_attr(ofnode node, int devfn,
return -ENOENT;
}
-static int mvebu_pcie_of_to_plat(struct udevice *dev)
+static int mvebu_pcie_port_parse_dt(ofnode node, ofnode parent, struct mvebu_pcie *pcie)
{
- struct mvebu_pcie *pcie = dev_get_plat(dev);
+ struct fdt_pci_addr pci_addr;
+ const u32 *addr;
+ u32 num_lanes;
int ret = 0;
+ int len;
/* Get port number, lane number and memory target / attr */
- if (ofnode_read_u32(dev_ofnode(dev), "marvell,pcie-port",
+ if (ofnode_read_u32(node, "marvell,pcie-port",
&pcie->port)) {
ret = -ENODEV;
goto err;
}
- if (ofnode_read_u32(dev_ofnode(dev), "marvell,pcie-lane", &pcie->lane))
+ if (ofnode_read_u32(node, "marvell,pcie-lane", &pcie->lane))
pcie->lane = 0;
sprintf(pcie->name, "pcie%d.%d", pcie->port, pcie->lane);
- /* pci_get_devfn() returns devfn in bits 15..8, see PCI_DEV usage */
- pcie->devfn = pci_get_devfn(dev);
- if (pcie->devfn < 0) {
- ret = -ENODEV;
+ if (!ofnode_read_u32(node, "num-lanes", &num_lanes) && num_lanes == 4)
+ pcie->is_x4 = true;
+
+ /* devfn is in bits [15:8], see PCI_DEV usage */
+ ret = ofnode_read_pci_addr(node, FDT_PCI_SPACE_CONFIG, "reg", &pci_addr);
+ if (ret < 0) {
+ printf("%s: property \"reg\" is invalid\n", pcie->name);
goto err;
}
+ pcie->devfn = pci_addr.phys_hi & 0xff00;
- ret = mvebu_get_tgt_attr(dev_ofnode(dev->parent), pcie->devfn,
+ ret = mvebu_get_tgt_attr(parent, pcie->devfn,
IORESOURCE_MEM,
&pcie->mem_target, &pcie->mem_attr);
if (ret < 0) {
@@ -586,7 +654,7 @@ static int mvebu_pcie_of_to_plat(struct udevice *dev)
goto err;
}
- ret = mvebu_get_tgt_attr(dev_ofnode(dev->parent), pcie->devfn,
+ ret = mvebu_get_tgt_attr(parent, pcie->devfn,
IORESOURCE_IO,
&pcie->io_target, &pcie->io_attr);
if (ret < 0) {
@@ -595,9 +663,15 @@ static int mvebu_pcie_of_to_plat(struct udevice *dev)
}
/* Parse PCIe controller register base from DT */
- ret = mvebu_pcie_port_parse_dt(dev_ofnode(dev), pcie);
- if (ret < 0)
+ addr = ofnode_get_property(node, "assigned-addresses", &len);
+ if (!addr) {
+ printf("%s: property \"assigned-addresses\" not found\n", pcie->name);
+ ret = -FDT_ERR_NOTFOUND;
goto err;
+ }
+
+ pcie->base = (void *)(u32)ofnode_translate_address(node, addr);
+ pcie->intregs = (u32)pcie->base - fdt32_to_cpu(addr[2]);
return 0;
@@ -615,7 +689,6 @@ static struct driver pcie_mvebu_drv = {
.id = UCLASS_PCI,
.ops = &mvebu_pcie_ops,
.probe = mvebu_pcie_probe,
- .of_to_plat = mvebu_pcie_of_to_plat,
.plat_auto = sizeof(struct mvebu_pcie),
};
@@ -625,9 +698,14 @@ static struct driver pcie_mvebu_drv = {
*/
static int mvebu_pcie_bind(struct udevice *parent)
{
+ struct mvebu_pcie **ports_pcie;
struct mvebu_pcie *pcie;
struct uclass_driver *drv;
struct udevice *dev;
+ struct resource mem;
+ struct resource io;
+ int ports_count, i;
+ ofnode *ports_nodes;
ofnode subnode;
/* Lookup pci driver */
@@ -637,19 +715,94 @@ static int mvebu_pcie_bind(struct udevice *parent)
return -ENOENT;
}
+ ports_count = ofnode_get_child_count(dev_ofnode(parent));
+ ports_pcie = calloc(ports_count, sizeof(*ports_pcie));
+ ports_nodes = calloc(ports_count, sizeof(*ports_nodes));
+ if (!ports_pcie || !ports_nodes) {
+ free(ports_pcie);
+ free(ports_nodes);
+ return -ENOMEM;
+ }
+ ports_count = 0;
+
+ mem.start = MBUS_PCI_MEM_BASE;
+ mem.end = MBUS_PCI_MEM_BASE + MBUS_PCI_MEM_SIZE - 1;
+ io.start = MBUS_PCI_IO_BASE;
+ io.end = MBUS_PCI_IO_BASE + MBUS_PCI_IO_SIZE - 1;
+
+ /* First phase: Fill mvebu_pcie struct for each port */
ofnode_for_each_subnode(subnode, dev_ofnode(parent)) {
if (!ofnode_is_available(subnode))
continue;
pcie = calloc(1, sizeof(*pcie));
if (!pcie)
- return -ENOMEM;
+ continue;
+
+ if (mvebu_pcie_port_parse_dt(subnode, dev_ofnode(parent), pcie) < 0) {
+ free(pcie);
+ continue;
+ }
+
+ /*
+ * MVEBU PCIe controller needs MEMORY and I/O BARs to be mapped
+ * into SoCs address space. Each controller will map 128M of MEM
+ * and 64K of I/O space when registered.
+ */
+
+ if (resource_size(&mem) >= SZ_128M) {
+ pcie->mem.start = mem.start;
+ pcie->mem.end = mem.start + SZ_128M - 1;
+ mem.start += SZ_128M;
+ } else {
+ printf("%s: unable to assign mbus window for mem\n", pcie->name);
+ pcie->mem.start = 0;
+ pcie->mem.end = -1;
+ }
+
+ if (resource_size(&io) >= SZ_64K) {
+ pcie->io.start = io.start;
+ pcie->io.end = io.start + SZ_64K - 1;
+ io.start += SZ_64K;
+ } else {
+ printf("%s: unable to assign mbus window for io\n", pcie->name);
+ pcie->io.start = 0;
+ pcie->io.end = -1;
+ }
+
+ ports_pcie[ports_count] = pcie;
+ ports_nodes[ports_count] = subnode;
+ ports_count++;
+ }
+
+ /* Second phase: Setup all PCIe links (do not enable them yet) */
+ for (i = 0; i < ports_count; i++)
+ mvebu_pcie_setup_link(ports_pcie[i]);
+
+ /* Third phase: Enable all PCIe links and create for each UCLASS_PCI device */
+ for (i = 0; i < ports_count; i++) {
+ pcie = ports_pcie[i];
+ subnode = ports_nodes[i];
+
+ /*
+ * PCIe link can be enabled only after all PCIe links were
+ * properly configured. This is because more PCIe links shares
+ * one enable bit and some PCIe links cannot be enabled
+ * individually.
+ */
+ if (mvebu_pcie_enable_link(pcie, subnode) < 0) {
+ free(pcie);
+ continue;
+ }
/* Create child device UCLASS_PCI and bind it */
device_bind(parent, &pcie_mvebu_drv, pcie->name, pcie, subnode,
&dev);
}
+ free(ports_pcie);
+ free(ports_nodes);
+
return 0;
}
diff --git a/include/configs/clearfog.h b/include/configs/clearfog.h
index a30bca5..c9af5a4 100644
--- a/include/configs/clearfog.h
+++ b/include/configs/clearfog.h
@@ -53,7 +53,7 @@
/* Defines for SPL */
#define CONFIG_SPL_SIZE (140 << 10)
-#define CONFIG_SPL_MAX_SIZE (CONFIG_SPL_SIZE - 0x0030)
+#define CONFIG_SPL_MAX_SIZE (CONFIG_SPL_SIZE - (CONFIG_SPL_TEXT_BASE - 0x40000000))
#define CONFIG_SPL_BSS_START_ADDR (0x40000000 + CONFIG_SPL_SIZE)
#define CONFIG_SPL_BSS_MAX_SIZE (16 << 10)
diff --git a/include/configs/db-88f6720.h b/include/configs/db-88f6720.h
index 19fc669..16c83a8 100644
--- a/include/configs/db-88f6720.h
+++ b/include/configs/db-88f6720.h
@@ -32,22 +32,9 @@
*/
#include "mv-common.h"
-/*
- * Memory layout while starting into the bin_hdr via the
- * BootROM:
- *
- * 0x4000.4000 - 0x4003.4000 headers space (192KiB)
- * 0x4000.4030 bin_hdr start address
- * 0x4003.4000 - 0x4004.7c00 BootROM memory allocations (15KiB)
- * 0x4007.fffc BootROM stack top
- *
- * The address space between 0x4007.fffc and 0x400f.fff is not locked in
- * L2 cache thus cannot be used.
- */
-
/* SPL */
/* Defines for SPL */
-#define CONFIG_SPL_MAX_SIZE ((128 << 10) - 0x4030)
+#define CONFIG_SPL_MAX_SIZE ((128 << 10) - (CONFIG_SPL_TEXT_BASE - 0x40000000))
#define CONFIG_SPL_BSS_START_ADDR (0x40000000 + (128 << 10))
#define CONFIG_SPL_BSS_MAX_SIZE (16 << 10)
diff --git a/include/configs/db-88f6820-amc.h b/include/configs/db-88f6820-amc.h
index 1f70c60..6538e66 100644
--- a/include/configs/db-88f6820-amc.h
+++ b/include/configs/db-88f6820-amc.h
@@ -41,7 +41,7 @@
/* Defines for SPL */
#define CONFIG_SPL_SIZE (140 << 10)
-#define CONFIG_SPL_MAX_SIZE (CONFIG_SPL_SIZE - 0x0030)
+#define CONFIG_SPL_MAX_SIZE (CONFIG_SPL_SIZE - (CONFIG_SPL_TEXT_BASE - 0x40000000))
#define CONFIG_SPL_BSS_START_ADDR (0x40000000 + CONFIG_SPL_SIZE)
#define CONFIG_SPL_BSS_MAX_SIZE (16 << 10)
diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h
index 41dadfe..5f26119 100644
--- a/include/configs/db-88f6820-gp.h
+++ b/include/configs/db-88f6820-gp.h
@@ -50,7 +50,7 @@
/* Defines for SPL */
#define CONFIG_SPL_SIZE (140 << 10)
-#define CONFIG_SPL_MAX_SIZE (CONFIG_SPL_SIZE - 0x0030)
+#define CONFIG_SPL_MAX_SIZE (CONFIG_SPL_SIZE - (CONFIG_SPL_TEXT_BASE - 0x40000000))
#define CONFIG_SPL_BSS_START_ADDR (0x40000000 + CONFIG_SPL_SIZE)
#define CONFIG_SPL_BSS_MAX_SIZE (16 << 10)
diff --git a/include/configs/db-mv784mp-gp.h b/include/configs/db-mv784mp-gp.h
index dbbc33e..449a567 100644
--- a/include/configs/db-mv784mp-gp.h
+++ b/include/configs/db-mv784mp-gp.h
@@ -59,7 +59,7 @@
/* SPL */
/* Defines for SPL */
-#define CONFIG_SPL_MAX_SIZE ((128 << 10) - 0x4030)
+#define CONFIG_SPL_MAX_SIZE ((128 << 10) - (CONFIG_SPL_TEXT_BASE - 0x40000000))
#define CONFIG_SPL_BSS_START_ADDR (0x40000000 + (128 << 10))
#define CONFIG_SPL_BSS_MAX_SIZE (16 << 10)
diff --git a/include/configs/ds414.h b/include/configs/ds414.h
index 7fba2b4..dbccd46 100644
--- a/include/configs/ds414.h
+++ b/include/configs/ds414.h
@@ -45,7 +45,7 @@
/* SPL */
/* Defines for SPL */
-#define CONFIG_SPL_MAX_SIZE ((128 << 10) - 0x4030)
+#define CONFIG_SPL_MAX_SIZE ((128 << 10) - (CONFIG_SPL_TEXT_BASE - 0x40000000))
#define CONFIG_SPL_BSS_START_ADDR (0x40000000 + (128 << 10))
#define CONFIG_SPL_BSS_MAX_SIZE (16 << 10)
diff --git a/include/configs/helios4.h b/include/configs/helios4.h
index 56d35d6..de1ebbf 100644
--- a/include/configs/helios4.h
+++ b/include/configs/helios4.h
@@ -53,7 +53,7 @@
/* Defines for SPL */
#define CONFIG_SPL_SIZE (140 << 10)
-#define CONFIG_SPL_MAX_SIZE (CONFIG_SPL_SIZE - 0x0030)
+#define CONFIG_SPL_MAX_SIZE (CONFIG_SPL_SIZE - (CONFIG_SPL_TEXT_BASE - 0x40000000))
#define CONFIG_SPL_BSS_START_ADDR (0x40000000 + CONFIG_SPL_SIZE)
#define CONFIG_SPL_BSS_MAX_SIZE (16 << 10)
diff --git a/include/configs/maxbcm.h b/include/configs/maxbcm.h
index 53ba649..073c5a5 100644
--- a/include/configs/maxbcm.h
+++ b/include/configs/maxbcm.h
@@ -48,7 +48,7 @@
/* SPL */
/* Defines for SPL */
-#define CONFIG_SPL_MAX_SIZE ((128 << 10) - 0x4030)
+#define CONFIG_SPL_MAX_SIZE ((128 << 10) - (CONFIG_SPL_TEXT_BASE - 0x40000000))
#define CONFIG_SPL_BSS_START_ADDR (0x40000000 + (128 << 10))
#define CONFIG_SPL_BSS_MAX_SIZE (16 << 10)
diff --git a/include/configs/theadorable.h b/include/configs/theadorable.h
index b43c03d..3c942cc 100644
--- a/include/configs/theadorable.h
+++ b/include/configs/theadorable.h
@@ -77,7 +77,7 @@
/* SPL */
/* Defines for SPL */
-#define CONFIG_SPL_MAX_SIZE ((128 << 10) - 0x4030)
+#define CONFIG_SPL_MAX_SIZE ((128 << 10) - (CONFIG_SPL_TEXT_BASE - 0x40000000))
#define CONFIG_SPL_BSS_START_ADDR (0x40000000 + (128 << 10))
#define CONFIG_SPL_BSS_MAX_SIZE (16 << 10)
diff --git a/include/configs/turris_omnia.h b/include/configs/turris_omnia.h
index 9436a62..b35299b 100644
--- a/include/configs/turris_omnia.h
+++ b/include/configs/turris_omnia.h
@@ -28,7 +28,7 @@
/* Defines for SPL */
#define CONFIG_SPL_SIZE (140 << 10)
-#define CONFIG_SPL_MAX_SIZE (CONFIG_SPL_SIZE - 0x0030)
+#define CONFIG_SPL_MAX_SIZE (CONFIG_SPL_SIZE - (CONFIG_SPL_TEXT_BASE - 0x40000000))
#define CONFIG_SPL_BSS_START_ADDR (0x40000000 + CONFIG_SPL_SIZE)
#define CONFIG_SPL_BSS_MAX_SIZE (16 << 10)
diff --git a/include/configs/x530.h b/include/configs/x530.h
index e78e249..67ff01d 100644
--- a/include/configs/x530.h
+++ b/include/configs/x530.h
@@ -68,7 +68,7 @@
/* Defines for SPL */
#define CONFIG_SPL_SIZE (140 << 10)
-#define CONFIG_SPL_MAX_SIZE (CONFIG_SPL_SIZE - 0x0030)
+#define CONFIG_SPL_MAX_SIZE (CONFIG_SPL_SIZE - (CONFIG_SPL_TEXT_BASE - 0x40000000))
#define CONFIG_SPL_BSS_START_ADDR (0x40000000 + CONFIG_SPL_SIZE)
#define CONFIG_SPL_BSS_MAX_SIZE (16 << 10)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index 224d815..9b63ce8 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -99,6 +99,7 @@ enum image_cfg_type {
IMAGE_CFG_NAND_BADBLK_LOCATION,
IMAGE_CFG_NAND_ECC_MODE,
IMAGE_CFG_NAND_PAGESZ,
+ IMAGE_CFG_CPU,
IMAGE_CFG_BINARY,
IMAGE_CFG_DATA,
IMAGE_CFG_DATA_DELAY,
@@ -129,6 +130,7 @@ static const char * const id_strs[] = {
[IMAGE_CFG_NAND_BADBLK_LOCATION] = "NAND_BADBLK_LOCATION",
[IMAGE_CFG_NAND_ECC_MODE] = "NAND_ECC_MODE",
[IMAGE_CFG_NAND_PAGESZ] = "NAND_PAGE_SIZE",
+ [IMAGE_CFG_CPU] = "CPU",
[IMAGE_CFG_BINARY] = "BINARY",
[IMAGE_CFG_DATA] = "DATA",
[IMAGE_CFG_DATA_DELAY] = "DATA_DELAY",
@@ -152,9 +154,11 @@ struct image_cfg_element {
enum image_cfg_type type;
union {
unsigned int version;
+ unsigned int cpu_sheeva;
unsigned int bootfrom;
struct {
const char *file;
+ unsigned int loadaddr;
unsigned int args[BINARY_MAX_ARGS];
unsigned int nargs;
} binary;
@@ -199,7 +203,7 @@ static const char *image_boot_mode_name(unsigned int id)
return NULL;
}
-int image_boot_mode_id(const char *boot_mode_name)
+static int image_boot_mode_id(const char *boot_mode_name)
{
int i;
@@ -210,7 +214,18 @@ int image_boot_mode_id(const char *boot_mode_name)
return -1;
}
-int image_nand_ecc_mode_id(const char *nand_ecc_mode_name)
+static const char *image_nand_ecc_mode_name(unsigned int id)
+{
+ int i;
+
+ for (i = 0; nand_ecc_modes[i].name; i++)
+ if (nand_ecc_modes[i].id == id)
+ return nand_ecc_modes[i].name;
+
+ return NULL;
+}
+
+static int image_nand_ecc_mode_id(const char *nand_ecc_mode_name)
{
int i;
@@ -280,6 +295,17 @@ static int image_get_bootfrom(void)
return e->bootfrom;
}
+static int image_is_cpu_sheeva(void)
+{
+ struct image_cfg_element *e;
+
+ e = image_find_option(IMAGE_CFG_CPU);
+ if (!e)
+ return 0;
+
+ return e->cpu_sheeva;
+}
+
/*
* Compute a 8-bit checksum of a memory area. This algorithm follows
* the requirements of the Marvell SoC BootROM specifications.
@@ -344,6 +370,29 @@ static uint32_t image_checksum32(void *start, uint32_t len)
return csum;
}
+static unsigned int options_to_baudrate(uint8_t options)
+{
+ switch (options & 0x7) {
+ case MAIN_HDR_V1_OPT_BAUD_2400:
+ return 2400;
+ case MAIN_HDR_V1_OPT_BAUD_4800:
+ return 4800;
+ case MAIN_HDR_V1_OPT_BAUD_9600:
+ return 9600;
+ case MAIN_HDR_V1_OPT_BAUD_19200:
+ return 19200;
+ case MAIN_HDR_V1_OPT_BAUD_38400:
+ return 38400;
+ case MAIN_HDR_V1_OPT_BAUD_57600:
+ return 57600;
+ case MAIN_HDR_V1_OPT_BAUD_115200:
+ return 115200;
+ case MAIN_HDR_V1_OPT_BAUD_DEFAULT:
+ default:
+ return 0;
+ }
+}
+
static uint8_t baudrate_to_option(unsigned int baudrate)
{
switch (baudrate) {
@@ -602,7 +651,8 @@ static int kwb_export_pubkey(RSA *key, struct pubkey_der_v1 *dst, FILE *hashf,
return 0;
}
-int kwb_sign(RSA *key, void *data, int datasz, struct sig_v1 *sig, char *signame)
+static int kwb_sign(RSA *key, void *data, int datasz, struct sig_v1 *sig,
+ char *signame)
{
EVP_PKEY *evp_key;
EVP_MD_CTX *ctx;
@@ -662,8 +712,8 @@ err_key:
return ret;
}
-int kwb_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
- char *signame)
+static int kwb_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
+ char *signame)
{
EVP_PKEY *evp_key;
EVP_MD_CTX *ctx;
@@ -722,8 +772,8 @@ err_key:
return ret;
}
-int kwb_sign_and_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
- char *signame)
+static int kwb_sign_and_verify(RSA *key, void *data, int datasz,
+ struct sig_v1 *sig, char *signame)
{
if (kwb_sign(key, data, datasz, sig, signame) < 0)
return -1;
@@ -735,7 +785,7 @@ int kwb_sign_and_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
}
-int kwb_dump_fuse_cmds_38x(FILE *out, struct secure_hdr_v1 *sec_hdr)
+static int kwb_dump_fuse_cmds_38x(FILE *out, struct secure_hdr_v1 *sec_hdr)
{
struct hash_v1 kak_pub_hash;
struct image_cfg_element *e;
@@ -992,10 +1042,13 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
static size_t image_headersz_v1(int *hasext)
{
- struct image_cfg_element *binarye;
+ struct image_cfg_element *e;
unsigned int count;
size_t headersz;
+ int cpu_sheeva;
+ struct stat s;
int cfgi;
+ int ret;
/*
* Calculate the size of the header and the size of the
@@ -1009,19 +1062,25 @@ static size_t image_headersz_v1(int *hasext)
*hasext = 1;
}
- count = image_count_options(IMAGE_CFG_DATA);
- if (count > 0)
- headersz += sizeof(struct register_set_hdr_v1) + 8 * count + 4;
+ cpu_sheeva = image_is_cpu_sheeva();
+ count = 0;
for (cfgi = 0; cfgi < cfgn; cfgi++) {
- int ret;
- struct stat s;
+ e = &image_cfg[cfgi];
- binarye = &image_cfg[cfgi];
- if (binarye->type != IMAGE_CFG_BINARY)
+ if (e->type == IMAGE_CFG_DATA)
+ count++;
+
+ if (e->type == IMAGE_CFG_DATA_DELAY ||
+ (e->type == IMAGE_CFG_BINARY && count > 0)) {
+ headersz += sizeof(struct register_set_hdr_v1) + 8 * count + 4;
+ count = 0;
+ }
+
+ if (e->type != IMAGE_CFG_BINARY)
continue;
- ret = stat(binarye->binary.file, &s);
+ ret = stat(e->binary.file, &s);
if (ret < 0) {
char cwd[PATH_MAX];
char *dir = cwd;
@@ -1036,30 +1095,74 @@ static size_t image_headersz_v1(int *hasext)
"Didn't find the file '%s' in '%s' which is mandatory to generate the image\n"
"This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n"
"image for your board. Use 'dumpimage -T kwbimage -p 0' to extract it from an existing image.\n",
- binarye->binary.file, dir);
+ e->binary.file, dir);
return 0;
}
headersz += sizeof(struct opt_hdr_v1) + sizeof(uint32_t) +
- (binarye->binary.nargs) * sizeof(uint32_t);
- headersz = ALIGN(headersz, 16);
+ (e->binary.nargs) * sizeof(uint32_t);
+
+ if (e->binary.loadaddr) {
+ /*
+ * BootROM loads kwbimage header (in which the
+ * executable code is also stored) to address
+ * 0x40004000 or 0x40000000. Thus there is
+ * restriction for the load address of the N-th
+ * BINARY image.
+ */
+ unsigned int base_addr, low_addr, high_addr;
+
+ base_addr = cpu_sheeva ? 0x40004000 : 0x40000000;
+ low_addr = base_addr + headersz;
+ high_addr = low_addr +
+ (BINARY_MAX_ARGS - e->binary.nargs) * sizeof(uint32_t);
+
+ if (cpu_sheeva && e->binary.loadaddr % 16) {
+ fprintf(stderr,
+ "Invalid LOAD_ADDRESS 0x%08x for BINARY %s with %d args.\n"
+ "Address for CPU SHEEVA must be 16-byte aligned.\n",
+ e->binary.loadaddr, e->binary.file, e->binary.nargs);
+ return 0;
+ }
+
+ if (e->binary.loadaddr % 4 || e->binary.loadaddr < low_addr ||
+ e->binary.loadaddr > high_addr) {
+ fprintf(stderr,
+ "Invalid LOAD_ADDRESS 0x%08x for BINARY %s with %d args.\n"
+ "Address must be 4-byte aligned and in range 0x%08x-0x%08x.\n",
+ e->binary.loadaddr, e->binary.file,
+ e->binary.nargs, low_addr, high_addr);
+ return 0;
+ }
+ headersz = e->binary.loadaddr - base_addr;
+ } else if (cpu_sheeva) {
+ headersz = ALIGN(headersz, 16);
+ } else {
+ headersz = ALIGN(headersz, 4);
+ }
+
headersz += ALIGN(s.st_size, 4) + sizeof(uint32_t);
if (hasext)
*hasext = 1;
}
+ if (count > 0)
+ headersz += sizeof(struct register_set_hdr_v1) + 8 * count + 4;
+
return image_headersz_align(headersz, image_get_bootfrom());
}
-int add_binary_header_v1(uint8_t **cur, uint8_t **next_ext,
- struct image_cfg_element *binarye,
- struct main_hdr_v1 *main_hdr)
+static int add_binary_header_v1(uint8_t **cur, uint8_t **next_ext,
+ struct image_cfg_element *binarye,
+ struct main_hdr_v1 *main_hdr)
{
struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)*cur;
+ uint32_t base_addr;
uint32_t add_args;
uint32_t offset;
uint32_t *args;
size_t binhdrsz;
+ int cpu_sheeva;
struct stat s;
int argi;
FILE *bin;
@@ -1091,13 +1194,22 @@ int add_binary_header_v1(uint8_t **cur, uint8_t **next_ext,
*cur += (binarye->binary.nargs + 1) * sizeof(uint32_t);
/*
- * ARM executable code inside the BIN header on some mvebu platforms
- * (e.g. A370, AXP) must always be aligned with the 128-bit boundary.
+ * ARM executable code inside the BIN header on platforms with Sheeva
+ * CPU (A370 and AXP) must always be aligned with the 128-bit boundary.
+ * In the case when this code is not position independent (e.g. ARM
+ * SPL), it must be placed at fixed load and execute address.
* This requirement can be met by inserting dummy arguments into
* BIN header, if needed.
*/
+ cpu_sheeva = image_is_cpu_sheeva();
+ base_addr = cpu_sheeva ? 0x40004000 : 0x40000000;
offset = *cur - (uint8_t *)main_hdr;
- add_args = ((16 - offset % 16) % 16) / sizeof(uint32_t);
+ if (binarye->binary.loadaddr)
+ add_args = (binarye->binary.loadaddr - base_addr - offset) / sizeof(uint32_t);
+ else if (cpu_sheeva)
+ add_args = ((16 - offset % 16) % 16) / sizeof(uint32_t);
+ else
+ add_args = 0;
if (add_args) {
*(args - 1) = cpu_to_le32(binarye->binary.nargs + add_args);
*cur += add_args * sizeof(uint32_t);
@@ -1135,7 +1247,7 @@ err_close:
return -1;
}
-int export_pub_kak_hash(RSA *kak, struct secure_hdr_v1 *secure_hdr)
+static int export_pub_kak_hash(RSA *kak, struct secure_hdr_v1 *secure_hdr)
{
FILE *hashf;
int res;
@@ -1154,8 +1266,8 @@ int export_pub_kak_hash(RSA *kak, struct secure_hdr_v1 *secure_hdr)
return res < 0 ? 1 : 0;
}
-int kwb_sign_csk_with_kak(struct image_tool_params *params,
- struct secure_hdr_v1 *secure_hdr, RSA *csk)
+static int kwb_sign_csk_with_kak(struct image_tool_params *params,
+ struct secure_hdr_v1 *secure_hdr, RSA *csk)
{
RSA *kak = NULL;
RSA *kak_pub = NULL;
@@ -1196,9 +1308,9 @@ int kwb_sign_csk_with_kak(struct image_tool_params *params,
return 0;
}
-int add_secure_header_v1(struct image_tool_params *params, uint8_t *ptr,
- int payloadsz, size_t headersz, uint8_t *image,
- struct secure_hdr_v1 *secure_hdr)
+static int add_secure_header_v1(struct image_tool_params *params, uint8_t *ptr,
+ int payloadsz, size_t headersz, uint8_t *image,
+ struct secure_hdr_v1 *secure_hdr)
{
struct image_cfg_element *e_jtagdelay;
struct image_cfg_element *e_boxid;
@@ -1248,6 +1360,22 @@ int add_secure_header_v1(struct image_tool_params *params, uint8_t *ptr,
return 0;
}
+static void finish_register_set_header_v1(uint8_t **cur, uint8_t **next_ext,
+ struct register_set_hdr_v1 *register_set_hdr,
+ int *datai, uint8_t delay)
+{
+ int size = sizeof(struct register_set_hdr_v1) + 8 * (*datai) + 4;
+
+ register_set_hdr->headertype = OPT_HDR_V1_REGISTER_TYPE;
+ register_set_hdr->headersz_lsb = cpu_to_le16(size & 0xFFFF);
+ register_set_hdr->headersz_msb = size >> 16;
+ register_set_hdr->data[*datai].last_entry.delay = delay;
+ *cur += size;
+ **next_ext = 1;
+ *next_ext = &register_set_hdr->data[*datai].last_entry.next;
+ *datai = 0;
+}
+
static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
uint8_t *ptr, int payloadsz)
{
@@ -1260,7 +1388,8 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
uint8_t *image, *cur;
int hasext = 0;
uint8_t *next_ext = NULL;
- int cfgi, datai, size;
+ int cfgi, datai;
+ uint8_t delay;
/*
* Calculate the size of the header and the size of the
@@ -1351,49 +1480,53 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
}
datai = 0;
- register_set_hdr = (struct register_set_hdr_v1 *)cur;
for (cfgi = 0; cfgi < cfgn; cfgi++) {
e = &image_cfg[cfgi];
if (e->type != IMAGE_CFG_DATA &&
- e->type != IMAGE_CFG_DATA_DELAY)
- continue;
- if (e->type == IMAGE_CFG_DATA_DELAY) {
- size = sizeof(struct register_set_hdr_v1) + 8 * datai + 4;
- register_set_hdr->headertype = OPT_HDR_V1_REGISTER_TYPE;
- register_set_hdr->headersz_lsb = cpu_to_le16(size & 0xFFFF);
- register_set_hdr->headersz_msb = size >> 16;
- register_set_hdr->data[datai].last_entry.delay = e->regdata_delay;
- cur += size;
- *next_ext = 1;
- next_ext = &register_set_hdr->data[datai].last_entry.next;
- datai = 0;
+ e->type != IMAGE_CFG_DATA_DELAY &&
+ e->type != IMAGE_CFG_BINARY)
continue;
+
+ if (datai == 0)
+ register_set_hdr = (struct register_set_hdr_v1 *)cur;
+
+ /* If delay is not specified, use the smallest possible value. */
+ if (e->type == IMAGE_CFG_DATA_DELAY)
+ delay = e->regdata_delay;
+ else
+ delay = REGISTER_SET_HDR_OPT_DELAY_MS(0);
+
+ /*
+ * DATA_DELAY command is the last entry in the register set
+ * header and BINARY command inserts new binary header.
+ * Therefore BINARY command requires to finish register set
+ * header if some DATA command was specified. And DATA_DELAY
+ * command automatically finish register set header even when
+ * there was no DATA command.
+ */
+ if (e->type == IMAGE_CFG_DATA_DELAY ||
+ (e->type == IMAGE_CFG_BINARY && datai != 0))
+ finish_register_set_header_v1(&cur, &next_ext, register_set_hdr,
+ &datai, delay);
+
+ if (e->type == IMAGE_CFG_DATA) {
+ register_set_hdr->data[datai].entry.address =
+ cpu_to_le32(e->regdata.raddr);
+ register_set_hdr->data[datai].entry.value =
+ cpu_to_le32(e->regdata.rdata);
+ datai++;
+ }
+
+ if (e->type == IMAGE_CFG_BINARY) {
+ if (add_binary_header_v1(&cur, &next_ext, e, main_hdr))
+ return NULL;
}
- register_set_hdr->data[datai].entry.address =
- cpu_to_le32(e->regdata.raddr);
- register_set_hdr->data[datai].entry.value =
- cpu_to_le32(e->regdata.rdata);
- datai++;
}
if (datai != 0) {
- size = sizeof(struct register_set_hdr_v1) + 8 * datai + 4;
- register_set_hdr->headertype = OPT_HDR_V1_REGISTER_TYPE;
- register_set_hdr->headersz_lsb = cpu_to_le16(size & 0xFFFF);
- register_set_hdr->headersz_msb = size >> 16;
- /* Set delay to the smallest possible value 1ms. */
- register_set_hdr->data[datai].last_entry.delay = 1;
- cur += size;
- *next_ext = 1;
- next_ext = &register_set_hdr->data[datai].last_entry.next;
- }
-
- for (cfgi = 0; cfgi < cfgn; cfgi++) {
- e = &image_cfg[cfgi];
- if (e->type != IMAGE_CFG_BINARY)
- continue;
-
- if (add_binary_header_v1(&cur, &next_ext, e, main_hdr))
- return NULL;
+ /* Set delay to the smallest possible value. */
+ delay = REGISTER_SET_HDR_OPT_DELAY_MS(0);
+ finish_register_set_header_v1(&cur, &next_ext, register_set_hdr,
+ &datai, delay);
}
if (secure_hdr && add_secure_header_v1(params, ptr, payloadsz + headersz,
@@ -1415,7 +1548,7 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
return image;
}
-int recognize_keyword(char *keyword)
+static int recognize_keyword(char *keyword)
{
int kw_id;
@@ -1455,6 +1588,18 @@ static int image_create_config_parse_oneline(char *line,
case IMAGE_CFG_VERSION:
el->version = atoi(value1);
break;
+ case IMAGE_CFG_CPU:
+ if (strcmp(value1, "FEROCEON") == 0)
+ el->cpu_sheeva = 0;
+ else if (strcmp(value1, "SHEEVA") == 0)
+ el->cpu_sheeva = 1;
+ else if (strcmp(value1, "A9") == 0)
+ el->cpu_sheeva = 0;
+ else {
+ fprintf(stderr, "Invalid CPU %s\n", value1);
+ return -1;
+ }
+ break;
case IMAGE_CFG_BOOT_FROM:
ret = image_boot_mode_id(value1);
@@ -1488,10 +1633,40 @@ static int image_create_config_parse_oneline(char *line,
el->binary.file = strdup(value1);
while (1) {
char *value = strtok_r(NULL, delimiters, &saveptr);
+ char *endptr;
if (!value)
break;
- el->binary.args[argi] = strtoul(value, NULL, 16);
+
+ if (!strcmp(value, "LOAD_ADDRESS")) {
+ value = strtok_r(NULL, delimiters, &saveptr);
+ if (!value) {
+ fprintf(stderr,
+ "Missing address argument for BINARY LOAD_ADDRESS\n");
+ return -1;
+ }
+ el->binary.loadaddr = strtoul(value, &endptr, 16);
+ if (*endptr) {
+ fprintf(stderr,
+ "Invalid argument '%s' for BINARY LOAD_ADDRESS\n",
+ value);
+ return -1;
+ }
+ value = strtok_r(NULL, delimiters, &saveptr);
+ if (value) {
+ fprintf(stderr,
+ "Unexpected argument '%s' after BINARY LOAD_ADDRESS\n",
+ value);
+ return -1;
+ }
+ break;
+ }
+
+ el->binary.args[argi] = strtoul(value, &endptr, 16);
+ if (*endptr) {
+ fprintf(stderr, "Invalid argument '%s' for BINARY\n", value);
+ return -1;
+ }
argi++;
if (argi >= BINARY_MAX_ARGS) {
fprintf(stderr,
@@ -1518,6 +1693,10 @@ static int image_create_config_parse_oneline(char *line,
el->regdata_delay = REGISTER_SET_HDR_OPT_DELAY_SDRAM_SETUP;
else
el->regdata_delay = REGISTER_SET_HDR_OPT_DELAY_MS(strtoul(value1, NULL, 10));
+ if (el->regdata_delay > 255) {
+ fprintf(stderr, "Maximal DATA_DELAY is 255\n");
+ return -1;
+ }
break;
case IMAGE_CFG_BAUDRATE:
el->baudrate = strtoul(value1, NULL, 10);
@@ -1727,9 +1906,12 @@ static void kwbimage_print_header(const void *ptr)
for_each_opt_hdr_v1 (ohdr, mhdr) {
if (ohdr->headertype == OPT_HDR_V1_BINARY_TYPE) {
- printf("BIN Hdr Size: ");
+ printf("BIN Img Size: ");
genimg_print_size(opt_hdr_v1_size(ohdr) - 12 -
4 * ohdr->data[0]);
+ printf("BIN Img Offs: %08x\n",
+ (unsigned)((uint8_t *)ohdr - (uint8_t *)mhdr) +
+ 8 + 4 * ohdr->data[0]);
}
}
@@ -1766,7 +1948,7 @@ static int kwbimage_verify_header(unsigned char *ptr, int image_size,
if (kwbimage_version(ptr) == 0) {
struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
- if (mhdr->ext & 0x1) {
+ if (mhdr->ext) {
struct ext_hdr_v0 *ext_hdr = (void *)(mhdr + 1);
csum = image_checksum8(ext_hdr, sizeof(*ext_hdr) - 1);
@@ -1892,6 +2074,15 @@ static int kwbimage_generate(struct image_tool_params *params,
case 1:
alloc_len = image_headersz_v1(NULL);
+ if (!alloc_len) {
+ free(image_cfg);
+ exit(EXIT_FAILURE);
+ }
+ if (alloc_len > 192*1024) {
+ fprintf(stderr, "Header is too big (%u bytes), maximal kwbimage header size is %u bytes\n", alloc_len, 192*1024);
+ free(image_cfg);
+ exit(EXIT_FAILURE);
+ }
break;
default:
@@ -1931,52 +2122,207 @@ static int kwbimage_generate(struct image_tool_params *params,
return 4 + (4 - s.st_size % 4) % 4;
}
+static int kwbimage_generate_config(void *ptr, struct image_tool_params *params)
+{
+ struct main_hdr_v0 *mhdr0 = (struct main_hdr_v0 *)ptr;
+ struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
+ size_t header_size = kwbheader_size(ptr);
+ struct register_set_hdr_v1 *regset_hdr;
+ struct ext_hdr_v0_reg *regdata;
+ struct ext_hdr_v0 *ehdr0;
+ struct opt_hdr_v1 *ohdr;
+ unsigned offset;
+ int cur_idx;
+ int version;
+ FILE *f;
+ int i;
+
+ f = fopen(params->outfile, "w");
+ if (!f) {
+ fprintf(stderr, "Can't open \"%s\": %s\n", params->outfile, strerror(errno));
+ return -1;
+ }
+
+ version = kwbimage_version(ptr);
+
+ if (version != 0)
+ fprintf(f, "VERSION %d\n", version);
+
+ fprintf(f, "BOOT_FROM %s\n", image_boot_mode_name(mhdr->blockid) ?: "<unknown>");
+
+ if (version == 0 && mhdr->blockid == IBR_HDR_NAND_ID)
+ fprintf(f, "NAND_ECC_MODE %s\n", image_nand_ecc_mode_name(mhdr0->nandeccmode));
+
+ if (mhdr->blockid == IBR_HDR_NAND_ID)
+ fprintf(f, "NAND_PAGE_SIZE 0x%x\n", (unsigned)mhdr->nandpagesize);
+
+ if (version != 0 && mhdr->blockid == IBR_HDR_NAND_ID) {
+ fprintf(f, "NAND_BLKSZ 0x%x\n", (unsigned)mhdr->nandblocksize);
+ fprintf(f, "NAND_BADBLK_LOCATION 0x%x\n", (unsigned)mhdr->nandbadblklocation);
+ }
+
+ if (version == 0 && mhdr->blockid == IBR_HDR_SATA_ID)
+ fprintf(f, "SATA_PIO_MODE %u\n", (unsigned)mhdr0->satapiomode);
+
+ /*
+ * Addresses and sizes which are specified by mkimage command line
+ * arguments and not in kwbimage config file
+ */
+
+ if (version != 0)
+ fprintf(f, "#HEADER_SIZE 0x%x\n",
+ ((unsigned)mhdr->headersz_msb << 8) | le16_to_cpu(mhdr->headersz_lsb));
+
+ fprintf(f, "#SRC_ADDRESS 0x%x\n", le32_to_cpu(mhdr->srcaddr));
+ fprintf(f, "#BLOCK_SIZE 0x%x\n", le32_to_cpu(mhdr->blocksize));
+ fprintf(f, "#DEST_ADDRESS 0x%08x\n", le32_to_cpu(mhdr->destaddr));
+ fprintf(f, "#EXEC_ADDRESS 0x%08x\n", le32_to_cpu(mhdr->execaddr));
+
+ if (version != 0) {
+ if (options_to_baudrate(mhdr->options))
+ fprintf(f, "BAUDRATE %u\n", options_to_baudrate(mhdr->options));
+ if (options_to_baudrate(mhdr->options) ||
+ ((mhdr->options >> 3) & 0x3) || ((mhdr->options >> 5) & 0x7)) {
+ fprintf(f, "UART_PORT %u\n", (unsigned)((mhdr->options >> 3) & 0x3));
+ fprintf(f, "UART_MPP 0x%x\n", (unsigned)((mhdr->options >> 5) & 0x7));
+ }
+ if (mhdr->flags & 0x1)
+ fprintf(f, "DEBUG 1\n");
+ }
+
+ cur_idx = 1;
+ for_each_opt_hdr_v1(ohdr, ptr) {
+ if (ohdr->headertype == OPT_HDR_V1_SECURE_TYPE) {
+ fprintf(f, "#SECURE_HEADER\n");
+ } else if (ohdr->headertype == OPT_HDR_V1_BINARY_TYPE) {
+ fprintf(f, "BINARY binary%d.bin", cur_idx);
+ for (i = 0; i < ohdr->data[0]; i++)
+ fprintf(f, " 0x%x", le32_to_cpu(((uint32_t *)ohdr->data)[i + 1]));
+ offset = (unsigned)((uint8_t *)ohdr - (uint8_t *)mhdr) + 8 + 4 * ohdr->data[0];
+ fprintf(f, " LOAD_ADDRESS 0x%08x\n", 0x40000000 + offset);
+ fprintf(f, " # for CPU SHEEVA: LOAD_ADDRESS 0x%08x\n", 0x40004000 + offset);
+ cur_idx++;
+ } else if (ohdr->headertype == OPT_HDR_V1_REGISTER_TYPE) {
+ regset_hdr = (struct register_set_hdr_v1 *)ohdr;
+ for (i = 0;
+ i < opt_hdr_v1_size(ohdr) - sizeof(struct opt_hdr_v1) -
+ sizeof(regset_hdr->data[0].last_entry);
+ i++)
+ fprintf(f, "DATA 0x%08x 0x%08x\n",
+ le32_to_cpu(regset_hdr->data[i].entry.address),
+ le32_to_cpu(regset_hdr->data[i].entry.value));
+ if (opt_hdr_v1_size(ohdr) - sizeof(struct opt_hdr_v1) >=
+ sizeof(regset_hdr->data[0].last_entry)) {
+ if (regset_hdr->data[0].last_entry.delay)
+ fprintf(f, "DATA_DELAY %u\n",
+ (unsigned)regset_hdr->data[0].last_entry.delay);
+ else
+ fprintf(f, "DATA_DELAY SDRAM_SETUP\n");
+ }
+ }
+ }
+
+ if (version == 0 && mhdr0->ext) {
+ ehdr0 = (struct ext_hdr_v0 *)(mhdr0 + 1);
+ if (ehdr0->offset) {
+ for (regdata = (struct ext_hdr_v0_reg *)((uint8_t *)ptr + ehdr0->offset);
+ (uint8_t *)regdata < (uint8_t *)ptr + header_size && regdata->raddr &&
+ regdata->rdata;
+ regdata++)
+ fprintf(f, "DATA 0x%08x 0x%08x\n", le32_to_cpu(regdata->raddr),
+ le32_to_cpu(regdata->rdata));
+ }
+ }
+
+ if (version == 0 && le16_to_cpu(mhdr0->ddrinitdelay))
+ fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)le16_to_cpu(mhdr0->ddrinitdelay));
+
+ /* Undocumented reserved fields */
+
+ if (version == 0 && (mhdr0->rsvd1[0] || mhdr0->rsvd1[1] || mhdr0->rsvd1[2]))
+ fprintf(f, "#RSVD1 0x%x 0x%x 0x%x\n", (unsigned)mhdr0->rsvd1[0],
+ (unsigned)mhdr0->rsvd1[1], (unsigned)mhdr0->rsvd1[2]);
+
+ if (version == 0 && mhdr0->rsvd3)
+ fprintf(f, "#RSVD3 0x%x\n", (unsigned)mhdr0->rsvd3);
+
+ if (version == 0 && le16_to_cpu(mhdr0->rsvd2))
+ fprintf(f, "#RSVD2 0x%x\n", (unsigned)le16_to_cpu(mhdr0->rsvd2));
+
+ if (version != 0 && mhdr->reserved4)
+ fprintf(f, "#RESERVED4 0x%x\n", (unsigned)mhdr->reserved4);
+
+ if (version != 0 && mhdr->reserved5)
+ fprintf(f, "#RESERVED5 0x%x\n", (unsigned)le16_to_cpu(mhdr->reserved5));
+
+ fclose(f);
+
+ return 0;
+}
+
static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params)
{
struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
size_t header_size = kwbheader_size(ptr);
struct opt_hdr_v1 *ohdr;
int idx = params->pflag;
- int cur_idx = 0;
+ int cur_idx;
uint32_t offset;
ulong image;
ulong size;
- for_each_opt_hdr_v1 (ohdr, ptr) {
- if (ohdr->headertype != OPT_HDR_V1_BINARY_TYPE)
- continue;
+ /* Generate kwbimage config file when '-p -1' is specified */
+ if (idx == -1)
+ return kwbimage_generate_config(ptr, params);
- if (idx == cur_idx) {
- image = (ulong)&ohdr->data[4 + 4 * ohdr->data[0]];
- size = opt_hdr_v1_size(ohdr) - 12 - 4 * ohdr->data[0];
- goto extract;
- }
+ image = 0;
+ size = 0;
- ++cur_idx;
- }
+ if (idx == 0) {
+ /* Extract data image when -p is not specified or when '-p 0' is specified */
+ offset = le32_to_cpu(mhdr->srcaddr);
- if (idx != cur_idx) {
- printf("Image %d is not present\n", idx);
- return -1;
- }
+ if (mhdr->blockid == IBR_HDR_SATA_ID) {
+ offset -= 1;
+ offset *= 512;
+ }
- offset = le32_to_cpu(mhdr->srcaddr);
+ if (mhdr->blockid == IBR_HDR_SDIO_ID)
+ offset *= 512;
- if (mhdr->blockid == IBR_HDR_SATA_ID) {
- offset -= 1;
- offset *= 512;
- }
+ if (mhdr->blockid == IBR_HDR_PEX_ID && offset == 0xFFFFFFFF)
+ offset = header_size;
- if (mhdr->blockid == IBR_HDR_SDIO_ID)
- offset *= 512;
+ image = (ulong)((uint8_t *)ptr + offset);
+ size = le32_to_cpu(mhdr->blocksize) - 4;
+ } else {
+ /* Extract N-th binary header executabe image when other '-p N' is specified */
+ cur_idx = 1;
+ for_each_opt_hdr_v1(ohdr, ptr) {
+ if (ohdr->headertype != OPT_HDR_V1_BINARY_TYPE)
+ continue;
- if (mhdr->blockid == IBR_HDR_PEX_ID && offset == 0xFFFFFFFF)
- offset = header_size;
+ if (idx == cur_idx) {
+ image = (ulong)&ohdr->data[4 + 4 * ohdr->data[0]];
+ size = opt_hdr_v1_size(ohdr) - 12 - 4 * ohdr->data[0];
+ break;
+ }
- image = (ulong)((uint8_t *)ptr + offset);
- size = le32_to_cpu(mhdr->blocksize) - 4;
+ ++cur_idx;
+ }
+
+ if (!image) {
+ fprintf(stderr, "Argument -p %d is invalid\n", idx);
+ fprintf(stderr, "Available subimages:\n");
+ fprintf(stderr, " -p -1 - kwbimage config file\n");
+ fprintf(stderr, " -p 0 - data image\n");
+ if (cur_idx - 1 > 0)
+ fprintf(stderr, " -p N - Nth binary header image (totally: %d)\n",
+ cur_idx - 1);
+ return -1;
+ }
+ }
-extract:
return imagetool_save_subimage(params->outfile, image, size);
}
@@ -1985,7 +2331,8 @@ extract:
*/
static int kwbimage_check_params(struct image_tool_params *params)
{
- if (!params->iflag && (!params->imagename || !strlen(params->imagename))) {
+ if (!params->lflag && !params->iflag &&
+ (!params->imagename || !strlen(params->imagename))) {
char *msg = "Configuration file for kwbimage creation omitted";
fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg);
diff --git a/tools/kwbimage.h b/tools/kwbimage.h
index 8d37357..9ebc7d7 100644
--- a/tools/kwbimage.h
+++ b/tools/kwbimage.h
@@ -208,7 +208,7 @@ static inline size_t kwbheader_size(const void *header)
const struct main_hdr_v0 *hdr = header;
return sizeof(*hdr) +
- (hdr->ext & 0x1) ? sizeof(struct ext_hdr_v0) : 0;
+ hdr->ext ? sizeof(struct ext_hdr_v0) : 0;
} else {
const struct main_hdr_v1 *hdr = header;
@@ -235,11 +235,11 @@ static inline int opt_hdr_v1_valid_size(const struct opt_hdr_v1 *ohdr,
{
uint32_t ohdr_size;
- if ((void *)(ohdr + 1) > mhdr_end)
+ if ((const void *)(ohdr + 1) > mhdr_end)
return 0;
ohdr_size = opt_hdr_v1_size(ohdr);
- if (ohdr_size < 8 || (void *)((uint8_t *)ohdr + ohdr_size) > mhdr_end)
+ if (ohdr_size < 8 || (const void *)((const uint8_t *)ohdr + ohdr_size) > mhdr_end)
return 0;
return 1;
@@ -252,7 +252,7 @@ static inline struct opt_hdr_v1 *opt_hdr_v1_first(void *img) {
return NULL;
mhdr = img;
- if (mhdr->ext & 0x1)
+ if (mhdr->ext)
return (struct opt_hdr_v1 *)(mhdr + 1);
else
return NULL;
@@ -272,7 +272,7 @@ static inline struct opt_hdr_v1 *_opt_hdr_v1_next(struct opt_hdr_v1 *cur)
static inline struct opt_hdr_v1 *opt_hdr_v1_next(struct opt_hdr_v1 *cur)
{
- if (*opt_hdr_v1_ext(cur) & 0x1)
+ if (*opt_hdr_v1_ext(cur))
return _opt_hdr_v1_next(cur);
else
return NULL;
diff --git a/tools/kwboot.c b/tools/kwboot.c
index d22e6ea..c3d8ab6 100644
--- a/tools/kwboot.c
+++ b/tools/kwboot.c
@@ -1398,7 +1398,7 @@ kwboot_add_bin_ohdr_v1(void *img, size_t *size, uint32_t binsz)
uint32_t ohdrsz;
uint8_t *prev_ext;
- if (hdr->ext & 0x1) {
+ if (hdr->ext) {
for_each_opt_hdr_v1 (ohdr, img)
if (opt_hdr_v1_next(ohdr) == NULL)
break;
@@ -1422,7 +1422,7 @@ kwboot_add_bin_ohdr_v1(void *img, size_t *size, uint32_t binsz)
ohdrsz = sizeof(*ohdr) + 4 + 4 * num_args + binsz + 4;
kwboot_img_grow_hdr(hdr, size, ohdrsz);
- *prev_ext |= 1;
+ *prev_ext = 1;
ohdr->headertype = OPT_HDR_V1_BINARY_TYPE;
ohdr->headersz_msb = ohdrsz >> 16;