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