GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,297 @@
|
||||
// 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 <dm.h>
|
||||
#include <init.h>
|
||||
#include <miiphy.h>
|
||||
#include <tpm-v1.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm-generic/gpio.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 */
|
||||
{ {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) || tpm_startup(tpm, TPM_ST_CLEAR) ||
|
||||
tpm_continue_self_test(tpm)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
mdelay(37);
|
||||
|
||||
flush_keys(tpm);
|
||||
load_and_run_keyprog(tpm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,528 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2013
|
||||
* Reinhard Pfau, Guntermann & Drunck GmbH, reinhard.pfau@gdsys.cc
|
||||
*/
|
||||
|
||||
#include <common.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 = tpm_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 = tpm_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 = tpm_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 = tpm_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 = tpm_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 = tpm_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 = tpm_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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,138 @@
|
||||
#include <common.h>
|
||||
#include <console.h> /* ctrlc */
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "hydra.h"
|
||||
|
||||
enum {
|
||||
HWVER_100 = 0,
|
||||
HWVER_110 = 1,
|
||||
HWVER_120 = 2,
|
||||
};
|
||||
|
||||
static struct pci_device_id hydra_supported[] = {
|
||||
{ 0x6d5e, 0xcdc1 },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct ihs_fpga *fpga;
|
||||
|
||||
struct ihs_fpga *get_fpga(void)
|
||||
{
|
||||
return fpga;
|
||||
}
|
||||
|
||||
void print_hydra_version(uint index)
|
||||
{
|
||||
u32 versions = readl(&fpga->versions);
|
||||
u32 fpga_version = readl(&fpga->fpga_version);
|
||||
|
||||
uint hardware_version = versions & 0xf;
|
||||
|
||||
printf("FPGA%u: mapped to %p\n ", index, fpga);
|
||||
|
||||
switch (hardware_version) {
|
||||
case HWVER_100:
|
||||
printf("HW-Ver 1.00\n");
|
||||
break;
|
||||
|
||||
case HWVER_110:
|
||||
printf("HW-Ver 1.10\n");
|
||||
break;
|
||||
|
||||
case HWVER_120:
|
||||
printf("HW-Ver 1.20\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("HW-Ver %d(not supported)\n",
|
||||
hardware_version);
|
||||
break;
|
||||
}
|
||||
|
||||
printf(" FPGA V %d.%02d\n",
|
||||
fpga_version / 100, fpga_version % 100);
|
||||
}
|
||||
|
||||
void hydra_initialize(void)
|
||||
{
|
||||
uint i;
|
||||
pci_dev_t devno;
|
||||
|
||||
/* Find and probe all the matching PCI devices */
|
||||
for (i = 0; (devno = pci_find_devices(hydra_supported, i)) >= 0; i++) {
|
||||
u32 val;
|
||||
|
||||
/* Try to enable I/O accesses and bus-mastering */
|
||||
val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
|
||||
pci_write_config_dword(devno, PCI_COMMAND, val);
|
||||
|
||||
/* Make sure it worked */
|
||||
pci_read_config_dword(devno, PCI_COMMAND, &val);
|
||||
if (!(val & PCI_COMMAND_MEMORY)) {
|
||||
puts("Can't enable I/O memory\n");
|
||||
continue;
|
||||
}
|
||||
if (!(val & PCI_COMMAND_MASTER)) {
|
||||
puts("Can't enable bus-mastering\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* read FPGA details */
|
||||
fpga = pci_map_bar(devno, PCI_BASE_ADDRESS_0,
|
||||
PCI_REGION_MEM);
|
||||
|
||||
print_hydra_version(i);
|
||||
}
|
||||
}
|
||||
|
||||
#define REFL_PATTERN (0xdededede)
|
||||
#define REFL_PATTERN_INV (~REFL_PATTERN)
|
||||
|
||||
int do_hydrate(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
uint k = 0;
|
||||
void __iomem *pcie2_base = (void __iomem *)(MVEBU_REG_PCIE_BASE +
|
||||
0x4000);
|
||||
|
||||
if (!fpga)
|
||||
return -1;
|
||||
|
||||
while (1) {
|
||||
u32 res;
|
||||
|
||||
writel(REFL_PATTERN, &fpga->reflection_low);
|
||||
res = readl(&fpga->reflection_low);
|
||||
if (res != REFL_PATTERN_INV)
|
||||
printf("round %u: read %08x, expected %08x\n",
|
||||
k, res, REFL_PATTERN_INV);
|
||||
writel(REFL_PATTERN_INV, &fpga->reflection_low);
|
||||
res = readl(&fpga->reflection_low);
|
||||
if (res != REFL_PATTERN)
|
||||
printf("round %u: read %08x, expected %08x\n",
|
||||
k, res, REFL_PATTERN);
|
||||
|
||||
res = readl(pcie2_base + 0x118) & 0x1f;
|
||||
if (res)
|
||||
printf("FrstErrPtr %u\n", res);
|
||||
res = readl(pcie2_base + 0x104);
|
||||
if (res) {
|
||||
printf("Uncorrectable Error Status 0x%08x\n", res);
|
||||
writel(res, pcie2_base + 0x104);
|
||||
}
|
||||
|
||||
if (!(++k % 10000))
|
||||
printf("round %u\n", k);
|
||||
|
||||
if (ctrlc())
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
hydrate, 1, 0, do_hydrate,
|
||||
"hydra reflection test",
|
||||
"hydra reflection test"
|
||||
);
|
||||
@@ -0,0 +1,14 @@
|
||||
struct ihs_fpga {
|
||||
u32 reflection_low; /* 0x0000 */
|
||||
u32 versions; /* 0x0004 */
|
||||
u32 fpga_version; /* 0x0008 */
|
||||
u32 fpga_features; /* 0x000c */
|
||||
u32 reserved0[4]; /* 0x0010 */
|
||||
u32 control; /* 0x0020 */
|
||||
u32 reserved1[375]; /* 0x0024 */
|
||||
u32 qsgmii_port_state[80]; /* 0x0600 */
|
||||
};
|
||||
|
||||
void print_hydra_version(uint index);
|
||||
void hydra_initialize(void);
|
||||
struct ihs_fpga *get_fpga(void);
|
||||
@@ -0,0 +1,355 @@
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <miiphy.h>
|
||||
#include <asm-generic/gpio.h>
|
||||
|
||||
#include "ihs_phys.h"
|
||||
#include "dt_helpers.h"
|
||||
|
||||
enum {
|
||||
PORTTYPE_MAIN_CAT,
|
||||
PORTTYPE_TOP_CAT,
|
||||
PORTTYPE_16C_16F,
|
||||
PORTTYPE_UNKNOWN
|
||||
};
|
||||
|
||||
static struct porttype {
|
||||
bool phy_invert_in_pol;
|
||||
bool phy_invert_out_pol;
|
||||
} porttypes[] = {
|
||||
{ true, false },
|
||||
{ false, true },
|
||||
{ false, false },
|
||||
};
|
||||
|
||||
static void ihs_phy_config(struct phy_device *phydev, bool qinpn, bool qoutpn)
|
||||
{
|
||||
u16 reg;
|
||||
|
||||
phy_config(phydev);
|
||||
|
||||
/* enable QSGMII autonegotiation with flow control */
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0004);
|
||||
reg = phy_read(phydev, MDIO_DEVAD_NONE, 16);
|
||||
reg |= (3 << 6);
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, 16, reg);
|
||||
|
||||
/*
|
||||
* invert QSGMII Q_INP/N and Q_OUTP/N if required
|
||||
* and perform global reset
|
||||
*/
|
||||
reg = phy_read(phydev, MDIO_DEVAD_NONE, 26);
|
||||
if (qinpn)
|
||||
reg |= (1 << 13);
|
||||
if (qoutpn)
|
||||
reg |= (1 << 12);
|
||||
reg |= (1 << 15);
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, 26, reg);
|
||||
|
||||
/* advertise 1000BASE-T full-duplex only */
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000);
|
||||
reg = phy_read(phydev, MDIO_DEVAD_NONE, 4);
|
||||
reg &= ~0x1e0;
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, 4, reg);
|
||||
reg = phy_read(phydev, MDIO_DEVAD_NONE, 9);
|
||||
reg = (reg & ~0x300) | 0x200;
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, 9, reg);
|
||||
|
||||
/* copper power up */
|
||||
reg = phy_read(phydev, MDIO_DEVAD_NONE, 16);
|
||||
reg &= ~0x0004;
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, 16, reg);
|
||||
}
|
||||
|
||||
uint calculate_octo_phy_mask(void)
|
||||
{
|
||||
uint k;
|
||||
uint octo_phy_mask = 0;
|
||||
struct gpio_desc gpio = {};
|
||||
char gpio_name[64];
|
||||
static const char * const dev_name[] = {"pca9698@23", "pca9698@21",
|
||||
"pca9698@24", "pca9698@25",
|
||||
"pca9698@26"};
|
||||
|
||||
/* mark all octo phys that should be present */
|
||||
for (k = 0; k < 5; ++k) {
|
||||
snprintf(gpio_name, 64, "cat-gpio-%u", k);
|
||||
|
||||
if (request_gpio_by_name(&gpio, dev_name[k], 0x20, gpio_name))
|
||||
continue;
|
||||
|
||||
/* check CAT flag */
|
||||
if (dm_gpio_get_value(&gpio))
|
||||
octo_phy_mask |= (1 << (k * 2));
|
||||
else
|
||||
/* If CAT == 0, there's no second octo phy -> skip */
|
||||
continue;
|
||||
|
||||
snprintf(gpio_name, 64, "second-octo-gpio-%u", k);
|
||||
|
||||
if (request_gpio_by_name(&gpio, dev_name[k], 0x27, gpio_name)) {
|
||||
/* default: second octo phy is present */
|
||||
octo_phy_mask |= (1 << (k * 2 + 1));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dm_gpio_get_value(&gpio) == 0)
|
||||
octo_phy_mask |= (1 << (k * 2 + 1));
|
||||
}
|
||||
|
||||
return octo_phy_mask;
|
||||
}
|
||||
|
||||
int register_miiphy_bus(uint k, struct mii_dev **bus)
|
||||
{
|
||||
int retval;
|
||||
struct mii_dev *mdiodev = mdio_alloc();
|
||||
char *name = bb_miiphy_buses[k].name;
|
||||
|
||||
if (!mdiodev)
|
||||
return -ENOMEM;
|
||||
strncpy(mdiodev->name,
|
||||
name,
|
||||
MDIO_NAME_LEN);
|
||||
mdiodev->read = bb_miiphy_read;
|
||||
mdiodev->write = bb_miiphy_write;
|
||||
|
||||
retval = mdio_register(mdiodev);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
*bus = miiphy_get_dev_by_name(name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct porttype *get_porttype(uint octo_phy_mask, uint k)
|
||||
{
|
||||
uint octo_index = k * 4;
|
||||
|
||||
if (!k) {
|
||||
if (octo_phy_mask & 0x01)
|
||||
return &porttypes[PORTTYPE_MAIN_CAT];
|
||||
else if (!(octo_phy_mask & 0x03))
|
||||
return &porttypes[PORTTYPE_16C_16F];
|
||||
} else {
|
||||
if (octo_phy_mask & (1 << octo_index))
|
||||
return &porttypes[PORTTYPE_TOP_CAT];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int init_single_phy(struct porttype *porttype, struct mii_dev *bus,
|
||||
uint bus_idx, uint m, uint phy_idx)
|
||||
{
|
||||
struct phy_device *phydev = phy_find_by_mask(
|
||||
bus, 1 << (m * 8 + phy_idx),
|
||||
PHY_INTERFACE_MODE_MII);
|
||||
|
||||
printf(" %u", bus_idx * 32 + m * 8 + phy_idx);
|
||||
|
||||
if (!phydev)
|
||||
puts("!");
|
||||
else
|
||||
ihs_phy_config(phydev, porttype->phy_invert_in_pol,
|
||||
porttype->phy_invert_out_pol);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int init_octo_phys(uint octo_phy_mask)
|
||||
{
|
||||
uint bus_idx;
|
||||
|
||||
/* there are up to four octo-phys on each mdio bus */
|
||||
for (bus_idx = 0; bus_idx < bb_miiphy_buses_num; ++bus_idx) {
|
||||
uint m;
|
||||
uint octo_index = bus_idx * 4;
|
||||
struct mii_dev *bus = NULL;
|
||||
struct porttype *porttype = NULL;
|
||||
int ret;
|
||||
|
||||
porttype = get_porttype(octo_phy_mask, bus_idx);
|
||||
|
||||
if (!porttype)
|
||||
continue;
|
||||
|
||||
for (m = 0; m < 4; ++m) {
|
||||
uint phy_idx;
|
||||
|
||||
/**
|
||||
* Register a bus device if there is at least one phy
|
||||
* on the current bus
|
||||
*/
|
||||
if (!m && octo_phy_mask & (0xf << octo_index)) {
|
||||
ret = register_miiphy_bus(bus_idx, &bus);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!(octo_phy_mask & BIT(octo_index + m)))
|
||||
continue;
|
||||
|
||||
for (phy_idx = 0; phy_idx < 8; ++phy_idx)
|
||||
init_single_phy(porttype, bus, bus_idx, m,
|
||||
phy_idx);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* MII GPIO bitbang implementation
|
||||
* MDC MDIO bus
|
||||
* 13 14 PHY1-4
|
||||
* 25 45 PHY5-8
|
||||
* 46 24 PHY9-10
|
||||
*/
|
||||
|
||||
struct gpio_mii {
|
||||
int index;
|
||||
struct gpio_desc mdc_gpio;
|
||||
struct gpio_desc mdio_gpio;
|
||||
int mdc_num;
|
||||
int mdio_num;
|
||||
int mdio_value;
|
||||
} gpio_mii_set[] = {
|
||||
{ 0, {}, {}, 13, 14, 1 },
|
||||
{ 1, {}, {}, 25, 45, 1 },
|
||||
{ 2, {}, {}, 46, 24, 1 },
|
||||
};
|
||||
|
||||
static int mii_mdio_init(struct bb_miiphy_bus *bus)
|
||||
{
|
||||
struct gpio_mii *gpio_mii = bus->priv;
|
||||
char name[32] = {};
|
||||
struct udevice *gpio_dev1 = NULL;
|
||||
struct udevice *gpio_dev2 = NULL;
|
||||
|
||||
if (uclass_get_device_by_name(UCLASS_GPIO, "gpio@18100", &gpio_dev1) ||
|
||||
uclass_get_device_by_name(UCLASS_GPIO, "gpio@18140", &gpio_dev2)) {
|
||||
printf("Could not get GPIO device.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (gpio_mii->mdc_num > 31) {
|
||||
gpio_mii->mdc_gpio.dev = gpio_dev2;
|
||||
gpio_mii->mdc_gpio.offset = gpio_mii->mdc_num - 32;
|
||||
} else {
|
||||
gpio_mii->mdc_gpio.dev = gpio_dev1;
|
||||
gpio_mii->mdc_gpio.offset = gpio_mii->mdc_num;
|
||||
}
|
||||
gpio_mii->mdc_gpio.flags = 0;
|
||||
snprintf(name, 32, "bb_miiphy_bus-%d-mdc", gpio_mii->index);
|
||||
dm_gpio_request(&gpio_mii->mdc_gpio, name);
|
||||
|
||||
if (gpio_mii->mdio_num > 31) {
|
||||
gpio_mii->mdio_gpio.dev = gpio_dev2;
|
||||
gpio_mii->mdio_gpio.offset = gpio_mii->mdio_num - 32;
|
||||
} else {
|
||||
gpio_mii->mdio_gpio.dev = gpio_dev1;
|
||||
gpio_mii->mdio_gpio.offset = gpio_mii->mdio_num;
|
||||
}
|
||||
gpio_mii->mdio_gpio.flags = 0;
|
||||
snprintf(name, 32, "bb_miiphy_bus-%d-mdio", gpio_mii->index);
|
||||
dm_gpio_request(&gpio_mii->mdio_gpio, name);
|
||||
|
||||
dm_gpio_set_dir_flags(&gpio_mii->mdc_gpio, GPIOD_IS_OUT);
|
||||
dm_gpio_set_value(&gpio_mii->mdc_gpio, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_mdio_active(struct bb_miiphy_bus *bus)
|
||||
{
|
||||
struct gpio_mii *gpio_mii = bus->priv;
|
||||
|
||||
dm_gpio_set_value(&gpio_mii->mdc_gpio, gpio_mii->mdio_value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_mdio_tristate(struct bb_miiphy_bus *bus)
|
||||
{
|
||||
struct gpio_mii *gpio_mii = bus->priv;
|
||||
|
||||
dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_set_mdio(struct bb_miiphy_bus *bus, int v)
|
||||
{
|
||||
struct gpio_mii *gpio_mii = bus->priv;
|
||||
|
||||
dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_OUT);
|
||||
dm_gpio_set_value(&gpio_mii->mdio_gpio, v);
|
||||
gpio_mii->mdio_value = v;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v)
|
||||
{
|
||||
struct gpio_mii *gpio_mii = bus->priv;
|
||||
|
||||
dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN);
|
||||
*v = (dm_gpio_get_value(&gpio_mii->mdio_gpio));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_set_mdc(struct bb_miiphy_bus *bus, int v)
|
||||
{
|
||||
struct gpio_mii *gpio_mii = bus->priv;
|
||||
|
||||
dm_gpio_set_value(&gpio_mii->mdc_gpio, v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_delay(struct bb_miiphy_bus *bus)
|
||||
{
|
||||
udelay(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bb_miiphy_bus bb_miiphy_buses[] = {
|
||||
{
|
||||
.name = "ihs0",
|
||||
.init = mii_mdio_init,
|
||||
.mdio_active = mii_mdio_active,
|
||||
.mdio_tristate = mii_mdio_tristate,
|
||||
.set_mdio = mii_set_mdio,
|
||||
.get_mdio = mii_get_mdio,
|
||||
.set_mdc = mii_set_mdc,
|
||||
.delay = mii_delay,
|
||||
.priv = &gpio_mii_set[0],
|
||||
},
|
||||
{
|
||||
.name = "ihs1",
|
||||
.init = mii_mdio_init,
|
||||
.mdio_active = mii_mdio_active,
|
||||
.mdio_tristate = mii_mdio_tristate,
|
||||
.set_mdio = mii_set_mdio,
|
||||
.get_mdio = mii_get_mdio,
|
||||
.set_mdc = mii_set_mdc,
|
||||
.delay = mii_delay,
|
||||
.priv = &gpio_mii_set[1],
|
||||
},
|
||||
{
|
||||
.name = "ihs2",
|
||||
.init = mii_mdio_init,
|
||||
.mdio_active = mii_mdio_active,
|
||||
.mdio_tristate = mii_mdio_tristate,
|
||||
.set_mdio = mii_set_mdio,
|
||||
.get_mdio = mii_get_mdio,
|
||||
.set_mdc = mii_set_mdc,
|
||||
.delay = mii_delay,
|
||||
.priv = &gpio_mii_set[2],
|
||||
},
|
||||
};
|
||||
|
||||
int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses);
|
||||
@@ -0,0 +1,2 @@
|
||||
uint calculate_octo_phy_mask(void);
|
||||
int init_octo_phys(uint octo_phy_mask);
|
||||
@@ -0,0 +1,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 = tpm_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 = tpm_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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
# 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_HRCON) += osd.o mclink.o dp501.o phy.o ioep-fpga.o fanctrl.o
|
||||
obj-$(CONFIG_TARGET_STRIDER) += mclink.o dp501.o phy.o ioep-fpga.o adv7611.o ch7301.o
|
||||
obj-$(CONFIG_TARGET_STRIDER) += fanctrl.o
|
||||
obj-$(CONFIG_STRIDER_CON) += osd.o
|
||||
obj-$(CONFIG_STRIDER_CON_DP) += osd.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
|
||||
@@ -0,0 +1,180 @@
|
||||
// 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 <i2c.h>
|
||||
|
||||
#define ADV7611_I2C_ADDR 0x4c
|
||||
#define ADV7611_RDINFO 0x2051
|
||||
|
||||
/*
|
||||
* ADV7611 I2C Addresses in u-boot notation
|
||||
*/
|
||||
enum {
|
||||
CP_I2C_ADDR = 0x22,
|
||||
DPLL_I2C_ADDR = 0x26,
|
||||
KSV_I2C_ADDR = 0x32,
|
||||
HDMI_I2C_ADDR = 0x34,
|
||||
EDID_I2C_ADDR = 0x36,
|
||||
INFOFRAME_I2C_ADDR = 0x3e,
|
||||
CEC_I2C_ADDR = 0x40,
|
||||
IO_I2C_ADDR = ADV7611_I2C_ADDR,
|
||||
};
|
||||
|
||||
/*
|
||||
* Global Control Registers
|
||||
*/
|
||||
enum {
|
||||
IO_RD_INFO_MSB = 0xea,
|
||||
IO_RD_INFO_LSB = 0xeb,
|
||||
IO_CEC_ADDR = 0xf4,
|
||||
IO_INFOFRAME_ADDR = 0xf5,
|
||||
IO_DPLL_ADDR = 0xf8,
|
||||
IO_KSV_ADDR = 0xf9,
|
||||
IO_EDID_ADDR = 0xfa,
|
||||
IO_HDMI_ADDR = 0xfb,
|
||||
IO_CP_ADDR = 0xfd,
|
||||
};
|
||||
|
||||
int adv7611_i2c[] = CONFIG_SYS_ADV7611_I2C;
|
||||
|
||||
int adv7611_probe(unsigned int screen)
|
||||
{
|
||||
int old_bus = i2c_get_bus_num();
|
||||
unsigned int rd_info;
|
||||
int res = 0;
|
||||
|
||||
i2c_set_bus_num(adv7611_i2c[screen]);
|
||||
|
||||
rd_info = (i2c_reg_read(IO_I2C_ADDR, IO_RD_INFO_MSB) << 8)
|
||||
| i2c_reg_read(IO_I2C_ADDR, IO_RD_INFO_LSB);
|
||||
|
||||
if (rd_info != ADV7611_RDINFO) {
|
||||
res = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* set I2C addresses to default values
|
||||
*/
|
||||
i2c_reg_write(IO_I2C_ADDR, IO_CEC_ADDR, CEC_I2C_ADDR << 1);
|
||||
i2c_reg_write(IO_I2C_ADDR, IO_INFOFRAME_ADDR, INFOFRAME_I2C_ADDR << 1);
|
||||
i2c_reg_write(IO_I2C_ADDR, IO_DPLL_ADDR, DPLL_I2C_ADDR << 1);
|
||||
i2c_reg_write(IO_I2C_ADDR, IO_KSV_ADDR, KSV_I2C_ADDR << 1);
|
||||
i2c_reg_write(IO_I2C_ADDR, IO_EDID_ADDR, EDID_I2C_ADDR << 1);
|
||||
i2c_reg_write(IO_I2C_ADDR, IO_HDMI_ADDR, HDMI_I2C_ADDR << 1);
|
||||
i2c_reg_write(IO_I2C_ADDR, IO_CP_ADDR, CP_I2C_ADDR << 1);
|
||||
|
||||
/*
|
||||
* do magic initialization sequence from
|
||||
* "ADV7611 Register Settings Recommendations Revision 1.5"
|
||||
* with most registers undocumented
|
||||
*/
|
||||
i2c_reg_write(CP_I2C_ADDR, 0x6c, 0x00);
|
||||
i2c_reg_write(HDMI_I2C_ADDR, 0x9b, 0x03);
|
||||
i2c_reg_write(HDMI_I2C_ADDR, 0x6f, 0x08);
|
||||
i2c_reg_write(HDMI_I2C_ADDR, 0x85, 0x1f);
|
||||
i2c_reg_write(HDMI_I2C_ADDR, 0x87, 0x70);
|
||||
i2c_reg_write(HDMI_I2C_ADDR, 0x57, 0xda);
|
||||
i2c_reg_write(HDMI_I2C_ADDR, 0x58, 0x01);
|
||||
i2c_reg_write(HDMI_I2C_ADDR, 0x03, 0x98);
|
||||
i2c_reg_write(HDMI_I2C_ADDR, 0x4c, 0x44);
|
||||
|
||||
/*
|
||||
* IO_REG_02, default 0xf0
|
||||
*
|
||||
* INP_COLOR_SPACE (IO, Address 0x02[7:4])
|
||||
* default: 0b1111 auto
|
||||
* set to : 0b0001 force RGB (range 0 to 255) input
|
||||
*
|
||||
* RGB_OUT (IO, Address 0x02[1])
|
||||
* default: 0 YPbPr color space output
|
||||
* set to : 1 RGB color space output
|
||||
*/
|
||||
i2c_reg_write(IO_I2C_ADDR, 0x02, 0x12);
|
||||
|
||||
/*
|
||||
* IO_REG_03, default 0x00
|
||||
*
|
||||
* OP_FORMAT_SEL (IO, Address 0x03[7:0])
|
||||
* default: 0x00 8-bit SDR ITU-656 mode
|
||||
* set to : 0x40 24-bit 4:4:4 SDR mode
|
||||
*/
|
||||
i2c_reg_write(IO_I2C_ADDR, 0x03, 0x40);
|
||||
|
||||
/*
|
||||
* IO_REG_05, default 0x2c
|
||||
*
|
||||
* AVCODE_INSERT_EN (IO, Address 0x05[2])
|
||||
* default: 1 insert AV codes into data stream
|
||||
* set to : 0 do not insert AV codes into data stream
|
||||
*/
|
||||
i2c_reg_write(IO_I2C_ADDR, 0x05, 0x28);
|
||||
|
||||
/*
|
||||
* IO_REG_0C, default 0x62
|
||||
*
|
||||
* POWER_DOWN (IO, Address 0x0C[5])
|
||||
* default: 1 chip is powered down
|
||||
* set to : 0 chip is operational
|
||||
*/
|
||||
i2c_reg_write(IO_I2C_ADDR, 0x0c, 0x42);
|
||||
|
||||
/*
|
||||
* IO_REG_15, default 0xbe
|
||||
*
|
||||
* TRI_SYNCS (IO, Address 0x15[3)
|
||||
* TRI_LLC (IO, Address 0x15[2])
|
||||
* TRI_PIX (IO, Address 0x15[1])
|
||||
* default: 1 video output pins are tristate
|
||||
* set to : 0 video output pins are active
|
||||
*/
|
||||
i2c_reg_write(IO_I2C_ADDR, 0x15, 0xb0);
|
||||
|
||||
/*
|
||||
* HDMI_REGISTER_02H, default 0xff
|
||||
*
|
||||
* CLOCK_TERMA_DISABLE (HDMI, Address 0x83[0])
|
||||
* default: 1 disable termination
|
||||
* set to : 0 enable termination
|
||||
* Future options are:
|
||||
* - use the chips automatic termination control
|
||||
* - set this manually on cable detect
|
||||
* but at the moment this seems a safe default.
|
||||
*/
|
||||
i2c_reg_write(HDMI_I2C_ADDR, 0x83, 0xfe);
|
||||
|
||||
/*
|
||||
* HDMI_CP_CNTRL_1, default 0x01
|
||||
*
|
||||
* HDMI_FRUN_EN (CP, Address 0xBA[0])
|
||||
* default: 1 Enable the free run feature in HDMI mode
|
||||
* set to : 0 Disable the free run feature in HDMI mode
|
||||
*/
|
||||
i2c_reg_write(CP_I2C_ADDR, 0xba, 0x00);
|
||||
|
||||
/*
|
||||
* INT1_CONFIGURATION, default 0x20
|
||||
*
|
||||
* INTRQ_DUR_SEL[1:0] (IO, Address 0x40[7:6])
|
||||
* default: 00 Interrupt signal is active for 4 Xtal periods
|
||||
* set to : 11 Active until cleared
|
||||
*
|
||||
* INTRQ_OP_SEL[1:0] (IO, Address 0x40[1:0])
|
||||
* default: 00 Open drain
|
||||
* set to : 10 Drives high when active
|
||||
*/
|
||||
i2c_reg_write(IO_I2C_ADDR, 0x40, 0xc2);
|
||||
|
||||
out:
|
||||
i2c_set_bus_num(old_bus);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
|
||||
@@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2014
|
||||
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
|
||||
*/
|
||||
|
||||
#ifndef _ADV7611_H_
|
||||
#define _ADV7611_H_
|
||||
|
||||
int adv7611_probe(unsigned int screen);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2014
|
||||
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
|
||||
*/
|
||||
|
||||
/* Chrontel CH7301C DVI Transmitter */
|
||||
|
||||
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <errno.h>
|
||||
#include <i2c.h>
|
||||
|
||||
#define CH7301_I2C_ADDR 0x75
|
||||
|
||||
enum {
|
||||
CH7301_CM = 0x1c, /* Clock Mode Register */
|
||||
CH7301_IC = 0x1d, /* Input Clock Register */
|
||||
CH7301_GPIO = 0x1e, /* GPIO Control Register */
|
||||
CH7301_IDF = 0x1f, /* Input Data Format Register */
|
||||
CH7301_CD = 0x20, /* Connection Detect Register */
|
||||
CH7301_DC = 0x21, /* DAC Control Register */
|
||||
CH7301_HPD = 0x23, /* Hot Plug Detection Register */
|
||||
CH7301_TCTL = 0x31, /* DVI Control Input Register */
|
||||
CH7301_TPCP = 0x33, /* DVI PLL Charge Pump Ctrl Register */
|
||||
CH7301_TPD = 0x34, /* DVI PLL Divide Register */
|
||||
CH7301_TPVT = 0x35, /* DVI PLL Supply Control Register */
|
||||
CH7301_TPF = 0x36, /* DVI PLL Filter Register */
|
||||
CH7301_TCT = 0x37, /* DVI Clock Test Register */
|
||||
CH7301_TSTP = 0x48, /* Test Pattern Register */
|
||||
CH7301_PM = 0x49, /* Power Management register */
|
||||
CH7301_VID = 0x4a, /* Version ID Register */
|
||||
CH7301_DID = 0x4b, /* Device ID Register */
|
||||
CH7301_DSP = 0x56, /* DVI Sync polarity Register */
|
||||
};
|
||||
|
||||
int ch7301_i2c[] = CONFIG_SYS_CH7301_I2C;
|
||||
|
||||
int ch7301_probe(unsigned screen, bool power)
|
||||
{
|
||||
u8 value;
|
||||
|
||||
i2c_set_bus_num(ch7301_i2c[screen]);
|
||||
if (i2c_probe(CH7301_I2C_ADDR))
|
||||
return -1;
|
||||
|
||||
value = i2c_reg_read(CH7301_I2C_ADDR, CH7301_DID);
|
||||
if (value != 0x17)
|
||||
return -1;
|
||||
|
||||
if (power) {
|
||||
i2c_reg_write(CH7301_I2C_ADDR, CH7301_TPCP, 0x08);
|
||||
i2c_reg_write(CH7301_I2C_ADDR, CH7301_TPD, 0x16);
|
||||
i2c_reg_write(CH7301_I2C_ADDR, CH7301_TPF, 0x60);
|
||||
i2c_reg_write(CH7301_I2C_ADDR, CH7301_DC, 0x09);
|
||||
i2c_reg_write(CH7301_I2C_ADDR, CH7301_PM, 0xc0);
|
||||
} else {
|
||||
i2c_reg_write(CH7301_I2C_ADDR, CH7301_DC, 0x00);
|
||||
i2c_reg_write(CH7301_I2C_ADDR, CH7301_PM, 0x01);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
|
||||
@@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2014
|
||||
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
|
||||
*/
|
||||
|
||||
#ifndef _CH7301_H_
|
||||
#define _CH7301_H_
|
||||
|
||||
int ch7301_probe(unsigned screen, bool power);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,581 @@
|
||||
// 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 <gdsys_fpga.h>
|
||||
|
||||
#ifndef CONFIG_GDSYS_LEGACY_DRIVERS
|
||||
#include <dm.h>
|
||||
#include <misc.h>
|
||||
#include <regmap.h>
|
||||
#include <board.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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
struct udevice *ioep = NULL;
|
||||
struct udevice *board;
|
||||
char name[8];
|
||||
int ret;
|
||||
|
||||
if (board_get(&board))
|
||||
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, board, 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, board, 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 */
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -0,0 +1,35 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2015
|
||||
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
|
||||
enum {
|
||||
FAN_CONFIG = 0x03,
|
||||
FAN_TACHLIM_LSB = 0x48,
|
||||
FAN_TACHLIM_MSB = 0x49,
|
||||
FAN_PWM_FREQ = 0x4D,
|
||||
};
|
||||
|
||||
void init_fan_controller(u8 addr)
|
||||
{
|
||||
int val;
|
||||
|
||||
/* set PWM Frequency to 2.5% resolution */
|
||||
i2c_reg_write(addr, FAN_PWM_FREQ, 20);
|
||||
|
||||
/* set Tachometer Limit */
|
||||
i2c_reg_write(addr, FAN_TACHLIM_LSB, 0x10);
|
||||
i2c_reg_write(addr, FAN_TACHLIM_MSB, 0x0a);
|
||||
|
||||
/* enable Tach input */
|
||||
val = i2c_reg_read(addr, FAN_CONFIG) | 0x04;
|
||||
i2c_reg_write(addr, FAN_CONFIG, val);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
|
||||
@@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2015
|
||||
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
|
||||
*/
|
||||
|
||||
#ifndef _FANCTRL_H_
|
||||
#define _FANCTRL_H_
|
||||
|
||||
void init_fan_controller(u8 addr);
|
||||
|
||||
#endif
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,163 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2014
|
||||
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
|
||||
*/
|
||||
|
||||
#include <common.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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,589 @@
|
||||
// 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>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#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 */
|
||||
@@ -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
|
||||
@@ -0,0 +1,140 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2012
|
||||
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <gdsys_fpga.h>
|
||||
|
||||
enum {
|
||||
MCINT_SLAVE_LINK_CHANGED_EV = 1 << 7,
|
||||
MCINT_TX_ERROR_EV = 1 << 9,
|
||||
MCINT_TX_BUFFER_FREE = 1 << 10,
|
||||
MCINT_TX_PACKET_TRANSMITTED_EV = 1 << 11,
|
||||
MCINT_RX_ERROR_EV = 1 << 13,
|
||||
MCINT_RX_CONTENT_AVAILABLE = 1 << 14,
|
||||
MCINT_RX_PACKET_RECEIVED_EV = 1 << 15,
|
||||
};
|
||||
|
||||
int mclink_probe(void)
|
||||
{
|
||||
unsigned int k;
|
||||
int slaves = 0;
|
||||
|
||||
for (k = 0; k < CONFIG_SYS_MCLINK_MAX; ++k) {
|
||||
int timeout = 0;
|
||||
unsigned int ctr = 0;
|
||||
u16 mc_status;
|
||||
|
||||
FPGA_GET_REG(k, mc_status, &mc_status);
|
||||
|
||||
if (!(mc_status & (1 << 15)))
|
||||
break;
|
||||
|
||||
FPGA_SET_REG(k, mc_control, 0x8000);
|
||||
|
||||
FPGA_GET_REG(k, mc_status, &mc_status);
|
||||
while (!(mc_status & (1 << 14))) {
|
||||
udelay(100);
|
||||
if (ctr++ > 500) {
|
||||
timeout = 1;
|
||||
break;
|
||||
}
|
||||
FPGA_GET_REG(k, mc_status, &mc_status);
|
||||
}
|
||||
if (timeout)
|
||||
break;
|
||||
|
||||
printf("waited %d us for mclink %d to come up\n", ctr * 100, k);
|
||||
|
||||
slaves++;
|
||||
}
|
||||
|
||||
return slaves;
|
||||
}
|
||||
|
||||
int mclink_send(u8 slave, u16 addr, u16 data)
|
||||
{
|
||||
unsigned int ctr = 0;
|
||||
u16 int_status;
|
||||
u16 rx_cmd_status;
|
||||
u16 rx_cmd;
|
||||
|
||||
/* reset interrupt status */
|
||||
FPGA_GET_REG(0, mc_int, &int_status);
|
||||
FPGA_SET_REG(0, mc_int, int_status);
|
||||
|
||||
/* send */
|
||||
FPGA_SET_REG(0, mc_tx_address, addr);
|
||||
FPGA_SET_REG(0, mc_tx_data, data);
|
||||
FPGA_SET_REG(0, mc_tx_cmd, (slave & 0x03) << 14);
|
||||
FPGA_SET_REG(0, mc_control, 0x8001);
|
||||
|
||||
/* wait for reply */
|
||||
FPGA_GET_REG(0, mc_int, &int_status);
|
||||
while (!(int_status & MCINT_RX_PACKET_RECEIVED_EV)) {
|
||||
udelay(100);
|
||||
if (ctr++ > 3)
|
||||
return -ETIMEDOUT;
|
||||
FPGA_GET_REG(0, mc_int, &int_status);
|
||||
}
|
||||
|
||||
FPGA_GET_REG(0, mc_rx_cmd_status, &rx_cmd_status);
|
||||
rx_cmd = (rx_cmd_status >> 12) & 0x03;
|
||||
if (rx_cmd != 0)
|
||||
printf("mclink_send: received cmd %d, expected %d\n", rx_cmd,
|
||||
0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mclink_receive(u8 slave, u16 addr, u16 *data)
|
||||
{
|
||||
u16 rx_cmd_status;
|
||||
u16 rx_cmd;
|
||||
u16 int_status;
|
||||
unsigned int ctr = 0;
|
||||
|
||||
/* send read request */
|
||||
FPGA_SET_REG(0, mc_tx_address, addr);
|
||||
FPGA_SET_REG(0, mc_tx_cmd,
|
||||
((slave & 0x03) << 14) | (1 << 12) | (1 << 0));
|
||||
FPGA_SET_REG(0, mc_control, 0x8001);
|
||||
|
||||
|
||||
/* wait for reply */
|
||||
FPGA_GET_REG(0, mc_int, &int_status);
|
||||
while (!(int_status & MCINT_RX_CONTENT_AVAILABLE)) {
|
||||
udelay(100);
|
||||
if (ctr++ > 3)
|
||||
return -ETIMEDOUT;
|
||||
FPGA_GET_REG(0, mc_int, &int_status);
|
||||
}
|
||||
|
||||
/* check reply */
|
||||
FPGA_GET_REG(0, mc_rx_cmd_status, &rx_cmd_status);
|
||||
if ((rx_cmd_status >> 14) != slave) {
|
||||
printf("mclink_receive: reply from slave %d, expected %d\n",
|
||||
rx_cmd_status >> 14, slave);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rx_cmd = (rx_cmd_status >> 12) & 0x03;
|
||||
if (rx_cmd != 1) {
|
||||
printf("mclink_send: received cmd %d, expected %d\n",
|
||||
rx_cmd, 1);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
FPGA_GET_REG(0, mc_rx_data, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
|
||||
@@ -0,0 +1,14 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2012
|
||||
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
|
||||
*/
|
||||
|
||||
#ifndef _MCLINK_H_
|
||||
#define _MCLINK_H_
|
||||
|
||||
int mclink_probe(void);
|
||||
int mclink_send(u8 slave, u16 addr, u16 data);
|
||||
int mclink_receive(u8 slave, u16 addr, u16 *data);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,503 @@
|
||||
// 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 <i2c.h>
|
||||
#include <malloc.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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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 */
|
||||
@@ -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
|
||||
@@ -0,0 +1,146 @@
|
||||
// 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 <dm.h>
|
||||
#include <hexdump.h>
|
||||
#include <video_osd.h>
|
||||
#include <malloc.h>
|
||||
|
||||
static int do_osd_write(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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"
|
||||
);
|
||||
@@ -0,0 +1,277 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2014
|
||||
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <miiphy.h>
|
||||
|
||||
enum {
|
||||
MIICMD_SET,
|
||||
MIICMD_MODIFY,
|
||||
MIICMD_VERIFY_VALUE,
|
||||
MIICMD_WAIT_FOR_VALUE,
|
||||
};
|
||||
|
||||
struct mii_setupcmd {
|
||||
u8 token;
|
||||
u8 reg;
|
||||
u16 data;
|
||||
u16 mask;
|
||||
u32 timeout;
|
||||
};
|
||||
|
||||
/*
|
||||
* verify we are talking to a 88e1518
|
||||
*/
|
||||
struct mii_setupcmd verify_88e1518[] = {
|
||||
{ MIICMD_SET, 22, 0x0000 },
|
||||
{ MIICMD_VERIFY_VALUE, 2, 0x0141, 0xffff },
|
||||
{ MIICMD_VERIFY_VALUE, 3, 0x0dd0, 0xfff0 },
|
||||
};
|
||||
|
||||
/*
|
||||
* workaround for erratum mentioned in 88E1518 release notes
|
||||
*/
|
||||
struct mii_setupcmd fixup_88e1518[] = {
|
||||
{ MIICMD_SET, 22, 0x00ff },
|
||||
{ MIICMD_SET, 17, 0x214b },
|
||||
{ MIICMD_SET, 16, 0x2144 },
|
||||
{ MIICMD_SET, 17, 0x0c28 },
|
||||
{ MIICMD_SET, 16, 0x2146 },
|
||||
{ MIICMD_SET, 17, 0xb233 },
|
||||
{ MIICMD_SET, 16, 0x214d },
|
||||
{ MIICMD_SET, 17, 0xcc0c },
|
||||
{ MIICMD_SET, 16, 0x2159 },
|
||||
{ MIICMD_SET, 22, 0x0000 },
|
||||
};
|
||||
|
||||
/*
|
||||
* default initialization:
|
||||
* - set RGMII receive timing to "receive clock transition when data stable"
|
||||
* - set RGMII transmit timing to "transmit clock internally delayed"
|
||||
* - set RGMII output impedance target to 78,8 Ohm
|
||||
* - run output impedance calibration
|
||||
* - set autonegotiation advertise to 1000FD only
|
||||
*/
|
||||
struct mii_setupcmd default_88e1518[] = {
|
||||
{ MIICMD_SET, 22, 0x0002 },
|
||||
{ MIICMD_MODIFY, 21, 0x0030, 0x0030 },
|
||||
{ MIICMD_MODIFY, 25, 0x0000, 0x0003 },
|
||||
{ MIICMD_MODIFY, 24, 0x8000, 0x8000 },
|
||||
{ MIICMD_WAIT_FOR_VALUE, 24, 0x4000, 0x4000, 2000 },
|
||||
{ MIICMD_SET, 22, 0x0000 },
|
||||
{ MIICMD_MODIFY, 4, 0x0000, 0x01e0 },
|
||||
{ MIICMD_MODIFY, 9, 0x0200, 0x0300 },
|
||||
};
|
||||
|
||||
/*
|
||||
* turn off CLK125 for PHY daughterboard
|
||||
*/
|
||||
struct mii_setupcmd ch1fix_88e1518[] = {
|
||||
{ MIICMD_SET, 22, 0x0002 },
|
||||
{ MIICMD_MODIFY, 16, 0x0006, 0x0006 },
|
||||
{ MIICMD_SET, 22, 0x0000 },
|
||||
};
|
||||
|
||||
/*
|
||||
* perform copper software reset
|
||||
*/
|
||||
struct mii_setupcmd swreset_88e1518[] = {
|
||||
{ MIICMD_SET, 22, 0x0000 },
|
||||
{ MIICMD_MODIFY, 0, 0x8000, 0x8000 },
|
||||
{ MIICMD_WAIT_FOR_VALUE, 0, 0x0000, 0x8000, 2000 },
|
||||
};
|
||||
|
||||
/*
|
||||
* special one for 88E1514:
|
||||
* Force SGMII to Copper mode
|
||||
*/
|
||||
struct mii_setupcmd mii_to_copper_88e1514[] = {
|
||||
{ MIICMD_SET, 22, 0x0012 },
|
||||
{ MIICMD_MODIFY, 20, 0x0001, 0x0007 },
|
||||
{ MIICMD_MODIFY, 20, 0x8000, 0x8000 },
|
||||
{ MIICMD_SET, 22, 0x0000 },
|
||||
};
|
||||
|
||||
/*
|
||||
* turn off SGMII auto-negotiation
|
||||
*/
|
||||
struct mii_setupcmd sgmii_autoneg_off_88e1518[] = {
|
||||
{ MIICMD_SET, 22, 0x0001 },
|
||||
{ MIICMD_MODIFY, 0, 0x0000, 0x1000 },
|
||||
{ MIICMD_MODIFY, 0, 0x8000, 0x8000 },
|
||||
{ MIICMD_SET, 22, 0x0000 },
|
||||
};
|
||||
|
||||
/*
|
||||
* invert LED2 polarity
|
||||
*/
|
||||
struct mii_setupcmd invert_led2_88e1514[] = {
|
||||
{ MIICMD_SET, 22, 0x0003 },
|
||||
{ MIICMD_MODIFY, 17, 0x0030, 0x0010 },
|
||||
{ MIICMD_SET, 22, 0x0000 },
|
||||
};
|
||||
|
||||
static int process_setupcmd(const char *bus, unsigned char addr,
|
||||
struct mii_setupcmd *setupcmd)
|
||||
{
|
||||
int res;
|
||||
u8 reg = setupcmd->reg;
|
||||
u16 data = setupcmd->data;
|
||||
u16 mask = setupcmd->mask;
|
||||
u32 timeout = setupcmd->timeout;
|
||||
u16 orig_data;
|
||||
unsigned long start;
|
||||
|
||||
debug("mii %s:%u reg %2u ", bus, addr, reg);
|
||||
|
||||
switch (setupcmd->token) {
|
||||
case MIICMD_MODIFY:
|
||||
res = miiphy_read(bus, addr, reg, &orig_data);
|
||||
if (res)
|
||||
break;
|
||||
debug("is %04x. (value %04x mask %04x) ", orig_data, data,
|
||||
mask);
|
||||
data = (orig_data & ~mask) | (data & mask);
|
||||
/* fallthrough */
|
||||
case MIICMD_SET:
|
||||
debug("=> %04x\n", data);
|
||||
res = miiphy_write(bus, addr, reg, data);
|
||||
break;
|
||||
case MIICMD_VERIFY_VALUE:
|
||||
res = miiphy_read(bus, addr, reg, &orig_data);
|
||||
if (res)
|
||||
break;
|
||||
if ((orig_data & mask) != (data & mask))
|
||||
res = -1;
|
||||
debug("(value %04x mask %04x) == %04x? %s\n", data, mask,
|
||||
orig_data, res ? "FAIL" : "PASS");
|
||||
break;
|
||||
case MIICMD_WAIT_FOR_VALUE:
|
||||
res = -1;
|
||||
start = get_timer(0);
|
||||
while ((res != 0) && (get_timer(start) < timeout)) {
|
||||
res = miiphy_read(bus, addr, reg, &orig_data);
|
||||
if (res)
|
||||
continue;
|
||||
if ((orig_data & mask) != (data & mask))
|
||||
res = -1;
|
||||
}
|
||||
debug("(value %04x mask %04x) == %04x? %s after %lu ms\n", data,
|
||||
mask, orig_data, res ? "FAIL" : "PASS",
|
||||
get_timer(start));
|
||||
break;
|
||||
default:
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int process_setup(const char *bus, unsigned char addr,
|
||||
struct mii_setupcmd *setupcmd, unsigned int count)
|
||||
{
|
||||
int res = 0;
|
||||
unsigned int k;
|
||||
|
||||
for (k = 0; k < count; ++k) {
|
||||
res = process_setupcmd(bus, addr, &setupcmd[k]);
|
||||
if (res) {
|
||||
printf("mii cmd %u on bus %s addr %u failed, aborting setup\n",
|
||||
setupcmd[k].token, bus, addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int setup_88e1518(const char *bus, unsigned char addr)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = process_setup(bus, addr,
|
||||
verify_88e1518, ARRAY_SIZE(verify_88e1518));
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = process_setup(bus, addr,
|
||||
fixup_88e1518, ARRAY_SIZE(fixup_88e1518));
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = process_setup(bus, addr,
|
||||
default_88e1518, ARRAY_SIZE(default_88e1518));
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
if (addr) {
|
||||
res = process_setup(bus, addr,
|
||||
ch1fix_88e1518, ARRAY_SIZE(ch1fix_88e1518));
|
||||
if (res)
|
||||
return res;
|
||||
}
|
||||
|
||||
res = process_setup(bus, addr,
|
||||
swreset_88e1518, ARRAY_SIZE(swreset_88e1518));
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setup_88e1514(const char *bus, unsigned char addr)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = process_setup(bus, addr,
|
||||
verify_88e1518, ARRAY_SIZE(verify_88e1518));
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = process_setup(bus, addr,
|
||||
fixup_88e1518, ARRAY_SIZE(fixup_88e1518));
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = process_setup(bus, addr,
|
||||
mii_to_copper_88e1514,
|
||||
ARRAY_SIZE(mii_to_copper_88e1514));
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = process_setup(bus, addr,
|
||||
sgmii_autoneg_off_88e1518,
|
||||
ARRAY_SIZE(sgmii_autoneg_off_88e1518));
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = process_setup(bus, addr,
|
||||
invert_led2_88e1514,
|
||||
ARRAY_SIZE(invert_led2_88e1514));
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = process_setup(bus, addr,
|
||||
default_88e1518, ARRAY_SIZE(default_88e1518));
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
if (addr) {
|
||||
res = process_setup(bus, addr,
|
||||
ch1fix_88e1518, ARRAY_SIZE(ch1fix_88e1518));
|
||||
if (res)
|
||||
return res;
|
||||
}
|
||||
|
||||
res = process_setup(bus, addr,
|
||||
swreset_88e1518, ARRAY_SIZE(swreset_88e1518));
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2014
|
||||
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
|
||||
*/
|
||||
|
||||
#ifndef _PHY_H_
|
||||
#define _PHY_H_
|
||||
|
||||
int setup_88e1514(const char *bus, unsigned char addr);
|
||||
int setup_88e1518(const char *bus, unsigned char addr);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,124 @@
|
||||
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.
|
||||
|
||||
if TARGET_HRCON
|
||||
|
||||
config SYS_BOARD
|
||||
default "mpc8308"
|
||||
|
||||
config SYS_VENDOR
|
||||
default "gdsys"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "hrcon"
|
||||
|
||||
config GDSYS_LEGACY_OSD_CMDS
|
||||
default y
|
||||
|
||||
config GDSYS_LEGACY_DRIVERS
|
||||
default y
|
||||
|
||||
endif
|
||||
|
||||
if TARGET_STRIDER
|
||||
|
||||
config SYS_BOARD
|
||||
default "mpc8308"
|
||||
|
||||
config SYS_VENDOR
|
||||
default "gdsys"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "strider"
|
||||
|
||||
config GDSYS_LEGACY_OSD_CMDS
|
||||
default y
|
||||
|
||||
config GDSYS_LEGACY_DRIVERS
|
||||
default y
|
||||
|
||||
endif
|
||||
|
||||
if TARGET_GAZERBEAM
|
||||
|
||||
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
|
||||
endif
|
||||
|
||||
if TARGET_HRCON || TARGET_STRIDER || TARGET_GAZERBEAM
|
||||
|
||||
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
|
||||
@@ -0,0 +1,14 @@
|
||||
MPC8308 BOARD
|
||||
M: Dirk Eibach <dirk.eibach@gdsys.cc>
|
||||
S: Maintained
|
||||
F: board/gdsys/mpc8308/
|
||||
F: include/configs/hrcon.h
|
||||
F: configs/hrcon_defconfig
|
||||
F: configs/hrcon_dh_defconfig
|
||||
F: include/configs/strider.h
|
||||
F: configs/strider_defconfig
|
||||
F: configs/strider_cpu_defconfig
|
||||
F: configs/strider_cpu_dp_defconfig
|
||||
F: configs/strider_con_defconfig
|
||||
F: configs/strider_con_dp_defconfig
|
||||
F: configs/gazerbeam_defconfig
|
||||
@@ -0,0 +1,9 @@
|
||||
# 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_HRCON) += hrcon.o
|
||||
obj-$(CONFIG_TARGET_STRIDER) += strider.o
|
||||
obj-$(CONFIG_TARGET_GAZERBEAM) += gazerbeam.o
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* (C) Copyright 2015
|
||||
* Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <board.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 <tpm-v1.h>
|
||||
#include <video_osd.h>
|
||||
|
||||
#include "../common/ihs_mdio.h"
|
||||
#include "../../../drivers/board/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 *board;
|
||||
struct udevice *serdes;
|
||||
int mc = 0;
|
||||
int con = 0;
|
||||
|
||||
if (board_get(&board))
|
||||
puts("Could not find board information device.\n");
|
||||
|
||||
/* Initialize serdes */
|
||||
uclass_get_device_by_phandle(UCLASS_MISC, board, "serdes", &serdes);
|
||||
|
||||
if (board_detect(board))
|
||||
puts("Device information detection failed.\n");
|
||||
|
||||
board_get_int(board, BOARD_MULTICHANNEL, &mc);
|
||||
board_get_int(board, 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 checkboard(void)
|
||||
{
|
||||
struct udevice *board;
|
||||
char *s = env_get("serial#");
|
||||
int mc = 0;
|
||||
int con = 0;
|
||||
|
||||
if (board_get(&board))
|
||||
puts("Could not find board information device.\n");
|
||||
|
||||
board_get_int(board, BOARD_MULTICHANNEL, &mc);
|
||||
board_get_int(board, 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 *board;
|
||||
struct udevice *osd;
|
||||
struct video_osd_info osd_info;
|
||||
struct udevice *tpm;
|
||||
int ret;
|
||||
|
||||
if (board_get(&board))
|
||||
puts("Could not find board information device.\n");
|
||||
|
||||
if (board) {
|
||||
int res = board_get_int(board, 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) || tpm_startup(tpm, TPM_ST_CLEAR) ||
|
||||
tpm_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, board, 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, bd_t *bd)
|
||||
{
|
||||
ft_cpu_setup(blob, bd);
|
||||
fsl_fdt_fixup_dr_usb(blob, bd);
|
||||
fdt_fixup_esdhc(blob, bd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,501 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2014
|
||||
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <env.h>
|
||||
#include <hwconfig.h>
|
||||
#include <i2c.h>
|
||||
#include <init.h>
|
||||
#include <spi.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <fdt_support.h>
|
||||
#include <pci.h>
|
||||
#include <mpc83xx.h>
|
||||
#include <fsl_esdhc.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/fsl_serdes.h>
|
||||
#include <asm/fsl_mpc83xx_serdes.h>
|
||||
|
||||
#include "mpc8308.h"
|
||||
|
||||
#include <gdsys_fpga.h>
|
||||
|
||||
#include "../common/ioep-fpga.h"
|
||||
#include "../common/osd.h"
|
||||
#include "../common/mclink.h"
|
||||
#include "../common/phy.h"
|
||||
#include "../common/fanctrl.h"
|
||||
|
||||
#include <pca953x.h>
|
||||
#include <pca9698.h>
|
||||
|
||||
#include <miiphy.h>
|
||||
|
||||
#define MAX_MUX_CHANNELS 2
|
||||
|
||||
enum {
|
||||
MCFPGA_DONE = BIT(0),
|
||||
MCFPGA_INIT_N = BIT(1),
|
||||
MCFPGA_PROGRAM_N = BIT(2),
|
||||
MCFPGA_UPDATE_ENABLE_N = BIT(3),
|
||||
MCFPGA_RESET_N = BIT(4),
|
||||
};
|
||||
|
||||
enum {
|
||||
GPIO_MDC = 1 << 14,
|
||||
GPIO_MDIO = 1 << 15,
|
||||
};
|
||||
|
||||
uint mclink_fpgacount;
|
||||
struct ihs_fpga *fpga_ptr[] = CONFIG_SYS_FPGA_PTR;
|
||||
|
||||
struct {
|
||||
u8 bus;
|
||||
u8 addr;
|
||||
} hrcon_fans[] = CONFIG_HRCON_FANS;
|
||||
|
||||
int fpga_set_reg(u32 fpga, u16 *reg, off_t regoff, u16 data)
|
||||
{
|
||||
int res;
|
||||
|
||||
switch (fpga) {
|
||||
case 0:
|
||||
out_le16(reg, data);
|
||||
break;
|
||||
default:
|
||||
res = mclink_send(fpga - 1, regoff, data);
|
||||
if (res < 0) {
|
||||
printf("mclink_send reg %02lx data %04x returned %d\n",
|
||||
regoff, data, res);
|
||||
return res;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fpga_get_reg(u32 fpga, u16 *reg, off_t regoff, u16 *data)
|
||||
{
|
||||
int res;
|
||||
|
||||
switch (fpga) {
|
||||
case 0:
|
||||
*data = in_le16(reg);
|
||||
break;
|
||||
default:
|
||||
if (fpga > mclink_fpgacount)
|
||||
return -EINVAL;
|
||||
res = mclink_receive(fpga - 1, regoff, data);
|
||||
if (res < 0) {
|
||||
printf("mclink_receive reg %02lx returned %d\n",
|
||||
regoff, res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int checkboard(void)
|
||||
{
|
||||
char *s = env_get("serial#");
|
||||
bool hw_type_cat = pca9698_get_value(0x20, 20);
|
||||
|
||||
puts("Board: ");
|
||||
|
||||
printf("HRCon %s", hw_type_cat ? "CAT" : "Fiber");
|
||||
|
||||
if (s) {
|
||||
puts(", serial# ");
|
||||
puts(s);
|
||||
}
|
||||
|
||||
puts("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int last_stage_init(void)
|
||||
{
|
||||
int slaves;
|
||||
uint k;
|
||||
uchar mclink_controllers[] = { 0x3c, 0x3d, 0x3e };
|
||||
u16 fpga_features;
|
||||
bool hw_type_cat = pca9698_get_value(0x20, 20);
|
||||
bool ch0_rgmii2_present;
|
||||
|
||||
FPGA_GET_REG(0, fpga_features, &fpga_features);
|
||||
|
||||
/* Turn on Parade DP501 */
|
||||
pca9698_direction_output(0x20, 10, 1);
|
||||
pca9698_direction_output(0x20, 11, 1);
|
||||
|
||||
ch0_rgmii2_present = !pca9698_get_value(0x20, 30);
|
||||
|
||||
/* wait for FPGA done, then reset FPGA */
|
||||
for (k = 0; k < ARRAY_SIZE(mclink_controllers); ++k) {
|
||||
uint ctr = 0;
|
||||
|
||||
if (i2c_probe(mclink_controllers[k]))
|
||||
continue;
|
||||
|
||||
while (!(pca953x_get_val(mclink_controllers[k])
|
||||
& MCFPGA_DONE)) {
|
||||
mdelay(100);
|
||||
if (ctr++ > 5) {
|
||||
printf("no done for mclink_controller %u\n", k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pca953x_set_dir(mclink_controllers[k], MCFPGA_RESET_N, 0);
|
||||
pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N, 0);
|
||||
udelay(10);
|
||||
pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N,
|
||||
MCFPGA_RESET_N);
|
||||
}
|
||||
|
||||
if (hw_type_cat) {
|
||||
uint mux_ch;
|
||||
int retval;
|
||||
struct mii_dev *mdiodev = mdio_alloc();
|
||||
|
||||
if (!mdiodev)
|
||||
return -ENOMEM;
|
||||
strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN);
|
||||
mdiodev->read = bb_miiphy_read;
|
||||
mdiodev->write = bb_miiphy_write;
|
||||
|
||||
retval = mdio_register(mdiodev);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
|
||||
if ((mux_ch == 1) && !ch0_rgmii2_present)
|
||||
continue;
|
||||
|
||||
setup_88e1514(bb_miiphy_buses[0].name, mux_ch);
|
||||
}
|
||||
}
|
||||
|
||||
/* give slave-PLLs and Parade DP501 some time to be up and running */
|
||||
mdelay(500);
|
||||
|
||||
mclink_fpgacount = CONFIG_SYS_MCLINK_MAX;
|
||||
slaves = mclink_probe();
|
||||
mclink_fpgacount = 0;
|
||||
|
||||
ioep_fpga_print_info(0);
|
||||
osd_probe(0);
|
||||
#ifdef CONFIG_SYS_OSD_DH
|
||||
osd_probe(4);
|
||||
#endif
|
||||
|
||||
if (slaves <= 0)
|
||||
return 0;
|
||||
|
||||
mclink_fpgacount = slaves;
|
||||
|
||||
for (k = 1; k <= slaves; ++k) {
|
||||
FPGA_GET_REG(k, fpga_features, &fpga_features);
|
||||
|
||||
ioep_fpga_print_info(k);
|
||||
osd_probe(k);
|
||||
#ifdef CONFIG_SYS_OSD_DH
|
||||
osd_probe(k + 4);
|
||||
#endif
|
||||
if (hw_type_cat) {
|
||||
int retval;
|
||||
struct mii_dev *mdiodev = mdio_alloc();
|
||||
|
||||
if (!mdiodev)
|
||||
return -ENOMEM;
|
||||
strncpy(mdiodev->name, bb_miiphy_buses[k].name,
|
||||
MDIO_NAME_LEN);
|
||||
mdiodev->read = bb_miiphy_read;
|
||||
mdiodev->write = bb_miiphy_write;
|
||||
|
||||
retval = mdio_register(mdiodev);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
setup_88e1514(bb_miiphy_buses[k].name, 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (k = 0; k < ARRAY_SIZE(hrcon_fans); ++k) {
|
||||
i2c_set_bus_num(hrcon_fans[k].bus);
|
||||
init_fan_controller(hrcon_fans[k].addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* provide access to fpga gpios and controls (for I2C bitbang)
|
||||
* (these may look all too simple but make iocon.h much more readable)
|
||||
*/
|
||||
void fpga_gpio_set(uint bus, int pin)
|
||||
{
|
||||
FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, gpio.set, pin);
|
||||
}
|
||||
|
||||
void fpga_gpio_clear(uint bus, int pin)
|
||||
{
|
||||
FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, gpio.clear, pin);
|
||||
}
|
||||
|
||||
int fpga_gpio_get(uint bus, int pin)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
FPGA_GET_REG(bus >= 4 ? (bus - 4) : bus, gpio.read, &val);
|
||||
|
||||
return val & pin;
|
||||
}
|
||||
|
||||
void fpga_control_set(uint bus, int pin)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
FPGA_GET_REG(bus >= 4 ? (bus - 4) : bus, control, &val);
|
||||
FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, control, val | pin);
|
||||
}
|
||||
|
||||
void fpga_control_clear(uint bus, int pin)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
FPGA_GET_REG(bus >= 4 ? (bus - 4) : bus, control, &val);
|
||||
FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, control, val & ~pin);
|
||||
}
|
||||
|
||||
void mpc8308_init(void)
|
||||
{
|
||||
pca9698_direction_output(0x20, 4, 1);
|
||||
}
|
||||
|
||||
void mpc8308_set_fpga_reset(uint state)
|
||||
{
|
||||
pca9698_set_value(0x20, 4, state ? 0 : 1);
|
||||
}
|
||||
|
||||
void mpc8308_setup_hw(void)
|
||||
{
|
||||
immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
|
||||
|
||||
/*
|
||||
* set "startup-finished"-gpios
|
||||
*/
|
||||
setbits_be32(&immr->gpio[0].dir, BIT(31 - 11) | BIT(31 - 12));
|
||||
setbits_gpio0_out(BIT(31 - 12));
|
||||
}
|
||||
|
||||
int mpc8308_get_fpga_done(uint fpga)
|
||||
{
|
||||
return pca9698_get_value(0x20, 19);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FSL_ESDHC
|
||||
int board_mmc_init(bd_t *bd)
|
||||
{
|
||||
immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
|
||||
sysconf83xx_t *sysconf = &immr->sysconf;
|
||||
|
||||
/* Enable cache snooping in eSDHC system configuration register */
|
||||
out_be32(&sysconf->sdhccr, 0x02000000);
|
||||
|
||||
return fsl_esdhc_mmc_init(bd);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct pci_region pcie_regions_0[] = {
|
||||
{
|
||||
.bus_start = CONFIG_SYS_PCIE1_MEM_BASE,
|
||||
.phys_start = CONFIG_SYS_PCIE1_MEM_PHYS,
|
||||
.size = CONFIG_SYS_PCIE1_MEM_SIZE,
|
||||
.flags = PCI_REGION_MEM,
|
||||
},
|
||||
{
|
||||
.bus_start = CONFIG_SYS_PCIE1_IO_BASE,
|
||||
.phys_start = CONFIG_SYS_PCIE1_IO_PHYS,
|
||||
.size = CONFIG_SYS_PCIE1_IO_SIZE,
|
||||
.flags = PCI_REGION_IO,
|
||||
},
|
||||
};
|
||||
|
||||
void pci_init_board(void)
|
||||
{
|
||||
immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
|
||||
sysconf83xx_t *sysconf = &immr->sysconf;
|
||||
law83xx_t *pcie_law = sysconf->pcielaw;
|
||||
struct pci_region *pcie_reg[] = { pcie_regions_0 };
|
||||
|
||||
fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_PEX,
|
||||
FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
|
||||
|
||||
/* Deassert the resets in the control register */
|
||||
out_be32(&sysconf->pecr1, 0xE0008000);
|
||||
udelay(2000);
|
||||
|
||||
/* Configure PCI Express Local Access Windows */
|
||||
out_be32(&pcie_law[0].bar, CONFIG_SYS_PCIE1_BASE & LAWBAR_BAR);
|
||||
out_be32(&pcie_law[0].ar, LBLAWAR_EN | LBLAWAR_512MB);
|
||||
|
||||
mpc83xx_pcie_init(1, pcie_reg);
|
||||
}
|
||||
|
||||
ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
|
||||
{
|
||||
info->portwidth = FLASH_CFI_16BIT;
|
||||
info->chipwidth = FLASH_CFI_BY16;
|
||||
info->interface = FLASH_CFI_X16;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF_BOARD_SETUP)
|
||||
int ft_board_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
ft_cpu_setup(blob, bd);
|
||||
fsl_fdt_fixup_dr_usb(blob, bd);
|
||||
fdt_fixup_esdhc(blob, bd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FPGA MII bitbang implementation
|
||||
*/
|
||||
|
||||
struct fpga_mii {
|
||||
uint fpga;
|
||||
int mdio;
|
||||
} fpga_mii[] = {
|
||||
{ 0, 1},
|
||||
{ 1, 1},
|
||||
{ 2, 1},
|
||||
{ 3, 1},
|
||||
};
|
||||
|
||||
static int mii_dummy_init(struct bb_miiphy_bus *bus)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_mdio_active(struct bb_miiphy_bus *bus)
|
||||
{
|
||||
struct fpga_mii *fpga_mii = bus->priv;
|
||||
|
||||
if (fpga_mii->mdio)
|
||||
FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
|
||||
else
|
||||
FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_mdio_tristate(struct bb_miiphy_bus *bus)
|
||||
{
|
||||
struct fpga_mii *fpga_mii = bus->priv;
|
||||
|
||||
FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_set_mdio(struct bb_miiphy_bus *bus, int v)
|
||||
{
|
||||
struct fpga_mii *fpga_mii = bus->priv;
|
||||
|
||||
if (v)
|
||||
FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
|
||||
else
|
||||
FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
|
||||
|
||||
fpga_mii->mdio = v;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v)
|
||||
{
|
||||
u16 gpio;
|
||||
struct fpga_mii *fpga_mii = bus->priv;
|
||||
|
||||
FPGA_GET_REG(fpga_mii->fpga, gpio.read, &gpio);
|
||||
|
||||
*v = ((gpio & GPIO_MDIO) != 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_set_mdc(struct bb_miiphy_bus *bus, int v)
|
||||
{
|
||||
struct fpga_mii *fpga_mii = bus->priv;
|
||||
|
||||
if (v)
|
||||
FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDC);
|
||||
else
|
||||
FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_delay(struct bb_miiphy_bus *bus)
|
||||
{
|
||||
udelay(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bb_miiphy_bus bb_miiphy_buses[] = {
|
||||
{
|
||||
.name = "board0",
|
||||
.init = mii_dummy_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 = &fpga_mii[0],
|
||||
},
|
||||
{
|
||||
.name = "board1",
|
||||
.init = mii_dummy_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 = &fpga_mii[1],
|
||||
},
|
||||
{
|
||||
.name = "board2",
|
||||
.init = mii_dummy_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 = &fpga_mii[2],
|
||||
},
|
||||
{
|
||||
.name = "board3",
|
||||
.init = mii_dummy_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 = &fpga_mii[3],
|
||||
},
|
||||
};
|
||||
|
||||
int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses);
|
||||
@@ -0,0 +1,121 @@
|
||||
// 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 "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
|
||||
@@ -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_ */
|
||||
@@ -0,0 +1,87 @@
|
||||
// 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 <mpc83xx.h>
|
||||
#include <spd_sdram.h>
|
||||
|
||||
#include <asm/bitops.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 */
|
||||
@@ -0,0 +1,556 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2014
|
||||
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <env.h>
|
||||
#include <hwconfig.h>
|
||||
#include <i2c.h>
|
||||
#include <init.h>
|
||||
#include <spi.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <fdt_support.h>
|
||||
#include <pci.h>
|
||||
#include <mpc83xx.h>
|
||||
#include <fsl_esdhc.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/fsl_serdes.h>
|
||||
#include <asm/fsl_mpc83xx_serdes.h>
|
||||
|
||||
#include "mpc8308.h"
|
||||
|
||||
#include <gdsys_fpga.h>
|
||||
|
||||
#include "../common/adv7611.h"
|
||||
#include "../common/ch7301.h"
|
||||
#include "../common/dp501.h"
|
||||
#include "../common/ioep-fpga.h"
|
||||
#include "../common/mclink.h"
|
||||
#include "../common/osd.h"
|
||||
#include "../common/phy.h"
|
||||
#include "../common/fanctrl.h"
|
||||
|
||||
#include <pca953x.h>
|
||||
#include <pca9698.h>
|
||||
|
||||
#include <miiphy.h>
|
||||
|
||||
#define MAX_MUX_CHANNELS 2
|
||||
|
||||
enum {
|
||||
MCFPGA_DONE = 1 << 0,
|
||||
MCFPGA_INIT_N = 1 << 1,
|
||||
MCFPGA_PROGRAM_N = 1 << 2,
|
||||
MCFPGA_UPDATE_ENABLE_N = 1 << 3,
|
||||
MCFPGA_RESET_N = 1 << 4,
|
||||
};
|
||||
|
||||
enum {
|
||||
GPIO_MDC = 1 << 14,
|
||||
GPIO_MDIO = 1 << 15,
|
||||
};
|
||||
|
||||
uint mclink_fpgacount;
|
||||
struct ihs_fpga *fpga_ptr[] = CONFIG_SYS_FPGA_PTR;
|
||||
|
||||
struct {
|
||||
u8 bus;
|
||||
u8 addr;
|
||||
} strider_fans[] = CONFIG_STRIDER_FANS;
|
||||
|
||||
int fpga_set_reg(u32 fpga, u16 *reg, off_t regoff, u16 data)
|
||||
{
|
||||
int res;
|
||||
|
||||
switch (fpga) {
|
||||
case 0:
|
||||
out_le16(reg, data);
|
||||
break;
|
||||
default:
|
||||
res = mclink_send(fpga - 1, regoff, data);
|
||||
if (res < 0) {
|
||||
printf("mclink_send reg %02lx data %04x returned %d\n",
|
||||
regoff, data, res);
|
||||
return res;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fpga_get_reg(u32 fpga, u16 *reg, off_t regoff, u16 *data)
|
||||
{
|
||||
int res;
|
||||
|
||||
switch (fpga) {
|
||||
case 0:
|
||||
*data = in_le16(reg);
|
||||
break;
|
||||
default:
|
||||
if (fpga > mclink_fpgacount)
|
||||
return -EINVAL;
|
||||
res = mclink_receive(fpga - 1, regoff, data);
|
||||
if (res < 0) {
|
||||
printf("mclink_receive reg %02lx returned %d\n",
|
||||
regoff, res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int checkboard(void)
|
||||
{
|
||||
char *s = env_get("serial#");
|
||||
bool hw_type_cat = pca9698_get_value(0x20, 18);
|
||||
|
||||
puts("Board: ");
|
||||
|
||||
printf("Strider %s", hw_type_cat ? "CAT" : "Fiber");
|
||||
|
||||
if (s) {
|
||||
puts(", serial# ");
|
||||
puts(s);
|
||||
}
|
||||
|
||||
puts("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int last_stage_init(void)
|
||||
{
|
||||
int slaves;
|
||||
uint k;
|
||||
uint mux_ch;
|
||||
uchar mclink_controllers_dvi[] = { 0x3c, 0x3d, 0x3e };
|
||||
#ifdef CONFIG_STRIDER_CPU
|
||||
uchar mclink_controllers_dp[] = { 0x24, 0x25, 0x26 };
|
||||
#endif
|
||||
bool hw_type_cat = pca9698_get_value(0x20, 18);
|
||||
#ifdef CONFIG_STRIDER_CON_DP
|
||||
bool is_dh = pca9698_get_value(0x20, 25);
|
||||
#endif
|
||||
bool ch0_sgmii2_present;
|
||||
|
||||
/* Turn on Analog Devices ADV7611 */
|
||||
pca9698_direction_output(0x20, 8, 0);
|
||||
|
||||
/* Turn on Parade DP501 */
|
||||
pca9698_direction_output(0x20, 10, 1);
|
||||
pca9698_direction_output(0x20, 11, 1);
|
||||
|
||||
ch0_sgmii2_present = !pca9698_get_value(0x20, 37);
|
||||
|
||||
/* wait for FPGA done, then reset FPGA */
|
||||
for (k = 0; k < ARRAY_SIZE(mclink_controllers_dvi); ++k) {
|
||||
uint ctr = 0;
|
||||
uchar *mclink_controllers = mclink_controllers_dvi;
|
||||
|
||||
#ifdef CONFIG_STRIDER_CPU
|
||||
if (i2c_probe(mclink_controllers[k])) {
|
||||
mclink_controllers = mclink_controllers_dp;
|
||||
if (i2c_probe(mclink_controllers[k]))
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
if (i2c_probe(mclink_controllers[k]))
|
||||
continue;
|
||||
#endif
|
||||
while (!(pca953x_get_val(mclink_controllers[k])
|
||||
& MCFPGA_DONE)) {
|
||||
mdelay(100);
|
||||
if (ctr++ > 5) {
|
||||
printf("no done for mclink_controller %d\n", k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pca953x_set_dir(mclink_controllers[k], MCFPGA_RESET_N, 0);
|
||||
pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N, 0);
|
||||
udelay(10);
|
||||
pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N,
|
||||
MCFPGA_RESET_N);
|
||||
}
|
||||
|
||||
if (hw_type_cat) {
|
||||
int retval;
|
||||
struct mii_dev *mdiodev = mdio_alloc();
|
||||
|
||||
if (!mdiodev)
|
||||
return -ENOMEM;
|
||||
strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN);
|
||||
mdiodev->read = bb_miiphy_read;
|
||||
mdiodev->write = bb_miiphy_write;
|
||||
|
||||
retval = mdio_register(mdiodev);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
|
||||
if ((mux_ch == 1) && !ch0_sgmii2_present)
|
||||
continue;
|
||||
|
||||
setup_88e1514(bb_miiphy_buses[0].name, mux_ch);
|
||||
}
|
||||
}
|
||||
|
||||
/* give slave-PLLs and Parade DP501 some time to be up and running */
|
||||
mdelay(500);
|
||||
|
||||
mclink_fpgacount = CONFIG_SYS_MCLINK_MAX;
|
||||
slaves = mclink_probe();
|
||||
mclink_fpgacount = 0;
|
||||
|
||||
ioep_fpga_print_info(0);
|
||||
|
||||
if (!adv7611_probe(0))
|
||||
printf(" Advantiv ADV7611 HDMI Receiver\n");
|
||||
|
||||
#ifdef CONFIG_STRIDER_CON
|
||||
if (ioep_fpga_has_osd(0))
|
||||
osd_probe(0);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STRIDER_CON_DP
|
||||
if (ioep_fpga_has_osd(0)) {
|
||||
osd_probe(0);
|
||||
if (is_dh)
|
||||
osd_probe(4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STRIDER_CPU
|
||||
ch7301_probe(0, false);
|
||||
dp501_probe(0, false);
|
||||
#endif
|
||||
|
||||
if (slaves <= 0)
|
||||
return 0;
|
||||
|
||||
mclink_fpgacount = slaves;
|
||||
|
||||
#ifdef CONFIG_STRIDER_CPU
|
||||
/* get ADV7611 out of reset, power up DP501, give some time to wakeup */
|
||||
for (k = 1; k <= slaves; ++k)
|
||||
FPGA_SET_REG(k, extended_control, 0x10); /* enable video */
|
||||
|
||||
mdelay(500);
|
||||
#endif
|
||||
|
||||
for (k = 1; k <= slaves; ++k) {
|
||||
ioep_fpga_print_info(k);
|
||||
#ifdef CONFIG_STRIDER_CON
|
||||
if (ioep_fpga_has_osd(k))
|
||||
osd_probe(k);
|
||||
#endif
|
||||
#ifdef CONFIG_STRIDER_CON_DP
|
||||
if (ioep_fpga_has_osd(k)) {
|
||||
osd_probe(k);
|
||||
if (is_dh)
|
||||
osd_probe(k + 4);
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_STRIDER_CPU
|
||||
if (!adv7611_probe(k))
|
||||
printf(" Advantiv ADV7611 HDMI Receiver\n");
|
||||
ch7301_probe(k, false);
|
||||
dp501_probe(k, false);
|
||||
#endif
|
||||
if (hw_type_cat) {
|
||||
int retval;
|
||||
struct mii_dev *mdiodev = mdio_alloc();
|
||||
|
||||
if (!mdiodev)
|
||||
return -ENOMEM;
|
||||
strncpy(mdiodev->name, bb_miiphy_buses[k].name,
|
||||
MDIO_NAME_LEN);
|
||||
mdiodev->read = bb_miiphy_read;
|
||||
mdiodev->write = bb_miiphy_write;
|
||||
|
||||
retval = mdio_register(mdiodev);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
setup_88e1514(bb_miiphy_buses[k].name, 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (k = 0; k < ARRAY_SIZE(strider_fans); ++k) {
|
||||
i2c_set_bus_num(strider_fans[k].bus);
|
||||
init_fan_controller(strider_fans[k].addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* provide access to fpga gpios (for I2C bitbang)
|
||||
* (these may look all too simple but make iocon.h much more readable)
|
||||
*/
|
||||
void fpga_gpio_set(uint bus, int pin)
|
||||
{
|
||||
FPGA_SET_REG(bus, gpio.set, pin);
|
||||
}
|
||||
|
||||
void fpga_gpio_clear(uint bus, int pin)
|
||||
{
|
||||
FPGA_SET_REG(bus, gpio.clear, pin);
|
||||
}
|
||||
|
||||
int fpga_gpio_get(uint bus, int pin)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
FPGA_GET_REG(bus, gpio.read, &val);
|
||||
|
||||
return val & pin;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_STRIDER_CON_DP
|
||||
void fpga_control_set(uint bus, int pin)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
FPGA_GET_REG(bus, control, &val);
|
||||
FPGA_SET_REG(bus, control, val | pin);
|
||||
}
|
||||
|
||||
void fpga_control_clear(uint bus, int pin)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
FPGA_GET_REG(bus, control, &val);
|
||||
FPGA_SET_REG(bus, control, val & ~pin);
|
||||
}
|
||||
#endif
|
||||
|
||||
void mpc8308_init(void)
|
||||
{
|
||||
pca9698_direction_output(0x20, 26, 1);
|
||||
}
|
||||
|
||||
void mpc8308_set_fpga_reset(uint state)
|
||||
{
|
||||
pca9698_set_value(0x20, 26, state ? 0 : 1);
|
||||
}
|
||||
|
||||
void mpc8308_setup_hw(void)
|
||||
{
|
||||
immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
|
||||
|
||||
/*
|
||||
* set "startup-finished"-gpios
|
||||
*/
|
||||
setbits_be32(&immr->gpio[0].dir, BIT(31 - 11) | BIT(31 - 12));
|
||||
setbits_gpio0_out(BIT(31 - 12));
|
||||
}
|
||||
|
||||
int mpc8308_get_fpga_done(uint fpga)
|
||||
{
|
||||
return pca9698_get_value(0x20, 20);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FSL_ESDHC
|
||||
int board_mmc_init(bd_t *bd)
|
||||
{
|
||||
immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
|
||||
sysconf83xx_t *sysconf = &immr->sysconf;
|
||||
|
||||
/* Enable cache snooping in eSDHC system configuration register */
|
||||
out_be32(&sysconf->sdhccr, 0x02000000);
|
||||
|
||||
return fsl_esdhc_mmc_init(bd);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct pci_region pcie_regions_0[] = {
|
||||
{
|
||||
.bus_start = CONFIG_SYS_PCIE1_MEM_BASE,
|
||||
.phys_start = CONFIG_SYS_PCIE1_MEM_PHYS,
|
||||
.size = CONFIG_SYS_PCIE1_MEM_SIZE,
|
||||
.flags = PCI_REGION_MEM,
|
||||
},
|
||||
{
|
||||
.bus_start = CONFIG_SYS_PCIE1_IO_BASE,
|
||||
.phys_start = CONFIG_SYS_PCIE1_IO_PHYS,
|
||||
.size = CONFIG_SYS_PCIE1_IO_SIZE,
|
||||
.flags = PCI_REGION_IO,
|
||||
},
|
||||
};
|
||||
|
||||
void pci_init_board(void)
|
||||
{
|
||||
immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
|
||||
sysconf83xx_t *sysconf = &immr->sysconf;
|
||||
law83xx_t *pcie_law = sysconf->pcielaw;
|
||||
struct pci_region *pcie_reg[] = { pcie_regions_0 };
|
||||
|
||||
fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_PEX,
|
||||
FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
|
||||
|
||||
/* Deassert the resets in the control register */
|
||||
out_be32(&sysconf->pecr1, 0xE0008000);
|
||||
udelay(2000);
|
||||
|
||||
/* Configure PCI Express Local Access Windows */
|
||||
out_be32(&pcie_law[0].bar, CONFIG_SYS_PCIE1_BASE & LAWBAR_BAR);
|
||||
out_be32(&pcie_law[0].ar, LBLAWAR_EN | LBLAWAR_512MB);
|
||||
|
||||
mpc83xx_pcie_init(1, pcie_reg);
|
||||
}
|
||||
|
||||
ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
|
||||
{
|
||||
info->portwidth = FLASH_CFI_16BIT;
|
||||
info->chipwidth = FLASH_CFI_BY16;
|
||||
info->interface = FLASH_CFI_X16;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF_BOARD_SETUP)
|
||||
int ft_board_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
ft_cpu_setup(blob, bd);
|
||||
fsl_fdt_fixup_dr_usb(blob, bd);
|
||||
fdt_fixup_esdhc(blob, bd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FPGA MII bitbang implementation
|
||||
*/
|
||||
|
||||
struct fpga_mii {
|
||||
uint fpga;
|
||||
int mdio;
|
||||
} fpga_mii[] = {
|
||||
{ 0, 1},
|
||||
{ 1, 1},
|
||||
{ 2, 1},
|
||||
{ 3, 1},
|
||||
};
|
||||
|
||||
static int mii_dummy_init(struct bb_miiphy_bus *bus)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_mdio_active(struct bb_miiphy_bus *bus)
|
||||
{
|
||||
struct fpga_mii *fpga_mii = bus->priv;
|
||||
|
||||
if (fpga_mii->mdio)
|
||||
FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
|
||||
else
|
||||
FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_mdio_tristate(struct bb_miiphy_bus *bus)
|
||||
{
|
||||
struct fpga_mii *fpga_mii = bus->priv;
|
||||
|
||||
FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_set_mdio(struct bb_miiphy_bus *bus, int v)
|
||||
{
|
||||
struct fpga_mii *fpga_mii = bus->priv;
|
||||
|
||||
if (v)
|
||||
FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
|
||||
else
|
||||
FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
|
||||
|
||||
fpga_mii->mdio = v;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v)
|
||||
{
|
||||
u16 gpio;
|
||||
struct fpga_mii *fpga_mii = bus->priv;
|
||||
|
||||
FPGA_GET_REG(fpga_mii->fpga, gpio.read, &gpio);
|
||||
|
||||
*v = ((gpio & GPIO_MDIO) != 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_set_mdc(struct bb_miiphy_bus *bus, int v)
|
||||
{
|
||||
struct fpga_mii *fpga_mii = bus->priv;
|
||||
|
||||
if (v)
|
||||
FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDC);
|
||||
else
|
||||
FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mii_delay(struct bb_miiphy_bus *bus)
|
||||
{
|
||||
udelay(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bb_miiphy_bus bb_miiphy_buses[] = {
|
||||
{
|
||||
.name = "board0",
|
||||
.init = mii_dummy_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 = &fpga_mii[0],
|
||||
},
|
||||
{
|
||||
.name = "board1",
|
||||
.init = mii_dummy_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 = &fpga_mii[1],
|
||||
},
|
||||
{
|
||||
.name = "board2",
|
||||
.init = mii_dummy_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 = &fpga_mii[2],
|
||||
},
|
||||
{
|
||||
.name = "board3",
|
||||
.init = mii_dummy_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 = &fpga_mii[3],
|
||||
},
|
||||
};
|
||||
|
||||
int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses);
|
||||
@@ -0,0 +1,22 @@
|
||||
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.
|
||||
|
||||
if TARGET_CONTROLCENTERD
|
||||
|
||||
config SYS_BOARD
|
||||
default "p1022"
|
||||
|
||||
config SYS_VENDOR
|
||||
default "gdsys"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "controlcenterd"
|
||||
|
||||
config GDSYS_LEGACY_DRIVERS
|
||||
default y
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,9 @@
|
||||
P1022 BOARD
|
||||
M: Dirk Eibach <dirk.eibach@gdsys.cc>
|
||||
S: Maintained
|
||||
F: board/gdsys/p1022/
|
||||
F: include/configs/controlcenterd.h
|
||||
F: configs/controlcenterd_36BIT_SDCARD_defconfig
|
||||
F: configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig
|
||||
F: configs/controlcenterd_TRAILBLAZER_defconfig
|
||||
F: configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig
|
||||
@@ -0,0 +1,10 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright 2010 Freescale Semiconductor, Inc.
|
||||
|
||||
obj-y += law.o
|
||||
obj-y += ddr.o
|
||||
obj-y += tlb.o
|
||||
obj-y += sdhc_boot.o
|
||||
obj-$(CONFIG_CONTROLCENTERD) += controlcenterd.o controlcenterd-id.o
|
||||
obj-$(CONFIG_FSL_DIU_FB) += diu.o
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2013
|
||||
* Reinhard Pfau, Guntermann & Drunck GmbH, reinhard.pfau@gdsys.cc
|
||||
*/
|
||||
|
||||
#ifndef __CONTROLCENTER_ID_H
|
||||
#define __CONTROLCENTER_ID_H
|
||||
|
||||
int ccdm_compute_self_hash(void);
|
||||
int startup_ccdm_id_module(void);
|
||||
|
||||
int show_self_hash(void);
|
||||
|
||||
#endif /* __CONTROLCENTER_ID_H */
|
||||
@@ -0,0 +1,428 @@
|
||||
/*
|
||||
* (C) Copyright 2013
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <env.h>
|
||||
#include <init.h>
|
||||
#include <pci.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/immap_85xx.h>
|
||||
#include <asm/fsl_pci.h>
|
||||
#include <fsl_ddr_sdram.h>
|
||||
#include <asm/fsl_serdes.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <fdt_support.h>
|
||||
#include <fsl_mdio.h>
|
||||
#include <tsec.h>
|
||||
#include <asm/fsl_law.h>
|
||||
#include <netdev.h>
|
||||
#include <i2c.h>
|
||||
#include <pca9698.h>
|
||||
#include <watchdog.h>
|
||||
#include "../common/dp501.h"
|
||||
#include "controlcenterd-id.h"
|
||||
|
||||
enum {
|
||||
HWVER_100 = 0,
|
||||
HWVER_110 = 1,
|
||||
HWVER_120 = 2,
|
||||
};
|
||||
|
||||
struct ihs_fpga {
|
||||
u32 reflection_low; /* 0x0000 */
|
||||
u32 versions; /* 0x0004 */
|
||||
u32 fpga_version; /* 0x0008 */
|
||||
u32 fpga_features; /* 0x000c */
|
||||
u32 reserved[4]; /* 0x0010 */
|
||||
u32 control; /* 0x0020 */
|
||||
};
|
||||
|
||||
#ifndef CONFIG_TRAILBLAZER
|
||||
static struct pci_device_id hydra_supported[] = {
|
||||
{ 0x6d5e, 0xcdc0 },
|
||||
{}
|
||||
};
|
||||
|
||||
static void hydra_initialize(void);
|
||||
#endif
|
||||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
|
||||
ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO3_ADDR);
|
||||
|
||||
/* Reset eLBC_DIU and SPI_eLBC in case we are booting from SD */
|
||||
clrsetbits_be32(&gur->pmuxcr, 0x00600000, 0x80000000);
|
||||
|
||||
/* Set pmuxcr to allow both i2c1 and i2c2 */
|
||||
setbits_be32(&gur->pmuxcr, 0x00001000);
|
||||
|
||||
/* Set pmuxcr to enable GPIO 3_11-3_13 */
|
||||
setbits_be32(&gur->pmuxcr, 0x00000010);
|
||||
|
||||
/* Set pmuxcr to enable GPIO 2_31,3_9+10 */
|
||||
setbits_be32(&gur->pmuxcr, 0x00000020);
|
||||
|
||||
/* Set pmuxcr to enable GPIO 2_28-2_30 */
|
||||
setbits_be32(&gur->pmuxcr, 0x000000c0);
|
||||
|
||||
/* Set pmuxcr to enable GPIO 3_20-3_22 */
|
||||
setbits_be32(&gur->pmuxcr2, 0x03000000);
|
||||
|
||||
/* Set pmuxcr to enable IRQ0-2 */
|
||||
clrbits_be32(&gur->pmuxcr, 0x00000300);
|
||||
|
||||
/* Set pmuxcr to disable IRQ3-11 */
|
||||
setbits_be32(&gur->pmuxcr, 0x000000F0);
|
||||
|
||||
/* Read back the register to synchronize the write. */
|
||||
in_be32(&gur->pmuxcr);
|
||||
|
||||
/* Set the pin muxing to enable ETSEC2. */
|
||||
clrbits_be32(&gur->pmuxcr2, 0x001F8000);
|
||||
|
||||
#ifdef CONFIG_TRAILBLAZER
|
||||
/*
|
||||
* GPIO3_10 SPERRTRIGGER
|
||||
*/
|
||||
setbits_be32(&pgpio->gpdir, 0x00200000);
|
||||
clrbits_be32(&pgpio->gpdat, 0x00200000);
|
||||
udelay(100);
|
||||
setbits_be32(&pgpio->gpdat, 0x00200000);
|
||||
udelay(100);
|
||||
clrbits_be32(&pgpio->gpdat, 0x00200000);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GPIO3_11 CPU-TO-FPGA-RESET#
|
||||
*/
|
||||
setbits_be32(&pgpio->gpdir, 0x00100000);
|
||||
clrbits_be32(&pgpio->gpdat, 0x00100000);
|
||||
|
||||
/*
|
||||
* GPIO3_21 CPU-STATUS-WATCHDOG-TRIGGER#
|
||||
*/
|
||||
setbits_be32(&pgpio->gpdir, 0x00000400);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int checkboard(void)
|
||||
{
|
||||
printf("Board: ControlCenter DIGITAL\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int misc_init_r(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* A list of PCI and SATA slots
|
||||
*/
|
||||
enum slot_id {
|
||||
SLOT_PCIE1 = 1,
|
||||
SLOT_PCIE2,
|
||||
SLOT_PCIE3,
|
||||
SLOT_PCIE4,
|
||||
SLOT_PCIE5,
|
||||
SLOT_SATA1,
|
||||
SLOT_SATA2
|
||||
};
|
||||
|
||||
/*
|
||||
* This array maps the slot identifiers to their names on the P1022DS board.
|
||||
*/
|
||||
static const char * const slot_names[] = {
|
||||
[SLOT_PCIE1] = "Slot 1",
|
||||
[SLOT_PCIE2] = "Slot 2",
|
||||
[SLOT_PCIE3] = "Slot 3",
|
||||
[SLOT_PCIE4] = "Slot 4",
|
||||
[SLOT_PCIE5] = "Mini-PCIe",
|
||||
[SLOT_SATA1] = "SATA 1",
|
||||
[SLOT_SATA2] = "SATA 2",
|
||||
};
|
||||
|
||||
/*
|
||||
* This array maps a given SERDES configuration and SERDES device to the PCI or
|
||||
* SATA slot that it connects to. This mapping is hard-coded in the FPGA.
|
||||
*/
|
||||
static u8 serdes_dev_slot[][SATA2 + 1] = {
|
||||
[0x01] = { [PCIE3] = SLOT_PCIE4, [PCIE2] = SLOT_PCIE5 },
|
||||
[0x02] = { [SATA1] = SLOT_SATA1, [SATA2] = SLOT_SATA2 },
|
||||
[0x09] = { [PCIE1] = SLOT_PCIE1, [PCIE3] = SLOT_PCIE4,
|
||||
[PCIE2] = SLOT_PCIE5 },
|
||||
[0x16] = { [PCIE1] = SLOT_PCIE1, [PCIE3] = SLOT_PCIE2,
|
||||
[PCIE2] = SLOT_PCIE3,
|
||||
[SATA1] = SLOT_SATA1, [SATA2] = SLOT_SATA2 },
|
||||
[0x17] = { [PCIE1] = SLOT_PCIE1, [PCIE3] = SLOT_PCIE2,
|
||||
[PCIE2] = SLOT_PCIE3 },
|
||||
[0x1a] = { [PCIE1] = SLOT_PCIE1, [PCIE2] = SLOT_PCIE3,
|
||||
[PCIE2] = SLOT_PCIE3,
|
||||
[SATA1] = SLOT_SATA1, [SATA2] = SLOT_SATA2 },
|
||||
[0x1c] = { [PCIE1] = SLOT_PCIE1,
|
||||
[SATA1] = SLOT_SATA1, [SATA2] = SLOT_SATA2 },
|
||||
[0x1e] = { [PCIE1] = SLOT_PCIE1, [PCIE3] = SLOT_PCIE3 },
|
||||
[0x1f] = { [PCIE1] = SLOT_PCIE1 },
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Returns the name of the slot to which the PCIe or SATA controller is
|
||||
* connected
|
||||
*/
|
||||
const char *board_serdes_name(enum srds_prtcl device)
|
||||
{
|
||||
ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
|
||||
u32 pordevsr = in_be32(&gur->pordevsr);
|
||||
unsigned int srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
|
||||
MPC85xx_PORDEVSR_IO_SEL_SHIFT;
|
||||
enum slot_id slot = serdes_dev_slot[srds_cfg][device];
|
||||
const char *name = slot_names[slot];
|
||||
|
||||
if (name)
|
||||
return name;
|
||||
else
|
||||
return "Nothing";
|
||||
}
|
||||
|
||||
void hw_watchdog_reset(void)
|
||||
{
|
||||
ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO3_ADDR);
|
||||
|
||||
clrbits_be32(&pgpio->gpdat, 0x00000400);
|
||||
setbits_be32(&pgpio->gpdat, 0x00000400);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TRAILBLAZER
|
||||
int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
return run_command(env_get("bootcmd"), flag);
|
||||
}
|
||||
|
||||
int board_early_init_r(void)
|
||||
{
|
||||
ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO3_ADDR);
|
||||
|
||||
/*
|
||||
* GPIO3_12 PPC_SYSTEMREADY#
|
||||
*/
|
||||
setbits_be32(&pgpio->gpdir, 0x00080000);
|
||||
setbits_be32(&pgpio->gpodr, 0x00080000);
|
||||
clrbits_be32(&pgpio->gpdat, 0x00080000);
|
||||
|
||||
return ccdm_compute_self_hash();
|
||||
}
|
||||
|
||||
int last_stage_init(void)
|
||||
{
|
||||
startup_ccdm_id_module();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
void pci_init_board(void)
|
||||
{
|
||||
fsl_pcie_init_board(0);
|
||||
|
||||
hydra_initialize();
|
||||
}
|
||||
|
||||
int board_early_init_r(void)
|
||||
{
|
||||
unsigned int k = 0;
|
||||
ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO3_ADDR);
|
||||
|
||||
/* wait for FPGA configuration to finish */
|
||||
while (!pca9698_get_value(0x22, 11) && (k++ < 30))
|
||||
udelay(100000);
|
||||
|
||||
if (k > 30) {
|
||||
puts("FPGA configuration timed out.\n");
|
||||
} else {
|
||||
/* clear FPGA reset */
|
||||
udelay(1000);
|
||||
setbits_be32(&pgpio->gpdat, 0x00100000);
|
||||
}
|
||||
|
||||
/* give time for PCIe link training */
|
||||
udelay(100000);
|
||||
|
||||
/*
|
||||
* GPIO3_12 PPC_SYSTEMREADY#
|
||||
*/
|
||||
setbits_be32(&pgpio->gpdir, 0x00080000);
|
||||
setbits_be32(&pgpio->gpodr, 0x00080000);
|
||||
clrbits_be32(&pgpio->gpdat, 0x00080000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int last_stage_init(void)
|
||||
{
|
||||
/* Turn on Parade DP501 */
|
||||
pca9698_direction_output(0x22, 7, 1);
|
||||
udelay(500000);
|
||||
|
||||
dp501_powerup(0x08);
|
||||
|
||||
startup_ccdm_id_module();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize on-board and/or PCI Ethernet devices
|
||||
*
|
||||
* Returns:
|
||||
* <0, error
|
||||
* 0, no ethernet devices found
|
||||
* >0, number of ethernet devices initialized
|
||||
*/
|
||||
int board_eth_init(bd_t *bis)
|
||||
{
|
||||
struct fsl_pq_mdio_info mdio_info;
|
||||
struct tsec_info_struct tsec_info[2];
|
||||
unsigned int num = 0;
|
||||
|
||||
#ifdef CONFIG_TSEC1
|
||||
SET_STD_TSEC_INFO(tsec_info[num], 1);
|
||||
num++;
|
||||
#endif
|
||||
#ifdef CONFIG_TSEC2
|
||||
SET_STD_TSEC_INFO(tsec_info[num], 2);
|
||||
num++;
|
||||
#endif
|
||||
|
||||
mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR;
|
||||
mdio_info.name = DEFAULT_MII_NAME;
|
||||
fsl_pq_mdio_init(bis, &mdio_info);
|
||||
|
||||
return tsec_eth_init(bis, tsec_info, num) + pci_eth_init(bis);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF_BOARD_SETUP
|
||||
int ft_board_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
phys_addr_t base;
|
||||
phys_size_t size;
|
||||
|
||||
ft_cpu_setup(blob, bd);
|
||||
|
||||
base = env_get_bootm_low();
|
||||
size = env_get_bootm_size();
|
||||
|
||||
fdt_fixup_memory(blob, (u64)base, (u64)size);
|
||||
|
||||
#ifdef CONFIG_HAS_FSL_DR_USB
|
||||
fsl_fdt_fixup_dr_usb(blob, bd);
|
||||
#endif
|
||||
|
||||
FT_FSL_PCI_SETUP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void hydra_initialize(void)
|
||||
{
|
||||
unsigned int 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;
|
||||
struct ihs_fpga *fpga;
|
||||
u32 versions;
|
||||
u32 fpga_version;
|
||||
u32 fpga_features;
|
||||
|
||||
unsigned hardware_version;
|
||||
unsigned feature_uart_channels;
|
||||
unsigned feature_sb_channels;
|
||||
|
||||
/* 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);
|
||||
|
||||
/* disable sideband clocks */
|
||||
writel(1, &fpga->control);
|
||||
|
||||
versions = readl(&fpga->versions);
|
||||
fpga_version = readl(&fpga->fpga_version);
|
||||
fpga_features = readl(&fpga->fpga_features);
|
||||
|
||||
hardware_version = versions & 0xf;
|
||||
feature_uart_channels = (fpga_features >> 6) & 0x1f;
|
||||
feature_sb_channels = fpga_features & 0x1f;
|
||||
|
||||
printf("FPGA%d: ", i);
|
||||
|
||||
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, features:",
|
||||
fpga_version / 100, fpga_version % 100);
|
||||
|
||||
printf(" %d uart channel(s)", feature_uart_channels);
|
||||
printf(" %d sideband channel(s)\n", feature_sb_channels);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2010 Freescale Semiconductor, Inc.
|
||||
* Authors: Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
|
||||
* Timur Tabi <timur@freescale.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
|
||||
#include <fsl_ddr_sdram.h>
|
||||
#include <fsl_ddr_dimm_params.h>
|
||||
|
||||
void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm,
|
||||
unsigned int ctrl_num)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (ctrl_num) {
|
||||
printf("Wrong parameter for controller number %d", ctrl_num);
|
||||
return;
|
||||
}
|
||||
if (!pdimm->n_ranks)
|
||||
return;
|
||||
|
||||
/* set odt_rd_cfg and odt_wr_cfg. */
|
||||
for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
|
||||
popts->cs_local_opts[i].odt_rd_cfg = 0;
|
||||
popts->cs_local_opts[i].odt_wr_cfg = 1;
|
||||
}
|
||||
|
||||
popts->clk_adjust = 5;
|
||||
popts->cpo_override = 0x1f;
|
||||
popts->write_data_delay = 2;
|
||||
popts->half_strength_driver_enable = 1;
|
||||
|
||||
/* Per AN4039, enable ZQ calibration. */
|
||||
popts->zq_en = 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPD_EEPROM
|
||||
/*
|
||||
* we only have a "fake" SPD-EEPROM here, which has 16 bit addresses
|
||||
*/
|
||||
void get_spd(generic_spd_eeprom_t *spd, u8 i2c_address)
|
||||
{
|
||||
int ret = i2c_read(i2c_address, 0, 2, (uchar *)spd,
|
||||
sizeof(generic_spd_eeprom_t));
|
||||
|
||||
if (ret) {
|
||||
if (i2c_address ==
|
||||
#ifdef SPD_EEPROM_ADDRESS
|
||||
SPD_EEPROM_ADDRESS
|
||||
#elif defined(SPD_EEPROM_ADDRESS1)
|
||||
SPD_EEPROM_ADDRESS1
|
||||
#endif
|
||||
) {
|
||||
printf("DDR: failed to read SPD from address %u\n",
|
||||
i2c_address);
|
||||
} else {
|
||||
debug("DDR: failed to read SPD from address %u\n",
|
||||
i2c_address);
|
||||
}
|
||||
memset(spd, 0, sizeof(generic_spd_eeprom_t));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,83 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2010-2011 Freescale Semiconductor, Inc.
|
||||
* Authors: Timur Tabi <timur@freescale.com>
|
||||
*
|
||||
* FSL DIU Framebuffer driver
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <asm/io.h>
|
||||
#include <stdio_dev.h>
|
||||
#include <video_fb.h>
|
||||
#include <fsl_diu_fb.h>
|
||||
|
||||
#define PMUXCR_ELBCDIU_MASK 0xc0000000
|
||||
#define PMUXCR_ELBCDIU_NOR16 0x80000000
|
||||
#define PMUXCR_ELBCDIU_DIU 0x40000000
|
||||
|
||||
/*
|
||||
* DIU Area Descriptor
|
||||
*
|
||||
* Note that we need to byte-swap the value before it's written to the AD
|
||||
* register. So even though the registers don't look like they're in the same
|
||||
* bit positions as they are on the MPC8610, the same value is written to the
|
||||
* AD register on the MPC8610 and on the P1022.
|
||||
*/
|
||||
#define AD_BYTE_F 0x10000000
|
||||
#define AD_ALPHA_C_SHIFT 25
|
||||
#define AD_BLUE_C_SHIFT 23
|
||||
#define AD_GREEN_C_SHIFT 21
|
||||
#define AD_RED_C_SHIFT 19
|
||||
#define AD_PIXEL_S_SHIFT 16
|
||||
#define AD_COMP_3_SHIFT 12
|
||||
#define AD_COMP_2_SHIFT 8
|
||||
#define AD_COMP_1_SHIFT 4
|
||||
#define AD_COMP_0_SHIFT 0
|
||||
|
||||
/*
|
||||
* Variables used by the DIU/LBC switching code. It's safe to makes these
|
||||
* global, because the DIU requires DDR, so we'll only run this code after
|
||||
* relocation.
|
||||
*/
|
||||
static u32 pmuxcr;
|
||||
|
||||
void diu_set_pixel_clock(unsigned int pixclock)
|
||||
{
|
||||
ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
|
||||
unsigned long speed_ccb, temp;
|
||||
u32 pixval;
|
||||
|
||||
speed_ccb = get_bus_freq(0);
|
||||
temp = 1000000000 / pixclock;
|
||||
temp *= 1000;
|
||||
pixval = speed_ccb / temp;
|
||||
debug("DIU pixval = %u\n", pixval);
|
||||
|
||||
/* Modify PXCLK in GUTS CLKDVDR */
|
||||
temp = in_be32(&gur->clkdvdr) & 0x2000FFFF;
|
||||
out_be32(&gur->clkdvdr, temp); /* turn off clock */
|
||||
out_be32(&gur->clkdvdr, temp | 0x80000000 | ((pixval & 0x1F) << 16));
|
||||
}
|
||||
|
||||
int platform_diu_init(unsigned int xres, unsigned int yres, const char *port)
|
||||
{
|
||||
ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
|
||||
u32 pixel_format;
|
||||
|
||||
pixel_format = cpu_to_le32(AD_BYTE_F | (3 << AD_ALPHA_C_SHIFT) |
|
||||
(0 << AD_BLUE_C_SHIFT) | (1 << AD_GREEN_C_SHIFT) |
|
||||
(2 << AD_RED_C_SHIFT) | (8 << AD_COMP_3_SHIFT) |
|
||||
(8 << AD_COMP_2_SHIFT) | (8 << AD_COMP_1_SHIFT) |
|
||||
(8 << AD_COMP_0_SHIFT) | (3 << AD_PIXEL_S_SHIFT));
|
||||
|
||||
printf("DIU: Switching to %ux%u\n", xres, yres);
|
||||
|
||||
/* Set PMUXCR to switch the muxed pins from the LBC to the DIU */
|
||||
clrsetbits_be32(&gur->pmuxcr, PMUXCR_ELBCDIU_MASK, PMUXCR_ELBCDIU_DIU);
|
||||
pmuxcr = in_be32(&gur->pmuxcr);
|
||||
|
||||
return fsl_diu_init(xres, yres, pixel_format, 0);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2010 Freescale Semiconductor, Inc.
|
||||
* Authors: Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
|
||||
* Timur Tabi <timur@freescale.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/fsl_law.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
struct law_entry law_table[] = {
|
||||
SET_LAW(CONFIG_SYS_ELBC_BASE_PHYS, LAW_SIZE_1M, LAW_TRGT_IF_LBC),
|
||||
};
|
||||
|
||||
int num_law_entries = ARRAY_SIZE(law_table);
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2011 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <mmc.h>
|
||||
#include <malloc.h>
|
||||
|
||||
/*
|
||||
* The environment variables are written to just after the u-boot image
|
||||
* on SDCard, so we must read the MBR to get the start address and code
|
||||
* length of the u-boot image, then calculate the address of the env.
|
||||
*/
|
||||
#define ESDHC_BOOT_IMAGE_SIZE 0x48
|
||||
#define ESDHC_BOOT_IMAGE_ADDR 0x50
|
||||
|
||||
int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr)
|
||||
{
|
||||
u8 *tmp_buf;
|
||||
u32 blklen, code_offset, code_len, n;
|
||||
|
||||
blklen = mmc->read_bl_len;
|
||||
tmp_buf = malloc(blklen);
|
||||
if (!tmp_buf)
|
||||
return 1;
|
||||
|
||||
/* read out the first block, get the config data information */
|
||||
n = mmc->block_dev.block_read(&mmc->block_dev, 0, 1, tmp_buf);
|
||||
if (!n) {
|
||||
free(tmp_buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get the Source Address, from offset 0x50 */
|
||||
code_offset = *(u32 *)(tmp_buf + ESDHC_BOOT_IMAGE_ADDR);
|
||||
|
||||
/* Get the code size from offset 0x48 */
|
||||
code_len = *(u32 *)(tmp_buf + ESDHC_BOOT_IMAGE_SIZE);
|
||||
|
||||
*env_addr = code_offset + code_len;
|
||||
|
||||
free(tmp_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2010 Freescale Semiconductor, Inc.
|
||||
* Authors: Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
|
||||
* Timur Tabi <timur@freescale.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
struct fsl_e_tlb_entry tlb_table[] = {
|
||||
/* TLB 0 - for temp stack in cache */
|
||||
SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR, CONFIG_SYS_INIT_RAM_ADDR,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, 0,
|
||||
0, 0, BOOKE_PAGESZ_4K, 0),
|
||||
SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 4 * 1024,
|
||||
CONFIG_SYS_INIT_RAM_ADDR + 4 * 1024,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, 0,
|
||||
0, 0, BOOKE_PAGESZ_4K, 0),
|
||||
SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 8 * 1024,
|
||||
CONFIG_SYS_INIT_RAM_ADDR + 8 * 1024,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, 0,
|
||||
0, 0, BOOKE_PAGESZ_4K, 0),
|
||||
SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 12 * 1024,
|
||||
CONFIG_SYS_INIT_RAM_ADDR + 12 * 1024,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, 0,
|
||||
0, 0, BOOKE_PAGESZ_4K, 0),
|
||||
|
||||
/* TLB 1 */
|
||||
/* *I*** - Covers boot page */
|
||||
SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I,
|
||||
0, 0, BOOKE_PAGESZ_4K, 1),
|
||||
|
||||
/* *I*G* - CCSRBAR */
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 1, BOOKE_PAGESZ_1M, 1),
|
||||
|
||||
/* *I*G* - eLBC */
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_ELBC_BASE, CONFIG_SYS_ELBC_BASE_PHYS,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 2, BOOKE_PAGESZ_1M, 1),
|
||||
|
||||
#if defined(CONFIG_TRAILBLAZER)
|
||||
/* *I*G - L2SRAM */
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_INIT_L2_ADDR, CONFIG_SYS_INIT_L2_ADDR_PHYS,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 9, BOOKE_PAGESZ_256K, 1),
|
||||
#else
|
||||
/* *I*G* - PCI */
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT, CONFIG_SYS_PCIE1_MEM_PHYS,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 3, BOOKE_PAGESZ_256M, 1),
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT + 0x10000000,
|
||||
CONFIG_SYS_PCIE1_MEM_PHYS + 0x10000000,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 4, BOOKE_PAGESZ_256M, 1),
|
||||
|
||||
/* *I*G* - PCI I/O */
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_IO_VIRT, CONFIG_SYS_PCIE1_IO_PHYS,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 5, BOOKE_PAGESZ_256K, 1),
|
||||
|
||||
#ifdef CONFIG_SYS_RAMBOOT
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_M,
|
||||
0, 6, BOOKE_PAGESZ_1G, 1),
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
int num_tlb_entries = ARRAY_SIZE(tlb_table);
|
||||
Reference in New Issue
Block a user