[U-Boot] [PATCH 16/17] arm: mvebu: Add gdsys ControlCenter-Compact board

Mario Six mario.six at gdsys.cc
Fri Dec 2 10:34:21 CET 2016


Hi Stefan,

On Thu, Dec 1, 2016 at 10:57 AM, Stefan Roese <sr at denx.de> wrote:
> On 23.11.2016 16:12, Mario Six wrote:
>> From: Dirk Eibach <dirk.eibach at 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 at gdsys.cc>
>> Signed-off-by: Mario Six <mario.six at gdsys.cc>
>> ---
>>  arch/arm/Kconfig                  |   1 +
>>  arch/arm/dts/Makefile             |   3 +-
>>  arch/arm/dts/controlcenterdc.dts  | 629 +++++++++++++++++++++++++++++++++
>
> Could you perhaps rename this file (and board name as well?) to
> something like "armada-38x-controlcenterdc*" instead? Its much easier
> to match the files to the architecture this way. And until now, all
> Armada XP / 38x (etc) files match this rule.
>

Sure, I'll rename that file in v2.

>>  arch/arm/mach-mvebu/Kconfig       |   4 +
>>  board/gdsys/38x/.gitignore        |   1 +
>
> Perhaps better s/38x/a38x for "Armada"?
>

OK, will be fixed in v2.

>>  board/gdsys/38x/Kconfig           |  42 +++
>>  board/gdsys/38x/MAINTAINERS       |   7 +
>>  board/gdsys/38x/Makefile          |  30 ++
>>  board/gdsys/38x/README            |  18 +
>>  board/gdsys/38x/controlcenterdc.c | 717 ++++++++++++++++++++++++++++++++++++++
>>  board/gdsys/38x/dt_helpers.c      |  60 ++++
>>  board/gdsys/38x/dt_helpers.h      |  16 +
>>  board/gdsys/38x/hre.c             | 517 +++++++++++++++++++++++++++
>>  board/gdsys/38x/hre.h             |  38 ++
>>  board/gdsys/38x/keyprogram.c      | 158 +++++++++
>>  board/gdsys/38x/keyprogram.h      |  14 +
>>  board/gdsys/38x/kwbimage.cfg.in   |  12 +
>>  board/gdsys/38x/spl.c             |  21 ++
>>  configs/controlcenterdc_defconfig |  54 +++
>>  include/configs/controlcenterdc.h | 244 +++++++++++++
>>  20 files changed, 2585 insertions(+), 1 deletion(-)
>>  create mode 100644 arch/arm/dts/controlcenterdc.dts
>>  create mode 100644 board/gdsys/38x/.gitignore
>>  create mode 100644 board/gdsys/38x/Kconfig
>>  create mode 100644 board/gdsys/38x/MAINTAINERS
>>  create mode 100644 board/gdsys/38x/Makefile
>>  create mode 100644 board/gdsys/38x/README
>>  create mode 100644 board/gdsys/38x/controlcenterdc.c
>>  create mode 100644 board/gdsys/38x/dt_helpers.c
>>  create mode 100644 board/gdsys/38x/dt_helpers.h
>>  create mode 100644 board/gdsys/38x/hre.c
>>  create mode 100644 board/gdsys/38x/hre.h
>>  create mode 100644 board/gdsys/38x/keyprogram.c
>>  create mode 100644 board/gdsys/38x/keyprogram.h
>>  create mode 100644 board/gdsys/38x/kwbimage.cfg.in
>>  create mode 100644 board/gdsys/38x/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 acd689b..f4c236b 100644
>> --- a/arch/arm/Kconfig
>> +++ b/arch/arm/Kconfig
>> @@ -970,6 +970,7 @@ source "board/freescale/mx53loco/Kconfig"
>>  source "board/freescale/mx53smd/Kconfig"
>>  source "board/freescale/s32v234evb/Kconfig"
>>  source "board/freescale/vf610twr/Kconfig"
>> +source "board/gdsys/38x/Kconfig"
>>  source "board/gumstix/pepper/Kconfig"
>>  source "board/h2200/Kconfig"
>>  source "board/hisilicon/hikey/Kconfig"
>> diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
>> index 2c5b2f2..b0bd507 100644
>> --- a/arch/arm/dts/Makefile
>> +++ b/arch/arm/dts/Makefile
>> @@ -76,7 +76,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               \
>> +     controlcenterdc.dtb
>>
>>  dtb-$(CONFIG_ARCH_UNIPHIER) += \
>>       uniphier-ld11-ref.dtb \
>> diff --git a/arch/arm/dts/controlcenterdc.dts b/arch/arm/dts/controlcenterdc.dts
>> new file mode 100644
>> index 0000000..baf0171
>> --- /dev/null
>> +++ b/arch/arm/dts/controlcenterdc.dts
>> @@ -0,0 +1,629 @@
>> +/*
>> + * Device Tree file for the Guntermann & Drunck ControlCenter-Compact board
>> + *
>> + * Copyright (C) 2016 Mario Six <mario.six at 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 at free-electrons.com>
>> + *
>> + * SPDX-License-Identifier:     GPL-2.0+
>> + */
>> +
>> +/dts-v1/;
>> +
>> +#include "armada-388.dtsi"
>> +
>> +&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>;
>> +                     };
>> +             };
>> +     };
>> +
>> +     cat_gpio_0 {
>> +             compatible = "generic,cat-gpio-0";
>> +             gpios = <&PCA23 0x20 0x0>;
>> +     };
>> +
>> +     cat_gpio_1 {
>> +             compatible = "generic,cat-gpio-1";
>> +             gpios = <&PCA21 0x20 0x0>;
>> +     };
>> +
>> +     cat_gpio_2 {
>> +             compatible = "generic,cat-gpio-2";
>> +             gpios = <&PCA24 0x20 0x0>;
>> +     };
>> +
>> +     cat_gpio_3 {
>> +             compatible = "generic,cat-gpio-3";
>> +             gpios = <&PCA25 0x20 0x0>;
>> +     };
>> +
>> +     cat_gpio_4 {
>> +             compatible = "generic,cat-gpio-4";
>> +             gpios = <&PCA26 0x20 0x0>;
>> +     };
>> +
>> +     second_octo_gpio_0 {
>> +             compatible = "generic,second-octo-gpio-0";
>> +             gpios = <&PCA23 0x27 0x0>;
>> +     };
>> +
>> +     fpga_program_gpio {
>> +             compatible = "generic,fpga-program-gpio";
>> +             u-boot,dm-pre-reloc;
>> +             gpios = <&PCA22 31 0>;
>> +     };
>> +
>> +     fpga_done_gpio {
>> +             compatible = "generic,fpga-done-gpio";
>> +             u-boot,dm-pre-reloc;
>> +             gpios = <&PCA22 19 0>;
>> +     };
>> +
>> +     fpga_ready_gpio {
>> +             compatible = "generic,fpga-ready-gpio";
>> +             u-boot,dm-pre-reloc;
>> +             gpios = <&PCA22 27 0>;
>> +     };
>> +
>> +     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 1ca7b52..ac36894 100644
>> --- a/arch/arm/mach-mvebu/Kconfig
>> +++ b/arch/arm/mach-mvebu/Kconfig
>> @@ -102,6 +102,10 @@ config TARGET_THEADORABLE
>>       bool "Support theadorable Armada XP"
>>       select MV78260
>>
>> +config TARGET_CONTROLCENTERDC
>> +     bool "Support CONTROLCENTERDC"
>> +     select 88F6820
>> +
>>  endchoice
>>
>>  config SYS_BOARD
>> diff --git a/board/gdsys/38x/.gitignore b/board/gdsys/38x/.gitignore
>> new file mode 100644
>> index 0000000..775b934
>> --- /dev/null
>> +++ b/board/gdsys/38x/.gitignore
>> @@ -0,0 +1 @@
>> +kwbimage.cfg
>> diff --git a/board/gdsys/38x/Kconfig b/board/gdsys/38x/Kconfig
>> new file mode 100644
>> index 0000000..dd99ac5
>> --- /dev/null
>> +++ b/board/gdsys/38x/Kconfig
>> @@ -0,0 +1,42 @@
>> +if TARGET_CONTROLCENTERDC
>> +
>> +config SYS_BOARD
>> +     default "38x"
>> +
>> +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
>> +
>> +config SYS_BOOTIMAGE_DEST_ADDR
>> +     hex "Boot image destination address"
>> +     default 0x007fffc0
>> +     help
>> +       Blah
>
> Hmmm, the help text is not really "helpful". ;)
>
> This option is also not referenced, so perhaps you can remove it?
>

Ahh, that was a leftover from a test I did (hence the very eloquently written
help text). Sorry about that.

Will be gone in v2.

>> +
>> +endmenu
>> +
>> +endif
>> diff --git a/board/gdsys/38x/MAINTAINERS b/board/gdsys/38x/MAINTAINERS
>> new file mode 100644
>> index 0000000..5dbc6ec
>> --- /dev/null
>> +++ b/board/gdsys/38x/MAINTAINERS
>> @@ -0,0 +1,7 @@
>> +38X BOARD
>> +M:   Dirk Eibach <eibach at gdsys.cc>
>> +M:   Mario Six <six at gdsys.de>
>> +S:   Maintained
>> +F:   board/gdsys/38x/
>> +F:   include/configs/controlcenterdc.h
>> +F:   configs/controlcenterdc_defconfig
>> diff --git a/board/gdsys/38x/Makefile b/board/gdsys/38x/Makefile
>> new file mode 100644
>> index 0000000..6d17196
>> --- /dev/null
>> +++ b/board/gdsys/38x/Makefile
>> @@ -0,0 +1,30 @@
>> +#
>> +# Copyright (C) 2015 Stefan Roese <sr at denx.de>
>> +# Copyright (C) 2015 Reinhard Pfau <reinhard.pfau at gdsys.cc>
>> +# Copyright (C) 2016 Mario Six <mario.six at 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),)
>> +
>> +extra-$(CONFIG_TARGET_CONTROLCENTERDC) += kwbimage.cfg
>> +
>> +ifneq ($(CONFIG_TARGET_CONTROLCENTERDC),)
>> +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
>> +endif
>
> Do you have multiple build targets for this directory? Do you need
> to have this check with CONFIG_TARGET_CONTROLCENTERDC?
>

No, there is only the one build target atm, so the check is indeed useless;
will remove in v2.

>> +
>> +$(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/38x/README b/board/gdsys/38x/README
>> new file mode 100644
>> index 0000000..9bea5b3
>> --- /dev/null
>> +++ b/board/gdsys/38x/README
>> @@ -0,0 +1,18 @@
>> +Update from original Marvell U-Boot to mainline U-Boot:
>> +-------------------------------------------------------
>> +
>> +The resulting image including the SPL binary with the
>> +full DDR setup is "u-boot-spl.kwb".
>> +
>> +To update the SPI NOR flash, please use the following
>> +command:
>> +
>> +=> sf probe;tftpboot 2000000 db-88f6820-gp/u-boot-spl.kwb;\
>> +sf update 2000000 0 60000
>> +
>> +Note that the original Marvell U-Boot seems to have
>> +problems with the "sf update" command. This does not
>> +work reliable. So here this command should be used:
>> +
>> +=> sf probe;tftpboot 2000000 db-88f6820-gp/u-boot-spl.kwb;\
>> +sf erase 0 60000;sf write 2000000 0 60000
>
> You copied this file from the Marvell directory. Does it really
> make sense to add it here as well? I suggest to just remove it.
>

OK, will remove in v2.

>> diff --git a/board/gdsys/38x/controlcenterdc.c b/board/gdsys/38x/controlcenterdc.c
>> new file mode 100644
>> index 0000000..f151265
>> --- /dev/null
>> +++ b/board/gdsys/38x/controlcenterdc.c
>> @@ -0,0 +1,717 @@
>> +/*
>> + * Copyright (C) 2015 Stefan Roese <sr at denx.de>
>> + * Copyright (C) 2016 Mario Six <mario.six at gdsys.cc>
>> + *
>> + * SPDX-License-Identifier:  GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <console.h> /* disable_ctrlc */
>> +#include <miiphy.h>
>> +#include <tpm.h>
>> +#include <asm/io.h>
>> +#include <asm/arch/cpu.h>
>> +#include <asm/arch/gpio.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"
>> +
>> +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
>> +
>> +#ifndef CONFIG_SPL_BUILD
>> +enum {
>> +     HWVER_100 = 0,
>> +     HWVER_110 = 1,
>> +     HWVER_120 = 2,
>> +};
>> +
>> +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 },
>> +};
>> +
>> +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 */
>> +};
>> +
>> +static struct ihs_fpga *fpga;
>> +
>> +static struct pci_device_id hydra_supported[] = {
>> +     { 0x6d5e, 0xcdc1 },
>> +     {}
>> +};
>> +#endif
>> +
>> +/*
>> + * 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 (get_gpio("generic,fpga-program-gpio", &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 (get_gpio("generic,fpga-done-gpio", &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 */
>> +     kw_gpio_set_valid(6, GPIO_OUTPUT_OK);
>> +     kw_gpio_direction_output(6, 1);
>
> Ah, here you use the "old" GPIO infrastucture. Please move to the DM
> GPIO driver and use the generic API instead.
>

OK, I'll look into that. I have no idea how well the bitbang MIIPHY functions
will work with DM-style GPIOs (they have only ever been used with legacy GPIO
interfaces from what I know), so I'll need to experiment with that a little.

>> +
>> +     /* wait for FPGA ready */
>> +     if (get_gpio("generic,fpga-ready-gpio", &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)
>> +{
>> +     /* adress of boot parameters */
>> +     gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
>> +
>> +     return 0;
>> +}
>> +
>> +int checkboard(void)
>> +{
>> +     puts("Board: Controlcenter Digital Compact\n");
>> +
>> +     return 0;
>> +}
>
> With DT support you should already get the board model printed from
> the DT. Do yo need this line here as well?
>

True, that produced two almost identical lines on startup. I'll just remove the
checkboard function in v2.

>> +
>> +#ifndef CONFIG_SPL_BUILD
>> +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);
>> +}
>> +
>> +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);
>> +     }
>> +}
>> +
>> +uint calculate_octo_phy_mask(void)
>> +{
>> +     uint k;
>> +     uint octo_phy_mask = 0;
>> +     struct gpio_desc gpio = {};
>> +     char name[64];
>> +
>> +     /* mark all octo phys that should be present */
>> +     for (k = 0; k < 5; ++k) {
>> +             snprintf(name, 64, "generic,cat-gpio-%u", k);
>> +
>> +             if (!get_gpio(name, &gpio))
>> +                     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(name, 64, "generic,second-octo-gpio-%u", k);
>> +
>> +             if (!get_gpio(name, &gpio)) {
>> +                     /* 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;
>
> I'm wondering how this works if "bb_miiphy_buses" is defined later in
> this file and you have no header file.
>

The bb_miiphy_busses array is declared in miiphy.h as extern, and we include
this header in controlcenterdc.c, so there's only a bit of magic at work here.
:-)

>> +
>> +     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_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 at least one phy
>> +                      * on the current bus
>> +                      */
>
> Multiline comment style please.
>

OK, will fix in v2.

>> +                     if (!m && octo_phy_mask & (0xf << octo_index)) {
>> +                             ret = register_miiphy_bus(bus_idx, &bus);
>> +                             if (ret)
>> +                                     return ret;
>> +                     }
>> +
>> +                     if (!(octo_phy_mask & (1 << (octo_index + m))))
>> +                             continue;
>> +
>> +                     for (phy_idx = 0; phy_idx < 8; ++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);
>> +
>> +                             ihs_phy_config(phydev,
>> +                                            porttype->phy_invert_in_pol,
>> +                                            porttype->phy_invert_out_pol);
>> +                     }
>> +             }
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +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 at 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");
>> +
>> +     /* reset all FPGA-QSGMII instances */
>> +     for (k = 0; k < 80; ++k)
>> +             writel(1 << 31, &fpga->qsgmii_port_state[k]);
>> +
>> +     udelay(100);
>> +
>> +     for (k = 0; k < 80; ++k)
>> +             writel(0, &fpga->qsgmii_port_state[k]);
>> +     return 0;
>> +}
>> +
>> +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);
>> +}
>> +
>> +static 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);
>> +     }
>> +}
>> +#endif
>> +
>> +int board_late_init(void)
>> +{
>> +#ifndef CONFIG_SPL_BUILD
>> +     hydra_initialize();
>> +#endif
>> +     return 0;
>> +}
>> +
>> +int board_fix_fdt(void)
>> +{
>> +     struct udevice *bus;
>> +     uint k;
>> +     char name[64];
>> +
>> +     bus = dev_get_by_ofname("/soc/internal-regs/i2c at 11000");
>> +
>> +     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(name);
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +int last_stage_init(void)
>> +{
>> +     disable_ctrlc(1);
>> +
>> +#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;
>> +}
>> +
>> +#ifndef CONFIG_SPL_BUILD
>> +
>> +#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"
>> +);
>> +
>> +/*
>> + * MII GPIO bitbang implementation
>> + * MDC MDIO bus
>> + * 13  14   PHY1-4
>> + * 25  45   PHY5-8
>> + * 46  24   PHY9-10
>> + */
>> +
>> +struct gpio_mii {
>> +     int mdc;
>> +     int mdio;
>> +     int mdio_value;
>> +} gpio_mii_set[] = {
>> +     { 13, 14, 1 },
>> +     { 25, 45, 1 },
>> +     { 46, 24, 1 },
>> +};
>> +
>> +static int mii_mdio_init(struct bb_miiphy_bus *bus)
>> +{
>> +     struct gpio_mii *gpio_mii = bus->priv;
>> +
>> +     kw_gpio_set_valid(gpio_mii->mdc, GPIO_OUTPUT_OK);
>> +     kw_gpio_set_valid(gpio_mii->mdio, GPIO_INPUT_OK | GPIO_OUTPUT_OK);
>> +     kw_gpio_direction_output(gpio_mii->mdc, 1);
>> +
>> +     return 0;
>> +}
>> +
>> +static int mii_mdio_active(struct bb_miiphy_bus *bus)
>> +{
>> +     struct gpio_mii *gpio_mii = bus->priv;
>> +
>> +     kw_gpio_direction_output(gpio_mii->mdio, gpio_mii->mdio_value);
>> +
>> +     return 0;
>> +}
>> +
>> +static int mii_mdio_tristate(struct bb_miiphy_bus *bus)
>> +{
>> +     struct gpio_mii *gpio_mii = bus->priv;
>> +
>> +     kw_gpio_direction_input(gpio_mii->mdio);
>> +
>> +     return 0;
>> +}
>> +
>> +static int mii_set_mdio(struct bb_miiphy_bus *bus, int v)
>> +{
>> +     struct gpio_mii *gpio_mii = bus->priv;
>> +
>> +     kw_gpio_set_value(gpio_mii->mdio, 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;
>> +
>> +     *v = (kw_gpio_get_value(gpio_mii->mdio) != 0);
>> +
>> +     return 0;
>> +}
>> +
>> +static int mii_set_mdc(struct bb_miiphy_bus *bus, int v)
>> +{
>> +     struct gpio_mii *gpio_mii = bus->priv;
>> +
>> +     kw_gpio_set_value(gpio_mii->mdc, 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 = sizeof(bb_miiphy_buses) /
>> +                       sizeof(bb_miiphy_buses[0]);
>
> static? And can you use ARRAY_SIZE()?
>

Usage of ARRAY_SIZE is OK, but the variable bb_miiphy_buses itself is first
declare as extern non-static in include/miiphy.h, so we will have to follow
that convention here.

>> +#endif
>
> Perhaps its also a good idea to move at least some of this code
> (especiall the command and perhaps some MDIO stuff) into separate
> files that are only compiled for non-SPL U-Boot. This will remove
> some of the #ifdefs as well.

OK, will look into separating out some things for v2.

>> diff --git a/board/gdsys/38x/dt_helpers.c b/board/gdsys/38x/dt_helpers.c
>> new file mode 100644
>> index 0000000..dedd048
>> --- /dev/null
>> +++ b/board/gdsys/38x/dt_helpers.c
>> @@ -0,0 +1,60 @@
>> +/*
>> + * (C) Copyright 2016
>> + * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
>> + *
>> + * SPDX-License-Identifier:    GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <i2c.h>
>> +#include <dm.h>
>> +#include <fdt_support.h>
>> +#include <asm-generic/gpio.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +bool get_gpio(char *name, struct gpio_desc *gpio)
>> +{
>> +     int node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, name);
>> +     int ret;
>> +
>> +     if (node < 0)
>> +             return false;
>> +
>> +     ret = gpio_request_by_name_nodev(gd->fdt_blob, node, "gpios", 0, gpio,
>> +                                      0);
>> +
>> +     if (ret < 0)
>> +             return false;
>> +
>> +     return dm_gpio_is_valid(gpio);
>> +}
>> +
>> +int fdt_disable_by_ofname(char *ofname)
>> +{
>> +     void *blob = gd->fdt_blob;
>> +     int offset;
>> +
>> +     offset = fdt_path_offset(blob, ofname);
>> +     return fdt_status_disabled(blob, offset);
>> +}
>> +
>> +struct udevice *dev_get_by_ofname(char *ofname)
>> +{
>> +     void *blob = gd->fdt_blob;
>> +     int offset;
>> +     struct udevice *dev;
>> +
>> +     offset = fdt_path_offset(blob, ofname);
>> +     device_get_global_by_of_offset(offset, &dev);
>> +
>> +     return dev;
>> +}
>> +
>> +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);
>> +}
>
> At least some of this might be very helpful as common U-Boot
> functions available for all boards.
>

OK, I'll create separate patches for "get_gpio" (with a better name) and
"dev_get_by_ofname" and put them in sensible subsystems (possibly
"dm_i2c_simple_probe" too). "fdt_disable_by_ofname" is probably a little too
special to our use case.

>> diff --git a/board/gdsys/38x/dt_helpers.h b/board/gdsys/38x/dt_helpers.h
>> new file mode 100644
>> index 0000000..8052b94
>> --- /dev/null
>> +++ b/board/gdsys/38x/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
>> +
>> +bool get_gpio(char *name, struct gpio_desc *gpio);
>> +int fdt_disable_by_ofname(char *ofname);
>> +struct udevice *dev_get_by_ofname(char *ofname);
>> +bool dm_i2c_simple_probe(struct udevice *bus, uint chip_addr);
>> +
>> +#endif /* __DT_HELPERS_H */
>> diff --git a/board/gdsys/38x/hre.c b/board/gdsys/38x/hre.c
>> new file mode 100644
>> index 0000000..10bf1a0
>> --- /dev/null
>> +++ b/board/gdsys/38x/hre.c
>> @@ -0,0 +1,517 @@
>> +/*
>> + * (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;
>> +     }
>> +     /* TODO remember key handle somehow? */
>
> Is this comment still valid?
>

Yes, it is, but it's highly unlikely that it will be addressed. Saving the key
handle here would make things easier, but there's no elegant way to do it
properly. Besides, the HRE code will most likely be removed from the board
files once we use our new method for securely loading TPM keys in the
ControlCenter-Compact board.

Hence, I'd say that I'll just remove the TODO in v2.

>> +
>> +     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/38x/hre.h b/board/gdsys/38x/hre.h
>> new file mode 100644
>> index 0000000..84ce279
>> --- /dev/null
>> +++ b/board/gdsys/38x/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/38x/keyprogram.c b/board/gdsys/38x/keyprogram.c
>> new file mode 100644
>> index 0000000..a4a6f1c
>> --- /dev/null
>> +++ b/board/gdsys/38x/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/38x/keyprogram.h b/board/gdsys/38x/keyprogram.h
>> new file mode 100644
>> index 0000000..a5ea7d3
>> --- /dev/null
>> +++ b/board/gdsys/38x/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/38x/kwbimage.cfg.in b/board/gdsys/38x/kwbimage.cfg.in
>> new file mode 100644
>> index 0000000..72e67d7
>> --- /dev/null
>> +++ b/board/gdsys/38x/kwbimage.cfg.in
>> @@ -0,0 +1,12 @@
>> +#
>> +# Copyright (C) 2014 Stefan Roese <sr at 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/38x/spl.c b/board/gdsys/38x/spl.c
>> new file mode 100644
>> index 0000000..2d05a9c
>> --- /dev/null
>> +++ b/board/gdsys/38x/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 0000000..ee06c84
>> --- /dev/null
>> +++ b/configs/controlcenterdc_defconfig
>> @@ -0,0 +1,54 @@
>> +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="controlcenterdc"
>> +CONFIG_FIT=y
>> +CONFIG_FIT_VERBOSE=y
>> +CONFIG_FIT_SIGNATURE=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_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_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_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 0000000..9097dce
>> --- /dev/null
>> +++ b/include/configs/controlcenterdc.h
>> @@ -0,0 +1,244 @@
>> +/*
>> + * Copyright (C) 2014 Stefan Roese <sr at denx.de>
>> + * Copyright (C) 2016 Mario Six <mario.six at 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
>> +
>> +#define CONFIG_SYS_NO_FLASH          /* Declare no flash (NOR/SPI) */
>> +
>> +/*
>> + * 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_MMC
>> +#define CONFIG_GENERIC_MMC
>> +#define CONFIG_SDHCI
>> +#define CONFIG_MV_SDHCI
>> +#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)
>> +
>> +/* Partition support */
>> +#define CONFIG_DOS_PARTITION
>> +#define CONFIG_EFI_PARTITION
>> +
>> +/* 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
>> +
>> +/*
>> + * GPIO
>> + */
>> +#define CONFIG_KIRKWOOD_GPIO
>> +
>> +/* 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)
>> +#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS   ((512 << 10) / 512) /* 512KiB */
>> +#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 at 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 */
>>
>
> Thanks,
> Stefan

Thanks for the review!

Best regards,
Mario



More information about the U-Boot mailing list