All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/3 v3] arm: mvebu: Add gdsys ControlCenter-Compact board
@ 2017-02-22 15:07 Mario Six
  2017-02-22 15:07 ` [U-Boot] [PATCH 1/3 v3] dm: Add callback to modify the device tree Mario Six
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Mario Six @ 2017-02-22 15:07 UTC (permalink / raw)
  To: u-boot

This patch series adds support for the Guntermann & Drunck
ControlCenter-Compact board.

Additionally, a board function for manipulating the device tree is added.

Dirk Eibach (1):
  arm: mvebu: Add gdsys ControlCenter-Compact board

Mario Six (2):
  dm: Add callback to modify the device tree
  controlcenterdc: Make secure boot available

 arch/arm/Kconfig                            |   1 +
 arch/arm/dts/Makefile                       |   3 +-
 arch/arm/dts/armada-38x-controlcenterdc.dts | 589 ++++++++++++++++++++++++++++
 arch/arm/mach-mvebu/Kconfig                 |   4 +
 board/gdsys/a38x/.gitignore                 |   1 +
 board/gdsys/a38x/Kconfig                    |  36 ++
 board/gdsys/a38x/MAINTAINERS                |   7 +
 board/gdsys/a38x/Makefile                   |  44 +++
 board/gdsys/a38x/controlcenterdc.c          | 279 +++++++++++++
 board/gdsys/a38x/dt_helpers.c               |  43 ++
 board/gdsys/a38x/dt_helpers.h               |  16 +
 board/gdsys/a38x/hre.c                      | 516 ++++++++++++++++++++++++
 board/gdsys/a38x/hre.h                      |  38 ++
 board/gdsys/a38x/hydra.c                    | 138 +++++++
 board/gdsys/a38x/hydra.h                    |  14 +
 board/gdsys/a38x/ihs_phys.c                 | 355 +++++++++++++++++
 board/gdsys/a38x/ihs_phys.h                 |   2 +
 board/gdsys/a38x/keyprogram.c               | 158 ++++++++
 board/gdsys/a38x/keyprogram.h               |  14 +
 board/gdsys/a38x/kwbimage.cfg.in            |  40 ++
 board/gdsys/a38x/spl.c                      |  21 +
 common/board_f.c                            |  10 +
 configs/controlcenterdc_defconfig           |  60 +++
 doc/driver-model/fdt-fixup.txt              | 132 +++++++
 dts/Kconfig                                 |  10 +
 include/common.h                            |   1 +
 include/configs/controlcenterdc.h           | 228 +++++++++++
 27 files changed, 2759 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/dts/armada-38x-controlcenterdc.dts
 create mode 100644 board/gdsys/a38x/.gitignore
 create mode 100644 board/gdsys/a38x/Kconfig
 create mode 100644 board/gdsys/a38x/MAINTAINERS
 create mode 100644 board/gdsys/a38x/Makefile
 create mode 100644 board/gdsys/a38x/controlcenterdc.c
 create mode 100644 board/gdsys/a38x/dt_helpers.c
 create mode 100644 board/gdsys/a38x/dt_helpers.h
 create mode 100644 board/gdsys/a38x/hre.c
 create mode 100644 board/gdsys/a38x/hre.h
 create mode 100644 board/gdsys/a38x/hydra.c
 create mode 100644 board/gdsys/a38x/hydra.h
 create mode 100644 board/gdsys/a38x/ihs_phys.c
 create mode 100644 board/gdsys/a38x/ihs_phys.h
 create mode 100644 board/gdsys/a38x/keyprogram.c
 create mode 100644 board/gdsys/a38x/keyprogram.h
 create mode 100644 board/gdsys/a38x/kwbimage.cfg.in
 create mode 100644 board/gdsys/a38x/spl.c
 create mode 100644 configs/controlcenterdc_defconfig
 create mode 100644 doc/driver-model/fdt-fixup.txt
 create mode 100644 include/configs/controlcenterdc.h

--
2.11.0

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH 1/3 v3] dm: Add callback to modify the device tree
  2017-02-22 15:07 [U-Boot] [PATCH 0/3 v3] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
@ 2017-02-22 15:07 ` Mario Six
  2017-03-03  4:52   ` Simon Glass
  2017-03-24  5:53   ` Stefan Roese
  2017-02-22 15:07 ` [U-Boot] [PATCH 2/3 v3] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
  2017-02-22 15:07 ` [U-Boot] [PATCH 3/3 v3] controlcenterdc: Make secure boot available Mario Six
  2 siblings, 2 replies; 12+ messages in thread
From: Mario Six @ 2017-02-22 15:07 UTC (permalink / raw)
  To: u-boot

Certain boards come in different variations by way of utilizing daughter
boards, for example. These boards might contain additional chips, which
are added to the main board's busses, e.g. I2C.

The device tree support for such boards would either, quite naturally,
employ the overlay mechanism to add such chips to the tree, or would use
one large default device tree, and delete the devices that are actually
not present.

Regardless of approach, even on the U-Boot level, a modification of the
device tree is a prerequisite to have such modular families of boards
supported properly.

Therefore, we add an option to make the U-Boot device tree (the actual
copy later used by the driver model) writeable, and add a callback
method that allows boards to modify the device tree at an early stage,
at which, hopefully, also the application of device tree overlays will
be possible.

Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v3:

None

Changes in v2:

* Switched from usage of globally writeable global data pointer to a locally
  writeable pointer passed to board_fix_fdt
* Added comments for board_fix_fdt in include/common.h
* Added documentation for pre-relocation device tree manipulation
---
 common/board_f.c               |  10 ++++
 doc/driver-model/fdt-fixup.txt | 132 +++++++++++++++++++++++++++++++++++++++++
 dts/Kconfig                    |  10 ++++
 include/common.h               |   1 +
 4 files changed, 153 insertions(+)
 create mode 100644 doc/driver-model/fdt-fixup.txt

diff --git a/common/board_f.c b/common/board_f.c
index ae6cd8528c..00d0b81d22 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -767,6 +767,13 @@ static int setup_reloc(void)
 	return 0;
 }

+#ifdef CONFIG_OF_BOARD_FIXUP
+static int fix_fdt(void)
+{
+	return board_fix_fdt((void *)gd->fdt_blob);
+}
+#endif
+
 /* ARM calls relocate_code from its crt0.S */
 #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
 		!CONFIG_IS_ENABLED(X86_64)
@@ -1028,6 +1035,9 @@ static const init_fnc_t init_sequence_f[] = {
 #ifdef CONFIG_SYS_EXTBDINFO
 	setup_board_extra,
 #endif
+#ifdef CONFIG_OF_BOARD_FIXUP
+	fix_fdt,
+#endif
 	INIT_FUNC_WATCHDOG_RESET
 	reloc_fdt,
 	setup_reloc,
diff --git a/doc/driver-model/fdt-fixup.txt b/doc/driver-model/fdt-fixup.txt
new file mode 100644
index 0000000000..70344bd2c3
--- /dev/null
+++ b/doc/driver-model/fdt-fixup.txt
@@ -0,0 +1,132 @@
+Pre-relocation device tree manipulation
+=======================================
+
+Contents:
+
+1. Purpose
+2. Implementation
+3. Example
+4. Work to be done
+
+1. Purpose
+----------
+
+In certain markets, it is beneficial for manufacturers of embedded devices to
+offer certain ranges of products, where the functionality of the devices within
+one series either don't differ greatly from another, or can be thought of as
+"extensions" of each other, where one device only differs from another in the
+addition of a small number of features (e.g. an additional output connector).
+
+To realize this in hardware, one method is to have a motherboard, and several
+possible daughter boards that can be attached to this mother board. Different
+daughter boards then either offer the slightly different functionality, or the
+addition of the daughter board to the device realizes the "extension" of
+functionality to the device described previously.
+
+For the software, we obviously want to reuse components for all these
+variations of the device. This means that the software somehow needs to cope
+with the situation that certain ICs may or may not be present on any given
+system, depending on which daughter boards are connected to the motherboard.
+
+In the Linux kernel, one possible solution to this problem is to employ the
+device tree overlay mechanism: There exists one "base" device tree, which
+features only the components guaranteed to exist in all varieties of the
+device. At the start of the kernel, the presence and type of the daughter
+boards is then detected, and the corresponding device tree overlays are applied
+to support the components on the daughter boards.
+
+Note that the components present on every variety of the board must, of course,
+provide a way to find out if and which daughter boards are installed for this
+mechanism to work.
+
+In the U-Boot boot loader, support for device tree overlays has recently been
+integrated, and is used on some boards to alter the device tree that is later
+passed to Linux. But since U-Boot's driver model, which is device tree-based as
+well, is being used in more and more drivers, the same problem of altering the
+device tree starts cropping up in U-Boot itself as well.
+
+An additional problem with the device tree in U-Boot is that it is read-only,
+and the current mechanisms don't allow easy manipulation of the device tree
+after the driver model has been initialized. While migrating to a live device
+tree (at least after the relocation) would greatly simplify the solution of
+this problem, it is a non-negligible task to implement it, an a interim
+solution is needed to address the problem at least in the medium-term.
+
+Hence, we propose a solution to this problem by offering a board-specific
+call-back function, which is passed a writeable pointer to the device tree.
+This function is called before the device tree is relocated, and specifically
+before the main U-Boot's driver model is instantiated, hence the main U-Boot
+"sees" all modifications to the device tree made in this function. Furthermore,
+we have the pre-relocation driver model at our disposal at this stage, which
+means that we can query the hardware for the existence and variety of the
+components easily.
+
+2. Implementation
+-----------------
+
+To take advantage of the pre-relocation device tree manipulation mechanism,
+boards have to implement the function board_fix_fdt, which has the following
+signature:
+
+int board_fix_fdt (void *rw_fdt_blob)
+
+The passed-in void pointer is a writeable pointer to the device tree, which can
+be used to manipulate the device tree using e.g. functions from
+include/fdt_support.h. The return value should either be 0 in case of
+successful execution of the device tree manipulation or something else for a
+failure. Note that returning a non-null value from the function will
+unrecoverably halt the boot process, as with any function from init_sequence_f
+(in common/board_f.c).
+
+Furthermore, the Kconfig option OF_BOARD_FIXUP has to be set for the function
+to be called:
+
+Device Tree Control
+-> [*] Board-specific manipulation of Device Tree
+
++----------------------------------------------------------+
+| WARNING: The actual manipulation of the device tree has  |
+| to be the _last_ set of operations in board_fix_fdt!     |
+| Since the pre-relocation driver model does not adapt to  |
+| changes made to the device tree either, its references   |
+| into the device tree will be invalid after manipulating  |
+| it, and unpredictable behavior might occur when          |
+| functions that rely on them are executed!                |
++----------------------------------------------------------+
+
+Hence, the recommended layout of the board_fixup_fdt call-back function is the
+following:
+
+int board_fix_fdt(void *rw_fdt_blob)
+{
+	/* Collect information about device's hardware and store them in e.g.
+	   local variables */
+
+	/* Do device tree manipulation using the values previously collected */
+
+	/* Return 0 on successful manipulation and non-zero otherwise */
+}
+
+If this convention is kept, both an "additive" approach, meaning that nodes for
+detected components are added to the device tree, as well as a "subtractive"
+approach, meaning that nodes for absent components are removed from the tree,
+as well as a combination of both approaches should work.
+
+3. Example
+----------
+
+The controlcenterdc board (board/gdsys/a38x/controlcenterdc.c) features a
+board_fix_fdt function, in which six GPIO expanders (which might be present or
+not, since they are on daughter boards) on a I2C bus are queried for, and
+subsequently deactivated in the device tree if they are not present.
+
+Note that the dm_i2c_simple_probe function does not use the device tree, hence
+it is safe to call it after the tree has already been manipulated.
+
+4. Work to be done
+------------------
+
+* The application of device tree overlay should be possible in board_fixup_fdt,
+  but has not been tested at this stage.
+
+2017-01-06, Mario Six <mario.six@gdsys.cc>
diff --git a/dts/Kconfig b/dts/Kconfig
index 4b7d8b15cc..3f64eda619 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -14,6 +14,16 @@ config OF_CONTROL
 	  This feature provides for run-time configuration of U-Boot
 	  via a flattened device tree.

+config OF_BOARD_FIXUP
+	bool "Board-specific manipulation of Device Tree"
+	help
+	  In certain circumstances it is necessary to be able to modify
+	  U-Boot's device tree (e.g. to delete device from it). This option
+	  make the Device Tree writeable and provides a board-specific
+	  "board_fix_fdt" callback (called during pre-relocation time), which
+	  enables the board initialization to modifiy the Device Tree. The
+	  modified copy is subsequently used by U-Boot after relocation.
+
 config SPL_OF_CONTROL
 	bool "Enable run-time configuration via Device Tree in SPL"
 	depends on SPL && OF_CONTROL
diff --git a/include/common.h b/include/common.h
index fbbc2cbc52..2cbbd5a60c 100644
--- a/include/common.h
+++ b/include/common.h
@@ -497,6 +497,7 @@ extern ssize_t spi_write (uchar *, int, uchar *, int);

 /* $(BOARD)/$(BOARD).c */
 int board_early_init_f (void);
+int board_fix_fdt (void *rw_fdt_blob); /* manipulate the U-Boot fdt before its relocation */
 int board_late_init (void);
 int board_postclk_init (void); /* after clocks/timebase, before env/serial */
 int board_early_init_r (void);
--
2.11.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH 2/3 v3] arm: mvebu: Add gdsys ControlCenter-Compact board
  2017-02-22 15:07 [U-Boot] [PATCH 0/3 v3] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
  2017-02-22 15:07 ` [U-Boot] [PATCH 1/3 v3] dm: Add callback to modify the device tree Mario Six
@ 2017-02-22 15:07 ` Mario Six
  2017-03-03  4:52   ` Simon Glass
  2017-03-24  5:53   ` Stefan Roese
  2017-02-22 15:07 ` [U-Boot] [PATCH 3/3 v3] controlcenterdc: Make secure boot available Mario Six
  2 siblings, 2 replies; 12+ messages in thread
From: Mario Six @ 2017-02-22 15:07 UTC (permalink / raw)
  To: u-boot

From: Dirk Eibach <dirk.eibach@gdsys.cc>

The gdsys ControlCenter Digital board is based on a Marvell Armada 38x
SOC.

It boots from SPI-Flash but can be configured to boot from SD-card for
factory programming and testing.

On board peripherals include:
- 2 x GbE
- Xilinx Kintex-7 FPGA connected via PCIe
- mSATA
- USB3 host
- Atmel TPM

Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v3:

* Removed gpio_request_simple function
* Removed dev_get_by_ofname function
* Removed "plain" GPIOs from the device tree

Changes in v2:

* Renamed DTS and board name to include armada-38x
* Renamed 38x directory to a38x
* Removed leftover dummy test Kconfig variable from board/gdsys/38x/Kconfig
* Removed unneeded check for build target in board/gdsys/38x/Makefile
* Removed duplicated board/gdsys/38x/README
* Switched MIIPHY to new GPIO API
* Removed checkboard function
* Fixed multi-line comment in board/gdsys/controlcenterdc.c
* Switched to usage of ARRAY_SIZE in board/gdsys/controlcenterdc.c
* Factored out hydra.{c,h} and ihs_phys.{c,h} from
  board/gdsys/controlcenterdc.c and removed ifdefs
* Removed unaddressed TODO from HRE
---
 arch/arm/Kconfig                            |   1 +
 arch/arm/dts/Makefile                       |   3 +-
 arch/arm/dts/armada-38x-controlcenterdc.dts | 589 ++++++++++++++++++++++++++++
 arch/arm/mach-mvebu/Kconfig                 |   4 +
 board/gdsys/a38x/.gitignore                 |   1 +
 board/gdsys/a38x/Kconfig                    |  36 ++
 board/gdsys/a38x/MAINTAINERS                |   7 +
 board/gdsys/a38x/Makefile                   |  44 +++
 board/gdsys/a38x/controlcenterdc.c          | 279 +++++++++++++
 board/gdsys/a38x/dt_helpers.c               |  43 ++
 board/gdsys/a38x/dt_helpers.h               |  16 +
 board/gdsys/a38x/hre.c                      | 516 ++++++++++++++++++++++++
 board/gdsys/a38x/hre.h                      |  38 ++
 board/gdsys/a38x/hydra.c                    | 138 +++++++
 board/gdsys/a38x/hydra.h                    |  14 +
 board/gdsys/a38x/ihs_phys.c                 | 355 +++++++++++++++++
 board/gdsys/a38x/ihs_phys.h                 |   2 +
 board/gdsys/a38x/keyprogram.c               | 158 ++++++++
 board/gdsys/a38x/keyprogram.h               |  14 +
 board/gdsys/a38x/kwbimage.cfg.in            |  12 +
 board/gdsys/a38x/spl.c                      |  21 +
 configs/controlcenterdc_defconfig           |  58 +++
 include/configs/controlcenterdc.h           | 228 +++++++++++
 23 files changed, 2576 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/dts/armada-38x-controlcenterdc.dts
 create mode 100644 board/gdsys/a38x/.gitignore
 create mode 100644 board/gdsys/a38x/Kconfig
 create mode 100644 board/gdsys/a38x/MAINTAINERS
 create mode 100644 board/gdsys/a38x/Makefile
 create mode 100644 board/gdsys/a38x/controlcenterdc.c
 create mode 100644 board/gdsys/a38x/dt_helpers.c
 create mode 100644 board/gdsys/a38x/dt_helpers.h
 create mode 100644 board/gdsys/a38x/hre.c
 create mode 100644 board/gdsys/a38x/hre.h
 create mode 100644 board/gdsys/a38x/hydra.c
 create mode 100644 board/gdsys/a38x/hydra.h
 create mode 100644 board/gdsys/a38x/ihs_phys.c
 create mode 100644 board/gdsys/a38x/ihs_phys.h
 create mode 100644 board/gdsys/a38x/keyprogram.c
 create mode 100644 board/gdsys/a38x/keyprogram.h
 create mode 100644 board/gdsys/a38x/kwbimage.cfg.in
 create mode 100644 board/gdsys/a38x/spl.c
 create mode 100644 configs/controlcenterdc_defconfig
 create mode 100644 include/configs/controlcenterdc.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e84b74efb6..59f6d025bc 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1124,6 +1124,7 @@ source "board/freescale/mx53loco/Kconfig"
 source "board/freescale/mx53smd/Kconfig"
 source "board/freescale/s32v234evb/Kconfig"
 source "board/freescale/vf610twr/Kconfig"
+source "board/gdsys/a38x/Kconfig"
 source "board/grinn/chiliboard/Kconfig"
 source "board/gumstix/pepper/Kconfig"
 source "board/h2200/Kconfig"
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index eb68c204bb..8edd2626f3 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -79,7 +79,8 @@ dtb-$(CONFIG_ARCH_MVEBU) +=			\
 	armada-xp-gp.dtb			\
 	armada-xp-maxbcm.dtb			\
 	armada-xp-synology-ds414.dtb		\
-	armada-xp-theadorable.dtb
+	armada-xp-theadorable.dtb		\
+	armada-38x-controlcenterdc.dtb

 dtb-$(CONFIG_ARCH_UNIPHIER_LD11) += \
 	uniphier-ld11-ref.dtb
diff --git a/arch/arm/dts/armada-38x-controlcenterdc.dts b/arch/arm/dts/armada-38x-controlcenterdc.dts
new file mode 100644
index 0000000000..d183fd7502
--- /dev/null
+++ b/arch/arm/dts/armada-38x-controlcenterdc.dts
@@ -0,0 +1,589 @@
+/*
+ * Device Tree file for the Guntermann & Drunck ControlCenter-Compact board
+ *
+ * Copyright (C) 2016 Mario Six <mario.six@gdsys.cc>
+ *
+ * based on the Device Tree file for Marvell Armada 388 evaluation board
+ * (DB-88F6820), which is
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+/dts-v1/;
+
+#include "armada-388.dtsi"
+
+&gpio0 {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio1 {
+	u-boot,dm-pre-reloc;
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+};
+
+&uart1 {
+	u-boot,dm-pre-reloc;
+};
+
+/ {
+	model = "Controlcenter Digital Compact";
+	compatible = "marvell,a385-db", "marvell,armada388",
+		"marvell,armada385", "marvell,armada380";
+
+	chosen {
+		bootargs = "console=ttyS1,115200 earlyprintk";
+		stdout-path = "/soc/internal-regs/serial at 12100";
+	};
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet2 = &eth2;
+		mdio-gpio0 = &MDIO0;
+		mdio-gpio1 = &MDIO1;
+		mdio-gpio2 = &MDIO2;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		i2c0 = &I2C0;
+		i2c1 = &I2C1;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>; /* 256 MB */
+	};
+
+	clocks {
+		sc16isclk: sc16isclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <11059200>;
+		};
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>;
+
+		internal-regs {
+			spi0: spi at 10600 {
+				status = "okay";
+				sc16is741: sc16is741 at 0 {
+					compatible = "nxp,sc16is741";
+					reg = <0>;
+					clocks = <&sc16isclk>;
+					spi-max-frequency = <4000000>;
+					interrupt-parent = <&gpio0>;
+					interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+			};
+
+			spi1: spi at 10680 {
+				status = "okay";
+				u-boot,dm-pre-reloc;
+				spi-flash at 0 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "n25q016a";
+					reg = <0>; /* Chip select 0 */
+					spi-max-frequency = <108000000>;
+				};
+				spi-flash at 1 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "n25q128a11";
+					reg = <1>; /* Chip select 1 */
+					spi-max-frequency = <108000000>;
+					u-boot,dm-pre-reloc;
+				};
+			};
+
+			I2C0: i2c at 11000 {
+				status = "okay";
+				clock-frequency = <1000000>;
+				u-boot,dm-pre-reloc;
+				PCA21: pca9698 at 21 {
+					compatible = "nxp,pca9698";
+					reg = <0x21>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+				PCA22: pca9698 at 22 {
+					compatible = "nxp,pca9698";
+					u-boot,dm-pre-reloc;
+					reg = <0x22>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+				PCA23: pca9698 at 23 {
+					compatible = "nxp,pca9698";
+					reg = <0x23>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+				PCA24: pca9698 at 24 {
+					compatible = "nxp,pca9698";
+					reg = <0x24>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+				PCA25: pca9698 at 25 {
+					compatible = "nxp,pca9698";
+					reg = <0x25>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+				PCA26: pca9698 at 26 {
+					compatible = "nxp,pca9698";
+					reg = <0x26>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+			};
+
+			I2C1: i2c at 11100 {
+				status = "okay";
+				clock-frequency = <400000>;
+				at97sc3205t at 29 {
+					compatible = "atmel,at97sc3204t";
+					reg = <0x29>;
+					u-boot,i2c-offset-len = <0>;
+				};
+				emc2305 at 2d {
+					compatible = "smsc,emc2305";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0x2d>;
+					fan at 0 {
+						reg = <0>;
+					};
+					fan at 1 {
+						reg = <1>;
+					};
+					fan at 2 {
+						reg = <2>;
+					};
+					fan at 3 {
+						reg = <3>;
+					};
+					fan at 4 {
+						reg = <4>;
+					};
+				};
+				lm77 at 48 {
+					compatible = "national,lm77";
+					reg = <0x48>;
+				};
+				ads1015 at 49 {
+					compatible = "ti,ads1015";
+					reg = <0x49>;
+				};
+				lm77 at 4a {
+					compatible = "national,lm77";
+					reg = <0x4a>;
+				};
+				ads1015 at 4b {
+					compatible = "ti,ads1015";
+					reg = <0x4b>;
+				};
+				emc2305 at 4c {
+					compatible = "smsc,emc2305";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0x4c>;
+					fan at 0 {
+						reg = <0>;
+					};
+					fan at 1 {
+						reg = <1>;
+					};
+					fan at 2 {
+						reg = <2>;
+					};
+					fan at 3 {
+						reg = <3>;
+					};
+					fan at 4 {
+						reg = <4>;
+					};
+				};
+				at24c512 at 54 {
+					compatible = "atmel,24c512";
+					reg = <0x54>;
+					u-boot,i2c-offset-len = <2>;
+				};
+				ds1339 at 68 {
+					compatible = "dallas,ds1339";
+					reg = <0x68>;
+				};
+			};
+
+			serial at 12000 {
+				status = "okay";
+			};
+
+			serial at 12100 {
+				status = "okay";
+			};
+
+			ethernet at 34000 {
+				status = "okay";
+				phy = <&phy1>;
+				phy-mode = "sgmii";
+			};
+
+			usb at 58000 {
+				status = "ok";
+			};
+
+			ethernet at 70000 {
+				status = "okay";
+				phy = <&phy0>;
+				phy-mode = "sgmii";
+			};
+
+			mdio at 72004 {
+				phy0: ethernet-phy at 0 {
+					reg = <1>;
+				};
+
+				phy1: ethernet-phy at 1 {
+					reg = <0>;
+				};
+			};
+
+			sata at a8000 {
+				status = "okay";
+			};
+
+			sdhci at d8000 {
+				broken-cd;
+				wp-inverted;
+				bus-width = <4>;
+				status = "okay";
+				no-1-8-v;
+			};
+
+			usb3 at f0000 {
+				status = "okay";
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+			/*
+			 * The two PCIe units are accessible through
+			 * standard PCIe slots on the board.
+			 */
+			pcie at 3,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+		};
+
+		MDIO0: mdio0 {
+			compatible = "virtual,mdio-gpio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			gpios = < /*MDC*/ &gpio0 13 0
+				  /*MDIO*/ &gpio0 14 0>;
+			mv88e1240 at 0 {
+				reg = <0x0>;
+			};
+			mv88e1240 at 1 {
+				reg = <0x1>;
+			};
+			mv88e1240 at 2 {
+				reg = <0x2>;
+			};
+			mv88e1240 at 3 {
+				reg = <0x3>;
+			};
+			mv88e1240 at 4 {
+				reg = <0x4>;
+			};
+			mv88e1240 at 5 {
+				reg = <0x5>;
+			};
+			mv88e1240 at 6 {
+				reg = <0x6>;
+			};
+			mv88e1240 at 7 {
+				reg = <0x7>;
+			};
+			mv88e1240 at 8 {
+				reg = <0x8>;
+			};
+			mv88e1240 at 9 {
+				reg = <0x9>;
+			};
+			mv88e1240 at a {
+				reg = <0xa>;
+			};
+			mv88e1240 at b {
+				reg = <0xb>;
+			};
+			mv88e1240 at c {
+				reg = <0xc>;
+			};
+			mv88e1240 at d {
+				reg = <0xd>;
+			};
+			mv88e1240 at e {
+				reg = <0xe>;
+			};
+			mv88e1240 at f {
+				reg = <0xf>;
+			};
+			mv88e1240 at 10 {
+				reg = <0x10>;
+			};
+			mv88e1240 at 11 {
+				reg = <0x11>;
+			};
+			mv88e1240 at 12 {
+				reg = <0x12>;
+			};
+			mv88e1240 at 13 {
+				reg = <0x13>;
+			};
+			mv88e1240 at 14 {
+				reg = <0x14>;
+			};
+			mv88e1240 at 15 {
+				reg = <0x15>;
+			};
+			mv88e1240 at 16 {
+				reg = <0x16>;
+			};
+			mv88e1240 at 17 {
+				reg = <0x17>;
+			};
+			mv88e1240 at 18 {
+				reg = <0x18>;
+			};
+			mv88e1240 at 19 {
+				reg = <0x19>;
+			};
+			mv88e1240 at 1a {
+				reg = <0x1a>;
+			};
+			mv88e1240 at 1b {
+				reg = <0x1b>;
+			};
+			mv88e1240 at 1c {
+				reg = <0x1c>;
+			};
+			mv88e1240 at 1d {
+				reg = <0x1d>;
+			};
+			mv88e1240 at 1e {
+				reg = <0x1e>;
+			};
+			mv88e1240 at 1f {
+				reg = <0x1f>;
+			};
+		};
+
+		MDIO1: mdio1 {
+			compatible = "virtual,mdio-gpio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			gpios = < /*MDC*/ &gpio0 25 0
+				  /*MDIO*/ &gpio1 13 0>;
+			mv88e1240 at 0 {
+				reg = <0x0>;
+			};
+			mv88e1240 at 1 {
+				reg = <0x1>;
+			};
+			mv88e1240 at 2 {
+				reg = <0x2>;
+			};
+			mv88e1240 at 3 {
+				reg = <0x3>;
+			};
+			mv88e1240 at 4 {
+				reg = <0x4>;
+			};
+			mv88e1240 at 5 {
+				reg = <0x5>;
+			};
+			mv88e1240 at 6 {
+				reg = <0x6>;
+			};
+			mv88e1240 at 7 {
+				reg = <0x7>;
+			};
+			mv88e1240 at 8 {
+				reg = <0x8>;
+			};
+			mv88e1240 at 9 {
+				reg = <0x9>;
+			};
+			mv88e1240 at a {
+				reg = <0xa>;
+			};
+			mv88e1240 at b {
+				reg = <0xb>;
+			};
+			mv88e1240 at c {
+				reg = <0xc>;
+			};
+			mv88e1240 at d {
+				reg = <0xd>;
+			};
+			mv88e1240 at e {
+				reg = <0xe>;
+			};
+			mv88e1240 at f {
+				reg = <0xf>;
+			};
+			mv88e1240 at 10 {
+				reg = <0x10>;
+			};
+			mv88e1240 at 11 {
+				reg = <0x11>;
+			};
+			mv88e1240 at 12 {
+				reg = <0x12>;
+			};
+			mv88e1240 at 13 {
+				reg = <0x13>;
+			};
+			mv88e1240 at 14 {
+				reg = <0x14>;
+			};
+			mv88e1240 at 15 {
+				reg = <0x15>;
+			};
+			mv88e1240 at 16 {
+				reg = <0x16>;
+			};
+			mv88e1240 at 17 {
+				reg = <0x17>;
+			};
+			mv88e1240 at 18 {
+				reg = <0x18>;
+			};
+			mv88e1240 at 19 {
+				reg = <0x19>;
+			};
+			mv88e1240 at 1a {
+				reg = <0x1a>;
+			};
+			mv88e1240 at 1b {
+				reg = <0x1b>;
+			};
+			mv88e1240 at 1c {
+				reg = <0x1c>;
+			};
+			mv88e1240 at 1d {
+				reg = <0x1d>;
+			};
+			mv88e1240 at 1e {
+				reg = <0x1e>;
+			};
+			mv88e1240 at 1f {
+				reg = <0x1f>;
+			};
+		};
+
+		MDIO2: mdio2 {
+			compatible = "virtual,mdio-gpio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			gpios = < /*MDC*/ &gpio1 14 0
+				  /*MDIO*/ &gpio0 24 0>;
+			mv88e1240 at 0 {
+				reg = <0x0>;
+			};
+			mv88e1240 at 1 {
+				reg = <0x1>;
+			};
+			mv88e1240 at 2 {
+				reg = <0x2>;
+			};
+			mv88e1240 at 3 {
+				reg = <0x3>;
+			};
+			mv88e1240 at 4 {
+				reg = <0x4>;
+			};
+			mv88e1240 at 5 {
+				reg = <0x5>;
+			};
+			mv88e1240 at 6 {
+				reg = <0x6>;
+			};
+			mv88e1240 at 7 {
+				reg = <0x7>;
+			};
+			mv88e1240 at 8 {
+				reg = <0x8>;
+			};
+			mv88e1240 at 9 {
+				reg = <0x9>;
+			};
+			mv88e1240 at a {
+				reg = <0xa>;
+			};
+			mv88e1240 at b {
+				reg = <0xb>;
+			};
+			mv88e1240 at c {
+				reg = <0xc>;
+			};
+			mv88e1240 at d {
+				reg = <0xd>;
+			};
+			mv88e1240 at e {
+				reg = <0xe>;
+			};
+			mv88e1240 at f {
+				reg = <0xf>;
+			};
+			mv88e1240 at 10 {
+				reg = <0x10>;
+			};
+			mv88e1240 at 11 {
+				reg = <0x11>;
+			};
+			mv88e1240 at 12 {
+				reg = <0x12>;
+			};
+			mv88e1240 at 13 {
+				reg = <0x13>;
+			};
+			mv88e1240 at 14 {
+				reg = <0x14>;
+			};
+			mv88e1240 at 15 {
+				reg = <0x15>;
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		finder_led {
+			label = "finder-led";
+			gpios = <&PCA22 25 0>;
+		};
+
+		status_led {
+			label = "status-led";
+			gpios = <&gpio0 29 0>;
+		};
+	};
+};
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 412bda4160..015bbd2f0d 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -112,6 +112,10 @@ config TARGET_THEADORABLE
 	select BOARD_LATE_INIT if USB
 	select MV78260

+config TARGET_CONTROLCENTERDC
+	bool "Support CONTROLCENTERDC"
+	select 88F6820
+
 endchoice

 config SYS_BOARD
diff --git a/board/gdsys/a38x/.gitignore b/board/gdsys/a38x/.gitignore
new file mode 100644
index 0000000000..775b9346b8
--- /dev/null
+++ b/board/gdsys/a38x/.gitignore
@@ -0,0 +1 @@
+kwbimage.cfg
diff --git a/board/gdsys/a38x/Kconfig b/board/gdsys/a38x/Kconfig
new file mode 100644
index 0000000000..3fdef64b59
--- /dev/null
+++ b/board/gdsys/a38x/Kconfig
@@ -0,0 +1,36 @@
+if TARGET_CONTROLCENTERDC
+
+config SYS_BOARD
+	default "a38x"
+
+config SYS_VENDOR
+	default "gdsys"
+
+config SYS_SOC
+	default "mvebu"
+
+config SYS_CONFIG_NAME
+	default "controlcenterdc"
+
+menu "Controlcenter DC board options"
+
+choice
+	prompt "Select boot method"
+
+config SPL_BOOT_DEVICE_SPI
+	bool "SPI"
+
+config SPL_BOOT_DEVICE_MMC
+	bool "MMC"
+	select SPL_LIBDISK_SUPPORT
+
+endchoice
+
+#config SPL_BOOT_DEVICE
+#	int
+#	default 1 if SPL_BOOT_DEVICE_SPI
+#	default 2 if SPL_BOOT_DEVICE_MMC
+
+endmenu
+
+endif
diff --git a/board/gdsys/a38x/MAINTAINERS b/board/gdsys/a38x/MAINTAINERS
new file mode 100644
index 0000000000..3cb9b63ff0
--- /dev/null
+++ b/board/gdsys/a38x/MAINTAINERS
@@ -0,0 +1,7 @@
+A38X BOARD
+M:	Dirk Eibach <eibach@gdsys.cc>
+M:	Mario Six <six@gdsys.de>
+S:	Maintained
+F:	board/gdsys/a38x/
+F:	include/configs/controlcenterdc.h
+F:	configs/controlcenterdc_defconfig
diff --git a/board/gdsys/a38x/Makefile b/board/gdsys/a38x/Makefile
new file mode 100644
index 0000000000..0c256d30ca
--- /dev/null
+++ b/board/gdsys/a38x/Makefile
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2015 Stefan Roese <sr@denx.de>
+# Copyright (C) 2015 Reinhard Pfau <reinhard.pfau@gdsys.cc>
+# Copyright (C) 2016 Mario Six <mario.six@gdsys.cc>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_TARGET_CONTROLCENTERDC) += controlcenterdc.o hre.o spl.o keyprogram.o dt_helpers.o
+
+ifeq ($(CONFIG_SPL_BUILD),)
+
+obj-$(CONFIG_TARGET_CONTROLCENTERDC) += hydra.o ihs_phys.o
+
+extra-$(CONFIG_TARGET_CONTROLCENTERDC) += kwbimage.cfg
+
+KWB_REPLACE += BOOT_FROM
+ifneq ($(CONFIG_SPL_BOOT_DEVICE_SPI),)
+	KWB_CFG_BOOT_FROM=spi
+endif
+ifneq ($(CONFIG_SPL_BOOT_DEVICE_MMC),)
+	KWB_CFG_BOOT_FROM=sdio
+endif
+
+ifneq ($(CONFIG_SECURED_MODE_IMAGE),)
+KWB_REPLACE += CSK_INDEX
+KWB_CFG_CSK_INDEX = $(CONFIG_SECURED_MODE_CSK_INDEX)
+
+KWB_REPLACE += SEC_BOOT_DEV
+KWB_CFG_SEC_BOOT_DEV=$(patsubst "%",%, \
+	$(if $(findstring BOOT_SPI_NOR_FLASH,$(CONFIG_SPL_BOOT_DEVICE)),0x34) \
+	$(if $(findstring BOOT_SDIO_MMC_CARD,$(CONFIG_SPL_BOOT_DEVICE)),0x31) \
+	)
+
+KWB_REPLACE += SEC_FUSE_DUMP
+KWB_CFG_SEC_FUSE_DUMP = a38x
+endif
+
+$(src)/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' \
+	<$< >$@
+
+endif
diff --git a/board/gdsys/a38x/controlcenterdc.c b/board/gdsys/a38x/controlcenterdc.c
new file mode 100644
index 0000000000..f0efb53447
--- /dev/null
+++ b/board/gdsys/a38x/controlcenterdc.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2015 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2016 Mario Six <mario.six@gdsys.cc>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <miiphy.h>
+#include <tpm.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm-generic/gpio.h>
+
+#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h"
+#include "../arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h"
+
+#include "keyprogram.h"
+#include "dt_helpers.h"
+#include "hydra.h"
+#include "ihs_phys.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ETH_PHY_CTRL_REG		0
+#define ETH_PHY_CTRL_POWER_DOWN_BIT	11
+#define ETH_PHY_CTRL_POWER_DOWN_MASK	(1 << ETH_PHY_CTRL_POWER_DOWN_BIT)
+
+#define DB_GP_88F68XX_GPP_OUT_ENA_LOW	0x7fffffff
+#define DB_GP_88F68XX_GPP_OUT_ENA_MID	0xffffefff
+
+#define DB_GP_88F68XX_GPP_OUT_VAL_LOW	0x0
+#define DB_GP_88F68XX_GPP_OUT_VAL_MID	0x00001000
+#define DB_GP_88F68XX_GPP_POL_LOW	0x0
+#define DB_GP_88F68XX_GPP_POL_MID	0x0
+
+/*
+ * Define the DDR layout / topology here in the board file. This will
+ * be used by the DDR3 init code in the SPL U-Boot version to configure
+ * the DDR3 controller.
+ */
+static struct hws_topology_map ddr_topology_map = {
+	0x1, /* active interfaces */
+	/* cs_mask, mirror, dqs_swap, ck_swap X PUPs */
+	{ { { {0x1, 0, 0, 0},
+	      {0x1, 0, 0, 0},
+	      {0x1, 0, 0, 0},
+	      {0x1, 0, 0, 0},
+	      {0x1, 0, 0, 0} },
+	    SPEED_BIN_DDR_1600K,	/* speed_bin */
+	    BUS_WIDTH_16,		/* memory_width */
+	    MEM_4G,			/* mem_size */
+	    DDR_FREQ_533,		/* frequency */
+	    0, 0,			/* cas_l cas_wl */
+	    HWS_TEMP_LOW} },		/* temperature */
+	5,				/* Num Of Bus Per Interface*/
+	BUS_MASK_32BIT			/* Busses mask */
+};
+
+static struct serdes_map serdes_topology_map[] = {
+	{SGMII0, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+	{USB3_HOST0, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+	/* SATA tx polarity is inverted */
+	{SATA1, SERDES_SPEED_3_GBPS, SERDES_DEFAULT_MODE, 0, 1},
+	{SGMII2, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+	{DEFAULT_SERDES, SERDES_SPEED_3_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+	{PEX2, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0}
+};
+
+int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
+{
+	*serdes_map_array = serdes_topology_map;
+	*count = ARRAY_SIZE(serdes_topology_map);
+	return 0;
+}
+
+void board_pex_config(void)
+{
+#ifdef CONFIG_SPL_BUILD
+	uint k;
+	struct gpio_desc gpio = {};
+
+	if (!request_gpio_by_name(&gpio, "pca9698 at 22", 31, "fpga-program-gpio")) {
+		/* prepare FPGA reconfiguration */
+		dm_gpio_set_dir_flags(&gpio, GPIOD_IS_OUT);
+		dm_gpio_set_value(&gpio, 0);
+
+		/* give lunatic PCIe clock some time to stabilize */
+		mdelay(500);
+
+		/* start FPGA reconfiguration */
+		dm_gpio_set_dir_flags(&gpio, GPIOD_IS_IN);
+	}
+
+	/* wait for FPGA done */
+	if (!request_gpio_by_name(&gpio, "pca9698 at 22", 19, "fpga-done-gpio")) {
+		for (k = 0; k < 20; ++k) {
+			if (dm_gpio_get_value(&gpio)) {
+				printf("FPGA done after %u rounds\n", k);
+				break;
+			}
+			mdelay(100);
+		}
+	}
+
+	/* disable FPGA reset */
+	if (!request_gpio_by_name(&gpio, "gpio at 18100", 6, "cpu-to-fpga-reset")) {
+		dm_gpio_set_dir_flags(&gpio, GPIOD_IS_OUT);
+		dm_gpio_set_value(&gpio, 1);
+	}
+
+	/* wait for FPGA ready */
+	if (!request_gpio_by_name(&gpio, "pca9698@22", 27, "fpga-ready-gpio")) {
+		for (k = 0; k < 2; ++k) {
+			if (!dm_gpio_get_value(&gpio))
+				break;
+			mdelay(100);
+		}
+	}
+#endif
+}
+
+struct hws_topology_map *ddr3_get_topology_map(void)
+{
+	return &ddr_topology_map;
+}
+
+int board_early_init_f(void)
+{
+#ifdef CONFIG_SPL_BUILD
+	/* Configure MPP */
+	writel(0x00111111, MVEBU_MPP_BASE + 0x00);
+	writel(0x40040000, MVEBU_MPP_BASE + 0x04);
+	writel(0x00466444, MVEBU_MPP_BASE + 0x08);
+	writel(0x00043300, MVEBU_MPP_BASE + 0x0c);
+	writel(0x44400000, MVEBU_MPP_BASE + 0x10);
+	writel(0x20000334, MVEBU_MPP_BASE + 0x14);
+	writel(0x40000000, MVEBU_MPP_BASE + 0x18);
+	writel(0x00004444, MVEBU_MPP_BASE + 0x1c);
+
+	/* Set GPP Out value */
+	writel(DB_GP_88F68XX_GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00);
+	writel(DB_GP_88F68XX_GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00);
+
+	/* Set GPP Polarity */
+	writel(DB_GP_88F68XX_GPP_POL_LOW, MVEBU_GPIO0_BASE + 0x0c);
+	writel(DB_GP_88F68XX_GPP_POL_MID, MVEBU_GPIO1_BASE + 0x0c);
+
+	/* Set GPP Out Enable */
+	writel(DB_GP_88F68XX_GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04);
+	writel(DB_GP_88F68XX_GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04);
+#endif
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* Address of boot parameters */
+	gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
+
+	return 0;
+}
+
+#ifndef CONFIG_SPL_BUILD
+void init_host_phys(struct mii_dev *bus)
+{
+	uint k;
+
+	for (k = 0; k < 2; ++k) {
+		struct phy_device *phydev;
+
+		phydev = phy_find_by_mask(bus, 1 << k,
+					  PHY_INTERFACE_MODE_SGMII);
+
+		if (phydev)
+			phy_config(phydev);
+	}
+}
+
+int ccdc_eth_init(void)
+{
+	uint k;
+	uint octo_phy_mask = 0;
+	int ret;
+	struct mii_dev *bus;
+
+	/* Init SoC's phys */
+	bus = miiphy_get_dev_by_name("ethernet at 34000");
+
+	if (bus)
+		init_host_phys(bus);
+
+	bus = miiphy_get_dev_by_name("ethernet@70000");
+
+	if (bus)
+		init_host_phys(bus);
+
+	/* Init octo phys */
+	octo_phy_mask = calculate_octo_phy_mask();
+
+	printf("IHS PHYS: %08x", octo_phy_mask);
+
+	ret = init_octo_phys(octo_phy_mask);
+
+	if (ret)
+		return ret;
+
+	printf("\n");
+
+	if (!get_fpga()) {
+		puts("fpga was NULL\n");
+		return 1;
+	}
+
+	/* reset all FPGA-QSGMII instances */
+	for (k = 0; k < 80; ++k)
+		writel(1 << 31, get_fpga()->qsgmii_port_state[k]);
+
+	udelay(100);
+
+	for (k = 0; k < 80; ++k)
+		writel(0, get_fpga()->qsgmii_port_state[k]);
+	return 0;
+}
+
+#endif
+
+int board_late_init(void)
+{
+#ifndef CONFIG_SPL_BUILD
+	hydra_initialize();
+#endif
+	return 0;
+}
+
+int board_fix_fdt(void *rw_fdt_blob)
+{
+	struct udevice *bus = NULL;
+	uint k;
+	char name[64];
+	int err;
+
+	err = uclass_get_device_by_name(UCLASS_I2C, "i2c at 11000", &bus);
+
+	if (err) {
+		printf("Could not get I2C bus.\n");
+		return err;
+	}
+
+	for (k = 0x21; k <= 0x26; k++) {
+		snprintf(name, 64,
+			 "/soc/internal-regs/i2c at 11000/pca9698@%02x", k);
+
+		if (!dm_i2c_simple_probe(bus, k))
+			fdt_disable_by_ofname(rw_fdt_blob, name);
+	}
+
+	return 0;
+}
+
+int last_stage_init(void)
+{
+#ifndef CONFIG_SPL_BUILD
+	ccdc_eth_init();
+#endif
+	if (tpm_init() || tpm_startup(TPM_ST_CLEAR) ||
+	    tpm_continue_self_test()) {
+		return 1;
+	}
+
+	mdelay(37);
+
+	flush_keys();
+	load_and_run_keyprog();
+
+	return 0;
+}
diff --git a/board/gdsys/a38x/dt_helpers.c b/board/gdsys/a38x/dt_helpers.c
new file mode 100644
index 0000000000..759d82a728
--- /dev/null
+++ b/board/gdsys/a38x/dt_helpers.c
@@ -0,0 +1,43 @@
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <fdt_support.h>
+#include <asm-generic/gpio.h>
+#include <dm.h>
+
+int fdt_disable_by_ofname(void *rw_fdt_blob, char *ofname)
+{
+	int offset = fdt_path_offset(rw_fdt_blob, ofname);
+
+	return fdt_status_disabled(rw_fdt_blob, offset);
+}
+
+bool dm_i2c_simple_probe(struct udevice *bus, uint chip_addr)
+{
+	struct udevice *dev;
+
+	return !dm_i2c_probe(bus, chip_addr, DM_I2C_CHIP_RD_ADDRESS |
+			     DM_I2C_CHIP_WR_ADDRESS, &dev);
+}
+
+int request_gpio_by_name(struct gpio_desc *gpio, const char *gpio_dev_name,
+			 uint offset, char *gpio_name)
+{
+	struct udevice *gpio_dev = NULL;
+
+	if (uclass_get_device_by_name(UCLASS_GPIO, gpio_dev_name, &gpio_dev))
+		return 1;
+
+	gpio->dev = gpio_dev;
+	gpio->offset = offset;
+	gpio->flags = 0;
+
+	return dm_gpio_request(gpio, gpio_name);
+}
+
diff --git a/board/gdsys/a38x/dt_helpers.h b/board/gdsys/a38x/dt_helpers.h
new file mode 100644
index 0000000000..1b95262c51
--- /dev/null
+++ b/board/gdsys/a38x/dt_helpers.h
@@ -0,0 +1,16 @@
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __DT_HELPERS_H
+#define __DT_HELPERS_H
+
+int fdt_disable_by_ofname(void *rw_fdt_blob, char *ofname);
+bool dm_i2c_simple_probe(struct udevice *bus, uint chip_addr);
+int request_gpio_by_name(struct gpio_desc *gpio, const char *gpio_dev_name,
+			 uint offset, char *gpio_name);
+
+#endif /* __DT_HELPERS_H */
diff --git a/board/gdsys/a38x/hre.c b/board/gdsys/a38x/hre.c
new file mode 100644
index 0000000000..1689d44db6
--- /dev/null
+++ b/board/gdsys/a38x/hre.c
@@ -0,0 +1,516 @@
+/*
+ * (C) Copyright 2013
+ * Reinhard Pfau, Guntermann & Drunck GmbH, reinhard.pfau at gdsys.cc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <fs.h>
+#include <i2c.h>
+#include <mmc.h>
+#include <tpm.h>
+#include <u-boot/sha1.h>
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+#include <pca9698.h>
+
+#include "hre.h"
+
+/* other constants */
+enum {
+	ESDHC_BOOT_IMAGE_SIG_OFS	= 0x40,
+	ESDHC_BOOT_IMAGE_SIZE_OFS	= 0x48,
+	ESDHC_BOOT_IMAGE_ADDR_OFS	= 0x50,
+	ESDHC_BOOT_IMAGE_TARGET_OFS	= 0x58,
+	ESDHC_BOOT_IMAGE_ENTRY_OFS	= 0x60,
+};
+
+enum {
+	I2C_SOC_0 = 0,
+	I2C_SOC_1 = 1,
+};
+
+enum access_mode {
+	HREG_NONE	= 0,
+	HREG_RD		= 1,
+	HREG_WR		= 2,
+	HREG_RDWR	= 3,
+};
+
+/* register constants */
+enum {
+	FIX_HREG_DEVICE_ID_HASH	= 0,
+	FIX_HREG_UNUSED1	= 1,
+	FIX_HREG_UNUSED2	= 2,
+	FIX_HREG_VENDOR		= 3,
+	COUNT_FIX_HREGS
+};
+
+static struct h_reg pcr_hregs[24];
+static struct h_reg fix_hregs[COUNT_FIX_HREGS];
+static struct h_reg var_hregs[8];
+
+/* hre opcodes */
+enum {
+	/* opcodes w/o data */
+	HRE_NOP		= 0x00,
+	HRE_SYNC	= HRE_NOP,
+	HRE_CHECK0	= 0x01,
+	/* opcodes w/o data, w/ sync dst */
+	/* opcodes w/ data */
+	HRE_LOAD	= 0x81,
+	/* opcodes w/data, w/sync dst */
+	HRE_XOR		= 0xC1,
+	HRE_AND		= 0xC2,
+	HRE_OR		= 0xC3,
+	HRE_EXTEND	= 0xC4,
+	HRE_LOADKEY	= 0xC5,
+};
+
+/* hre errors */
+enum {
+	HRE_E_OK	= 0,
+	HRE_E_TPM_FAILURE,
+	HRE_E_INVALID_HREG,
+};
+
+static uint64_t device_id;
+static uint64_t device_cl;
+static uint64_t device_type;
+
+static uint32_t platform_key_handle;
+
+static uint32_t hre_tpm_err;
+static int hre_err = HRE_E_OK;
+
+#define IS_PCR_HREG(spec) ((spec) & 0x20)
+#define IS_FIX_HREG(spec) (((spec) & 0x38) == 0x08)
+#define IS_VAR_HREG(spec) (((spec) & 0x38) == 0x10)
+#define HREG_IDX(spec) ((spec) & (IS_PCR_HREG(spec) ? 0x1f : 0x7))
+
+static const uint8_t vendor[] = "Guntermann & Drunck";
+
+/**
+ * @brief get the size of a given (TPM) NV area
+ * @param index	NV index of the area to get size for
+ * @param size	pointer to the size
+ * @return 0 on success, != 0 on error
+ */
+static int get_tpm_nv_size(uint32_t index, uint32_t *size)
+{
+	uint32_t err;
+	uint8_t info[72];
+	uint8_t *ptr;
+	uint16_t v16;
+
+	err = tpm_get_capability(TPM_CAP_NV_INDEX, index,
+		info, sizeof(info));
+	if (err) {
+		printf("tpm_get_capability(CAP_NV_INDEX, %08x) failed: %u\n",
+		       index, err);
+		return 1;
+	}
+
+	/* skip tag and nvIndex */
+	ptr = info + 6;
+	/* skip 2 pcr info fields */
+	v16 = get_unaligned_be16(ptr);
+	ptr += 2 + v16 + 1 + 20;
+	v16 = get_unaligned_be16(ptr);
+	ptr += 2 + v16 + 1 + 20;
+	/* skip permission and flags */
+	ptr += 6 + 3;
+
+	*size = get_unaligned_be32(ptr);
+	return 0;
+}
+
+/**
+ * @brief search for a key by usage auth and pub key hash.
+ * @param auth	usage auth of the key to search for
+ * @param pubkey_digest	(SHA1) hash of the pub key structure of the key
+ * @param[out] handle	the handle of the key iff found
+ * @return 0 if key was found in TPM; != 0 if not.
+ */
+static int find_key(const uint8_t auth[20], const uint8_t pubkey_digest[20],
+		uint32_t *handle)
+{
+	uint16_t key_count;
+	uint32_t key_handles[10];
+	uint8_t buf[288];
+	uint8_t *ptr;
+	uint32_t err;
+	uint8_t digest[20];
+	size_t buf_len;
+	unsigned int i;
+
+	/* fetch list of already loaded keys in the TPM */
+	err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
+	if (err)
+		return -1;
+	key_count = get_unaligned_be16(buf);
+	ptr = buf + 2;
+	for (i = 0; i < key_count; ++i, ptr += 4)
+		key_handles[i] = get_unaligned_be32(ptr);
+
+	/* now search a(/ the) key which we can access with the given auth */
+	for (i = 0; i < key_count; ++i) {
+		buf_len = sizeof(buf);
+		err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
+		if (err && err != TPM_AUTHFAIL)
+			return -1;
+		if (err)
+			continue;
+		sha1_csum(buf, buf_len, digest);
+		if (!memcmp(digest, pubkey_digest, 20)) {
+			*handle = key_handles[i];
+			return 0;
+		}
+	}
+	return 1;
+}
+
+/**
+ * @brief read CCDM common data from TPM NV
+ * @return 0 if CCDM common data was found and read, !=0 if something failed.
+ */
+static int read_common_data(void)
+{
+	uint32_t size = 0;
+	uint32_t err;
+	uint8_t buf[256];
+	sha1_context ctx;
+
+	if (get_tpm_nv_size(NV_COMMON_DATA_INDEX, &size) ||
+	    size < NV_COMMON_DATA_MIN_SIZE)
+		return 1;
+	err = tpm_nv_read_value(NV_COMMON_DATA_INDEX,
+		buf, min(sizeof(buf), size));
+	if (err) {
+		printf("tpm_nv_read_value() failed: %u\n", err);
+		return 1;
+	}
+
+	device_id = get_unaligned_be64(buf);
+	device_cl = get_unaligned_be64(buf + 8);
+	device_type = get_unaligned_be64(buf + 16);
+
+	sha1_starts(&ctx);
+	sha1_update(&ctx, buf, 24);
+	sha1_finish(&ctx, fix_hregs[FIX_HREG_DEVICE_ID_HASH].digest);
+	fix_hregs[FIX_HREG_DEVICE_ID_HASH].valid = true;
+
+	platform_key_handle = get_unaligned_be32(buf + 24);
+
+	return 0;
+}
+
+/**
+ * @brief get pointer to  hash register by specification
+ * @param spec	specification of a hash register
+ * @return pointer to hash register or NULL if @a spec does not qualify a
+ * valid hash register; NULL else.
+ */
+static struct h_reg *get_hreg(uint8_t spec)
+{
+	uint8_t idx;
+
+	idx = HREG_IDX(spec);
+	if (IS_FIX_HREG(spec)) {
+		if (idx < ARRAY_SIZE(fix_hregs))
+			return fix_hregs + idx;
+		hre_err = HRE_E_INVALID_HREG;
+	} else if (IS_PCR_HREG(spec)) {
+		if (idx < ARRAY_SIZE(pcr_hregs))
+			return pcr_hregs + idx;
+		hre_err = HRE_E_INVALID_HREG;
+	} else if (IS_VAR_HREG(spec)) {
+		if (idx < ARRAY_SIZE(var_hregs))
+			return var_hregs + idx;
+		hre_err = HRE_E_INVALID_HREG;
+	}
+	return NULL;
+}
+
+/**
+ * @brief get pointer of a hash register by specification and usage.
+ * @param spec	specification of a hash register
+ * @param mode	access mode (read or write or read/write)
+ * @return pointer to hash register if found and valid; NULL else.
+ *
+ * This func uses @a get_reg() to determine the hash register for a given spec.
+ * If a register is found it is validated according to the desired access mode.
+ * The value of automatic registers (PCR register and fixed registers) is
+ * loaded or computed on read access.
+ */
+static struct h_reg *access_hreg(uint8_t spec, enum access_mode mode)
+{
+	struct h_reg *result;
+
+	result = get_hreg(spec);
+	if (!result)
+		return NULL;
+
+	if (mode & HREG_WR) {
+		if (IS_FIX_HREG(spec)) {
+			hre_err = HRE_E_INVALID_HREG;
+			return NULL;
+		}
+	}
+	if (mode & HREG_RD) {
+		if (!result->valid) {
+			if (IS_PCR_HREG(spec)) {
+				hre_tpm_err = tpm_pcr_read(HREG_IDX(spec),
+					result->digest, 20);
+				result->valid = (hre_tpm_err == TPM_SUCCESS);
+			} else if (IS_FIX_HREG(spec)) {
+				switch (HREG_IDX(spec)) {
+				case FIX_HREG_DEVICE_ID_HASH:
+					read_common_data();
+					break;
+				case FIX_HREG_VENDOR:
+					memcpy(result->digest, vendor, 20);
+					result->valid = true;
+					break;
+				}
+			} else {
+				result->valid = true;
+			}
+		}
+		if (!result->valid) {
+			hre_err = HRE_E_INVALID_HREG;
+			return NULL;
+		}
+	}
+
+	return result;
+}
+
+static void *compute_and(void *_dst, const void *_src, size_t n)
+{
+	uint8_t *dst = _dst;
+	const uint8_t *src = _src;
+	size_t i;
+
+	for (i = n; i-- > 0; )
+		*dst++ &= *src++;
+
+	return _dst;
+}
+
+static void *compute_or(void *_dst, const void *_src, size_t n)
+{
+	uint8_t *dst = _dst;
+	const uint8_t *src = _src;
+	size_t i;
+
+	for (i = n; i-- > 0; )
+		*dst++ |= *src++;
+
+	return _dst;
+}
+
+static void *compute_xor(void *_dst, const void *_src, size_t n)
+{
+	uint8_t *dst = _dst;
+	const uint8_t *src = _src;
+	size_t i;
+
+	for (i = n; i-- > 0; )
+		*dst++ ^= *src++;
+
+	return _dst;
+}
+
+static void *compute_extend(void *_dst, const void *_src, size_t n)
+{
+	uint8_t digest[20];
+	sha1_context ctx;
+
+	sha1_starts(&ctx);
+	sha1_update(&ctx, _dst, n);
+	sha1_update(&ctx, _src, n);
+	sha1_finish(&ctx, digest);
+	memcpy(_dst, digest, min(n, sizeof(digest)));
+
+	return _dst;
+}
+
+static int hre_op_loadkey(struct h_reg *src_reg, struct h_reg *dst_reg,
+		const void *key, size_t key_size)
+{
+	uint32_t parent_handle;
+	uint32_t key_handle;
+
+	if (!src_reg || !dst_reg || !src_reg->valid || !dst_reg->valid)
+		return -1;
+	if (find_key(src_reg->digest, dst_reg->digest, &parent_handle))
+		return -1;
+	hre_tpm_err = tpm_load_key2_oiap(parent_handle, key, key_size,
+		src_reg->digest, &key_handle);
+	if (hre_tpm_err) {
+		hre_err = HRE_E_TPM_FAILURE;
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * @brief executes the next opcode on the hash register engine.
+ * @param[in,out] ip	pointer to the opcode (instruction pointer)
+ * @param[in,out] code_size	(remaining) size of the code
+ * @return new instruction pointer on success, NULL on error.
+ */
+static const uint8_t *hre_execute_op(const uint8_t **ip, size_t *code_size)
+{
+	bool dst_modified = false;
+	uint32_t ins;
+	uint8_t opcode;
+	uint8_t src_spec;
+	uint8_t dst_spec;
+	uint16_t data_size;
+	struct h_reg *src_reg, *dst_reg;
+	uint8_t buf[20];
+	const uint8_t *src_buf, *data;
+	uint8_t *ptr;
+	int i;
+	void * (*bin_func)(void *, const void *, size_t);
+
+	if (*code_size < 4)
+		return NULL;
+
+	ins = get_unaligned_be32(*ip);
+	opcode = **ip;
+	data = *ip + 4;
+	src_spec = (ins >> 18) & 0x3f;
+	dst_spec = (ins >> 12) & 0x3f;
+	data_size = (ins & 0x7ff);
+
+	debug("HRE: ins=%08x (op=%02x, s=%02x, d=%02x, L=%d)\n", ins,
+	      opcode, src_spec, dst_spec, data_size);
+
+	if ((opcode & 0x80) && (data_size + 4) > *code_size)
+		return NULL;
+
+	src_reg = access_hreg(src_spec, HREG_RD);
+	if (hre_err || hre_tpm_err)
+		return NULL;
+	dst_reg = access_hreg(dst_spec, (opcode & 0x40) ? HREG_RDWR : HREG_WR);
+	if (hre_err || hre_tpm_err)
+		return NULL;
+
+	switch (opcode) {
+	case HRE_NOP:
+		goto end;
+	case HRE_CHECK0:
+		if (src_reg) {
+			for (i = 0; i < 20; ++i) {
+				if (src_reg->digest[i])
+					return NULL;
+			}
+		}
+		break;
+	case HRE_LOAD:
+		bin_func = memcpy;
+		goto do_bin_func;
+	case HRE_XOR:
+		bin_func = compute_xor;
+		goto do_bin_func;
+	case HRE_AND:
+		bin_func = compute_and;
+		goto do_bin_func;
+	case HRE_OR:
+		bin_func = compute_or;
+		goto do_bin_func;
+	case HRE_EXTEND:
+		bin_func = compute_extend;
+do_bin_func:
+		if (!dst_reg)
+			return NULL;
+		if (src_reg) {
+			src_buf = src_reg->digest;
+		} else {
+			if (!data_size) {
+				memset(buf, 0, 20);
+				src_buf = buf;
+			} else if (data_size == 1) {
+				memset(buf, *data, 20);
+				src_buf = buf;
+			} else if (data_size >= 20) {
+				src_buf = data;
+			} else {
+				src_buf = buf;
+				for (ptr = (uint8_t *)src_buf, i = 20; i > 0;
+					i -= data_size, ptr += data_size)
+					memcpy(ptr, data,
+					       min_t(size_t, i, data_size));
+			}
+		}
+		bin_func(dst_reg->digest, src_buf, 20);
+		dst_reg->valid = true;
+		dst_modified = true;
+		break;
+	case HRE_LOADKEY:
+		if (hre_op_loadkey(src_reg, dst_reg, data, data_size))
+			return NULL;
+		break;
+	default:
+		return NULL;
+	}
+
+	if (dst_reg && dst_modified && IS_PCR_HREG(dst_spec)) {
+		hre_tpm_err = tpm_extend(HREG_IDX(dst_spec), dst_reg->digest,
+			dst_reg->digest);
+		if (hre_tpm_err) {
+			hre_err = HRE_E_TPM_FAILURE;
+			return NULL;
+		}
+	}
+end:
+	*ip += 4;
+	*code_size -= 4;
+	if (opcode & 0x80) {
+		*ip += data_size;
+		*code_size -= data_size;
+	}
+
+	return *ip;
+}
+
+/**
+ * @brief runs a program on the hash register engine.
+ * @param code		pointer to the (HRE) code.
+ * @param code_size	size of the code (in bytes).
+ * @return 0 on success, != 0 on failure.
+ */
+int hre_run_program(const uint8_t *code, size_t code_size)
+{
+	size_t code_left;
+	const uint8_t *ip = code;
+
+	code_left = code_size;
+	hre_tpm_err = 0;
+	hre_err = HRE_E_OK;
+	while (code_left > 0)
+		if (!hre_execute_op(&ip, &code_left))
+			return -1;
+
+	return hre_err;
+}
+
+int hre_verify_program(struct key_program *prg)
+{
+	uint32_t crc;
+
+	crc = crc32(0, prg->code, prg->code_size);
+
+	if (crc != prg->code_crc) {
+		printf("HRC crc mismatch: %08x != %08x\n",
+		       crc, prg->code_crc);
+		return 1;
+	}
+	return 0;
+}
diff --git a/board/gdsys/a38x/hre.h b/board/gdsys/a38x/hre.h
new file mode 100644
index 0000000000..84ce2794fa
--- /dev/null
+++ b/board/gdsys/a38x/hre.h
@@ -0,0 +1,38 @@
+/*
+ * (C) Copyright 2013
+ * Reinhard Pfau, Guntermann & Drunck GmbH, reinhard.pfau at gdsys.cc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __HRE_H
+#define __HRE_H
+
+struct key_program {
+	uint32_t magic;
+	uint32_t code_crc;
+	uint32_t code_size;
+	uint8_t code[];
+};
+
+struct h_reg {
+	bool valid;
+	uint8_t digest[20];
+};
+
+/* CCDM specific contants */
+enum {
+	/* NV indices */
+	NV_COMMON_DATA_INDEX	= 0x40000001,
+	/* magics for key blob chains */
+	MAGIC_KEY_PROGRAM	= 0x68726500,
+	MAGIC_HMAC		= 0x68616300,
+	MAGIC_END_OF_CHAIN	= 0x00000000,
+	/* sizes */
+	NV_COMMON_DATA_MIN_SIZE	= 3 * sizeof(uint64_t) + 2 * sizeof(uint16_t),
+};
+
+int hre_verify_program(struct key_program *prg);
+int hre_run_program(const uint8_t *code, size_t code_size);
+
+#endif /* __HRE_H */
diff --git a/board/gdsys/a38x/hydra.c b/board/gdsys/a38x/hydra.c
new file mode 100644
index 0000000000..fa50ad2830
--- /dev/null
+++ b/board/gdsys/a38x/hydra.c
@@ -0,0 +1,138 @@
+#include <common.h>
+#include <console.h> /* ctrlc */
+#include <asm/io.h>
+
+#include "hydra.h"
+
+enum {
+	HWVER_100 = 0,
+	HWVER_110 = 1,
+	HWVER_120 = 2,
+};
+
+static struct pci_device_id hydra_supported[] = {
+	{ 0x6d5e, 0xcdc1 },
+	{}
+};
+
+static struct ihs_fpga *fpga;
+
+struct ihs_fpga *get_fpga(void)
+{
+	return fpga;
+}
+
+void print_hydra_version(uint index)
+{
+	u32 versions = readl(&fpga->versions);
+	u32 fpga_version = readl(&fpga->fpga_version);
+
+	uint hardware_version = versions & 0xf;
+
+	printf("FPGA%u: mapped to %p\n       ", index, fpga);
+
+	switch (hardware_version) {
+	case HWVER_100:
+		printf("HW-Ver 1.00\n");
+		break;
+
+	case HWVER_110:
+		printf("HW-Ver 1.10\n");
+		break;
+
+	case HWVER_120:
+		printf("HW-Ver 1.20\n");
+		break;
+
+	default:
+		printf("HW-Ver %d(not supported)\n",
+		       hardware_version);
+		break;
+	}
+
+	printf("       FPGA V %d.%02d\n",
+	       fpga_version / 100, fpga_version % 100);
+}
+
+void hydra_initialize(void)
+{
+	uint i;
+	pci_dev_t devno;
+
+	/* Find and probe all the matching PCI devices */
+	for (i = 0; (devno = pci_find_devices(hydra_supported, i)) >= 0; i++) {
+		u32 val;
+
+		/* Try to enable I/O accesses and bus-mastering */
+		val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+		pci_write_config_dword(devno, PCI_COMMAND, val);
+
+		/* Make sure it worked */
+		pci_read_config_dword(devno, PCI_COMMAND, &val);
+		if (!(val & PCI_COMMAND_MEMORY)) {
+			puts("Can't enable I/O memory\n");
+			continue;
+		}
+		if (!(val & PCI_COMMAND_MASTER)) {
+			puts("Can't enable bus-mastering\n");
+			continue;
+		}
+
+		/* read FPGA details */
+		fpga = pci_map_bar(devno, PCI_BASE_ADDRESS_0,
+				   PCI_REGION_MEM);
+
+		print_hydra_version(i);
+	}
+}
+
+#define REFL_PATTERN (0xdededede)
+#define REFL_PATTERN_INV (~REFL_PATTERN)
+
+int do_hydrate(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	uint k = 0;
+	void __iomem *pcie2_base = (void __iomem *)(MVEBU_REG_PCIE_BASE +
+						    0x4000);
+
+	if (!fpga)
+		return -1;
+
+	while (1) {
+		u32 res;
+
+		writel(REFL_PATTERN, &fpga->reflection_low);
+		res = readl(&fpga->reflection_low);
+		if (res != REFL_PATTERN_INV)
+			printf("round %u: read %08x, expected %08x\n",
+			       k, res, REFL_PATTERN_INV);
+		writel(REFL_PATTERN_INV, &fpga->reflection_low);
+		res = readl(&fpga->reflection_low);
+		if (res != REFL_PATTERN)
+			printf("round %u: read %08x, expected %08x\n",
+			       k, res, REFL_PATTERN);
+
+		res = readl(pcie2_base + 0x118) & 0x1f;
+		if (res)
+			printf("FrstErrPtr %u\n", res);
+		res = readl(pcie2_base + 0x104);
+		if (res) {
+			printf("Uncorrectable Error Status 0x%08x\n", res);
+			writel(res, pcie2_base + 0x104);
+		}
+
+		if (!(++k % 10000))
+			printf("round %u\n", k);
+
+		if (ctrlc())
+			break;
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	hydrate,	1,	0,	do_hydrate,
+	"hydra reflection test",
+	"hydra reflection test"
+);
diff --git a/board/gdsys/a38x/hydra.h b/board/gdsys/a38x/hydra.h
new file mode 100644
index 0000000000..26562a560a
--- /dev/null
+++ b/board/gdsys/a38x/hydra.h
@@ -0,0 +1,14 @@
+struct ihs_fpga {
+	u32 reflection_low;		/* 0x0000 */
+	u32 versions;			/* 0x0004 */
+	u32 fpga_version;		/* 0x0008 */
+	u32 fpga_features;		/* 0x000c */
+	u32 reserved0[4];		/* 0x0010 */
+	u32 control;			/* 0x0020 */
+	u32 reserved1[375];		/* 0x0024 */
+	u32 qsgmii_port_state[80];	/* 0x0600 */
+};
+
+void print_hydra_version(uint index);
+void hydra_initialize(void);
+struct ihs_fpga *get_fpga(void);
diff --git a/board/gdsys/a38x/ihs_phys.c b/board/gdsys/a38x/ihs_phys.c
new file mode 100644
index 0000000000..494de18f86
--- /dev/null
+++ b/board/gdsys/a38x/ihs_phys.c
@@ -0,0 +1,355 @@
+#include <common.h>
+#include <dm.h>
+#include <miiphy.h>
+#include <asm-generic/gpio.h>
+
+#include "ihs_phys.h"
+#include "dt_helpers.h"
+
+enum {
+	PORTTYPE_MAIN_CAT,
+	PORTTYPE_TOP_CAT,
+	PORTTYPE_16C_16F,
+	PORTTYPE_UNKNOWN
+};
+
+static struct porttype {
+	bool phy_invert_in_pol;
+	bool phy_invert_out_pol;
+} porttypes[] = {
+	{ true, false },
+	{ false, true },
+	{ false, false },
+};
+
+static void ihs_phy_config(struct phy_device *phydev, bool qinpn, bool qoutpn)
+{
+	u16 reg;
+
+	phy_config(phydev);
+
+	/* enable QSGMII autonegotiation with flow control */
+	phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0004);
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, 16);
+	reg |= (3 << 6);
+	phy_write(phydev, MDIO_DEVAD_NONE, 16, reg);
+
+	/*
+	 * invert QSGMII Q_INP/N and Q_OUTP/N if required
+	 * and perform global reset
+	 */
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, 26);
+	if (qinpn)
+		reg |= (1 << 13);
+	if (qoutpn)
+		reg |= (1 << 12);
+	reg |= (1 << 15);
+	phy_write(phydev, MDIO_DEVAD_NONE, 26, reg);
+
+	/* advertise 1000BASE-T full-duplex only  */
+	phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000);
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, 4);
+	reg &= ~0x1e0;
+	phy_write(phydev, MDIO_DEVAD_NONE, 4, reg);
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, 9);
+	reg = (reg & ~0x300) | 0x200;
+	phy_write(phydev, MDIO_DEVAD_NONE, 9, reg);
+
+	/* copper power up */
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, 16);
+	reg &= ~0x0004;
+	phy_write(phydev, MDIO_DEVAD_NONE, 16, reg);
+}
+
+uint calculate_octo_phy_mask(void)
+{
+	uint k;
+	uint octo_phy_mask = 0;
+	struct gpio_desc gpio = {};
+	char gpio_name[64];
+	static const char * const dev_name[] = {"pca9698 at 23", "pca9698 at 21",
+						"pca9698 at 24", "pca9698 at 25",
+						"pca9698@26"};
+
+	/* mark all octo phys that should be present */
+	for (k = 0; k < 5; ++k) {
+		snprintf(gpio_name, 64, "cat-gpio-%u", k);
+
+		if (request_gpio_by_name(&gpio, dev_name[k], 0x20, gpio_name))
+			continue;
+
+		/* check CAT flag */
+		if (dm_gpio_get_value(&gpio))
+			octo_phy_mask |= (1 << (k * 2));
+		else
+			/* If CAT == 0, there's no second octo phy -> skip */
+			continue;
+
+		snprintf(gpio_name, 64, "second-octo-gpio-%u", k);
+
+		if (request_gpio_by_name(&gpio, dev_name[k], 0x27, gpio_name)) {
+			/* default: second octo phy is present */
+			octo_phy_mask |= (1 << (k * 2 + 1));
+			continue;
+		}
+
+		if (dm_gpio_get_value(&gpio) == 0)
+			octo_phy_mask |= (1 << (k * 2 + 1));
+	}
+
+	return octo_phy_mask;
+}
+
+int register_miiphy_bus(uint k, struct mii_dev **bus)
+{
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	char *name = bb_miiphy_buses[k].name;
+
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name,
+		name,
+		MDIO_NAME_LEN);
+	mdiodev->read = bb_miiphy_read;
+	mdiodev->write = bb_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
+	*bus = miiphy_get_dev_by_name(name);
+
+	return 0;
+}
+
+struct porttype *get_porttype(uint octo_phy_mask, uint k)
+{
+	uint octo_index = k * 4;
+
+	if (!k) {
+		if (octo_phy_mask & 0x01)
+			return &porttypes[PORTTYPE_MAIN_CAT];
+		else if (!(octo_phy_mask & 0x03))
+			return &porttypes[PORTTYPE_16C_16F];
+	} else {
+		if (octo_phy_mask & (1 << octo_index))
+			return &porttypes[PORTTYPE_TOP_CAT];
+	}
+
+	return NULL;
+}
+
+int init_single_phy(struct porttype *porttype, struct mii_dev *bus,
+		    uint bus_idx, uint m, uint phy_idx)
+{
+	struct phy_device *phydev = phy_find_by_mask(
+		bus, 1 << (m * 8 + phy_idx),
+		PHY_INTERFACE_MODE_MII);
+
+	printf(" %u", bus_idx * 32 + m * 8 + phy_idx);
+
+	if (!phydev)
+		puts("!");
+	else
+		ihs_phy_config(phydev, porttype->phy_invert_in_pol,
+			       porttype->phy_invert_out_pol);
+
+	return 0;
+}
+
+int init_octo_phys(uint octo_phy_mask)
+{
+	uint bus_idx;
+
+	/* there are up to four octo-phys on each mdio bus */
+	for (bus_idx = 0; bus_idx < bb_miiphy_buses_num; ++bus_idx) {
+		uint m;
+		uint octo_index = bus_idx * 4;
+		struct mii_dev *bus = NULL;
+		struct porttype *porttype = NULL;
+		int ret;
+
+		porttype = get_porttype(octo_phy_mask, bus_idx);
+
+		if (!porttype)
+			continue;
+
+		for (m = 0; m < 4; ++m) {
+			uint phy_idx;
+
+			/**
+			 * Register a bus device if there is@least one phy
+			 * on the current bus
+			 */
+			if (!m && octo_phy_mask & (0xf << octo_index)) {
+				ret = register_miiphy_bus(bus_idx, &bus);
+				if (ret)
+					return ret;
+			}
+
+			if (!(octo_phy_mask & BIT(octo_index + m)))
+				continue;
+
+			for (phy_idx = 0; phy_idx < 8; ++phy_idx)
+				init_single_phy(porttype, bus, bus_idx, m,
+						phy_idx);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * MII GPIO bitbang implementation
+ * MDC MDIO bus
+ * 13  14   PHY1-4
+ * 25  45   PHY5-8
+ * 46  24   PHY9-10
+ */
+
+struct gpio_mii {
+	int index;
+	struct gpio_desc mdc_gpio;
+	struct gpio_desc mdio_gpio;
+	int mdc_num;
+	int mdio_num;
+	int mdio_value;
+} gpio_mii_set[] = {
+	{ 0, {}, {}, 13, 14, 1 },
+	{ 1, {}, {}, 25, 45, 1 },
+	{ 2, {}, {}, 46, 24, 1 },
+};
+
+static int mii_mdio_init(struct bb_miiphy_bus *bus)
+{
+	struct gpio_mii *gpio_mii = bus->priv;
+	char name[32] = {};
+	struct udevice *gpio_dev1 = NULL;
+	struct udevice *gpio_dev2 = NULL;
+
+	if (uclass_get_device_by_name(UCLASS_GPIO, "gpio at 18100", &gpio_dev1) ||
+	    uclass_get_device_by_name(UCLASS_GPIO, "gpio at 18140", &gpio_dev2)) {
+		printf("Could not get GPIO device.\n");
+		return 1;
+	}
+
+	if (gpio_mii->mdc_num > 31) {
+		gpio_mii->mdc_gpio.dev = gpio_dev2;
+		gpio_mii->mdc_gpio.offset = gpio_mii->mdc_num - 32;
+	} else {
+		gpio_mii->mdc_gpio.dev = gpio_dev1;
+		gpio_mii->mdc_gpio.offset = gpio_mii->mdc_num;
+	}
+	gpio_mii->mdc_gpio.flags = 0;
+	snprintf(name, 32, "bb_miiphy_bus-%d-mdc", gpio_mii->index);
+	dm_gpio_request(&gpio_mii->mdc_gpio, name);
+
+	if (gpio_mii->mdio_num > 31) {
+		gpio_mii->mdio_gpio.dev = gpio_dev2;
+		gpio_mii->mdio_gpio.offset = gpio_mii->mdio_num - 32;
+	} else {
+		gpio_mii->mdio_gpio.dev = gpio_dev1;
+		gpio_mii->mdio_gpio.offset = gpio_mii->mdio_num;
+	}
+	gpio_mii->mdio_gpio.flags = 0;
+	snprintf(name, 32, "bb_miiphy_bus-%d-mdio", gpio_mii->index);
+	dm_gpio_request(&gpio_mii->mdio_gpio, name);
+
+	dm_gpio_set_dir_flags(&gpio_mii->mdc_gpio, GPIOD_IS_OUT);
+	dm_gpio_set_value(&gpio_mii->mdc_gpio, 1);
+
+	return 0;
+}
+
+static int mii_mdio_active(struct bb_miiphy_bus *bus)
+{
+	struct gpio_mii *gpio_mii = bus->priv;
+
+	dm_gpio_set_value(&gpio_mii->mdc_gpio, gpio_mii->mdio_value);
+
+	return 0;
+}
+
+static int mii_mdio_tristate(struct bb_miiphy_bus *bus)
+{
+	struct gpio_mii *gpio_mii = bus->priv;
+
+	dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN);
+
+	return 0;
+}
+
+static int mii_set_mdio(struct bb_miiphy_bus *bus, int v)
+{
+	struct gpio_mii *gpio_mii = bus->priv;
+
+	dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_OUT);
+	dm_gpio_set_value(&gpio_mii->mdio_gpio, v);
+	gpio_mii->mdio_value = v;
+
+	return 0;
+}
+
+static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v)
+{
+	struct gpio_mii *gpio_mii = bus->priv;
+
+	dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN);
+	*v = (dm_gpio_get_value(&gpio_mii->mdio_gpio));
+
+	return 0;
+}
+
+static int mii_set_mdc(struct bb_miiphy_bus *bus, int v)
+{
+	struct gpio_mii *gpio_mii = bus->priv;
+
+	dm_gpio_set_value(&gpio_mii->mdc_gpio, v);
+
+	return 0;
+}
+
+static int mii_delay(struct bb_miiphy_bus *bus)
+{
+	udelay(1);
+
+	return 0;
+}
+
+struct bb_miiphy_bus bb_miiphy_buses[] = {
+	{
+		.name = "ihs0",
+		.init = mii_mdio_init,
+		.mdio_active = mii_mdio_active,
+		.mdio_tristate = mii_mdio_tristate,
+		.set_mdio = mii_set_mdio,
+		.get_mdio = mii_get_mdio,
+		.set_mdc = mii_set_mdc,
+		.delay = mii_delay,
+		.priv = &gpio_mii_set[0],
+	},
+	{
+		.name = "ihs1",
+		.init = mii_mdio_init,
+		.mdio_active = mii_mdio_active,
+		.mdio_tristate = mii_mdio_tristate,
+		.set_mdio = mii_set_mdio,
+		.get_mdio = mii_get_mdio,
+		.set_mdc = mii_set_mdc,
+		.delay = mii_delay,
+		.priv = &gpio_mii_set[1],
+	},
+	{
+		.name = "ihs2",
+		.init = mii_mdio_init,
+		.mdio_active = mii_mdio_active,
+		.mdio_tristate = mii_mdio_tristate,
+		.set_mdio = mii_set_mdio,
+		.get_mdio = mii_get_mdio,
+		.set_mdc = mii_set_mdc,
+		.delay = mii_delay,
+		.priv = &gpio_mii_set[2],
+	},
+};
+
+int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses);
diff --git a/board/gdsys/a38x/ihs_phys.h b/board/gdsys/a38x/ihs_phys.h
new file mode 100644
index 0000000000..c4bec4d46c
--- /dev/null
+++ b/board/gdsys/a38x/ihs_phys.h
@@ -0,0 +1,2 @@
+uint calculate_octo_phy_mask(void);
+int init_octo_phys(uint octo_phy_mask);
diff --git a/board/gdsys/a38x/keyprogram.c b/board/gdsys/a38x/keyprogram.c
new file mode 100644
index 0000000000..a4a6f1cca5
--- /dev/null
+++ b/board/gdsys/a38x/keyprogram.c
@@ -0,0 +1,158 @@
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <tpm.h>
+#include <malloc.h>
+#include <linux/ctype.h>
+#include <asm/unaligned.h>
+
+#include "hre.h"
+
+int flush_keys(void)
+{
+	u16 key_count;
+	u8 buf[288];
+	u8 *ptr;
+	u32 err;
+	uint i;
+
+	/* fetch list of already loaded keys in the TPM */
+	err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
+	if (err)
+		return -1;
+	key_count = get_unaligned_be16(buf);
+	ptr = buf + 2;
+	for (i = 0; i < key_count; ++i, ptr += 4) {
+		err = tpm_flush_specific(get_unaligned_be32(ptr), TPM_RT_KEY);
+		if (err && err != TPM_KEY_OWNER_CONTROL)
+			return err;
+	}
+
+	return 0;
+}
+
+int decode_hexstr(char *hexstr, u8 **result)
+{
+	int len = strlen(hexstr);
+	int bytes = len / 2;
+	int i;
+	u8 acc = 0;
+
+	if (len % 2 == 1)
+		return 1;
+
+	*result = (u8 *)malloc(bytes);
+
+	for (i = 0; i < len; i++) {
+		char cur = tolower(hexstr[i]);
+		u8 val;
+
+		if ((cur >= 'a' && cur <= 'f') || (cur >= '0' && cur <= '9')) {
+			val = cur - (cur > '9' ? 87 : 48);
+
+			if (i % 2 == 0)
+				acc = 16 * val;
+			else
+				(*result)[i / 2] = acc + val;
+		} else {
+			free(*result);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+int extract_subprogram(u8 **progdata, u32 expected_magic,
+		       struct key_program **result)
+{
+	struct key_program *prog = *result;
+	u32 magic, code_crc, code_size;
+
+	magic = get_unaligned_be32(*progdata);
+	code_crc = get_unaligned_be32(*progdata + 4);
+	code_size = get_unaligned_be32(*progdata + 8);
+
+	*progdata += 12;
+
+	if (magic != expected_magic)
+		return -1;
+
+	*result = malloc(sizeof(struct key_program) + code_size);
+
+	if (!*result)
+		return -1;
+
+	prog->magic = magic;
+	prog->code_crc = code_crc;
+	prog->code_size = code_size;
+	memcpy(prog->code, *progdata, code_size);
+
+	*progdata += code_size;
+
+	if (hre_verify_program(prog)) {
+		free(prog);
+		return -1;
+	}
+
+	return 0;
+}
+
+struct key_program *parse_and_check_keyprog(u8 *progdata)
+{
+	struct key_program *result = NULL, *hmac = NULL;
+
+	/* Part 1: Load key program */
+
+	if (extract_subprogram(&progdata, MAGIC_KEY_PROGRAM, &result))
+		return NULL;
+
+	/* Part 2: Load hmac program */
+
+	if (extract_subprogram(&progdata, MAGIC_HMAC, &hmac))
+		return NULL;
+
+	free(hmac);
+
+	return result;
+}
+
+int load_and_run_keyprog(void)
+{
+	char *cmd = NULL;
+	u8 *binprog = NULL;
+	char *hexprog;
+	struct key_program *prog;
+
+	cmd = getenv("loadkeyprogram");
+
+	if (!cmd || run_command(cmd, 0))
+		return 1;
+
+	hexprog = getenv("keyprogram");
+
+	if (decode_hexstr(hexprog, &binprog))
+		return 1;
+
+	prog = parse_and_check_keyprog(binprog);
+	free(binprog);
+
+	if (!prog)
+		return 1;
+
+	if (hre_run_program(prog->code, prog->code_size)) {
+		free(prog);
+		return 1;
+	}
+
+	printf("\nSD code ran successfully\n");
+
+	free(prog);
+
+	return 0;
+}
diff --git a/board/gdsys/a38x/keyprogram.h b/board/gdsys/a38x/keyprogram.h
new file mode 100644
index 0000000000..a5ea7d3137
--- /dev/null
+++ b/board/gdsys/a38x/keyprogram.h
@@ -0,0 +1,14 @@
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __KEYPROGRAM_H
+#define __KEYPROGRAM_H
+
+int load_and_run_keyprog(void);
+int flush_keys(void);
+
+#endif /* __KEYPROGRAM_H */
diff --git a/board/gdsys/a38x/kwbimage.cfg.in b/board/gdsys/a38x/kwbimage.cfg.in
new file mode 100644
index 0000000000..72e67d75c3
--- /dev/null
+++ b/board/gdsys/a38x/kwbimage.cfg.in
@@ -0,0 +1,12 @@
+#
+# Copyright (C) 2014 Stefan Roese <sr@denx.de>
+#
+
+# Armada 38x uses version 1 image format
+VERSION		1
+
+# Boot Media configurations
+#@BOOT_FROM
+
+# Binary Header (bin_hdr) with DDR3 training code
+BINARY spl/u-boot-spl.bin 0000005b 00000068
diff --git a/board/gdsys/a38x/spl.c b/board/gdsys/a38x/spl.c
new file mode 100644
index 0000000000..2d05a9c98a
--- /dev/null
+++ b/board/gdsys/a38x/spl.c
@@ -0,0 +1,21 @@
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/arch/cpu.h>
+
+void spl_board_init(void)
+{
+#if CONFIG_SPL_BOOT_DEVICE == SPL_BOOT_SPI_NOR_FLASH
+	u32 *bootrom_save = (u32 *)CONFIG_SPL_BOOTROM_SAVE;
+	u32 *regs = (u32 *)(*bootrom_save);
+
+	printf("Returning to BootROM (return address %08x)...\n", regs[13]);
+	return_to_bootrom();
+#endif
+}
diff --git a/configs/controlcenterdc_defconfig b/configs/controlcenterdc_defconfig
new file mode 100644
index 0000000000..e1c4f0c999
--- /dev/null
+++ b/configs/controlcenterdc_defconfig
@@ -0,0 +1,58 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_SPL_GPIO_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_TARGET_CONTROLCENTERDC=y
+CONFIG_SPL_SPI_FLASH_SUPPORT=y
+CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_DEFAULT_DEVICE_TREE="armada-38x-controlcenterdc"
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_SPL=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+CONFIG_HUSH_PARSER=y
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_GO is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_GPIO=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_TPM=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_EFI_PARTITION=y
+CONFIG_OF_BOARD_FIXUP=y
+CONFIG_SPL_OF_TRANSLATE=y
+CONFIG_DM_GPIO=y
+CONFIG_DM_PCA953X=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_MVTWSI=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_MV=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xd0012000
+CONFIG_DEBUG_UART_CLOCK=250000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_TPM_ATMEL_TWI=y
+CONFIG_TPM_AUTH_SESSIONS=y
+CONFIG_TPM_FLUSH_RESOURCES=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_TPM=y
+# CONFIG_EFI_LOADER is not set
diff --git a/include/configs/controlcenterdc.h b/include/configs/controlcenterdc.h
new file mode 100644
index 0000000000..add5f90cc2
--- /dev/null
+++ b/include/configs/controlcenterdc.h
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2016 Mario Six <mario.six@gdsys.cc>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _CONFIG_CONTROLCENTERDC_H
+#define _CONFIG_CONTROLCENTERDC_H
+
+/*
+ * High Level Configuration Options (easy to change)
+ */
+#define CONFIG_CUSTOMER_BOARD_SUPPORT
+
+#define CONFIG_SKIP_LOWLEVEL_INIT	/* disable board lowlevel_init */
+#define CONFIG_DISPLAY_BOARDINFO_LATE
+#define CONFIG_BOARD_LATE_INIT
+#define CONFIG_LAST_STAGE_INIT
+#define CONFIG_SPL_BOARD_INIT
+
+/*
+ * TEXT_BASE needs to be below 16MiB, since this area is scrubbed
+ * for DDR ECC byte filling in the SPL before loading the main
+ * U-Boot into it.
+ */
+#define	CONFIG_SYS_TEXT_BASE	0x00800000
+
+#define CONFIG_SYS_TCLK		250000000	/* 250MHz */
+
+#define CONFIG_LOADADDR 		1000000
+
+/*
+ * Commands configuration
+ */
+#define CONFIG_CMD_ENV
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_SCSI
+#define CONFIG_CMD_SPI
+
+/* SPI NOR flash default params, used by sf commands */
+#define CONFIG_SF_DEFAULT_BUS		1
+#define CONFIG_SF_DEFAULT_SPEED		1000000
+#define CONFIG_SF_DEFAULT_MODE		SPI_MODE_3
+
+/*
+ * SDIO/MMC Card Configuration
+ */
+#define CONFIG_SYS_MMC_BASE		MVEBU_SDIO_BASE
+
+/*
+ * SATA/SCSI/AHCI configuration
+ */
+#define CONFIG_LIBATA
+#define CONFIG_SCSI
+#define CONFIG_SCSI_AHCI
+#define CONFIG_SCSI_AHCI_PLAT
+#define CONFIG_SYS_SCSI_MAX_SCSI_ID	2
+#define CONFIG_SYS_SCSI_MAX_LUN		1
+#define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
+					 CONFIG_SYS_SCSI_MAX_LUN)
+
+/* Additional FS support/configuration */
+#define CONFIG_SUPPORT_VFAT
+
+/* USB/EHCI configuration */
+#define CONFIG_EHCI_IS_TDI
+
+/* Environment in SPI NOR flash */
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_SPI_BUS		1
+#define CONFIG_ENV_OFFSET		(1 << 20) /* 1MiB in */
+#define CONFIG_ENV_SIZE			(64 << 10) /* 64KiB */
+#define CONFIG_ENV_SECT_SIZE		(256 << 10) /* 256KiB sectors */
+
+#define CONFIG_PHY_MARVELL		/* there is a marvell phy */
+#define PHY_ANEG_TIMEOUT	8000	/* PHY needs a longer aneg time */
+
+/* PCIe support */
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_PCI
+#define CONFIG_PCI_MVEBU
+#define CONFIG_PCI_PNP
+#define CONFIG_PCI_SCAN_SHOW
+#endif
+
+#define CONFIG_SYS_ALT_MEMTEST
+
+/*
+ * Software (bit-bang) MII driver configuration
+ */
+#define CONFIG_BITBANGMII		/* bit-bang MII PHY management */
+#define CONFIG_BITBANGMII_MULTI
+
+/* SPL */
+/*
+ * Select the boot device here
+ *
+ * Currently supported are:
+ * SPL_BOOT_SPI_NOR_FLASH	- Booting via SPI NOR flash
+ * SPL_BOOT_SDIO_MMC_CARD	- Booting via SDIO/MMC card (partition 1)
+ */
+#define SPL_BOOT_SPI_NOR_FLASH		1
+#define SPL_BOOT_SDIO_MMC_CARD		2
+#define CONFIG_SPL_BOOT_DEVICE		SPL_BOOT_SPI_NOR_FLASH
+
+/* Defines for SPL */
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_SIZE			(160 << 10)
+
+#if defined(CONFIG_SECURED_MODE_IMAGE)
+#define CONFIG_SPL_TEXT_BASE		0x40002614
+#define CONFIG_SPL_MAX_SIZE		(CONFIG_SPL_SIZE - 0x2614)
+#else
+#define CONFIG_SPL_TEXT_BASE		0x40000030
+#define CONFIG_SPL_MAX_SIZE		(CONFIG_SPL_SIZE - 0x30)
+#endif
+
+#define CONFIG_SPL_BSS_START_ADDR	(0x40000000 + CONFIG_SPL_SIZE)
+#define CONFIG_SPL_BSS_MAX_SIZE		(16 << 10)
+
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_MALLOC_SIMPLE
+#endif
+
+#define CONFIG_SPL_STACK		(0x40000000 + ((212 - 16) << 10))
+#define CONFIG_SPL_BOOTROM_SAVE		(CONFIG_SPL_STACK + 4)
+
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_I2C_SUPPORT
+
+#if CONFIG_SPL_BOOT_DEVICE == SPL_BOOT_SPI_NOR_FLASH
+/* SPL related SPI defines */
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x30000
+#define CONFIG_SYS_U_BOOT_OFFS		CONFIG_SYS_SPI_U_BOOT_OFFS
+#endif
+
+#if CONFIG_SPL_BOOT_DEVICE == SPL_BOOT_SDIO_MMC_CARD
+/* SPL related MMC defines */
+#define CONFIG_SPL_MMC_SUPPORT
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION 1
+#define CONFIG_SYS_MMC_U_BOOT_OFFS		(168 << 10)
+#define CONFIG_SYS_U_BOOT_OFFS			CONFIG_SYS_MMC_U_BOOT_OFFS
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR	(CONFIG_SYS_U_BOOT_OFFS / 512)
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_FIXED_SDHCI_ALIGNED_BUFFER	0x00180000	/* in SDRAM */
+#endif
+#endif
+
+/*
+ * Environment Configuration
+ */
+#define CONFIG_ENV_OVERWRITE
+
+#define CONFIG_BAUDRATE 115200
+
+#define CONFIG_HOSTNAME		ccdc
+#define CONFIG_ROOTPATH		"/opt/nfsroot"
+#define CONFIG_BOOTFILE		"ccdc.img"
+
+#define CONFIG_PREBOOT		/* enable preboot variable */
+
+#define CONFIG_EXTRA_ENV_SETTINGS						\
+	"netdev=eth1\0"						\
+	"consoledev=ttyS1\0"							\
+	"u-boot=u-boot.bin\0"							\
+	"bootfile_addr=1000000\0"						\
+	"keyprogram_addr=3000000\0"						\
+	"keyprogram_file=keyprogram.img\0"						\
+	"fdtfile=controlcenterdc.dtb\0"						\
+	"load=tftpboot ${loadaddr} ${u-boot}\0"					\
+	"mmcdev=0:2\0"								\
+	"update=sf probe 1:0;"							\
+		" sf erase 0 +${filesize};"					\
+		" sf write ${fileaddr} 0 ${filesize}\0"				\
+	"upd=run load update\0"							\
+	"fdt_high=0x10000000\0"							\
+	"initrd_high=0x10000000\0"						\
+	"loadkeyprogram=tpm flush_keys;"					\
+		" mmc rescan;"							\
+		" ext4load mmc ${mmcdev} ${keyprogram_addr} ${keyprogram_file};"\
+		" source ${keyprogram_addr}:script at 1\0"				\
+	"gpio1=gpio@22_25\0"							\
+	"gpio2=A29\0"								\
+	"blinkseq='0 0 0 0 2 0 2 2 3 1 3 1 0 0 2 2 3 1 3 3 2 0 2 2 3 1 1 1 "	\
+		  "2 0 2 2 3 1 3 1 0 0 2 0 3 3 3 1 2 0 0 0 3 1 1 1 0 0 0 0'\0"	\
+	"bootfail=for i in ${blinkseq}; do"					\
+		" if test $i -eq 0; then"					\
+		" gpio clear ${gpio1}; gpio set ${gpio2};"			\
+		" elif test $i -eq 1; then"					\
+		" gpio clear ${gpio1}; gpio clear ${gpio2};"			\
+		" elif test $i -eq 2; then"					\
+		" gpio set ${gpio1}; gpio set ${gpio2};"			\
+		" else;"							\
+		" gpio clear ${gpio1}; gpio set ${gpio2};"			\
+		" fi; sleep 0.12; done\0"
+
+#define CONFIG_NFSBOOTCOMMAND								\
+	"setenv bootargs root=/dev/nfs rw "						\
+	"nfsroot=${serverip}:${rootpath} "						\
+	"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off "	\
+	"console=${consoledev},${baudrate} ${othbootargs}; "				\
+	"tftpboot ${bootfile_addr} ${bootfile}; "						\
+	"bootm ${bootfile_addr}"
+
+#define CONFIG_MMCBOOTCOMMAND					\
+	"setenv bootargs root=/dev/mmcblk0p3 rw rootwait "	\
+	"console=${consoledev},${baudrate} ${othbootargs}; "	\
+	"ext2load mmc 0:2 ${bootfile_addr} ${bootfile}; "	\
+	"bootm ${bootfile_addr}"
+
+#define CONFIG_BOOTCOMMAND			\
+	"if env exists keyprogram; then;"	\
+	" setenv keyprogram; run nfsboot;"	\
+        " fi;"					\
+        " run dobootfail"
+
+/*
+ * mv-common.h should be defined after CMD configs since it used them
+ * to enable certain macros
+ */
+#include "mv-common.h"
+
+#endif /* _CONFIG_CONTROLCENTERDC_H */
--
2.11.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH 3/3 v3] controlcenterdc: Make secure boot available
  2017-02-22 15:07 [U-Boot] [PATCH 0/3 v3] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
  2017-02-22 15:07 ` [U-Boot] [PATCH 1/3 v3] dm: Add callback to modify the device tree Mario Six
  2017-02-22 15:07 ` [U-Boot] [PATCH 2/3 v3] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
@ 2017-02-22 15:07 ` Mario Six
  2017-03-23  9:31   ` Stefan Roese
  2 siblings, 1 reply; 12+ messages in thread
From: Mario Six @ 2017-02-22 15:07 UTC (permalink / raw)
  To: u-boot

Make secure booting available for the controlcenterdc
board.

Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>
Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v3:

* Added secure boot options to config to enable secure boot by default

Changes in v2:

* Moved definition and interpretation of SECURED_MODE_IMAGE and
  SECURED_MODE_CSK_INDEX to previous patch
---
 board/gdsys/a38x/kwbimage.cfg.in  | 28 ++++++++++++++++++++++++++++
 configs/controlcenterdc_defconfig |  2 ++
 2 files changed, 30 insertions(+)

diff --git a/board/gdsys/a38x/kwbimage.cfg.in b/board/gdsys/a38x/kwbimage.cfg.in
index 72e67d75c3..ebb3d326f6 100644
--- a/board/gdsys/a38x/kwbimage.cfg.in
+++ b/board/gdsys/a38x/kwbimage.cfg.in
@@ -1,5 +1,6 @@
 #
 # Copyright (C) 2014 Stefan Roese <sr@denx.de>
+# Copyright (C) 2015-2016 Reinhard Pfau <reinhard.pfau@gdsys.cc>
 #

 # Armada 38x uses version 1 image format
@@ -10,3 +11,30 @@ VERSION		1

 # Binary Header (bin_hdr) with DDR3 training code
 BINARY spl/u-boot-spl.bin 0000005b 00000068
+
+# Name of KAK
+KAK	kwb_kak
+
+# Name of (active) CSK
+CSK 	kwb_csk
+
+# BoxID
+BOX_ID	0x1
+
+# FlashID
+FLASH_ID 0x1
+
+# JTAG delay
+JTAG_DELAY 5
+
+# active CSK index
+#@CSK_INDEX
+
+# whether to encode box ID and flash ID into image
+#SEC_SPECIALIZED_IMG
+
+# secured mode boot device
+#@SEC_BOOT_DEV
+
+# secured mode: dump fuse commands
+#@SEC_FUSE_DUMP
diff --git a/configs/controlcenterdc_defconfig b/configs/controlcenterdc_defconfig
index e1c4f0c999..277f2a2939 100644
--- a/configs/controlcenterdc_defconfig
+++ b/configs/controlcenterdc_defconfig
@@ -3,6 +3,8 @@ CONFIG_ARCH_MVEBU=y
 CONFIG_SPL_GPIO_SUPPORT=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_TARGET_CONTROLCENTERDC=y
+CONFIG_MVEBU_EFUSE=y
+CONFIG_SECURED_MODE_IMAGE=y
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="armada-38x-controlcenterdc"
--
2.11.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH 2/3 v3] arm: mvebu: Add gdsys ControlCenter-Compact board
  2017-02-22 15:07 ` [U-Boot] [PATCH 2/3 v3] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
@ 2017-03-03  4:52   ` Simon Glass
  2017-03-24  5:53   ` Stefan Roese
  1 sibling, 0 replies; 12+ messages in thread
From: Simon Glass @ 2017-03-03  4:52 UTC (permalink / raw)
  To: u-boot

Hi Mario,

On 22 February 2017 at 08:07, Mario Six <mario.six@gdsys.cc> wrote:
> From: Dirk Eibach <dirk.eibach@gdsys.cc>
>
> The gdsys ControlCenter Digital board is based on a Marvell Armada 38x
> SOC.
>
> It boots from SPI-Flash but can be configured to boot from SD-card for
> factory programming and testing.
>
> On board peripherals include:
> - 2 x GbE
> - Xilinx Kintex-7 FPGA connected via PCIe
> - mSATA
> - USB3 host
> - Atmel TPM
>
> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v3:
>
> * Removed gpio_request_simple function
> * Removed dev_get_by_ofname function
> * Removed "plain" GPIOs from the device tree

You are using uclass_get_device_by_name() on an I2C bus. Can you
instead use aliases and uclass_get_device_by_seq()? There is quite a
bit of getting stuff by name. Perhaps it is fine for now, but it would
be better I think to have a driver associated with a DT node, which
has phandles for the things it needs.

Regards,
Simon

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH 1/3 v3] dm: Add callback to modify the device tree
  2017-02-22 15:07 ` [U-Boot] [PATCH 1/3 v3] dm: Add callback to modify the device tree Mario Six
@ 2017-03-03  4:52   ` Simon Glass
  2017-03-24  5:53   ` Stefan Roese
  1 sibling, 0 replies; 12+ messages in thread
From: Simon Glass @ 2017-03-03  4:52 UTC (permalink / raw)
  To: u-boot

Hi Mario,

On 22 February 2017 at 08:07, Mario Six <mario.six@gdsys.cc> wrote:
> Certain boards come in different variations by way of utilizing daughter
> boards, for example. These boards might contain additional chips, which
> are added to the main board's busses, e.g. I2C.
>
> The device tree support for such boards would either, quite naturally,
> employ the overlay mechanism to add such chips to the tree, or would use
> one large default device tree, and delete the devices that are actually
> not present.
>
> Regardless of approach, even on the U-Boot level, a modification of the
> device tree is a prerequisite to have such modular families of boards
> supported properly.
>
> Therefore, we add an option to make the U-Boot device tree (the actual
> copy later used by the driver model) writeable, and add a callback
> method that allows boards to modify the device tree at an early stage,
> at which, hopefully, also the application of device tree overlays will
> be possible.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v3:
>
> None
>
> Changes in v2:
>
> * Switched from usage of globally writeable global data pointer to a locally
>   writeable pointer passed to board_fix_fdt
> * Added comments for board_fix_fdt in include/common.h
> * Added documentation for pre-relocation device tree manipulation
> ---
>  common/board_f.c               |  10 ++++
>  doc/driver-model/fdt-fixup.txt | 132 +++++++++++++++++++++++++++++++++++++++++
>  dts/Kconfig                    |  10 ++++
>  include/common.h               |   1 +
>  4 files changed, 153 insertions(+)
>  create mode 100644 doc/driver-model/fdt-fixup.txt

Reviewed-by: Simon Glass <sjg@chromium.org>

I think as things stand this is reasonable.

But IMO it would be better (i.e. faster) to manipulate the live DT,
assuming we have one (see my series on that).

Regards,
Simon

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH 3/3 v3] controlcenterdc: Make secure boot available
  2017-02-22 15:07 ` [U-Boot] [PATCH 3/3 v3] controlcenterdc: Make secure boot available Mario Six
@ 2017-03-23  9:31   ` Stefan Roese
  2017-03-23  9:45     ` Mario Six
  0 siblings, 1 reply; 12+ messages in thread
From: Stefan Roese @ 2017-03-23  9:31 UTC (permalink / raw)
  To: u-boot

Hi Mario,

On 22.02.2017 16:07, Mario Six wrote:
> Make secure booting available for the controlcenterdc
> board.
> 
> Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v3:
> 
> * Added secure boot options to config to enable secure boot by default
> 
> Changes in v2:
> 
> * Moved definition and interpretation of SECURED_MODE_IMAGE and
>   SECURED_MODE_CSK_INDEX to previous patch

When trying to compile with these patches applied, I get this
error:

[stefan at stefan-work u-boot-marvell (master)]$ make -s -j10
Couldn't open RSA private key: './kwb_csk.key': No such file or directory
Failed to load CSK
Could not create image
Makefile:982: recipe for target 'u-boot-spl.kwb' failed

We need to find a way, to compile for this board without such errors.
Perhaps by providing a "default key"? Any ideas?

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH 3/3 v3] controlcenterdc: Make secure boot available
  2017-03-23  9:31   ` Stefan Roese
@ 2017-03-23  9:45     ` Mario Six
  2017-03-23 10:04       ` Stefan Roese
  0 siblings, 1 reply; 12+ messages in thread
From: Mario Six @ 2017-03-23  9:45 UTC (permalink / raw)
  To: u-boot

On Thu, Mar 23, 2017 at 10:31 AM, Stefan Roese <sr@denx.de> wrote:
> Hi Mario,
>
> On 22.02.2017 16:07, Mario Six wrote:
>> Make secure booting available for the controlcenterdc
>> board.
>>
>> Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>
>> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>> ---
>> Changes in v3:
>>
>> * Added secure boot options to config to enable secure boot by default
>>
>> Changes in v2:
>>
>> * Moved definition and interpretation of SECURED_MODE_IMAGE and
>>   SECURED_MODE_CSK_INDEX to previous patch
>
> When trying to compile with these patches applied, I get this
> error:
>
> [stefan at stefan-work u-boot-marvell (master)]$ make -s -j10
> Couldn't open RSA private key: './kwb_csk.key': No such file or directory
> Failed to load CSK
> Could not create image
> Makefile:982: recipe for target 'u-boot-spl.kwb' failed
>
> We need to find a way, to compile for this board without such errors.
> Perhaps by providing a "default key"? Any ideas?
>
> Thanks,
> Stefan
>

Hi Stefan,

Hm, yes, for automatic building, the need to put the KAK and CSK keys somewhere
is problematic; didn't consider that, sorry.

The easiest way would probably be to have some Makefile check for the existence
of kwb_kak.key and kwb_csk.key in the root directory, and create them if they
don't exists, using

openssl genrsa -out kwb_kak.key 2048 openssl genrsa -out kwb_csk.key 2048

But I am not quite sure where to put those checks/instructions in a
non-disruptive manner.

Best regards,

Mario

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH 3/3 v3] controlcenterdc: Make secure boot available
  2017-03-23  9:45     ` Mario Six
@ 2017-03-23 10:04       ` Stefan Roese
  2017-03-23 10:13         ` Mario Six
  0 siblings, 1 reply; 12+ messages in thread
From: Stefan Roese @ 2017-03-23 10:04 UTC (permalink / raw)
  To: u-boot

On 23.03.2017 10:45, Mario Six wrote:
> On Thu, Mar 23, 2017 at 10:31 AM, Stefan Roese <sr@denx.de> wrote:
>> Hi Mario,
>>
>> On 22.02.2017 16:07, Mario Six wrote:
>>> Make secure booting available for the controlcenterdc
>>> board.
>>>
>>> Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>
>>> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>>> ---
>>> Changes in v3:
>>>
>>> * Added secure boot options to config to enable secure boot by default
>>>
>>> Changes in v2:
>>>
>>> * Moved definition and interpretation of SECURED_MODE_IMAGE and
>>>   SECURED_MODE_CSK_INDEX to previous patch
>>
>> When trying to compile with these patches applied, I get this
>> error:
>>
>> [stefan at stefan-work u-boot-marvell (master)]$ make -s -j10
>> Couldn't open RSA private key: './kwb_csk.key': No such file or directory
>> Failed to load CSK
>> Could not create image
>> Makefile:982: recipe for target 'u-boot-spl.kwb' failed
>>
>> We need to find a way, to compile for this board without such errors.
>> Perhaps by providing a "default key"? Any ideas?
>>
>> Thanks,
>> Stefan
>>
>
> Hi Stefan,
>
> Hm, yes, for automatic building, the need to put the KAK and CSK keys somewhere
> is problematic; didn't consider that, sorry.
>
> The easiest way would probably be to have some Makefile check for the existence
> of kwb_kak.key and kwb_csk.key in the root directory, and create them if they
> don't exists, using
>
> openssl genrsa -out kwb_kak.key 2048 openssl genrsa -out kwb_csk.key 2048

Sounds like a doable solution.

> But I am not quite sure where to put those checks/instructions in a
> non-disruptive manner.

Perhaps its better, to place those files into the board directory,
for cases, where multiple targets with different keys are being
built?

I'm currently busy with collecting most pending mvebu patches for
a pull request now. To get this going, I'll probably drop this
last patch from you (patch 3/3) for now, to get the remaining
stuff into mainline.

This way, you will have a bit more time to figure this out in an
acceptable way.

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH 3/3 v3] controlcenterdc: Make secure boot available
  2017-03-23 10:04       ` Stefan Roese
@ 2017-03-23 10:13         ` Mario Six
  0 siblings, 0 replies; 12+ messages in thread
From: Mario Six @ 2017-03-23 10:13 UTC (permalink / raw)
  To: u-boot

On Thu, Mar 23, 2017 at 11:04 AM, Stefan Roese <sr@denx.de> wrote:
> On 23.03.2017 10:45, Mario Six wrote:
>>
>> On Thu, Mar 23, 2017 at 10:31 AM, Stefan Roese <sr@denx.de> wrote:
>>>
>>> Hi Mario,
>>>
>>> On 22.02.2017 16:07, Mario Six wrote:
>>>>
>>>> Make secure booting available for the controlcenterdc
>>>> board.
>>>>
>>>> Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>
>>>> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>>>> ---
>>>> Changes in v3:
>>>>
>>>> * Added secure boot options to config to enable secure boot by default
>>>>
>>>> Changes in v2:
>>>>
>>>> * Moved definition and interpretation of SECURED_MODE_IMAGE and
>>>>   SECURED_MODE_CSK_INDEX to previous patch
>>>
>>>
>>> When trying to compile with these patches applied, I get this
>>> error:
>>>
>>> [stefan at stefan-work u-boot-marvell (master)]$ make -s -j10
>>> Couldn't open RSA private key: './kwb_csk.key': No such file or directory
>>> Failed to load CSK
>>> Could not create image
>>> Makefile:982: recipe for target 'u-boot-spl.kwb' failed
>>>
>>> We need to find a way, to compile for this board without such errors.
>>> Perhaps by providing a "default key"? Any ideas?
>>>
>>> Thanks,
>>> Stefan
>>>
>>
>> Hi Stefan,
>>
>> Hm, yes, for automatic building, the need to put the KAK and CSK keys
>> somewhere
>> is problematic; didn't consider that, sorry.
>>
>> The easiest way would probably be to have some Makefile check for the
>> existence
>> of kwb_kak.key and kwb_csk.key in the root directory, and create them if
>> they
>> don't exists, using
>>
>> openssl genrsa -out kwb_kak.key 2048 openssl genrsa -out kwb_csk.key 2048
>
>
> Sounds like a doable solution.
>
>> But I am not quite sure where to put those checks/instructions in a
>> non-disruptive manner.
>
>
> Perhaps its better, to place those files into the board directory,
> for cases, where multiple targets with different keys are being
> built?
>
> I'm currently busy with collecting most pending mvebu patches for
> a pull request now. To get this going, I'll probably drop this
> last patch from you (patch 3/3) for now, to get the remaining
> stuff into mainline.
>
> This way, you will have a bit more time to figure this out in an
> acceptable way.
>
>
> Thanks,
> Stefan
>

OK, that's fine with me. Thanks for testing!

Best regards,

Mario

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH 1/3 v3] dm: Add callback to modify the device tree
  2017-02-22 15:07 ` [U-Boot] [PATCH 1/3 v3] dm: Add callback to modify the device tree Mario Six
  2017-03-03  4:52   ` Simon Glass
@ 2017-03-24  5:53   ` Stefan Roese
  1 sibling, 0 replies; 12+ messages in thread
From: Stefan Roese @ 2017-03-24  5:53 UTC (permalink / raw)
  To: u-boot

On 22.02.2017 16:07, Mario Six wrote:
> Certain boards come in different variations by way of utilizing daughter
> boards, for example. These boards might contain additional chips, which
> are added to the main board's busses, e.g. I2C.
>
> The device tree support for such boards would either, quite naturally,
> employ the overlay mechanism to add such chips to the tree, or would use
> one large default device tree, and delete the devices that are actually
> not present.
>
> Regardless of approach, even on the U-Boot level, a modification of the
> device tree is a prerequisite to have such modular families of boards
> supported properly.
>
> Therefore, we add an option to make the U-Boot device tree (the actual
> copy later used by the driver model) writeable, and add a callback
> method that allows boards to modify the device tree at an early stage,
> at which, hopefully, also the application of device tree overlays will
> be possible.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>

Applied to u-boot-marvell/master.

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH 2/3 v3] arm: mvebu: Add gdsys ControlCenter-Compact board
  2017-02-22 15:07 ` [U-Boot] [PATCH 2/3 v3] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
  2017-03-03  4:52   ` Simon Glass
@ 2017-03-24  5:53   ` Stefan Roese
  1 sibling, 0 replies; 12+ messages in thread
From: Stefan Roese @ 2017-03-24  5:53 UTC (permalink / raw)
  To: u-boot

On 22.02.2017 16:07, Mario Six wrote:
> From: Dirk Eibach <dirk.eibach@gdsys.cc>
>
> The gdsys ControlCenter Digital board is based on a Marvell Armada 38x
> SOC.
>
> It boots from SPI-Flash but can be configured to boot from SD-card for
> factory programming and testing.
>
> On board peripherals include:
> - 2 x GbE
> - Xilinx Kintex-7 FPGA connected via PCIe
> - mSATA
> - USB3 host
> - Atmel TPM
>
> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>

Applied to u-boot-marvell/master.

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-03-24  5:53 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-22 15:07 [U-Boot] [PATCH 0/3 v3] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
2017-02-22 15:07 ` [U-Boot] [PATCH 1/3 v3] dm: Add callback to modify the device tree Mario Six
2017-03-03  4:52   ` Simon Glass
2017-03-24  5:53   ` Stefan Roese
2017-02-22 15:07 ` [U-Boot] [PATCH 2/3 v3] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
2017-03-03  4:52   ` Simon Glass
2017-03-24  5:53   ` Stefan Roese
2017-02-22 15:07 ` [U-Boot] [PATCH 3/3 v3] controlcenterdc: Make secure boot available Mario Six
2017-03-23  9:31   ` Stefan Roese
2017-03-23  9:45     ` Mario Six
2017-03-23 10:04       ` Stefan Roese
2017-03-23 10:13         ` Mario Six

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.