aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/board/gdsys
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/board/gdsys
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/board/gdsys')
-rw-r--r--roms/u-boot/board/gdsys/a38x/MAINTAINERS7
-rw-r--r--roms/u-boot/board/gdsys/a38x/Makefile11
-rw-r--r--roms/u-boot/board/gdsys/a38x/controlcenterdc.c302
-rw-r--r--roms/u-boot/board/gdsys/a38x/dt_helpers.c42
-rw-r--r--roms/u-boot/board/gdsys/a38x/dt_helpers.h15
-rw-r--r--roms/u-boot/board/gdsys/a38x/hre.c529
-rw-r--r--roms/u-boot/board/gdsys/a38x/hre.h37
-rw-r--r--roms/u-boot/board/gdsys/a38x/hydra.c140
-rw-r--r--roms/u-boot/board/gdsys/a38x/hydra.h14
-rw-r--r--roms/u-boot/board/gdsys/a38x/ihs_phys.c357
-rw-r--r--roms/u-boot/board/gdsys/a38x/ihs_phys.h2
-rw-r--r--roms/u-boot/board/gdsys/a38x/keyprogram.c161
-rw-r--r--roms/u-boot/board/gdsys/a38x/keyprogram.h13
-rw-r--r--roms/u-boot/board/gdsys/a38x/spl.c20
-rw-r--r--roms/u-boot/board/gdsys/common/Makefile13
-rw-r--r--roms/u-boot/board/gdsys/common/cmd_ioloop.c585
-rw-r--r--roms/u-boot/board/gdsys/common/dp501.c161
-rw-r--r--roms/u-boot/board/gdsys/common/dp501.h31
-rw-r--r--roms/u-boot/board/gdsys/common/fpga.c28
-rw-r--r--roms/u-boot/board/gdsys/common/ihs_mdio.c164
-rw-r--r--roms/u-boot/board/gdsys/common/ihs_mdio.h22
-rw-r--r--roms/u-boot/board/gdsys/common/ioep-fpga.c591
-rw-r--r--roms/u-boot/board/gdsys/common/ioep-fpga.h13
-rw-r--r--roms/u-boot/board/gdsys/common/osd.c506
-rw-r--r--roms/u-boot/board/gdsys/common/osd.h13
-rw-r--r--roms/u-boot/board/gdsys/common/osd_cmd.c147
-rw-r--r--roms/u-boot/board/gdsys/mpc8308/Kconfig83
-rw-r--r--roms/u-boot/board/gdsys/mpc8308/MAINTAINERS6
-rw-r--r--roms/u-boot/board/gdsys/mpc8308/Makefile7
-rw-r--r--roms/u-boot/board/gdsys/mpc8308/gazerbeam.c186
-rw-r--r--roms/u-boot/board/gdsys/mpc8308/mpc8308.c122
-rw-r--r--roms/u-boot/board/gdsys/mpc8308/mpc8308.h13
-rw-r--r--roms/u-boot/board/gdsys/mpc8308/sdram.c89
33 files changed, 4430 insertions, 0 deletions
diff --git a/roms/u-boot/board/gdsys/a38x/MAINTAINERS b/roms/u-boot/board/gdsys/a38x/MAINTAINERS
new file mode 100644
index 000000000..d31e675dd
--- /dev/null
+++ b/roms/u-boot/board/gdsys/a38x/MAINTAINERS
@@ -0,0 +1,7 @@
+A38X BOARD
+M: Dirk Eibach <dirk.eibach@gdsys.cc>
+M: Mario Six <mario.six@gdsys.cc>
+S: Maintained
+F: board/gdsys/a38x/
+F: include/configs/controlcenterdc.h
+F: configs/controlcenterdc_defconfig
diff --git a/roms/u-boot/board/gdsys/a38x/Makefile b/roms/u-boot/board/gdsys/a38x/Makefile
new file mode 100644
index 000000000..32fffab46
--- /dev/null
+++ b/roms/u-boot/board/gdsys/a38x/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# 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>
+
+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
+endif
diff --git a/roms/u-boot/board/gdsys/a38x/controlcenterdc.c b/roms/u-boot/board/gdsys/a38x/controlcenterdc.c
new file mode 100644
index 000000000..dc424f271
--- /dev/null
+++ b/roms/u-boot/board/gdsys/a38x/controlcenterdc.c
@@ -0,0 +1,302 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2016 Mario Six <mario.six@gdsys.cc>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <init.h>
+#include <miiphy.h>
+#include <net.h>
+#include <tpm-v1.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm-generic/gpio.h>
+#include <linux/delay.h>
+
+#include "../drivers/ddr/marvell/a38x/ddr3_init.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 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
+
+static int get_tpm(struct udevice **devp)
+{
+ int rc;
+
+ rc = uclass_first_device_err(UCLASS_TPM, devp);
+ if (rc) {
+ printf("Could not find TPM (ret=%d)\n", rc);
+ return CMD_RET_FAILURE;
+ }
+
+ return 0;
+}
+
+/*
+ * 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 mv_ddr_topology_map ddr_topology_map = {
+ DEBUG_LEVEL_ERROR,
+ 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 */
+ MV_DDR_DEV_WIDTH_16BIT, /* memory_width */
+ MV_DDR_DIE_CAP_4GBIT, /* mem_size */
+ MV_DDR_FREQ_533, /* frequency */
+ 0, 0, /* cas_wl cas_l */
+ MV_DDR_TEMP_LOW, /* temperature */
+ MV_DDR_TIM_DEFAULT} }, /* timing */
+ BUS_MASK_32BIT, /* Busses mask */
+ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
+ NOT_COMBINED, /* ddr twin-die combined */
+ { {0} }, /* raw spd data */
+ {0} /* timing parameters */
+
+};
+
+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 mv_ddr_topology_map *mv_ddr_topology_map_get(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)
+{
+ struct udevice *tpm;
+ int ret;
+
+#ifndef CONFIG_SPL_BUILD
+ ccdc_eth_init();
+#endif
+ ret = get_tpm(&tpm);
+ if (ret || tpm_init(tpm) || tpm1_startup(tpm, TPM_ST_CLEAR) ||
+ tpm1_continue_self_test(tpm)) {
+ return 1;
+ }
+
+ mdelay(37);
+
+ flush_keys(tpm);
+ load_and_run_keyprog(tpm);
+
+ return 0;
+}
diff --git a/roms/u-boot/board/gdsys/a38x/dt_helpers.c b/roms/u-boot/board/gdsys/a38x/dt_helpers.c
new file mode 100644
index 000000000..c859024a2
--- /dev/null
+++ b/roms/u-boot/board/gdsys/a38x/dt_helpers.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <fdt_support.h>
+#include <asm-generic/gpio.h>
+#include <dm.h>
+
+int fdt_disable_by_ofname(void *rw_fdt_blob, char *ofname)
+{
+ int offset = fdt_path_offset(rw_fdt_blob, ofname);
+
+ return fdt_status_disabled(rw_fdt_blob, offset);
+}
+
+bool dm_i2c_simple_probe(struct udevice *bus, uint chip_addr)
+{
+ struct udevice *dev;
+
+ return !dm_i2c_probe(bus, chip_addr, DM_I2C_CHIP_RD_ADDRESS |
+ DM_I2C_CHIP_WR_ADDRESS, &dev);
+}
+
+int request_gpio_by_name(struct gpio_desc *gpio, const char *gpio_dev_name,
+ uint offset, char *gpio_name)
+{
+ struct udevice *gpio_dev = NULL;
+
+ if (uclass_get_device_by_name(UCLASS_GPIO, gpio_dev_name, &gpio_dev))
+ return 1;
+
+ gpio->dev = gpio_dev;
+ gpio->offset = offset;
+ gpio->flags = 0;
+
+ return dm_gpio_request(gpio, gpio_name);
+}
+
diff --git a/roms/u-boot/board/gdsys/a38x/dt_helpers.h b/roms/u-boot/board/gdsys/a38x/dt_helpers.h
new file mode 100644
index 000000000..245fadd0d
--- /dev/null
+++ b/roms/u-boot/board/gdsys/a38x/dt_helpers.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ */
+
+#ifndef __DT_HELPERS_H
+#define __DT_HELPERS_H
+
+int fdt_disable_by_ofname(void *rw_fdt_blob, char *ofname);
+bool dm_i2c_simple_probe(struct udevice *bus, uint chip_addr);
+int request_gpio_by_name(struct gpio_desc *gpio, const char *gpio_dev_name,
+ uint offset, char *gpio_name);
+
+#endif /* __DT_HELPERS_H */
diff --git a/roms/u-boot/board/gdsys/a38x/hre.c b/roms/u-boot/board/gdsys/a38x/hre.c
new file mode 100644
index 000000000..de5411a6b
--- /dev/null
+++ b/roms/u-boot/board/gdsys/a38x/hre.c
@@ -0,0 +1,529 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2013
+ * Reinhard Pfau, Guntermann & Drunck GmbH, reinhard.pfau@gdsys.cc
+ */
+
+#include <common.h>
+#include <log.h>
+#include <malloc.h>
+#include <fs.h>
+#include <i2c.h>
+#include <mmc.h>
+#include <tpm-v1.h>
+#include <u-boot/crc.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 tpm TPM device
+ * @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(struct udevice *tpm, uint32_t index, uint32_t *size)
+{
+ uint32_t err;
+ uint8_t info[72];
+ uint8_t *ptr;
+ uint16_t v16;
+
+ err = tpm1_get_capability(tpm, 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 tpm TPM device
+ * @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(struct udevice *tpm, 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 = tpm1_get_capability(tpm, 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 = tpm1_get_pub_key_oiap(tpm, 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
+ * @param tpm TPM device
+ * @return 0 if CCDM common data was found and read, !=0 if something failed.
+ */
+static int read_common_data(struct udevice *tpm)
+{
+ uint32_t size = 0;
+ uint32_t err;
+ uint8_t buf[256];
+ sha1_context ctx;
+
+ if (get_tpm_nv_size(tpm, NV_COMMON_DATA_INDEX, &size) ||
+ size < NV_COMMON_DATA_MIN_SIZE)
+ return 1;
+ err = tpm1_nv_read_value(tpm, 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 tpm TPM device
+ * @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(struct udevice *tpm, 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 = tpm1_pcr_read(tpm, 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(tpm);
+ 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 udevice *tpm, 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(tpm, src_reg->digest, dst_reg->digest, &parent_handle))
+ return -1;
+ hre_tpm_err = tpm1_load_key2_oiap(tpm, 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 tpm TPM device
+ * @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(struct udevice *tpm, 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(tpm, src_spec, HREG_RD);
+ if (hre_err || hre_tpm_err)
+ return NULL;
+ dst_reg = access_hreg(tpm, 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(tpm, 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 = tpm1_extend(tpm, 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 tpm TPM device
+ * @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(struct udevice *tpm, 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(tpm, &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/roms/u-boot/board/gdsys/a38x/hre.h b/roms/u-boot/board/gdsys/a38x/hre.h
new file mode 100644
index 000000000..da983aa45
--- /dev/null
+++ b/roms/u-boot/board/gdsys/a38x/hre.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2013
+ * Reinhard Pfau, Guntermann & Drunck GmbH, reinhard.pfau@gdsys.cc
+ */
+
+#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(struct udevice *tpm, const uint8_t *code, size_t code_size);
+
+#endif /* __HRE_H */
diff --git a/roms/u-boot/board/gdsys/a38x/hydra.c b/roms/u-boot/board/gdsys/a38x/hydra.c
new file mode 100644
index 000000000..495a97691
--- /dev/null
+++ b/roms/u-boot/board/gdsys/a38x/hydra.c
@@ -0,0 +1,140 @@
+#include <common.h>
+#include <command.h>
+#include <console.h> /* ctrlc */
+#include <pci.h>
+#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(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ uint k = 0;
+ void __iomem *pcie2_base = (void __iomem *)(MVEBU_REG_PCIE_BASE +
+ 0x4000);
+
+ if (!fpga)
+ return -1;
+
+ while (1) {
+ u32 res;
+
+ writel(REFL_PATTERN, &fpga->reflection_low);
+ res = readl(&fpga->reflection_low);
+ if (res != REFL_PATTERN_INV)
+ printf("round %u: read %08x, expected %08x\n",
+ k, res, REFL_PATTERN_INV);
+ writel(REFL_PATTERN_INV, &fpga->reflection_low);
+ res = readl(&fpga->reflection_low);
+ if (res != REFL_PATTERN)
+ printf("round %u: read %08x, expected %08x\n",
+ k, res, REFL_PATTERN);
+
+ res = readl(pcie2_base + 0x118) & 0x1f;
+ if (res)
+ printf("FrstErrPtr %u\n", res);
+ res = readl(pcie2_base + 0x104);
+ if (res) {
+ printf("Uncorrectable Error Status 0x%08x\n", res);
+ writel(res, pcie2_base + 0x104);
+ }
+
+ if (!(++k % 10000))
+ printf("round %u\n", k);
+
+ if (ctrlc())
+ break;
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ hydrate, 1, 0, do_hydrate,
+ "hydra reflection test",
+ "hydra reflection test"
+);
diff --git a/roms/u-boot/board/gdsys/a38x/hydra.h b/roms/u-boot/board/gdsys/a38x/hydra.h
new file mode 100644
index 000000000..26562a560
--- /dev/null
+++ b/roms/u-boot/board/gdsys/a38x/hydra.h
@@ -0,0 +1,14 @@
+struct ihs_fpga {
+ u32 reflection_low; /* 0x0000 */
+ u32 versions; /* 0x0004 */
+ u32 fpga_version; /* 0x0008 */
+ u32 fpga_features; /* 0x000c */
+ u32 reserved0[4]; /* 0x0010 */
+ u32 control; /* 0x0020 */
+ u32 reserved1[375]; /* 0x0024 */
+ u32 qsgmii_port_state[80]; /* 0x0600 */
+};
+
+void print_hydra_version(uint index);
+void hydra_initialize(void);
+struct ihs_fpga *get_fpga(void);
diff --git a/roms/u-boot/board/gdsys/a38x/ihs_phys.c b/roms/u-boot/board/gdsys/a38x/ihs_phys.c
new file mode 100644
index 000000000..c23d15092
--- /dev/null
+++ b/roms/u-boot/board/gdsys/a38x/ihs_phys.c
@@ -0,0 +1,357 @@
+#include <common.h>
+#include <dm.h>
+#include <miiphy.h>
+#include <asm-generic/gpio.h>
+#include <linux/bitops.h>
+#include <linux/delay.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);
diff --git a/roms/u-boot/board/gdsys/a38x/ihs_phys.h b/roms/u-boot/board/gdsys/a38x/ihs_phys.h
new file mode 100644
index 000000000..c4bec4d46
--- /dev/null
+++ b/roms/u-boot/board/gdsys/a38x/ihs_phys.h
@@ -0,0 +1,2 @@
+uint calculate_octo_phy_mask(void);
+int init_octo_phys(uint octo_phy_mask);
diff --git a/roms/u-boot/board/gdsys/a38x/keyprogram.c b/roms/u-boot/board/gdsys/a38x/keyprogram.c
new file mode 100644
index 000000000..7020fae18
--- /dev/null
+++ b/roms/u-boot/board/gdsys/a38x/keyprogram.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <tpm-v1.h>
+#include <malloc.h>
+#include <linux/ctype.h>
+#include <asm/unaligned.h>
+
+#include "hre.h"
+
+int flush_keys(struct udevice *tpm)
+{
+ u16 key_count;
+ u8 buf[288];
+ u8 *ptr;
+ u32 err;
+ uint i;
+
+ /* fetch list of already loaded keys in the TPM */
+ err = tpm1_get_capability(tpm, 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 = tpm1_flush_specific(tpm, 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(struct udevice *tpm)
+{
+ char *cmd = NULL;
+ u8 *binprog = NULL;
+ char *hexprog;
+ struct key_program *prog;
+
+ cmd = env_get("loadkeyprogram");
+
+ if (!cmd || run_command(cmd, 0))
+ return 1;
+
+ hexprog = env_get("keyprogram");
+
+ if (decode_hexstr(hexprog, &binprog))
+ return 1;
+
+ prog = parse_and_check_keyprog(binprog);
+ free(binprog);
+
+ if (!prog)
+ return 1;
+
+ if (hre_run_program(tpm, prog->code, prog->code_size)) {
+ free(prog);
+ return 1;
+ }
+
+ printf("\nSD code ran successfully\n");
+
+ free(prog);
+
+ return 0;
+}
diff --git a/roms/u-boot/board/gdsys/a38x/keyprogram.h b/roms/u-boot/board/gdsys/a38x/keyprogram.h
new file mode 100644
index 000000000..06889c67e
--- /dev/null
+++ b/roms/u-boot/board/gdsys/a38x/keyprogram.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ */
+
+#ifndef __KEYPROGRAM_H
+#define __KEYPROGRAM_H
+
+int load_and_run_keyprog(struct udevice *tpm);
+int flush_keys(struct udevice *tpm);
+
+#endif /* __KEYPROGRAM_H */
diff --git a/roms/u-boot/board/gdsys/a38x/spl.c b/roms/u-boot/board/gdsys/a38x/spl.c
new file mode 100644
index 000000000..84864d197
--- /dev/null
+++ b/roms/u-boot/board/gdsys/a38x/spl.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ */
+
+#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/roms/u-boot/board/gdsys/common/Makefile b/roms/u-boot/board/gdsys/common/Makefile
new file mode 100644
index 000000000..dd6d5e69d
--- /dev/null
+++ b/roms/u-boot/board/gdsys/common/Makefile
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2007
+# Stefan Roese, DENX Software Engineering, sr@denx.de.
+
+obj-$(CONFIG_SYS_FPGA_COMMON) += fpga.o
+obj-$(CONFIG_CMD_IOLOOP) += cmd_ioloop.o
+obj-$(CONFIG_CONTROLCENTERD) += dp501.o
+obj-$(CONFIG_TARGET_GAZERBEAM) += osd.o ihs_mdio.o ioep-fpga.o
+
+ifdef CONFIG_OSD
+obj-$(CONFIG_GDSYS_LEGACY_OSD_CMDS) += osd_cmd.o
+endif
diff --git a/roms/u-boot/board/gdsys/common/cmd_ioloop.c b/roms/u-boot/board/gdsys/common/cmd_ioloop.c
new file mode 100644
index 000000000..658756d98
--- /dev/null
+++ b/roms/u-boot/board/gdsys/common/cmd_ioloop.c
@@ -0,0 +1,585 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014
+ * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+
+#include <gdsys_fpga.h>
+
+#ifndef CONFIG_GDSYS_LEGACY_DRIVERS
+#include <dm.h>
+#include <misc.h>
+#include <regmap.h>
+#include <sysinfo.h>
+
+#include "../../../drivers/misc/gdsys_soc.h"
+#include "../../../drivers/misc/gdsys_ioep.h"
+#include "../../../drivers/misc/ihs_fpga.h"
+
+const int HEADER_WORDS = sizeof(struct io_generic_packet) / 2;
+#endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */
+
+enum status_print_type {
+ STATUS_LOUD = 0,
+ STATUS_SILENT = 1,
+};
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+enum {
+ STATE_TX_PACKET_BUILDING = BIT(0),
+ STATE_TX_TRANSMITTING = BIT(1),
+ STATE_TX_BUFFER_FULL = BIT(2),
+ STATE_TX_ERR = BIT(3),
+ STATE_RECEIVE_TIMEOUT = BIT(4),
+ STATE_PROC_RX_STORE_TIMEOUT = BIT(5),
+ STATE_PROC_RX_RECEIVE_TIMEOUT = BIT(6),
+ STATE_RX_DIST_ERR = BIT(7),
+ STATE_RX_LENGTH_ERR = BIT(8),
+ STATE_RX_FRAME_CTR_ERR = BIT(9),
+ STATE_RX_FCS_ERR = BIT(10),
+ STATE_RX_PACKET_DROPPED = BIT(11),
+ STATE_RX_DATA_LAST = BIT(12),
+ STATE_RX_DATA_FIRST = BIT(13),
+ STATE_RX_DATA_AVAILABLE = BIT(15),
+};
+
+enum {
+ IRQ_CPU_TRANSMITBUFFER_FREE_STATUS = BIT(5),
+ IRQ_CPU_PACKET_TRANSMITTED_EVENT = BIT(6),
+ IRQ_NEW_CPU_PACKET_RECEIVED_EVENT = BIT(7),
+ IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS = BIT(8),
+};
+
+enum {
+ CTRL_PROC_RECEIVE_ENABLE = BIT(12),
+ CTRL_FLUSH_TRANSMIT_BUFFER = BIT(15),
+};
+
+struct io_generic_packet {
+ u16 target_address;
+ u16 source_address;
+ u8 packet_type;
+ u8 bc;
+ u16 packet_length;
+} __attribute__((__packed__));
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
+
+unsigned long long rx_ctr;
+unsigned long long tx_ctr;
+unsigned long long err_ctr;
+#ifndef CONFIG_GDSYS_LEGACY_DRIVERS
+struct udevice *dev;
+#endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+static void io_check_status(uint fpga, u16 status, enum status_print_type type)
+{
+ u16 mask = STATE_RX_DIST_ERR | STATE_RX_LENGTH_ERR |
+ STATE_RX_FRAME_CTR_ERR | STATE_RX_FCS_ERR |
+ STATE_RX_PACKET_DROPPED | STATE_TX_ERR;
+
+ if (!(status & mask)) {
+ FPGA_SET_REG(fpga, ep.rx_tx_status, status);
+ return;
+ }
+
+ err_ctr++;
+ FPGA_SET_REG(fpga, ep.rx_tx_status, status);
+
+ if (type == STATUS_SILENT)
+ return;
+
+ if (status & STATE_RX_PACKET_DROPPED)
+ printf("RX_PACKET_DROPPED, status %04x\n", status);
+
+ if (status & STATE_RX_DIST_ERR)
+ printf("RX_DIST_ERR\n");
+ if (status & STATE_RX_LENGTH_ERR)
+ printf("RX_LENGTH_ERR\n");
+ if (status & STATE_RX_FRAME_CTR_ERR)
+ printf("RX_FRAME_CTR_ERR\n");
+ if (status & STATE_RX_FCS_ERR)
+ printf("RX_FCS_ERR\n");
+
+ if (status & STATE_TX_ERR)
+ printf("TX_ERR\n");
+}
+#else
+static void io_check_status(struct udevice *dev, enum status_print_type type)
+{
+ u16 status = 0;
+ int ret;
+
+ ret = misc_call(dev, 0, NULL, 0, &status, 0);
+ if (!ret)
+ return;
+
+ err_ctr++;
+
+ if (type != STATUS_LOUD)
+ return;
+
+ if (status & STATE_RX_PACKET_DROPPED)
+ printf("RX_PACKET_DROPPED, status %04x\n", status);
+
+ if (status & STATE_RX_DIST_ERR)
+ printf("RX_DIST_ERR\n");
+ if (status & STATE_RX_LENGTH_ERR)
+ printf("RX_LENGTH_ERR\n");
+ if (status & STATE_RX_FRAME_CTR_ERR)
+ printf("RX_FRAME_CTR_ERR\n");
+ if (status & STATE_RX_FCS_ERR)
+ printf("RX_FCS_ERR\n");
+
+ if (status & STATE_TX_ERR)
+ printf("TX_ERR\n");
+}
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+static void io_send(uint fpga, uint size)
+{
+ uint k;
+ struct io_generic_packet packet = {
+ .source_address = 1,
+ .packet_type = 1,
+ .packet_length = size,
+ };
+ u16 *p = (u16 *)&packet;
+
+ for (k = 0; k < sizeof(packet) / 2; ++k)
+ FPGA_SET_REG(fpga, ep.transmit_data, *p++);
+
+ for (k = 0; k < (size + 1) / 2; ++k)
+ FPGA_SET_REG(fpga, ep.transmit_data, k);
+
+ FPGA_SET_REG(fpga, ep.rx_tx_control,
+ CTRL_PROC_RECEIVE_ENABLE | CTRL_FLUSH_TRANSMIT_BUFFER);
+
+ tx_ctr++;
+}
+#else
+static void io_send(struct udevice *dev, uint size)
+{
+ uint k;
+ u16 buffer[HEADER_WORDS + 128];
+ struct io_generic_packet header = {
+ .source_address = 1,
+ .packet_type = 1,
+ .packet_length = size,
+ };
+ const uint words = (size + 1) / 2;
+
+ memcpy(buffer, &header, 2 * HEADER_WORDS);
+ for (k = 0; k < words; ++k)
+ buffer[k + HEADER_WORDS] = (2 * k + 1) + ((2 * k) << 8);
+
+ misc_write(dev, 0, buffer, HEADER_WORDS + words);
+
+ tx_ctr++;
+}
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+static void io_receive(uint fpga)
+{
+ u16 rx_tx_status;
+
+ FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
+
+ while (rx_tx_status & STATE_RX_DATA_AVAILABLE) {
+ u16 rx;
+
+ if (rx_tx_status & STATE_RX_DATA_LAST)
+ rx_ctr++;
+
+ FPGA_GET_REG(fpga, ep.receive_data, &rx);
+
+ FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
+ }
+}
+#else
+static void io_receive(struct udevice *dev)
+{
+ u16 buffer[HEADER_WORDS + 128];
+
+ if (!misc_read(dev, 0, buffer, 0))
+ rx_ctr++;
+}
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+static void io_reflect(uint fpga)
+{
+ u16 buffer[128];
+
+ uint k = 0;
+ uint n;
+ u16 rx_tx_status;
+
+ FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
+
+ while (rx_tx_status & STATE_RX_DATA_AVAILABLE) {
+ FPGA_GET_REG(fpga, ep.receive_data, &buffer[k++]);
+ if (rx_tx_status & STATE_RX_DATA_LAST)
+ break;
+
+ FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
+ }
+
+ if (!k)
+ return;
+
+ for (n = 0; n < k; ++n)
+ FPGA_SET_REG(fpga, ep.transmit_data, buffer[n]);
+
+ FPGA_SET_REG(fpga, ep.rx_tx_control,
+ CTRL_PROC_RECEIVE_ENABLE | CTRL_FLUSH_TRANSMIT_BUFFER);
+
+ tx_ctr++;
+}
+#else
+static void io_reflect(struct udevice *dev)
+{
+ u16 buffer[HEADER_WORDS + 128];
+ struct io_generic_packet *header;
+
+ if (misc_read(dev, 0, buffer, 0))
+ return;
+
+ header = (struct io_generic_packet *)&buffer;
+
+ misc_write(dev, 0, buffer, HEADER_WORDS + header->packet_length);
+}
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+/*
+ * FPGA io-endpoint reflector
+ *
+ * Syntax:
+ * ioreflect {fpga} {reportrate}
+ */
+int do_ioreflect(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ uint fpga;
+ uint rate = 0;
+ unsigned long long last_seen = 0;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ fpga = simple_strtoul(argv[1], NULL, 10);
+
+ /*
+ * If another parameter, it is the report rate in packets.
+ */
+ if (argc > 2)
+ rate = simple_strtoul(argv[2], NULL, 10);
+
+ /* Enable receive path */
+ FPGA_SET_REG(fpga, ep.rx_tx_control, CTRL_PROC_RECEIVE_ENABLE);
+
+ /* Set device address to dummy 1*/
+ FPGA_SET_REG(fpga, ep.device_address, 1);
+
+ rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
+
+ while (1) {
+ u16 top_int;
+ u16 rx_tx_status;
+
+ FPGA_GET_REG(fpga, top_interrupt, &top_int);
+ FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
+
+ io_check_status(fpga, rx_tx_status, STATUS_SILENT);
+ if ((top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS) &&
+ (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS))
+ io_reflect(fpga);
+
+ if (rate) {
+ if (!(tx_ctr % rate) && (tx_ctr != last_seen))
+ printf("refl %llu, err %llu\n", tx_ctr,
+ err_ctr);
+ last_seen = tx_ctr;
+ }
+
+ if (ctrlc())
+ break;
+ }
+
+ return 0;
+}
+#else
+/*
+ * FPGA io-endpoint reflector
+ *
+ * Syntax:
+ * ioreflect {reportrate}
+ */
+int do_ioreflect(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct udevice *fpga;
+ struct regmap *map;
+ uint rate = 0;
+ unsigned long long last_seen = 0;
+
+ if (!dev) {
+ printf("No device selected\n");
+ return 1;
+ }
+
+ gdsys_soc_get_fpga(dev, &fpga);
+ regmap_init_mem(dev_ofnode(dev), &map);
+
+ /* Enable receive path */
+ misc_set_enabled(dev, true);
+
+ rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
+
+ while (1) {
+ uint top_int;
+
+ ihs_fpga_get(map, top_interrupt, &top_int);
+ io_check_status(dev, STATUS_SILENT);
+ if ((top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS) &&
+ (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS))
+ io_reflect(dev);
+
+ if (rate) {
+ if (!(tx_ctr % rate) && (tx_ctr != last_seen))
+ printf("refl %llu, err %llu\n", tx_ctr,
+ err_ctr);
+ last_seen = tx_ctr;
+ }
+
+ if (ctrlc())
+ break;
+ }
+
+ return 0;
+}
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#define DISP_LINE_LEN 16
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+/*
+ * FPGA io-endpoint looptest
+ *
+ * Syntax:
+ * ioloop {fpga} {size} {rate}
+ */
+int do_ioloop(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ uint fpga;
+ uint size;
+ uint rate = 0;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ /*
+ * FPGA is specified since argc > 2
+ */
+ fpga = simple_strtoul(argv[1], NULL, 10);
+
+ /*
+ * packet size is specified since argc > 2
+ */
+ size = simple_strtoul(argv[2], NULL, 10);
+
+ /*
+ * If another parameter, it is the test rate in packets per second.
+ */
+ if (argc > 3)
+ rate = simple_strtoul(argv[3], NULL, 10);
+
+ /* enable receive path */
+ FPGA_SET_REG(fpga, ep.rx_tx_control, CTRL_PROC_RECEIVE_ENABLE);
+
+ /* set device address to dummy 1*/
+ FPGA_SET_REG(fpga, ep.device_address, 1);
+
+ rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
+
+ while (1) {
+ u16 top_int;
+ u16 rx_tx_status;
+
+ FPGA_GET_REG(fpga, top_interrupt, &top_int);
+ FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
+
+ io_check_status(fpga, rx_tx_status, STATUS_LOUD);
+ if (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS)
+ io_send(fpga, size);
+ if (top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS)
+ io_receive(fpga);
+
+ if (rate) {
+ if (ctrlc())
+ break;
+ udelay(1000000 / rate);
+ if (!(tx_ctr % rate))
+ printf("d %llu, tx %llu, rx %llu, err %llu\n",
+ tx_ctr - rx_ctr, tx_ctr, rx_ctr,
+ err_ctr);
+ }
+ }
+
+ return 0;
+}
+#else
+/*
+ * FPGA io-endpoint looptest
+ *
+ * Syntax:
+ * ioloop {size} {rate}
+ */
+int do_ioloop(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ uint size;
+ uint rate = 0;
+ struct udevice *fpga;
+ struct regmap *map;
+
+ if (!dev) {
+ printf("No device selected\n");
+ return 1;
+ }
+
+ gdsys_soc_get_fpga(dev, &fpga);
+ regmap_init_mem(dev_ofnode(dev), &map);
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ /*
+ * packet size is specified since argc > 1
+ */
+ size = simple_strtoul(argv[2], NULL, 10);
+
+ /*
+ * If another parameter, it is the test rate in packets per second.
+ */
+ if (argc > 2)
+ rate = simple_strtoul(argv[3], NULL, 10);
+
+ /* Enable receive path */
+ misc_set_enabled(dev, true);
+
+ rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
+
+ while (1) {
+ uint top_int;
+
+ if (ctrlc())
+ break;
+
+ ihs_fpga_get(map, top_interrupt, &top_int);
+
+ io_check_status(dev, STATUS_LOUD);
+ if (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS)
+ io_send(dev, size);
+ if (top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS)
+ io_receive(dev);
+
+ if (rate) {
+ udelay(1000000 / rate);
+ if (!(tx_ctr % rate))
+ printf("d %llu, tx %llu, rx %llu, err %llu\n",
+ tx_ctr - rx_ctr, tx_ctr, rx_ctr,
+ err_ctr);
+ }
+ }
+ return 0;
+}
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#ifndef CONFIG_GDSYS_LEGACY_DRIVERS
+int do_iodev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct udevice *ioep = NULL;
+ struct udevice *sysinfo;
+ char name[8];
+ int ret;
+
+ if (sysinfo_get(&sysinfo))
+ return CMD_RET_FAILURE;
+
+ if (argc > 1) {
+ int i = simple_strtoul(argv[1], NULL, 10);
+
+ snprintf(name, sizeof(name), "ioep%d", i);
+
+ ret = uclass_get_device_by_phandle(UCLASS_MISC, sysinfo, name,
+ &ioep);
+
+ if (ret || !ioep) {
+ printf("Invalid IOEP %d\n", i);
+ return CMD_RET_FAILURE;
+ }
+
+ dev = ioep;
+ } else {
+ int i = 0;
+
+ while (1) {
+ snprintf(name, sizeof(name), "ioep%d", i);
+
+ ret = uclass_get_device_by_phandle(UCLASS_MISC, sysinfo,
+ name, &ioep);
+
+ if (ret || !ioep)
+ break;
+
+ printf("IOEP %d:\t%s\n", i++, ioep->name);
+ }
+
+ if (dev)
+ printf("\nSelected IOEP: %s\n", dev->name);
+ else
+ puts("\nNo IOEP selected.\n");
+ }
+
+ return 0;
+}
+#endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+U_BOOT_CMD(
+ ioloop, 4, 0, do_ioloop,
+ "fpga io-endpoint looptest",
+ "fpga packetsize [packets/sec]"
+);
+
+U_BOOT_CMD(
+ ioreflect, 3, 0, do_ioreflect,
+ "fpga io-endpoint reflector",
+ "fpga reportrate"
+);
+#else
+U_BOOT_CMD(
+ ioloop, 3, 0, do_ioloop,
+ "fpga io-endpoint looptest",
+ "packetsize [packets/sec]"
+);
+
+U_BOOT_CMD(
+ ioreflect, 2, 0, do_ioreflect,
+ "fpga io-endpoint reflector",
+ "reportrate"
+);
+
+U_BOOT_CMD(
+ iodev, 2, 0, do_iodev,
+ "fpga io-endpoint listing/selection",
+ "[ioep device to select]"
+);
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
diff --git a/roms/u-boot/board/gdsys/common/dp501.c b/roms/u-boot/board/gdsys/common/dp501.c
new file mode 100644
index 000000000..9ca69ebcb
--- /dev/null
+++ b/roms/u-boot/board/gdsys/common/dp501.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2012
+ * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
+ */
+
+/* Parade Technologies Inc. DP501 DisplayPort DVI/HDMI Transmitter */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+
+#include <common.h>
+#include <asm/io.h>
+#include <errno.h>
+#include <i2c.h>
+
+#define DP501_I2C_ADDR 0x08
+
+#ifdef CONFIG_SYS_DP501_I2C
+int dp501_i2c[] = CONFIG_SYS_DP501_I2C;
+#endif
+
+#ifdef CONFIG_SYS_DP501_BASE
+int dp501_base[] = CONFIG_SYS_DP501_BASE;
+#endif
+
+static void dp501_setbits(u8 addr, u8 reg, u8 mask)
+{
+ u8 val;
+
+ val = i2c_reg_read(addr, reg);
+ setbits_8(&val, mask);
+ i2c_reg_write(addr, reg, val);
+}
+
+static void dp501_clrbits(u8 addr, u8 reg, u8 mask)
+{
+ u8 val;
+
+ val = i2c_reg_read(addr, reg);
+ clrbits_8(&val, mask);
+ i2c_reg_write(addr, reg, val);
+}
+
+static int dp501_detect_cable_adapter(u8 addr)
+{
+ u8 val = i2c_reg_read(addr, 0x00);
+
+ return !(val & 0x04);
+}
+
+static void dp501_link_training(u8 addr)
+{
+ u8 val;
+ u8 link_bw;
+ u8 max_lane_cnt;
+ u8 lane_cnt;
+
+ val = i2c_reg_read(addr, 0x51);
+ if (val >= 0x0a)
+ link_bw = 0x0a;
+ else
+ link_bw = 0x06;
+ if (link_bw != val)
+ printf("DP sink supports %d Mbps link rate, set to %d Mbps\n",
+ val * 270, link_bw * 270);
+ i2c_reg_write(addr, 0x5d, link_bw); /* set link_bw */
+ val = i2c_reg_read(addr, 0x52);
+ max_lane_cnt = val & 0x1f;
+ if (max_lane_cnt >= 4)
+ lane_cnt = 4;
+ else
+ lane_cnt = max_lane_cnt;
+ if (lane_cnt != max_lane_cnt)
+ printf("DP sink supports %d lanes, set to %d lanes\n",
+ max_lane_cnt, lane_cnt);
+ i2c_reg_write(addr, 0x5e, lane_cnt | (val & 0x80)); /* set lane_cnt */
+ val = i2c_reg_read(addr, 0x53);
+ i2c_reg_write(addr, 0x5c, val); /* set downspread_ctl */
+
+ i2c_reg_write(addr, 0x5f, 0x0d); /* start training */
+}
+
+void dp501_powerup(u8 addr)
+{
+ dp501_clrbits(addr, 0x0a, 0x30); /* power on encoder */
+ dp501_setbits(addr, 0x0a, 0x0e); /* block HDCP and MCCS on I2C bride*/
+ i2c_reg_write(addr, 0x27, 0x30); /* Hardware auto detect DVO timing */
+ dp501_setbits(addr, 0x72, 0x80); /* DPCD read enable */
+ dp501_setbits(addr, 0x30, 0x20); /* RS polynomial select */
+ i2c_reg_write(addr, 0x71, 0x20); /* Enable Aux burst write */
+ dp501_setbits(addr, 0x78, 0x30); /* Disable HPD2 IRQ */
+ dp501_clrbits(addr, 0x2f, 0x40); /* Link FIFO reset selection */
+ dp501_clrbits(addr, 0x60, 0x20); /* Enable scrambling */
+
+#ifdef CONFIG_SYS_DP501_VCAPCTRL0
+ i2c_reg_write(addr, 0x24, CONFIG_SYS_DP501_VCAPCTRL0);
+#else
+ i2c_reg_write(addr, 0x24, 0xc0); /* SDR mode 0, ext. H/VSYNC */
+#endif
+
+#ifdef CONFIG_SYS_DP501_DIFFERENTIAL
+ i2c_reg_write(addr + 2, 0x24, 0x10); /* clock input differential */
+ i2c_reg_write(addr + 2, 0x25, 0x04);
+ i2c_reg_write(addr + 2, 0x26, 0x10);
+#else
+ i2c_reg_write(addr + 2, 0x24, 0x02); /* clock input single ended */
+#endif
+
+ i2c_reg_write(addr + 2, 0x1a, 0x04); /* SPDIF input method TTL */
+
+ i2c_reg_write(addr + 2, 0x00, 0x18); /* driving strength */
+ i2c_reg_write(addr + 2, 0x03, 0x06); /* driving strength */
+ i2c_reg_write(addr, 0x2c, 0x00); /* configure N value */
+ i2c_reg_write(addr, 0x2d, 0x00); /* configure N value */
+ i2c_reg_write(addr, 0x2e, 0x0c); /* configure N value */
+ i2c_reg_write(addr, 0x76, 0xff); /* clear all interrupt */
+ dp501_setbits(addr, 0x78, 0x03); /* clear all interrupt */
+ i2c_reg_write(addr, 0x75, 0xf8); /* aux channel reset */
+ i2c_reg_write(addr, 0x75, 0x00); /* clear aux channel reset */
+ i2c_reg_write(addr, 0x87, 0x7f); /* set retry counter as 7
+ retry interval 400us */
+
+ if (dp501_detect_cable_adapter(addr)) {
+ printf("DVI/HDMI cable adapter detected\n");
+ i2c_reg_write(addr, 0x5e, 0x04); /* enable 4 channel */
+ dp501_clrbits(addr, 0x00, 0x08); /* DVI/HDMI HDCP operation */
+ } else {
+ printf("no DVI/HDMI cable adapter detected\n");
+ dp501_setbits(addr, 0x00, 0x08); /* for DP HDCP operation */
+
+ dp501_link_training(addr);
+ }
+}
+
+void dp501_powerdown(u8 addr)
+{
+ dp501_setbits(addr, 0x0a, 0x30); /* power down encoder, standby mode */
+}
+
+
+int dp501_probe(unsigned screen, bool power)
+{
+#ifdef CONFIG_SYS_DP501_BASE
+ uint8_t dp501_addr = dp501_base[screen];
+#else
+ uint8_t dp501_addr = DP501_I2C_ADDR;
+#endif
+
+#ifdef CONFIG_SYS_DP501_I2C
+ i2c_set_bus_num(dp501_i2c[screen]);
+#endif
+
+ if (i2c_probe(dp501_addr))
+ return -1;
+
+ dp501_powerup(dp501_addr);
+
+ return 0;
+}
+
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
diff --git a/roms/u-boot/board/gdsys/common/dp501.h b/roms/u-boot/board/gdsys/common/dp501.h
new file mode 100644
index 000000000..b98b54edc
--- /dev/null
+++ b/roms/u-boot/board/gdsys/common/dp501.h
@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 2012
+ * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _DP501_H_
+#define _DP501_H_
+
+void dp501_powerup(u8 addr);
+void dp501_powerdown(u8 addr);
+int dp501_probe(unsigned screen, bool power);
+
+#endif
diff --git a/roms/u-boot/board/gdsys/common/fpga.c b/roms/u-boot/board/gdsys/common/fpga.c
new file mode 100644
index 000000000..5ba6613ed
--- /dev/null
+++ b/roms/u-boot/board/gdsys/common/fpga.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2013
+ * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
+ */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+
+#include <common.h>
+#include <gdsys_fpga.h>
+
+#include <asm/io.h>
+
+int fpga_set_reg(u32 fpga, u16 *reg, off_t regoff, u16 data)
+{
+ out_le16(reg, data);
+
+ return 0;
+}
+
+int fpga_get_reg(u32 fpga, u16 *reg, off_t regoff, u16 *data)
+{
+ *data = in_le16(reg);
+
+ return 0;
+}
+
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
diff --git a/roms/u-boot/board/gdsys/common/ihs_mdio.c b/roms/u-boot/board/gdsys/common/ihs_mdio.c
new file mode 100644
index 000000000..5f1215e9e
--- /dev/null
+++ b/roms/u-boot/board/gdsys/common/ihs_mdio.c
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014
+ * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
+ */
+
+#include <common.h>
+#include <linux/delay.h>
+
+#include <miiphy.h>
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+#include <gdsys_fpga.h>
+#else
+#include <fdtdec.h>
+#include <dm.h>
+#include <regmap.h>
+#endif
+
+#include "ihs_mdio.h"
+
+#ifndef CONFIG_GDSYS_LEGACY_DRIVERS
+enum {
+ REG_MDIO_CONTROL = 0x0,
+ REG_MDIO_ADDR_DATA = 0x2,
+ REG_MDIO_RX_DATA = 0x4,
+};
+
+static inline u16 read_reg(struct udevice *fpga, uint base, uint addr)
+{
+ struct regmap *map;
+ u8 *ptr;
+
+ regmap_init_mem(dev_ofnode(fpga), &map);
+ ptr = regmap_get_range(map, 0);
+
+ return in_le16((u16 *)(ptr + base + addr));
+}
+
+static inline void write_reg(struct udevice *fpga, uint base, uint addr,
+ u16 val)
+{
+ struct regmap *map;
+ u8 *ptr;
+
+ regmap_init_mem(dev_ofnode(fpga), &map);
+ ptr = regmap_get_range(map, 0);
+
+ out_le16((u16 *)(ptr + base + addr), val);
+}
+#endif
+
+static inline u16 read_control(struct ihs_mdio_info *info)
+{
+ u16 val;
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+ FPGA_GET_REG(info->fpga, mdio.control, &val);
+#else
+ val = read_reg(info->fpga, info->base, REG_MDIO_CONTROL);
+#endif
+ return val;
+}
+
+static inline void write_control(struct ihs_mdio_info *info, u16 val)
+{
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+ FPGA_SET_REG(info->fpga, mdio.control, val);
+#else
+ write_reg(info->fpga, info->base, REG_MDIO_CONTROL, val);
+#endif
+}
+
+static inline void write_addr_data(struct ihs_mdio_info *info, u16 val)
+{
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+ FPGA_SET_REG(info->fpga, mdio.address_data, val);
+#else
+ write_reg(info->fpga, info->base, REG_MDIO_ADDR_DATA, val);
+#endif
+}
+
+static inline u16 read_rx_data(struct ihs_mdio_info *info)
+{
+ u16 val;
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+ FPGA_GET_REG(info->fpga, mdio.rx_data, &val);
+#else
+ val = read_reg(info->fpga, info->base, REG_MDIO_RX_DATA);
+#endif
+ return val;
+}
+
+static int ihs_mdio_idle(struct mii_dev *bus)
+{
+ struct ihs_mdio_info *info = bus->priv;
+ u16 val;
+ unsigned int ctr = 0;
+
+ do {
+ val = read_control(info);
+ udelay(100);
+ if (ctr++ > 10)
+ return -1;
+ } while (!(val & (1 << 12)));
+
+ return 0;
+}
+
+static int ihs_mdio_reset(struct mii_dev *bus)
+{
+ ihs_mdio_idle(bus);
+
+ return 0;
+}
+
+static int ihs_mdio_read(struct mii_dev *bus, int addr, int dev_addr,
+ int regnum)
+{
+ struct ihs_mdio_info *info = bus->priv;
+ u16 val;
+
+ ihs_mdio_idle(bus);
+
+ write_control(info,
+ ((addr & 0x1f) << 5) | (regnum & 0x1f) | (2 << 10));
+
+ /* wait for rx data available */
+ udelay(100);
+
+ val = read_rx_data(info);
+
+ return val;
+}
+
+static int ihs_mdio_write(struct mii_dev *bus, int addr, int dev_addr,
+ int regnum, u16 value)
+{
+ struct ihs_mdio_info *info = bus->priv;
+
+ ihs_mdio_idle(bus);
+
+ write_addr_data(info, value);
+ write_control(info, ((addr & 0x1f) << 5) | (regnum & 0x1f) | (1 << 10));
+
+ return 0;
+}
+
+int ihs_mdio_init(struct ihs_mdio_info *info)
+{
+ struct mii_dev *bus = mdio_alloc();
+
+ if (!bus) {
+ printf("Failed to allocate FSL MDIO bus\n");
+ return -1;
+ }
+
+ bus->read = ihs_mdio_read;
+ bus->write = ihs_mdio_write;
+ bus->reset = ihs_mdio_reset;
+ strcpy(bus->name, info->name);
+
+ bus->priv = info;
+
+ return mdio_register(bus);
+}
diff --git a/roms/u-boot/board/gdsys/common/ihs_mdio.h b/roms/u-boot/board/gdsys/common/ihs_mdio.h
new file mode 100644
index 000000000..d0a4b0d7a
--- /dev/null
+++ b/roms/u-boot/board/gdsys/common/ihs_mdio.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2014
+ * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
+ */
+
+#ifndef _IHS_MDIO_H_
+#define _IHS_MDIO_H_
+
+struct ihs_mdio_info {
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+ u32 fpga;
+#else
+ struct udevice *fpga;
+ int base;
+#endif
+ char *name;
+};
+
+int ihs_mdio_init(struct ihs_mdio_info *info);
+
+#endif
diff --git a/roms/u-boot/board/gdsys/common/ioep-fpga.c b/roms/u-boot/board/gdsys/common/ioep-fpga.c
new file mode 100644
index 000000000..7292d7ab5
--- /dev/null
+++ b/roms/u-boot/board/gdsys/common/ioep-fpga.c
@@ -0,0 +1,591 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014
+ * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
+ */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+
+#include <common.h>
+
+#include <gdsys_fpga.h>
+#include <linux/bitops.h>
+
+enum pcb_video_type {
+ PCB_DVI_SL,
+ PCB_DP_165MPIX,
+ PCB_DP_300MPIX,
+ PCB_HDMI,
+ PCB_DP_1_2,
+ PCB_HDMI_2_0,
+};
+
+enum pcb_transmission_type {
+ PCB_CAT_1G,
+ PCB_FIBER_3G,
+ PCB_CAT_10G,
+ PCB_FIBER_10G,
+};
+
+enum carrier_speed {
+ CARRIER_SPEED_1G,
+ CARRIER_SPEED_3G,
+ CARRIER_SPEED_2_5G = CARRIER_SPEED_3G,
+ CARRIER_SPEED_10G,
+};
+
+enum ram_config {
+ RAM_DDR2_32BIT_295MBPS,
+ RAM_DDR3_32BIT_590MBPS,
+ RAM_DDR3_48BIT_590MBPS,
+ RAM_DDR3_64BIT_1800MBPS,
+ RAM_DDR3_48BIT_1800MBPS,
+};
+
+enum sysclock {
+ SYSCLK_147456,
+};
+
+struct fpga_versions {
+ bool video_channel;
+ bool con_side;
+ enum pcb_video_type pcb_video_type;
+ enum pcb_transmission_type pcb_transmission_type;
+ unsigned int hw_version;
+};
+
+struct fpga_features {
+ u8 video_channels;
+ u8 carriers;
+ enum carrier_speed carrier_speed;
+ enum ram_config ram_config;
+ enum sysclock sysclock;
+
+ bool pcm_tx;
+ bool pcm_rx;
+ bool spdif_tx;
+ bool spdif_rx;
+ bool usb2;
+ bool rs232;
+ bool compression_type1;
+ bool compression_type2;
+ bool compression_type3;
+ bool interlace;
+ bool osd;
+ bool compression_pipes;
+};
+
+#ifdef CONFIG_SYS_FPGA_FLAVOR_GAZERBEAM
+
+static int get_versions(unsigned int fpga, struct fpga_versions *versions)
+{
+ enum {
+ VERSIONS_FPGA_VIDEO_CHANNEL = BIT(12),
+ VERSIONS_FPGA_CON_SIDE = BIT(13),
+ VERSIONS_FPGA_SC = BIT(14),
+ VERSIONS_PCB_CON = BIT(9),
+ VERSIONS_PCB_SC = BIT(8),
+ VERSIONS_PCB_VIDEO_MASK = 0x3 << 6,
+ VERSIONS_PCB_VIDEO_DP_1_2 = 0x0 << 6,
+ VERSIONS_PCB_VIDEO_HDMI_2_0 = 0x1 << 6,
+ VERSIONS_PCB_TRANSMISSION_MASK = 0x3 << 4,
+ VERSIONS_PCB_TRANSMISSION_FIBER_10G = 0x0 << 4,
+ VERSIONS_PCB_TRANSMISSION_CAT_10G = 0x1 << 4,
+ VERSIONS_PCB_TRANSMISSION_FIBER_3G = 0x2 << 4,
+ VERSIONS_PCB_TRANSMISSION_CAT_1G = 0x3 << 4,
+ VERSIONS_HW_VER_MASK = 0xf << 0,
+ };
+ u16 raw_versions;
+
+ memset(versions, 0, sizeof(struct fpga_versions));
+
+ FPGA_GET_REG(fpga, versions, &raw_versions);
+
+ versions->video_channel = raw_versions & VERSIONS_FPGA_VIDEO_CHANNEL;
+ versions->con_side = raw_versions & VERSIONS_FPGA_CON_SIDE;
+
+ switch (raw_versions & VERSIONS_PCB_VIDEO_MASK) {
+ case VERSIONS_PCB_VIDEO_DP_1_2:
+ versions->pcb_video_type = PCB_DP_1_2;
+ break;
+
+ case VERSIONS_PCB_VIDEO_HDMI_2_0:
+ versions->pcb_video_type = PCB_HDMI_2_0;
+ break;
+ }
+
+ switch (raw_versions & VERSIONS_PCB_TRANSMISSION_MASK) {
+ case VERSIONS_PCB_TRANSMISSION_FIBER_10G:
+ versions->pcb_transmission_type = PCB_FIBER_10G;
+ break;
+
+ case VERSIONS_PCB_TRANSMISSION_CAT_10G:
+ versions->pcb_transmission_type = PCB_CAT_10G;
+ break;
+
+ case VERSIONS_PCB_TRANSMISSION_FIBER_3G:
+ versions->pcb_transmission_type = PCB_FIBER_3G;
+ break;
+
+ case VERSIONS_PCB_TRANSMISSION_CAT_1G:
+ versions->pcb_transmission_type = PCB_CAT_1G;
+ break;
+
+ }
+
+ versions->hw_version = raw_versions & VERSIONS_HW_VER_MASK;
+
+ return 0;
+}
+
+static int get_features(unsigned int fpga, struct fpga_features *features)
+{
+ enum {
+ FEATURE_SPDIF_RX = BIT(15),
+ FEATURE_SPDIF_TX = BIT(14),
+ FEATURE_PCM_RX = BIT(13),
+ FEATURE_PCM_TX = BIT(12),
+ FEATURE_RAM_MASK = GENMASK(11, 8),
+ FEATURE_RAM_DDR2_32BIT_295MBPS = 0x0 << 8,
+ FEATURE_RAM_DDR3_32BIT_590MBPS = 0x1 << 8,
+ FEATURE_RAM_DDR3_48BIT_590MBPS = 0x2 << 8,
+ FEATURE_RAM_DDR3_64BIT_1800MBPS = 0x3 << 8,
+ FEATURE_RAM_DDR3_48BIT_1800MBPS = 0x4 << 8,
+ FEATURE_CARRIER_SPEED_MASK = GENMASK(7, 6),
+ FEATURE_CARRIER_SPEED_1G = 0x0 << 6,
+ FEATURE_CARRIER_SPEED_2_5G = 0x1 << 6,
+ FEATURE_CARRIER_SPEED_10G = 0x2 << 6,
+ FEATURE_CARRIERS_MASK = GENMASK(5, 4),
+ FEATURE_CARRIERS_0 = 0x0 << 4,
+ FEATURE_CARRIERS_1 = 0x1 << 4,
+ FEATURE_CARRIERS_2 = 0x2 << 4,
+ FEATURE_CARRIERS_4 = 0x3 << 4,
+ FEATURE_USB2 = BIT(3),
+ FEATURE_VIDEOCHANNELS_MASK = GENMASK(2, 0),
+ FEATURE_VIDEOCHANNELS_0 = 0x0 << 0,
+ FEATURE_VIDEOCHANNELS_1 = 0x1 << 0,
+ FEATURE_VIDEOCHANNELS_1_1 = 0x2 << 0,
+ FEATURE_VIDEOCHANNELS_2 = 0x3 << 0,
+ };
+
+ enum {
+ EXT_FEATURE_OSD = BIT(15),
+ EXT_FEATURE_ETHERNET = BIT(9),
+ EXT_FEATURE_INTERLACE = BIT(8),
+ EXT_FEATURE_RS232 = BIT(7),
+ EXT_FEATURE_COMPRESSION_PERF_MASK = GENMASK(6, 4),
+ EXT_FEATURE_COMPRESSION_PERF_1X = 0x0 << 4,
+ EXT_FEATURE_COMPRESSION_PERF_2X = 0x1 << 4,
+ EXT_FEATURE_COMPRESSION_PERF_4X = 0x2 << 4,
+ EXT_FEATURE_COMPRESSION_TYPE1 = BIT(0),
+ EXT_FEATURE_COMPRESSION_TYPE2 = BIT(1),
+ EXT_FEATURE_COMPRESSION_TYPE3 = BIT(2),
+ };
+
+ u16 raw_features;
+ u16 raw_extended_features;
+
+ memset(features, 0, sizeof(struct fpga_features));
+
+ FPGA_GET_REG(fpga, fpga_features, &raw_features);
+ FPGA_GET_REG(fpga, fpga_ext_features, &raw_extended_features);
+
+ switch (raw_features & FEATURE_VIDEOCHANNELS_MASK) {
+ case FEATURE_VIDEOCHANNELS_0:
+ features->video_channels = 0;
+ break;
+
+ case FEATURE_VIDEOCHANNELS_1:
+ features->video_channels = 1;
+ break;
+
+ case FEATURE_VIDEOCHANNELS_1_1:
+ case FEATURE_VIDEOCHANNELS_2:
+ features->video_channels = 2;
+ break;
+ };
+
+ switch (raw_features & FEATURE_CARRIERS_MASK) {
+ case FEATURE_CARRIERS_0:
+ features->carriers = 0;
+ break;
+
+ case FEATURE_CARRIERS_1:
+ features->carriers = 1;
+ break;
+
+ case FEATURE_CARRIERS_2:
+ features->carriers = 2;
+ break;
+
+ case FEATURE_CARRIERS_4:
+ features->carriers = 4;
+ break;
+ }
+
+ switch (raw_features & FEATURE_CARRIER_SPEED_MASK) {
+ case FEATURE_CARRIER_SPEED_1G:
+ features->carrier_speed = CARRIER_SPEED_1G;
+ break;
+ case FEATURE_CARRIER_SPEED_2_5G:
+ features->carrier_speed = CARRIER_SPEED_2_5G;
+ break;
+ case FEATURE_CARRIER_SPEED_10G:
+ features->carrier_speed = CARRIER_SPEED_10G;
+ break;
+ }
+
+ switch (raw_features & FEATURE_RAM_MASK) {
+ case FEATURE_RAM_DDR2_32BIT_295MBPS:
+ features->ram_config = RAM_DDR2_32BIT_295MBPS;
+ break;
+
+ case FEATURE_RAM_DDR3_32BIT_590MBPS:
+ features->ram_config = RAM_DDR3_32BIT_590MBPS;
+ break;
+
+ case FEATURE_RAM_DDR3_48BIT_590MBPS:
+ features->ram_config = RAM_DDR3_48BIT_590MBPS;
+ break;
+
+ case FEATURE_RAM_DDR3_64BIT_1800MBPS:
+ features->ram_config = RAM_DDR3_64BIT_1800MBPS;
+ break;
+
+ case FEATURE_RAM_DDR3_48BIT_1800MBPS:
+ features->ram_config = RAM_DDR3_48BIT_1800MBPS;
+ break;
+ }
+
+ features->pcm_tx = raw_features & FEATURE_PCM_TX;
+ features->pcm_rx = raw_features & FEATURE_PCM_RX;
+ features->spdif_tx = raw_features & FEATURE_SPDIF_TX;
+ features->spdif_rx = raw_features & FEATURE_SPDIF_RX;
+ features->usb2 = raw_features & FEATURE_USB2;
+ features->rs232 = raw_extended_features & EXT_FEATURE_RS232;
+ features->compression_type1 = raw_extended_features & EXT_FEATURE_COMPRESSION_TYPE1;
+ features->compression_type2 = raw_extended_features & EXT_FEATURE_COMPRESSION_TYPE2;
+ features->compression_type3 = raw_extended_features & EXT_FEATURE_COMPRESSION_TYPE3;
+ features->interlace = raw_extended_features & EXT_FEATURE_INTERLACE;
+ features->osd = raw_extended_features & EXT_FEATURE_OSD;
+ features->compression_pipes = raw_extended_features & EXT_FEATURE_COMPRESSION_PERF_MASK;
+
+ return 0;
+}
+
+#else
+
+static int get_versions(unsigned int fpga, struct fpga_versions *versions)
+{
+ enum {
+ /* HW version encoding is a mess, leave it for the moment */
+ VERSIONS_HW_VER_MASK = 0xf << 0,
+ VERSIONS_PIX_CLOCK_GEN_IDT8N3QV01 = BIT(4),
+ VERSIONS_SFP = BIT(5),
+ VERSIONS_VIDEO_MASK = 0x7 << 6,
+ VERSIONS_VIDEO_DVI = 0x0 << 6,
+ VERSIONS_VIDEO_DP_165 = 0x1 << 6,
+ VERSIONS_VIDEO_DP_300 = 0x2 << 6,
+ VERSIONS_VIDEO_HDMI = 0x3 << 6,
+ VERSIONS_UT_MASK = 0xf << 12,
+ VERSIONS_UT_MAIN_SERVER = 0x0 << 12,
+ VERSIONS_UT_MAIN_USER = 0x1 << 12,
+ VERSIONS_UT_VIDEO_SERVER = 0x2 << 12,
+ VERSIONS_UT_VIDEO_USER = 0x3 << 12,
+ };
+ u16 raw_versions;
+
+ memset(versions, 0, sizeof(struct fpga_versions));
+
+ FPGA_GET_REG(fpga, versions, &raw_versions);
+
+ switch (raw_versions & VERSIONS_UT_MASK) {
+ case VERSIONS_UT_MAIN_SERVER:
+ versions->video_channel = false;
+ versions->con_side = false;
+ break;
+
+ case VERSIONS_UT_MAIN_USER:
+ versions->video_channel = false;
+ versions->con_side = true;
+ break;
+
+ case VERSIONS_UT_VIDEO_SERVER:
+ versions->video_channel = true;
+ versions->con_side = false;
+ break;
+
+ case VERSIONS_UT_VIDEO_USER:
+ versions->video_channel = true;
+ versions->con_side = true;
+ break;
+
+ }
+
+ switch (raw_versions & VERSIONS_VIDEO_MASK) {
+ case VERSIONS_VIDEO_DVI:
+ versions->pcb_video_type = PCB_DVI_SL;
+ break;
+
+ case VERSIONS_VIDEO_DP_165:
+ versions->pcb_video_type = PCB_DP_165MPIX;
+ break;
+
+ case VERSIONS_VIDEO_DP_300:
+ versions->pcb_video_type = PCB_DP_300MPIX;
+ break;
+
+ case VERSIONS_VIDEO_HDMI:
+ versions->pcb_video_type = PCB_HDMI;
+ break;
+ }
+
+ versions->hw_version = raw_versions & VERSIONS_HW_VER_MASK;
+
+ if (raw_versions & VERSIONS_SFP)
+ versions->pcb_transmission_type = PCB_FIBER_3G;
+ else
+ versions->pcb_transmission_type = PCB_CAT_1G;
+
+ return 0;
+}
+
+static int get_features(unsigned int fpga, struct fpga_features *features)
+{
+ enum {
+ FEATURE_CARRIER_SPEED_2_5 = BIT(4),
+ FEATURE_RAM_MASK = 0x7 << 5,
+ FEATURE_RAM_DDR2_32BIT = 0x0 << 5,
+ FEATURE_RAM_DDR3_32BIT = 0x1 << 5,
+ FEATURE_RAM_DDR3_48BIT = 0x2 << 5,
+ FEATURE_PCM_AUDIO_TX = BIT(9),
+ FEATURE_PCM_AUDIO_RX = BIT(10),
+ FEATURE_OSD = BIT(11),
+ FEATURE_USB20 = BIT(12),
+ FEATURE_COMPRESSION_MASK = 7 << 13,
+ FEATURE_COMPRESSION_TYPE1 = 0x1 << 13,
+ FEATURE_COMPRESSION_TYPE1_TYPE2 = 0x3 << 13,
+ FEATURE_COMPRESSION_TYPE1_TYPE2_TYPE3 = 0x7 << 13,
+ };
+
+ enum {
+ EXTENDED_FEATURE_SPDIF_AUDIO_TX = BIT(0),
+ EXTENDED_FEATURE_SPDIF_AUDIO_RX = BIT(1),
+ EXTENDED_FEATURE_RS232 = BIT(2),
+ EXTENDED_FEATURE_COMPRESSION_PIPES = BIT(3),
+ EXTENDED_FEATURE_INTERLACE = BIT(4),
+ };
+
+ u16 raw_features;
+#ifdef GDSYS_LEGACY_DRIVERS
+ u16 raw_extended_features;
+#endif
+
+ memset(features, 0, sizeof(struct fpga_features));
+
+ FPGA_GET_REG(fpga, fpga_features, &raw_features);
+#ifdef GDSYS_LEGACY_DRIVERS
+ FPGA_GET_REG(fpga, fpga_ext_features, &raw_extended_features);
+#endif
+
+ features->video_channels = raw_features & 0x3;
+ features->carriers = (raw_features >> 2) & 0x3;
+
+ features->carrier_speed = (raw_features & FEATURE_CARRIER_SPEED_2_5)
+ ? CARRIER_SPEED_2_5G : CARRIER_SPEED_1G;
+
+ switch (raw_features & FEATURE_RAM_MASK) {
+ case FEATURE_RAM_DDR2_32BIT:
+ features->ram_config = RAM_DDR2_32BIT_295MBPS;
+ break;
+
+ case FEATURE_RAM_DDR3_32BIT:
+ features->ram_config = RAM_DDR3_32BIT_590MBPS;
+ break;
+
+ case FEATURE_RAM_DDR3_48BIT:
+ features->ram_config = RAM_DDR3_48BIT_590MBPS;
+ break;
+ }
+
+ features->pcm_tx = raw_features & FEATURE_PCM_AUDIO_TX;
+ features->pcm_rx = raw_features & FEATURE_PCM_AUDIO_RX;
+#ifdef GDSYS_LEGACY_DRIVERS
+ features->spdif_tx = raw_extended_features & EXTENDED_FEATURE_SPDIF_AUDIO_TX;
+ features->spdif_rx = raw_extended_features & EXTENDED_FEATURE_SPDIF_AUDIO_RX;
+#endif
+
+ features->usb2 = raw_features & FEATURE_USB20;
+#ifdef GDSYS_LEGACY_DRIVERS
+ features->rs232 = raw_extended_features & EXTENDED_FEATURE_RS232;
+#endif
+
+ features->compression_type1 = false;
+ features->compression_type2 = false;
+ features->compression_type3 = false;
+ switch (raw_features & FEATURE_COMPRESSION_MASK) {
+ case FEATURE_COMPRESSION_TYPE1_TYPE2_TYPE3:
+ features->compression_type3 = true;
+ case FEATURE_COMPRESSION_TYPE1_TYPE2:
+ features->compression_type2 = true;
+ case FEATURE_COMPRESSION_TYPE1:
+ features->compression_type1 = true;
+ break;
+ }
+
+#ifdef GDSYS_LEGACY_DRIVERS
+ features->interlace = raw_extended_features & EXTENDED_FEATURE_INTERLACE;
+#endif
+ features->osd = raw_features & FEATURE_OSD;
+#ifdef GDSYS_LEGACY_DRIVERS
+ features->compression_pipes = raw_extended_features & EXTENDED_FEATURE_COMPRESSION_PIPES;
+#endif
+
+ return 0;
+}
+
+#include <linux/bitops.h>
+#endif
+
+bool ioep_fpga_has_osd(unsigned int fpga)
+{
+ struct fpga_features features;
+
+ get_features(fpga, &features);
+
+ return features.osd;
+}
+
+void ioep_fpga_print_info(unsigned int fpga)
+{
+ u16 fpga_version;
+ struct fpga_versions versions;
+ struct fpga_features features;
+
+ FPGA_GET_REG(fpga, fpga_version, &fpga_version);
+ get_versions(fpga, &versions);
+ get_features(fpga, &features);
+
+ if (versions.video_channel)
+ printf("Videochannel");
+ else
+ printf("Mainchannel");
+
+ if (versions.con_side)
+ printf(" User");
+ else
+ printf(" Server");
+
+// FIXME
+#if 0
+ if (versions & (1<<4))
+ printf(" UC");
+#endif
+
+ switch(versions.pcb_transmission_type) {
+ case PCB_CAT_1G:
+ case PCB_CAT_10G:
+ printf(" CAT");
+ break;
+ case PCB_FIBER_3G:
+ case PCB_FIBER_10G:
+ printf(" Fiber");
+ break;
+ };
+
+ switch (versions.pcb_video_type) {
+ case PCB_DVI_SL:
+ printf(" DVI,");
+ break;
+ case PCB_DP_165MPIX:
+ printf(" DP 165MPix/s,");
+ break;
+ case PCB_DP_300MPIX:
+ printf(" DP 300MPix/s,");
+ break;
+ case PCB_HDMI:
+ printf(" HDMI,");
+ break;
+ case PCB_DP_1_2:
+ printf(" DP 1.2,");
+ break;
+ case PCB_HDMI_2_0:
+ printf(" HDMI 2.0,");
+ break;
+ }
+
+ printf(" FPGA V %d.%02d\n features: ",
+ fpga_version / 100, fpga_version % 100);
+
+ if (!features.compression_type1 &&
+ !features.compression_type2 &&
+ !features.compression_type3)
+ printf("no compression, ");
+
+ if (features.compression_type1)
+ printf("type1, ");
+
+ if (features.compression_type2)
+ printf("type2, ");
+
+ if (features.compression_type3)
+ printf("type3, ");
+
+ printf("%sosd", features.osd ? "" : "no ");
+
+ if (features.pcm_rx && features.pcm_tx)
+ printf(", pcm rx+tx");
+ else if(features.pcm_rx)
+ printf(", pcm rx");
+ else if(features.pcm_tx)
+ printf(", pcm tx");
+
+ if (features.spdif_rx && features.spdif_tx)
+ printf(", spdif rx+tx");
+ else if(features.spdif_rx)
+ printf(", spdif rx");
+ else if(features.spdif_tx)
+ printf(", spdif tx");
+
+ puts(",\n ");
+
+ switch (features.sysclock) {
+ case SYSCLK_147456:
+ printf("clock 147.456 MHz");
+ break;
+ }
+
+ switch (features.ram_config) {
+ case RAM_DDR2_32BIT_295MBPS:
+ printf(", RAM 32 bit DDR2");
+ break;
+ case RAM_DDR3_32BIT_590MBPS:
+ printf(", RAM 32 bit DDR3");
+ break;
+ case RAM_DDR3_48BIT_590MBPS:
+ case RAM_DDR3_48BIT_1800MBPS:
+ printf(", RAM 48 bit DDR3");
+ break;
+ case RAM_DDR3_64BIT_1800MBPS:
+ printf(", RAM 64 bit DDR3");
+ break;
+ }
+
+ printf(", %d carrier(s)", features.carriers);
+
+ switch(features.carrier_speed) {
+ case CARRIER_SPEED_1G:
+ printf(", 1Gbit/s");
+ break;
+ case CARRIER_SPEED_3G:
+ printf(", 3Gbit/s");
+ break;
+ case CARRIER_SPEED_10G:
+ printf(", 10Gbit/s");
+ break;
+ }
+
+ printf(", %d video channel(s)\n", features.video_channels);
+}
+
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
diff --git a/roms/u-boot/board/gdsys/common/ioep-fpga.h b/roms/u-boot/board/gdsys/common/ioep-fpga.h
new file mode 100644
index 000000000..53570b936
--- /dev/null
+++ b/roms/u-boot/board/gdsys/common/ioep-fpga.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2014
+ * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
+ */
+
+#ifndef _IOEP_FPGA_H_
+#define _IOEP_FPGA_H_
+
+void ioep_fpga_print_info(unsigned int fpga);
+bool ioep_fpga_has_osd(unsigned int fpga);
+
+#endif
diff --git a/roms/u-boot/board/gdsys/common/osd.c b/roms/u-boot/board/gdsys/common/osd.c
new file mode 100644
index 000000000..679f8f301
--- /dev/null
+++ b/roms/u-boot/board/gdsys/common/osd.c
@@ -0,0 +1,506 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2010
+ * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
+ */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+
+#include <common.h>
+#include <command.h>
+#include <i2c.h>
+#include <malloc.h>
+#include <linux/stringify.h>
+
+#include "ch7301.h"
+#include "dp501.h"
+#include <gdsys_fpga.h>
+
+#define ICS8N3QV01_I2C_ADDR 0x6E
+#define ICS8N3QV01_FREF 114285000
+#define ICS8N3QV01_FREF_LL 114285000LL
+#define ICS8N3QV01_F_DEFAULT_0 156250000LL
+#define ICS8N3QV01_F_DEFAULT_1 125000000LL
+#define ICS8N3QV01_F_DEFAULT_2 100000000LL
+#define ICS8N3QV01_F_DEFAULT_3 25175000LL
+
+#define SIL1178_MASTER_I2C_ADDRESS 0x38
+#define SIL1178_SLAVE_I2C_ADDRESS 0x39
+
+#define PIXCLK_640_480_60 25180000
+#define MAX_X_CHARS 53
+#define MAX_Y_CHARS 26
+
+#ifdef CONFIG_SYS_OSD_DH
+#define MAX_OSD_SCREEN 8
+#define OSD_DH_BASE 4
+#else
+#define MAX_OSD_SCREEN 4
+#endif
+
+#ifdef CONFIG_SYS_OSD_DH
+#define OSD_SET_REG(screen, fld, val) \
+ do { \
+ if (screen >= OSD_DH_BASE) \
+ FPGA_SET_REG(screen - OSD_DH_BASE, osd1.fld, val); \
+ else \
+ FPGA_SET_REG(screen, osd0.fld, val); \
+ } while (0)
+#else
+#define OSD_SET_REG(screen, fld, val) \
+ FPGA_SET_REG(screen, osd0.fld, val)
+#endif
+
+#ifdef CONFIG_SYS_OSD_DH
+#define OSD_GET_REG(screen, fld, val) \
+ do { \
+ if (screen >= OSD_DH_BASE) \
+ FPGA_GET_REG(screen - OSD_DH_BASE, osd1.fld, val); \
+ else \
+ FPGA_GET_REG(screen, osd0.fld, val); \
+ } while (0)
+#else
+#define OSD_GET_REG(screen, fld, val) \
+ FPGA_GET_REG(screen, osd0.fld, val)
+#endif
+
+unsigned int base_width;
+unsigned int base_height;
+size_t bufsize;
+u16 *buf;
+
+unsigned int osd_screen_mask = 0;
+
+#ifdef CONFIG_SYS_ICS8N3QV01_I2C
+int ics8n3qv01_i2c[] = CONFIG_SYS_ICS8N3QV01_I2C;
+#endif
+
+#ifdef CONFIG_SYS_SIL1178_I2C
+int sil1178_i2c[] = CONFIG_SYS_SIL1178_I2C;
+#endif
+
+#ifdef CONFIG_SYS_MPC92469AC
+static void mpc92469ac_calc_parameters(unsigned int fout,
+ unsigned int *post_div, unsigned int *feedback_div)
+{
+ unsigned int n = *post_div;
+ unsigned int m = *feedback_div;
+ unsigned int a;
+ unsigned int b = 14745600 / 16;
+
+ if (fout < 50169600)
+ n = 8;
+ else if (fout < 100339199)
+ n = 4;
+ else if (fout < 200678399)
+ n = 2;
+ else
+ n = 1;
+
+ a = fout * n + (b / 2); /* add b/2 for proper rounding */
+
+ m = a / b;
+
+ *post_div = n;
+ *feedback_div = m;
+}
+
+static void mpc92469ac_set(unsigned screen, unsigned int fout)
+{
+ unsigned int n;
+ unsigned int m;
+ unsigned int bitval = 0;
+ mpc92469ac_calc_parameters(fout, &n, &m);
+
+ switch (n) {
+ case 1:
+ bitval = 0x00;
+ break;
+ case 2:
+ bitval = 0x01;
+ break;
+ case 4:
+ bitval = 0x02;
+ break;
+ case 8:
+ bitval = 0x03;
+ break;
+ }
+
+ FPGA_SET_REG(screen, mpc3w_control, (bitval << 9) | m);
+}
+#endif
+
+#ifdef CONFIG_SYS_ICS8N3QV01_I2C
+
+static unsigned int ics8n3qv01_get_fout_calc(unsigned index)
+{
+ unsigned long long n;
+ unsigned long long mint;
+ unsigned long long mfrac;
+ u8 reg_a, reg_b, reg_c, reg_d, reg_f;
+ unsigned long long fout_calc;
+
+ if (index > 3)
+ return 0;
+
+ reg_a = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 0 + index);
+ reg_b = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 4 + index);
+ reg_c = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 8 + index);
+ reg_d = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 12 + index);
+ reg_f = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 20 + index);
+
+ mint = ((reg_a >> 1) & 0x1f) | (reg_f & 0x20);
+ mfrac = ((reg_a & 0x01) << 17) | (reg_b << 9) | (reg_c << 1)
+ | (reg_d >> 7);
+ n = reg_d & 0x7f;
+
+ fout_calc = (mint * ICS8N3QV01_FREF_LL
+ + mfrac * ICS8N3QV01_FREF_LL / 262144LL
+ + ICS8N3QV01_FREF_LL / 524288LL
+ + n / 2)
+ / n
+ * 1000000
+ / (1000000 - 100);
+
+ return fout_calc;
+}
+
+
+static void ics8n3qv01_calc_parameters(unsigned int fout,
+ unsigned int *_mint, unsigned int *_mfrac,
+ unsigned int *_n)
+{
+ unsigned int n;
+ unsigned int foutiic;
+ unsigned int fvcoiic;
+ unsigned int mint;
+ unsigned long long mfrac;
+
+ n = (2215000000U + fout / 2) / fout;
+ if ((n & 1) && (n > 5))
+ n -= 1;
+
+ foutiic = fout - (fout / 10000);
+ fvcoiic = foutiic * n;
+
+ mint = fvcoiic / 114285000;
+ if ((mint < 17) || (mint > 63))
+ printf("ics8n3qv01_calc_parameters: cannot determine mint\n");
+
+ mfrac = ((unsigned long long)fvcoiic % 114285000LL) * 262144LL
+ / 114285000LL;
+
+ *_mint = mint;
+ *_mfrac = mfrac;
+ *_n = n;
+}
+
+static void ics8n3qv01_set(unsigned int fout)
+{
+ unsigned int n;
+ unsigned int mint;
+ unsigned int mfrac;
+ unsigned int fout_calc;
+ unsigned long long fout_prog;
+ long long off_ppm;
+ u8 reg0, reg4, reg8, reg12, reg18, reg20;
+
+ fout_calc = ics8n3qv01_get_fout_calc(1);
+ off_ppm = (fout_calc - ICS8N3QV01_F_DEFAULT_1) * 1000000
+ / ICS8N3QV01_F_DEFAULT_1;
+ printf(" PLL is off by %lld ppm\n", off_ppm);
+ fout_prog = (unsigned long long)fout * (unsigned long long)fout_calc
+ / ICS8N3QV01_F_DEFAULT_1;
+ ics8n3qv01_calc_parameters(fout_prog, &mint, &mfrac, &n);
+
+ reg0 = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 0) & 0xc0;
+ reg0 |= (mint & 0x1f) << 1;
+ reg0 |= (mfrac >> 17) & 0x01;
+ i2c_reg_write(ICS8N3QV01_I2C_ADDR, 0, reg0);
+
+ reg4 = mfrac >> 9;
+ i2c_reg_write(ICS8N3QV01_I2C_ADDR, 4, reg4);
+
+ reg8 = mfrac >> 1;
+ i2c_reg_write(ICS8N3QV01_I2C_ADDR, 8, reg8);
+
+ reg12 = mfrac << 7;
+ reg12 |= n & 0x7f;
+ i2c_reg_write(ICS8N3QV01_I2C_ADDR, 12, reg12);
+
+ reg18 = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 18) & 0x03;
+ reg18 |= 0x20;
+ i2c_reg_write(ICS8N3QV01_I2C_ADDR, 18, reg18);
+
+ reg20 = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 20) & 0x1f;
+ reg20 |= mint & (1 << 5);
+ i2c_reg_write(ICS8N3QV01_I2C_ADDR, 20, reg20);
+}
+#endif
+
+static int osd_write_videomem(unsigned screen, unsigned offset,
+ u16 *data, size_t charcount)
+{
+ unsigned int k;
+
+ for (k = 0; k < charcount; ++k) {
+ if (offset + k >= bufsize)
+ return -1;
+#ifdef CONFIG_SYS_OSD_DH
+ if (screen >= OSD_DH_BASE)
+ FPGA_SET_REG(screen - OSD_DH_BASE,
+ videomem1[offset + k], data[k]);
+ else
+ FPGA_SET_REG(screen, videomem0[offset + k], data[k]);
+#else
+ FPGA_SET_REG(screen, videomem0[offset + k], data[k]);
+#endif
+ }
+
+ return charcount;
+}
+
+static int osd_print(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ unsigned screen;
+
+ if (argc < 5) {
+ cmd_usage(cmdtp);
+ return 1;
+ }
+
+ for (screen = 0; screen < MAX_OSD_SCREEN; ++screen) {
+ unsigned x;
+ unsigned y;
+ unsigned charcount;
+ unsigned len;
+ u8 color;
+ unsigned int k;
+ char *text;
+ int res;
+
+ if (!(osd_screen_mask & (1 << screen)))
+ continue;
+
+ x = simple_strtoul(argv[1], NULL, 16);
+ y = simple_strtoul(argv[2], NULL, 16);
+ color = simple_strtoul(argv[3], NULL, 16);
+ text = argv[4];
+ charcount = strlen(text);
+ len = (charcount > bufsize) ? bufsize : charcount;
+
+ for (k = 0; k < len; ++k)
+ buf[k] = (text[k] << 8) | color;
+
+ res = osd_write_videomem(screen, y * base_width + x, buf, len);
+ if (res < 0)
+ return res;
+
+ OSD_SET_REG(screen, control, 0x0049);
+ }
+
+ return 0;
+}
+
+int osd_probe(unsigned screen)
+{
+ u16 version;
+ u16 features;
+ int old_bus = i2c_get_bus_num();
+ bool pixclock_present = false;
+ bool output_driver_present = false;
+
+ OSD_GET_REG(0, version, &version);
+ OSD_GET_REG(0, features, &features);
+
+ base_width = ((features & 0x3f00) >> 8) + 1;
+ base_height = (features & 0x001f) + 1;
+ bufsize = base_width * base_height;
+ buf = malloc(sizeof(u16) * bufsize);
+ if (!buf)
+ return -1;
+
+#ifdef CONFIG_SYS_OSD_DH
+ printf("OSD%d-%d: Digital-OSD version %01d.%02d, %d" "x%d characters\n",
+ (screen >= OSD_DH_BASE) ? (screen - OSD_DH_BASE) : screen,
+ (screen > 3) ? 1 : 0, version/100, version%100, base_width,
+ base_height);
+#else
+ printf("OSD%d: Digital-OSD version %01d.%02d, %d" "x%d characters\n",
+ screen, version/100, version%100, base_width, base_height);
+#endif
+ /* setup pixclock */
+
+#ifdef CONFIG_SYS_MPC92469AC
+ pixclock_present = true;
+ mpc92469ac_set(screen, PIXCLK_640_480_60);
+#endif
+
+#ifdef CONFIG_SYS_ICS8N3QV01_I2C
+ i2c_set_bus_num(ics8n3qv01_i2c[screen]);
+ if (!i2c_probe(ICS8N3QV01_I2C_ADDR)) {
+ ics8n3qv01_set(PIXCLK_640_480_60);
+ pixclock_present = true;
+ }
+#endif
+
+ if (!pixclock_present)
+ printf(" no pixelclock found\n");
+
+ /* setup output driver */
+
+#ifdef CONFIG_SYS_CH7301_I2C
+ if (!ch7301_probe(screen, true))
+ output_driver_present = true;
+#endif
+
+#ifdef CONFIG_SYS_SIL1178_I2C
+ i2c_set_bus_num(sil1178_i2c[screen]);
+ if (!i2c_probe(SIL1178_SLAVE_I2C_ADDRESS)) {
+ if (i2c_reg_read(SIL1178_SLAVE_I2C_ADDRESS, 0x02) == 0x06) {
+ /*
+ * magic initialization sequence,
+ * adapted from datasheet
+ */
+ i2c_reg_write(SIL1178_SLAVE_I2C_ADDRESS, 0x08, 0x36);
+ i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0f, 0x44);
+ i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0f, 0x4c);
+ i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0e, 0x10);
+ i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0a, 0x80);
+ i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x09, 0x30);
+ i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0c, 0x89);
+ i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0d, 0x60);
+ i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x08, 0x36);
+ i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x08, 0x37);
+ output_driver_present = true;
+ }
+ }
+#endif
+
+#ifdef CONFIG_SYS_DP501_I2C
+ if (!dp501_probe(screen, true))
+ output_driver_present = true;
+#endif
+
+ if (!output_driver_present)
+ printf(" no output driver found\n");
+
+ OSD_SET_REG(screen, xy_size, ((32 - 1) << 8) | (16 - 1));
+ OSD_SET_REG(screen, x_pos, 0x007f);
+ OSD_SET_REG(screen, y_pos, 0x005f);
+
+ if (pixclock_present && output_driver_present)
+ osd_screen_mask |= 1 << screen;
+
+ i2c_set_bus_num(old_bus);
+
+ return 0;
+}
+
+int osd_write(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ unsigned screen;
+
+ if ((argc < 4) || (strlen(argv[3]) % 4)) {
+ cmd_usage(cmdtp);
+ return 1;
+ }
+
+ for (screen = 0; screen < MAX_OSD_SCREEN; ++screen) {
+ unsigned x;
+ unsigned y;
+ unsigned k;
+ u16 buffer[base_width];
+ char *rp;
+ u16 *wp = buffer;
+ unsigned count = (argc > 4) ?
+ simple_strtoul(argv[4], NULL, 16) : 1;
+
+ if (!(osd_screen_mask & (1 << screen)))
+ continue;
+
+ x = simple_strtoul(argv[1], NULL, 16);
+ y = simple_strtoul(argv[2], NULL, 16);
+ rp = argv[3];
+
+
+ while (*rp) {
+ char substr[5];
+
+ memcpy(substr, rp, 4);
+ substr[4] = 0;
+ *wp = simple_strtoul(substr, NULL, 16);
+
+ rp += 4;
+ wp++;
+ if (wp - buffer > base_width)
+ break;
+ }
+
+ for (k = 0; k < count; ++k) {
+ unsigned offset =
+ y * base_width + x + k * (wp - buffer);
+ osd_write_videomem(screen, offset, buffer,
+ wp - buffer);
+ }
+
+ OSD_SET_REG(screen, control, 0x0049);
+ }
+
+ return 0;
+}
+
+int osd_size(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ unsigned screen;
+ unsigned x;
+ unsigned y;
+
+ if (argc < 3) {
+ cmd_usage(cmdtp);
+ return 1;
+ }
+
+ x = simple_strtoul(argv[1], NULL, 16);
+ y = simple_strtoul(argv[2], NULL, 16);
+
+ if (!x || (x > 64) || (x > MAX_X_CHARS) ||
+ !y || (y > 32) || (y > MAX_Y_CHARS)) {
+ cmd_usage(cmdtp);
+ return 1;
+ }
+
+ for (screen = 0; screen < MAX_OSD_SCREEN; ++screen) {
+ if (!(osd_screen_mask & (1 << screen)))
+ continue;
+
+ OSD_SET_REG(screen, xy_size, ((x - 1) << 8) | (y - 1));
+ OSD_SET_REG(screen, x_pos, 32767 * (640 - 12 * x) / 65535);
+ OSD_SET_REG(screen, y_pos, 32767 * (480 - 18 * y) / 65535);
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ osdw, 5, 0, osd_write,
+ "write 16-bit hex encoded buffer to osd memory",
+ "pos_x pos_y buffer count\n"
+);
+
+U_BOOT_CMD(
+ osdp, 5, 0, osd_print,
+ "write ASCII buffer to osd memory",
+ "pos_x pos_y color text\n"
+);
+
+U_BOOT_CMD(
+ osdsize, 3, 0, osd_size,
+ "set OSD XY size in characters",
+ "size_x(max. " __stringify(MAX_X_CHARS)
+ ") size_y(max. " __stringify(MAX_Y_CHARS) ")\n"
+);
+
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
diff --git a/roms/u-boot/board/gdsys/common/osd.h b/roms/u-boot/board/gdsys/common/osd.h
new file mode 100644
index 000000000..4e8e53ab4
--- /dev/null
+++ b/roms/u-boot/board/gdsys/common/osd.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2010
+ * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
+ */
+
+#ifndef _OSD_H_
+#define _OSD_H_
+
+int ch7301_probe(unsigned screen, bool power);
+int osd_probe(unsigned screen);
+
+#endif
diff --git a/roms/u-boot/board/gdsys/common/osd_cmd.c b/roms/u-boot/board/gdsys/common/osd_cmd.c
new file mode 100644
index 000000000..fe6249794
--- /dev/null
+++ b/roms/u-boot/board/gdsys/common/osd_cmd.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2017
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ *
+ * based on the gdsys osd driver, which is
+ *
+ * (C) Copyright 2010
+ * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <hexdump.h>
+#include <video_osd.h>
+#include <malloc.h>
+
+static int do_osd_write(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ uint x, y;
+ uint count;
+ char *hexstr;
+ u8 *buffer;
+ size_t buflen;
+ int res;
+
+ if (argc < 4 || (strlen(argv[3])) % 2)
+ return CMD_RET_USAGE;
+
+ x = simple_strtoul(argv[1], NULL, 16);
+ y = simple_strtoul(argv[2], NULL, 16);
+ hexstr = argv[3];
+ count = (argc > 4) ? simple_strtoul(argv[4], NULL, 16) : 1;
+
+ buflen = strlen(hexstr) / 2;
+
+ buffer = malloc(buflen);
+ if (!buffer) {
+ puts("Memory allocation failure\n");
+ return CMD_RET_FAILURE;
+ }
+
+ res = hex2bin(buffer, hexstr, buflen);
+ if (res) {
+ free(buffer);
+ puts("Hexadecimal input contained invalid characters\n");
+ return CMD_RET_FAILURE;
+ }
+
+ for (uclass_first_device(UCLASS_VIDEO_OSD, &dev);
+ dev;
+ uclass_next_device(&dev)) {
+ int res;
+
+ res = video_osd_set_mem(dev, x, y, buffer, buflen, count);
+ if (res) {
+ free(buffer);
+ printf("Could not write to video mem on osd %s\n",
+ dev->name);
+ return CMD_RET_FAILURE;
+ }
+ }
+
+ free(buffer);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_osd_print(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ uint x, y;
+ u8 color;
+ char *text;
+
+ if (argc < 5)
+ return CMD_RET_USAGE;
+
+ x = simple_strtoul(argv[1], NULL, 16);
+ y = simple_strtoul(argv[2], NULL, 16);
+ color = simple_strtoul(argv[3], NULL, 16);
+ text = argv[4];
+
+ for (uclass_first_device(UCLASS_VIDEO_OSD, &dev);
+ dev;
+ uclass_next_device(&dev)) {
+ int res;
+
+ res = video_osd_print(dev, x, y, color, text);
+ if (res) {
+ printf("Could not print string to osd %s\n", dev->name);
+ return CMD_RET_FAILURE;
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_osd_size(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ uint x, y;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ x = simple_strtoul(argv[1], NULL, 16);
+ y = simple_strtoul(argv[2], NULL, 16);
+
+ for (uclass_first_device(UCLASS_VIDEO_OSD, &dev);
+ dev;
+ uclass_next_device(&dev)) {
+ int res;
+
+ res = video_osd_set_size(dev, x, y);
+
+ if (res) {
+ printf("Could not set size on osd %s\n", dev->name);
+ return CMD_RET_FAILURE;
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+ osdw, 5, 0, do_osd_write,
+ "write 16-bit hex encoded buffer to osd memory",
+ "osdw [pos_x] [pos_y] [buffer] [count] - write 8-bit hex encoded buffer to osd memory\n"
+);
+
+U_BOOT_CMD(
+ osdp, 5, 0, do_osd_print,
+ "write ASCII buffer to osd memory",
+ "osdp [pos_x] [pos_y] [color] [text] - write ASCII buffer to osd memory\n"
+);
+
+U_BOOT_CMD(
+ osdsize, 3, 0, do_osd_size,
+ "set OSD XY size in characters",
+ "osdsize [size_x] [size_y] - set OSD XY size in characters\n"
+);
diff --git a/roms/u-boot/board/gdsys/mpc8308/Kconfig b/roms/u-boot/board/gdsys/mpc8308/Kconfig
new file mode 100644
index 000000000..c3fd0518b
--- /dev/null
+++ b/roms/u-boot/board/gdsys/mpc8308/Kconfig
@@ -0,0 +1,83 @@
+if TARGET_GAZERBEAM
+
+config GDSYS_LEGACY_OSD_CMDS
+ bool
+ help
+ Use the 'osdw', 'osdp', and 'osdsize' legacy commands required by
+ gdsys devices.
+
+config GDSYS_LEGACY_DRIVERS
+ bool
+ help
+ Enable the gdsys legacy drivers under board/gdsys/common. If this
+ option is not set, all relevant DM drivers must be configured for the
+ device in question.
+
+config SYS_FPGA0_BASE
+ hex
+ default E0600000
+ help
+ The base address of the first FPGA's register map.
+
+config SYS_FPGA0_SIZE
+ hex
+ default 1
+ help
+ The base address of the first FPGA's register map.
+
+config SYS_FPGA1_BASE
+ hex
+ help
+ The base address of the second FPGA's register map.
+
+config SYS_FPGA1_SIZE
+ hex
+ help
+ The base address of the second FPGA's register map.
+
+config SYS_BOARD
+ default "mpc8308"
+
+config SYS_VENDOR
+ default "gdsys"
+
+config SYS_CONFIG_NAME
+ default "gazerbeam"
+
+config SYS_FPGA1_BASE
+ default E0700000
+
+config SYS_FPGA1_SIZE
+ default 1
+
+config GDSYS_LEGACY_OSD_CMDS
+ default y
+
+choice
+ prompt "FPGA flavor selection"
+
+config SYS_FPGA_FLAVOR_LEGACY
+ bool "Legacy flavor"
+ help
+ This enables support for the gdsys pre-Gazerbeam FPGA memory layout.
+
+config SYS_FPGA_FLAVOR_GAZERBEAM
+ bool "Gazerbeam flavor"
+ help
+ This enables support for the gdsys FPGA memory layout of the
+ Gazerbeam board.
+
+endchoice
+
+config EXTENDED_FEATURES
+ bool "FPGA extended features"
+ depends on GDSYS_LEGACY_DRIVERS
+ help
+ Enable support for the extended features field of the IHS FPGA.
+
+config CMD_IOLOOP
+ bool "Enable 'ioloop' and 'ioreflect' commands"
+ help
+ These commands provide FPGA tests.
+
+endif
diff --git a/roms/u-boot/board/gdsys/mpc8308/MAINTAINERS b/roms/u-boot/board/gdsys/mpc8308/MAINTAINERS
new file mode 100644
index 000000000..dc0b389f7
--- /dev/null
+++ b/roms/u-boot/board/gdsys/mpc8308/MAINTAINERS
@@ -0,0 +1,6 @@
+MPC8308 BOARD
+M: Dirk Eibach <dirk.eibach@gdsys.cc>
+S: Maintained
+F: board/gdsys/mpc8308/
+F: include/configs/gazerbeam.h
+F: configs/gazerbeam_defconfig
diff --git a/roms/u-boot/board/gdsys/mpc8308/Makefile b/roms/u-boot/board/gdsys/mpc8308/Makefile
new file mode 100644
index 000000000..f86d997bc
--- /dev/null
+++ b/roms/u-boot/board/gdsys/mpc8308/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2014
+# Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
+
+obj-y := mpc8308.o sdram.o
+obj-$(CONFIG_TARGET_GAZERBEAM) += gazerbeam.o
diff --git a/roms/u-boot/board/gdsys/mpc8308/gazerbeam.c b/roms/u-boot/board/gdsys/mpc8308/gazerbeam.c
new file mode 100644
index 000000000..3d4a7e57f
--- /dev/null
+++ b/roms/u-boot/board/gdsys/mpc8308/gazerbeam.c
@@ -0,0 +1,186 @@
+/*
+ * (C) Copyright 2015
+ * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <env.h>
+#include <fdt_support.h>
+#include <fsl_esdhc.h>
+#include <init.h>
+#include <miiphy.h>
+#include <misc.h>
+#include <sysinfo.h>
+#include <tpm-v1.h>
+#include <video_osd.h>
+#include <asm/global_data.h>
+
+#include "../common/ihs_mdio.h"
+#include "../../../drivers/sysinfo/gazerbeam.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ihs_mdio_info ihs_mdio_info[] = {
+ { .fpga = NULL, .name = "ihs0", .base = 0x58 },
+ { .fpga = NULL, .name = "ihs1", .base = 0x58 },
+};
+
+static int get_tpm(struct udevice **devp)
+{
+ int rc;
+
+ rc = uclass_first_device_err(UCLASS_TPM, devp);
+ if (rc) {
+ printf("Could not find TPM (ret=%d)\n", rc);
+ return CMD_RET_FAILURE;
+ }
+
+ return 0;
+}
+
+int board_early_init_r(void)
+{
+ struct udevice *sysinfo;
+ struct udevice *serdes;
+ int mc = 0;
+ int con = 0;
+
+ if (sysinfo_get(&sysinfo))
+ puts("Could not find sysinfo information device.\n");
+
+ /* Initialize serdes */
+ uclass_get_device_by_phandle(UCLASS_MISC, sysinfo, "serdes", &serdes);
+
+ if (sysinfo_detect(sysinfo))
+ puts("Device information detection failed.\n");
+
+ sysinfo_get_int(sysinfo, BOARD_MULTICHANNEL, &mc);
+ sysinfo_get_int(sysinfo, BOARD_VARIANT, &con);
+
+ if (mc == 2 || mc == 1)
+ dev_disable_by_path("/immr@e0000000/i2c@3100/pca9698@22");
+
+ if (mc == 4) {
+ dev_disable_by_path("/immr@e0000000/i2c@3100/pca9698@20");
+ dev_enable_by_path("/localbus@e0005000/iocon_uart@2,0");
+ dev_enable_by_path("/fpga1bus");
+ }
+
+ if (mc == 2 || con == VAR_CON) {
+ dev_enable_by_path("/fpga0bus/fpga0_video1");
+ dev_enable_by_path("/fpga0bus/fpga0_iic_video1");
+ dev_enable_by_path("/fpga0bus/fpga0_axi_video1");
+ }
+
+ if (con == VAR_CON) {
+ dev_enable_by_path("/fpga0bus/fpga0_video0");
+ dev_enable_by_path("/fpga0bus/fpga0_iic_video0");
+ dev_enable_by_path("/fpga0bus/fpga0_axi_video0");
+ }
+
+ return 0;
+}
+
+int checksysinfo(void)
+{
+ struct udevice *sysinfo;
+ char *s = env_get("serial#");
+ int mc = 0;
+ int con = 0;
+
+ if (sysinfo_get(&sysinfo))
+ puts("Could not find sysinfo information device.\n");
+
+ sysinfo_get_int(sysinfo, BOARD_MULTICHANNEL, &mc);
+ sysinfo_get_int(sysinfo, BOARD_VARIANT, &con);
+
+ puts("Board: Gazerbeam ");
+ printf("%s ", mc == 4 ? "MC4" : mc == 2 ? "MC2" : "SC");
+ printf("%s", con == VAR_CON ? "CON" : "CPU");
+
+ if (s) {
+ puts(", serial# ");
+ puts(s);
+ }
+
+ puts("\n");
+
+ return 0;
+}
+
+static void display_osd_info(struct udevice *osd,
+ struct video_osd_info *osd_info)
+{
+ printf("OSD-%s: Digital-OSD version %01d.%02d, %d x %d characters\n",
+ osd->name, osd_info->major_version, osd_info->minor_version,
+ osd_info->width, osd_info->height);
+}
+
+int last_stage_init(void)
+{
+ int fpga_hw_rev = 0;
+ int i;
+ struct udevice *sysinfo;
+ struct udevice *osd;
+ struct video_osd_info osd_info;
+ struct udevice *tpm;
+ int ret;
+
+ if (sysinfo_get(&sysinfo))
+ puts("Could not find sysinfo information device.\n");
+
+ if (sysinfo) {
+ int res = sysinfo_get_int(sysinfo, BOARD_HWVERSION,
+ &fpga_hw_rev);
+
+ if (res)
+ printf("Could not determind FPGA HW revision (res = %d)\n",
+ res);
+ }
+
+ env_set_ulong("fpga_hw_rev", fpga_hw_rev);
+
+ ret = get_tpm(&tpm);
+ if (ret || tpm_init(tpm) || tpm1_startup(tpm, TPM_ST_CLEAR) ||
+ tpm1_continue_self_test(tpm)) {
+ printf("TPM init failed\n");
+ }
+
+ if (fpga_hw_rev >= 4) {
+ for (i = 0; i < 4; i++) {
+ struct udevice *rxaui;
+ char name[8];
+
+ snprintf(name, sizeof(name), "rxaui%d", i);
+ /* Disable RXAUI polarity inversion */
+ ret = uclass_get_device_by_phandle(UCLASS_MISC, sysinfo,
+ name, &rxaui);
+ if (!ret)
+ misc_set_enabled(rxaui, false);
+ }
+ }
+
+ for (uclass_first_device(UCLASS_VIDEO_OSD, &osd);
+ osd;
+ uclass_next_device(&osd)) {
+ video_osd_get_info(osd, &osd_info);
+ display_osd_info(osd, &osd_info);
+ }
+
+ return 0;
+}
+
+#if defined(CONFIG_OF_BOARD_SETUP)
+int ft_board_setup(void *blob, struct bd_info *bd)
+{
+ ft_cpu_setup(blob, bd);
+ fsl_fdt_fixup_dr_usb(blob, bd);
+ fdt_fixup_esdhc(blob, bd);
+
+ return 0;
+}
+#endif
diff --git a/roms/u-boot/board/gdsys/mpc8308/mpc8308.c b/roms/u-boot/board/gdsys/mpc8308/mpc8308.c
new file mode 100644
index 000000000..0f90f8ad3
--- /dev/null
+++ b/roms/u-boot/board/gdsys/mpc8308/mpc8308.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014
+ * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
+ */
+
+#include <common.h>
+#include <command.h>
+#include <init.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/global_data.h>
+#include <linux/delay.h>
+
+#include "mpc8308.h"
+#include <gdsys_fpga.h>
+
+#define REFLECTION_TESTPATTERN 0xdede
+#define REFLECTION_TESTPATTERN_INV (~REFLECTION_TESTPATTERN & 0xffff)
+
+#ifdef CONFIG_SYS_FPGA_NO_RFL_HI
+#define REFLECTION_TESTREG reflection_low
+#else
+#define REFLECTION_TESTREG reflection_high
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+/* as gpio output status cannot be read back, we have to buffer it locally */
+u32 gpio0_out;
+
+void setbits_gpio0_out(u32 mask)
+{
+ immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+
+ gpio0_out |= mask;
+ out_be32(&immr->gpio[0].dat, gpio0_out);
+}
+
+void clrbits_gpio0_out(u32 mask)
+{
+ immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+
+ gpio0_out &= ~mask;
+ out_be32(&immr->gpio[0].dat, gpio0_out);
+}
+
+int get_fpga_state(uint dev)
+{
+ return gd->arch.fpga_state[dev];
+}
+
+int board_early_init_f(void)
+{
+ uint k;
+
+ for (k = 0; k < CONFIG_SYS_FPGA_COUNT; ++k)
+ gd->arch.fpga_state[k] = 0;
+
+ return 0;
+}
+
+int board_early_init_r(void)
+{
+ uint k;
+ uint ctr;
+
+ for (k = 0; k < CONFIG_SYS_FPGA_COUNT; ++k)
+ gd->arch.fpga_state[k] = 0;
+
+ /*
+ * reset FPGA
+ */
+ mpc8308_init();
+
+ mpc8308_set_fpga_reset(1);
+
+ mpc8308_setup_hw();
+
+ for (k = 0; k < CONFIG_SYS_FPGA_COUNT; ++k) {
+ ctr = 0;
+ while (!mpc8308_get_fpga_done(k)) {
+ mdelay(100);
+ if (ctr++ > 5) {
+ gd->arch.fpga_state[k] |=
+ FPGA_STATE_DONE_FAILED;
+ break;
+ }
+ }
+ }
+
+ udelay(10);
+
+ mpc8308_set_fpga_reset(0);
+
+ for (k = 0; k < CONFIG_SYS_FPGA_COUNT; ++k) {
+ /*
+ * wait for fpga out of reset
+ */
+ ctr = 0;
+ while (1) {
+ u16 val;
+
+ FPGA_SET_REG(k, reflection_low, REFLECTION_TESTPATTERN);
+
+ FPGA_GET_REG(k, REFLECTION_TESTREG, &val);
+ if (val == REFLECTION_TESTPATTERN_INV)
+ break;
+
+ mdelay(100);
+ if (ctr++ > 5) {
+ gd->arch.fpga_state[k] |=
+ FPGA_STATE_REFLECTION_FAILED;
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+#endif
diff --git a/roms/u-boot/board/gdsys/mpc8308/mpc8308.h b/roms/u-boot/board/gdsys/mpc8308/mpc8308.h
new file mode 100644
index 000000000..1e4f24fb2
--- /dev/null
+++ b/roms/u-boot/board/gdsys/mpc8308/mpc8308.h
@@ -0,0 +1,13 @@
+#ifndef __MPC8308_H_
+#define __MPC8308_H_
+
+void setbits_gpio0_out(u32 mask);
+void clrbits_gpio0_out(u32 mask);
+
+/* functions to be provided by board implementation */
+void mpc8308_init(void);
+void mpc8308_set_fpga_reset(unsigned state);
+void mpc8308_setup_hw(void);
+int mpc8308_get_fpga_done(unsigned fpga);
+
+#endif /* __MPC8308_H_ */
diff --git a/roms/u-boot/board/gdsys/mpc8308/sdram.c b/roms/u-boot/board/gdsys/mpc8308/sdram.c
new file mode 100644
index 000000000..bfd55f54e
--- /dev/null
+++ b/roms/u-boot/board/gdsys/mpc8308/sdram.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2007 Freescale Semiconductor, Inc.
+ * Copyright (C) 2010 Ilya Yanok, Emcraft Systems, yanok@emcraft.com
+ *
+ * Authors: Nick.Spence@freescale.com
+ * Wilson.Lo@freescale.com
+ * scottwood@freescale.com
+ *
+ * This files is mostly identical to the original from
+ * board\freescale\mpc8315erdb\sdram.c
+ */
+
+#ifndef CONFIG_MPC83XX_SDRAM
+
+#include <common.h>
+#include <init.h>
+#include <mpc83xx.h>
+#include <spd_sdram.h>
+
+#include <asm/bitops.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Fixed sdram init -- doesn't use serial presence detect.
+ *
+ * This is useful for faster booting in configs where the RAM is unlikely
+ * to be changed, or for things like NAND booting where space is tight.
+ */
+static long fixed_sdram(void)
+{
+ immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ u32 msize = CONFIG_SYS_DDR_SIZE * 1024 * 1024;
+ u32 msize_log2 = __ilog2(msize);
+
+ out_be32(&im->sysconf.ddrlaw[0].bar,
+ CONFIG_SYS_SDRAM_BASE & 0xfffff000);
+ out_be32(&im->sysconf.ddrlaw[0].ar, LBLAWAR_EN | (msize_log2 - 1));
+ out_be32(&im->sysconf.ddrcdr, CONFIG_SYS_DDRCDR_VALUE);
+
+ out_be32(&im->ddr.csbnds[0].csbnds, (msize - 1) >> 24);
+ out_be32(&im->ddr.cs_config[0], CONFIG_SYS_DDR_CS0_CONFIG);
+
+ /* Currently we use only one CS, so disable the other bank. */
+ out_be32(&im->ddr.cs_config[1], 0);
+
+ out_be32(&im->ddr.sdram_clk_cntl, CONFIG_SYS_DDR_SDRAM_CLK_CNTL);
+ out_be32(&im->ddr.timing_cfg_3, CONFIG_SYS_DDR_TIMING_3);
+ out_be32(&im->ddr.timing_cfg_1, CONFIG_SYS_DDR_TIMING_1);
+ out_be32(&im->ddr.timing_cfg_2, CONFIG_SYS_DDR_TIMING_2);
+ out_be32(&im->ddr.timing_cfg_0, CONFIG_SYS_DDR_TIMING_0);
+
+ out_be32(&im->ddr.sdram_cfg, CONFIG_SYS_DDR_SDRAM_CFG);
+ out_be32(&im->ddr.sdram_cfg2, CONFIG_SYS_DDR_SDRAM_CFG2);
+ out_be32(&im->ddr.sdram_mode, CONFIG_SYS_DDR_MODE);
+ out_be32(&im->ddr.sdram_mode2, CONFIG_SYS_DDR_MODE2);
+
+ out_be32(&im->ddr.sdram_interval, CONFIG_SYS_DDR_INTERVAL);
+ sync();
+
+ /* enable DDR controller */
+ setbits_be32(&im->ddr.sdram_cfg, SDRAM_CFG_MEM_EN);
+ sync();
+
+ return get_ram_size(CONFIG_SYS_SDRAM_BASE, msize);
+}
+
+int dram_init(void)
+{
+ immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ u32 msize;
+
+ if ((in_be32(&im->sysconf.immrbar) & IMMRBAR_BASE_ADDR) != (u32)im)
+ return -ENXIO;
+
+ /* DDR SDRAM */
+ msize = fixed_sdram();
+
+ /* return total bus SDRAM size(bytes) -- DDR */
+ gd->ram_size = msize;
+
+ return 0;
+}
+
+#endif /* !CONFIG_MPC83XX_SDRAM */